From: Jeremy Benoist Date: Sun, 2 Oct 2016 15:37:41 +0000 (+0200) Subject: Merge remote-tracking branch 'origin/master' into 2.1 X-Git-Tag: 2.1.0~6 X-Git-Url: https://git.immae.eu/?a=commitdiff_plain;h=77557d289bafc088baf806e4744f110dfd959300;hp=c21f2924f39c99fbfb6ee2e0918726e9de2c5e27;p=github%2Fwallabag%2Fwallabag.git Merge remote-tracking branch 'origin/master' into 2.1 --- diff --git a/.bowerrc b/.bowerrc new file mode 100644 index 00000000..e0163687 --- /dev/null +++ b/.bowerrc @@ -0,0 +1,4 @@ +{ + "directory" : "app/Resources/static/lib", + "json" : "bower.json" +} diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 00000000..976a9eb5 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,4 @@ +{ + "extends": "airbnb", + "installedESLint": true, +} diff --git a/.gitignore b/.gitignore index f596c7b8..fb51034e 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,11 @@ docker/data/ # To avoid crazy stuff on some PR, we must manually FORCE ADD IT on each new release composer.lock + +# assets stuff +/node_modules/ +!app/Resources/static/lib +app/Resources/static/lib/* +/bin +!/src/Wallabag/CoreBundle/Resources/public +/src/Wallabag/CoreBundle/Resources/public/* diff --git a/.travis.yml b/.travis.yml index 53cf9bb5..c5fe7b01 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,9 @@ language: php +services: + - rabbitmq + - redis + # faster builds on docker-container setup sudo: false @@ -15,6 +19,9 @@ cache: directories: - vendor - $HOME/.composer/cache + - node_modules + - $HOME/.cache/bower + - $HOME/.npm php: - 5.5 @@ -23,6 +30,9 @@ php: - 7.1 - nightly +node_js: + - "5" + env: - DB=mysql - DB=pgsql @@ -52,6 +62,8 @@ matrix: env: DB=sqlite - php: 7.0 env: CS_FIXER=run VALIDATE_TRANSLATION_FILE=run DB=sqlite + - php: 7.0 + env: DB=sqlite ASSETS=build allow_failures: - php: hhvm-3.12 - php: 7.1 @@ -67,15 +79,20 @@ before_script: - if [[ ! $PHP = hhvm* ]]; then echo "memory_limit=-1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini; fi; # xdebug isn't enable for PHP 7.1 - if [[ ! $PHP = hhvm* ]]; then phpenv config-rm xdebug.ini || echo "xdebug not available"; fi + - if [[ $PHP = 5.5 ]]; then composer require "phpunit/phpunit:4.*" --no-update; fi; - composer self-update --no-progress - - if [[ "$DB" = "pgsql" ]]; then psql -c 'create database wallabag_test;' -U postgres; fi; + - if [[ $DB = pgsql ]]; then psql -c 'create database wallabag_test;' -U postgres; fi; + +install: + - if [[ $ASSETS = build ]]; then source ~/.nvm/nvm.sh && nvm install 5.0; fi; + - if [[ $ASSETS = build ]]; then npm install -g npm@latest; fi; before_install: - if [[ $TRAVIS_REPO_SLUG = wallabag/wallabag ]]; then cp .composer-auth.json ~/.composer/auth.json; fi; script: - - travis_wait composer install --no-interaction --no-progress --prefer-dist -o + - travis_wait bash install.sh - ant prepare-$DB - phpunit -v - - if [ "$CS_FIXER" = "run" ]; then php bin/php-cs-fixer fix src/ --verbose --dry-run ; fi; - - if [ "$VALIDATE_TRANSLATION_FILE" = "run" ]; then php bin/console lint:yaml src/Wallabag/CoreBundle/Resources/translations -v ; fi; + - if [[ $CS_FIXER = run ]]; then php bin/php-cs-fixer fix src/ --verbose --dry-run ; fi; + - if [[ $VALIDATE_TRANSLATION_FILE = run ]]; then php bin/console lint:yaml src/Wallabag/CoreBundle/Resources/translations -v ; fi; diff --git a/Gruntfile.js b/Gruntfile.js new file mode 100644 index 00000000..8dc5b83b --- /dev/null +++ b/Gruntfile.js @@ -0,0 +1,216 @@ +module.exports = function (grunt) { + require('load-grunt-tasks')(grunt); + + grunt.initConfig({ + appDir: 'app/Resources/static', + buildDir: 'web/bundles/wallabagcore', + + postcss: { + material: { + options: { + map: { + inline: false, + }, + + processors: [ + require('pixrem')(), + require('autoprefixer')({ browsers: 'last 2 versions' }), + require('cssnano')(), + ], + }, + src: '<%= buildDir %>/material.css', + dest: '<%= buildDir %>/themes/material/css/style.min.css', + }, + baggy: { + options: { + map: { + inline: false, + }, + + processors: [ + require('pixrem')(), + require('autoprefixer')({ browsers: 'last 2 versions' }), + require('cssnano')(), + ], + }, + src: '<%= buildDir %>/baggy.css', + dest: '<%= buildDir %>/themes/baggy/css/style.min.css', + }, + }, + concat: { + options: { + separator: ';', + }, + jsMaterial: { + src: [ + '<%= appDir %>/themes/material/js/init.js', + '<%= appDir %>/themes/_global/js/restoreScroll.js', + 'node_modules/jquery.tinydot/src/jquery.tinydot.js', + ], + dest: '<%= buildDir %>/material.js', + }, + jsBaggy: { + src: [ + '<%= appDir %>/themes/baggy/js/init.js', + '<%= appDir %>/themes/_global/js/restoreScroll.js', + '<%= appDir %>/themes/baggy/js/autoClose.js', + '<%= appDir %>/themes/baggy/js/autoCompleteTags.js', + '<%= appDir %>/themes/baggy/js/closeMessage.js', + '<%= appDir %>/themes/baggy/js/popupForm.js', + // Save link is no more used for now + // '<%= appDir %>/themes/baggy/js/saveLink.js', + ], + dest: '<%= buildDir %>/baggy.js', + }, + cssMaterial: { + src: [ + 'node_modules/materialize-css/bin/materialize.css', + '<%= appDir %>/themes/material/css/*.css', + ], + dest: '<%= buildDir %>/material.css', + }, + cssBaggy: { + src: [ + '<%= appDir %>/themes/baggy/css/*.css', + ], + dest: '<%= buildDir %>/baggy.css', + }, + }, + browserify: { + '<%= buildDir %>/material.browser.js': ['<%= buildDir %>/material.js'], + '<%= buildDir %>/baggy.browser.js': ['<%= buildDir %>/baggy.js'], + }, + uglify: { + material: { + files: { + '<%= buildDir %>/themes/material/js/material.min.js': + ['<%= buildDir %>/material.browser.js'], + }, + options: { + sourceMap: true, + }, + }, + baggy: { + files: { + '<%= buildDir %>/themes/baggy/js/baggy.min.js': + ['<%= buildDir %>/baggy.browser.js'], + }, + options: { + sourceMap: true, + }, + }, + }, + copy: { + pickerjs: { + expand: true, + cwd: 'node_modules/pickadate/lib', + src: 'picker.js', + dest: '<%= buildDir %>', + }, + annotator: { + expand: true, + cwd: 'node_modules/annotator/pkg', + src: 'annotator.min.js', + dest: '<%= buildDir %>/themes/_global/js/', + }, + }, + symlink: { + baggyfonts: { + files: [ + { + expand: true, + overwrite: true, + cwd: '<%= appDir %>/lib/icomoon-bower/', + src: 'fonts', + dest: '<%= buildDir %>/themes/baggy/', + }, + { + expand: true, + overwrite: true, + cwd: '<%= appDir %>/lib/bower-pt-sans/fonts', + src: '*', + dest: '<%= buildDir %>/themes/baggy/fonts/', + }, + ], + }, + materialfonts: { + files: [ + { + expand: true, + overwrite: true, + cwd: '<%= appDir %>/lib/icomoon-bower/', + src: 'fonts', + dest: '<%= buildDir %>/themes/material/', + }, + { + expand: true, + overwrite: true, + cwd: 'node_modules/materialize-css/', + src: 'font', + dest: '<%= buildDir %>/themes/material', + }, + { + expand: true, + overwrite: true, + cwd: '<%= appDir %>/lib/roboto-fontface/fonts/', + src: '*', + dest: '<%= buildDir %>/themes/material/fonts/roboto/', + }, + { + expand: true, + overwrite: true, + cwd: '<%= appDir %>/lib/material-design-icons-iconfont/dist/fonts/', + src: '*', + dest: '<%= buildDir %>/themes/material/fonts/', + }, + ], + }, + pics: { + files: [ + { + expand: true, + overwrite: true, + cwd: '<%= appDir %>/themes/_global/', + src: 'img', + dest: '<%= buildDir %>/themes/_global/', + }, + ], + }, + }, + clean: { + css: { + src: ['<%= buildDir %>/**/*.css'], + }, + js: { + src: ['<%= buildDir %>/**/*.js', '<%= buildDir %>/**/*.map'], + }, + all: { + src: ['./<%= buildDir %>'], + }, + }, + }); + + grunt.registerTask( + 'fonts', + 'Install fonts', + ['symlink:baggyfonts', 'symlink:materialfonts'] + ); + + grunt.registerTask( + 'js', + 'Build and install js files', + ['clean:js', 'copy:pickerjs', 'concat:jsMaterial', 'concat:jsBaggy', 'browserify', 'uglify'] + ); + + grunt.registerTask( + 'default', + 'Build and install everything', + ['clean', 'copy:pickerjs', 'concat', 'browserify', 'uglify', 'postcss', 'symlink'] + ); + + grunt.registerTask( + 'css', + 'Compiles the stylesheets.', + ['clean:css', 'concat:cssMaterial', 'concat:cssBaggy', 'postcss'] + ); +}; diff --git a/README.md b/README.md index 2ce6479e..ca61f029 100644 --- a/README.md +++ b/README.md @@ -10,15 +10,14 @@ More informations on our website: [wallabag.org](https://wallabag.org) # Install wallabag -If you don't have it yet, please [install composer](https://getcomposer.org/download/) or be sure to use Composer 1.2 (`composer selfupdate` can help you about that). +If you don't have it yet, please [install composer](https://getcomposer.org/download/) or be sure to use Composer 1.2 (`composer selfupdate` can help you about that). Read [our documentation](http://doc.wallabag.org) to have more information about installation. Then you can install wallabag by executing the following commands: ``` git clone https://github.com/wallabag/wallabag.git cd wallabag - git checkout 2.0.8 - SYMFONY_ENV=prod composer install --no-dev -o --prefer-dist - php bin/console wallabag:install --env=prod + git checkout 2.1.0 + ./install.sh php bin/console server:run --env=prod ``` diff --git a/app/AppKernel.php b/app/AppKernel.php index 04f86eb7..52f85558 100644 --- a/app/AppKernel.php +++ b/app/AppKernel.php @@ -13,7 +13,6 @@ class AppKernel extends Kernel new Symfony\Bundle\TwigBundle\TwigBundle(), new Symfony\Bundle\MonologBundle\MonologBundle(), new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(), - new Symfony\Bundle\AsseticBundle\AsseticBundle(), new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(), new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(), new FOS\RestBundle\FOSRestBundle(), @@ -39,6 +38,7 @@ class AppKernel extends Kernel new Wallabag\UserBundle\WallabagUserBundle(), new Wallabag\ImportBundle\WallabagImportBundle(), new Wallabag\AnnotationBundle\WallabagAnnotationBundle(), + new OldSound\RabbitMqBundle\OldSoundRabbitMqBundle(), ]; if (in_array($this->getEnvironment(), ['dev', 'test'], true)) { diff --git a/app/DoctrineMigrations/Version20160410190541.php b/app/DoctrineMigrations/Version20160410190541.php new file mode 100644 index 00000000..4014857b --- /dev/null +++ b/app/DoctrineMigrations/Version20160410190541.php @@ -0,0 +1,46 @@ +container = $container; + } + + private function getTable($tableName) + { + return $this->container->getParameter('database_table_prefix') . $tableName; + } + + /** + * @param Schema $schema + */ + public function up(Schema $schema) + { + $this->addSql('ALTER TABLE `'.$this->getTable('entry').'` ADD `uuid` LONGTEXT DEFAULT NULL'); + $this->addSql("INSERT INTO `".$this->getTable('craue_config_setting')."` (`name`, `value`, `section`) VALUES ('share_public', '1', 'entry')"); + } + + /** + * @param Schema $schema + */ + public function down(Schema $schema) + { + $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'sqlite', 'This down migration can\'t be executed on SQLite databases, because SQLite don\'t support DROP COLUMN.'); + + $this->addSql('ALTER TABLE `'.$this->getTable('entry').'` DROP `uuid`'); + $this->addSql("DELETE FROM `".$this->getTable('craue_config_setting')."` WHERE `name` = 'share_public'"); + } +} diff --git a/app/DoctrineMigrations/Version20160812120952.php b/app/DoctrineMigrations/Version20160812120952.php new file mode 100644 index 00000000..a8d3bcf2 --- /dev/null +++ b/app/DoctrineMigrations/Version20160812120952.php @@ -0,0 +1,48 @@ +container = $container; + } + + private function getTable($tableName) + { + return $this->container->getParameter('database_table_prefix') . $tableName; + } + + /** + * @param Schema $schema + */ + public function up(Schema $schema) + { + if ($this->connection->getDatabasePlatform()->getName() == 'sqlite') { + $this->addSql('ALTER TABLE '.$this->getTable('oauth2_clients').' ADD name longtext DEFAULT NULL'); + } else { + $this->addSql('ALTER TABLE '.$this->getTable('oauth2_clients').' ADD name longtext COLLATE \'utf8_unicode_ci\' DEFAULT NULL'); + } + } + + /** + * @param Schema $schema + */ + public function down(Schema $schema) + { + $this->abortIf($this->connection->getDatabasePlatform()->getName() == 'sqlite', 'Migration can only be executed safely on \'mysql\' or \'postgresql\'.'); + + $this->addSql('ALTER TABLE '.$this->getTable('oauth2_clients').' DROP COLUMN name'); + } +} diff --git a/app/DoctrineMigrations/Version20160911214952.php b/app/DoctrineMigrations/Version20160911214952.php new file mode 100644 index 00000000..35809cec --- /dev/null +++ b/app/DoctrineMigrations/Version20160911214952.php @@ -0,0 +1,42 @@ +container = $container; + } + + private function getTable($tableName) + { + return $this->container->getParameter('database_table_prefix') . $tableName; + } + + /** + * @param Schema $schema + */ + public function up(Schema $schema) + { + $this->addSql('INSERT INTO `'.$this->getTable('craue_config_setting').'` (`name`, `value`, `section`) VALUES (\'import_with_redis\', \'0\', \'import\')'); + $this->addSql('INSERT INTO `'.$this->getTable('craue_config_setting').'` (`name`, `value`, `section`) VALUES (\'import_with_rabbitmq\', \'0\', \'import\')'); + } + + /** + * @param Schema $schema + */ + public function down(Schema $schema) + { + } +} diff --git a/app/DoctrineMigrations/Version20160916201049.php b/app/DoctrineMigrations/Version20160916201049.php new file mode 100644 index 00000000..202901e6 --- /dev/null +++ b/app/DoctrineMigrations/Version20160916201049.php @@ -0,0 +1,46 @@ +container = $container; + } + + private function getTable($tableName) + { + return $this->container->getParameter('database_table_prefix') . $tableName; + } + + /** + * @param Schema $schema + */ + public function up(Schema $schema) + { + $this->addSql('ALTER TABLE '.$this->getTable('config').' ADD pocket_consumer_key VARCHAR(255) DEFAULT NULL'); + $this->addSql("DELETE FROM `".$this->getTable('craue_config_setting')."` WHERE `name` = 'pocket_consumer_key';"); + } + + /** + * @param Schema $schema + */ + public function down(Schema $schema) + { + $this->abortIf($this->connection->getDatabasePlatform()->getName() == 'sqlite', 'Migration can only be executed safely on \'mysql\' or \'postgresql\'.'); + + $this->addSql('ALTER TABLE `'.$this->getTable('config').'` DROP pocket_consumer_key'); + $this->addSql("INSERT INTO `".$this->getTable('craue_config_setting')."` (`name`, `value`, `section`) VALUES ('pocket_consumer_key', NULL, 'import')"); + } +} diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.da.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.da.yml index c46fdb14..85079330 100644 --- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.da.yml +++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.da.yml @@ -8,7 +8,8 @@ export_csv: Aktiver eksport til CSV export_json: Aktiver eksport til JSON export_txt: Aktiver eksport til TXT export_xml: Aktiver eksport til XML -pocket_consumer_key: Brugers nøgle til Pocket for at importere materialer (https://getpocket.com/developer/docs/authentication) +# import_with_rabbitmq: Enable RabbitMQ to import data asynchronously +# import_with_redis: Enable Redis to import data asynchronously shaarli_url: Shaarli-URL, hvis tjenesten er aktiv share_diaspora: Aktiver deling til Diaspora share_mail: Aktiver deling med email @@ -27,3 +28,4 @@ piwik_site_id: ID for din side hos Piwik piwik_enabled: Aktiver Piwik demo_mode_enabled: "Aktiver demo-indstilling? (anvendes kun til wallabags offentlige demo)" demo_mode_username: "Demobruger" +# share_public: Allow public url for entries diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.de.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.de.yml index fa2093b5..eaba14cd 100644 --- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.de.yml +++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.de.yml @@ -8,7 +8,8 @@ export_csv: CSV-Export aktivieren export_json: JSON-Export aktivieren export_txt: TXT-Export aktivieren export_xml: XML-Export aktivieren -pocket_consumer_key: Consumer-Key für Pocket, um Inhalte zu importieren (https://getpocket.com/developer/docs/authentication) +# import_with_rabbitmq: Enable RabbitMQ to import data asynchronously +# import_with_redis: Enable Redis to import data asynchronously shaarli_url: Shaarli-URL, sofern der Service aktiviert ist share_diaspora: Teilen zu Diaspora aktiveren share_mail: Teilen via E-Mail aktiveren @@ -27,3 +28,4 @@ piwik_site_id: ID deiner Webseite in Piwik piwik_enabled: Piwik aktivieren demo_mode_enabled: "Test-Modus aktivieren? (nur für die öffentliche wallabag-Demo genutzt)" demo_mode_username: "Test-Benutzer" +# share_public: Allow public url for entries diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.en.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.en.yml index b627376e..8aaa27e7 100644 --- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.en.yml +++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.en.yml @@ -8,7 +8,8 @@ export_csv: Enable CSV export export_json: Enable JSON export export_txt: Enable TXT export export_xml: Enable XML export -pocket_consumer_key: Consumer key for Pocket to import contents (https://getpocket.com/developer/docs/authentication) +import_with_rabbitmq: Enable RabbitMQ to import data asynchronously +import_with_redis: Enable Redis to import data asynchronously shaarli_url: Shaarli URL, if the service is enabled share_diaspora: Enable share to Diaspora share_mail: Enable share by email @@ -27,3 +28,4 @@ piwik_site_id: ID of your website in Piwik piwik_enabled: Enable Piwik demo_mode_enabled: "Enable demo mode ? (only used for the wallabag public demo)" demo_mode_username: "Demo user" +share_public: Allow public url for entries diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.es.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.es.yml index af1657e4..bf3a79af 100644 --- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.es.yml +++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.es.yml @@ -8,7 +8,8 @@ export_csv: Activar exportación a CSV export_json: Activar exportación a JSON export_txt: Activar exportación a TXT export_xml: Activar exportación a XML -pocket_consumer_key: Consumer key for Pocket to import contents (https://getpocket.com/developer/docs/authentication) +# import_with_rabbitmq: Enable RabbitMQ to import data asynchronously +# import_with_redis: Enable Redis to import data asynchronously shaarli_url: Shaarli URL, si el servicio está activado share_diaspora: Activar compartir con Diaspora share_mail: Activar compartir con email @@ -27,3 +28,4 @@ piwik_site_id: ID de tu website de Piwik piwik_enabled: Activar Piwik demo_mode_enabled: "Activar modo demo (sólo usado para la demo de wallabag)" demo_mode_username: "Nombre de usuario demo" +# share_public: Allow public url for entries diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.fa.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.fa.yml index 7cb4e833..d86c4343 100644 --- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.fa.yml +++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.fa.yml @@ -8,7 +8,8 @@ export_csv: فعال‌سازی برون‌سپاری به CSV export_json: فعال‌سازی برون‌سپاری به JSON export_txt: فعال‌سازی برون‌سپاری به TXT export_xml: فعال‌سازی برون‌سپاری به XML -pocket_consumer_key: کلید کاربری Pocket برای درون‌ریزی مطالب (https://getpocket.com/developer/docs/authentication) +# import_with_rabbitmq: Enable RabbitMQ to import data asynchronously +# import_with_redis: Enable Redis to import data asynchronously shaarli_url: نشانی Shaarli، اگر فعال بود share_diaspora: فعال‌سازی هم‌رسانی به Diaspora share_mail: فعال‌سازی هم‌رسانی با ایمیل @@ -22,3 +23,9 @@ export: "برون‌سپاری" import: "درون‌ریزی" misc: "غیره" modify_settings: "اعمال" +# piwik_host: Host of your website in Piwik +# piwik_site_id: ID of your website in Piwik +# piwik_enabled: Enable Piwik +# demo_mode_enabled: "Enable demo mode ? (only used for the wallabag public demo)" +# demo_mode_username: "Demo user" +# share_public: Allow public url for entries diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.fr.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.fr.yml index 084eb6df..5e1ecf26 100644 --- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.fr.yml +++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.fr.yml @@ -8,7 +8,8 @@ export_csv: Activer l'export CSV export_json: Activer l'export JSON export_txt: Activer l'export TXT export_xml: Activer l'export XML -pocket_consumer_key: Clé d'authentification Pocket pour importer les données (https://getpocket.com/developer/docs/authentication) +import_with_rabbitmq: Activer RabbitMQ pour gérer les imports de façon asynchrone +import_with_redis: Activer Redis pour gérer les imports de façon asynchrone shaarli_url: URL de Shaarli, si le service Shaarli est activé share_diaspora: Activer le partage vers Diaspora share_mail: Activer le partage par email @@ -27,3 +28,4 @@ piwik_site_id: ID de votre site dans Piwik piwik_enabled: Activer Piwik demo_mode_enabled: "Activer le mode démo ? (utiliser uniquement pour la démo publique de wallabag)" demo_mode_username: "Utilisateur de la démo" +share_public: Autoriser une URL publique pour les articles diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.it.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.it.yml index e4417139..9d820e4b 100644 --- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.it.yml +++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.it.yml @@ -8,7 +8,8 @@ export_csv: Abilita esportazione CSV export_json: Abilita esportazione JSON export_txt: Abilita esportazione TXT export_xml: Abilita esportazione XML -pocket_consumer_key: Consumer key per Pocket per importare i contenuti (https://getpocket.com/developer/docs/authentication) +# import_with_rabbitmq: Enable RabbitMQ to import data asynchronously +# import_with_redis: Enable Redis to import data asynchronously shaarli_url: Shaarli URL, se il servizio è abilitato share_diaspora: Abilita la condivisione con Diaspora share_mail: Abilita la condivisione per email @@ -27,3 +28,4 @@ piwik_site_id: ID del tuo sito in Piwik piwik_enabled: Abilita Piwik demo_mode_enabled: "Abilita modalità demo ? (usato solo per la demo pubblica di wallabag)" demo_mode_username: "Utente Demo" +# share_public: Allow public url for entries diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.oc.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.oc.yml index 67880b8b..49dc7732 100644 --- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.oc.yml +++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.oc.yml @@ -8,7 +8,8 @@ export_csv: Activar l'expòrt CSV export_json: Activar l'expòrt JSON export_txt: Activar l'expòrt TXT export_xml: Activar l'expòrt XML -pocket_consumer_key: Clau d'autentificacion Pocket per importar las donadas (https://getpocket.com/developer/docs/authentication) +# import_with_rabbitmq: Enable RabbitMQ to import data asynchronously +# import_with_redis: Enable Redis to import data asynchronously shaarli_url: URL de Shaarli, se lo servici Shaarli es activat share_diaspora: Activar lo partatge cap a Diaspora share_mail: Activar lo partatge per corrièl @@ -27,3 +28,4 @@ piwik_site_id: ID de vòstre site dins Piwik piwik_enabled: Activar Piwik demo_mode_enabled: "Activar lo mode demostracion ? (utilizar solament per la demostracion publica de wallabag)" demo_mode_username: "Utilizaire de la demostracion" +# share_public: Allow public url for entries diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.pl.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.pl.yml index 87ca5060..7432b0a7 100644 --- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.pl.yml +++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.pl.yml @@ -8,7 +8,8 @@ export_csv: Włącz eksport do CSV export_json: Włącz eksport do JSON export_txt: Włącz eksport do TXT export_xml: Włącz eksport do XML -pocket_consumer_key: Klucz klienta Pocket do importu zawartości (https://getpocket.com/developer/docs/authentication) +import_with_rabbitmq: Włącz RabbitMQ dla asynchronicznego importu danych +import_with_redis: Włącz Redis dla asynchronicznego importu danych shaarli_url: Adress URL Shaarli, jeżeli usługa jest włączona share_diaspora: Włącz udostępnianie dla Diaspora share_mail: Włącz udostępnianie przez email @@ -22,3 +23,9 @@ export: "eksport" import: "import" misc: "różne" modify_settings: "zatwierdz" +piwik_host: Host twojej strony Piwik +piwik_site_id: ID twojej strony Piwik +piwik_enabled: Włacz Piwik +demo_mode_enabled: "Włacz tryb demo? (używany wyłącznie dla publicznej demonstracji Wallabag)" +demo_mode_username: "Użytkownik Demonstracyjny" +share_public: Zezwalaj na publiczny adres url dla wpisow diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.ro.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.ro.yml index f5ff8c6a..20d664f7 100644 --- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.ro.yml +++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.ro.yml @@ -8,7 +8,8 @@ export_csv: Permite exportare CSV export_json: Permite exportare JSON export_txt: Permite exportare TXT export_xml: Permite exportare XML -pocket_consumer_key: Cheie consumator pentru importarea contentului din Pocket (https://getpocket.com/developer/docs/authentication) +# import_with_rabbitmq: Enable RabbitMQ to import data asynchronously +# import_with_redis: Enable Redis to import data asynchronously shaarli_url: Shaarli URL, dacă serviciul este permis share_diaspora: Permite share către Diaspora share_mail: Permite share prin email @@ -22,3 +23,9 @@ export: "exportă" import: "importă" misc: "diverse" modify_settings: "aplică" +# piwik_host: Host of your website in Piwik +# piwik_site_id: ID of your website in Piwik +# piwik_enabled: Enable Piwik +# demo_mode_enabled: "Enable demo mode ? (only used for the wallabag public demo)" +# demo_mode_username: "Demo user" +# share_public: Allow public url for entries diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.tr.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.tr.yml new file mode 100644 index 00000000..4b4d3edb --- /dev/null +++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.tr.yml @@ -0,0 +1,31 @@ +# download_pictures: Download pictures on your server +# carrot: Enable share to Carrot +# diaspora_url: Diaspora URL, if the service is enabled +# export_epub: Enable ePub export +# export_mobi: Enable .mobi export +# export_pdf: Enable PDF export +# export_csv: Enable CSV export +# export_json: Enable JSON export +# export_txt: Enable TXT export +# export_xml: Enable XML export +# import_with_rabbitmq: Enable RabbitMQ to import data asynchronously +# import_with_redis: Enable Redis to import data asynchronously +# shaarli_url: Shaarli URL, if the service is enabled +# share_diaspora: Enable share to Diaspora +# share_mail: Enable share by email +# share_shaarli: Enable share to Shaarli +# share_twitter: Enable share to Twitter +# show_printlink: Display a link to print content +# wallabag_support_url: Support URL for wallabag +# wallabag_url: URL of *your* wallabag instance +# entry: "article" +# export: "export" +# import: "import" +# misc: "misc" +# modify_settings: "apply" +# piwik_host: Host of your website in Piwik +# piwik_site_id: ID of your website in Piwik +# piwik_enabled: Enable Piwik +# demo_mode_enabled: "Enable demo mode ? (only used for the wallabag public demo)" +# demo_mode_username: "Demo user" +# share_public: Allow public url for entries diff --git a/src/Wallabag/CoreBundle/Resources/public/themes/_global/img/appicon/apple-touch-icon-114.png b/app/Resources/static/themes/_global/img/appicon/apple-touch-icon-114.png similarity index 100% rename from src/Wallabag/CoreBundle/Resources/public/themes/_global/img/appicon/apple-touch-icon-114.png rename to app/Resources/static/themes/_global/img/appicon/apple-touch-icon-114.png diff --git a/src/Wallabag/CoreBundle/Resources/public/themes/_global/img/appicon/apple-touch-icon-120.png b/app/Resources/static/themes/_global/img/appicon/apple-touch-icon-120.png similarity index 100% rename from src/Wallabag/CoreBundle/Resources/public/themes/_global/img/appicon/apple-touch-icon-120.png rename to app/Resources/static/themes/_global/img/appicon/apple-touch-icon-120.png diff --git a/src/Wallabag/CoreBundle/Resources/public/themes/_global/img/appicon/apple-touch-icon-144.png b/app/Resources/static/themes/_global/img/appicon/apple-touch-icon-144.png similarity index 100% rename from src/Wallabag/CoreBundle/Resources/public/themes/_global/img/appicon/apple-touch-icon-144.png rename to app/Resources/static/themes/_global/img/appicon/apple-touch-icon-144.png diff --git a/src/Wallabag/CoreBundle/Resources/public/themes/_global/img/appicon/apple-touch-icon-152.png b/app/Resources/static/themes/_global/img/appicon/apple-touch-icon-152.png similarity index 100% rename from src/Wallabag/CoreBundle/Resources/public/themes/_global/img/appicon/apple-touch-icon-152.png rename to app/Resources/static/themes/_global/img/appicon/apple-touch-icon-152.png diff --git a/src/Wallabag/CoreBundle/Resources/public/themes/_global/img/appicon/apple-touch-icon-57.png b/app/Resources/static/themes/_global/img/appicon/apple-touch-icon-57.png similarity index 100% rename from src/Wallabag/CoreBundle/Resources/public/themes/_global/img/appicon/apple-touch-icon-57.png rename to app/Resources/static/themes/_global/img/appicon/apple-touch-icon-57.png diff --git a/src/Wallabag/CoreBundle/Resources/public/themes/_global/img/appicon/apple-touch-icon-72.png b/app/Resources/static/themes/_global/img/appicon/apple-touch-icon-72.png similarity index 100% rename from src/Wallabag/CoreBundle/Resources/public/themes/_global/img/appicon/apple-touch-icon-72.png rename to app/Resources/static/themes/_global/img/appicon/apple-touch-icon-72.png diff --git a/src/Wallabag/CoreBundle/Resources/public/themes/_global/img/appicon/apple-touch-icon-76.png b/app/Resources/static/themes/_global/img/appicon/apple-touch-icon-76.png similarity index 100% rename from src/Wallabag/CoreBundle/Resources/public/themes/_global/img/appicon/apple-touch-icon-76.png rename to app/Resources/static/themes/_global/img/appicon/apple-touch-icon-76.png diff --git a/src/Wallabag/CoreBundle/Resources/public/themes/_global/img/appicon/apple-touch-icon.png b/app/Resources/static/themes/_global/img/appicon/apple-touch-icon.png similarity index 100% rename from src/Wallabag/CoreBundle/Resources/public/themes/_global/img/appicon/apple-touch-icon.png rename to app/Resources/static/themes/_global/img/appicon/apple-touch-icon.png diff --git a/src/Wallabag/CoreBundle/Resources/public/themes/_global/img/appicon/favicon.ico b/app/Resources/static/themes/_global/img/appicon/favicon.ico similarity index 100% rename from src/Wallabag/CoreBundle/Resources/public/themes/_global/img/appicon/favicon.ico rename to app/Resources/static/themes/_global/img/appicon/favicon.ico diff --git a/src/Wallabag/CoreBundle/Resources/public/themes/baggy/img/bg-select.png b/app/Resources/static/themes/_global/img/bg-select.png similarity index 100% rename from src/Wallabag/CoreBundle/Resources/public/themes/baggy/img/bg-select.png rename to app/Resources/static/themes/_global/img/bg-select.png diff --git a/src/Wallabag/CoreBundle/Resources/public/themes/_global/img/icons/carrot-icon--black.png b/app/Resources/static/themes/_global/img/icons/carrot-icon--black.png similarity index 100% rename from src/Wallabag/CoreBundle/Resources/public/themes/_global/img/icons/carrot-icon--black.png rename to app/Resources/static/themes/_global/img/icons/carrot-icon--black.png diff --git a/src/Wallabag/CoreBundle/Resources/public/themes/_global/img/icons/carrot-icon--white.png b/app/Resources/static/themes/_global/img/icons/carrot-icon--white.png similarity index 100% rename from src/Wallabag/CoreBundle/Resources/public/themes/_global/img/icons/carrot-icon--white.png rename to app/Resources/static/themes/_global/img/icons/carrot-icon--white.png diff --git a/src/Wallabag/CoreBundle/Resources/public/themes/_global/img/icons/diaspora-icon--black.png b/app/Resources/static/themes/_global/img/icons/diaspora-icon--black.png similarity index 100% rename from src/Wallabag/CoreBundle/Resources/public/themes/_global/img/icons/diaspora-icon--black.png rename to app/Resources/static/themes/_global/img/icons/diaspora-icon--black.png diff --git a/src/Wallabag/CoreBundle/Resources/public/themes/_global/img/icons/diaspora-icon--white.png b/app/Resources/static/themes/_global/img/icons/diaspora-icon--white.png similarity index 100% rename from src/Wallabag/CoreBundle/Resources/public/themes/_global/img/icons/diaspora-icon--white.png rename to app/Resources/static/themes/_global/img/icons/diaspora-icon--white.png diff --git a/src/Wallabag/CoreBundle/Resources/public/themes/material/img/logo-other_themes.png b/app/Resources/static/themes/_global/img/logo-other_themes.png similarity index 100% rename from src/Wallabag/CoreBundle/Resources/public/themes/material/img/logo-other_themes.png rename to app/Resources/static/themes/_global/img/logo-other_themes.png diff --git a/src/Wallabag/CoreBundle/Resources/public/themes/material/img/logo-square.png b/app/Resources/static/themes/_global/img/logo-square.png similarity index 100% rename from src/Wallabag/CoreBundle/Resources/public/themes/material/img/logo-square.png rename to app/Resources/static/themes/_global/img/logo-square.png diff --git a/src/Wallabag/CoreBundle/Resources/public/themes/baggy/img/logo-w.png b/app/Resources/static/themes/_global/img/logo-w.png similarity index 100% rename from src/Wallabag/CoreBundle/Resources/public/themes/baggy/img/logo-w.png rename to app/Resources/static/themes/_global/img/logo-w.png diff --git a/src/Wallabag/CoreBundle/Resources/public/themes/baggy/img/logo-wallabag.svg b/app/Resources/static/themes/_global/img/logo-wallabag.svg similarity index 100% rename from src/Wallabag/CoreBundle/Resources/public/themes/baggy/img/logo-wallabag.svg rename to app/Resources/static/themes/_global/img/logo-wallabag.svg diff --git a/src/Wallabag/CoreBundle/Resources/public/themes/_global/js/bookmarklet.js b/app/Resources/static/themes/_global/js/bookmarklet.js similarity index 100% rename from src/Wallabag/CoreBundle/Resources/public/themes/_global/js/bookmarklet.js rename to app/Resources/static/themes/_global/js/bookmarklet.js diff --git a/app/Resources/static/themes/_global/js/restoreScroll.js b/app/Resources/static/themes/_global/js/restoreScroll.js new file mode 100644 index 00000000..9c4d7e20 --- /dev/null +++ b/app/Resources/static/themes/_global/js/restoreScroll.js @@ -0,0 +1,25 @@ +function supportsLocalStorage() { + try { + return 'localStorage' in window && window.localStorage !== null; + } catch (e) { + return false; + } +} + +function savePercent(id, percent) { + if (!supportsLocalStorage()) { return false; } + localStorage['wallabag.article.' + id + '.percent'] = percent; + return true; +} + +function retrievePercent(id) { + if (!supportsLocalStorage()) { return false; } + + var bheight = $(document).height(); + var percent = localStorage['wallabag.article.' + id + '.percent']; + var scroll = bheight * percent; + + $('html,body').animate({ scrollTop: scroll }, 'fast'); + + return true; +} diff --git a/app/Resources/static/themes/baggy/css/font.css b/app/Resources/static/themes/baggy/css/font.css new file mode 100755 index 00000000..cae7904a --- /dev/null +++ b/app/Resources/static/themes/baggy/css/font.css @@ -0,0 +1,6 @@ +@font-face { + font-family: "PT Sans"; + font-style: normal; + font-weight: 700; + src: local("PT Sans Bold"), local("PTSans-Bold"), url("../fonts/pt_sans/regular/PTS55F.woff") format("woff"); +} diff --git a/src/Wallabag/CoreBundle/Resources/public/themes/baggy/css/main.css b/app/Resources/static/themes/baggy/css/main.css similarity index 55% rename from src/Wallabag/CoreBundle/Resources/public/themes/baggy/css/main.css rename to app/Resources/static/themes/baggy/css/main.css index ba430cc4..7ffaa12c 100755 --- a/src/Wallabag/CoreBundle/Resources/public/themes/baggy/css/main.css +++ b/app/Resources/static/themes/baggy/css/main.css @@ -15,7 +15,7 @@ html { } body { - background-color: #EEE; + background-color: #eee; } .login { @@ -28,9 +28,9 @@ body { } .login form { - background-color: #FFF; + background-color: #fff; padding: 1.5em; - box-shadow: 0 1px 8px rgba(0,0,0,0.9); + box-shadow: 0 1px 8px rgba(0, 0, 0, 0.9); width: 20em; position: absolute; top: 8em; @@ -50,7 +50,7 @@ body { ========================================================================== */ ::selection { - color: #FFF; + color: #fff; background-color: #000; } @@ -65,12 +65,16 @@ body { left: 0.6em; } -h2, h3, h4 { - font-family: 'PT Sans', sans-serif; +h2, +h3, +h4 { + font-family: "PT Sans", sans-serif; text-transform: uppercase; } -p, li, label { +p, +li, +label { color: #666; } @@ -79,28 +83,38 @@ a { font-weight: bold; } -a:hover, a:focus { +a.nostyle { + text-decoration: none; +} + +a:hover, +a:focus { text-decoration: none; } form fieldset { - border:0; + border: 0; padding: 0; margin: 0; } -form input[type="text"], form input[type="number"], select, form input[type="password"], form input[type="url"], form input[type="email"] { +form input[type="text"], +form input[type="number"], +select, +form input[type="password"], +form input[type="url"], +form input[type="email"] { border: 1px solid #999; padding: 0.5em 1em; min-width: 12em; color: #666; } -@media screen and (-webkit-min-device-pixel-ratio:0){ - select{ +@media screen and (-webkit-min-device-pixel-ratio: 0) { + select { -webkit-appearance: none; border-radius: 0; - background: #FFF url(../img/bg-select.png) no-repeat right center; + background: #fff url("../../_global/img/bg-select.png") no-repeat right center; } } @@ -127,31 +141,34 @@ form .row { margin-bottom: 0.5em; } -form button, input[type="submit"] { - cursor:pointer; +form button, +input[type="submit"] { + cursor: pointer; background-color: #000; - color: #FFF; - border:0; + color: #fff; padding: 0.5em 1em; display: inline-block; - border:1px solid #000; + border: 1px solid #000; } - form button:hover, form button:focus, input[type="submit"]:hover, input[type="submit"]:focus { - background-color: #FFF; - color: #000; - -webkit-transition: all 0.5s ease; - -moz-transition: all 0.5s ease; - -ms-transition: all 0.5s ease; - -o-transition: all 0.5s ease; - transition: all 0.5s ease; - } +form button:hover, +form button:focus, +input[type="submit"]:hover, +input[type="submit"]:focus { + background-color: #fff; + color: #000; + -webkit-transition: all 0.5s ease; + -moz-transition: all 0.5s ease; + -ms-transition: all 0.5s ease; + -o-transition: all 0.5s ease; + transition: all 0.5s ease; +} #bookmarklet { cursor: move; } -h2:after { +h2::after { content: ""; height: 4px; width: 70px; @@ -163,12 +180,12 @@ h2:after { padding: 0; margin: 0; } - .links li { - list-style: none; - margin: 0; - padding: 0; - } +.links li { + list-style: none; + margin: 0; + padding: 0; +} #links { position: fixed; @@ -179,119 +196,132 @@ h2:after { background-color: #333; padding-top: 9.5em; height: 100%; - box-shadow:inset -4px 0 20px rgba(0,0,0,0.6); + box-shadow: inset -4px 0 20px rgba(0, 0, 0, 0.6); z-index: 15; } #main { - margin-left: 13em; + margin-left: 12em; position: relative; z-index: 10; padding-right: 5%; padding-bottom: 1em; } - #links > li > a { - display: block; - padding: 0.5em 2em 0.5em 1em; - color: #FFF; - position: relative; - text-transform: uppercase; - text-decoration: none; - font-weight: normal; - font-family: 'PT Sans', sans-serif; - -webkit-transition: all 0.5s ease; - -moz-transition: all 0.5s ease; - -ms-transition: all 0.5s ease; - -o-transition: all 0.5s ease; - transition: all 0.5s ease; - } - - #links > li > a:hover, #links > li > a:focus { - background-color: #999; - color: #000; - } +#links > li > a { + display: block; + padding: 0.5em 2em 0.5em 1em; + color: #fff; + position: relative; + text-transform: uppercase; + text-decoration: none; + font-weight: normal; + font-family: "PT Sans", sans-serif; + -webkit-transition: all 0.5s ease; + -moz-transition: all 0.5s ease; + -ms-transition: all 0.5s ease; + -o-transition: all 0.5s ease; + transition: all 0.5s ease; +} - #links .current:after { - content: ""; - width: 0; - height: 0; - position: absolute; - border-style: solid; - border-width: 10px; - border-color: transparent #EEE transparent transparent; - right: 0; - top: 50%; - margin-top: -10px; - } +#links > li > a:hover, +#links > li > a:focus { + background-color: #999; + color: #000; +} - #links li:last-child { - position: fixed; - bottom: 1em; - width: 10em; - } +#links .current::after { + content: ""; + width: 0; + height: 0; + position: absolute; + border-style: solid; + border-width: 10px; + border-color: transparent #eee transparent transparent; + right: 0; + top: 50%; + margin-top: -10px; +} - #links li:last-child a:before { - font-size: 1.2em; - position: relative; - top: 2px; - } +#links li:last-child { + position: fixed; + bottom: 1em; + width: 10em; +} +#links li:last-child a::before { + font-size: 1.2em; + position: relative; + top: 2px; +} #sort { - padding: 0; - list-style-type: none; - opacity: 0.5; - display: inline-block; + padding: 0; + list-style-type: none; + opacity: 0.5; + display: inline-block; } #sort li { - display: inline; - font-size: 0.9em; + display: inline; + font-size: 0.9em; } #sort li + li { - margin-left: 10px; + margin-left: 10px; } #sort a { - padding: 2px 2px 0; - vertical-align: middle; + padding: 2px 2px 0; + vertical-align: middle; } #sort img { - vertical-align: baseline; + vertical-align: baseline; } + #sort img:hover { - cursor: pointer; + cursor: pointer; } #display-mode { float: right; - vertical-align: middle; margin-top: 10px; margin-bottom: 10px; opacity: 0.5; } + #listmode { width: 16px; display: inline-block; text-decoration: none; } + #listmode a:hover { opacity: 1; } + #listmode.tablemode { background-image: url("../img/baggy/table.png"); background-repeat: no-repeat; background-position: bottom; } + #listmode.listmode { background-image: url("../img/baggy/list.png"); background-repeat: no-repeat; background-position: bottom; } +#warning_message { + position: fixed; + background-color: #ff6347; + z-index: 1000; + bottom: 0; + left: 0; + width: 100%; + color: #000; +} /* ========================================================================== 2 = Layout @@ -319,12 +349,52 @@ footer a { } .list-entries { - letter-spacing:-5px; + letter-spacing: -5px; } .listmode .entry { - width: 100%!important; - margin-left: 0!important; + width: 100% !important; + margin-left: 0 !important; +} + +.card-entry-labels { + position: absolute; + top: 100px; + left: -1em; + z-index: 90; + max-width: 50%; + padding-left: 0; +} + +.card-entry-labels li { + margin: 10px 10px 10px auto; + padding: 5px 12px 5px 25px; + background-color: rgba(0, 0, 0, 0.6); + border-radius: 0 3px 3px 0; + color: #fff; + cursor: default; + max-height: 2em; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.card-entry-tags { + max-height: 2em; + overflow-y: hidden; + padding: 0; +} + +.card-entry-tags li { + display: inline-block; + margin: 0 5px; + padding: 5px 12px; + background-color: rgba(0, 0, 0, 0.6); + border-radius: 3px; + max-height: 2em; + overflow: hidden; + text-overflow: ellipsis; + color: #fff; } .list-entries + .results { @@ -344,47 +414,39 @@ footer a { } .entry { - background-color: #FFF; - letter-spacing:normal; - box-shadow: 0 3px 7px rgba(0,0,0,0.3); + background-color: #fff; + letter-spacing: normal; + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); display: inline-block; width: 32%; margin-bottom: 1.5em; vertical-align: top; - margin-left: 1.5%; + margin-right: 1%; position: relative; overflow: hidden; - padding: 1.5em 1.5em 3em 1.5em; - - /* Removing CSS transitions because they make the switch from list view to - * table view jerky - */ - /* -webkit-transition: all 0.5s ease; */ - /* -moz-transition: all 0.5s ease; */ - /* -ms-transition: all 0.5s ease; */ - /* -o-transition: all 0.5s ease; */ - /* transition: all 0.5s ease; */ + padding: 1.5em 1.5em 3em; + height: 440px; } -.entry:before { +.entry::before { content: ""; width: 0; height: 0; - border-style:solid; - border-color: transparent transparent #000 transparent; + border-style: solid; + border-color: transparent transparent #000; border-width: 10px; position: absolute; bottom: 0.3em; z-index: 10; right: 1.5em; -webkit-transition: all 0.5s ease; - -moz-transition: all 0.5s ease; - -ms-transition: all 0.5s ease; - -o-transition: all 0.5s ease; - transition: all 0.5s ease; + -moz-transition: all 0.5s ease; + -ms-transition: all 0.5s ease; + -o-transition: all 0.5s ease; + transition: all 0.5s ease; } -.entry:after { +.entry::after { content: ""; position: absolute; height: 7px; @@ -393,21 +455,21 @@ footer a { left: 0; background-color: #000; -webkit-transition: all 0.5s ease; - -moz-transition: all 0.5s ease; - -ms-transition: all 0.5s ease; - -o-transition: all 0.5s ease; - transition: all 0.5s ease; + -moz-transition: all 0.5s ease; + -ms-transition: all 0.5s ease; + -o-transition: all 0.5s ease; + transition: all 0.5s ease; } .entry:hover { - box-shadow: 0 3px 10px rgba(0,0,0,1); + box-shadow: 0 3px 10px rgba(0, 0, 0, 1); } -.entry:hover:after { +.entry:hover::after { height: 40px; } -.entry:hover:before { +.entry:hover::before { bottom: 2.4em; } @@ -419,12 +481,14 @@ footer a { text-transform: none; margin-bottom: 0; line-height: 1.2; + text-align: justify; + -moz-text-align-last: center; + text-align-last: center; } - .entry h2:after { - content: none; - } - +.entry h2::after { + content: none; +} .entry h2 a { display: block; @@ -432,24 +496,16 @@ footer a { color: #000; word-wrap: break-word; -webkit-transition: all 0.5s ease; - -moz-transition: all 0.5s ease; - -ms-transition: all 0.5s ease; - -o-transition: all 0.5s ease; - transition: all 0.5s ease; + -moz-transition: all 0.5s ease; + -ms-transition: all 0.5s ease; + -o-transition: all 0.5s ease; + transition: all 0.5s ease; } -/* -.entry h2 a:after { - content: ""; - position: absolute; - top: 0; - width: 100%; - height: 100%; - left: 0; -} -*/ img.preview { - max-width: 100%; + max-width: calc(100% + 3em); + left: -1.5em; + position: relative; } .entry p { @@ -458,9 +514,9 @@ img.preview { line-height: 1.7; } - .entry h2 a:first-letter { - text-transform: uppercase; - } +.entry h2 a::first-letter { + text-transform: uppercase; +} .entry:hover .tools { bottom: 0; @@ -475,26 +531,26 @@ img.preview { padding-right: 0.5em; text-align: right; -webkit-transition: all 0.5s ease; - -moz-transition: all 0.5s ease; - -ms-transition: all 0.5s ease; - -o-transition: all 0.5s ease; - transition: all 0.5s ease; + -moz-transition: all 0.5s ease; + -ms-transition: all 0.5s ease; + -o-transition: all 0.5s ease; + transition: all 0.5s ease; } - .entry .tools a { - color: #666; - text-decoration: none; - display: block; - padding: 0.4em; - } +.entry .tools a { + color: #666; + text-decoration: none; + display: block; + padding: 0.4em; +} - .entry .tools a:hover { - color: #FFF; - } +.entry .tools a:hover { + color: #fff; +} - .entry .tools li { - display: inline-block; - } +.entry .tools li { + display: inline-block; +} .entry:nth-child(3n+1) { margin-left: 0; @@ -510,11 +566,12 @@ img.preview { vertical-align: top; letter-spacing: normal; width: 50%; + text-align: right; } div.pagination ul { text-align: right; - margin-bottom:50px; + margin-bottom: 50px; } .nb-results { @@ -533,11 +590,13 @@ div.pagination ul a { text-decoration: none; } -div.pagination ul a:hover, div.pagination ul a:focus { - text-decoration: underline; +div.pagination ul a:hover, +div.pagination ul a:focus { + text-decoration: underline; } -div.pagination ul .disabled { +div.pagination ul .prev.disabled, +div.pagination ul .next.disabled { display: none; } @@ -556,7 +615,7 @@ div.pagination ul .current { ========================================================================== */ .popup-form { - background: rgba(0,0,0,0.5); + background: rgba(0, 0, 0, 0.5); position: absolute; top: 0; left: 10em; @@ -567,11 +626,11 @@ div.pagination ul .current { margin-top: -30% !important; padding: 2em; display: none; - border-left: 1px #EEE solid; + border-left: 1px #eee solid; } - .popup-form form { - background-color: #FFF; +.popup-form form { + background-color: #fff; position: absolute; top: 0; left: 0; @@ -580,51 +639,52 @@ div.pagination ul .current { width: 400px; height: 200px; padding: 2em; - } +} #bagit-form-form .addurl { - margin-left: 0; + margin-left: 0; } .closeMessage, .close-button { background-color: #000; - color: #FFF; - font-size: 1.2em; - line-height: 1.6; - width: 1.6em; - height: 1.6em; - text-align: center; + color: #fff; + font-size: 1.2em; + line-height: 1.6; + width: 1.6em; + height: 1.6em; + text-align: center; text-decoration: none; } - .closeMessage:hover, - .closeMessage:focus, - .close-button:hover, - .close-button:focus { + +.closeMessage:hover, +.closeMessage:focus, +.close-button:hover, +.close-button:focus { background-color: #999; color: #000; - } +} .close-button--popup { - display: inline-block; - position: absolute; - top: 0; - right: 0; - font-size: 1.4em; + display: inline-block; + position: absolute; + top: 0; + right: 0; + font-size: 1.4em; } .active-current { background-color: #999; } -.active-current:after { +.active-current::after { content: ""; width: 0; height: 0; position: absolute; border-style: solid; border-width: 10px; - border-color: transparent #EEE transparent transparent; + border-color: transparent #eee transparent transparent; right: 0; top: 50%; margin-top: -10px; @@ -637,26 +697,27 @@ div.pagination ul .current { .add-to-wallabag-link-after { background-color: #000; color: #fff; - padding: 0 3px 2px 3px; + padding: 0 3px 2px; } a.add-to-wallabag-link-after { - visibility: hidden; - position: absolute; - opacity: 0; - transition-duration: 2s; - transition-timing-function: ease-out; + visibility: hidden; + position: absolute; + opacity: 0; + transition-duration: 2s; + transition-timing-function: ease-out; } -#article article a:hover + a.add-to-wallabag-link-after, a.add-to-wallabag-link-after:hover { - opacity: 1; - visibility: visible; - transition-duration: .3s; - transition-timing-function: ease-in; +#article article a:hover + a.add-to-wallabag-link-after, +a.add-to-wallabag-link-after:hover { + opacity: 1; + visibility: visible; + transition-duration: 0.3s; + transition-timing-function: ease-in; } -a.add-to-wallabag-link-after:after { - content: "w"; +a.add-to-wallabag-link-after::after { + content: "w"; } #add-link-result { @@ -664,29 +725,78 @@ a.add-to-wallabag-link-after:after { font-size: 0.9em; } +.btn-clickable { + cursor: pointer; +} + /* ========================================================================== 3 = Pictos ========================================================================== */ @font-face { - font-family: 'icomoon'; - src:url('../fonts/icomoon.eot?-s0mcsx'); - src:url('../fonts/icomoon.eot?#iefix-s0mcsx') format('embedded-opentype'), - url('../fonts/icomoon.woff?-s0mcsx') format('woff'), - url('../fonts/icomoon.ttf?-s0mcsx') format('truetype'), - url('../fonts/icomoon.svg?-s0mcsx#icomoon') format('svg'); + font-family: icomoon; + src: url("../fonts/icomoon.eot?-s0mcsx"); + src: + url("../fonts/icomoon.eot?#iefix-s0mcsx") format("embedded-opentype"), + url("../fonts/icomoon.woff?-s0mcsx") format("woff"), + url("../fonts/icomoon.ttf?-s0mcsx") format("truetype"), + url("../fonts/icomoon.svg?-s0mcsx#icomoon") format("svg"); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'Material Icons'; + font-style: normal; + font-weight: 400; + src: url(../fonts/MaterialIcons-Regular.eot); + + /* For IE6-8 */ + src: local("Material Icons"), local("MaterialIcons-Regular"), url(../fonts/MaterialIcons-Regular.woff2) format("woff2"), url(../fonts/MaterialIcons-Regular.woff) format("woff"), url(../fonts/MaterialIcons-Regular.ttf) format("truetype"); +} + +.material-icons { + font-family: 'Material Icons'; font-weight: normal; font-style: normal; + font-size: 1em; /* Preferred icon size */ + width: 1em; + height: 1em; + display: inline-block; + line-height: 1; + text-transform: none; + letter-spacing: normal; + word-wrap: normal; + white-space: nowrap; + direction: ltr; + + /* Support for all WebKit browsers. */ + -webkit-font-smoothing: antialiased; + + /* Support for Safari and Chrome. */ + text-rendering: optimizeLegibility; + + /* Support for Firefox. */ + -moz-osx-font-smoothing: grayscale; + + /* Support for IE. */ + font-feature-settings: 'liga'; } +.material-icons.md-18 { font-size: 18px; } +.material-icons.md-24 { font-size: 24px; } +.material-icons.md-36 { font-size: 36px; } +.material-icons.md-48 { font-size: 48px; } + .icon span, .icon-image span { position: absolute; top: -9999px; } -[class^="icon-"]:before, [class*=" icon-"]:before { - font-family: 'icomoon'; +[class^="icon-"]::before, +[class*=" icon-"]::before { + font-family: icomoon; speak: none; font-style: normal; font-weight: normal; @@ -699,93 +809,113 @@ a.add-to-wallabag-link-after:after { -moz-osx-font-smoothing: grayscale; } -.icon-flattr:before { - content: "\e800"; +.icon-flattr::before { + content: "\ead4"; } -.icon-mail:before { - content: "\e80a"; + +.icon-mail::before { + content: "\ea86"; } -.icon-up-open:before { + +.icon-up-open::before { content: "\e80b"; } -.icon-star:before { - content: "\e805"; + +.icon-star::before { + content: "\e9d9"; } -.icon-check:before { - content: "\e804"; + +.icon-check::before { + content: "\ea10"; } -.icon-link:before { - content: "\e801"; + +.icon-link::before { + content: "\e9cb"; } -.icon-reply:before { + +.icon-reply::before { content: "\e806"; } -.icon-menu:before { - content: "\e802"; + +.icon-menu::before { + content: "\e9bd"; } -.icon-clock:before { + +.icon-clock::before { content: "\e803"; } -.icon-twitter:before { - content: "\e807"; + +.icon-twitter::before { + content: "\ea91"; } -.icon-down-open:before { + +.icon-down-open::before { content: "\e809"; } -.icon-trash:before { - content: "\e80c"; + +.icon-trash::before { + content: "\e9ac"; } -.icon-delete:before { - content: "\e600"; + +.icon-delete::before { + content: "\ea0d"; } -.icon-power:before { - content: "\e601"; + +.icon-power::before { + content: "\ea14"; } -.icon-arrow-up-thick:before { - content: "\e602"; + +.icon-arrow-up-thick::before { + content: "\ea3a"; } -.icon-rss:before { + +.icon-rss::before { content: "\e808"; } -.icon-print:before { - content: "\e80d"; + +.icon-print::before { + content: "\e954"; } -.icon-reload:before { + +.icon-reload::before { content: "\ea2e"; } +.icon-price-tags::before { + content: "\e936"; +} /* .icon-image class, for image-based icons ========================================================================== */ .icon-image { - background-size: 16px 16px; - background-repeat: no-repeat; - background-position: center; - padding-right: 1em !important; - padding-left: 1em !important; + background-size: 16px 16px; + background-repeat: no-repeat; + background-position: center; + padding-right: 1em !important; + padding-left: 1em !important; } /* Carrot (http://carrot.org) */ .icon-image--carrot { - background-image: url('../../_global/img/icons/carrot-icon--white.png'); + background-image: url("../../_global/img/icons/carrot-icon--white.png"); } /* Diaspora */ .icon-image--diaspora { - background-image: url('../../_global/img/icons/diaspora-icon--black.png'); + background-image: url("../../_global/img/icons/diaspora-icon--black.png"); } /* ========================================================================== Icon selected ========================================================================== */ -.icon-star.fav:before { - color: #FFF; +.icon-star.fav::before { + color: #fff; } -.icon-check.archive:before { - color: #FFF; +.icon-check.archive::before { + color: #fff; } /* ========================================================================== @@ -797,33 +927,25 @@ a.add-to-wallabag-link-after:after { margin-top: 1em; } -.messages > * { display: inline-block;} +.messages > * { + display: inline-block; +} .warning { - /* font-size: 3em; - color: #999; - font-style: italic; - position: absolute; - top: 50%; - left: 0; - width: 100%; - text-align: center; - padding-right: 5%; - margin-top: -2em;*/ font-weight: bold; display: block; width: 100%; } .more-info { - font-size: 0.85em; + font-size: 0.85em; line-height: 1.5; - color: #aaa; + color: #aaa; } - .more-info a { +.more-info a { color: #aaa; - } +} /* ========================================================================== 5 = Article @@ -844,8 +966,8 @@ a.add-to-wallabag-link-after:after { } blockquote { - border:1px solid #999; - background-color: #FFF; + border: 1px solid #999; + background-color: #fff; padding: 1em; margin: 0; } @@ -854,11 +976,13 @@ blockquote { text-align: left; } -#article h2, #article h3, #article h4 { +#article h2, +#article h3, +#article h4 { text-transform: none; } -#article h2:after { +#article h2::after { content: none; } @@ -880,19 +1004,20 @@ blockquote { #article_toolbar a { background-color: #000; padding: 0.3em 0.5em 0.2em; - color: #FFF; + color: #fff; text-decoration: none; } -#article_toolbar a:hover, #article_toolbar a:focus { +#article_toolbar a:hover, +#article_toolbar a:focus { background-color: #999; } #nav-btn-add-tag { - cursor: pointer; + cursor: pointer; } -.shaarli:before { +.shaarli::before { content: "*"; } @@ -902,7 +1027,7 @@ blockquote { display: block; } -.return:before { +.return::before { margin-right: 0.5em; } @@ -913,11 +1038,11 @@ blockquote { .icon-rss { background-color: #000; - color: #FFF; + color: #fff; padding: 0.2em 0.5em; } -.icon-rss:before { +.icon-rss::before { position: relative; top: 2px; } @@ -926,8 +1051,9 @@ blockquote { margin-bottom: 0.5em; } -.list-tags .icon-rss:hover, .list-tags .icon-rss:focus { - background-color: #FFF; +.list-tags .icon-rss:hover, +.list-tags .icon-rss:focus { + background-color: #fff; color: #000; text-decoration: none; } @@ -936,14 +1062,13 @@ blockquote { text-decoration: none; } -.list-tags a:hover, .list-tags a:focus { +.list-tags a:hover, +.list-tags a:focus { text-decoration: underline; } pre code { font-family: "Courier New", Courier, monospace; - border: 1px solid #ccc; - font-size: 0.96em; } #filter-form { @@ -952,28 +1077,45 @@ pre code { height: 100%; top: 0; right: 0; - background-color: #FFF; + background-color: #fff; padding: 15px; padding-right: 30px; padding-top: 30px; border-left: 1px #333 solid; z-index: 12; - - /*transition-property: transform; - transition-duration: 0.3s; - transition-delay: 0.3s; - - transform: translate3d(100%, 0, 0);*/ -} - -#filter-form form { - + min-width: 300px; } #filter-form form .filter-group { margin: 5px; } +#download-form { + position: fixed; + width: 10%; + height: 100%; + top: 0; + right: 0; + background-color: #fff; + padding: 15px; + padding-right: 30px; + padding-top: 30px; + border-left: 1px #333 solid; + z-index: 12; + min-width: 200px; +} + +#download-form li { + display: block; + padding: 0.5em 2em 0.5em 1em; + color: #fff; + position: relative; + text-transform: uppercase; + text-decoration: none; + font-weight: 400; + font-family: PT Sans, sans-serif; + transition: all 0.5s ease; +} /* ========================================================================== 6 = Media Queries @@ -1015,6 +1157,7 @@ pre code { width: 100%; margin-left: 0; } + body > header { background-color: #333; position: fixed; @@ -1023,70 +1166,86 @@ pre code { height: 3em; z-index: 11; } + #links li:last-child { position: static; width: auto; } - #links li:last-child a:before { + + #links li:last-child a::before { content: none; } + .logo { width: 1.25em; height: 1.25em; left: 0; top: 0; } + .login > header { position: static; } + .login form { width: 100%; position: static; margin-left: 0; } + .login .logo { - width: auto; height: auto; top: 0.5em; width: 75px; height: 75px; margin-left: -37.5px; } + .desktopHide { display: block; position: fixed; z-index: 20; top: 0; right: 0; - border:0; + border: 0; width: 2.5em; height: 2.5em; cursor: pointer; background-color: #999; font-size: 1.2em; } - .desktopHide:hover, .desktopHide:focus { - background-color: #FFF; - } + .desktopHide:hover, + .desktopHide:focus { + background-color: #fff; + } + #links { display: none; width: 100%; height: auto; padding-top: 3em; } + #links.menu--open { display: block; } - footer { + + footer { position: static; margin-right: 3em; } + #main { margin-left: 1.5em; padding-right: 1.5em; position: static; margin-top: 3em; } + + .card-entry-labels { + display: none; + } + #article_toolbar .topPosF { display: none; } @@ -1098,6 +1257,7 @@ pre code { #article h1 { font-size: 1.5em; } + #article_toolbar a { padding: 0.3em 0.4em 0.2em; } @@ -1106,7 +1266,9 @@ pre code { display: none; } - .popup-form, #bagit-form, #search-form { + .popup-form, + #bagit-form, + #search-form { left: 0; width: 100%; border-left: none; diff --git a/app/Resources/static/themes/baggy/css/messages.css b/app/Resources/static/themes/baggy/css/messages.css new file mode 100755 index 00000000..bfaf1448 --- /dev/null +++ b/app/Resources/static/themes/baggy/css/messages.css @@ -0,0 +1,19 @@ +.messages.error.install { + border: 1px solid #c42608; + color: #c00 !important; + background: #fff0ef; + text-align: left; +} + +.messages.notice.install { + border: 1px solid #ebcd41; + color: #000; + background: #fffcd3; + text-align: left; +} + +.messages.success.install { + border: 1px solid #6dc70c; + background: #e0fbcc !important; + text-align: left; +} diff --git a/app/Resources/static/themes/baggy/css/print.css b/app/Resources/static/themes/baggy/css/print.css new file mode 100755 index 00000000..f7f6a8ad --- /dev/null +++ b/app/Resources/static/themes/baggy/css/print.css @@ -0,0 +1,66 @@ +@media print { + /* ### Layout ### */ + + body { + font-family: Serif; + background-color: #fff; + } + + @page { + margin: 1cm; + } + + img { + max-width: 100% !important; + } + + /* ### Content ### */ + + /* Hide useless blocks */ + body > header, + #article_toolbar, + #links, + #sort, + body > footer, + .top_link, + div.tools, + header div, + .messages, + .entrie + .results, + #article .mbm a, + #article-informations { + display: none !important; + } + + article { + border: none !important; + } + + /* Add URL after links */ + .vieworiginal a::after { + content: " (" attr(href) ")"; + } + + /* Add explanation after abbr */ + abbr[title]::after { + content: " (" attr(title) ")"; + } + + /* Change border on current pager item */ + .pagination span.current { + border-style: dashed; + } + + #main { + width: 100%; + padding: 0; + margin: 0; + margin-left: 0; + padding-right: 0; + padding-bottom: 0; + } + + #article { + width: 100%; + } +} diff --git a/src/Wallabag/CoreBundle/Resources/public/themes/baggy/css/ratatouille.css b/app/Resources/static/themes/baggy/css/ratatouille.css similarity index 63% rename from src/Wallabag/CoreBundle/Resources/public/themes/baggy/css/ratatouille.css rename to app/Resources/static/themes/baggy/css/ratatouille.css index 605eb641..b5aeb54e 100644 --- a/src/Wallabag/CoreBundle/Resources/public/themes/baggy/css/ratatouille.css +++ b/app/Resources/static/themes/baggy/css/ratatouille.css @@ -6,8 +6,8 @@ * { -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; } html { @@ -18,7 +18,7 @@ html { body { font-size: 1em; - line-height:1.5; + line-height: 1.5; margin: 0; } @@ -35,7 +35,7 @@ h6:first-child, p:first-child, ul:first-child, ol:first-child, -dl:first-child{ +dl:first-child { margin-top: 0; } @@ -43,14 +43,13 @@ code, kbd, pre, samp { - font-family: monospace, serif; + font-family: monospace, serif; } pre { - white-space: pre-wrap; + white-space: pre-wrap; } - .upper { text-transform: uppercase; } @@ -61,12 +60,12 @@ pre { .inner { margin: 0 auto; - max-width: 61.25em;/*980px*/ + max-width: 61.25em; /* 980px */ } table, img, figure { max-width: 100%; - height :auto; + height: auto; } iframe { @@ -93,13 +92,13 @@ button, input, select, textarea { - font-family: inherit; - font-size: 100%; - margin: 0; + font-family: inherit; + font-size: 100%; + margin: 0; } input[type="search"] { - -webkit-appearance: textfield; + -webkit-appearance: textfield; } /* ========================================================================== @@ -115,11 +114,17 @@ input[type="search"] { display: none; } -.dtable { display:table } +.dtable { + display: table; +} - .dtable > * { display:table-row; } +.dtable > * { + display: table-row; +} - .dtable > * > * { display:table-cell; } +.dtable > * > * { + display: table-cell; +} .element-invisible { border: 0; @@ -133,32 +138,60 @@ input[type="search"] { } .small { - font-size:0.8em; + font-size: 0.8em; } .big { font-size: 1.2em; } -/*Width*/ +/* Width */ -.w100 { width:100%; } -.w90 { width:90%; } -.w80 { width:80%; } -.w70 { width:70%; } -.w60 { width:60%; } -.w50 { width:50%; } -.w40 { width:40%; } -.w30 { width:30%; } -.w20 { width:20%; } -.w10 { width:10%; } +.w100 { + width: 100%; +} + +.w90 { + width: 90%; +} + +.w80 { + width: 80%; +} +.w70 { + width: 70%; +} + +.w60 { + width: 60%; +} + +.w50 { + width: 50%; +} + +.w40 { + width: 40%; +} + +.w30 { + width: 30%; +} + +.w20 { + width: 20%; +} + +.w10 { + width: 10%; +} /* ========================================================================== Internet Explorer ========================================================================== */ -/*IE8 and IE9*/ +/* IE8 and IE9 */ article, aside, @@ -172,40 +205,20 @@ main, nav, section, summary { - display: block; + display: block; } -/*IE8 and IE9*/ +/* IE8 and IE9 */ audio, canvas, video { - display: inline-block; + display: inline-block; } -@media screen and (-webkit-min-device-pixel-ratio:0){ - select{ +@media screen and (-webkit-min-device-pixel-ratio: 0) { + select { -webkit-appearance: none; border-radius: 0; } } - -/* ========================================================================== - Medias Queries - ========================================================================== */ - -/*Desktop 1080px*/ - -@media screen and (max-width: 67.50em) { -} - -/*Tablet 800px*/ - -@media screen and (max-width: 50em) { -} - -/*Mobile 640px*/ - -@media screen and (max-width: 40em) { -} - diff --git a/app/Resources/static/themes/baggy/font/icomoon.eot b/app/Resources/static/themes/baggy/font/icomoon.eot new file mode 100644 index 00000000..248758fb Binary files /dev/null and b/app/Resources/static/themes/baggy/font/icomoon.eot differ diff --git a/app/Resources/static/themes/baggy/font/icomoon.svg b/app/Resources/static/themes/baggy/font/icomoon.svg new file mode 100644 index 00000000..b1b9c92a --- /dev/null +++ b/app/Resources/static/themes/baggy/font/icomoon.svg @@ -0,0 +1,501 @@ + + + +Generated by IcoMoon + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/Resources/static/themes/baggy/font/icomoon.ttf b/app/Resources/static/themes/baggy/font/icomoon.ttf new file mode 100644 index 00000000..c03770c6 Binary files /dev/null and b/app/Resources/static/themes/baggy/font/icomoon.ttf differ diff --git a/app/Resources/static/themes/baggy/font/icomoon.woff b/app/Resources/static/themes/baggy/font/icomoon.woff new file mode 100644 index 00000000..121e0bdd Binary files /dev/null and b/app/Resources/static/themes/baggy/font/icomoon.woff differ diff --git a/src/Wallabag/CoreBundle/Resources/public/themes/baggy/img/baggy/blank.png b/app/Resources/static/themes/baggy/img/blank.png similarity index 100% rename from src/Wallabag/CoreBundle/Resources/public/themes/baggy/img/baggy/blank.png rename to app/Resources/static/themes/baggy/img/blank.png diff --git a/src/Wallabag/CoreBundle/Resources/public/themes/baggy/img/baggy/down.png b/app/Resources/static/themes/baggy/img/down.png similarity index 100% rename from src/Wallabag/CoreBundle/Resources/public/themes/baggy/img/baggy/down.png rename to app/Resources/static/themes/baggy/img/down.png diff --git a/src/Wallabag/CoreBundle/Resources/public/themes/baggy/img/baggy/list.png b/app/Resources/static/themes/baggy/img/list.png similarity index 100% rename from src/Wallabag/CoreBundle/Resources/public/themes/baggy/img/baggy/list.png rename to app/Resources/static/themes/baggy/img/list.png diff --git a/src/Wallabag/CoreBundle/Resources/public/themes/baggy/img/baggy/table.png b/app/Resources/static/themes/baggy/img/table.png similarity index 100% rename from src/Wallabag/CoreBundle/Resources/public/themes/baggy/img/baggy/table.png rename to app/Resources/static/themes/baggy/img/table.png diff --git a/src/Wallabag/CoreBundle/Resources/public/themes/baggy/img/baggy/top.png b/app/Resources/static/themes/baggy/img/top.png similarity index 100% rename from src/Wallabag/CoreBundle/Resources/public/themes/baggy/img/baggy/top.png rename to app/Resources/static/themes/baggy/img/top.png diff --git a/app/Resources/static/themes/baggy/js/autoClose.js b/app/Resources/static/themes/baggy/js/autoClose.js new file mode 100644 index 00000000..b0dafab2 --- /dev/null +++ b/app/Resources/static/themes/baggy/js/autoClose.js @@ -0,0 +1,8 @@ +var $ = global.jquery = require('jquery'); + +$(document).ready(function () { + var currentUrl = window.location.href; + if (currentUrl.match('&closewin=true')) { + window.close(); + } +}); diff --git a/app/Resources/static/themes/baggy/js/autoCompleteTags.js b/app/Resources/static/themes/baggy/js/autoCompleteTags.js new file mode 100755 index 00000000..edd0a421 --- /dev/null +++ b/app/Resources/static/themes/baggy/js/autoCompleteTags.js @@ -0,0 +1,46 @@ +var $ = global.jquery = require('jquery'); + +jQuery(function ($) { + function split(val) { + return val.split(/,\s*/); + } + function extractLast(term) { + return split(term).pop(); + } + + + $('#value').bind('keydown', function (event) { + if (event.keyCode === $.ui.keyCode.TAB && $(this).data('ui-autocomplete').menu.active) { + event.preventDefault(); + } + }).autocomplete({ + source: function (request, response) { + $.getJSON('./?view=tags', { + term: extractLast(request.term), + //id: $(':hidden#entry_id').val() + }, response); + }, + search: function () { + // custom minLength + var term = extractLast(this.value); + if (term.length < 1) { + return false; + } + }, + focus: function () { + // prevent value inserted on focus + return false; + }, + select: function (event, ui) { + var terms = split(this.value); + // remove the current input + terms.pop(); + // add the selected item + terms.push(ui.item.value); + // add placeholder to get the comma-and-space at the end + terms.push(''); + this.value = terms.join(', '); + return false; + }, + }); +}); diff --git a/app/Resources/static/themes/baggy/js/closeMessage.js b/app/Resources/static/themes/baggy/js/closeMessage.js new file mode 100644 index 00000000..ae4b1791 --- /dev/null +++ b/app/Resources/static/themes/baggy/js/closeMessage.js @@ -0,0 +1,19 @@ +var $ = global.jquery = require('jquery'); + +$(function () { + //--------------------------------------------------------------------------- + // Show the close icon when the user hover over a message + //--------------------------------------------------------------------------- + // $('.messages').on('mouseenter', function(){ + // $(this).find('a.closeMessage').stop(true, true).show(); + // }).on('mouseleave', function(){ + // $(this).find('a.closeMessage').stop(true, true).hide(); + // }); + //--------------------------------------------------------------------------- + // Close the message box when the user clicks the close icon + //--------------------------------------------------------------------------- + $('a.closeMessage').on('click', function () { + $(this).parents('div.messages').slideUp(300, function () { $(this).remove(); }); + return false; + }); +}); diff --git a/app/Resources/static/themes/baggy/js/init.js b/app/Resources/static/themes/baggy/js/init.js new file mode 100755 index 00000000..d7d4b166 --- /dev/null +++ b/app/Resources/static/themes/baggy/js/init.js @@ -0,0 +1,98 @@ +var $ = global.jquery = require('jquery'); +require('jquery.cookie'); +require('jquery-ui'); +var annotator = require('annotator'); + + +$.fn.ready(function () { + var $listmode = $('#listmode'); + var $listentries = $('#list-entries'); + + /* ========================================================================== + Menu + ========================================================================== */ + + $('#menu').click(function () { + $('#links').toggleClass('menu--open'); + if ($('#content').hasClass('opacity03')) { + $('#content').removeClass('opacity03'); + } + }); + + /* ========================================================================== + List mode or Table Mode + ========================================================================== */ + + $listmode.click(function () { + if (jquery.cookie('listmode') === 1) { + // Cookie + $.removeCookie('listmode'); + + $listentries.removeClass('listmode'); + $listmode.removeClass('tablemode'); + $listmode.addClass('listmode'); + } else { + // Cookie + jquery.cookie('listmode', 1, { expires: 365 }); + + $listentries.addClass('listmode'); + $listmode.removeClass('listmode'); + $listmode.addClass('tablemode'); + } + }); + + /* ========================================================================== + Cookie listmode + ========================================================================== */ + + if (jquery.cookie('listmode') === 1) { + $listentries.addClass('listmode'); + $listmode.removeClass('listmode'); + $listmode.addClass('tablemode'); + } + + /* ========================================================================== + Add tag panel + ========================================================================== */ + + + $('#nav-btn-add-tag').on('click', function () { + $('.nav-panel-add-tag').toggle(100); + $('.nav-panel-menu').addClass('hidden'); + $('#tag_label').focus(); + return false; + }); + + /* ========================================================================== + Annotations & Remember position + ========================================================================== */ + + if ($('article').length) { + var app = new annotator.App(); + + app.include(annotator.ui.main, { + element: document.querySelector('article'), + }); + + var x = JSON.parse($('#annotationroutes').html()); + app.include(annotator.storage.http, x); + + app.start().then(function () { + app.annotations.load({ entry: x.entryId }); + }); + + $(window).scroll(function (e) { + var scrollTop = $(window).scrollTop(); + var docHeight = $(document).height(); + var scrollPercent = (scrollTop) / (docHeight); + var scrollPercentRounded = Math.round(scrollPercent * 100) / 100; + savePercent(x.entryId, scrollPercentRounded); + }); + + retrievePercent(x.entryId); + + $(window).resize(function () { + retrievePercent(x.entryId); + }); + } +}); diff --git a/app/Resources/static/themes/baggy/js/popupForm.js b/app/Resources/static/themes/baggy/js/popupForm.js new file mode 100644 index 00000000..95ba60ee --- /dev/null +++ b/app/Resources/static/themes/baggy/js/popupForm.js @@ -0,0 +1,101 @@ +var $ = global.jquery = require('jquery'); + +$(document).ready(function () { + $('#search-form').hide(); + $('#bagit-form').hide(); + $('#filter-form').hide(); + $('#download-form').hide(); + + //--------------------------------------------------------------------------- + // Toggle the 'Search' popup in the sidebar + //--------------------------------------------------------------------------- + function toggleSearch() { + $('#search-form').toggle(); + $('#search').toggleClass('current'); + $('#search').toggleClass('active-current'); + $('#search-arrow').toggleClass('arrow-down'); + if ($('#search').hasClass('current')) { + $('#content').addClass('opacity03'); + } else { + $('#content').removeClass('opacity03'); + } + } + + //--------------------------------------------------------------------------- + // Toggle the 'Filter' popup on entries list + //--------------------------------------------------------------------------- + function toggleFilter() { + $('#filter-form').toggle(); + } + + //--------------------------------------------------------------------------- + // Toggle the 'Download' popup on entries list + //--------------------------------------------------------------------------- + function toggleDownload() { + $('#download-form').toggle(); + } + + //--------------------------------------------------------------------------- + // Toggle the 'Save a Link' popup in the sidebar + //--------------------------------------------------------------------------- + function toggleBagit() { + $('#bagit-form').toggle(); + $('#bagit').toggleClass('current'); + $('#bagit').toggleClass('active-current'); + $('#bagit-arrow').toggleClass('arrow-down'); + if ($('#bagit').hasClass('current')) { + $('#content').addClass('opacity03'); + } else { + $('#content').removeClass('opacity03'); + } + } + + //--------------------------------------------------------------------------- + // Close all #links popups in the sidebar + //--------------------------------------------------------------------------- + function closePopups() { + $('#links .messages').hide(); + $('#links > li > a').removeClass('active-current'); + $('#links > li > a').removeClass('current'); + $('[id$=-arrow]').removeClass('arrow-down'); + $('#content').removeClass('opacity03'); + } + + $('#search').click(function () { + closePopups(); + toggleSearch(); + $('#searchfield').focus(); + }); + + $('.filter-btn').click(function () { + closePopups(); + toggleFilter(); + }); + + $('.download-btn').click(function () { + closePopups(); + toggleDownload(); + }); + + $('#bagit').click(function () { + closePopups(); + toggleBagit(); + $('#plainurl').focus(); + }); + + $('#search-form-close').click(function () { + toggleSearch(); + }); + + $('#filter-form-close').click(function () { + toggleFilter(); + }); + + $('#download-form-close').click(function () { + toggleDownload(); + }); + + $('#bagit-form-close').click(function () { + toggleBagit(); + }); +}); diff --git a/app/Resources/static/themes/baggy/js/saveLink.js b/app/Resources/static/themes/baggy/js/saveLink.js new file mode 100755 index 00000000..5c720886 --- /dev/null +++ b/app/Resources/static/themes/baggy/js/saveLink.js @@ -0,0 +1,75 @@ +var $ = global.jquery = require('jquery'); + +$.fn.ready(function () { + var $bagit = $('#bagit'); + var $bagitForm = $('#bagit-form'); + var $bagitFormForm = $('#bagit-form-form'); + + /* ========================================================================== + bag it link and close button + ========================================================================== */ + + function toggleSaveLinkForm(url, event) { + $('#add-link-result').empty(); + + $bagit.toggleClass('active-current'); + + // only if bag-it link is not presented on page + if ($bagit.length === 0) { + if (event !== 'undefined' && event) { + $bagitForm.css({ position: 'absolute', top: event.pageY, left: event.pageX - 200 }); + } else { + $bagitForm.css({ position: 'relative', top: 'auto', left: 'auto' }); + } + } + + if ($('#search-form').length !== 0) { + $('#search').removeClass('current'); + $('#search-arrow').removeClass('arrow-down'); + $('#search-form').hide(); + } + $bagitForm.toggle(); + $('#content').toggleClass('opacity03'); + if (url !== 'undefined' && url) { + $('#plainurl').val(url); + } + $('#plainurl').focus(); + } + + // send 'bag it link' form request via ajax + $bagitFormForm.submit(function (event) { + $('body').css('cursor', 'wait'); + $('#add-link-result').empty(); + + $.ajax({ + type: $bagitFormForm.attr('method'), + url: $bagitFormForm.attr('action'), + data: $bagitFormForm.serialize(), + success: function (data) { + $('#add-link-result').html('Done!'); + $('#plainurl').val(''); + $('#plainurl').blur(''); + $('body').css('cursor', 'auto'); + }, + error: function (data) { + $('#add-link-result').html('Failed!'); + $('body').css('cursor', 'auto'); + }, + }); + + event.preventDefault(); + }); + + /* ========================================================================== + Process all links inside an article + ========================================================================== */ + + $('article a[href^="http"]').after(function () { + return ' '; + }); + + $('.add-to-wallabag-link-after').click(function (event) { + toggleSaveLinkForm($(this).attr('href'), event); + event.preventDefault(); + }); +}); diff --git a/app/Resources/static/themes/material/css/main.css b/app/Resources/static/themes/material/css/main.css new file mode 100755 index 00000000..005cc302 --- /dev/null +++ b/app/Resources/static/themes/material/css/main.css @@ -0,0 +1,680 @@ +/* ========================================================================== + Sommaire + + 0 = Common + 1 = Nav + 2 = Side-nav + 3 = Filters slider + 4 = Cards + 5 = Article + 6 = Media queries + 7 = Font + 8 = Others + + ========================================================================== */ + +/* ========================================================================== + 0 = Common + ========================================================================== */ + +@font-face { + font-family: icomoon; + src: url("../fonts/icomoon.eot"); + src: + url("../fonts/icomoon.eot#iefix") format("embedded-opentype"), + url("../fonts/icomoon.ttf") format("truetype"), + url("../fonts/icomoon.woff") format("woff"), + url("../fonts/icomoon.svg#icomoon") format("svg"); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'Material Icons'; + font-style: normal; + font-weight: 400; + src: url(../fonts/MaterialIcons-Regular.eot); + + /* For IE6-8 */ + src: local("Material Icons"), local("MaterialIcons-Regular"), url(../fonts/MaterialIcons-Regular.woff2) format("woff2"), url(../fonts/MaterialIcons-Regular.woff) format("woff"), url(../fonts/MaterialIcons-Regular.ttf) format("truetype"); +} + +.material-icons { + font-family: 'Material Icons'; + font-weight: normal; + font-style: normal; + font-size: 24px; /* Preferred icon size */ + width: 1em; + height: 1em; + display: inline-block; + line-height: 1; + text-transform: none; + letter-spacing: normal; + word-wrap: normal; + white-space: nowrap; + direction: ltr; + + /* Support for all WebKit browsers. */ + -webkit-font-smoothing: antialiased; + + /* Support for Safari and Chrome. */ + text-rendering: optimizeLegibility; + + /* Support for Firefox. */ + -moz-osx-font-smoothing: grayscale; + + /* Support for IE. */ + font-feature-settings: 'liga'; +} + +[class^="icon-"], +[class*=" icon-"] { + font-family: icomoon; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +body { + display: flex; + min-height: 100vh; + flex-direction: column; + background: #f0f0f0; +} + +body.login main { + padding: 0; + min-height: 100vh; +} + +.border-bottom { + border-bottom: 1px solid #ddd; +} + +nav, +main, +footer { + padding-left: 240px; +} + +main, +#content, +.valign-wrapper { + height: 100%; +} + +#main { + flex: 1 0 auto; +} + +.results { + height: 1em; + line-height: 30px; +} + +.results .nb-results, +.results .pagination { + margin: 15px; + margin-bottom: 0; +} + +.pagination { + float: right; +} + +.pagination ul { + margin: 0 !important; +} + +.pagination li { + padding: 0; +} + +.pagination a { + padding: 0 10px; + height: 30px; + display: block; +} + +.pagination .disabled { + margin-right: 10px; + margin-left: 10px; +} + +div.pagination ul .prev.disabled, +div.pagination ul .next.disabled { + display: none; +} + +.pagination li.active span { + padding: 0 10px; + height: 30px; + display: block; + color: #fff; +} + +.page-footer .footer-copyright p { + display: inline; +} + +.hidden { + display: none; +} + +.picker__date-display { + display: none; +} + +footer.page-footer { + margin-top: 10px; + padding-top: 0px; +} + +footer .row { + margin-bottom: 10px; +} + +/* ========================================================================== + 1 = Nav + ========================================================================== */ + +nav input { + color: #aaa; +} + +.nav-wrapper .button-collapse { + padding: 0 15px; +} + +.nav-input { + display: none; +} + +.nav-panels { + overflow: hidden; +} + +.nav-panel-buttom li { + max-height: 64px; +} + +.nav-panels { + transition: background 0.2s ease; +} + +.nav-panel-add .add, +.nav-panel-search .search, +.nav-panels .close { + color: #444 !important; +} + +.nav-panels .action { + padding-left: 0.75rem; + font-size: 2.1rem; + white-space: nowrap; +} + +.nav-panels .input-field input { + display: block; + line-height: inherit; + padding-left: 4rem !important; + width: calc(100% - 8rem); +} + +.nav-panels .input-field input:focus { + background-color: #fff; + border: 0; + box-shadow: none; + color: #444; +} + +.input-field.nav-panel-add label { + left: 1rem; +} + +.input-field.nav-panel-add .close { + position: absolute; + top: 0; + right: 1rem; + color: transparent; + cursor: pointer; + font-size: 2rem; + transition: 0.3s color; +} + +#button_filters { + display: none; +} + +#button_export { + display: none; +} + +.input-field.nav-panel-add, .input-field.nav-panel-add form { + height: 100%; +} + +/* ========================================================================== + 2 = Side-nav + ========================================================================== */ + +.side-nav.fixed a { + font-size: 13px; + line-height: 44px; + height: 44px; +} + +.side-nav .collapsible-header, +.side-nav.fixed .collapsible-header { + height: 45px; + line-height: 44px; + padding: 0 20px; +} + +.bold > a { + font-weight: bold; +} + +.side-nav > li.logo { + line-height: 0; + text-align: center; +} + +#main .logo a { + height: 100pt; +} + +#main .logo img { + height: 100pt; + width: 100pt; +} + +#main .logo:hover { + background: transparent; +} + +.side-nav li { + padding: 0; +} + +.side-nav a { + margin: 0 1rem; +} + +span.numberItems { + float: right; +} + +/* ========================================================================== + * 3 = Filters slider + * ========================================================================== */ + +#filters button { + padding: 0; + width: 100%; +} + +.side-nav.fixed.right-aligned { + right: -250px; + left: auto !important; + overflow-y: visible; +} + +#filters div.with-checkbox { + height: 3rem; + margin-top: 0; +} + +/* ========================================================================== + 4 = Cards + ========================================================================== */ + +main #content { + padding: 0 0.5rem; +} + +main ul.row { + padding: 0 0.75rem; +} + +.data .card .card-body { + height: 22em; + overflow: hidden; +} + +.card .card-content .card-title { + line-height: 32px; + max-height: 64px; +} + +.card .card-content i.right, .card .card-reveal i.right { + margin-left: 0; +} + +.card .card-entry-labels { + position: absolute; + top: 10px; + z-index: 90; + max-width: 50%; +} + +.card .card-entry-labels li { + margin: 10px 10px 10px auto; + padding: 5px 12px 5px 16px; + background-color: rgba(0, 151, 167, 0.85); + border-radius: 0 3px 3px 0; + color: #fff; + cursor: default; + max-height: 2em; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.card .card-entry-labels-hidden { + margin-top: 5px; +} + +.card .card-entry-labels-hidden li { + display: inline-block; + background-color: rgba(0, 151, 167, 0.85); + margin: 0 5px; + padding: 5px 12px; + border-radius: 3px; + color: #fff; + max-height: 2em; + max-width: calc(100% - 15px); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.card .card-content .estimatedTime { + margin-bottom: 10px; +} + +.card .card-action .original { + line-height: 24px; +} + +.card .card-action ul.links { + margin: 0; + font-size: 24px; + line-height: 24px; +} + +.card .card-action a { + color: #fff !important; + margin: 0; +} + +.card .card-action a:hover { + color: #fff !important; +} + +.settings .div_tabs { + padding-bottom: 15px; +} + +.card.sw { + max-width: 370px; + margin-left: auto; + margin-right: auto; +} + +.card .card-image { + height: 14em; +} + +.card .card-image .preview { + height: 14em; + background-size: cover; + background-repeat: no-repeat; + background-position: 50%; +} + +/* ========================================================================== + 5 = Article + ========================================================================== */ + +#article { + font-size: 20px; + margin: 0 auto; + max-width: 40em; +} + +#article img, +#article figure { + max-width: 100%; + height: auto; +} + +#article > header > h1 { + font-size: 2em; +} + +.reader-mode { + width: 95px !important; + transition: width 0.2s ease; +} + +.reader-mode:hover { + width: 240px !important; +} + +.reader-mode .collapsible-body { + height: 0; + overflow: hidden; +} + +.reader-mode:hover .collapsible-body { + height: auto; +} + +.reader-mode span { + opacity: 0; + transition: opacity 0.2s ease; +} + +.reader-mode:hover span { + opacity: 1; +} + +.progress { + position: fixed; + top: 0; + width: 100%; + height: 3px; + margin: 0; + z-index: 9999; +} + +#article aside .link { + color: #000; + font-size: 0.8em; + text-decoration: none; +} + +#article aside #list { + float: right; + margin: 0 15px 10px; +} + +#article aside .chip { + background-color: rgba(0, 151, 167, 0.85); + color: #fff; + padding: 0 15px 0 10px; +} + +#article aside .chip i { + color: #fff; +} + +/* ========================================================================== + 6 = Media queries + ========================================================================== */ + +@media only screen and (max-width: 992px) { + header, + main, + footer { + padding-left: 0; + } + nav, + main, + footer { + padding-left: 0; + } + .pagination { + width: auto; + } + .reader-mode { + width: 240px !important; + } + .reader-mode span { + opacity: 1; + } + .tabs { + display: inline-block; + height: auto; + } + .tab { + min-width: 100%; + } + .indicator { + display: none; + } + .pagination li.prev, + .pagination li.next { + width: auto; + } +} + +@media only screen and (min-width: 400px) { + .nav-panel-buttom { + float: right; + } +} + +@media only screen and (min-width: 993px) and (max-width: 1180px) { + .row .col.l1 { + width: 25%; + margin-left: 0; + } + .row .col.l2 { + width: 33.33333%; + margin-left: 0; + } + .row .col.l3 { + width: 41.66667%; + margin-left: 0; + } + .row .col.l4 { + width: 50%; + margin-left: 0; + } + .row .col.l5 { + width: 58.33333%; + margin-left: 0; + } + .row .col.l6 { + width: 66.66667%; + margin-left: 0; + } + .row .col.l7 { + width: 75%; + margin-left: 0; + } + .row .col.l8 { + width: 83.33333%; + margin-left: 0; + } + .row .col.l9 { + width: 91.66667%; + margin-left: 0; + } + .row .col.l10 { + width: 100%; + margin-left: 0; + } +} + +@media only screen and (max-width: 350px) { + .nb-results { + display: none; + } +} + +/* ========================================================================== + 7 = Font + ========================================================================== */ + +.icon-google-plus2::before { + content: "\ea89"; +} + +.icon-facebook2::before { + content: "\ea8d"; +} + +.icon-twitter::before { + content: "\ea91"; +} + +.icon-apple::before { + content: "\eabf"; +} + +.icon-android::before { + content: "\eac1"; +} + +.icon-chrome::before { + content: "\eae5"; +} + +.icon-firefox::before { + content: "\eae6"; +} + +.icon-link::before { + content: "\e9cb"; +} + +footer [class^="icon-"], +footer [class*=" icon-"] { + font-size: 2em; + transition: text-shadow 0.2s ease; + padding-right: 10px; +} + +footer [class^="icon-"]:hover, +footer [class*=" icon-"]:hover { + text-shadow: 0 0 10px rgba(0, 0, 0, 0.3); +} + +/* ========================================================================== + 8 = Others + ========================================================================== */ + +/* force height on non-input field in the settings page */ +div.settings div.input-field div, +div.settings div.input-field ul { + margin-top: 40px; +} + +/* but avoid to kill all file input */ +div.settings div.file-field div { + margin-top: inherit; +} + +.input-field label.active { + font-size: 1rem; +} diff --git a/app/Resources/static/themes/material/css/print.css b/app/Resources/static/themes/material/css/print.css new file mode 100755 index 00000000..1eb96735 --- /dev/null +++ b/app/Resources/static/themes/material/css/print.css @@ -0,0 +1,77 @@ +@media print { + /* ### Layout ### */ + + body { + font-family: Serif; + background-color: #fff; + } + + @page { + margin: 1cm; + } + + img { + max-width: 100% !important; + } + + /* ### Content ### */ + + /* Hide useless blocks */ + body > header, + #article_toolbar, + #links, + #sort, + body > footer, + .top_link, + div.tools, + header div, + .messages, + .entry + .results, + #slide-out, + .progress, .hide-on-large-only, + #article > aside, + #article .mbm a + { + display: none !important; + } + + main { + padding-left: 0 !important; + } + + #article { + margin: inherit !important; + } + + article { + border: none !important; + } + + /* Add URL after links */ + .vieworiginal a::after { + content: " (" attr(href) ")"; + } + + /* Add explanation after abbr */ + abbr[title]::after { + content: " (" attr(title) ")"; + } + + /* Change border on current pager item */ + .pagination span.current { + border-style: dashed; + } + + #main { + width: 100%; + padding: 0; + margin: 0; + margin-left: 0; + padding-right: 0; + padding-bottom: 0; + } + + #article { + width: 100%; + } +} diff --git a/app/Resources/static/themes/material/js/init.js b/app/Resources/static/themes/material/js/init.js new file mode 100755 index 00000000..d6a87941 --- /dev/null +++ b/app/Resources/static/themes/material/js/init.js @@ -0,0 +1,117 @@ +var $ = require('jquery'); +require('materialize'); +var annotator = require('annotator'); + +function initFilters() { + // no display if filters not aviable + if ($('div').is('#filters')) { + $('#button_filters').show(); + $('.button-collapse-right').sideNav({ edge: 'right' }); + $('#clear_form_filters').on('click', function () { + $('#filters input').val(''); + $('#filters :checked').removeAttr('checked'); + return false; + }); + } +} + +function initExport() { + // no display if export not aviable + if ($('div').is('#export')) { + $('#button_export').show(); + $('.button-collapse-right').sideNav({ edge: 'right' }); + } +} + +$(document).ready(function () { + // sideNav + $('.button-collapse').sideNav(); + $('select').material_select(); + $('.collapsible').collapsible({ + accordion: false, + }); + $('.datepicker').pickadate({ + selectMonths: true, + selectYears: 15, + formatSubmit: 'dd/mm/yyyy', + hiddenName: true, + format: 'dd/mm/yyyy', + }); + initFilters(); + initExport(); + + $('#nav-btn-add-tag').on('click', function () { + $('.nav-panel-add-tag').toggle(100); + $('.nav-panel-menu').addClass('hidden'); + $('#tag_label').focus(); + return false; + }); + $('#nav-btn-add').on('click', function () { + $('.nav-panel-buttom').hide(100); + $('.nav-panel-add').show(100); + $('.nav-panels .action').hide(100); + $('.nav-panel-menu').addClass('hidden'); + $('.nav-panels').css('background', 'white'); + $('#entry_url').focus(); + return false; + }); + $('#nav-btn-search').on('click', function () { + $('.nav-panel-buttom').hide(100); + $('.nav-panel-search').show(100); + $('.nav-panels .action').hide(100); + $('.nav-panel-menu').addClass('hidden'); + $('.nav-panels').css('background', 'white'); + $('#searchfield').focus(); + return false; + }); + $('.close').on('click', function () { + $('.nav-panel-add').hide(100); + $('.nav-panel-search').hide(100); + $('.nav-panel-buttom').show(100); + $('.nav-panels .action').show(100); + $('.nav-panel-menu').removeClass('hidden'); + $('.nav-panels').css('background', 'transparent'); + return false; + }); + $(window).scroll(function () { + var s = $(window).scrollTop(); + var d = $(document).height(); + var c = $(window).height(); + var scrollPercent = (s / (d - c)) * 100; + $('.progress .determinate').css('width', scrollPercent + '%'); + }); + +/* ========================================================================== + Annotations & Remember position + ========================================================================== */ + + if ($('article').length) { + var app = new annotator.App(); + var x = JSON.parse($('#annotationroutes').html()); + + + app.include(annotator.ui.main, { + element: document.querySelector('article'), + }); + + app.include(annotator.storage.http, x); + + app.start().then(function () { + app.annotations.load({ entry: x.entryId }); + }); + + $(window).scroll(function (e) { + var scrollTop = $(window).scrollTop(); + var docHeight = $(document).height(); + var scrollPercent = (scrollTop) / (docHeight); + var scrollPercentRounded = Math.round(scrollPercent * 100) / 100; + savePercent(x.entryId, scrollPercentRounded); + }); + + retrievePercent(x.entryId); + + $(window).resize(function () { + retrievePercent(x.entryId); + }); + } +}); diff --git a/app/config/config.yml b/app/config/config.yml index 2b11937c..fbebfee7 100644 --- a/app/config/config.yml +++ b/app/config/config.yml @@ -30,7 +30,7 @@ framework: assets: ~ wallabag_core: - version: 2.0.8 + version: 2.1.0 paypal_url: "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9UBA65LG3FX9Y&lc=gb" languages: en: 'English' @@ -49,9 +49,13 @@ wallabag_core: language: en rss_limit: 50 reading_speed: 1 + cache_lifetime: 10 + +wallabag_user: + registration_enabled: "%fosuser_registration%" wallabag_import: - allow_mimetypes: ['application/octet-stream', 'application/json', 'text/plain'] + allow_mimetypes: ['application/octet-stream', 'application/json', 'text/plain', 'text/csv'] resource_dir: "%kernel.root_dir%/../web/uploads/import" # Twig Configuration @@ -60,19 +64,7 @@ twig: strict_variables: "%kernel.debug%" form_themes: - "LexikFormFilterBundle:Form:form_div_layout.html.twig" - -# Assetic Configuration -assetic: - debug: "%kernel.debug%" - use_controller: false - bundles: [ ] - #java: /usr/bin/java - filters: - cssrewrite: ~ - #closure: - # jar: "%kernel.root_dir%/Resources/java/compiler.jar" - #yui_css: - # jar: "%kernel.root_dir%/Resources/java/yuicompressor-2.4.7.jar" + exception_controller: wallabag_core.exception_controller:showAction # Doctrine Configuration doctrine: @@ -224,3 +216,106 @@ lexik_maintenance: response: code: 503 status: "wallabag Service Temporarily Unavailable" + +old_sound_rabbit_mq: + connections: + default: + host: "%rabbitmq_host%" + port: "%rabbitmq_port%" + user: "%rabbitmq_user%" + password: "%rabbitmq_password%" + vhost: / + lazy: true + producers: + import_pocket: + connection: default + exchange_options: + name: 'wallabag.import.pocket' + type: topic + import_readability: + connection: default + exchange_options: + name: 'wallabag.import.readability' + type: topic + import_instapaper: + connection: default + exchange_options: + name: 'wallabag.import.instapaper' + type: topic + import_wallabag_v1: + connection: default + exchange_options: + name: 'wallabag.import.wallabag_v1' + type: topic + import_wallabag_v2: + connection: default + exchange_options: + name: 'wallabag.import.wallabag_v2' + type: topic + import_firefox: + connection: default + exchange_options: + name: 'wallabag.import.firefox' + type: topic + import_chrome: + connection: default + exchange_options: + name: 'wallabag.import.chrome' + type: topic + consumers: + import_pocket: + connection: default + exchange_options: + name: 'wallabag.import.pocket' + type: topic + queue_options: + name: 'wallabag.import.pocket' + callback: wallabag_import.consumer.amqp.pocket + import_readability: + connection: default + exchange_options: + name: 'wallabag.import.readability' + type: topic + queue_options: + name: 'wallabag.import.readability' + callback: wallabag_import.consumer.amqp.readability + import_instapaper: + connection: default + exchange_options: + name: 'wallabag.import.instapaper' + type: topic + queue_options: + name: 'wallabag.import.instapaper' + callback: wallabag_import.consumer.amqp.instapaper + import_wallabag_v1: + connection: default + exchange_options: + name: 'wallabag.import.wallabag_v1' + type: topic + queue_options: + name: 'wallabag.import.wallabag_v1' + callback: wallabag_import.consumer.amqp.wallabag_v1 + import_wallabag_v2: + connection: default + exchange_options: + name: 'wallabag.import.wallabag_v2' + type: topic + queue_options: + name: 'wallabag.import.wallabag_v2' + callback: wallabag_import.consumer.amqp.wallabag_v2 + import_firefox: + connection: default + exchange_options: + name: 'wallabag.import.firefox' + type: topic + queue_options: + name: 'wallabag.import.firefox' + callback: wallabag_import.consumer.amqp.firefox + import_chrome: + connection: default + exchange_options: + name: 'wallabag.import.chrome' + type: topic + queue_options: + name: 'wallabag.import.chrome' + callback: wallabag_import.consumer.amqp.chrome diff --git a/app/config/config_dev.yml b/app/config/config_dev.yml index 0fa23dbf..3b67d8f6 100644 --- a/app/config/config_dev.yml +++ b/app/config/config_dev.yml @@ -35,11 +35,16 @@ monolog: VERBOSITY_DEBUG: DEBUG channels: [doctrine] -assetic: - use_controller: true - swiftmailer: # see http://mailcatcher.me/ transport: smtp host: 'localhost' port: 1025 + +# If you want to use cache for queries used in WallabagExtension +# Uncomment the following lines +#doctrine: +# orm: +# metadata_cache_driver: apcu +# result_cache_driver: apcu +# query_cache_driver: apcu diff --git a/app/config/parameters.yml.dist b/app/config/parameters.yml.dist index d45839f4..f2e5bec3 100644 --- a/app/config/parameters.yml.dist +++ b/app/config/parameters.yml.dist @@ -34,6 +34,19 @@ parameters: twofactor_sender: no-reply@wallabag.org # fosuser stuff + fosuser_registration: true fosuser_confirmation: true from_email: no-reply@wallabag.org + + rss_limit: 50 + + # RabbitMQ processing + rabbitmq_host: localhost + rabbitmq_port: 5672 + rabbitmq_user: guest + rabbitmq_password: guest + + # Redis processing + redis_host: localhost + redis_port: 6379 diff --git a/app/config/parameters_test.yml b/app/config/parameters_test.yml index 696c95ef..2943b27a 100644 --- a/app/config/parameters_test.yml +++ b/app/config/parameters_test.yml @@ -5,4 +5,4 @@ parameters: test_database_name: null test_database_user: null test_database_password: null - test_database_path: '%kernel.root_dir%/../data/db/wallabag_testYO.sqlite' + test_database_path: '%kernel.root_dir%/../data/db/wallabag_test.sqlite' diff --git a/app/config/routing.yml b/app/config/routing.yml index 40cc7165..2be74d7f 100644 --- a/app/config/routing.yml +++ b/app/config/routing.yml @@ -7,6 +7,11 @@ wallabag_import: type: annotation prefix: /import +wallabag_user: + resource: "@WallabagUserBundle/Controller/" + type: annotation + prefix: /users + wallabag_api: resource: "@WallabagApiBundle/Resources/config/routing.yml" prefix: / diff --git a/app/config/security.yml b/app/config/security.yml index e24e03df..efb00a53 100644 --- a/app/config/security.yml +++ b/app/config/security.yml @@ -60,6 +60,8 @@ security: - { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: /(unread|starred|archive).xml$, roles: IS_AUTHENTICATED_ANONYMOUSLY } + - { path: ^/share, roles: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/settings, roles: ROLE_SUPER_ADMIN } - { path: ^/annotations, roles: ROLE_USER } + - { path: ^/users, roles: ROLE_SUPER_ADMIN } - { path: ^/, roles: ROLE_USER } diff --git a/app/config/services.yml b/app/config/services.yml index 480408d9..a57ef0f3 100644 --- a/app/config/services.yml +++ b/app/config/services.yml @@ -16,6 +16,12 @@ services: wallabag.twig_extension: class: Wallabag\CoreBundle\Twig\WallabagExtension public: false + arguments: + - "@wallabag_core.entry_repository" + - "@wallabag_core.tag_repository" + - "@security.token_storage" + - "%wallabag_core.cache_lifetime%" + - "@translator" tags: - { name: twig.extension } diff --git a/bin/symfony_requirements b/bin/symfony_requirements index 8825a964..a7bf65a1 100755 --- a/bin/symfony_requirements +++ b/bin/symfony_requirements @@ -22,7 +22,6 @@ echo '> Checking Symfony requirements:'.PHP_EOL.' '; $messages = array(); foreach ($symfonyRequirements->getRequirements() as $req) { - /** @var $req Requirement */ if ($helpText = get_error_message($req, $lineSize)) { echo_style('red', 'E'); $messages['error'][] = $helpText; @@ -121,10 +120,14 @@ function echo_block($style, $title, $message) echo PHP_EOL.PHP_EOL; - echo_style($style, str_repeat(' ', $width).PHP_EOL); - echo_style($style, str_pad(' ['.$title.']', $width, ' ', STR_PAD_RIGHT).PHP_EOL); - echo_style($style, str_pad($message, $width, ' ', STR_PAD_RIGHT).PHP_EOL); - echo_style($style, str_repeat(' ', $width).PHP_EOL); + echo_style($style, str_repeat(' ', $width)); + echo PHP_EOL; + echo_style($style, str_pad(' ['.$title.']', $width, ' ', STR_PAD_RIGHT)); + echo PHP_EOL; + echo_style($style, $message); + echo PHP_EOL; + echo_style($style, str_repeat(' ', $width)); + echo PHP_EOL; } function has_color_support() diff --git a/bower.json b/bower.json new file mode 100644 index 00000000..f2d2bd26 --- /dev/null +++ b/bower.json @@ -0,0 +1,39 @@ +{ + "name": "wallabag", + "version": "2.0.0-beta.1", + "homepage": "https://github.com/wallabag/wallabag", + "authors": [ + { + "name": "Nicolas Lœuillet", + "email": "nicolas@loeuillet.org", + "homepage": "http://www.cdetc.fr", + "role": "Developer" + }, + { + "name": "Thomas Citharel", + "homepage": "http://tcit.fr", + "role": "Developer" + }, + { + "name": "Jérémy Benoist", + "homepage": "http://www.j0k3r.net", + "role": "Developer" + } + ], + "description": "wallabag is a self hostable application for saving web pages", + "license": "MIT", + "main": "bower.json", + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "test", + "tests" + ], + "dependencies": { + "icomoon-bower": "^0.1.0", + "bower-pt-sans": "pt-sans#*", + "roboto-fontface": "^0.4.5", + "material-design-icons-iconfont": "^2.0.4" + } +} diff --git a/composer.json b/composer.json index c7830a14..8220ed45 100644 --- a/composer.json +++ b/composer.json @@ -48,7 +48,6 @@ "doctrine/doctrine-bundle": "^1.6", "doctrine/doctrine-cache-bundle": "^1.2", "twig/extensions": "~1.0", - "symfony/assetic-bundle": "~2.3", "symfony/swiftmailer-bundle": "^2.3", "symfony/monolog-bundle": "^2.8", "sensio/distribution-bundle": "^5.0", @@ -81,22 +80,26 @@ "mnapoli/piwik-twig-extension": "^1.0", "lexik/maintenance-bundle": "~2.1", "ocramius/proxy-manager": "1.*", - "white-october/pagerfanta-bundle": "^1.0" + "white-october/pagerfanta-bundle": "^1.0", + "mouf/nodejs-installer": "~1.0", + "php-amqplib/rabbitmq-bundle": "^1.8", + "predis/predis": "^1.0", + "javibravo/simpleue": "^1.0" }, "require-dev": { "doctrine/doctrine-fixtures-bundle": "~2.2", "doctrine/data-fixtures": "~1.1.1", "sensio/generator-bundle": "^3.0", - "phpunit/phpunit": "~4.4", + "phpunit/phpunit": "~5.0", "symfony/phpunit-bridge": "^3.0", - "friendsofphp/php-cs-fixer": "~1.9" + "friendsofphp/php-cs-fixer": "~1.9", + "m6web/redis-mock": "^2.0" }, "scripts": { "post-cmd": [ "Incenteev\\ParameterHandler\\ScriptHandler::buildParameters", "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap", "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache", - "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets", "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile", "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::prepareDeploymentTarget" ], @@ -113,7 +116,6 @@ "symfony-var-dir": "var", "symfony-web-dir": "web", "symfony-tests-dir": "tests", - "symfony-assets-install": "relative", "incenteev-parameters": { "file": "app/config/parameters.yml" } diff --git a/docker-compose.yml b/docker-compose.yml index 50d8c546..3c28f2f1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,6 +11,7 @@ services: links: - php:php command: nginx -c /nginx.conf + php: build: context: docker/php @@ -30,6 +31,7 @@ services: # If all DBMS are commented out, sqlite will be used as default # - ./docker/postgres/env # - ./docker/mariadb/env + #postgres: # image: postgres:9 # ports: @@ -38,6 +40,7 @@ services: # - ./docker/data/pgsql:/var/lib/postgresql/data # env_file: # - ./docker/postgres/env + #mariadb: # image: mariadb:10 # ports: @@ -46,3 +49,13 @@ services: # - ./docker/data/mariadb:/var/lib/mysql # env_file: # - ./docker/mariadb/env + + rabbitmq: + image: rabbitmq:3-management + ports: + - "15672:15672" + + redis: + image: redis + ports: + - "6379:6379" diff --git a/docs/de/conf.py b/docs/de/conf.py index 8f2d130d..cc9dcdf8 100644 --- a/docs/de/conf.py +++ b/docs/de/conf.py @@ -12,7 +12,7 @@ source_suffix = '.rst' master_doc = 'index' project = u'wallabag-fr' copyright = u'2013-2016, Nicolas Lœuillet - MIT Licence' -version = '2.0.0' +version = '2.1.0' release = version exclude_patterns = ['_build'] pygments_style = 'sphinx' diff --git a/docs/de/developer/rabbitmq.rst b/docs/de/developer/rabbitmq.rst new file mode 100644 index 00000000..bea02ff4 --- /dev/null +++ b/docs/de/developer/rabbitmq.rst @@ -0,0 +1,77 @@ +Installiere RabbitMQ für asynchrone Aufgaben +============================================ + +Um asynchrone Aufgaben zu starten (nützlich z.B. für große Imports), können wir RabbitMQ nutzen. + +Voraussetzungen +--------------- + +Du musst RabbitMQ auf deinem Server installiert haben. + +Installation +~~~~~~~~~~~~ + +.. code:: bash + + wget https://www.rabbitmq.com/rabbitmq-signing-key-public.asc + apt-key add rabbitmq-signing-key-public.asc + apt-get update + apt-get install rabbitmq-server + +Konfiguration und Starten +~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code:: bash + + rabbitmq-plugins enable rabbitmq_management # (useful to have a web interface, available at http://localhost:15672/ (guest/guest) + rabbitmq-server -detached + +RabbitMQ stoppen +~~~~~~~~~~~~~~~ + +.. code:: bash + + rabbitmqctl stop + + +Konfigure RabbitMQ in wallabag +------------------------------ + +Bearbeite die Datei ``parameters.yml``, um die RabbitMQ Konfiguration einzurichten. Die Standardkonfiguration sollte ok sein: + +.. code:: yaml + + rabbitmq_host: localhost + rabbitmq_port: 5672 + rabbitmq_user: guest + rabbitmq_password: guest + + +Starte den RabbitMQ Consumer +---------------------------- + +Abhängig von welchem Service du importieren möchtest, solltest du einen Cron Job aktivieren (oder mehrere, wenn du viele unterstützen willst): + +.. code:: bash + + # for Pocket import + bin/console rabbitmq:consumer import_pocket -w + + # for Readability import + bin/console rabbitmq:consumer import_readability -w + + # for Instapaper import + bin/console rabbitmq:consumer import_instapaper -w + + # for wallabag v1 import + bin/console rabbitmq:consumer import_wallabag_v1 -w + + # for wallabag v2 import + bin/console rabbitmq:consumer import_wallabag_v2 -w + + # for Firefox import + bin/console rabbitmq:consumer import_firefox -w + + # for Chrome import + bin/console rabbitmq:consumer import_chrome -w + diff --git a/docs/de/developer/redis.rst b/docs/de/developer/redis.rst new file mode 100644 index 00000000..d613ce6c --- /dev/null +++ b/docs/de/developer/redis.rst @@ -0,0 +1,71 @@ +Installiere Redis für asynchrone Aufgaben +========================================= + +Um asynchrone Aufgaben zu starten (nützlich z.B. für große Imports), können wir Redis nutzen. + +Voraussetzungen +--------------- + +Du musst Redis auf deinem Server installiert haben. + +Installation +~~~~~~~~~~~~ + +.. code:: bash + + apt-get install redis-server + +Starten +~~~~~~ + +Der Redis Service läuft eventuell schon direkt nach der Installation. Falls nicht kannst du ihn wie folgt starten: + +.. code:: bash + + redis-server + + +Konfigure Redis in wallabag +--------------------------- + +Bearbeite die Datei ``parameters.yml``, um die RabbitMQ Konfiguration einzurichten. Die Standardkonfiguration sollte ok sein: + +.. code:: yaml + + redis_host: localhost + redis_port: 6379 + + +Starte den Redis Consumer +------------------------- + +Abhängig von welchem Service du importieren möchtest, solltest du einen Cron Job aktivieren (oder mehrere, wenn du viele unterstützen willst): + +.. code:: bash + + # for Pocket import + bin/console wallabag:import:redis-worker pocket -vv >> /path/to/wallabag/var/logs/redis-pocket.log + + # for Readability import + bin/console wallabag:import:redis-worker readability -vv >> /path/to/wallabag/var/logs/redis-readability.log + + # for Instapaper import + bin/console wallabag:import:redis-worker instapaper -vv >> /path/to/wallabag/var/logs/redis-instapaper.log + + # for wallabag v1 import + bin/console wallabag:import:redis-worker wallabag_v1 -vv >> /path/to/wallabag/var/logs/redis-wallabag_v1.log + + # for wallabag v2 import + bin/console wallabag:import:redis-worker wallabag_v2 -vv >> /path/to/wallabag/var/logs/redis-wallabag_v2.log + + # for Firefox import + bin/console wallabag:import:redis-worker firefox -vv >> /path/to/wallabag/var/logs/redis-firefox.log + + # for Chrome import + bin/console wallabag:import:redis-worker instapaper -vv >> /path/to/wallabag/var/logs/redis-chrome.log + +Wenn du den Import nur für ein paar Nachrichten und nicht für alle starten willst, kannst du die Nummer (im folgenden Beispiel 12) angeben. Der Redis Worker wird dann nach der 12. Nachricht stoppen: + +.. code:: bash + + bin/console wallabag:import:redis-worker pocket -vv --maxIterations=12 diff --git a/docs/de/index.rst b/docs/de/index.rst index 5311150f..b3cd33b0 100644 --- a/docs/de/index.rst +++ b/docs/de/index.rst @@ -17,6 +17,11 @@ Die Hauptdokumentation für diese Applikation ist in einigen Abschnitten organis * :ref:`user-docs` * :ref:`dev-docs` +Die Dokumentation ist in anderen Sprachen verfügbar : + +* `Documentation in english `_ +* `Documentation en français `_ + .. _user-docs: .. toctree:: @@ -25,7 +30,8 @@ Die Hauptdokumentation für diese Applikation ist in einigen Abschnitten organis user/faq user/installation - user/upgrade + user/upgrade-2.0.x-2.1.y + user/upgrade-2.0.x-2.0.y user/migration user/import user/create_account @@ -50,3 +56,5 @@ Die Hauptdokumentation für diese Applikation ist in einigen Abschnitten organis developer/documentation developer/translate developer/maintenance + developer/redis + developer/rabbitmq diff --git a/docs/de/user/installation.rst b/docs/de/user/installation.rst index fced2ed4..05602bf3 100644 --- a/docs/de/user/installation.rst +++ b/docs/de/user/installation.rst @@ -46,7 +46,7 @@ Composer installieren: curl -s http://getcomposer.org/installer | php -Du kannst eine spezifische Anleitung `hier `__ finden: +Du kannst eine spezifische Anleitung `hier `__ finden. Um wallabag selbst zu installieren, musst du die folgenden Kommandos ausführen: @@ -54,9 +54,8 @@ Um wallabag selbst zu installieren, musst du die folgenden Kommandos ausführen: git clone https://github.com/wallabag/wallabag.git cd wallabag - git checkout 2.0.8 - SYMFONY_ENV=prod composer install --no-dev -o --prefer-dist - php bin/console wallabag:install --env=prod + git checkout 2.1.0 + ./install.sh Um PHPs eingebauten Server zu starten und zu testen, ob alles korrekt installiert wurde, kannst du folgendes Kommando ausführen: diff --git a/docs/de/user/upgrade.rst b/docs/de/user/upgrade-2.0.x-2.0.y.rst similarity index 94% rename from docs/de/user/upgrade.rst rename to docs/de/user/upgrade-2.0.x-2.0.y.rst index c04b68f3..adf288bd 100644 --- a/docs/de/user/upgrade.rst +++ b/docs/de/user/upgrade-2.0.x-2.0.y.rst @@ -1,5 +1,5 @@ -Wallabag updaten -================ +Wallabag updaten 2.0.x -> 2.1.x +=============================== Update auf einem dedizierten Webserver -------------------------------------- diff --git a/docs/de/user/upgrade-2.0.x-2.1.y.rst b/docs/de/user/upgrade-2.0.x-2.1.y.rst new file mode 100644 index 00000000..85229d30 --- /dev/null +++ b/docs/de/user/upgrade-2.0.x-2.1.y.rst @@ -0,0 +1,64 @@ +Wallabag updaten +================ + +.. warning:: +Wenn du den Import von Pocket durch das Hinzufügen des Consumer Key in den internen Einstellungen konfiguriert hast, fertige bitte ein Backup deines Keys an, bevor du auf das neue Release migrierst: Du wirst den Key nach dem Update in der Konfiguration erneut eintragen müssen. + +Update auf einem dedizierten Webserver +-------------------------------------- + +Das neueste Release ist auf https://www.wallabag.org/pages/download-wallabag.html veröffentlicht. Um deine wallabag-Installation auf die neueste Version zu aktualisieren, führe die folgenden Kommandos in deinem wallabag-Ordner aus (ersetze ``2.1.0`` mit der neuesten Releasenummer): + +:: + + git fetch origin + git fetch --tags + git checkout 2.1.0 + ASSETS=build ./install.sh + php bin/console doctrine:migrations:migrate --env=prod + php bin/console cache:clear --env=prod + +Update auf einem Shared Webhosting +---------------------------------- + +Sichere deine ``app/config/parameters.yml`` Datei. + +Lade das neueste Release von wallabag herunter: + +.. code-block:: bash + + wget http://wllbg.org/latest-v2-package && tar xvf latest-v2-package + +(md5 hash: ``4f84c725d1d6e3345eae0a406115e5ff``) + +Entpacke das Archiv in deinen wallabag-Ordner und ersetze ``app/config/parameters.yml`` mit deiner Datei. + +Bitte beachte, dass wir in dieser Version neue Parameter hinzugefügt haben. Du musst die Datei ``app/config/parameters.yml`` bearbeiten und die folgenden Zeilen hinzufügen (ersetze die Werte mit deiner Konfiguration): + +.. code-block:: bash + + # RabbitMQ processing + rabbitmq_host: localhost + rabbitmq_port: 5672 + rabbitmq_user: guest + rabbitmq_password: guest + + # Redis processing + redis_host: localhost + redis_port: 6379 + +Wenn du SQLite nutzt, musst auch das ``data/`` Verzeichnis in die neue Installation kopieren. + +Leere den ``var/cache`` Ordner. + +Du musst einige SQL-Abfragen ausführen, um die Datenbank zu aktualisieren. Wir nehmen in diesem Fall an, dass das Tabellenpräfix ``wallabag_`` ist und eine MySQL-Datenbank genutzt wird: + +.. code-block:: sql + + ALTER TABLE `wallabag_entry` ADD `uuid` LONGTEXT DEFAULT NULL; + INSERT INTO `wallabag_craue_config_setting` (`name`, `value`, `section`) VALUES ('share_public', '1', 'entry'); + ALTER TABLE `wallabag_oauth2_clients` ADD name longtext COLLATE 'utf8_unicode_ci' DEFAULT NULL; + INSERT INTO `wallabag_craue_config_setting` (`name`, `value`, `section`) VALUES ('import_with_redis', '0', 'import'); + INSERT INTO `wallabag_craue_config_setting` (`name`, `value`, `section`) VALUES ('import_with_rabbitmq', '0', 'import'); + ALTER TABLE `wallabag_config` ADD `pocket_consumer_key` VARCHAR(255) DEFAULT NULL; + DELETE FROM `wallabag_craue_config_setting` WHERE `name` = 'pocket_consumer_key'; diff --git a/docs/en/conf.py b/docs/en/conf.py index 86e33704..717b35f1 100644 --- a/docs/en/conf.py +++ b/docs/en/conf.py @@ -12,7 +12,7 @@ source_suffix = '.rst' master_doc = 'index' project = u'wallabag' copyright = u'2013-2016, Nicolas Lœuillet - MIT Licence' -version = '2.0.0' +version = '2.1.0' release = version exclude_patterns = ['_build'] pygments_style = 'sphinx' diff --git a/docs/en/developer/rabbitmq.rst b/docs/en/developer/rabbitmq.rst new file mode 100644 index 00000000..63b85106 --- /dev/null +++ b/docs/en/developer/rabbitmq.rst @@ -0,0 +1,76 @@ +Install RabbitMQ for asynchronous tasks +======================================= + +In order to launch asynchronous tasks (useful for huge imports for example), we can use RabbitMQ. + +Requirements +------------ + +You need to have RabbitMQ installed on your server. + +Installation +~~~~~~~~~~~~ + +.. code:: bash + + wget https://www.rabbitmq.com/rabbitmq-signing-key-public.asc + apt-key add rabbitmq-signing-key-public.asc + apt-get update + apt-get install rabbitmq-server + +Configuration and launch +~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code:: bash + + rabbitmq-plugins enable rabbitmq_management # (useful to have a web interface, available at http://localhost:15672/ (guest/guest) + rabbitmq-server -detached + +Stop RabbitMQ +~~~~~~~~~~~~~ + +.. code:: bash + + rabbitmqctl stop + + +Configure RabbitMQ in wallabag +------------------------------ + +Edit your ``parameters.yml`` file to edit RabbitMQ configuration. The default one should be ok: + +.. code:: yaml + + rabbitmq_host: localhost + rabbitmq_port: 5672 + rabbitmq_user: guest + rabbitmq_password: guest + + +Launch RabbitMQ consumer +------------------------ + +Depending on which service you want to import from you need to enable one (or many if you want to support many) cron job: + +.. code:: bash + + # for Pocket import + bin/console rabbitmq:consumer import_pocket -w + + # for Readability import + bin/console rabbitmq:consumer import_readability -w + + # for Instapaper import + bin/console rabbitmq:consumer import_instapaper -w + + # for wallabag v1 import + bin/console rabbitmq:consumer import_wallabag_v1 -w + + # for wallabag v2 import + bin/console rabbitmq:consumer import_wallabag_v2 -w + + # for Firefox import + bin/console rabbitmq:consumer import_firefox -w + + # for Chrome import + bin/console rabbitmq:consumer import_chrome -w diff --git a/docs/en/developer/redis.rst b/docs/en/developer/redis.rst new file mode 100644 index 00000000..820a52e9 --- /dev/null +++ b/docs/en/developer/redis.rst @@ -0,0 +1,71 @@ +Install Redis for asynchronous tasks +==================================== + +In order to launch asynchronous tasks (useful for huge imports for example), we can use Redis. + +Requirements +------------ + +You need to have Redis installed on your server. + +Installation +~~~~~~~~~~~~ + +.. code:: bash + + apt-get install redis-server + +Launch +~~~~~~ + +The server might be already running after installing, if not you can launch it using: + +.. code:: bash + + redis-server + + +Configure Redis in wallabag +--------------------------- + +Edit your ``parameters.yml`` file to edit Redis configuration. The default one should be ok: + +.. code:: yaml + + redis_host: localhost + redis_port: 6379 + + +Launch Redis consumer +--------------------- + +Depending on which service you want to import from you need to enable one (or many if you want to support many) cron job: + +.. code:: bash + + # for Pocket import + bin/console wallabag:import:redis-worker pocket -vv >> /path/to/wallabag/var/logs/redis-pocket.log + + # for Readability import + bin/console wallabag:import:redis-worker readability -vv >> /path/to/wallabag/var/logs/redis-readability.log + + # for Instapaper import + bin/console wallabag:import:redis-worker instapaper -vv >> /path/to/wallabag/var/logs/redis-instapaper.log + + # for wallabag v1 import + bin/console wallabag:import:redis-worker wallabag_v1 -vv >> /path/to/wallabag/var/logs/redis-wallabag_v1.log + + # for wallabag v2 import + bin/console wallabag:import:redis-worker wallabag_v2 -vv >> /path/to/wallabag/var/logs/redis-wallabag_v2.log + + # for Firefox import + bin/console wallabag:import:redis-worker firefox -vv >> /path/to/wallabag/var/logs/redis-firefox.log + + # for Chrome import + bin/console wallabag:import:redis-worker instapaper -vv >> /path/to/wallabag/var/logs/redis-chrome.log + +If you want to launch the import only for some messages and not all, you can specify this number (here 12) and the worker will stop right after the 12th message : + +.. code:: bash + + bin/console wallabag:import:redis-worker pocket -vv --maxIterations=12 diff --git a/docs/en/index.rst b/docs/en/index.rst index 03025ef9..beb3816e 100644 --- a/docs/en/index.rst +++ b/docs/en/index.rst @@ -17,6 +17,11 @@ The main documentation for this application is organized into a couple sections: * :ref:`user-docs` * :ref:`dev-docs` +The documentation is available in other languages: + +* `Documentation en français `_ +* `Deutsch Dokumentation `_ + .. _user-docs: .. toctree:: @@ -25,7 +30,8 @@ The main documentation for this application is organized into a couple sections: user/faq user/installation - user/upgrade + user/upgrade-2.0.x-2.1.y + user/upgrade-2.0.x-2.0.y user/migration user/import user/create_account @@ -35,6 +41,7 @@ The main documentation for this application is organized into a couple sections: user/errors_during_fetching user/annotations user/download_articles + user/share user/filters user/tags user/android @@ -50,3 +57,5 @@ The main documentation for this application is organized into a couple sections: developer/documentation developer/translate developer/maintenance + developer/redis + developer/rabbitmq diff --git a/docs/en/user/import.rst b/docs/en/user/import.rst index 63210484..758e3816 100644 --- a/docs/en/user/import.rst +++ b/docs/en/user/import.rst @@ -23,22 +23,43 @@ Now, all is fine to migrate from Pocket. Import your data into wallabag 2.x ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Click on ``Import`` link in the menu, on ``Import contents`` in Pocket section +Click on ``Import`` link in the menu, on ``Import contents`` in Pocket section and then on ``Connect to Pocket and import data``. You need to authorize wallabag to interact with your Pocket account. -Your data will be imported. Data import can be a demanding process for your server -(we need to work on this import to improve it). +Your data will be imported. Data import can be a demanding process for your server. + +From Readability +---------------- + +Export your Readability data +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +On the tools (`https://www.readability.com/tools/`_) page, click on "Export your data" in the "Data Export" section. You will received an email to download a json (which does not end with .json in fact). + +Import your data into wallabag 2.x +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Click on ``Import`` link in the menu, on ``Import contents`` in Readability section +and then select your json file and upload it. + +Your data will be imported. Data import can be a demanding process for your server. From Instapaper --------------- -*Feature not yet implemented in wallabag v2.* +Export your Instapaper data +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -From Readability ----------------- +On the settings (`https://www.instapaper.com/user`_) page, click on "Download .CSV file" in the "Export" section. A CSV file will be downloaded (like ``instapaper-export.csv``). -*Feature not yet implemented in wallabag v2.* +Import your data into wallabag 2.x +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Click on ``Import`` link in the menu, on ``Import contents`` in Instapaper section +and then select your CSV file and upload it. + +Your data will be imported. Data import can be a demanding process for your server. From HTML or JSON file ---------------------- diff --git a/docs/en/user/installation.rst b/docs/en/user/installation.rst index 763d7c66..8e9f71d4 100644 --- a/docs/en/user/installation.rst +++ b/docs/en/user/installation.rst @@ -37,7 +37,7 @@ Installation On a dedicated web server (recommended way) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -wallabag uses a large number of libraries in order to function. These libraries must be installed with a tool called Composer. You need to install it if you have not already done so and be sure to use the 1.2 version (if you already have Composer, run a ``composer selfupdate``). +wallabag uses a large number of PHP libraries in order to function. These libraries must be installed with a tool called Composer. You need to install it if you have not already done so and be sure to use the 1.2 version (if you already have Composer, run a ``composer selfupdate``). Install Composer: @@ -45,7 +45,7 @@ Install Composer: curl -s http://getcomposer.org/installer | php -You can find specific instructions `here `__: +You can find specific instructions `here `__. To install wallabag itself, you must run the following commands: @@ -53,9 +53,8 @@ To install wallabag itself, you must run the following commands: git clone https://github.com/wallabag/wallabag.git cd wallabag - git checkout 2.0.8 - SYMFONY_ENV=prod composer install --no-dev -o --prefer-dist - php bin/console wallabag:install --env=prod + git checkout 2.1.0 + ./install.sh To start PHP's build-in server and test if everything did install correctly, you can do: diff --git a/docs/en/user/migration.rst b/docs/en/user/migration.rst index e141ae40..42062796 100644 --- a/docs/en/user/migration.rst +++ b/docs/en/user/migration.rst @@ -24,20 +24,38 @@ After creating an user account on your new wallabag v2 instance, you must head o :alt: Import from wallabag v1 :align: center +From wallabag 2.x +----------------- + +From the previous wallabag instance on which you were before, go to `All articles`, then export these articles as json. + +.. image:: ../../img/user/export_v2.png + :alt: Export depuis wallabag v2 + :align: center + +From your new wallabag instance, create your user account and click on the link in the menu to proceed to import. Choose import from wallabag v2 and select your json file to upload it. + +.. note:: + If you encounter issues during the export or the import, don't hesitate to `ask for support `__. + Import via command-line interface (CLI) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +--------------------------------------- If you have a CLI access on your web server, you can execute this command to import your wallabag v1 export: :: - bin/console wallabag:import-v1 1 ~/Downloads/wallabag-export-1-2016-04-05.json --env=prod + bin/console wallabag:import 1 ~/Downloads/wallabag-export-1-2016-04-05.json --env=prod Please replace values: * ``1`` is the user identifier in database (The ID of the first user created on wallabag is 1) * ``~/Downloads/wallabag-export-1-2016-04-05.json`` is the path of your wallabag v1 export +If you want to mark all these entries as read, you can add the ``--markAsRead`` option. + +To import a wallabag v2 file, you need to add the option ``--importer=v2``. + You'll have this in return: :: @@ -46,17 +64,3 @@ You'll have this in return: 403 imported 0 already saved End : 05-04-2016 11:36:09 --- - -From wallabag 2.x ------------------ - -From the previous wallabag instance on which you were before, go to `All articles`, then export these articles as json. - -.. image:: ../../img/user/export_v2.png - :alt: Export depuis wallabag v2 - :align: center - -From your new wallabag instance, create your user account and click on the link in the menu to proceed to import. Choose import from wallabag v2 and select your json file to upload it. - -.. note:: - If you encounter issues during the export or the import, don't hesitate to `ask for support `__. diff --git a/docs/en/user/share.rst b/docs/en/user/share.rst new file mode 100644 index 00000000..e99e51ab --- /dev/null +++ b/docs/en/user/share.rst @@ -0,0 +1,17 @@ +Share articles +============== + +When you're reading an article, you can share it. Just click on the share button: + +.. image:: ../../img/user/share.png + :alt: share article + :align: center + +Now, you can share the article: + +- with a public URL (you'll have a light view of the article) +- with a tweet +- into your Shaarli +- with a post in Diaspora* +- to Carrot +- with an email diff --git a/docs/en/user/upgrade.rst b/docs/en/user/upgrade-2.0.x-2.0.y.rst similarity index 88% rename from docs/en/user/upgrade.rst rename to docs/en/user/upgrade-2.0.x-2.0.y.rst index 90ed6c70..6a0818b3 100644 --- a/docs/en/user/upgrade.rst +++ b/docs/en/user/upgrade-2.0.x-2.0.y.rst @@ -1,5 +1,5 @@ -Upgrade wallabag -================ +Upgrade from 2.0.x to 2.0.y +=========================== Upgrade on a dedicated web server --------------------------------- @@ -25,7 +25,7 @@ Download the last release of wallabag: wget http://wllbg.org/latest-v2-package && tar xvf latest-v2-package -(md5 hash of the package: ``4f84c725d1d6e3345eae0a406115e5ff``) +(md5 hash of the 2.0.8 package: ``4f84c725d1d6e3345eae0a406115e5ff``) Extract the archive in your wallabag folder and replace ``app/config/parameters.yml`` with yours. diff --git a/docs/en/user/upgrade-2.0.x-2.1.y.rst b/docs/en/user/upgrade-2.0.x-2.1.y.rst new file mode 100644 index 00000000..5ae5eb43 --- /dev/null +++ b/docs/en/user/upgrade-2.0.x-2.1.y.rst @@ -0,0 +1,64 @@ +Upgrading from 2.0.x to 2.1.y +============================= + +.. warning:: +Before this migration, if you configured the Pocket import by adding your consumer key in Internal settings, please do a backup of it: you'll have to add it into the Config page after the upgrade. + +Upgrade on a dedicated web server +--------------------------------- + +The last release is published on https://www.wallabag.org/pages/download-wallabag.html. In order to upgrade your wallabag installation and get the last version, run the following commands in you wallabag folder (replace ``2.1.0`` by the last release number): + +:: + + git fetch origin + git fetch --tags + git checkout 2.1.0 + ASSETS=build ./install.sh + php bin/console doctrine:migrations:migrate --env=prod + php bin/console cache:clear --env=prod + +Upgrade on a shared hosting +--------------------------- + +Backup your ``app/config/parameters.yml`` file. + +Download the last release of wallabag: + +.. code-block:: bash + + wget http://wllbg.org/latest-v2-package && tar xvf latest-v2-package + +(md5 hash of the package: ``4f84c725d1d6e3345eae0a406115e5ff``) + +Extract the archive in your wallabag folder and replace ``app/config/parameters.yml`` with yours. + +Please note that we added new parameters in this version. You have to edit ``app/config/parameters.yml`` by adding these lines (replace with your configuration) : + +.. code-block:: bash + + # RabbitMQ processing + rabbitmq_host: localhost + rabbitmq_port: 5672 + rabbitmq_user: guest + rabbitmq_password: guest + + # Redis processing + redis_host: localhost + redis_port: 6379 + +If you use SQLite, you must also copy your ``data/`` folder inside the new installation. + +Empty ``var/cache`` folder. + +You must run some SQL queries to upgrade your database. We assume that the table prefix is ``wallabag_`` and the database server is a MySQL one: + +.. code-block:: sql + + ALTER TABLE `wallabag_entry` ADD `uuid` LONGTEXT DEFAULT NULL; + INSERT INTO `wallabag_craue_config_setting` (`name`, `value`, `section`) VALUES ('share_public', '1', 'entry'); + ALTER TABLE `wallabag_oauth2_clients` ADD name longtext COLLATE 'utf8_unicode_ci' DEFAULT NULL; + INSERT INTO `wallabag_craue_config_setting` (`name`, `value`, `section`) VALUES ('import_with_redis', '0', 'import'); + INSERT INTO `wallabag_craue_config_setting` (`name`, `value`, `section`) VALUES ('import_with_rabbitmq', '0', 'import'); + ALTER TABLE `wallabag_config` ADD `pocket_consumer_key` VARCHAR(255) DEFAULT NULL; + DELETE FROM `wallabag_craue_config_setting` WHERE `name` = 'pocket_consumer_key'; diff --git a/docs/fr/conf.py b/docs/fr/conf.py index f1fe3967..49a57e2d 100644 --- a/docs/fr/conf.py +++ b/docs/fr/conf.py @@ -12,7 +12,7 @@ source_suffix = '.rst' master_doc = 'index' project = u'wallabag-fr' copyright = u'2013-2016, Nicolas Lœuillet - MIT Licence' -version = '2.0.0' +version = '2.1.0' release = version exclude_patterns = ['_build'] pygments_style = 'sphinx' diff --git a/docs/fr/developer/rabbitmq.rst b/docs/fr/developer/rabbitmq.rst new file mode 100644 index 00000000..20182e6e --- /dev/null +++ b/docs/fr/developer/rabbitmq.rst @@ -0,0 +1,76 @@ +Installer RabbitMQ pour des tâches asynchrones +============================================== + +Pour lancer des tâches asynchrones (utile pour des imports importants par exemple), nous pouvons utiliser RabbitMQ. + +Pré-requis +---------- + +Vous devez installer RabbitMQ sur votre serveur. + +Installation +~~~~~~~~~~~~ + +.. code:: bash + + wget https://www.rabbitmq.com/rabbitmq-signing-key-public.asc + apt-key add rabbitmq-signing-key-public.asc + apt-get update + apt-get install rabbitmq-server + +Configuration et démarrage +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code:: bash + + rabbitmq-plugins enable rabbitmq_management # (useful to have a web interface, available at http://localhost:15672/ (guest/guest) + rabbitmq-server -detached + +Arrêter RabbitMQ +~~~~~~~~~~~~~~~~ + +.. code:: bash + + rabbitmqctl stop + + +Configurer RabbitMQ dans wallabag +--------------------------------- + +Modifiez votre fichier ``parameters.yml`` pour éditer la configuration RabbitMQ. Celle par défaut devrait convenir : + +.. code:: yaml + + rabbitmq_host: localhost + rabbitmq_port: 5672 + rabbitmq_user: guest + rabbitmq_password: guest + + +Démarrer les clients RabbitMQ +----------------------------- + +En fonction du service dont vous souhaitez importer vos données, vous devez activer un (ou plusieurs si vous souhaitez en supporter plusieurs) cron job : + +.. code:: bash + + # for Pocket import + bin/console rabbitmq:consumer import_pocket -w + + # for Readability import + bin/console rabbitmq:consumer import_readability -w + + # for Instapaper import + bin/console rabbitmq:consumer import_instapaper -w + + # for wallabag v1 import + bin/console rabbitmq:consumer import_wallabag_v1 -w + + # for wallabag v2 import + bin/console rabbitmq:consumer import_wallabag_v2 -w + + # for Firefox import + bin/console rabbitmq:consumer import_firefox -w + + # for Chrome import + bin/console rabbitmq:consumer import_chrome -w diff --git a/docs/fr/developer/redis.rst b/docs/fr/developer/redis.rst new file mode 100644 index 00000000..097e375d --- /dev/null +++ b/docs/fr/developer/redis.rst @@ -0,0 +1,71 @@ +Installer Redis pour des tâches asynchrones +=========================================== + +Pour lancer des tâches asynchrones (utile pour des imports importants par exemple), nous pouvons utiliser Redis. + +Pré-requis +---------- + +Vous devez installer Redis sur votre serveur. + +Installation +~~~~~~~~~~~~ + +.. code:: bash + + apt-get install redis-server + +Démarrage +~~~~~~~~~ + +Le serveur devrait déjà être démarré après l'installation. Si ce n'est pas le cas, vous pouvez le démarrer ainsi : + +.. code:: bash + + redis-server + + +Configurer Redis dans wallabag +------------------------------- + +Modifiez votre fichier ``parameters.yml`` pour éditer la configuration Redis. Celle par défaut devrait convenir : + +.. code:: yaml + + redis_host: localhost + redis_port: 6379 + + +Démarrer les clients Redis +-------------------------- + +En fonction du service dont vous souhaitez importer vos données, vous devez activer un (ou plusieurs si vous souhaitez en supporter plusieurs) cron job : + +.. code:: bash + + # for Pocket import + bin/console wallabag:import:redis-worker pocket -vv >> /path/to/wallabag/var/logs/redis-pocket.log + + # for Readability import + bin/console wallabag:import:redis-worker readability -vv >> /path/to/wallabag/var/logs/redis-readability.log + + # for Instapaper import + bin/console wallabag:import:redis-worker instapaper -vv >> /path/to/wallabag/var/logs/redis-instapaper.log + + # for wallabag v1 import + bin/console wallabag:import:redis-worker wallabag_v1 -vv >> /path/to/wallabag/var/logs/redis-wallabag_v1.log + + # for wallabag v2 import + bin/console wallabag:import:redis-worker wallabag_v2 -vv >> /path/to/wallabag/var/logs/redis-wallabag_v2.log + + # for Firefox import + bin/console wallabag:import:redis-worker firefox -vv >> /path/to/wallabag/var/logs/redis-firefox.log + + # for Chrome import + bin/console wallabag:import:redis-worker instapaper -vv >> /path/to/wallabag/var/logs/redis-chrome.log + +Si vous souhaitez démarrer l'import pour quelques messages uniquement, vous pouvez spécifier cette valeur en paramètre (ici 12) et le client va s'arrêter après le 12ème message : + +.. code:: bash + + bin/console wallabag:import:redis-worker pocket -vv --maxIterations=12 diff --git a/docs/fr/index.rst b/docs/fr/index.rst index 1e72dae7..359b103c 100644 --- a/docs/fr/index.rst +++ b/docs/fr/index.rst @@ -18,6 +18,11 @@ La documentation principale de cette application est découpée en plusieurs sec * :ref:`user-docs` * :ref:`dev-docs` +La documentation est disponible dans d'autres langues : + +* `Documentation in english `_ +* `Deutsch Dokumentation `_ + .. _user-docs: .. toctree:: @@ -26,7 +31,8 @@ La documentation principale de cette application est découpée en plusieurs sec user/faq user/installation - user/upgrade + user/upgrade-2.0.x-2.1.y + user/upgrade-2.0.x-2.0.y user/migration user/import user/create_account @@ -36,6 +42,7 @@ La documentation principale de cette application est découpée en plusieurs sec user/errors_during_fetching user/annotations user/download_articles + user/share user/filters user/tags @@ -50,3 +57,5 @@ La documentation principale de cette application est découpée en plusieurs sec developer/documentation developer/translate developer/maintenance + developer/redis + developer/rabbitmq diff --git a/docs/fr/user/import.rst b/docs/fr/user/import.rst index e6c2fa02..6f114dd6 100644 --- a/docs/fr/user/import.rst +++ b/docs/fr/user/import.rst @@ -28,17 +28,40 @@ la section Pocket puis sur ``Se connecter à Pocket et importer les données``. Vous devez autoriser wallabag à se connecter à votre compte Pocket. Vos données vont être importées. L'import de données est une action qui peut être couteuse -pour votre serveur (nous devons encore travailler pour améliorer cet import). +pour votre serveur. + +Depuis Readability +------------------ + +Exportez vos données de Readability +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Sur la page des outils (`https://www.readability.com/tools/`_), cliquez sur "Export your data" dans la section "Data Export". Vous allez recevoir un email avec un lien pour télécharger le json. + +Importez vos données dans wallabag 2.x +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Cliquez sur le lien ``Importer`` dans le menu, sur ``Importer les contenus`` dans +la section Readability et ensuite sélectionnez votre fichier json pour l'uploader. + +Vos données vont être importées. L'import de données est une action qui peut être couteuse pour votre serveur. Depuis Instapaper ----------------- -*Fonctionnalité pas encore implémentée dans wallabag v2.* +Exportez vos données de Instapaper +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Depuis Readability ------------------- +Sur la page des paramètres (`https://www.instapaper.com/user`_), cliquez sur "Download .CSV file" dans la section "Export". Un fichier CSV se téléchargera (``instapaper-export.csv``). + +Importez vos données dans wallabag 2.x +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Cliquez sur le lien ``Importer`` dans le menu, sur ``Importer les contenus`` dans +la section Instapaper et ensuite sélectionnez votre fichier CSV pour l'uploader. + +Vos données vont être importées. L'import de données est une action qui peut être couteuse pour votre serveur. -*Fonctionnalité pas encore implémentée dans wallabag v2.* Depuis un fichier HTML ou JSON ------------------------------ diff --git a/docs/fr/user/installation.rst b/docs/fr/user/installation.rst index 480970c5..4fccd0d4 100644 --- a/docs/fr/user/installation.rst +++ b/docs/fr/user/installation.rst @@ -35,7 +35,7 @@ Installation Sur un serveur dédié (méthode conseillée) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -wallabag utilise un grand nombre de bibliothèques pour fonctionner. Ces bibliothèques doivent être installées à l'aide d'un outil nommé Composer. Vous devez l'installer si ce n'est déjà fait et vous assurer que vous utilisez bien la version 1.2 (si vous avez déjà Composer, faite un ``composer selfupdate``). +wallabag utilise un grand nombre de bibliothèques PHP pour fonctionner. Ces bibliothèques doivent être installées à l'aide d'un outil nommé Composer. Vous devez l'installer si ce n'est déjà fait et vous assurer que vous utilisez bien la version 1.2 (si vous avez déjà Composer, faite un ``composer selfupdate``). Installation de Composer : @@ -43,17 +43,16 @@ Installation de Composer : curl -s http://getcomposer.org/installer | php -Vous pouvez trouver des instructions spécifiques `ici (en anglais) `__ : +Vous pouvez trouver des instructions spécifiques `ici (en anglais) `__. -Pour installer wallabag, vous devez exécuter ces deux commandes : +Pour installer wallabag, vous devez exécuter ces commandes : :: git clone https://github.com/wallabag/wallabag.git cd wallabag - git checkout 2.0.8 - SYMFONY_ENV=prod composer install --no-dev -o --prefer-dist - php bin/console wallabag:install --env=prod + git checkout 2.1.0 + ./install.sh Pour démarrer le serveur interne à php et vérifier que tout s'est installé correctement, vous pouvez exécuter : diff --git a/docs/fr/user/migration.rst b/docs/fr/user/migration.rst index 66024572..91f8bab2 100644 --- a/docs/fr/user/migration.rst +++ b/docs/fr/user/migration.rst @@ -24,20 +24,38 @@ Une fois que vous avez créé un compte utilisateur sur votre nouvelle instance :alt: Import depuis wallabag v1 :align: center -Import via via la ligne de commande (CLI) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Depuis wallabag 2.x +------------------- + +Depuis l'instance sur laquelle vous étiez, rendez-vous dans la section `Tous les articles`, puis exportez ces articles au format json. + +.. image:: ../../img/user/export_v2.png + :alt: Export depuis wallabag v2 + :align: center + +Depuis votre nouvelle instance de wallabag, créez votre compte utilisateur puis cliquez sur le lien dans le menu pour accéder à l'import. Choisissez l'import depuis wallabag v2 puis sélectionnez votre fichier json pour l'uploader. + +.. note:: + S'il vous arrive des problèmes durant l'export ou l'import, n'hésitez pas à `demander de l'aide `__. + +Import via la ligne de commande (CLI) +------------------------------------- Si vous avez accès à la ligne de commandes de votre serveur web, vous pouvez exécuter cette commande pour import votre fichier wallabag v1 : :: - bin/console wallabag:import-v1 1 ~/Downloads/wallabag-export-1-2016-04-05.json --env=prod + bin/console wallabag:import 1 ~/Downloads/wallabag-export-1-2016-04-05.json --env=prod Remplacez les valeurs : * ``1`` est l'identifiant de votre utilisateur en base (l'ID de votre premier utilisateur créé sur wallabag est 1) * ``~/Downloads/wallabag-export-1-2016-04-05.json`` est le chemin de votre export wallabag v1 +Si vous voulez marquer tous ces articles comme lus, vous pouvez ajouter l'option ``--markAsRead``. + +Pour importer un fichier wallabag v2, vous devez ajouter l'option ``--importer=v2``. + Vous obtiendrez : :: @@ -46,17 +64,3 @@ Vous obtiendrez : 403 imported 0 already saved End : 05-04-2016 11:36:09 --- - -Depuis wallabag 2.x -------------------- - -Depuis l'instance sur laquelle vous étiez, rendez-vous dans la section `Tous les articles`, puis exportez ces articles au format json. - -.. image:: ../../img/user/export_v2.png - :alt: Export depuis wallabag v2 - :align: center - -Depuis votre nouvelle instance de wallabag, créez votre compte utilisateur puis cliquez sur le lien dans le menu pour accéder à l'import. Choisissez l'import depuis wallabag v2 puis sélectionnez votre fichier json pour l'uploader. - -.. note:: - S'il vous arrive des problèmes durant l'export ou l'import, n'hésitez pas à `demander de l'aide `__. diff --git a/docs/fr/user/share.rst b/docs/fr/user/share.rst new file mode 100644 index 00000000..b5faa5ba --- /dev/null +++ b/docs/fr/user/share.rst @@ -0,0 +1,17 @@ +Partager des articles +===================== + +Quand vous lisez un article, vous pouvez le partager. Cliquez sur le bouton de partage : + +.. image:: ../../img/user/share.png + :alt: partager un article + :align: center + +Vous pouvez maintenant le partager : + +- avec une URL publique (vous obtiendrez une vue allégée de l'article) +- avec un tweet +- dans votre Shaarli +- avec un message dans Diaspora* +- sur Carrot +- avec un email diff --git a/docs/fr/user/upgrade.rst b/docs/fr/user/upgrade-2.0.x-2.0.y.rst similarity index 88% rename from docs/fr/user/upgrade.rst rename to docs/fr/user/upgrade-2.0.x-2.0.y.rst index 1ead2c94..d8dfac6e 100644 --- a/docs/fr/user/upgrade.rst +++ b/docs/fr/user/upgrade-2.0.x-2.0.y.rst @@ -1,5 +1,5 @@ -Mettre à jour wallabag -====================== +Mettre à jour de la 2.0.x à la 2.0.y +==================================== Mise à jour sur un serveur dédié -------------------------------- @@ -25,7 +25,7 @@ Téléchargez la dernière version de wallabag : wget http://wllbg.org/latest-v2-package && tar xvf latest-v2-package -(hash md5 de l'archive : ``4f84c725d1d6e3345eae0a406115e5ff``) +(hash md5 de l'archive 2.0.8 : ``4f84c725d1d6e3345eae0a406115e5ff``) Décompressez l'archive dans votre répertoire d'installation et remplacez le fichier ``app/config/parameters.yml`` avec le votre. diff --git a/docs/fr/user/upgrade-2.0.x-2.1.y.rst b/docs/fr/user/upgrade-2.0.x-2.1.y.rst new file mode 100644 index 00000000..a4afe768 --- /dev/null +++ b/docs/fr/user/upgrade-2.0.x-2.1.y.rst @@ -0,0 +1,65 @@ +Mettre à jour de la 2.0.x à la 2.1.y +==================================== + +.. warning:: +Avant cette migration, si vous aviez configuré l'import depuis Pocket en ajoutant votre consumer key dans les paramètres internes, pensez à effectuer une sauvegarde de celle-ci : vous devrez l'ajouter dans la configuration de wallabag après la mise à jour. + +Mise à jour sur un serveur dédié +-------------------------------- + +La dernière version de wallabag est publiée à cette adresse : https://www.wallabag.org/pages/download-wallabag.html. Pour mettre à jour votre installation de wallabag, exécutez les commandes suivantes dans votre répertoire d'installation (remplacez ``2.1.0`` par le numéro de la dernière version) : + +:: + + git fetch origin + git fetch --tags + git checkout 2.1.0 + ASSETS=build ./install.sh + php bin/console doctrine:migrations:migrate --env=prod + php bin/console cache:clear --env=prod + +Mise à jour sur un hébergement mutualisé +---------------------------------------- + +Effectuez une sauvegarde du fichier ``app/config/parameters.yml``. + +Téléchargez la dernière version de wallabag : + +.. code-block:: bash + + wget http://wllbg.org/latest-v2-package && tar xvf latest-v2-package + +(hash md5 de l'archive : ``4f84c725d1d6e3345eae0a406115e5ff``) + +Décompressez l'archive dans votre répertoire d'installation et remplacez le fichier ``app/config/parameters.yml`` avec le votre. + +Nous avons ajouté de nouveaux paramètres dans cette nouvelle version. Vous devez donc éditer le fichier ``app/config/parameters.yml`` en ajoutant ces lignes (et en remplaçant par votre configuration) : + +.. code-block:: bash + + # RabbitMQ processing + rabbitmq_host: localhost + rabbitmq_port: 5672 + rabbitmq_user: guest + rabbitmq_password: guest + + # Redis processing + redis_host: localhost + redis_port: 6379 + +Si vous utilisez SQLite, vous devez également conserver le contenu du répertoire ``data/``. + +Videz le répertoire ``var/cache``. + +Vous allez devoir également exécuter des requêtes SQL pour mettre à jour votre base de données. Nous partons du principe que le préfixe de vos tables est ``wallabag_`` et que le serveur SQL est un serveur MySQL : + +.. code-block:: sql + + ALTER TABLE `wallabag_entry` ADD `uuid` LONGTEXT DEFAULT NULL; + INSERT INTO `wallabag_craue_config_setting` (`name`, `value`, `section`) VALUES ('share_public', '1', 'entry'); + ALTER TABLE `wallabag_oauth2_clients` ADD name longtext COLLATE 'utf8_unicode_ci' DEFAULT NULL; + INSERT INTO `wallabag_craue_config_setting` (`name`, `value`, `section`) VALUES ('import_with_redis', '0', 'import'); + INSERT INTO `wallabag_craue_config_setting` (`name`, `value`, `section`) VALUES ('import_with_rabbitmq', '0', 'import'); + ALTER TABLE `wallabag_config` ADD `pocket_consumer_key` VARCHAR(255) DEFAULT NULL; + DELETE FROM `wallabag_craue_config_setting` WHERE `name` = 'pocket_consumer_key'; + diff --git a/docs/img/user/share.png b/docs/img/user/share.png new file mode 100644 index 00000000..4cfe9edb Binary files /dev/null and b/docs/img/user/share.png differ diff --git a/install.sh b/install.sh new file mode 100755 index 00000000..a486e8a5 --- /dev/null +++ b/install.sh @@ -0,0 +1,18 @@ +#! /usr/bin/env bash + +if [[ $ASSETS == 'build' ]]; then + echo "Installing PHP dependencies through Composer..." + composer install --no-interaction --no-progress --prefer-dist -o + + chmod ugo+x vendor/mouf/nodejs-installer/bin/local/npm + echo "Downloading javascript librairies through npm..." + vendor/mouf/nodejs-installer/bin/local/npm install + + echo "Downloading fonts librairies through bower..." + node_modules/bower/bin/bower install + + echo "Concat, minify and installing assets..." + node_modules/grunt/bin/grunt +else + composer install --no-interaction --no-progress --prefer-dist -o +fi diff --git a/install_dev.sh b/install_dev.sh new file mode 100755 index 00000000..81f871da --- /dev/null +++ b/install_dev.sh @@ -0,0 +1,16 @@ +#! /usr/bin/env bash + +echo "Installing PHP dependencies (including dev) through Composer..." +composer install + +echo "Downloading javascript librairies through npm..." +npm install + +echo "Downloading fonts librairies through bower..." +bower install + +echo "Concat, minify and installing assets..." +grunt + +echo "Installing wallabag..." +php bin/console wallabag:install diff --git a/package.json b/package.json new file mode 100644 index 00000000..39a10e9c --- /dev/null +++ b/package.json @@ -0,0 +1,89 @@ +{ + "name": "wallabag", + "version": "2.1.0", + "description": "wallabag is a self hostable application for saving web pages", + "main": "index.js", + "private": true, + "directories": { + "doc": "docs" + }, + "dependencies": { + "annotator": "git://github.com/wallabag/annotator.git#0f076c7d371ed25eb0793346f46982d90f2c4c85", + "autoprefixer": "^6.3.6", + "bower": "^1.7.7", + "browserify": "^13.0.0", + "browserify-shim": "^3.8.12", + "cssnano": "^3.5.2", + "es6-promise": "^3.2.1", + "grunt": ">=0.4.0", + "grunt-browserify": "^5.0.0", + "grunt-cli": "^1.2.0", + "grunt-contrib-clean": "^1.0.0", + "grunt-contrib-concat": "^1.0.0", + "grunt-contrib-copy": "^1.0.0", + "grunt-contrib-symlink": "^1.0.0", + "grunt-contrib-uglify": "^1.0.0", + "grunt-postcss": "^0.8.0", + "hammerjs": "^2.0.6", + "jquery": "^2.2.1", + "jquery-ui": "^1.10.5", + "jquery.cookie": "^1.4.1", + "jquery.tinydot": "^0.2.1", + "load-grunt-tasks": "^3.4.1", + "materialize-css": "0.97.5", + "npm": "^3.8.3", + "pickadate": "^3.5.6", + "pixrem": "^3.0.0", + "postcss-cssnext": "^2.5.1", + "prismjs": "^1.4.1", + "through": "^2.3.8" + }, + "engines": { + "node": ">0.12" + }, + "browser": { + "jquery": "./node_modules/jquery/dist/jquery.js", + "jQuery": "./node_modules/jquery/dist/jquery.js", + "materialize": "./node_modules/materialize-css/bin/materialize.js" + }, + "browserify-shim": { + "jquery": "$", + "jQuery": "jQuery", + "materialize": "materialize" + }, + "browserify": { + "transform": [ + "browserify-shim" + ] + }, + "repository": { + "type": "git", + "url": "https://github.com/wallabag/wallabag" + }, + "contributors": [ + { + "name": "Nicolas Lœuillet", + "email": "nicolas@loeuillet.org", + "homepage": "http://www.cdetc.fr", + "role": "Developer" + }, + { + "name": "Thomas Citharel", + "homepage": "http://tcit.fr", + "role": "Developer" + }, + { + "name": "Jérémy Benoist", + "homepage": "http://www.j0k3r.net", + "role": "Developer" + } + ], + "license": "MIT", + "bugs": { + "url": "https://github.com/wallabag/wallabag/issues" + }, + "devDependencies": { + "eslint": "^2.11.1", + "eslint-config-airbnb": "^9.0.1" + } +} diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 38880908..3216b6ff 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -16,6 +16,7 @@ + diff --git a/src/Wallabag/ApiBundle/Controller/WallabagRestController.php b/src/Wallabag/ApiBundle/Controller/WallabagRestController.php index af24e498..104720a9 100644 --- a/src/Wallabag/ApiBundle/Controller/WallabagRestController.php +++ b/src/Wallabag/ApiBundle/Controller/WallabagRestController.php @@ -7,7 +7,7 @@ use Hateoas\Configuration\Route; use Hateoas\Representation\Factory\PagerfantaFactory; use Nelmio\ApiDocBundle\Annotation\ApiDoc; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Security\Core\Exception\AccessDeniedException; use Wallabag\CoreBundle\Entity\Entry; @@ -22,6 +22,38 @@ class WallabagRestController extends FOSRestController } } + /** + * Check if an entry exist by url. + * + * @ApiDoc( + * parameters={ + * {"name"="url", "dataType"="string", "required"=true, "format"="An url", "description"="Url to check if it exists"} + * } + * ) + * + * @return JsonResponse + */ + public function getEntriesExistsAction(Request $request) + { + $this->validateAuthentication(); + + $url = $request->query->get('url', ''); + + if (empty($url)) { + throw $this->createAccessDeniedException('URL is empty?, logged user id: '.$user->getId()); + } + + $res = $this->getDoctrine() + ->getRepository('WallabagCoreBundle:Entry') + ->findByUrlAndUserId($url, $this->getUser()->getId()); + + $exists = false === $res ? false : true; + + $json = $this->get('serializer')->serialize(['exists' => $exists], 'json'); + + return (new JsonResponse())->setJson($json); + } + /** * Retrieve all entries. It could be filtered by many options. * @@ -34,10 +66,11 @@ class WallabagRestController extends FOSRestController * {"name"="page", "dataType"="integer", "required"=false, "format"="default '1'", "description"="what page you want."}, * {"name"="perPage", "dataType"="integer", "required"=false, "format"="default'30'", "description"="results per page."}, * {"name"="tags", "dataType"="string", "required"=false, "format"="api,rest", "description"="a list of tags url encoded. Will returns entries that matches ALL tags."}, + * {"name"="since", "dataType"="integer", "required"=false, "format"="default '0'", "description"="The timestamp since when you want entries updated."}, * } * ) * - * @return Response + * @return JsonResponse */ public function getEntriesAction(Request $request) { @@ -49,10 +82,12 @@ class WallabagRestController extends FOSRestController $order = $request->query->get('order', 'desc'); $page = (int) $request->query->get('page', 1); $perPage = (int) $request->query->get('perPage', 30); + $since = $request->query->get('since', 0); + $tags = $request->query->get('tags', ''); $pager = $this->getDoctrine() ->getRepository('WallabagCoreBundle:Entry') - ->findEntries($this->getUser()->getId(), $isArchived, $isStarred, $sort, $order); + ->findEntries($this->getUser()->getId(), $isArchived, $isStarred, $sort, $order, $since, $tags); $pager->setCurrentPage($page); $pager->setMaxPerPage($perPage); @@ -65,7 +100,7 @@ class WallabagRestController extends FOSRestController $json = $this->get('serializer')->serialize($paginatedCollection, 'json'); - return $this->renderJsonResponse($json); + return (new JsonResponse())->setJson($json); } /** @@ -77,7 +112,7 @@ class WallabagRestController extends FOSRestController * } * ) * - * @return Response + * @return JsonResponse */ public function getEntryAction(Entry $entry) { @@ -86,7 +121,7 @@ class WallabagRestController extends FOSRestController $json = $this->get('serializer')->serialize($entry, 'json'); - return $this->renderJsonResponse($json); + return (new JsonResponse())->setJson($json); } /** @@ -102,7 +137,7 @@ class WallabagRestController extends FOSRestController * } * ) * - * @return Response + * @return JsonResponse */ public function postEntriesAction(Request $request) { @@ -146,7 +181,7 @@ class WallabagRestController extends FOSRestController $json = $this->get('serializer')->serialize($entry, 'json'); - return $this->renderJsonResponse($json); + return (new JsonResponse())->setJson($json); } /** @@ -164,7 +199,7 @@ class WallabagRestController extends FOSRestController * } * ) * - * @return Response + * @return JsonResponse */ public function patchEntriesAction(Entry $entry, Request $request) { @@ -197,7 +232,7 @@ class WallabagRestController extends FOSRestController $json = $this->get('serializer')->serialize($entry, 'json'); - return $this->renderJsonResponse($json); + return (new JsonResponse())->setJson($json); } /** @@ -209,7 +244,7 @@ class WallabagRestController extends FOSRestController * } * ) * - * @return Response + * @return JsonResponse */ public function deleteEntriesAction(Entry $entry) { @@ -222,7 +257,7 @@ class WallabagRestController extends FOSRestController $json = $this->get('serializer')->serialize($entry, 'json'); - return $this->renderJsonResponse($json); + return (new JsonResponse())->setJson($json); } /** @@ -234,7 +269,7 @@ class WallabagRestController extends FOSRestController * } * ) * - * @return Response + * @return JsonResponse */ public function getEntriesTagsAction(Entry $entry) { @@ -243,7 +278,7 @@ class WallabagRestController extends FOSRestController $json = $this->get('serializer')->serialize($entry->getTags(), 'json'); - return $this->renderJsonResponse($json); + return (new JsonResponse())->setJson($json); } /** @@ -258,7 +293,7 @@ class WallabagRestController extends FOSRestController * } * ) * - * @return Response + * @return JsonResponse */ public function postEntriesTagsAction(Request $request, Entry $entry) { @@ -276,7 +311,7 @@ class WallabagRestController extends FOSRestController $json = $this->get('serializer')->serialize($entry, 'json'); - return $this->renderJsonResponse($json); + return (new JsonResponse())->setJson($json); } /** @@ -289,7 +324,7 @@ class WallabagRestController extends FOSRestController * } * ) * - * @return Response + * @return JsonResponse */ public function deleteEntriesTagsAction(Entry $entry, Tag $tag) { @@ -303,7 +338,7 @@ class WallabagRestController extends FOSRestController $json = $this->get('serializer')->serialize($entry, 'json'); - return $this->renderJsonResponse($json); + return (new JsonResponse())->setJson($json); } /** @@ -311,7 +346,7 @@ class WallabagRestController extends FOSRestController * * @ApiDoc() * - * @return Response + * @return JsonResponse */ public function getTagsAction() { @@ -319,11 +354,82 @@ class WallabagRestController extends FOSRestController $tags = $this->getDoctrine() ->getRepository('WallabagCoreBundle:Tag') - ->findAllTags($this->getUser()->getId()); + ->findAllTagsWithEntries($this->getUser()->getId()); + + $json = $this->get('serializer')->serialize($tags, 'json'); + + return (new JsonResponse())->setJson($json); + } + + /** + * Permanently remove one tag from **every** entry. + * + * @ApiDoc( + * requirements={ + * {"name"="tag", "dataType"="string", "required"=true, "requirement"="\w+", "description"="Tag as a string"} + * } + * ) + * + * @return JsonResponse + */ + public function deleteTagLabelAction(Request $request) + { + $this->validateAuthentication(); + $label = $request->request->get('tag', ''); + + $tag = $this->getDoctrine()->getRepository('WallabagCoreBundle:Tag')->findOneByLabel($label); + + if (empty($tag)) { + throw $this->createNotFoundException('Tag not found'); + } + + $this->getDoctrine() + ->getRepository('WallabagCoreBundle:Entry') + ->removeTag($this->getUser()->getId(), $tag); + + $json = $this->get('serializer')->serialize($tag, 'json'); + + return (new JsonResponse())->setJson($json); + } + + /** + * Permanently remove some tags from **every** entry. + * + * @ApiDoc( + * requirements={ + * {"name"="tags", "dataType"="string", "required"=true, "format"="tag1,tag2", "description"="Tags as strings (comma splitted)"} + * } + * ) + * + * @return JsonResponse + */ + public function deleteTagsLabelAction(Request $request) + { + $this->validateAuthentication(); + + $tagsLabels = $request->request->get('tags', ''); + + $tags = []; + + foreach (explode(',', $tagsLabels) as $tagLabel) { + $tagEntity = $this->getDoctrine()->getRepository('WallabagCoreBundle:Tag')->findOneByLabel($tagLabel); + + if (!empty($tagEntity)) { + $tags[] = $tagEntity; + } + } + + if (empty($tags)) { + throw $this->createNotFoundException('Tags not found'); + } + + $this->getDoctrine() + ->getRepository('WallabagCoreBundle:Entry') + ->removeTags($this->getUser()->getId(), $tags); $json = $this->get('serializer')->serialize($tags, 'json'); - return $this->renderJsonResponse($json); + return (new JsonResponse())->setJson($json); } /** @@ -335,7 +441,7 @@ class WallabagRestController extends FOSRestController * } * ) * - * @return Response + * @return JsonResponse */ public function deleteTagAction(Tag $tag) { @@ -347,14 +453,15 @@ class WallabagRestController extends FOSRestController $json = $this->get('serializer')->serialize($tag, 'json'); - return $this->renderJsonResponse($json); + return (new JsonResponse())->setJson($json); } + /** * Retrieve version number. * * @ApiDoc() * - * @return Response + * @return JsonResponse */ public function getVersionAction() { @@ -362,7 +469,7 @@ class WallabagRestController extends FOSRestController $json = $this->get('serializer')->serialize($version, 'json'); - return $this->renderJsonResponse($json); + return (new JsonResponse())->setJson($json); } /** @@ -378,17 +485,4 @@ class WallabagRestController extends FOSRestController throw $this->createAccessDeniedException('Access forbidden. Entry user id: '.$requestUserId.', logged user id: '.$user->getId()); } } - - /** - * Send a JSON Response. - * We don't use the Symfony JsonRespone, because it takes an array as parameter instead of a JSON string. - * - * @param string $json - * - * @return Response - */ - private function renderJsonResponse($json) - { - return new Response($json, 200, ['application/json']); - } } diff --git a/src/Wallabag/ApiBundle/Entity/Client.php b/src/Wallabag/ApiBundle/Entity/Client.php index c04ed0f6..3e2f491c 100644 --- a/src/Wallabag/ApiBundle/Entity/Client.php +++ b/src/Wallabag/ApiBundle/Entity/Client.php @@ -18,8 +18,39 @@ class Client extends BaseClient */ protected $id; + /** + * @var string + * + * @ORM\Column(name="name", type="text", nullable=true) + */ + protected $name; + public function __construct() { parent::__construct(); } + + /** + * Get name. + * + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * Set name. + * + * @param string $name + * + * @return Client + */ + public function setName($name) + { + $this->name = $name; + + return $this; + } } diff --git a/src/Wallabag/CoreBundle/Command/InstallCommand.php b/src/Wallabag/CoreBundle/Command/InstallCommand.php index 035eb865..cc7c2c94 100644 --- a/src/Wallabag/CoreBundle/Command/InstallCommand.php +++ b/src/Wallabag/CoreBundle/Command/InstallCommand.php @@ -2,6 +2,8 @@ namespace Wallabag\CoreBundle\Command; +use FOS\UserBundle\Event\UserEvent; +use FOS\UserBundle\FOSUserEvents; use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Input\ArrayInput; @@ -61,7 +63,6 @@ class InstallCommand extends ContainerAwareCommand ->setupDatabase() ->setupAdmin() ->setupConfig() - ->setupAsset() ; $output->writeln('Wallabag has been successfully installed.'); @@ -70,7 +71,7 @@ class InstallCommand extends ContainerAwareCommand protected function checkRequirements() { - $this->defaultOutput->writeln('Step 1 of 5. Checking system requirements.'); + $this->defaultOutput->writeln('Step 1 of 4. Checking system requirements.'); $rows = []; @@ -138,7 +139,7 @@ class InstallCommand extends ContainerAwareCommand protected function setupDatabase() { - $this->defaultOutput->writeln('Step 2 of 5. Setting up database.'); + $this->defaultOutput->writeln('Step 2 of 4. Setting up database.'); // user want to reset everything? Don't care about what is already here if (true === $this->defaultInput->getOption('reset')) { @@ -209,7 +210,7 @@ class InstallCommand extends ContainerAwareCommand protected function setupAdmin() { - $this->defaultOutput->writeln('Step 3 of 5. Administration setup.'); + $this->defaultOutput->writeln('Step 3 of 4. Administration setup.'); $questionHelper = $this->getHelperSet()->get('question'); $question = new ConfirmationQuestion('Would you like to create a new admin user (recommended) ? (Y/n)', true); @@ -237,14 +238,9 @@ class InstallCommand extends ContainerAwareCommand $em->persist($user); - $config = new Config($user); - $config->setTheme($this->getContainer()->getParameter('wallabag_core.theme')); - $config->setItemsPerPage($this->getContainer()->getParameter('wallabag_core.items_on_page')); - $config->setRssLimit($this->getContainer()->getParameter('wallabag_core.rss_limit')); - $config->setReadingSpeed($this->getContainer()->getParameter('wallabag_core.reading_speed')); - $config->setLanguage($this->getContainer()->getParameter('wallabag_core.language')); - - $em->persist($config); + // dispatch a created event so the associated config will be created + $event = new UserEvent($user); + $this->getContainer()->get('event_dispatcher')->dispatch(FOSUserEvents::USER_CREATED, $event); $this->defaultOutput->writeln(''); @@ -253,13 +249,18 @@ class InstallCommand extends ContainerAwareCommand protected function setupConfig() { - $this->defaultOutput->writeln('Step 4 of 5. Config setup.'); + $this->defaultOutput->writeln('Step 4 of 4. Config setup.'); $em = $this->getContainer()->get('doctrine.orm.entity_manager'); // cleanup before insert new stuff $em->createQuery('DELETE FROM CraueConfigBundle:Setting')->execute(); $settings = [ + [ + 'name' => 'share_public', + 'value' => '1', + 'section' => 'entry', + ], [ 'name' => 'carrot', 'value' => '1', @@ -331,8 +332,13 @@ class InstallCommand extends ContainerAwareCommand 'section' => 'export', ], [ - 'name' => 'pocket_consumer_key', - 'value' => null, + 'name' => 'import_with_redis', + 'value' => '0', + 'section' => 'import', + ], + [ + 'name' => 'import_with_rabbitmq', + 'value' => '0', 'section' => 'import', ], [ @@ -392,20 +398,6 @@ class InstallCommand extends ContainerAwareCommand return $this; } - protected function setupAsset() - { - $this->defaultOutput->writeln('Step 5 of 5. Installing assets.'); - - $this - ->runCommand('assets:install') - ->runCommand('assetic:dump') - ; - - $this->defaultOutput->writeln(''); - - return $this; - } - /** * Run a command. * diff --git a/src/Wallabag/CoreBundle/Controller/ConfigController.php b/src/Wallabag/CoreBundle/Controller/ConfigController.php index 4f75511b..91cdcae5 100644 --- a/src/Wallabag/CoreBundle/Controller/ConfigController.php +++ b/src/Wallabag/CoreBundle/Controller/ConfigController.php @@ -11,7 +11,6 @@ use Wallabag\CoreBundle\Entity\Config; use Wallabag\CoreBundle\Entity\TaggingRule; use Wallabag\CoreBundle\Form\Type\ConfigType; use Wallabag\CoreBundle\Form\Type\ChangePasswordType; -use Wallabag\CoreBundle\Form\Type\NewUserType; use Wallabag\CoreBundle\Form\Type\RssType; use Wallabag\CoreBundle\Form\Type\TaggingRuleType; use Wallabag\CoreBundle\Form\Type\UserInformationType; @@ -106,7 +105,21 @@ class ConfigController extends Controller // handle tagging rule $taggingRule = new TaggingRule(); - $newTaggingRule = $this->createForm(TaggingRuleType::class, $taggingRule, ['action' => $this->generateUrl('config').'#set5']); + $action = $this->generateUrl('config').'#set5'; + + if ($request->query->has('tagging-rule')) { + $taggingRule = $this->getDoctrine() + ->getRepository('WallabagCoreBundle:TaggingRule') + ->find($request->query->get('tagging-rule')); + + if ($this->getUser()->getId() !== $taggingRule->getConfig()->getUser()->getId()) { + return $this->redirect($action); + } + + $action = $this->generateUrl('config').'?tagging-rule='.$taggingRule->getId().'#set5'; + } + + $newTaggingRule = $this->createForm(TaggingRuleType::class, $taggingRule, ['action' => $action]); $newTaggingRule->handleRequest($request); if ($newTaggingRule->isValid()) { @@ -122,45 +135,12 @@ class ConfigController extends Controller return $this->redirect($this->generateUrl('config').'#set5'); } - // handle adding new user - $newUser = $userManager->createUser(); - // enable created user by default - $newUser->setEnabled(true); - $newUserForm = $this->createForm(NewUserType::class, $newUser, [ - 'validation_groups' => ['Profile'], - 'action' => $this->generateUrl('config').'#set6', - ]); - $newUserForm->handleRequest($request); - - if ($newUserForm->isValid() && $this->get('security.authorization_checker')->isGranted('ROLE_SUPER_ADMIN')) { - $userManager->updateUser($newUser, true); - - $config = new Config($newUser); - $config->setTheme($this->getParameter('wallabag_core.theme')); - $config->setItemsPerPage($this->getParameter('wallabag_core.items_on_page')); - $config->setRssLimit($this->getParameter('wallabag_core.rss_limit')); - $config->setLanguage($this->getParameter('wallabag_core.language')); - $config->setReadingSpeed($this->getParameter('wallabag_core.reading_speed')); - - $em->persist($config); - - $em->flush(); - - $this->get('session')->getFlashBag()->add( - 'notice', - $this->get('translator')->trans('flashes.config.notice.user_added', ['%username%' => $newUser->getUsername()]) - ); - - return $this->redirect($this->generateUrl('config').'#set6'); - } - return $this->render('WallabagCoreBundle:Config:index.html.twig', [ 'form' => [ 'config' => $configForm->createView(), 'rss' => $rssForm->createView(), 'pwd' => $pwdForm->createView(), 'user' => $userForm->createView(), - 'new_user' => $newUserForm->createView(), 'new_tagging_rule' => $newTaggingRule->createView(), ], 'rss' => [ @@ -210,9 +190,7 @@ class ConfigController extends Controller */ public function deleteTaggingRuleAction(TaggingRule $rule) { - if ($this->getUser()->getId() != $rule->getConfig()->getUser()->getId()) { - throw $this->createAccessDeniedException('You can not access this tagging rule.'); - } + $this->validateRuleAction($rule); $em = $this->getDoctrine()->getManager(); $em->remove($rule); @@ -226,6 +204,34 @@ class ConfigController extends Controller return $this->redirect($this->generateUrl('config').'#set5'); } + /** + * Edit a tagging rule. + * + * @param TaggingRule $rule + * + * @Route("/tagging-rule/edit/{id}", requirements={"id" = "\d+"}, name="edit_tagging_rule") + * + * @return RedirectResponse + */ + public function editTaggingRuleAction(TaggingRule $rule) + { + $this->validateRuleAction($rule); + + return $this->redirect($this->generateUrl('config').'?tagging-rule='.$rule->getId().'#set5'); + } + + /** + * Validate that a rule can be edited/deleted by the current user. + * + * @param TaggingRule $rule + */ + private function validateRuleAction(TaggingRule $rule) + { + if ($this->getUser()->getId() != $rule->getConfig()->getUser()->getId()) { + throw $this->createAccessDeniedException('You can not access this tagging rule.'); + } + } + /** * Retrieve config for the current user. * If no config were found, create a new one. @@ -238,6 +244,7 @@ class ConfigController extends Controller ->getRepository('WallabagCoreBundle:Config') ->findOneByUser($this->getUser()); + // should NEVER HAPPEN ... if (!$config) { $config = new Config($this->getUser()); } diff --git a/src/Wallabag/CoreBundle/Controller/DeveloperController.php b/src/Wallabag/CoreBundle/Controller/DeveloperController.php index d85ba5ee..f3492b74 100644 --- a/src/Wallabag/CoreBundle/Controller/DeveloperController.php +++ b/src/Wallabag/CoreBundle/Controller/DeveloperController.php @@ -21,7 +21,7 @@ class DeveloperController extends Controller { $clients = $this->getDoctrine()->getRepository('WallabagApiBundle:Client')->findAll(); - return $this->render('WallabagCoreBundle:Developer:index.html.twig', [ + return $this->render('@WallabagCore/themes/common/Developer/index.html.twig', [ 'clients' => $clients, ]); } @@ -49,16 +49,17 @@ class DeveloperController extends Controller $this->get('session')->getFlashBag()->add( 'notice', - 'flashes.developer.notice.client_created' + $this->get('translator')->trans('flashes.developer.notice.client_created', ['%name%' => $client->getName()]) ); - return $this->render('WallabagCoreBundle:Developer:client_parameters.html.twig', [ + return $this->render('@WallabagCore/themes/common/Developer/client_parameters.html.twig', [ 'client_id' => $client->getPublicId(), 'client_secret' => $client->getSecret(), + 'client_name' => $client->getName(), ]); } - return $this->render('WallabagCoreBundle:Developer:client.html.twig', [ + return $this->render('@WallabagCore/themes/common/Developer/client.html.twig', [ 'form' => $clientForm->createView(), ]); } @@ -80,7 +81,7 @@ class DeveloperController extends Controller $this->get('session')->getFlashBag()->add( 'notice', - 'flashes.developer.notice.client_deleted' + $this->get('translator')->trans('flashes.developer.notice.client_deleted', ['%name%' => $client->getName()]) ); return $this->redirect($this->generateUrl('developer')); @@ -95,6 +96,6 @@ class DeveloperController extends Controller */ public function howtoFirstAppAction() { - return $this->render('WallabagCoreBundle:Developer:howto_app.html.twig'); + return $this->render('@WallabagCore/themes/common/Developer/howto_app.html.twig'); } } diff --git a/src/Wallabag/CoreBundle/Controller/EntryController.php b/src/Wallabag/CoreBundle/Controller/EntryController.php index ccdf9406..3b28e635 100644 --- a/src/Wallabag/CoreBundle/Controller/EntryController.php +++ b/src/Wallabag/CoreBundle/Controller/EntryController.php @@ -4,7 +4,6 @@ namespace Wallabag\CoreBundle\Controller; use Pagerfanta\Adapter\DoctrineORMAdapter; use Pagerfanta\Exception\OutOfRangeCurrentPageException; -use Pagerfanta\Pagerfanta; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Request; @@ -13,30 +12,40 @@ use Wallabag\CoreBundle\Entity\Entry; use Wallabag\CoreBundle\Form\Type\EntryFilterType; use Wallabag\CoreBundle\Form\Type\EditEntryType; use Wallabag\CoreBundle\Form\Type\NewEntryType; +use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache; class EntryController extends Controller { /** - * @param Entry $entry + * Fetch content and update entry. + * In case it fails, entry will return to avod loosing the data. + * + * @param Entry $entry + * @param string $prefixMessage Should be the translation key: entry_saved or entry_reloaded + * + * @return Entry */ - private function updateEntry(Entry $entry) + private function updateEntry(Entry $entry, $prefixMessage = 'entry_saved') { + // put default title in case of fetching content failed + $entry->setTitle('No title found'); + + $message = 'flashes.entry.notice.'.$prefixMessage; + try { $entry = $this->get('wallabag_core.content_proxy')->updateEntry($entry, $entry->getUrl()); - - $em = $this->getDoctrine()->getManager(); - $em->persist($entry); - $em->flush(); } catch (\Exception $e) { $this->get('logger')->error('Error while saving an entry', [ 'exception' => $e, 'entry' => $entry, ]); - return false; + $message = 'flashes.entry.notice.'.$prefixMessage.'_failed'; } - return true; + $this->get('session')->getFlashBag()->add('notice', $message); + + return $entry; } /** @@ -66,12 +75,11 @@ class EntryController extends Controller return $this->redirect($this->generateUrl('view', ['id' => $existingEntry->getId()])); } - $message = 'flashes.entry.notice.entry_saved'; - if (false === $this->updateEntry($entry)) { - $message = 'flashes.entry.notice.entry_saved_failed'; - } + $this->updateEntry($entry); - $this->get('session')->getFlashBag()->add('notice', $message); + $em = $this->getDoctrine()->getManager(); + $em->persist($entry); + $em->flush(); return $this->redirect($this->generateUrl('homepage')); } @@ -95,6 +103,10 @@ class EntryController extends Controller if (false === $this->checkIfEntryAlreadyExists($entry)) { $this->updateEntry($entry); + + $em = $this->getDoctrine()->getManager(); + $em->persist($entry); + $em->flush(); } return $this->redirect($this->generateUrl('homepage')); @@ -226,6 +238,10 @@ class EntryController extends Controller $repository = $this->get('wallabag_core.entry_repository'); switch ($type) { + case 'untagged': + $qb = $repository->getBuilderForUntaggedByUser($this->getUser()->getId()); + + break; case 'starred': $qb = $repository->getBuilderForStarredByUser($this->getUser()->getId()); break; @@ -257,9 +273,10 @@ class EntryController extends Controller } $pagerAdapter = new DoctrineORMAdapter($qb->getQuery()); - $entries = new Pagerfanta($pagerAdapter); - $entries->setMaxPerPage($this->getUser()->getConfig()->getItemsPerPage()); + $entries = $this->get('wallabag_core.helper.prepare_pager_for_entries') + ->prepare($pagerAdapter, $page); + try { $entries->setCurrentPage($page); } catch (OutOfRangeCurrentPageException $e) { @@ -311,15 +328,11 @@ class EntryController extends Controller { $this->checkUserAction($entry); - $message = 'flashes.entry.notice.entry_reloaded'; - if (false === $this->updateEntry($entry)) { - $message = 'flashes.entry.notice.entry_reload_failed'; - } + $this->updateEntry($entry, 'entry_reloaded'); - $this->get('session')->getFlashBag()->add( - 'notice', - $message - ); + $em = $this->getDoctrine()->getManager(); + $em->persist($entry); + $em->flush(); return $this->redirect($this->generateUrl('view', ['id' => $entry->getId()])); } @@ -434,7 +447,7 @@ class EntryController extends Controller */ private function checkUserAction(Entry $entry) { - if ($this->getUser()->getId() != $entry->getUser()->getId()) { + if (null === $this->getUser() || $this->getUser()->getId() != $entry->getUser()->getId()) { throw $this->createAccessDeniedException('You can not access this entry.'); } } @@ -450,4 +463,91 @@ class EntryController extends Controller { return $this->get('wallabag_core.entry_repository')->findByUrlAndUserId($entry->getUrl(), $this->getUser()->getId()); } + + /** + * Get public URL for entry (and generate it if necessary). + * + * @param Entry $entry + * + * @Route("/share/{id}", requirements={"id" = "\d+"}, name="share") + * + * @return \Symfony\Component\HttpFoundation\Response + */ + public function shareAction(Entry $entry) + { + $this->checkUserAction($entry); + + if (null === $entry->getUuid()) { + $entry->generateUuid(); + + $em = $this->getDoctrine()->getManager(); + $em->persist($entry); + $em->flush(); + } + + return $this->redirect($this->generateUrl('share_entry', [ + 'uuid' => $entry->getUuid(), + ])); + } + + /** + * Disable public sharing for an entry. + * + * @param Entry $entry + * + * @Route("/share/delete/{id}", requirements={"id" = "\d+"}, name="delete_share") + * + * @return \Symfony\Component\HttpFoundation\Response + */ + public function deleteShareAction(Entry $entry) + { + $this->checkUserAction($entry); + + $entry->cleanUuid(); + + $em = $this->getDoctrine()->getManager(); + $em->persist($entry); + $em->flush(); + + return $this->redirect($this->generateUrl('view', [ + 'id' => $entry->getId(), + ])); + } + + /** + * Ability to view a content publicly. + * + * @param Entry $entry + * + * @Route("/share/{uuid}", requirements={"uuid" = ".+"}, name="share_entry") + * @Cache(maxage="25200", smaxage="25200", public=true) + * + * @return \Symfony\Component\HttpFoundation\Response + */ + public function shareEntryAction(Entry $entry) + { + if (!$this->get('craue_config')->get('share_public')) { + throw $this->createAccessDeniedException('Sharing an entry is disabled for this user.'); + } + + return $this->render( + '@WallabagCore/themes/common/Entry/share.html.twig', + ['entry' => $entry] + ); + } + + /** + * Shows untagged articles for current user. + * + * @param Request $request + * @param int $page + * + * @Route("/untagged/list/{page}", name="untagged", defaults={"page" = "1"}) + * + * @return \Symfony\Component\HttpFoundation\Response + */ + public function showUntaggedEntriesAction(Request $request, $page) + { + return $this->showEntries('untagged', $request, $page); + } } diff --git a/src/Wallabag/CoreBundle/Controller/ExceptionController.php b/src/Wallabag/CoreBundle/Controller/ExceptionController.php new file mode 100644 index 00000000..abfa9c2f --- /dev/null +++ b/src/Wallabag/CoreBundle/Controller/ExceptionController.php @@ -0,0 +1,40 @@ +templateExists($template)) { + return $template; + } + } + + // try to find a template for the given format + $template = sprintf('@Twig/Exception/%s.%s.twig', $name, $format); + if ($this->templateExists($template)) { + return $template; + } + + // default to a generic HTML exception + $request->setRequestFormat('html'); + + return sprintf('@Twig/Exception/%s.html.twig', $showException ? 'exception_full' : $name); + } +} diff --git a/src/Wallabag/CoreBundle/Controller/ExportController.php b/src/Wallabag/CoreBundle/Controller/ExportController.php index 944c755d..6191d5d7 100644 --- a/src/Wallabag/CoreBundle/Controller/ExportController.php +++ b/src/Wallabag/CoreBundle/Controller/ExportController.php @@ -46,7 +46,7 @@ class ExportController extends Controller * * @Route("/export/{category}.{format}", name="export_entries", requirements={ * "format": "epub|mobi|pdf|json|xml|txt|csv", - * "category": "all|unread|starred|archive" + * "category": "all|unread|starred|archive|tag_entries|untagged" * }) * * @return \Symfony\Component\HttpFoundation\Response diff --git a/src/Wallabag/CoreBundle/Controller/FooterController.php b/src/Wallabag/CoreBundle/Controller/FooterController.php deleted file mode 100644 index fd93c436..00000000 --- a/src/Wallabag/CoreBundle/Controller/FooterController.php +++ /dev/null @@ -1,27 +0,0 @@ -container->getParameter('addons_url'); - $socialsUrl = $this->container->getParameter('socials_url'); - - return $this->render( - 'WallabagCoreBundle::footer.html.twig', - [ - 'addonsUrl' => $addonsUrl, - 'socialsUrl' => $socialsUrl, - ] - ); - } -} diff --git a/src/Wallabag/CoreBundle/Controller/RssController.php b/src/Wallabag/CoreBundle/Controller/RssController.php index 2118885c..38e3b5a0 100644 --- a/src/Wallabag/CoreBundle/Controller/RssController.php +++ b/src/Wallabag/CoreBundle/Controller/RssController.php @@ -87,7 +87,7 @@ class RssController extends Controller $perPage = $user->getConfig()->getRssLimit() ?: $this->getParameter('wallabag_core.rss_limit'); $entries->setMaxPerPage($perPage); - return $this->render('WallabagCoreBundle:Entry:entries.xml.twig', [ + return $this->render('@WallabagCore/themes/common/Entry/entries.xml.twig', [ 'type' => $type, 'entries' => $entries, ]); diff --git a/src/Wallabag/CoreBundle/Controller/StaticController.php b/src/Wallabag/CoreBundle/Controller/StaticController.php index 2a57f06f..82714217 100644 --- a/src/Wallabag/CoreBundle/Controller/StaticController.php +++ b/src/Wallabag/CoreBundle/Controller/StaticController.php @@ -15,7 +15,7 @@ class StaticController extends Controller $addonsUrl = $this->container->getParameter('addons_url'); return $this->render( - 'WallabagCoreBundle:Static:howto.html.twig', + '@WallabagCore/themes/common/Static/howto.html.twig', ['addonsUrl' => $addonsUrl] ); } @@ -26,7 +26,7 @@ class StaticController extends Controller public function aboutAction() { return $this->render( - 'WallabagCoreBundle:Static:about.html.twig', + '@WallabagCore/themes/common/Static/about.html.twig', [ 'version' => $this->getParameter('wallabag_core.version'), 'paypal_url' => $this->getParameter('wallabag_core.paypal_url'), @@ -40,7 +40,7 @@ class StaticController extends Controller public function quickstartAction() { return $this->render( - 'WallabagCoreBundle:Static:quickstart.html.twig', + '@WallabagCore/themes/common/Static/quickstart.html.twig', [] ); } diff --git a/src/Wallabag/CoreBundle/Controller/TagController.php b/src/Wallabag/CoreBundle/Controller/TagController.php index 8645fb44..623a6146 100644 --- a/src/Wallabag/CoreBundle/Controller/TagController.php +++ b/src/Wallabag/CoreBundle/Controller/TagController.php @@ -2,12 +2,15 @@ namespace Wallabag\CoreBundle\Controller; +use Pagerfanta\Adapter\ArrayAdapter; +use Pagerfanta\Exception\OutOfRangeCurrentPageException; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Request; use Wallabag\CoreBundle\Entity\Entry; use Wallabag\CoreBundle\Entity\Tag; use Wallabag\CoreBundle\Form\Type\NewTagType; +use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; class TagController extends Controller { @@ -81,13 +84,48 @@ class TagController extends Controller { $tags = $this->getDoctrine() ->getRepository('WallabagCoreBundle:Tag') - ->findAllTags($this->getUser()->getId()); - - return $this->render( - 'WallabagCoreBundle:Tag:tags.html.twig', - [ - 'tags' => $tags, - ] - ); + ->findAllTagsWithEntries($this->getUser()->getId()); + + return $this->render('WallabagCoreBundle:Tag:tags.html.twig', [ + 'tags' => $tags, + ]); + } + + /** + * @param Tag $tag + * @param int $page + * + * @Route("/tag/list/{slug}/{page}", name="tag_entries", defaults={"page" = "1"}) + * @ParamConverter("tag", options={"mapping": {"slug": "slug"}}) + * + * @return \Symfony\Component\HttpFoundation\Response + */ + public function showEntriesForTagAction(Tag $tag, $page, Request $request) + { + $entriesByTag = $this->getDoctrine() + ->getRepository('WallabagCoreBundle:Entry') + ->findAllByTagId($this->getUser()->getId(), $tag->getId()); + + $pagerAdapter = new ArrayAdapter($entriesByTag); + + $entries = $this->get('wallabag_core.helper.prepare_pager_for_entries') + ->prepare($pagerAdapter, $page); + + try { + $entries->setCurrentPage($page); + } catch (OutOfRangeCurrentPageException $e) { + if ($page > 1) { + return $this->redirect($this->generateUrl($request->get('_route'), [ + 'slug' => $tag->getSlug(), + 'page' => $entries->getNbPages(), + ]), 302); + } + } + + return $this->render('WallabagCoreBundle:Entry:entries.html.twig', [ + 'form' => null, + 'entries' => $entries, + 'currentPage' => $page, + ]); } } diff --git a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadConfigData.php b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadConfigData.php index 03be9667..921c739f 100644 --- a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadConfigData.php +++ b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadConfigData.php @@ -20,6 +20,7 @@ class LoadConfigData extends AbstractFixture implements OrderedFixtureInterface $adminConfig->setItemsPerPage(30); $adminConfig->setReadingSpeed(1); $adminConfig->setLanguage('en'); + $adminConfig->setPocketConsumerKey('xxxxx'); $manager->persist($adminConfig); @@ -30,6 +31,7 @@ class LoadConfigData extends AbstractFixture implements OrderedFixtureInterface $bobConfig->setItemsPerPage(10); $bobConfig->setReadingSpeed(1); $bobConfig->setLanguage('fr'); + $bobConfig->setPocketConsumerKey(null); $manager->persist($bobConfig); @@ -40,6 +42,7 @@ class LoadConfigData extends AbstractFixture implements OrderedFixtureInterface $emptyConfig->setItemsPerPage(10); $emptyConfig->setReadingSpeed(1); $emptyConfig->setLanguage('en'); + $emptyConfig->setPocketConsumerKey(null); $manager->persist($emptyConfig); diff --git a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadSettingData.php b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadSettingData.php index 09058796..9425f961 100644 --- a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadSettingData.php +++ b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadSettingData.php @@ -15,6 +15,11 @@ class LoadSettingData extends AbstractFixture implements OrderedFixtureInterface public function load(ObjectManager $manager) { $settings = [ + [ + 'name' => 'share_public', + 'value' => '1', + 'section' => 'entry', + ], [ 'name' => 'carrot', 'value' => '1', @@ -86,8 +91,13 @@ class LoadSettingData extends AbstractFixture implements OrderedFixtureInterface 'section' => 'export', ], [ - 'name' => 'pocket_consumer_key', - 'value' => null, + 'name' => 'import_with_redis', + 'value' => '0', + 'section' => 'import', + ], + [ + 'name' => 'import_with_rabbitmq', + 'value' => '0', 'section' => 'import', ], [ diff --git a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadTagData.php b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadTagData.php index 8553dced..09e99f36 100644 --- a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadTagData.php +++ b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadTagData.php @@ -28,6 +28,13 @@ class LoadTagData extends AbstractFixture implements OrderedFixtureInterface $this->addReference('bar-tag', $tag2); + $tag3 = new Tag(); + $tag3->setLabel('baz'); + + $manager->persist($tag3); + + $this->addReference('baz-tag', $tag3); + $manager->flush(); } diff --git a/src/Wallabag/CoreBundle/DependencyInjection/Configuration.php b/src/Wallabag/CoreBundle/DependencyInjection/Configuration.php index d1bb9820..d8141eea 100644 --- a/src/Wallabag/CoreBundle/DependencyInjection/Configuration.php +++ b/src/Wallabag/CoreBundle/DependencyInjection/Configuration.php @@ -36,6 +36,9 @@ class Configuration implements ConfigurationInterface ->end() ->scalarNode('paypal_url') ->end() + ->integerNode('cache_lifetime') + ->defaultValue(10) + ->end() ->end() ; diff --git a/src/Wallabag/CoreBundle/DependencyInjection/WallabagCoreExtension.php b/src/Wallabag/CoreBundle/DependencyInjection/WallabagCoreExtension.php index 7d08b73b..0cbde908 100644 --- a/src/Wallabag/CoreBundle/DependencyInjection/WallabagCoreExtension.php +++ b/src/Wallabag/CoreBundle/DependencyInjection/WallabagCoreExtension.php @@ -22,6 +22,7 @@ class WallabagCoreExtension extends Extension $container->setParameter('wallabag_core.reading_speed', $config['reading_speed']); $container->setParameter('wallabag_core.version', $config['version']); $container->setParameter('wallabag_core.paypal_url', $config['paypal_url']); + $container->setParameter('wallabag_core.cache_lifetime', $config['cache_lifetime']); $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); $loader->load('services.yml'); diff --git a/src/Wallabag/CoreBundle/Entity/Config.php b/src/Wallabag/CoreBundle/Entity/Config.php index a25656d3..d0f0e3f3 100644 --- a/src/Wallabag/CoreBundle/Entity/Config.php +++ b/src/Wallabag/CoreBundle/Entity/Config.php @@ -80,6 +80,13 @@ class Config */ private $readingSpeed; + /** + * @var string + * + * @ORM\Column(name="pocket_consumer_key", type="string", nullable=true) + */ + private $pocketConsumerKey; + /** * @ORM\OneToOne(targetEntity="Wallabag\UserBundle\Entity\User", inversedBy="config") */ @@ -278,6 +285,30 @@ class Config return $this->readingSpeed; } + /** + * Set pocketConsumerKey. + * + * @param string $pocketConsumerKey + * + * @return Config + */ + public function setPocketConsumerKey($pocketConsumerKey) + { + $this->pocketConsumerKey = $pocketConsumerKey; + + return $this; + } + + /** + * Get pocketConsumerKey. + * + * @return string + */ + public function getPocketConsumerKey() + { + return $this->pocketConsumerKey; + } + /** * @param TaggingRule $rule * diff --git a/src/Wallabag/CoreBundle/Entity/Entry.php b/src/Wallabag/CoreBundle/Entity/Entry.php index ceae78b0..a4b0d7a8 100644 --- a/src/Wallabag/CoreBundle/Entity/Entry.php +++ b/src/Wallabag/CoreBundle/Entity/Entry.php @@ -37,6 +37,15 @@ class Entry */ private $id; + /** + * @var string + * + * @ORM\Column(name="uuid", type="text", nullable=true) + * + * @Groups({"entries_for_user", "export_all"}) + */ + private $uuid; + /** * @var string * @@ -88,20 +97,20 @@ class Entry private $content; /** - * @var date + * @var \DateTime * * @ORM\Column(name="created_at", type="datetime") * - * @Groups({"export_all"}) + * @Groups({"entries_for_user", "export_all"}) */ private $createdAt; /** - * @var date + * @var \DateTime * * @ORM\Column(name="updated_at", type="datetime") * - * @Groups({"export_all"}) + * @Groups({"entries_for_user", "export_all"}) */ private $updatedAt; @@ -401,7 +410,22 @@ class Entry } /** - * @return string + * Set created_at. + * Only used when importing data from an other service. + * + * @param \DateTime $createdAt + * + * @return Entry + */ + public function setCreatedAt(\DateTime $createdAt) + { + $this->createdAt = $createdAt; + + return $this; + } + + /** + * @return \DateTime */ public function getCreatedAt() { @@ -409,7 +433,7 @@ class Entry } /** - * @return string + * @return \DateTime */ public function getUpdatedAt() { @@ -595,4 +619,37 @@ class Entry { return $this->language; } + + /** + * @return string + */ + public function getUuid() + { + return $this->uuid; + } + + /** + * @param string $uuid + * + * @return Entry + */ + public function setUuid($uuid) + { + $this->uuid = $uuid; + + return $this; + } + + public function generateUuid() + { + if (null === $this->uuid) { + // @see http://blog.kevingomez.fr/til/2015/07/26/why-is-uniqid-slow/ for true parameter + $this->uuid = uniqid('', true); + } + } + + public function cleanUuid() + { + $this->uuid = null; + } } diff --git a/src/Wallabag/CoreBundle/Form/Type/ClientType.php b/src/Wallabag/CoreBundle/Form/Type/ClientType.php index 8b351e60..d1fa94e6 100644 --- a/src/Wallabag/CoreBundle/Form/Type/ClientType.php +++ b/src/Wallabag/CoreBundle/Form/Type/ClientType.php @@ -6,6 +6,7 @@ use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\CallbackTransformer; use Symfony\Component\Form\Extension\Core\Type\SubmitType; use Symfony\Component\Form\Extension\Core\Type\UrlType; +use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; @@ -14,7 +15,8 @@ class ClientType extends AbstractType public function buildForm(FormBuilderInterface $builder, array $options) { $builder - ->add('redirect_uris', UrlType::class, ['required' => true, 'label' => 'developer.client.form.redirect_uris_label']) + ->add('name', TextType::class, ['label' => 'developer.client.form.name_label']) + ->add('redirect_uris', UrlType::class, ['required' => false, 'label' => 'developer.client.form.redirect_uris_label']) ->add('save', SubmitType::class, ['label' => 'developer.client.form.save_label']) ; diff --git a/src/Wallabag/CoreBundle/Form/Type/ConfigType.php b/src/Wallabag/CoreBundle/Form/Type/ConfigType.php index 7d25cc80..0bac2874 100644 --- a/src/Wallabag/CoreBundle/Form/Type/ConfigType.php +++ b/src/Wallabag/CoreBundle/Form/Type/ConfigType.php @@ -52,6 +52,9 @@ class ConfigType extends AbstractType 'choices' => array_flip($this->languages), 'label' => 'config.form_settings.language_label', ]) + ->add('pocket_consumer_key', null, [ + 'label' => 'config.form_settings.pocket_consumer_key_label', + ]) ->add('save', SubmitType::class, [ 'label' => 'config.form.save', ]) diff --git a/src/Wallabag/CoreBundle/Helper/ContentProxy.php b/src/Wallabag/CoreBundle/Helper/ContentProxy.php index 5dd684f2..8019df42 100644 --- a/src/Wallabag/CoreBundle/Helper/ContentProxy.php +++ b/src/Wallabag/CoreBundle/Helper/ContentProxy.php @@ -95,14 +95,24 @@ class ContentProxy * Assign some tags to an entry. * * @param Entry $entry - * @param array|string $tags An array of tag or a string coma separated of tag + * @param array|string $tags An array of tag or a string coma separated of tag + * @param array $entitiesReady Entities from the EntityManager which are persisted but not yet flushed + * It is mostly to fix duplicate tag on import @see http://stackoverflow.com/a/7879164/569101 */ - public function assignTagsToEntry(Entry $entry, $tags) + public function assignTagsToEntry(Entry $entry, $tags, array $entitiesReady = []) { if (!is_array($tags)) { $tags = explode(',', $tags); } + // keeps only Tag entity from the "not yet flushed entities" + $tagsNotYetFlushed = []; + foreach ($entitiesReady as $entity) { + if ($entity instanceof Tag) { + $tagsNotYetFlushed[$entity->getLabel()] = $entity; + } + } + foreach ($tags as $label) { $label = trim($label); @@ -111,11 +121,15 @@ class ContentProxy continue; } - $tagEntity = $this->tagRepository->findOneByLabel($label); + if (isset($tagsNotYetFlushed[$label])) { + $tagEntity = $tagsNotYetFlushed[$label]; + } else { + $tagEntity = $this->tagRepository->findOneByLabel($label); - if (is_null($tagEntity)) { - $tagEntity = new Tag(); - $tagEntity->setLabel($label); + if (is_null($tagEntity)) { + $tagEntity = new Tag(); + $tagEntity->setLabel($label); + } } // only add the tag on the entry if the relation doesn't exist diff --git a/src/Wallabag/CoreBundle/Helper/EntriesExport.php b/src/Wallabag/CoreBundle/Helper/EntriesExport.php index ccf4e4f3..0c627dcd 100644 --- a/src/Wallabag/CoreBundle/Helper/EntriesExport.php +++ b/src/Wallabag/CoreBundle/Helper/EntriesExport.php @@ -302,7 +302,7 @@ class EntriesExport $enclosure = '"'; $handle = fopen('php://memory', 'rb+'); - fputcsv($handle, ['Title', 'URL', 'Content', 'Tags', 'MIME Type', 'Language'], $delimiter, $enclosure); + fputcsv($handle, ['Title', 'URL', 'Content', 'Tags', 'MIME Type', 'Language', 'Creation date'], $delimiter, $enclosure); foreach ($this->entries as $entry) { fputcsv( @@ -315,6 +315,7 @@ class EntriesExport implode(', ', $entry->getTags()->toArray()), $entry->getMimetype(), $entry->getLanguage(), + $entry->getCreatedAt()->format('d/m/Y h:i:s'), ], $delimiter, $enclosure diff --git a/src/Wallabag/CoreBundle/Helper/PreparePagerForEntries.php b/src/Wallabag/CoreBundle/Helper/PreparePagerForEntries.php new file mode 100644 index 00000000..f9066bee --- /dev/null +++ b/src/Wallabag/CoreBundle/Helper/PreparePagerForEntries.php @@ -0,0 +1,34 @@ +user = $token->getToken()->getUser(); + $this->router = $router; + } + + /** + * @param AdapterInterface $adapter + * @param int $page + * + * @return null|Pagerfanta + */ + public function prepare(AdapterInterface $adapter, $page = 1) + { + $entries = new Pagerfanta($adapter); + $entries->setMaxPerPage($this->user->getConfig()->getItemsPerPage()); + + return $entries; + } +} diff --git a/src/Wallabag/CoreBundle/ParamConverter/UsernameRssTokenConverter.php b/src/Wallabag/CoreBundle/ParamConverter/UsernameRssTokenConverter.php index 6ea2a4f3..40b5673d 100644 --- a/src/Wallabag/CoreBundle/ParamConverter/UsernameRssTokenConverter.php +++ b/src/Wallabag/CoreBundle/ParamConverter/UsernameRssTokenConverter.php @@ -49,7 +49,7 @@ class UsernameRssTokenConverter implements ParamConverterInterface $em = $this->registry->getManagerForClass($configuration->getClass()); // Check, if class name is what we need - if ('Wallabag\UserBundle\Entity\User' !== $em->getClassMetadata($configuration->getClass())->getName()) { + if (null !== $em && 'Wallabag\UserBundle\Entity\User' !== $em->getClassMetadata($configuration->getClass())->getName()) { return false; } @@ -69,9 +69,8 @@ class UsernameRssTokenConverter implements ParamConverterInterface $username = $request->attributes->get('username'); $rssToken = $request->attributes->get('token'); - // Check, if route attributes exists - if (null === $username || null === $rssToken) { - throw new \InvalidArgumentException('Route attribute is missing'); + if (!$request->attributes->has('username') || !$request->attributes->has('token')) { + return false; } // Get actual entity manager for class diff --git a/src/Wallabag/CoreBundle/Repository/EntryRepository.php b/src/Wallabag/CoreBundle/Repository/EntryRepository.php index 4d45e5f5..1b023e96 100644 --- a/src/Wallabag/CoreBundle/Repository/EntryRepository.php +++ b/src/Wallabag/CoreBundle/Repository/EntryRepository.php @@ -3,6 +3,7 @@ namespace Wallabag\CoreBundle\Repository; use Doctrine\ORM\EntityRepository; +use Doctrine\ORM\Query; use Pagerfanta\Adapter\DoctrineORMAdapter; use Pagerfanta\Pagerfanta; use Wallabag\CoreBundle\Entity\Tag; @@ -84,6 +85,22 @@ class EntryRepository extends EntityRepository ; } + /** + * Retrieves untagged entries for a user. + * + * @param int $userId + * + * @return QueryBuilder + */ + public function getBuilderForUntaggedByUser($userId) + { + return $this + ->getBuilderByUser($userId) + ->leftJoin('e.tags', 't') + ->groupBy('e.id') + ->having('count(t.id) = 0'); + } + /** * Find Entries. * @@ -92,12 +109,15 @@ class EntryRepository extends EntityRepository * @param bool $isStarred * @param string $sort * @param string $order + * @param int $since + * @param string $tags * * @return array */ - public function findEntries($userId, $isArchived = null, $isStarred = null, $sort = 'created', $order = 'ASC') + public function findEntries($userId, $isArchived = null, $isStarred = null, $sort = 'created', $order = 'ASC', $since = 0, $tags = '') { $qb = $this->createQueryBuilder('e') + ->leftJoin('e.tags', 't') ->where('e.user =:userId')->setParameter('userId', $userId); if (null !== $isArchived) { @@ -108,6 +128,16 @@ class EntryRepository extends EntityRepository $qb->andWhere('e.isStarred =:isStarred')->setParameter('isStarred', (bool) $isStarred); } + if ($since >= 0) { + $qb->andWhere('e.updatedAt > :since')->setParameter('since', new \DateTime(date('Y-m-d H:i:s', $since))); + } + + if ('' !== $tags) { + foreach (explode(',', $tags) as $tag) { + $qb->andWhere('t.label = :label')->setParameter('label', $tag); + } + } + if ('created' === $sort) { $qb->orderBy('e.id', $order); } elseif ('updated' === $sort) { @@ -209,6 +239,19 @@ class EntryRepository extends EntityRepository $this->getEntityManager()->flush(); } + /** + * Remove tags from all user entries. + * + * @param int $userId + * @param Array $tags + */ + public function removeTags($userId, $tags) + { + foreach ($tags as $tag) { + $this->removeTag($userId, $tag); + } + } + /** * Find all entries that are attached to a give tag id. * @@ -238,7 +281,7 @@ class EntryRepository extends EntityRepository public function findByUrlAndUserId($url, $userId) { $res = $this->createQueryBuilder('e') - ->where('e.url = :url')->setParameter('url', $url) + ->where('e.url = :url')->setParameter('url', urldecode($url)) ->andWhere('e.user = :user_id')->setParameter('user_id', $userId) ->getQuery() ->getResult(); diff --git a/src/Wallabag/CoreBundle/Repository/TagRepository.php b/src/Wallabag/CoreBundle/Repository/TagRepository.php index abf915fe..9d127da7 100644 --- a/src/Wallabag/CoreBundle/Repository/TagRepository.php +++ b/src/Wallabag/CoreBundle/Repository/TagRepository.php @@ -7,13 +7,39 @@ use Doctrine\ORM\EntityRepository; class TagRepository extends EntityRepository { /** - * Find Tags. + * Count all tags per user. + * + * @param int $userId + * @param int $cacheLifeTime Duration of the cache for this query + * + * @return int + */ + public function countAllTags($userId, $cacheLifeTime = null) + { + $query = $this->createQueryBuilder('t') + ->select('t.slug') + ->leftJoin('t.entries', 'e') + ->where('e.user = :userId')->setParameter('userId', $userId) + ->groupBy('t.slug') + ->getQuery(); + + if (null !== $cacheLifeTime) { + $query->useQueryCache(true); + $query->useResultCache(true); + $query->setResultCacheLifetime($cacheLifeTime); + } + + return count($query->getArrayResult()); + } + + /** + * Find all tags with associated entries per user. * * @param int $userId * * @return array */ - public function findAllTags($userId) + public function findAllTagsWithEntries($userId) { return $this->createQueryBuilder('t') ->leftJoin('t.entries', 'e') diff --git a/src/Wallabag/CoreBundle/Resources/config/parameters.yml b/src/Wallabag/CoreBundle/Resources/config/parameters.yml index abd9ab68..6068e84c 100644 --- a/src/Wallabag/CoreBundle/Resources/config/parameters.yml +++ b/src/Wallabag/CoreBundle/Resources/config/parameters.yml @@ -6,7 +6,3 @@ parameters: google_play: https://play.google.com/store/apps/details?id=fr.gaulupeau.apps.InThePoche ios: https://itunes.apple.com/app/wallabag/id828331015?mt=8 windows: https://www.microsoft.com/store/apps/wallabag/9nblggh11646 - socials_url: - twitter: https://twitter.com/wallabagapp - google_plus: https://plus.google.com/+WallabagOrg/posts - facebook: https://facebook.com/Wallabag diff --git a/src/Wallabag/CoreBundle/Resources/config/services.yml b/src/Wallabag/CoreBundle/Resources/config/services.yml index f8835198..d1139846 100644 --- a/src/Wallabag/CoreBundle/Resources/config/services.yml +++ b/src/Wallabag/CoreBundle/Resources/config/services.yml @@ -88,17 +88,6 @@ services: arguments: - WallabagCoreBundle:Tag - wallabag_core.registration_confirmed: - class: Wallabag\CoreBundle\EventListener\RegistrationConfirmedListener - arguments: - - "@doctrine.orm.entity_manager" - - "%wallabag_core.theme%" - - "%wallabag_core.items_on_page%" - - "%wallabag_core.rss_limit%" - - "%wallabag_core.language%" - tags: - - { name: kernel.event_subscriber } - wallabag_core.helper.entries_export: class: Wallabag\CoreBundle\Helper\EntriesExport arguments: @@ -119,3 +108,23 @@ services: class: Wallabag\CoreBundle\Helper\Redirect arguments: - "@router" + + wallabag_core.helper.prepare_pager_for_entries: + class: Wallabag\CoreBundle\Helper\PreparePagerForEntries + arguments: + - "@security.token_storage" + - "@router" + + wallabag_core.redis.client: + class: Predis\Client + arguments: + - + host: '%redis_host%' + port: '%redis_port%' + schema: tcp + + wallabag_core.exception_controller: + class: Wallabag\CoreBundle\Controller\ExceptionController + arguments: + - '@twig' + - '%kernel.debug%' diff --git a/src/Wallabag/CoreBundle/Resources/public/themes/_global/js/annotator.min.js b/src/Wallabag/CoreBundle/Resources/public/themes/_global/js/annotator.min.js deleted file mode 100644 index fdc35c69..00000000 --- a/src/Wallabag/CoreBundle/Resources/public/themes/_global/js/annotator.min.js +++ /dev/null @@ -1,23 +0,0 @@ -/* -** Annotator v2.0.0-alpha.3-0f076c7 -** https://github.com/okfn/annotator/ -** -** Copyright 2016, the Annotator project contributors. -** Dual licensed under the MIT and GPLv3 licenses. -** https://github.com/okfn/annotator/blob/master/LICENSE -** -** Built at: 2016-02-26 15:02:00Z -*/ -(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.annotator=f()}})(function(){var define,module,exports;return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o1){for(var i=1;i=0&&j=0},isEmptyObject:function(obj){var name;for(name in obj){return false}return true},isPlainObject:function(obj){var key;if(!obj||jQuery.type(obj)!=="object"||obj.nodeType||jQuery.isWindow(obj)){return false}try{if(obj.constructor&&!hasOwn.call(obj,"constructor")&&!hasOwn.call(obj.constructor.prototype,"isPrototypeOf")){return false}}catch(e){return false}if(!support.ownFirst){for(key in obj){return hasOwn.call(obj,key)}}for(key in obj){}return key===undefined||hasOwn.call(obj,key)},type:function(obj){if(obj==null){return obj+""}return typeof obj==="object"||typeof obj==="function"?class2type[toString.call(obj)]||"object":typeof obj},globalEval:function(data){if(data&&jQuery.trim(data)){(window.execScript||function(data){window["eval"].call(window,data)})(data)}},camelCase:function(string){return string.replace(rmsPrefix,"ms-").replace(rdashAlpha,fcamelCase)},nodeName:function(elem,name){return elem.nodeName&&elem.nodeName.toLowerCase()===name.toLowerCase()},each:function(obj,callback){var length,i=0;if(isArrayLike(obj)){length=obj.length;for(;i0&&length-1 in obj}var Sizzle=function(window){var i,support,Expr,getText,isXML,tokenize,compile,select,outermostContext,sortInput,hasDuplicate,setDocument,document,docElem,documentIsHTML,rbuggyQSA,rbuggyMatches,matches,contains,expando="sizzle"+1*new Date,preferredDoc=window.document,dirruns=0,done=0,classCache=createCache(),tokenCache=createCache(),compilerCache=createCache(),sortOrder=function(a,b){if(a===b){hasDuplicate=true}return 0},MAX_NEGATIVE=1<<31,hasOwn={}.hasOwnProperty,arr=[],pop=arr.pop,push_native=arr.push,push=arr.push,slice=arr.slice,indexOf=function(list,elem){var i=0,len=list.length;for(;i+~]|"+whitespace+")"+whitespace+"*"),rattributeQuotes=new RegExp("="+whitespace+"*([^\\]'\"]*?)"+whitespace+"*\\]","g"),rpseudo=new RegExp(pseudos),ridentifier=new RegExp("^"+identifier+"$"),matchExpr={ID:new RegExp("^#("+identifier+")"),CLASS:new RegExp("^\\.("+identifier+")"),TAG:new RegExp("^("+identifier+"|[*])"),ATTR:new RegExp("^"+attributes),PSEUDO:new RegExp("^"+pseudos),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+whitespace+"*(even|odd|(([+-]|)(\\d*)n|)"+whitespace+"*(?:([+-]|)"+whitespace+"*(\\d+)|))"+whitespace+"*\\)|)","i"),bool:new RegExp("^(?:"+booleans+")$","i"),needsContext:new RegExp("^"+whitespace+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+whitespace+"*((?:-\\d)?\\d*)"+whitespace+"*\\)|)(?=[^-]|$)","i")},rinputs=/^(?:input|select|textarea|button)$/i,rheader=/^h\d$/i,rnative=/^[^{]+\{\s*\[native \w/,rquickExpr=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,rsibling=/[+~]/,rescape=/'|\\/g,runescape=new RegExp("\\\\([\\da-f]{1,6}"+whitespace+"?|("+whitespace+")|.)","ig"),funescape=function(_,escaped,escapedWhitespace){var high="0x"+escaped-65536;return high!==high||escapedWhitespace?escaped:high<0?String.fromCharCode(high+65536):String.fromCharCode(high>>10|55296,high&1023|56320)},unloadHandler=function(){setDocument()};try{push.apply(arr=slice.call(preferredDoc.childNodes),preferredDoc.childNodes);arr[preferredDoc.childNodes.length].nodeType}catch(e){push={apply:arr.length?function(target,els){push_native.apply(target,slice.call(els))}:function(target,els){var j=target.length,i=0;while(target[j++]=els[i++]){}target.length=j-1}}}function Sizzle(selector,context,results,seed){var m,i,elem,nid,nidselect,match,groups,newSelector,newContext=context&&context.ownerDocument,nodeType=context?context.nodeType:9;results=results||[];if(typeof selector!=="string"||!selector||nodeType!==1&&nodeType!==9&&nodeType!==11){return results}if(!seed){if((context?context.ownerDocument||context:preferredDoc)!==document){setDocument(context)}context=context||document;if(documentIsHTML){if(nodeType!==11&&(match=rquickExpr.exec(selector))){if(m=match[1]){if(nodeType===9){if(elem=context.getElementById(m)){if(elem.id===m){results.push(elem);return results}}else{return results}}else{if(newContext&&(elem=newContext.getElementById(m))&&contains(context,elem)&&elem.id===m){results.push(elem);return results}}}else if(match[2]){push.apply(results,context.getElementsByTagName(selector));return results}else if((m=match[3])&&support.getElementsByClassName&&context.getElementsByClassName){push.apply(results,context.getElementsByClassName(m));return results}}if(support.qsa&&!compilerCache[selector+" "]&&(!rbuggyQSA||!rbuggyQSA.test(selector))){if(nodeType!==1){newContext=context;newSelector=selector}else if(context.nodeName.toLowerCase()!=="object"){if(nid=context.getAttribute("id")){nid=nid.replace(rescape,"\\$&")}else{context.setAttribute("id",nid=expando)}groups=tokenize(selector);i=groups.length;nidselect=ridentifier.test(nid)?"#"+nid:"[id='"+nid+"']";while(i--){groups[i]=nidselect+" "+toSelector(groups[i])}newSelector=groups.join(",");newContext=rsibling.test(selector)&&testContext(context.parentNode)||context}if(newSelector){try{push.apply(results,newContext.querySelectorAll(newSelector));return results}catch(qsaError){}finally{if(nid===expando){context.removeAttribute("id")}}}}}}return select(selector.replace(rtrim,"$1"),context,results,seed)}function createCache(){var keys=[];function cache(key,value){if(keys.push(key+" ")>Expr.cacheLength){delete cache[keys.shift()]}return cache[key+" "]=value}return cache}function markFunction(fn){fn[expando]=true; -return fn}function assert(fn){var div=document.createElement("div");try{return!!fn(div)}catch(e){return false}finally{if(div.parentNode){div.parentNode.removeChild(div)}div=null}}function addHandle(attrs,handler){var arr=attrs.split("|"),i=arr.length;while(i--){Expr.attrHandle[arr[i]]=handler}}function siblingCheck(a,b){var cur=b&&a,diff=cur&&a.nodeType===1&&b.nodeType===1&&(~b.sourceIndex||MAX_NEGATIVE)-(~a.sourceIndex||MAX_NEGATIVE);if(diff){return diff}if(cur){while(cur=cur.nextSibling){if(cur===b){return-1}}}return a?1:-1}function createInputPseudo(type){return function(elem){var name=elem.nodeName.toLowerCase();return name==="input"&&elem.type===type}}function createButtonPseudo(type){return function(elem){var name=elem.nodeName.toLowerCase();return(name==="input"||name==="button")&&elem.type===type}}function createPositionalPseudo(fn){return markFunction(function(argument){argument=+argument;return markFunction(function(seed,matches){var j,matchIndexes=fn([],seed.length,argument),i=matchIndexes.length;while(i--){if(seed[j=matchIndexes[i]]){seed[j]=!(matches[j]=seed[j])}}})})}function testContext(context){return context&&typeof context.getElementsByTagName!=="undefined"&&context}support=Sizzle.support={};isXML=Sizzle.isXML=function(elem){var documentElement=elem&&(elem.ownerDocument||elem).documentElement;return documentElement?documentElement.nodeName!=="HTML":false};setDocument=Sizzle.setDocument=function(node){var hasCompare,parent,doc=node?node.ownerDocument||node:preferredDoc;if(doc===document||doc.nodeType!==9||!doc.documentElement){return document}document=doc;docElem=document.documentElement;documentIsHTML=!isXML(document);if((parent=document.defaultView)&&parent.top!==parent){if(parent.addEventListener){parent.addEventListener("unload",unloadHandler,false)}else if(parent.attachEvent){parent.attachEvent("onunload",unloadHandler)}}support.attributes=assert(function(div){div.className="i";return!div.getAttribute("className")});support.getElementsByTagName=assert(function(div){div.appendChild(document.createComment(""));return!div.getElementsByTagName("*").length});support.getElementsByClassName=rnative.test(document.getElementsByClassName);support.getById=assert(function(div){docElem.appendChild(div).id=expando;return!document.getElementsByName||!document.getElementsByName(expando).length});if(support.getById){Expr.find["ID"]=function(id,context){if(typeof context.getElementById!=="undefined"&&documentIsHTML){var m=context.getElementById(id);return m?[m]:[]}};Expr.filter["ID"]=function(id){var attrId=id.replace(runescape,funescape);return function(elem){return elem.getAttribute("id")===attrId}}}else{delete Expr.find["ID"];Expr.filter["ID"]=function(id){var attrId=id.replace(runescape,funescape);return function(elem){var node=typeof elem.getAttributeNode!=="undefined"&&elem.getAttributeNode("id");return node&&node.value===attrId}}}Expr.find["TAG"]=support.getElementsByTagName?function(tag,context){if(typeof context.getElementsByTagName!=="undefined"){return context.getElementsByTagName(tag)}else if(support.qsa){return context.querySelectorAll(tag)}}:function(tag,context){var elem,tmp=[],i=0,results=context.getElementsByTagName(tag);if(tag==="*"){while(elem=results[i++]){if(elem.nodeType===1){tmp.push(elem)}}return tmp}return results};Expr.find["CLASS"]=support.getElementsByClassName&&function(className,context){if(typeof context.getElementsByClassName!=="undefined"&&documentIsHTML){return context.getElementsByClassName(className)}};rbuggyMatches=[];rbuggyQSA=[];if(support.qsa=rnative.test(document.querySelectorAll)){assert(function(div){docElem.appendChild(div).innerHTML=""+"";if(div.querySelectorAll("[msallowcapture^='']").length){rbuggyQSA.push("[*^$]="+whitespace+"*(?:''|\"\")")}if(!div.querySelectorAll("[selected]").length){rbuggyQSA.push("\\["+whitespace+"*(?:value|"+booleans+")")}if(!div.querySelectorAll("[id~="+expando+"-]").length){rbuggyQSA.push("~=")}if(!div.querySelectorAll(":checked").length){rbuggyQSA.push(":checked")}if(!div.querySelectorAll("a#"+expando+"+*").length){rbuggyQSA.push(".#.+[+~]")}});assert(function(div){var input=document.createElement("input");input.setAttribute("type","hidden");div.appendChild(input).setAttribute("name","D");if(div.querySelectorAll("[name=d]").length){rbuggyQSA.push("name"+whitespace+"*[*^$|!~]?=")}if(!div.querySelectorAll(":enabled").length){rbuggyQSA.push(":enabled",":disabled")}div.querySelectorAll("*,:x");rbuggyQSA.push(",.*:")})}if(support.matchesSelector=rnative.test(matches=docElem.matches||docElem.webkitMatchesSelector||docElem.mozMatchesSelector||docElem.oMatchesSelector||docElem.msMatchesSelector)){assert(function(div){support.disconnectedMatch=matches.call(div,"div");matches.call(div,"[s!='']:x");rbuggyMatches.push("!=",pseudos)})}rbuggyQSA=rbuggyQSA.length&&new RegExp(rbuggyQSA.join("|"));rbuggyMatches=rbuggyMatches.length&&new RegExp(rbuggyMatches.join("|"));hasCompare=rnative.test(docElem.compareDocumentPosition);contains=hasCompare||rnative.test(docElem.contains)?function(a,b){var adown=a.nodeType===9?a.documentElement:a,bup=b&&b.parentNode;return a===bup||!!(bup&&bup.nodeType===1&&(adown.contains?adown.contains(bup):a.compareDocumentPosition&&a.compareDocumentPosition(bup)&16))}:function(a,b){if(b){while(b=b.parentNode){if(b===a){return true}}}return false};sortOrder=hasCompare?function(a,b){if(a===b){hasDuplicate=true;return 0}var compare=!a.compareDocumentPosition-!b.compareDocumentPosition;if(compare){return compare}compare=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1;if(compare&1||!support.sortDetached&&b.compareDocumentPosition(a)===compare){if(a===document||a.ownerDocument===preferredDoc&&contains(preferredDoc,a)){return-1}if(b===document||b.ownerDocument===preferredDoc&&contains(preferredDoc,b)){return 1}return sortInput?indexOf(sortInput,a)-indexOf(sortInput,b):0}return compare&4?-1:1}:function(a,b){if(a===b){hasDuplicate=true;return 0}var cur,i=0,aup=a.parentNode,bup=b.parentNode,ap=[a],bp=[b];if(!aup||!bup){return a===document?-1:b===document?1:aup?-1:bup?1:sortInput?indexOf(sortInput,a)-indexOf(sortInput,b):0}else if(aup===bup){return siblingCheck(a,b)}cur=a;while(cur=cur.parentNode){ap.unshift(cur)}cur=b;while(cur=cur.parentNode){bp.unshift(cur)}while(ap[i]===bp[i]){i++}return i?siblingCheck(ap[i],bp[i]):ap[i]===preferredDoc?-1:bp[i]===preferredDoc?1:0};return document};Sizzle.matches=function(expr,elements){return Sizzle(expr,null,null,elements)};Sizzle.matchesSelector=function(elem,expr){if((elem.ownerDocument||elem)!==document){setDocument(elem)}expr=expr.replace(rattributeQuotes,"='$1']");if(support.matchesSelector&&documentIsHTML&&!compilerCache[expr+" "]&&(!rbuggyMatches||!rbuggyMatches.test(expr))&&(!rbuggyQSA||!rbuggyQSA.test(expr))){try{var ret=matches.call(elem,expr);if(ret||support.disconnectedMatch||elem.document&&elem.document.nodeType!==11){return ret}}catch(e){}}return Sizzle(expr,document,null,[elem]).length>0};Sizzle.contains=function(context,elem){if((context.ownerDocument||context)!==document){setDocument(context)}return contains(context,elem)};Sizzle.attr=function(elem,name){if((elem.ownerDocument||elem)!==document){setDocument(elem)}var fn=Expr.attrHandle[name.toLowerCase()],val=fn&&hasOwn.call(Expr.attrHandle,name.toLowerCase())?fn(elem,name,!documentIsHTML):undefined;return val!==undefined?val:support.attributes||!documentIsHTML?elem.getAttribute(name):(val=elem.getAttributeNode(name))&&val.specified?val.value:null};Sizzle.error=function(msg){throw new Error("Syntax error, unrecognized expression: "+msg)};Sizzle.uniqueSort=function(results){var elem,duplicates=[],j=0,i=0;hasDuplicate=!support.detectDuplicates;sortInput=!support.sortStable&&results.slice(0);results.sort(sortOrder);if(hasDuplicate){while(elem=results[i++]){if(elem===results[i]){j=duplicates.push(i)}}while(j--){results.splice(duplicates[j],1)}}sortInput=null;return results};getText=Sizzle.getText=function(elem){var node,ret="",i=0,nodeType=elem.nodeType;if(!nodeType){while(node=elem[i++]){ret+=getText(node)}}else if(nodeType===1||nodeType===9||nodeType===11){if(typeof elem.textContent==="string"){return elem.textContent}else{for(elem=elem.firstChild;elem;elem=elem.nextSibling){ret+=getText(elem)}}}else if(nodeType===3||nodeType===4){return elem.nodeValue}return ret};Expr=Sizzle.selectors={cacheLength:50,createPseudo:markFunction,match:matchExpr,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:true}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:true},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(match){match[1]=match[1].replace(runescape,funescape);match[3]=(match[3]||match[4]||match[5]||"").replace(runescape,funescape);if(match[2]==="~="){match[3]=" "+match[3]+" "}return match.slice(0,4)},CHILD:function(match){match[1]=match[1].toLowerCase();if(match[1].slice(0,3)==="nth"){if(!match[3]){Sizzle.error(match[0])}match[4]=+(match[4]?match[5]+(match[6]||1):2*(match[3]==="even"||match[3]==="odd"));match[5]=+(match[7]+match[8]||match[3]==="odd")}else if(match[3]){Sizzle.error(match[0])}return match},PSEUDO:function(match){var excess,unquoted=!match[6]&&match[2];if(matchExpr["CHILD"].test(match[0])){return null}if(match[3]){match[2]=match[4]||match[5]||""}else if(unquoted&&rpseudo.test(unquoted)&&(excess=tokenize(unquoted,true))&&(excess=unquoted.indexOf(")",unquoted.length-excess)-unquoted.length)){match[0]=match[0].slice(0,excess);match[2]=unquoted.slice(0,excess)}return match.slice(0,3)}},filter:{TAG:function(nodeNameSelector){var nodeName=nodeNameSelector.replace(runescape,funescape).toLowerCase();return nodeNameSelector==="*"?function(){return true}:function(elem){return elem.nodeName&&elem.nodeName.toLowerCase()===nodeName}},CLASS:function(className){var pattern=classCache[className+" "];return pattern||(pattern=new RegExp("(^|"+whitespace+")"+className+"("+whitespace+"|$)"))&&classCache(className,function(elem){return pattern.test(typeof elem.className==="string"&&elem.className||typeof elem.getAttribute!=="undefined"&&elem.getAttribute("class")||"")})},ATTR:function(name,operator,check){return function(elem){var result=Sizzle.attr(elem,name);if(result==null){return operator==="!="}if(!operator){return true}result+="";return operator==="="?result===check:operator==="!="?result!==check:operator==="^="?check&&result.indexOf(check)===0:operator==="*="?check&&result.indexOf(check)>-1:operator==="$="?check&&result.slice(-check.length)===check:operator==="~="?(" "+result.replace(rwhitespace," ")+" ").indexOf(check)>-1:operator==="|="?result===check||result.slice(0,check.length+1)===check+"-":false}},CHILD:function(type,what,argument,first,last){var simple=type.slice(0,3)!=="nth",forward=type.slice(-4)!=="last",ofType=what==="of-type";return first===1&&last===0?function(elem){return!!elem.parentNode}:function(elem,context,xml){var cache,uniqueCache,outerCache,node,nodeIndex,start,dir=simple!==forward?"nextSibling":"previousSibling",parent=elem.parentNode,name=ofType&&elem.nodeName.toLowerCase(),useCache=!xml&&!ofType,diff=false;if(parent){if(simple){while(dir){node=elem;while(node=node[dir]){if(ofType?node.nodeName.toLowerCase()===name:node.nodeType===1){return false}}start=dir=type==="only"&&!start&&"nextSibling"}return true}start=[forward?parent.firstChild:parent.lastChild];if(forward&&useCache){node=parent;outerCache=node[expando]||(node[expando]={});uniqueCache=outerCache[node.uniqueID]||(outerCache[node.uniqueID]={});cache=uniqueCache[type]||[];nodeIndex=cache[0]===dirruns&&cache[1];diff=nodeIndex&&cache[2];node=nodeIndex&&parent.childNodes[nodeIndex];while(node=++nodeIndex&&node&&node[dir]||(diff=nodeIndex=0)||start.pop()){if(node.nodeType===1&&++diff&&node===elem){uniqueCache[type]=[dirruns,nodeIndex,diff];break}}}else{if(useCache){node=elem;outerCache=node[expando]||(node[expando]={});uniqueCache=outerCache[node.uniqueID]||(outerCache[node.uniqueID]={});cache=uniqueCache[type]||[];nodeIndex=cache[0]===dirruns&&cache[1];diff=nodeIndex}if(diff===false){while(node=++nodeIndex&&node&&node[dir]||(diff=nodeIndex=0)||start.pop()){if((ofType?node.nodeName.toLowerCase()===name:node.nodeType===1)&&++diff){if(useCache){outerCache=node[expando]||(node[expando]={});uniqueCache=outerCache[node.uniqueID]||(outerCache[node.uniqueID]={});uniqueCache[type]=[dirruns,diff]}if(node===elem){break}}}}}diff-=last;return diff===first||diff%first===0&&diff/first>=0}}},PSEUDO:function(pseudo,argument){var args,fn=Expr.pseudos[pseudo]||Expr.setFilters[pseudo.toLowerCase()]||Sizzle.error("unsupported pseudo: "+pseudo);if(fn[expando]){return fn(argument)}if(fn.length>1){args=[pseudo,pseudo,"",argument];return Expr.setFilters.hasOwnProperty(pseudo.toLowerCase())?markFunction(function(seed,matches){var idx,matched=fn(seed,argument),i=matched.length;while(i--){idx=indexOf(seed,matched[i]);seed[idx]=!(matches[idx]=matched[i])}}):function(elem){return fn(elem,0,args)}}return fn}},pseudos:{not:markFunction(function(selector){var input=[],results=[],matcher=compile(selector.replace(rtrim,"$1"));return matcher[expando]?markFunction(function(seed,matches,context,xml){var elem,unmatched=matcher(seed,null,xml,[]),i=seed.length;while(i--){if(elem=unmatched[i]){seed[i]=!(matches[i]=elem)}}}):function(elem,context,xml){input[0]=elem;matcher(input,null,xml,results);input[0]=null;return!results.pop()}}),has:markFunction(function(selector){return function(elem){return Sizzle(selector,elem).length>0}}),contains:markFunction(function(text){text=text.replace(runescape,funescape);return function(elem){return(elem.textContent||elem.innerText||getText(elem)).indexOf(text)>-1}}),lang:markFunction(function(lang){if(!ridentifier.test(lang||"")){Sizzle.error("unsupported lang: "+lang)}lang=lang.replace(runescape,funescape).toLowerCase();return function(elem){var elemLang;do{if(elemLang=documentIsHTML?elem.lang:elem.getAttribute("xml:lang")||elem.getAttribute("lang")){elemLang=elemLang.toLowerCase();return elemLang===lang||elemLang.indexOf(lang+"-")===0}}while((elem=elem.parentNode)&&elem.nodeType===1);return false}}),target:function(elem){var hash=window.location&&window.location.hash;return hash&&hash.slice(1)===elem.id},root:function(elem){return elem===docElem},focus:function(elem){return elem===document.activeElement&&(!document.hasFocus||document.hasFocus())&&!!(elem.type||elem.href||~elem.tabIndex)},enabled:function(elem){return elem.disabled===false},disabled:function(elem){return elem.disabled===true},checked:function(elem){var nodeName=elem.nodeName.toLowerCase();return nodeName==="input"&&!!elem.checked||nodeName==="option"&&!!elem.selected},selected:function(elem){if(elem.parentNode){elem.parentNode.selectedIndex}return elem.selected===true},empty:function(elem){for(elem=elem.firstChild;elem;elem=elem.nextSibling){if(elem.nodeType<6){return false}}return true},parent:function(elem){return!Expr.pseudos["empty"](elem)},header:function(elem){return rheader.test(elem.nodeName)},input:function(elem){return rinputs.test(elem.nodeName)},button:function(elem){var name=elem.nodeName.toLowerCase();return name==="input"&&elem.type==="button"||name==="button"},text:function(elem){var attr;return elem.nodeName.toLowerCase()==="input"&&elem.type==="text"&&((attr=elem.getAttribute("type"))==null||attr.toLowerCase()==="text")},first:createPositionalPseudo(function(){return[0]}),last:createPositionalPseudo(function(matchIndexes,length){return[length-1]}),eq:createPositionalPseudo(function(matchIndexes,length,argument){return[argument<0?argument+length:argument]}),even:createPositionalPseudo(function(matchIndexes,length){var i=0;for(;i=0;){matchIndexes.push(i)}return matchIndexes}),gt:createPositionalPseudo(function(matchIndexes,length,argument){var i=argument<0?argument+length:argument;for(;++i1?function(elem,context,xml){var i=matchers.length;while(i--){if(!matchers[i](elem,context,xml)){return false}}return true}:matchers[0]}function multipleContexts(selector,contexts,results){var i=0,len=contexts.length;for(;i-1){seed[temp]=!(results[temp]=elem)}}}}else{matcherOut=condense(matcherOut===results?matcherOut.splice(preexisting,matcherOut.length):matcherOut);if(postFinder){postFinder(null,results,matcherOut,xml)}else{push.apply(results,matcherOut)}}})}function matcherFromTokens(tokens){var checkContext,matcher,j,len=tokens.length,leadingRelative=Expr.relative[tokens[0].type],implicitRelative=leadingRelative||Expr.relative[" "],i=leadingRelative?1:0,matchContext=addCombinator(function(elem){return elem===checkContext},implicitRelative,true),matchAnyContext=addCombinator(function(elem){return indexOf(checkContext,elem)>-1},implicitRelative,true),matchers=[function(elem,context,xml){var ret=!leadingRelative&&(xml||context!==outermostContext)||((checkContext=context).nodeType?matchContext(elem,context,xml):matchAnyContext(elem,context,xml));checkContext=null;return ret}];for(;i1&&elementMatcher(matchers),i>1&&toSelector(tokens.slice(0,i-1).concat({value:tokens[i-2].type===" "?"*":""})).replace(rtrim,"$1"),matcher,i0,byElement=elementMatchers.length>0,superMatcher=function(seed,context,xml,results,outermost){var elem,j,matcher,matchedCount=0,i="0",unmatched=seed&&[],setMatched=[],contextBackup=outermostContext,elems=seed||byElement&&Expr.find["TAG"]("*",outermost),dirrunsUnique=dirruns+=contextBackup==null?1:Math.random()||.1,len=elems.length;if(outermost){outermostContext=context===document||context||outermost}for(;i!==len&&(elem=elems[i])!=null;i++){if(byElement&&elem){j=0;if(!context&&elem.ownerDocument!==document){setDocument(elem);xml=!documentIsHTML}while(matcher=elementMatchers[j++]){if(matcher(elem,context||document,xml)){results.push(elem);break}}if(outermost){dirruns=dirrunsUnique}}if(bySet){if(elem=!matcher&&elem){matchedCount--}if(seed){unmatched.push(elem)}}}matchedCount+=i;if(bySet&&i!==matchedCount){j=0;while(matcher=setMatchers[j++]){matcher(unmatched,setMatched,context,xml)}if(seed){if(matchedCount>0){while(i--){if(!(unmatched[i]||setMatched[i])){setMatched[i]=pop.call(results)}}}setMatched=condense(setMatched)}push.apply(results,setMatched);if(outermost&&!seed&&setMatched.length>0&&matchedCount+setMatchers.length>1){Sizzle.uniqueSort(results)}}if(outermost){dirruns=dirrunsUnique;outermostContext=contextBackup}return unmatched};return bySet?markFunction(superMatcher):superMatcher}compile=Sizzle.compile=function(selector,match){var i,setMatchers=[],elementMatchers=[],cached=compilerCache[selector+" "];if(!cached){if(!match){match=tokenize(selector)}i=match.length;while(i--){cached=matcherFromTokens(match[i]);if(cached[expando]){setMatchers.push(cached)}else{elementMatchers.push(cached)}}cached=compilerCache(selector,matcherFromGroupMatchers(elementMatchers,setMatchers));cached.selector=selector}return cached};select=Sizzle.select=function(selector,context,results,seed){var i,tokens,token,type,find,compiled=typeof selector==="function"&&selector,match=!seed&&tokenize(selector=compiled.selector||selector);results=results||[];if(match.length===1){tokens=match[0]=match[0].slice(0);if(tokens.length>2&&(token=tokens[0]).type==="ID"&&support.getById&&context.nodeType===9&&documentIsHTML&&Expr.relative[tokens[1].type]){context=(Expr.find["ID"](token.matches[0].replace(runescape,funescape),context)||[])[0];if(!context){return results}else if(compiled){context=context.parentNode}selector=selector.slice(tokens.shift().value.length)}i=matchExpr["needsContext"].test(selector)?0:tokens.length;while(i--){token=tokens[i];if(Expr.relative[type=token.type]){break}if(find=Expr.find[type]){if(seed=find(token.matches[0].replace(runescape,funescape),rsibling.test(tokens[0].type)&&testContext(context.parentNode)||context)){tokens.splice(i,1);selector=seed.length&&toSelector(tokens);if(!selector){push.apply(results,seed);return results}break}}}}(compiled||compile(selector,match))(seed,context,!documentIsHTML,results,!context||rsibling.test(selector)&&testContext(context.parentNode)||context);return results};support.sortStable=expando.split("").sort(sortOrder).join("")===expando;support.detectDuplicates=!!hasDuplicate;setDocument();support.sortDetached=assert(function(div1){return div1.compareDocumentPosition(document.createElement("div"))&1});if(!assert(function(div){div.innerHTML="";return div.firstChild.getAttribute("href")==="#"})){addHandle("type|href|height|width",function(elem,name,isXML){if(!isXML){return elem.getAttribute(name,name.toLowerCase()==="type"?1:2)}})}if(!support.attributes||!assert(function(div){div.innerHTML="";div.firstChild.setAttribute("value","");return div.firstChild.getAttribute("value")===""})){addHandle("value",function(elem,name,isXML){if(!isXML&&elem.nodeName.toLowerCase()==="input"){return elem.defaultValue}})}if(!assert(function(div){return div.getAttribute("disabled")==null})){addHandle(booleans,function(elem,name,isXML){var val;if(!isXML){return elem[name]===true?name.toLowerCase():(val=elem.getAttributeNode(name))&&val.specified?val.value:null}})}return Sizzle}(window);jQuery.find=Sizzle;jQuery.expr=Sizzle.selectors;jQuery.expr[":"]=jQuery.expr.pseudos;jQuery.uniqueSort=jQuery.unique=Sizzle.uniqueSort;jQuery.text=Sizzle.getText;jQuery.isXMLDoc=Sizzle.isXML;jQuery.contains=Sizzle.contains;var dir=function(elem,dir,until){var matched=[],truncate=until!==undefined;while((elem=elem[dir])&&elem.nodeType!==9){if(elem.nodeType===1){if(truncate&&jQuery(elem).is(until)){break}matched.push(elem)}}return matched};var siblings=function(n,elem){var matched=[];for(;n;n=n.nextSibling){if(n.nodeType===1&&n!==elem){matched.push(n)}}return matched};var rneedsContext=jQuery.expr.match.needsContext;var rsingleTag=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/;var risSimple=/^.[^:#\[\.,]*$/;function winnow(elements,qualifier,not){if(jQuery.isFunction(qualifier)){return jQuery.grep(elements,function(elem,i){return!!qualifier.call(elem,i,elem)!==not})}if(qualifier.nodeType){return jQuery.grep(elements,function(elem){return elem===qualifier!==not})}if(typeof qualifier==="string"){if(risSimple.test(qualifier)){return jQuery.filter(qualifier,elements,not)}qualifier=jQuery.filter(qualifier,elements)}return jQuery.grep(elements,function(elem){return jQuery.inArray(elem,qualifier)>-1!==not})}jQuery.filter=function(expr,elems,not){var elem=elems[0];if(not){expr=":not("+expr+")"}return elems.length===1&&elem.nodeType===1?jQuery.find.matchesSelector(elem,expr)?[elem]:[]:jQuery.find.matches(expr,jQuery.grep(elems,function(elem){return elem.nodeType===1}))};jQuery.fn.extend({find:function(selector){var i,ret=[],self=this,len=self.length;if(typeof selector!=="string"){return this.pushStack(jQuery(selector).filter(function(){for(i=0;i1?jQuery.unique(ret):ret);ret.selector=this.selector?this.selector+" "+selector:selector;return ret},filter:function(selector){return this.pushStack(winnow(this,selector||[],false))},not:function(selector){return this.pushStack(winnow(this,selector||[],true))},is:function(selector){return!!winnow(this,typeof selector==="string"&&rneedsContext.test(selector)?jQuery(selector):selector||[],false).length}});var rootjQuery,rquickExpr=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,init=jQuery.fn.init=function(selector,context,root){var match,elem;if(!selector){return this}root=root||rootjQuery;if(typeof selector==="string"){if(selector.charAt(0)==="<"&&selector.charAt(selector.length-1)===">"&&selector.length>=3){match=[null,selector,null]}else{match=rquickExpr.exec(selector)}if(match&&(match[1]||!context)){if(match[1]){context=context instanceof jQuery?context[0]:context;jQuery.merge(this,jQuery.parseHTML(match[1],context&&context.nodeType?context.ownerDocument||context:document,true));if(rsingleTag.test(match[1])&&jQuery.isPlainObject(context)){for(match in context){if(jQuery.isFunction(this[match])){this[match](context[match])}else{this.attr(match,context[match])}}}return this}else{elem=document.getElementById(match[2]);if(elem&&elem.parentNode){if(elem.id!==match[2]){return rootjQuery.find(selector)}this.length=1;this[0]=elem}this.context=document;this.selector=selector;return this}}else if(!context||context.jquery){return(context||root).find(selector)}else{return this.constructor(context).find(selector)}}else if(selector.nodeType){this.context=this[0]=selector;this.length=1;return this}else if(jQuery.isFunction(selector)){return typeof root.ready!=="undefined"?root.ready(selector):selector(jQuery)}if(selector.selector!==undefined){this.selector=selector.selector;this.context=selector.context}return jQuery.makeArray(selector,this)};init.prototype=jQuery.fn;rootjQuery=jQuery(document);var rparentsprev=/^(?:parents|prev(?:Until|All))/,guaranteedUnique={children:true,contents:true,next:true,prev:true};jQuery.fn.extend({has:function(target){var i,targets=jQuery(target,this),len=targets.length;return this.filter(function(){for(i=0;i-1:cur.nodeType===1&&jQuery.find.matchesSelector(cur,selectors))){matched.push(cur);break}}}return this.pushStack(matched.length>1?jQuery.uniqueSort(matched):matched)},index:function(elem){if(!elem){return this[0]&&this[0].parentNode?this.first().prevAll().length:-1}if(typeof elem==="string"){return jQuery.inArray(this[0],jQuery(elem))}return jQuery.inArray(elem.jquery?elem[0]:elem,this)},add:function(selector,context){return this.pushStack(jQuery.uniqueSort(jQuery.merge(this.get(),jQuery(selector,context))))},addBack:function(selector){return this.add(selector==null?this.prevObject:this.prevObject.filter(selector))}});function sibling(cur,dir){do{cur=cur[dir]}while(cur&&cur.nodeType!==1);return cur}jQuery.each({parent:function(elem){var parent=elem.parentNode;return parent&&parent.nodeType!==11?parent:null},parents:function(elem){return dir(elem,"parentNode")},parentsUntil:function(elem,i,until){return dir(elem,"parentNode",until)},next:function(elem){return sibling(elem,"nextSibling")},prev:function(elem){return sibling(elem,"previousSibling")},nextAll:function(elem){return dir(elem,"nextSibling")},prevAll:function(elem){return dir(elem,"previousSibling")},nextUntil:function(elem,i,until){return dir(elem,"nextSibling",until)},prevUntil:function(elem,i,until){return dir(elem,"previousSibling",until)},siblings:function(elem){return siblings((elem.parentNode||{}).firstChild,elem)},children:function(elem){return siblings(elem.firstChild)},contents:function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.merge([],elem.childNodes)}},function(name,fn){jQuery.fn[name]=function(until,selector){var ret=jQuery.map(this,fn,until);if(name.slice(-5)!=="Until"){selector=until}if(selector&&typeof selector==="string"){ret=jQuery.filter(selector,ret)}if(this.length>1){if(!guaranteedUnique[name]){ret=jQuery.uniqueSort(ret)}if(rparentsprev.test(name)){ret=ret.reverse()}}return this.pushStack(ret)}});var rnotwhite=/\S+/g;function createOptions(options){ -var object={};jQuery.each(options.match(rnotwhite)||[],function(_,flag){object[flag]=true});return object}jQuery.Callbacks=function(options){options=typeof options==="string"?createOptions(options):jQuery.extend({},options);var firing,memory,fired,locked,list=[],queue=[],firingIndex=-1,fire=function(){locked=options.once;fired=firing=true;for(;queue.length;firingIndex=-1){memory=queue.shift();while(++firingIndex-1){list.splice(index,1);if(index<=firingIndex){firingIndex--}}});return this},has:function(fn){return fn?jQuery.inArray(fn,list)>-1:list.length>0},empty:function(){if(list){list=[]}return this},disable:function(){locked=queue=[];list=memory="";return this},disabled:function(){return!list},lock:function(){locked=true;if(!memory){self.disable()}return this},locked:function(){return!!locked},fireWith:function(context,args){if(!locked){args=args||[];args=[context,args.slice?args.slice():args];queue.push(args);if(!firing){fire()}}return this},fire:function(){self.fireWith(this,arguments);return this},fired:function(){return!!fired}};return self};jQuery.extend({Deferred:function(func){var tuples=[["resolve","done",jQuery.Callbacks("once memory"),"resolved"],["reject","fail",jQuery.Callbacks("once memory"),"rejected"],["notify","progress",jQuery.Callbacks("memory")]],state="pending",promise={state:function(){return state},always:function(){deferred.done(arguments).fail(arguments);return this},then:function(){var fns=arguments;return jQuery.Deferred(function(newDefer){jQuery.each(tuples,function(i,tuple){var fn=jQuery.isFunction(fns[i])&&fns[i];deferred[tuple[1]](function(){var returned=fn&&fn.apply(this,arguments);if(returned&&jQuery.isFunction(returned.promise)){returned.promise().progress(newDefer.notify).done(newDefer.resolve).fail(newDefer.reject)}else{newDefer[tuple[0]+"With"](this===promise?newDefer.promise():this,fn?[returned]:arguments)}})});fns=null}).promise()},promise:function(obj){return obj!=null?jQuery.extend(obj,promise):promise}},deferred={};promise.pipe=promise.then;jQuery.each(tuples,function(i,tuple){var list=tuple[2],stateString=tuple[3];promise[tuple[1]]=list.add;if(stateString){list.add(function(){state=stateString},tuples[i^1][2].disable,tuples[2][2].lock)}deferred[tuple[0]]=function(){deferred[tuple[0]+"With"](this===deferred?promise:this,arguments);return this};deferred[tuple[0]+"With"]=list.fireWith});promise.promise(deferred);if(func){func.call(deferred,deferred)}return deferred},when:function(subordinate){var i=0,resolveValues=slice.call(arguments),length=resolveValues.length,remaining=length!==1||subordinate&&jQuery.isFunction(subordinate.promise)?length:0,deferred=remaining===1?subordinate:jQuery.Deferred(),updateFunc=function(i,contexts,values){return function(value){contexts[i]=this;values[i]=arguments.length>1?slice.call(arguments):value;if(values===progressValues){deferred.notifyWith(contexts,values)}else if(!--remaining){deferred.resolveWith(contexts,values)}}},progressValues,progressContexts,resolveContexts;if(length>1){progressValues=new Array(length);progressContexts=new Array(length);resolveContexts=new Array(length);for(;i0){return}readyList.resolveWith(document,[jQuery]);if(jQuery.fn.triggerHandler){jQuery(document).triggerHandler("ready");jQuery(document).off("ready")}}});function detach(){if(document.addEventListener){document.removeEventListener("DOMContentLoaded",completed);window.removeEventListener("load",completed)}else{document.detachEvent("onreadystatechange",completed);window.detachEvent("onload",completed)}}function completed(){if(document.addEventListener||window.event.type==="load"||document.readyState==="complete"){detach();jQuery.ready()}}jQuery.ready.promise=function(obj){if(!readyList){readyList=jQuery.Deferred();if(document.readyState==="complete"||document.readyState!=="loading"&&!document.documentElement.doScroll){window.setTimeout(jQuery.ready)}else if(document.addEventListener){document.addEventListener("DOMContentLoaded",completed);window.addEventListener("load",completed)}else{document.attachEvent("onreadystatechange",completed);window.attachEvent("onload",completed);var top=false;try{top=window.frameElement==null&&document.documentElement}catch(e){}if(top&&top.doScroll){(function doScrollCheck(){if(!jQuery.isReady){try{top.doScroll("left")}catch(e){return window.setTimeout(doScrollCheck,50)}detach();jQuery.ready()}})()}}}return readyList.promise(obj)};jQuery.ready.promise();var i;for(i in jQuery(support)){break}support.ownFirst=i==="0";support.inlineBlockNeedsLayout=false;jQuery(function(){var val,div,body,container;body=document.getElementsByTagName("body")[0];if(!body||!body.style){return}div=document.createElement("div");container=document.createElement("div");container.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px";body.appendChild(container).appendChild(div);if(typeof div.style.zoom!=="undefined"){div.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1";support.inlineBlockNeedsLayout=val=div.offsetWidth===3;if(val){body.style.zoom=1}}body.removeChild(container)});(function(){var div=document.createElement("div");support.deleteExpando=true;try{delete div.test}catch(e){support.deleteExpando=false}div=null})();var acceptData=function(elem){var noData=jQuery.noData[(elem.nodeName+" ").toLowerCase()],nodeType=+elem.nodeType||1;return nodeType!==1&&nodeType!==9?false:!noData||noData!==true&&elem.getAttribute("classid")===noData};var rbrace=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,rmultiDash=/([A-Z])/g;function dataAttr(elem,key,data){if(data===undefined&&elem.nodeType===1){var name="data-"+key.replace(rmultiDash,"-$1").toLowerCase();data=elem.getAttribute(name);if(typeof data==="string"){try{data=data==="true"?true:data==="false"?false:data==="null"?null:+data+""===data?+data:rbrace.test(data)?jQuery.parseJSON(data):data}catch(e){}jQuery.data(elem,key,data)}else{data=undefined}}return data}function isEmptyDataObject(obj){var name;for(name in obj){if(name==="data"&&jQuery.isEmptyObject(obj[name])){continue}if(name!=="toJSON"){return false}}return true}function internalData(elem,name,data,pvt){if(!acceptData(elem)){return}var ret,thisCache,internalKey=jQuery.expando,isNode=elem.nodeType,cache=isNode?jQuery.cache:elem,id=isNode?elem[internalKey]:elem[internalKey]&&internalKey;if((!id||!cache[id]||!pvt&&!cache[id].data)&&data===undefined&&typeof name==="string"){return}if(!id){if(isNode){id=elem[internalKey]=deletedIds.pop()||jQuery.guid++}else{id=internalKey}}if(!cache[id]){cache[id]=isNode?{}:{toJSON:jQuery.noop}}if(typeof name==="object"||typeof name==="function"){if(pvt){cache[id]=jQuery.extend(cache[id],name)}else{cache[id].data=jQuery.extend(cache[id].data,name)}}thisCache=cache[id];if(!pvt){if(!thisCache.data){thisCache.data={}}thisCache=thisCache.data}if(data!==undefined){thisCache[jQuery.camelCase(name)]=data}if(typeof name==="string"){ret=thisCache[name];if(ret==null){ret=thisCache[jQuery.camelCase(name)]}}else{ret=thisCache}return ret}function internalRemoveData(elem,name,pvt){if(!acceptData(elem)){return}var thisCache,i,isNode=elem.nodeType,cache=isNode?jQuery.cache:elem,id=isNode?elem[jQuery.expando]:jQuery.expando;if(!cache[id]){return}if(name){thisCache=pvt?cache[id]:cache[id].data;if(thisCache){if(!jQuery.isArray(name)){if(name in thisCache){name=[name]}else{name=jQuery.camelCase(name);if(name in thisCache){name=[name]}else{name=name.split(" ")}}}else{name=name.concat(jQuery.map(name,jQuery.camelCase))}i=name.length;while(i--){delete thisCache[name[i]]}if(pvt?!isEmptyDataObject(thisCache):!jQuery.isEmptyObject(thisCache)){return}}}if(!pvt){delete cache[id].data;if(!isEmptyDataObject(cache[id])){return}}if(isNode){jQuery.cleanData([elem],true)}else if(support.deleteExpando||cache!=cache.window){delete cache[id]}else{cache[id]=undefined}}jQuery.extend({cache:{},noData:{"applet ":true,"embed ":true,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(elem){elem=elem.nodeType?jQuery.cache[elem[jQuery.expando]]:elem[jQuery.expando];return!!elem&&!isEmptyDataObject(elem)},data:function(elem,name,data){return internalData(elem,name,data)},removeData:function(elem,name){return internalRemoveData(elem,name)},_data:function(elem,name,data){return internalData(elem,name,data,true)},_removeData:function(elem,name){return internalRemoveData(elem,name,true)}});jQuery.fn.extend({data:function(key,value){var i,name,data,elem=this[0],attrs=elem&&elem.attributes;if(key===undefined){if(this.length){data=jQuery.data(elem);if(elem.nodeType===1&&!jQuery._data(elem,"parsedAttrs")){i=attrs.length;while(i--){if(attrs[i]){name=attrs[i].name;if(name.indexOf("data-")===0){name=jQuery.camelCase(name.slice(5));dataAttr(elem,name,data[name])}}}jQuery._data(elem,"parsedAttrs",true)}}return data}if(typeof key==="object"){return this.each(function(){jQuery.data(this,key)})}return arguments.length>1?this.each(function(){jQuery.data(this,key,value)}):elem?dataAttr(elem,key,jQuery.data(elem,key)):undefined},removeData:function(key){return this.each(function(){jQuery.removeData(this,key)})}});jQuery.extend({queue:function(elem,type,data){var queue;if(elem){type=(type||"fx")+"queue";queue=jQuery._data(elem,type);if(data){if(!queue||jQuery.isArray(data)){queue=jQuery._data(elem,type,jQuery.makeArray(data))}else{queue.push(data)}}return queue||[]}},dequeue:function(elem,type){type=type||"fx";var queue=jQuery.queue(elem,type),startLength=queue.length,fn=queue.shift(),hooks=jQuery._queueHooks(elem,type),next=function(){jQuery.dequeue(elem,type)};if(fn==="inprogress"){fn=queue.shift();startLength--}if(fn){if(type==="fx"){queue.unshift("inprogress")}delete hooks.stop;fn.call(elem,next,hooks)}if(!startLength&&hooks){hooks.empty.fire()}},_queueHooks:function(elem,type){var key=type+"queueHooks";return jQuery._data(elem,key)||jQuery._data(elem,key,{empty:jQuery.Callbacks("once memory").add(function(){jQuery._removeData(elem,type+"queue");jQuery._removeData(elem,key)})})}});jQuery.fn.extend({queue:function(type,data){var setter=2;if(typeof type!=="string"){data=type;type="fx";setter--}if(arguments.length
a";support.leadingWhitespace=div.firstChild.nodeType===3;support.tbody=!div.getElementsByTagName("tbody").length;support.htmlSerialize=!!div.getElementsByTagName("link").length;support.html5Clone=document.createElement("nav").cloneNode(true).outerHTML!=="<:nav>";input.type="checkbox";input.checked=true;fragment.appendChild(input);support.appendChecked=input.checked;div.innerHTML="";support.noCloneChecked=!!div.cloneNode(true).lastChild.defaultValue;fragment.appendChild(div);input=document.createElement("input");input.setAttribute("type","radio");input.setAttribute("checked","checked");input.setAttribute("name","t");div.appendChild(input);support.checkClone=div.cloneNode(true).cloneNode(true).lastChild.checked;support.noCloneEvent=!!div.addEventListener;div[jQuery.expando]=1;support.attributes=!div.getAttribute(jQuery.expando)})();var wrapMap={option:[1,""],legend:[1,"
","
"],area:[1,"",""],param:[1,"",""],thead:[1,"","
"],tr:[2,"","
"],col:[2,"","
"],td:[3,"","
"],_default:support.htmlSerialize?[0,"",""]:[1,"X
","
"]};wrapMap.optgroup=wrapMap.option;wrapMap.tbody=wrapMap.tfoot=wrapMap.colgroup=wrapMap.caption=wrapMap.thead;wrapMap.th=wrapMap.td;function getAll(context,tag){var elems,elem,i=0,found=typeof context.getElementsByTagName!=="undefined"?context.getElementsByTagName(tag||"*"):typeof context.querySelectorAll!=="undefined"?context.querySelectorAll(tag||"*"):undefined;if(!found){for(found=[],elems=context.childNodes||context;(elem=elems[i])!=null;i++){if(!tag||jQuery.nodeName(elem,tag)){found.push(elem)}else{jQuery.merge(found,getAll(elem,tag))}}}return tag===undefined||tag&&jQuery.nodeName(context,tag)?jQuery.merge([context],found):found}function setGlobalEval(elems,refElements){var elem,i=0;for(;(elem=elems[i])!=null;i++){jQuery._data(elem,"globalEval",!refElements||jQuery._data(refElements[i],"globalEval"))}}var rhtml=/<|&#?\w+;/,rtbody=/"&&!rtbody.test(elem)?tmp:0;j=elem&&elem.childNodes.length;while(j--){if(jQuery.nodeName(tbody=elem.childNodes[j],"tbody")&&!tbody.childNodes.length){elem.removeChild(tbody)}}}jQuery.merge(nodes,tmp.childNodes);tmp.textContent="";while(tmp.firstChild){tmp.removeChild(tmp.firstChild)}tmp=safe.lastChild}}}if(tmp){safe.removeChild(tmp)}if(!support.appendChecked){jQuery.grep(getAll(nodes,"input"),fixDefaultChecked)}i=0;while(elem=nodes[i++]){if(selection&&jQuery.inArray(elem,selection)>-1){if(ignored){ignored.push(elem)}continue}contains=jQuery.contains(elem.ownerDocument,elem);tmp=getAll(safe.appendChild(elem),"script");if(contains){setGlobalEval(tmp)}if(scripts){j=0;while(elem=tmp[j++]){if(rscriptType.test(elem.type||"")){scripts.push(elem)}}}}tmp=null;return safe}(function(){var i,eventName,div=document.createElement("div");for(i in{submit:true,change:true,focusin:true}){eventName="on"+i;if(!(support[i]=eventName in window)){div.setAttribute(eventName,"t");support[i]=div.attributes[eventName].expando===false}}div=null})();var rformElems=/^(?:input|select|textarea)$/i,rkeyEvent=/^key/,rmouseEvent=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,rfocusMorph=/^(?:focusinfocus|focusoutblur)$/,rtypenamespace=/^([^.]*)(?:\.(.+)|)/;function returnTrue(){return true}function returnFalse(){return false}function safeActiveElement(){try{return document.activeElement}catch(err){}}function on(elem,types,selector,data,fn,one){var origFn,type;if(typeof types==="object"){if(typeof selector!=="string"){data=data||selector;selector=undefined}for(type in types){on(elem,type,selector,data,types[type],one)}return elem}if(data==null&&fn==null){fn=selector;data=selector=undefined}else if(fn==null){if(typeof selector==="string"){fn=data;data=undefined}else{fn=data;data=selector;selector=undefined}}if(fn===false){fn=returnFalse}else if(!fn){return elem}if(one===1){origFn=fn;fn=function(event){jQuery().off(event);return origFn.apply(this,arguments)};fn.guid=origFn.guid||(origFn.guid=jQuery.guid++)}return elem.each(function(){jQuery.event.add(this,types,fn,data,selector)})}jQuery.event={global:{},add:function(elem,types,handler,data,selector){var tmp,events,t,handleObjIn,special,eventHandle,handleObj,handlers,type,namespaces,origType,elemData=jQuery._data(elem);if(!elemData){return}if(handler.handler){handleObjIn=handler;handler=handleObjIn.handler;selector=handleObjIn.selector}if(!handler.guid){handler.guid=jQuery.guid++}if(!(events=elemData.events)){events=elemData.events={}}if(!(eventHandle=elemData.handle)){eventHandle=elemData.handle=function(e){return typeof jQuery!=="undefined"&&(!e||jQuery.event.triggered!==e.type)?jQuery.event.dispatch.apply(eventHandle.elem,arguments):undefined};eventHandle.elem=elem}types=(types||"").match(rnotwhite)||[""];t=types.length;while(t--){tmp=rtypenamespace.exec(types[t])||[];type=origType=tmp[1];namespaces=(tmp[2]||"").split(".").sort();if(!type){continue}special=jQuery.event.special[type]||{};type=(selector?special.delegateType:special.bindType)||type;special=jQuery.event.special[type]||{};handleObj=jQuery.extend({type:type,origType:origType,data:data,handler:handler,guid:handler.guid,selector:selector,needsContext:selector&&jQuery.expr.match.needsContext.test(selector),namespace:namespaces.join(".")},handleObjIn);if(!(handlers=events[type])){handlers=events[type]=[];handlers.delegateCount=0;if(!special.setup||special.setup.call(elem,data,namespaces,eventHandle)===false){if(elem.addEventListener){elem.addEventListener(type,eventHandle,false)}else if(elem.attachEvent){elem.attachEvent("on"+type,eventHandle)}}}if(special.add){special.add.call(elem,handleObj);if(!handleObj.handler.guid){handleObj.handler.guid=handler.guid}}if(selector){handlers.splice(handlers.delegateCount++,0,handleObj)}else{handlers.push(handleObj)}jQuery.event.global[type]=true}elem=null},remove:function(elem,types,handler,selector,mappedTypes){var j,handleObj,tmp,origCount,t,events,special,handlers,type,namespaces,origType,elemData=jQuery.hasData(elem)&&jQuery._data(elem);if(!elemData||!(events=elemData.events)){return}types=(types||"").match(rnotwhite)||[""];t=types.length;while(t--){tmp=rtypenamespace.exec(types[t])||[];type=origType=tmp[1];namespaces=(tmp[2]||"").split(".").sort();if(!type){for(type in events){jQuery.event.remove(elem,type+types[t],handler,selector,true)}continue}special=jQuery.event.special[type]||{};type=(selector?special.delegateType:special.bindType)||type;handlers=events[type]||[];tmp=tmp[2]&&new RegExp("(^|\\.)"+namespaces.join("\\.(?:.*\\.|)")+"(\\.|$)");origCount=j=handlers.length;while(j--){handleObj=handlers[j];if((mappedTypes||origType===handleObj.origType)&&(!handler||handler.guid===handleObj.guid)&&(!tmp||tmp.test(handleObj.namespace))&&(!selector||selector===handleObj.selector||selector==="**"&&handleObj.selector)){handlers.splice(j,1);if(handleObj.selector){handlers.delegateCount--}if(special.remove){special.remove.call(elem,handleObj)}}}if(origCount&&!handlers.length){if(!special.teardown||special.teardown.call(elem,namespaces,elemData.handle)===false){jQuery.removeEvent(elem,type,elemData.handle)}delete events[type]}}if(jQuery.isEmptyObject(events)){delete elemData.handle;jQuery._removeData(elem,"events")}},trigger:function(event,data,elem,onlyHandlers){var handle,ontype,cur,bubbleType,special,tmp,i,eventPath=[elem||document],type=hasOwn.call(event,"type")?event.type:event,namespaces=hasOwn.call(event,"namespace")?event.namespace.split("."):[];cur=tmp=elem=elem||document;if(elem.nodeType===3||elem.nodeType===8){return}if(rfocusMorph.test(type+jQuery.event.triggered)){return}if(type.indexOf(".")>-1){namespaces=type.split(".");type=namespaces.shift();namespaces.sort()}ontype=type.indexOf(":")<0&&"on"+type;event=event[jQuery.expando]?event:new jQuery.Event(type,typeof event==="object"&&event);event.isTrigger=onlyHandlers?2:3;event.namespace=namespaces.join(".");event.rnamespace=event.namespace?new RegExp("(^|\\.)"+namespaces.join("\\.(?:.*\\.|)")+"(\\.|$)"):null;event.result=undefined;if(!event.target){event.target=elem}data=data==null?[event]:jQuery.makeArray(data,[event]);special=jQuery.event.special[type]||{};if(!onlyHandlers&&special.trigger&&special.trigger.apply(elem,data)===false){return}if(!onlyHandlers&&!special.noBubble&&!jQuery.isWindow(elem)){bubbleType=special.delegateType||type;if(!rfocusMorph.test(bubbleType+type)){cur=cur.parentNode}for(;cur;cur=cur.parentNode){eventPath.push(cur);tmp=cur}if(tmp===(elem.ownerDocument||document)){eventPath.push(tmp.defaultView||tmp.parentWindow||window)}}i=0;while((cur=eventPath[i++])&&!event.isPropagationStopped()){event.type=i>1?bubbleType:special.bindType||type;handle=(jQuery._data(cur,"events")||{})[event.type]&&jQuery._data(cur,"handle");if(handle){handle.apply(cur,data)}handle=ontype&&cur[ontype];if(handle&&handle.apply&&acceptData(cur)){event.result=handle.apply(cur,data);if(event.result===false){event.preventDefault()}}}event.type=type;if(!onlyHandlers&&!event.isDefaultPrevented()){if((!special._default||special._default.apply(eventPath.pop(),data)===false)&&acceptData(elem)){if(ontype&&elem[type]&&!jQuery.isWindow(elem)){tmp=elem[ontype];if(tmp){elem[ontype]=null}jQuery.event.triggered=type;try{elem[type]()}catch(e){}jQuery.event.triggered=undefined;if(tmp){elem[ontype]=tmp}}}}return event.result},dispatch:function(event){event=jQuery.event.fix(event);var i,j,ret,matched,handleObj,handlerQueue=[],args=slice.call(arguments),handlers=(jQuery._data(this,"events")||{})[event.type]||[],special=jQuery.event.special[event.type]||{};args[0]=event;event.delegateTarget=this;if(special.preDispatch&&special.preDispatch.call(this,event)===false){return}handlerQueue=jQuery.event.handlers.call(this,event,handlers);i=0;while((matched=handlerQueue[i++])&&!event.isPropagationStopped()){event.currentTarget=matched.elem;j=0;while((handleObj=matched.handlers[j++])&&!event.isImmediatePropagationStopped()){if(!event.rnamespace||event.rnamespace.test(handleObj.namespace)){event.handleObj=handleObj;event.data=handleObj.data;ret=((jQuery.event.special[handleObj.origType]||{}).handle||handleObj.handler).apply(matched.elem,args);if(ret!==undefined){if((event.result=ret)===false){event.preventDefault();event.stopPropagation()}}}}}if(special.postDispatch){special.postDispatch.call(this,event)}return event.result},handlers:function(event,handlers){var i,matches,sel,handleObj,handlerQueue=[],delegateCount=handlers.delegateCount,cur=event.target;if(delegateCount&&cur.nodeType&&(event.type!=="click"||isNaN(event.button)||event.button<1)){for(;cur!=this;cur=cur.parentNode||this){if(cur.nodeType===1&&(cur.disabled!==true||event.type!=="click")){matches=[];for(i=0;i-1:jQuery.find(sel,this,null,[cur]).length}if(matches[sel]){matches.push(handleObj)}}if(matches.length){handlerQueue.push({elem:cur,handlers:matches})}}}}if(delegateCount]","i"),rxhtmlTag=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,rnoInnerhtml=/\s*$/g,safeFragment=createSafeFragment(document),fragmentDiv=safeFragment.appendChild(document.createElement("div"));function manipulationTarget(elem,content){return jQuery.nodeName(elem,"table")&&jQuery.nodeName(content.nodeType!==11?content:content.firstChild,"tr")?elem.getElementsByTagName("tbody")[0]||elem.appendChild(elem.ownerDocument.createElement("tbody")):elem}function disableScript(elem){elem.type=(jQuery.find.attr(elem,"type")!==null)+"/"+elem.type;return elem}function restoreScript(elem){var match=rscriptTypeMasked.exec(elem.type);if(match){elem.type=match[1]}else{elem.removeAttribute("type")}return elem}function cloneCopyEvent(src,dest){if(dest.nodeType!==1||!jQuery.hasData(src)){return}var type,i,l,oldData=jQuery._data(src),curData=jQuery._data(dest,oldData),events=oldData.events;if(events){delete curData.handle;curData.events={};for(type in events){for(i=0,l=events[type].length;i1&&typeof value==="string"&&!support.checkClone&&rchecked.test(value)){return collection.each(function(index){var self=collection.eq(index);if(isFunction){args[0]=value.call(this,index,self.html())}domManip(self,args,callback,ignored)})}if(l){fragment=buildFragment(args,collection[0].ownerDocument,false,collection,ignored);first=fragment.firstChild;if(fragment.childNodes.length===1){fragment=first}if(first||ignored){scripts=jQuery.map(getAll(fragment,"script"),disableScript);hasScripts=scripts.length;for(;i")},clone:function(elem,dataAndEvents,deepDataAndEvents){var destElements,node,clone,i,srcElements,inPage=jQuery.contains(elem.ownerDocument,elem);if(support.html5Clone||jQuery.isXMLDoc(elem)||!rnoshimcache.test("<"+elem.nodeName+">")){clone=elem.cloneNode(true)}else{fragmentDiv.innerHTML=elem.outerHTML;fragmentDiv.removeChild(clone=fragmentDiv.firstChild)}if((!support.noCloneEvent||!support.noCloneChecked)&&(elem.nodeType===1||elem.nodeType===11)&&!jQuery.isXMLDoc(elem)){destElements=getAll(clone);srcElements=getAll(elem);for(i=0;(node=srcElements[i])!=null;++i){if(destElements[i]){fixCloneNodeIssues(node,destElements[i])}}}if(dataAndEvents){if(deepDataAndEvents){srcElements=srcElements||getAll(elem);destElements=destElements||getAll(clone);for(i=0;(node=srcElements[i])!=null;i++){cloneCopyEvent(node,destElements[i])}}else{cloneCopyEvent(elem,clone)}}destElements=getAll(clone,"script");if(destElements.length>0){setGlobalEval(destElements,!inPage&&getAll(elem,"script"))}destElements=srcElements=node=null;return clone},cleanData:function(elems,forceAcceptData){var elem,type,id,data,i=0,internalKey=jQuery.expando,cache=jQuery.cache,attributes=support.attributes,special=jQuery.event.special;for(;(elem=elems[i])!=null;i++){if(forceAcceptData||acceptData(elem)){id=elem[internalKey];data=id&&cache[id];if(data){if(data.events){for(type in data.events){if(special[type]){jQuery.event.remove(elem,type)}else{jQuery.removeEvent(elem,type,data.handle)}}}if(cache[id]){delete cache[id];if(!attributes&&typeof elem.removeAttribute!=="undefined"){elem.removeAttribute(internalKey)}else{elem[internalKey]=undefined}deletedIds.push(id)}}}}}});jQuery.fn.extend({domManip:domManip,detach:function(selector){return remove(this,selector,true)},remove:function(selector){return remove(this,selector)},text:function(value){return access(this,function(value){return value===undefined?jQuery.text(this):this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(value))},null,value,arguments.length)},append:function(){return domManip(this,arguments,function(elem){if(this.nodeType===1||this.nodeType===11||this.nodeType===9){var target=manipulationTarget(this,elem);target.appendChild(elem)}})},prepend:function(){return domManip(this,arguments,function(elem){if(this.nodeType===1||this.nodeType===11||this.nodeType===9){var target=manipulationTarget(this,elem);target.insertBefore(elem,target.firstChild)}})},before:function(){return domManip(this,arguments,function(elem){if(this.parentNode){this.parentNode.insertBefore(elem,this)}})},after:function(){return domManip(this,arguments,function(elem){if(this.parentNode){this.parentNode.insertBefore(elem,this.nextSibling)}})},empty:function(){var elem,i=0;for(;(elem=this[i])!=null;i++){if(elem.nodeType===1){jQuery.cleanData(getAll(elem,false))}while(elem.firstChild){elem.removeChild(elem.firstChild)}if(elem.options&&jQuery.nodeName(elem,"select")){elem.options.length=0}}return this},clone:function(dataAndEvents,deepDataAndEvents){dataAndEvents=dataAndEvents==null?false:dataAndEvents;deepDataAndEvents=deepDataAndEvents==null?dataAndEvents:deepDataAndEvents;return this.map(function(){return jQuery.clone(this,dataAndEvents,deepDataAndEvents)})},html:function(value){return access(this,function(value){var elem=this[0]||{},i=0,l=this.length;if(value===undefined){return elem.nodeType===1?elem.innerHTML.replace(rinlinejQuery,""):undefined}if(typeof value==="string"&&!rnoInnerhtml.test(value)&&(support.htmlSerialize||!rnoshimcache.test(value))&&(support.leadingWhitespace||!rleadingWhitespace.test(value))&&!wrapMap[(rtagName.exec(value)||["",""])[1].toLowerCase()]){value=jQuery.htmlPrefilter(value);try{for(;i")).appendTo(doc.documentElement);doc=(iframe[0].contentWindow||iframe[0].contentDocument).document;doc.write();doc.close();display=actualDisplay(nodeName,doc);iframe.detach()}elemdisplay[nodeName]=display}return display}var rmargin=/^margin/;var rnumnonpx=new RegExp("^("+pnum+")(?!px)[a-z%]+$","i");var swap=function(elem,options,callback,args){var ret,name,old={};for(name in options){old[name]=elem.style[name];elem.style[name]=options[name]}ret=callback.apply(elem,args||[]);for(name in options){elem.style[name]=old[name]}return ret};var documentElement=document.documentElement;(function(){var pixelPositionVal,pixelMarginRightVal,boxSizingReliableVal,reliableHiddenOffsetsVal,reliableMarginRightVal,reliableMarginLeftVal,container=document.createElement("div"),div=document.createElement("div");if(!div.style){return}div.style.cssText="float:left;opacity:.5";support.opacity=div.style.opacity==="0.5";support.cssFloat=!!div.style.cssFloat;div.style.backgroundClip="content-box";div.cloneNode(true).style.backgroundClip="";support.clearCloneStyle=div.style.backgroundClip==="content-box";container=document.createElement("div");container.style.cssText="border:0;width:8px;height:0;top:0;left:-9999px;"+"padding:0;margin-top:1px;position:absolute";div.innerHTML="";container.appendChild(div);support.boxSizing=div.style.boxSizing===""||div.style.MozBoxSizing===""||div.style.WebkitBoxSizing==="";jQuery.extend(support,{reliableHiddenOffsets:function(){if(pixelPositionVal==null){computeStyleTests()}return reliableHiddenOffsetsVal},boxSizingReliable:function(){if(pixelPositionVal==null){computeStyleTests()}return boxSizingReliableVal},pixelMarginRight:function(){if(pixelPositionVal==null){computeStyleTests()}return pixelMarginRightVal},pixelPosition:function(){if(pixelPositionVal==null){computeStyleTests()}return pixelPositionVal},reliableMarginRight:function(){if(pixelPositionVal==null){computeStyleTests()}return reliableMarginRightVal},reliableMarginLeft:function(){if(pixelPositionVal==null){computeStyleTests()}return reliableMarginLeftVal}});function computeStyleTests(){var contents,divStyle,documentElement=document.documentElement;documentElement.appendChild(container);div.style.cssText="-webkit-box-sizing:border-box;box-sizing:border-box;"+"position:relative;display:block;"+"margin:auto;border:1px;padding:1px;"+"top:1%;width:50%";pixelPositionVal=boxSizingReliableVal=reliableMarginLeftVal=false;pixelMarginRightVal=reliableMarginRightVal=true;if(window.getComputedStyle){divStyle=window.getComputedStyle(div);pixelPositionVal=(divStyle||{}).top!=="1%";reliableMarginLeftVal=(divStyle||{}).marginLeft==="2px";boxSizingReliableVal=(divStyle||{width:"4px"}).width==="4px";div.style.marginRight="50%";pixelMarginRightVal=(divStyle||{marginRight:"4px"}).marginRight==="4px";contents=div.appendChild(document.createElement("div"));contents.style.cssText=div.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;"+"box-sizing:content-box;display:block;margin:0;border:0;padding:0";contents.style.marginRight=contents.style.width="0";div.style.width="1px";reliableMarginRightVal=!parseFloat((window.getComputedStyle(contents)||{}).marginRight);div.removeChild(contents)}div.style.display="none";reliableHiddenOffsetsVal=div.getClientRects().length===0;if(reliableHiddenOffsetsVal){div.style.display="";div.innerHTML="
t
";contents=div.getElementsByTagName("td");contents[0].style.cssText="margin:0;border:0;padding:0;display:none";reliableHiddenOffsetsVal=contents[0].offsetHeight===0;if(reliableHiddenOffsetsVal){contents[0].style.display="";contents[1].style.display="none";reliableHiddenOffsetsVal=contents[0].offsetHeight===0}}documentElement.removeChild(container)}})();var getStyles,curCSS,rposition=/^(top|right|bottom|left)$/;if(window.getComputedStyle){getStyles=function(elem){var view=elem.ownerDocument.defaultView;if(!view||!view.opener){view=window}return view.getComputedStyle(elem)};curCSS=function(elem,name,computed){var width,minWidth,maxWidth,ret,style=elem.style;computed=computed||getStyles(elem);ret=computed?computed.getPropertyValue(name)||computed[name]:undefined;if((ret===""||ret===undefined)&&!jQuery.contains(elem.ownerDocument,elem)){ret=jQuery.style(elem,name)}if(computed){if(!support.pixelMarginRight()&&rnumnonpx.test(ret)&&rmargin.test(name)){width=style.width;minWidth=style.minWidth;maxWidth=style.maxWidth;style.minWidth=style.maxWidth=style.width=ret;ret=computed.width;style.width=width;style.minWidth=minWidth;style.maxWidth=maxWidth}}return ret===undefined?ret:ret+""}}else if(documentElement.currentStyle){getStyles=function(elem){return elem.currentStyle};curCSS=function(elem,name,computed){var left,rs,rsLeft,ret,style=elem.style;computed=computed||getStyles(elem);ret=computed?computed[name]:undefined;if(ret==null&&style&&style[name]){ret=style[name]}if(rnumnonpx.test(ret)&&!rposition.test(name)){left=style.left;rs=elem.runtimeStyle;rsLeft=rs&&rs.left;if(rsLeft){rs.left=elem.currentStyle.left}style.left=name==="fontSize"?"1em":ret;ret=style.pixelLeft+"px";style.left=left;if(rsLeft){rs.left=rsLeft}}return ret===undefined?ret:ret+""||"auto"}}function addGetHookIf(conditionFn,hookFn){return{get:function(){if(conditionFn()){delete this.get;return}return(this.get=hookFn).apply(this,arguments)}}}var ralpha=/alpha\([^)]*\)/i,ropacity=/opacity\s*=\s*([^)]*)/i,rdisplayswap=/^(none|table(?!-c[ea]).+)/,rnumsplit=new RegExp("^("+pnum+")(.*)$","i"),cssShow={position:"absolute",visibility:"hidden",display:"block"},cssNormalTransform={letterSpacing:"0",fontWeight:"400"},cssPrefixes=["Webkit","O","Moz","ms"],emptyStyle=document.createElement("div").style;function vendorPropName(name){if(name in emptyStyle){return name}var capName=name.charAt(0).toUpperCase()+name.slice(1),i=cssPrefixes.length;while(i--){name=cssPrefixes[i]+capName;if(name in emptyStyle){return name}}}function showHide(elements,show){var display,elem,hidden,values=[],index=0,length=elements.length;for(;index=1||value==="")&&jQuery.trim(filter.replace(ralpha,""))===""&&style.removeAttribute){style.removeAttribute("filter");if(value===""||currentStyle&&!currentStyle.filter){return}}style.filter=ralpha.test(filter)?filter.replace(ralpha,opacity):filter+" "+opacity}}}jQuery.cssHooks.marginRight=addGetHookIf(support.reliableMarginRight,function(elem,computed){if(computed){return swap(elem,{display:"inline-block"},curCSS,[elem,"marginRight"])}});jQuery.cssHooks.marginLeft=addGetHookIf(support.reliableMarginLeft,function(elem,computed){if(computed){return(parseFloat(curCSS(elem,"marginLeft"))||(jQuery.contains(elem.ownerDocument,elem)?elem.getBoundingClientRect().left-swap(elem,{marginLeft:0},function(){return elem.getBoundingClientRect().left}):0))+"px"}});jQuery.each({margin:"",padding:"",border:"Width"},function(prefix,suffix){jQuery.cssHooks[prefix+suffix]={expand:function(value){var i=0,expanded={},parts=typeof value==="string"?value.split(" "):[value];for(;i<4;i++){expanded[prefix+cssExpand[i]+suffix]=parts[i]||parts[i-2]||parts[0]}return expanded}};if(!rmargin.test(prefix)){jQuery.cssHooks[prefix+suffix].set=setPositiveNumber}});jQuery.fn.extend({css:function(name,value){return access(this,function(elem,name,value){var styles,len,map={},i=0;if(jQuery.isArray(name)){styles=getStyles(elem);len=name.length;for(;i1)},show:function(){return showHide(this,true)},hide:function(){return showHide(this)},toggle:function(state){if(typeof state==="boolean"){return state?this.show():this.hide()}return this.each(function(){if(isHidden(this)){jQuery(this).show()}else{jQuery(this).hide()}})}});function Tween(elem,options,prop,end,easing){return new Tween.prototype.init(elem,options,prop,end,easing)}jQuery.Tween=Tween;Tween.prototype={constructor:Tween,init:function(elem,options,prop,end,easing,unit){this.elem=elem;this.prop=prop;this.easing=easing||jQuery.easing._default;this.options=options;this.start=this.now=this.cur();this.end=end;this.unit=unit||(jQuery.cssNumber[prop]?"":"px")},cur:function(){var hooks=Tween.propHooks[this.prop];return hooks&&hooks.get?hooks.get(this):Tween.propHooks._default.get(this)},run:function(percent){var eased,hooks=Tween.propHooks[this.prop];if(this.options.duration){this.pos=eased=jQuery.easing[this.easing](percent,this.options.duration*percent,0,1,this.options.duration)}else{this.pos=eased=percent}this.now=(this.end-this.start)*eased+this.start;if(this.options.step){this.options.step.call(this.elem,this.now,this)}if(hooks&&hooks.set){hooks.set(this)}else{Tween.propHooks._default.set(this)}return this}};Tween.prototype.init.prototype=Tween.prototype;Tween.propHooks={_default:{get:function(tween){var result;if(tween.elem.nodeType!==1||tween.elem[tween.prop]!=null&&tween.elem.style[tween.prop]==null){return tween.elem[tween.prop]}result=jQuery.css(tween.elem,tween.prop,"");return!result||result==="auto"?0:result},set:function(tween){if(jQuery.fx.step[tween.prop]){jQuery.fx.step[tween.prop](tween)}else if(tween.elem.nodeType===1&&(tween.elem.style[jQuery.cssProps[tween.prop]]!=null||jQuery.cssHooks[tween.prop])){jQuery.style(tween.elem,tween.prop,tween.now+tween.unit)}else{tween.elem[tween.prop]=tween.now}}}};Tween.propHooks.scrollTop=Tween.propHooks.scrollLeft={set:function(tween){if(tween.elem.nodeType&&tween.elem.parentNode){tween.elem[tween.prop]=tween.now}}};jQuery.easing={linear:function(p){return p},swing:function(p){return.5-Math.cos(p*Math.PI)/2},_default:"swing"};jQuery.fx=Tween.prototype.init;jQuery.fx.step={};var fxNow,timerId,rfxtypes=/^(?:toggle|show|hide)$/,rrun=/queueHooks$/;function createFxNow(){window.setTimeout(function(){fxNow=undefined});return fxNow=jQuery.now()}function genFx(type,includeWidth){var which,attrs={height:type},i=0;includeWidth=includeWidth?1:0;for(;i<4;i+=2-includeWidth){which=cssExpand[i];attrs["margin"+which]=attrs["padding"+which]=type}if(includeWidth){attrs.opacity=attrs.width=type}return attrs}function createTween(value,prop,animation){var tween,collection=(Animation.tweeners[prop]||[]).concat(Animation.tweeners["*"]),index=0,length=collection.length;for(;index
a";a=div.getElementsByTagName("a")[0];input.setAttribute("type","checkbox");div.appendChild(input);a=div.getElementsByTagName("a")[0];a.style.cssText="top:1px";support.getSetAttribute=div.className!=="t";support.style=/top/.test(a.getAttribute("style"));support.hrefNormalized=a.getAttribute("href")==="/a";support.checkOn=!!input.value;support.optSelected=opt.selected;support.enctype=!!document.createElement("form").enctype;select.disabled=true;support.optDisabled=!opt.disabled;input=document.createElement("input");input.setAttribute("value","");support.input=input.getAttribute("value")==="";input.value="t";input.setAttribute("type","radio");support.radioValue=input.value==="t"})();var rreturn=/\r/g;jQuery.fn.extend({val:function(value){var hooks,ret,isFunction,elem=this[0];if(!arguments.length){if(elem){hooks=jQuery.valHooks[elem.type]||jQuery.valHooks[elem.nodeName.toLowerCase()];if(hooks&&"get"in hooks&&(ret=hooks.get(elem,"value"))!==undefined){return ret}ret=elem.value;return typeof ret==="string"?ret.replace(rreturn,""):ret==null?"":ret}return}isFunction=jQuery.isFunction(value);return this.each(function(i){var val;if(this.nodeType!==1){return}if(isFunction){val=value.call(this,i,jQuery(this).val())}else{val=value}if(val==null){val=""}else if(typeof val==="number"){val+=""}else if(jQuery.isArray(val)){val=jQuery.map(val,function(value){return value==null?"":value+""})}hooks=jQuery.valHooks[this.type]||jQuery.valHooks[this.nodeName.toLowerCase()];if(!hooks||!("set"in hooks)||hooks.set(this,val,"value")===undefined){this.value=val}})}});jQuery.extend({valHooks:{option:{get:function(elem){var val=jQuery.find.attr(elem,"value");return val!=null?val:jQuery.trim(jQuery.text(elem))}},select:{get:function(elem){var value,option,options=elem.options,index=elem.selectedIndex,one=elem.type==="select-one"||index<0,values=one?null:[],max=one?index+1:options.length,i=index<0?max:one?index:0;for(;i=0){try{option.selected=optionSet=true}catch(_){option.scrollHeight}}else{option.selected=false}}if(!optionSet){elem.selectedIndex=-1}return options}}}});jQuery.each(["radio","checkbox"],function(){jQuery.valHooks[this]={set:function(elem,value){if(jQuery.isArray(value)){return elem.checked=jQuery.inArray(jQuery(elem).val(),value)>-1}}};if(!support.checkOn){jQuery.valHooks[this].get=function(elem){return elem.getAttribute("value")===null?"on":elem.value}}});var nodeHook,boolHook,attrHandle=jQuery.expr.attrHandle,ruseDefault=/^(?:checked|selected)$/i,getSetAttribute=support.getSetAttribute,getSetInput=support.input;jQuery.fn.extend({attr:function(name,value){return access(this,jQuery.attr,name,value,arguments.length>1)},removeAttr:function(name){return this.each(function(){jQuery.removeAttr(this,name)})}});jQuery.extend({attr:function(elem,name,value){var ret,hooks,nType=elem.nodeType;if(nType===3||nType===8||nType===2){return}if(typeof elem.getAttribute==="undefined"){return jQuery.prop(elem,name,value)}if(nType!==1||!jQuery.isXMLDoc(elem)){name=name.toLowerCase();hooks=jQuery.attrHooks[name]||(jQuery.expr.match.bool.test(name)?boolHook:nodeHook)}if(value!==undefined){if(value===null){jQuery.removeAttr(elem,name);return}if(hooks&&"set"in hooks&&(ret=hooks.set(elem,value,name))!==undefined){return ret}elem.setAttribute(name,value+"");return value}if(hooks&&"get"in hooks&&(ret=hooks.get(elem,name))!==null){return ret}ret=jQuery.find.attr(elem,name);return ret==null?undefined:ret},attrHooks:{type:{set:function(elem,value){if(!support.radioValue&&value==="radio"&&jQuery.nodeName(elem,"input")){var val=elem.value;elem.setAttribute("type",value);if(val){elem.value=val}return value}}}},removeAttr:function(elem,value){var name,propName,i=0,attrNames=value&&value.match(rnotwhite);if(attrNames&&elem.nodeType===1){while(name=attrNames[i++]){propName=jQuery.propFix[name]||name;if(jQuery.expr.match.bool.test(name)){if(getSetInput&&getSetAttribute||!ruseDefault.test(name)){elem[propName]=false}else{elem[jQuery.camelCase("default-"+name)]=elem[propName]=false}}else{jQuery.attr(elem,name,"")}elem.removeAttribute(getSetAttribute?name:propName)}}}});boolHook={set:function(elem,value,name){if(value===false){jQuery.removeAttr(elem,name)}else if(getSetInput&&getSetAttribute||!ruseDefault.test(name)){elem.setAttribute(!getSetAttribute&&jQuery.propFix[name]||name,name)}else{elem[jQuery.camelCase("default-"+name)]=elem[name]=true}return name}};jQuery.each(jQuery.expr.match.bool.source.match(/\w+/g),function(i,name){var getter=attrHandle[name]||jQuery.find.attr;if(getSetInput&&getSetAttribute||!ruseDefault.test(name)){attrHandle[name]=function(elem,name,isXML){var ret,handle;if(!isXML){handle=attrHandle[name];attrHandle[name]=ret;ret=getter(elem,name,isXML)!=null?name.toLowerCase():null;attrHandle[name]=handle}return ret}}else{attrHandle[name]=function(elem,name,isXML){if(!isXML){return elem[jQuery.camelCase("default-"+name)]?name.toLowerCase():null}}}});if(!getSetInput||!getSetAttribute){jQuery.attrHooks.value={set:function(elem,value,name){if(jQuery.nodeName(elem,"input")){elem.defaultValue=value}else{return nodeHook&&nodeHook.set(elem,value,name)}}}}if(!getSetAttribute){nodeHook={set:function(elem,value,name){var ret=elem.getAttributeNode(name);if(!ret){elem.setAttributeNode(ret=elem.ownerDocument.createAttribute(name))}ret.value=value+="";if(name==="value"||value===elem.getAttribute(name)){return value}}};attrHandle.id=attrHandle.name=attrHandle.coords=function(elem,name,isXML){var ret;if(!isXML){return(ret=elem.getAttributeNode(name))&&ret.value!==""?ret.value:null}};jQuery.valHooks.button={get:function(elem,name){var ret=elem.getAttributeNode(name);if(ret&&ret.specified){return ret.value}},set:nodeHook.set};jQuery.attrHooks.contenteditable={set:function(elem,value,name){nodeHook.set(elem,value===""?false:value,name)}};jQuery.each(["width","height"],function(i,name){jQuery.attrHooks[name]={set:function(elem,value){if(value===""){elem.setAttribute(name,"auto");return value}}}})}if(!support.style){jQuery.attrHooks.style={get:function(elem){return elem.style.cssText||undefined},set:function(elem,value){return elem.style.cssText=value+""}}}var rfocusable=/^(?:input|select|textarea|button|object)$/i,rclickable=/^(?:a|area)$/i;jQuery.fn.extend({prop:function(name,value){return access(this,jQuery.prop,name,value,arguments.length>1)},removeProp:function(name){name=jQuery.propFix[name]||name;return this.each(function(){try{this[name]=undefined;delete this[name]}catch(e){}})}});jQuery.extend({prop:function(elem,name,value){var ret,hooks,nType=elem.nodeType;if(nType===3||nType===8||nType===2){return}if(nType!==1||!jQuery.isXMLDoc(elem)){name=jQuery.propFix[name]||name;hooks=jQuery.propHooks[name]}if(value!==undefined){if(hooks&&"set"in hooks&&(ret=hooks.set(elem,value,name))!==undefined){return ret}return elem[name]=value}if(hooks&&"get"in hooks&&(ret=hooks.get(elem,name))!==null){return ret}return elem[name]},propHooks:{tabIndex:{get:function(elem){var tabindex=jQuery.find.attr(elem,"tabindex");return tabindex?parseInt(tabindex,10):rfocusable.test(elem.nodeName)||rclickable.test(elem.nodeName)&&elem.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}});if(!support.hrefNormalized){jQuery.each(["href","src"],function(i,name){jQuery.propHooks[name]={get:function(elem){return elem.getAttribute(name,4)}}})}if(!support.optSelected){jQuery.propHooks.selected={get:function(elem){var parent=elem.parentNode;if(parent){parent.selectedIndex;if(parent.parentNode){parent.parentNode.selectedIndex}}return null}}}jQuery.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){jQuery.propFix[this.toLowerCase()]=this});if(!support.enctype){jQuery.propFix.enctype="encoding"}var rclass=/[\t\r\n\f]/g;function getClass(elem){return jQuery.attr(elem,"class")||""}jQuery.fn.extend({addClass:function(value){var classes,elem,cur,curValue,clazz,j,finalValue,i=0;if(jQuery.isFunction(value)){return this.each(function(j){jQuery(this).addClass(value.call(this,j,getClass(this)))})}if(typeof value==="string"&&value){classes=value.match(rnotwhite)||[];while(elem=this[i++]){curValue=getClass(elem);cur=elem.nodeType===1&&(" "+curValue+" ").replace(rclass," ");if(cur){j=0;while(clazz=classes[j++]){if(cur.indexOf(" "+clazz+" ")<0){cur+=clazz+" "}}finalValue=jQuery.trim(cur);if(curValue!==finalValue){jQuery.attr(elem,"class",finalValue)}}}}return this},removeClass:function(value){var classes,elem,cur,curValue,clazz,j,finalValue,i=0;if(jQuery.isFunction(value)){return this.each(function(j){jQuery(this).removeClass(value.call(this,j,getClass(this)))})}if(!arguments.length){return this.attr("class","")}if(typeof value==="string"&&value){classes=value.match(rnotwhite)||[];while(elem=this[i++]){curValue=getClass(elem);cur=elem.nodeType===1&&(" "+curValue+" ").replace(rclass," ");if(cur){j=0;while(clazz=classes[j++]){while(cur.indexOf(" "+clazz+" ")>-1){cur=cur.replace(" "+clazz+" "," ")}}finalValue=jQuery.trim(cur);if(curValue!==finalValue){jQuery.attr(elem,"class",finalValue)}}}}return this},toggleClass:function(value,stateVal){var type=typeof value;if(typeof stateVal==="boolean"&&type==="string"){return stateVal?this.addClass(value):this.removeClass(value)}if(jQuery.isFunction(value)){return this.each(function(i){jQuery(this).toggleClass(value.call(this,i,getClass(this),stateVal),stateVal)})}return this.each(function(){var className,i,self,classNames;if(type==="string"){i=0;self=jQuery(this);classNames=value.match(rnotwhite)||[];while(className=classNames[i++]){if(self.hasClass(className)){self.removeClass(className)}else{self.addClass(className)}}}else if(value===undefined||type==="boolean"){className=getClass(this);if(className){jQuery._data(this,"__className__",className)}jQuery.attr(this,"class",className||value===false?"":jQuery._data(this,"__className__")||"")}})},hasClass:function(selector){var className,elem,i=0;className=" "+selector+" ";while(elem=this[i++]){if(elem.nodeType===1&&(" "+getClass(elem)+" ").replace(rclass," ").indexOf(className)>-1){return true}}return false}});jQuery.each(("blur focus focusin focusout load resize scroll unload click dblclick "+"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave "+"change select submit keydown keypress keyup error contextmenu").split(" "),function(i,name){jQuery.fn[name]=function(data,fn){return arguments.length>0?this.on(name,null,data,fn):this.trigger(name)}});jQuery.fn.extend({hover:function(fnOver,fnOut){return this.mouseenter(fnOver).mouseleave(fnOut||fnOver)}});var location=window.location;var nonce=jQuery.now();var rquery=/\?/;var rvalidtokens=/(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;jQuery.parseJSON=function(data){if(window.JSON&&window.JSON.parse){return window.JSON.parse(data+"")}var requireNonComma,depth=null,str=jQuery.trim(data+"");return str&&!jQuery.trim(str.replace(rvalidtokens,function(token,comma,open,close){if(requireNonComma&&comma){depth=0}if(depth===0){return token}requireNonComma=open||comma;depth+=!close-!open;return""}))?Function("return "+str)():jQuery.error("Invalid JSON: "+data)};jQuery.parseXML=function(data){var xml,tmp;if(!data||typeof data!=="string"){return null}try{if(window.DOMParser){tmp=new window.DOMParser;xml=tmp.parseFromString(data,"text/xml")}else{xml=new window.ActiveXObject("Microsoft.XMLDOM");xml.async="false";xml.loadXML(data)}}catch(e){xml=undefined}if(!xml||!xml.documentElement||xml.getElementsByTagName("parsererror").length){jQuery.error("Invalid XML: "+data)}return xml};var rhash=/#.*$/,rts=/([?&])_=[^&]*/,rheaders=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,rlocalProtocol=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,rnoContent=/^(?:GET|HEAD)$/,rprotocol=/^\/\//,rurl=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,prefilters={},transports={},allTypes="*/".concat("*"),ajaxLocation=location.href,ajaxLocParts=rurl.exec(ajaxLocation.toLowerCase())||[];function addToPrefiltersOrTransports(structure){return function(dataTypeExpression,func){if(typeof dataTypeExpression!=="string"){func=dataTypeExpression;dataTypeExpression="*"}var dataType,i=0,dataTypes=dataTypeExpression.toLowerCase().match(rnotwhite)||[];if(jQuery.isFunction(func)){while(dataType=dataTypes[i++]){if(dataType.charAt(0)==="+"){dataType=dataType.slice(1)||"*";(structure[dataType]=structure[dataType]||[]).unshift(func)}else{(structure[dataType]=structure[dataType]||[]).push(func)}}}}}function inspectPrefiltersOrTransports(structure,options,originalOptions,jqXHR){var inspected={},seekingTransport=structure===transports;function inspect(dataType){var selected;inspected[dataType]=true;jQuery.each(structure[dataType]||[],function(_,prefilterOrFactory){var dataTypeOrTransport=prefilterOrFactory(options,originalOptions,jqXHR);if(typeof dataTypeOrTransport==="string"&&!seekingTransport&&!inspected[dataTypeOrTransport]){options.dataTypes.unshift(dataTypeOrTransport);inspect(dataTypeOrTransport);return false}else if(seekingTransport){return!(selected=dataTypeOrTransport)}});return selected}return inspect(options.dataTypes[0])||!inspected["*"]&&inspect("*")}function ajaxExtend(target,src){var deep,key,flatOptions=jQuery.ajaxSettings.flatOptions||{};for(key in src){if(src[key]!==undefined){(flatOptions[key]?target:deep||(deep={}))[key]=src[key]}}if(deep){jQuery.extend(true,target,deep)}return target}function ajaxHandleResponses(s,jqXHR,responses){var firstDataType,ct,finalDataType,type,contents=s.contents,dataTypes=s.dataTypes;while(dataTypes[0]==="*"){dataTypes.shift();if(ct===undefined){ct=s.mimeType||jqXHR.getResponseHeader("Content-Type")}}if(ct){for(type in contents){if(contents[type]&&contents[type].test(ct)){dataTypes.unshift(type);break}}}if(dataTypes[0]in responses){finalDataType=dataTypes[0]}else{for(type in responses){if(!dataTypes[0]||s.converters[type+" "+dataTypes[0]]){finalDataType=type;break}if(!firstDataType){firstDataType=type}}finalDataType=finalDataType||firstDataType}if(finalDataType){if(finalDataType!==dataTypes[0]){dataTypes.unshift(finalDataType)}return responses[finalDataType]}}function ajaxConvert(s,response,jqXHR,isSuccess){var conv2,current,conv,tmp,prev,converters={},dataTypes=s.dataTypes.slice();if(dataTypes[1]){for(conv in s.converters){converters[conv.toLowerCase()]=s.converters[conv]}}current=dataTypes.shift();while(current){if(s.responseFields[current]){jqXHR[s.responseFields[current]]=response}if(!prev&&isSuccess&&s.dataFilter){response=s.dataFilter(response,s.dataType)}prev=current;current=dataTypes.shift();if(current){if(current==="*"){current=prev}else if(prev!=="*"&&prev!==current){conv=converters[prev+" "+current]||converters["* "+current];if(!conv){for(conv2 in converters){tmp=conv2.split(" ");if(tmp[1]===current){conv=converters[prev+" "+tmp[0]]||converters["* "+tmp[0]];if(conv){if(conv===true){conv=converters[conv2]}else if(converters[conv2]!==true){current=tmp[0];dataTypes.unshift(tmp[1])}break}}}}if(conv!==true){if(conv&&s["throws"]){response=conv(response)}else{try{response=conv(response)}catch(e){return{state:"parsererror",error:conv?e:"No conversion from "+prev+" to "+current}}}}}}}return{state:"success",data:response}}jQuery.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:ajaxLocation,type:"GET",isLocal:rlocalProtocol.test(ajaxLocParts[1]),global:true,processData:true,async:true,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":allTypes,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":true,"text json":jQuery.parseJSON,"text xml":jQuery.parseXML},flatOptions:{url:true,context:true}},ajaxSetup:function(target,settings){return settings?ajaxExtend(ajaxExtend(target,jQuery.ajaxSettings),settings):ajaxExtend(jQuery.ajaxSettings,target)},ajaxPrefilter:addToPrefiltersOrTransports(prefilters),ajaxTransport:addToPrefiltersOrTransports(transports),ajax:function(url,options){if(typeof url==="object"){options=url;url=undefined}options=options||{};var parts,i,cacheURL,responseHeadersString,timeoutTimer,fireGlobals,transport,responseHeaders,s=jQuery.ajaxSetup({},options),callbackContext=s.context||s,globalEventContext=s.context&&(callbackContext.nodeType||callbackContext.jquery)?jQuery(callbackContext):jQuery.event,deferred=jQuery.Deferred(),completeDeferred=jQuery.Callbacks("once memory"),statusCode=s.statusCode||{},requestHeaders={},requestHeadersNames={},state=0,strAbort="canceled",jqXHR={readyState:0,getResponseHeader:function(key){var match;if(state===2){if(!responseHeaders){responseHeaders={};while(match=rheaders.exec(responseHeadersString)){responseHeaders[match[1].toLowerCase()]=match[2]}}match=responseHeaders[key.toLowerCase()]}return match==null?null:match},getAllResponseHeaders:function(){return state===2?responseHeadersString:null},setRequestHeader:function(name,value){var lname=name.toLowerCase();if(!state){name=requestHeadersNames[lname]=requestHeadersNames[lname]||name;requestHeaders[name]=value}return this},overrideMimeType:function(type){if(!state){s.mimeType=type}return this},statusCode:function(map){var code;if(map){if(state<2){for(code in map){statusCode[code]=[statusCode[code],map[code]]}}else{jqXHR.always(map[jqXHR.status])}}return this},abort:function(statusText){var finalText=statusText||strAbort;if(transport){transport.abort(finalText)}done(0,finalText);return this}};deferred.promise(jqXHR).complete=completeDeferred.add;jqXHR.success=jqXHR.done;jqXHR.error=jqXHR.fail;s.url=((url||s.url||ajaxLocation)+"").replace(rhash,"").replace(rprotocol,ajaxLocParts[1]+"//");s.type=options.method||options.type||s.method||s.type;s.dataTypes=jQuery.trim(s.dataType||"*").toLowerCase().match(rnotwhite)||[""];if(s.crossDomain==null){parts=rurl.exec(s.url.toLowerCase());s.crossDomain=!!(parts&&(parts[1]!==ajaxLocParts[1]||parts[2]!==ajaxLocParts[2]||(parts[3]||(parts[1]==="http:"?"80":"443"))!==(ajaxLocParts[3]||(ajaxLocParts[1]==="http:"?"80":"443"))))}if(s.data&&s.processData&&typeof s.data!=="string"){s.data=jQuery.param(s.data,s.traditional)}inspectPrefiltersOrTransports(prefilters,s,options,jqXHR);if(state===2){return jqXHR}fireGlobals=jQuery.event&&s.global;if(fireGlobals&&jQuery.active++===0){jQuery.event.trigger("ajaxStart")}s.type=s.type.toUpperCase();s.hasContent=!rnoContent.test(s.type);cacheURL=s.url;if(!s.hasContent){if(s.data){cacheURL=s.url+=(rquery.test(cacheURL)?"&":"?")+s.data;delete s.data}if(s.cache===false){s.url=rts.test(cacheURL)?cacheURL.replace(rts,"$1_="+nonce++):cacheURL+(rquery.test(cacheURL)?"&":"?")+"_="+nonce++}}if(s.ifModified){if(jQuery.lastModified[cacheURL]){jqXHR.setRequestHeader("If-Modified-Since",jQuery.lastModified[cacheURL])}if(jQuery.etag[cacheURL]){jqXHR.setRequestHeader("If-None-Match",jQuery.etag[cacheURL])}}if(s.data&&s.hasContent&&s.contentType!==false||options.contentType){jqXHR.setRequestHeader("Content-Type",s.contentType)}jqXHR.setRequestHeader("Accept",s.dataTypes[0]&&s.accepts[s.dataTypes[0]]?s.accepts[s.dataTypes[0]]+(s.dataTypes[0]!=="*"?", "+allTypes+"; q=0.01":""):s.accepts["*"]);for(i in s.headers){jqXHR.setRequestHeader(i,s.headers[i])}if(s.beforeSend&&(s.beforeSend.call(callbackContext,jqXHR,s)===false||state===2)){return jqXHR.abort()}strAbort="abort";for(i in{success:1,error:1,complete:1}){jqXHR[i](s[i])}transport=inspectPrefiltersOrTransports(transports,s,options,jqXHR);if(!transport){done(-1,"No Transport")}else{jqXHR.readyState=1;if(fireGlobals){globalEventContext.trigger("ajaxSend",[jqXHR,s])}if(state===2){return jqXHR}if(s.async&&s.timeout>0){timeoutTimer=window.setTimeout(function(){jqXHR.abort("timeout")},s.timeout)}try{state=1;transport.send(requestHeaders,done)}catch(e){if(state<2){done(-1,e)}else{throw e}}}function done(status,nativeStatusText,responses,headers){var isSuccess,success,error,response,modified,statusText=nativeStatusText;if(state===2){return}state=2;if(timeoutTimer){window.clearTimeout(timeoutTimer)}transport=undefined;responseHeadersString=headers||"";jqXHR.readyState=status>0?4:0;isSuccess=status>=200&&status<300||status===304;if(responses){response=ajaxHandleResponses(s,jqXHR,responses)}response=ajaxConvert(s,response,jqXHR,isSuccess);if(isSuccess){if(s.ifModified){modified=jqXHR.getResponseHeader("Last-Modified");if(modified){jQuery.lastModified[cacheURL]=modified}modified=jqXHR.getResponseHeader("etag");if(modified){jQuery.etag[cacheURL]=modified}}if(status===204||s.type==="HEAD"){statusText="nocontent"}else if(status===304){statusText="notmodified"}else{statusText=response.state;success=response.data;error=response.error;isSuccess=!error}}else{error=statusText;if(status||!statusText){statusText="error";if(status<0){status=0}}}jqXHR.status=status;jqXHR.statusText=(nativeStatusText||statusText)+"";if(isSuccess){deferred.resolveWith(callbackContext,[success,statusText,jqXHR])}else{deferred.rejectWith(callbackContext,[jqXHR,statusText,error])}jqXHR.statusCode(statusCode);statusCode=undefined;if(fireGlobals){globalEventContext.trigger(isSuccess?"ajaxSuccess":"ajaxError",[jqXHR,s,isSuccess?success:error])}completeDeferred.fireWith(callbackContext,[jqXHR,statusText]);if(fireGlobals){globalEventContext.trigger("ajaxComplete",[jqXHR,s]);if(!--jQuery.active){jQuery.event.trigger("ajaxStop")}}}return jqXHR},getJSON:function(url,data,callback){return jQuery.get(url,data,callback,"json")},getScript:function(url,callback){return jQuery.get(url,undefined,callback,"script")}});jQuery.each(["get","post"],function(i,method){jQuery[method]=function(url,data,callback,type){if(jQuery.isFunction(data)){type=type||callback;callback=data;data=undefined}return jQuery.ajax(jQuery.extend({url:url,type:method,dataType:type,data:data,success:callback},jQuery.isPlainObject(url)&&url))}});jQuery._evalUrl=function(url){return jQuery.ajax({url:url,type:"GET",dataType:"script",cache:true,async:false,global:false,"throws":true})};jQuery.fn.extend({wrapAll:function(html){if(jQuery.isFunction(html)){return this.each(function(i){jQuery(this).wrapAll(html.call(this,i))})}if(this[0]){var wrap=jQuery(html,this[0].ownerDocument).eq(0).clone(true);if(this[0].parentNode){wrap.insertBefore(this[0])}wrap.map(function(){var elem=this;while(elem.firstChild&&elem.firstChild.nodeType===1){elem=elem.firstChild}return elem}).append(this)}return this},wrapInner:function(html){if(jQuery.isFunction(html)){return this.each(function(i){jQuery(this).wrapInner(html.call(this,i))})}return this.each(function(){var self=jQuery(this),contents=self.contents();if(contents.length){contents.wrapAll(html)}else{self.append(html)}})},wrap:function(html){var isFunction=jQuery.isFunction(html);return this.each(function(i){jQuery(this).wrapAll(isFunction?html.call(this,i):html)})},unwrap:function(){return this.parent().each(function(){if(!jQuery.nodeName(this,"body")){jQuery(this).replaceWith(this.childNodes)}}).end()}});function getDisplay(elem){return elem.style&&elem.style.display||jQuery.css(elem,"display")}function filterHidden(elem){while(elem&&elem.nodeType===1){if(getDisplay(elem)==="none"||elem.type==="hidden"){return true}elem=elem.parentNode}return false}jQuery.expr.filters.hidden=function(elem){return support.reliableHiddenOffsets()?elem.offsetWidth<=0&&elem.offsetHeight<=0&&!elem.getClientRects().length:filterHidden(elem)};jQuery.expr.filters.visible=function(elem){return!jQuery.expr.filters.hidden(elem)};var r20=/%20/g,rbracket=/\[\]$/,rCRLF=/\r?\n/g,rsubmitterTypes=/^(?:submit|button|image|reset|file)$/i,rsubmittable=/^(?:input|select|textarea|keygen)/i;function buildParams(prefix,obj,traditional,add){var name;if(jQuery.isArray(obj)){jQuery.each(obj,function(i,v){if(traditional||rbracket.test(prefix)){add(prefix,v)}else{buildParams(prefix+"["+(typeof v==="object"&&v!=null?i:"")+"]",v,traditional,add)}})}else if(!traditional&&jQuery.type(obj)==="object"){for(name in obj){buildParams(prefix+"["+name+"]",obj[name],traditional,add)}}else{add(prefix,obj)}}jQuery.param=function(a,traditional){var prefix,s=[],add=function(key,value){value=jQuery.isFunction(value)?value():value==null?"":value;s[s.length]=encodeURIComponent(key)+"="+encodeURIComponent(value)};if(traditional===undefined){traditional=jQuery.ajaxSettings&&jQuery.ajaxSettings.traditional}if(jQuery.isArray(a)||a.jquery&&!jQuery.isPlainObject(a)){jQuery.each(a,function(){add(this.name,this.value)})}else{for(prefix in a){buildParams(prefix,a[prefix],traditional,add)}}return s.join("&").replace(r20,"+")};jQuery.fn.extend({serialize:function(){return jQuery.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var elements=jQuery.prop(this,"elements");return elements?jQuery.makeArray(elements):this}).filter(function(){var type=this.type;return this.name&&!jQuery(this).is(":disabled")&&rsubmittable.test(this.nodeName)&&!rsubmitterTypes.test(type)&&(this.checked||!rcheckableType.test(type))}).map(function(i,elem){var val=jQuery(this).val();return val==null?null:jQuery.isArray(val)?jQuery.map(val,function(val){return{name:elem.name,value:val.replace(rCRLF,"\r\n")}}):{name:elem.name,value:val.replace(rCRLF,"\r\n")}}).get()}});jQuery.ajaxSettings.xhr=window.ActiveXObject!==undefined?function(){if(this.isLocal){return createActiveXHR()}if(document.documentMode>8){return createStandardXHR()}return/^(get|post|head|put|delete|options)$/i.test(this.type)&&createStandardXHR()||createActiveXHR()}:createStandardXHR;var xhrId=0,xhrCallbacks={},xhrSupported=jQuery.ajaxSettings.xhr();if(window.attachEvent){window.attachEvent("onunload",function(){for(var key in xhrCallbacks){xhrCallbacks[key](undefined,true)}})}support.cors=!!xhrSupported&&"withCredentials"in xhrSupported; -xhrSupported=support.ajax=!!xhrSupported;if(xhrSupported){jQuery.ajaxTransport(function(options){if(!options.crossDomain||support.cors){var callback;return{send:function(headers,complete){var i,xhr=options.xhr(),id=++xhrId;xhr.open(options.type,options.url,options.async,options.username,options.password);if(options.xhrFields){for(i in options.xhrFields){xhr[i]=options.xhrFields[i]}}if(options.mimeType&&xhr.overrideMimeType){xhr.overrideMimeType(options.mimeType)}if(!options.crossDomain&&!headers["X-Requested-With"]){headers["X-Requested-With"]="XMLHttpRequest"}for(i in headers){if(headers[i]!==undefined){xhr.setRequestHeader(i,headers[i]+"")}}xhr.send(options.hasContent&&options.data||null);callback=function(_,isAbort){var status,statusText,responses;if(callback&&(isAbort||xhr.readyState===4)){delete xhrCallbacks[id];callback=undefined;xhr.onreadystatechange=jQuery.noop;if(isAbort){if(xhr.readyState!==4){xhr.abort()}}else{responses={};status=xhr.status;if(typeof xhr.responseText==="string"){responses.text=xhr.responseText}try{statusText=xhr.statusText}catch(e){statusText=""}if(!status&&options.isLocal&&!options.crossDomain){status=responses.text?200:404}else if(status===1223){status=204}}}if(responses){complete(status,statusText,responses,xhr.getAllResponseHeaders())}};if(!options.async){callback()}else if(xhr.readyState===4){window.setTimeout(callback)}else{xhr.onreadystatechange=xhrCallbacks[id]=callback}},abort:function(){if(callback){callback(undefined,true)}}}}})}function createStandardXHR(){try{return new window.XMLHttpRequest}catch(e){}}function createActiveXHR(){try{return new window.ActiveXObject("Microsoft.XMLHTTP")}catch(e){}}jQuery.ajaxPrefilter(function(s){if(s.crossDomain){s.contents.script=false}});jQuery.ajaxSetup({accepts:{script:"text/javascript, application/javascript, "+"application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(text){jQuery.globalEval(text);return text}}});jQuery.ajaxPrefilter("script",function(s){if(s.cache===undefined){s.cache=false}if(s.crossDomain){s.type="GET";s.global=false}});jQuery.ajaxTransport("script",function(s){if(s.crossDomain){var script,head=document.head||jQuery("head")[0]||document.documentElement;return{send:function(_,callback){script=document.createElement("script");script.async=true;if(s.scriptCharset){script.charset=s.scriptCharset}script.src=s.url;script.onload=script.onreadystatechange=function(_,isAbort){if(isAbort||!script.readyState||/loaded|complete/.test(script.readyState)){script.onload=script.onreadystatechange=null;if(script.parentNode){script.parentNode.removeChild(script)}script=null;if(!isAbort){callback(200,"success")}}};head.insertBefore(script,head.firstChild)},abort:function(){if(script){script.onload(undefined,true)}}}}});var oldCallbacks=[],rjsonp=/(=)\?(?=&|$)|\?\?/;jQuery.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var callback=oldCallbacks.pop()||jQuery.expando+"_"+nonce++;this[callback]=true;return callback}});jQuery.ajaxPrefilter("json jsonp",function(s,originalSettings,jqXHR){var callbackName,overwritten,responseContainer,jsonProp=s.jsonp!==false&&(rjsonp.test(s.url)?"url":typeof s.data==="string"&&(s.contentType||"").indexOf("application/x-www-form-urlencoded")===0&&rjsonp.test(s.data)&&"data");if(jsonProp||s.dataTypes[0]==="jsonp"){callbackName=s.jsonpCallback=jQuery.isFunction(s.jsonpCallback)?s.jsonpCallback():s.jsonpCallback;if(jsonProp){s[jsonProp]=s[jsonProp].replace(rjsonp,"$1"+callbackName)}else if(s.jsonp!==false){s.url+=(rquery.test(s.url)?"&":"?")+s.jsonp+"="+callbackName}s.converters["script json"]=function(){if(!responseContainer){jQuery.error(callbackName+" was not called")}return responseContainer[0]};s.dataTypes[0]="json";overwritten=window[callbackName];window[callbackName]=function(){responseContainer=arguments};jqXHR.always(function(){if(overwritten===undefined){jQuery(window).removeProp(callbackName)}else{window[callbackName]=overwritten}if(s[callbackName]){s.jsonpCallback=originalSettings.jsonpCallback;oldCallbacks.push(callbackName)}if(responseContainer&&jQuery.isFunction(overwritten)){overwritten(responseContainer[0])}responseContainer=overwritten=undefined});return"script"}});support.createHTMLDocument=function(){if(!document.implementation.createHTMLDocument){return false}var doc=document.implementation.createHTMLDocument("");doc.body.innerHTML="
";return doc.body.childNodes.length===2}();jQuery.parseHTML=function(data,context,keepScripts){if(!data||typeof data!=="string"){return null}if(typeof context==="boolean"){keepScripts=context;context=false}context=context||(support.createHTMLDocument?document.implementation.createHTMLDocument(""):document);var parsed=rsingleTag.exec(data),scripts=!keepScripts&&[];if(parsed){return[context.createElement(parsed[1])]}parsed=buildFragment([data],context,scripts);if(scripts&&scripts.length){jQuery(scripts).remove()}return jQuery.merge([],parsed.childNodes)};var _load=jQuery.fn.load;jQuery.fn.load=function(url,params,callback){if(typeof url!=="string"&&_load){return _load.apply(this,arguments)}var selector,type,response,self=this,off=url.indexOf(" ");if(off>-1){selector=jQuery.trim(url.slice(off,url.length));url=url.slice(0,off)}if(jQuery.isFunction(params)){callback=params;params=undefined}else if(params&&typeof params==="object"){type="POST"}if(self.length>0){jQuery.ajax({url:url,type:type||"GET",dataType:"html",data:params}).done(function(responseText){response=arguments;self.html(selector?jQuery("
").append(jQuery.parseHTML(responseText)).find(selector):responseText)}).always(callback&&function(jqXHR,status){self.each(function(){callback.apply(self,response||[jqXHR.responseText,status,jqXHR])})})}return this};jQuery.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(i,type){jQuery.fn[type]=function(fn){return this.on(type,fn)}});jQuery.expr.filters.animated=function(elem){return jQuery.grep(jQuery.timers,function(fn){return elem===fn.elem}).length};function getWindow(elem){return jQuery.isWindow(elem)?elem:elem.nodeType===9?elem.defaultView||elem.parentWindow:false}jQuery.offset={setOffset:function(elem,options,i){var curPosition,curLeft,curCSSTop,curTop,curOffset,curCSSLeft,calculatePosition,position=jQuery.css(elem,"position"),curElem=jQuery(elem),props={};if(position==="static"){elem.style.position="relative"}curOffset=curElem.offset();curCSSTop=jQuery.css(elem,"top");curCSSLeft=jQuery.css(elem,"left");calculatePosition=(position==="absolute"||position==="fixed")&&jQuery.inArray("auto",[curCSSTop,curCSSLeft])>-1;if(calculatePosition){curPosition=curElem.position();curTop=curPosition.top;curLeft=curPosition.left}else{curTop=parseFloat(curCSSTop)||0;curLeft=parseFloat(curCSSLeft)||0}if(jQuery.isFunction(options)){options=options.call(elem,i,jQuery.extend({},curOffset))}if(options.top!=null){props.top=options.top-curOffset.top+curTop}if(options.left!=null){props.left=options.left-curOffset.left+curLeft}if("using"in options){options.using.call(elem,props)}else{curElem.css(props)}}};jQuery.fn.extend({offset:function(options){if(arguments.length){return options===undefined?this:this.each(function(i){jQuery.offset.setOffset(this,options,i)})}var docElem,win,box={top:0,left:0},elem=this[0],doc=elem&&elem.ownerDocument;if(!doc){return}docElem=doc.documentElement;if(!jQuery.contains(docElem,elem)){return box}if(typeof elem.getBoundingClientRect!=="undefined"){box=elem.getBoundingClientRect()}win=getWindow(doc);return{top:box.top+(win.pageYOffset||docElem.scrollTop)-(docElem.clientTop||0),left:box.left+(win.pageXOffset||docElem.scrollLeft)-(docElem.clientLeft||0)}},position:function(){if(!this[0]){return}var offsetParent,offset,parentOffset={top:0,left:0},elem=this[0];if(jQuery.css(elem,"position")==="fixed"){offset=elem.getBoundingClientRect()}else{offsetParent=this.offsetParent();offset=this.offset();if(!jQuery.nodeName(offsetParent[0],"html")){parentOffset=offsetParent.offset()}parentOffset.top+=jQuery.css(offsetParent[0],"borderTopWidth",true);parentOffset.left+=jQuery.css(offsetParent[0],"borderLeftWidth",true)}return{top:offset.top-parentOffset.top-jQuery.css(elem,"marginTop",true),left:offset.left-parentOffset.left-jQuery.css(elem,"marginLeft",true)}},offsetParent:function(){return this.map(function(){var offsetParent=this.offsetParent;while(offsetParent&&(!jQuery.nodeName(offsetParent,"html")&&jQuery.css(offsetParent,"position")==="static")){offsetParent=offsetParent.offsetParent}return offsetParent||documentElement})}});jQuery.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(method,prop){var top=/Y/.test(prop);jQuery.fn[method]=function(val){return access(this,function(elem,method,val){var win=getWindow(elem);if(val===undefined){return win?prop in win?win[prop]:win.document.documentElement[method]:elem[method]}if(win){win.scrollTo(!top?val:jQuery(win).scrollLeft(),top?val:jQuery(win).scrollTop())}else{elem[method]=val}},method,val,arguments.length,null)}});jQuery.each(["top","left"],function(i,prop){jQuery.cssHooks[prop]=addGetHookIf(support.pixelPosition,function(elem,computed){if(computed){computed=curCSS(elem,prop);return rnumnonpx.test(computed)?jQuery(elem).position()[prop]+"px":computed}})});jQuery.each({Height:"height",Width:"width"},function(name,type){jQuery.each({padding:"inner"+name,content:type,"":"outer"+name},function(defaultExtra,funcName){jQuery.fn[funcName]=function(margin,value){var chainable=arguments.length&&(defaultExtra||typeof margin!=="boolean"),extra=defaultExtra||(margin===true||value===true?"margin":"border");return access(this,function(elem,type,value){var doc;if(jQuery.isWindow(elem)){return elem.document.documentElement["client"+name]}if(elem.nodeType===9){doc=elem.documentElement;return Math.max(elem.body["scroll"+name],doc["scroll"+name],elem.body["offset"+name],doc["offset"+name],doc["client"+name])}return value===undefined?jQuery.css(elem,type,extra):jQuery.style(elem,type,value,extra)},type,chainable?margin:undefined,chainable,null)}})});jQuery.fn.extend({bind:function(types,data,fn){return this.on(types,null,data,fn)},unbind:function(types,fn){return this.off(types,null,fn)},delegate:function(selector,types,data,fn){return this.on(types,selector,data,fn)},undelegate:function(selector,types,fn){return arguments.length===1?this.off(selector,"**"):this.off(types,selector||"**",fn)}});jQuery.fn.size=function(){return this.length};jQuery.fn.andSelf=jQuery.fn.addBack;if(typeof define==="function"&&define.amd){define("jquery",[],function(){return jQuery})}var _jQuery=window.jQuery,_$=window.$;jQuery.noConflict=function(deep){if(window.$===jQuery){window.$=_$}if(deep&&window.jQuery===jQuery){window.jQuery=_jQuery}return jQuery};if(!noGlobal){window.jQuery=window.$=jQuery}return jQuery})},{}],8:[function(require,module,exports){(function(){module.exports={xpath:require("./xpath"),Range:require("./range")}}).call(this)},{"./range":9,"./xpath":11}],9:[function(require,module,exports){(function(){var $,Range,Util,xpath,__hasProp={}.hasOwnProperty,__extends=function(child,parent){for(var key in parent){if(__hasProp.call(parent,key))child[key]=parent[key]}function ctor(){this.constructor=child}ctor.prototype=parent.prototype;child.prototype=new ctor;child.__super__=parent.prototype;return child};xpath=require("./xpath");Util=require("./util");$=require("jquery");Range={};Range.sniff=function(r){if(r.commonAncestorContainer!=null){return new Range.BrowserRange(r)}else if(typeof r.start==="string"){return new Range.SerializedRange(r)}else if(r.start&&typeof r.start==="object"){return new Range.NormalizedRange(r)}else{console.error("Could not sniff range type");return false}};Range.RangeError=function(_super){__extends(RangeError,_super);function RangeError(type,message,parent){this.type=type;this.message=message;this.parent=parent!=null?parent:null;RangeError.__super__.constructor.call(this,this.message)}return RangeError}(Error);Range.BrowserRange=function(){function BrowserRange(obj){this.commonAncestorContainer=obj.commonAncestorContainer;this.startContainer=obj.startContainer;this.startOffset=obj.startOffset;this.endContainer=obj.endContainer;this.endOffset=obj.endOffset}BrowserRange.prototype.normalize=function(root){var nr,r;if(this.tainted){console.error("You may only call normalize() once on a BrowserRange!");return false}else{this.tainted=true}r={};this._normalizeStart(r);this._normalizeEnd(r);nr={};if(r.startOffset>0){if(r.start.nodeValue.length>r.startOffset){nr.start=r.start.splitText(r.startOffset)}else{nr.start=r.start.nextSibling}}else{nr.start=r.start}if(r.start===r.end){if(nr.start.nodeValue.length>r.endOffset-r.startOffset){nr.start.splitText(r.endOffset-r.startOffset)}nr.end=nr.start}else{if(r.end.nodeValue.length>r.endOffset){r.end.splitText(r.endOffset)}nr.end=r.end}nr.commonAncestor=this.commonAncestorContainer;while(nr.commonAncestor.nodeType!==Util.NodeTypes.ELEMENT_NODE){nr.commonAncestor=nr.commonAncestor.parentNode}return new Range.NormalizedRange(nr)};BrowserRange.prototype._normalizeStart=function(r){if(this.startContainer.nodeType===Util.NodeTypes.ELEMENT_NODE){r.start=Util.getFirstTextNodeNotBefore(this.startContainer.childNodes[this.startOffset]);return r.startOffset=0}else{r.start=this.startContainer;return r.startOffset=this.startOffset}};BrowserRange.prototype._normalizeEnd=function(r){var n,node;if(this.endContainer.nodeType===Util.NodeTypes.ELEMENT_NODE){node=this.endContainer.childNodes[this.endOffset];if(node!=null){n=node;while(n!=null&&n.nodeType!==Util.NodeTypes.TEXT_NODE){n=n.firstChild}if(n!=null){r.end=n;r.endOffset=0}}if(r.end==null){if(this.endOffset){node=this.endContainer.childNodes[this.endOffset-1]}else{node=this.endContainer.previousSibling}r.end=Util.getLastTextNodeUpTo(node);return r.endOffset=r.end.nodeValue.length}}else{r.end=this.endContainer;return r.endOffset=this.endOffset}};BrowserRange.prototype.serialize=function(root,ignoreSelector){return this.normalize(root).serialize(root,ignoreSelector)};return BrowserRange}();Range.NormalizedRange=function(){function NormalizedRange(obj){this.commonAncestor=obj.commonAncestor;this.start=obj.start;this.end=obj.end}NormalizedRange.prototype.normalize=function(root){return this};NormalizedRange.prototype.limit=function(bounds){var nodes,parent,startParents,_i,_len,_ref;nodes=$.grep(this.textNodes(),function(node){return node.parentNode===bounds||$.contains(bounds,node.parentNode)});if(!nodes.length){return null}this.start=nodes[0];this.end=nodes[nodes.length-1];startParents=$(this.start).parents();_ref=$(this.end).parents();for(_i=0,_len=_ref.length;_i<_len;_i++){parent=_ref[_i];if(startParents.index(parent)!==-1){this.commonAncestor=parent;break}}return this};NormalizedRange.prototype.serialize=function(root,ignoreSelector){var end,serialization,start;serialization=function(node,isEnd){var n,nodes,offset,origParent,path,textNodes,_i,_len;if(ignoreSelector){origParent=$(node).parents(":not("+ignoreSelector+")").eq(0)}else{origParent=$(node).parent()}path=xpath.fromNode(origParent,root)[0];textNodes=Util.getTextNodes(origParent);nodes=textNodes.slice(0,textNodes.index(node));offset=0;for(_i=0,_len=nodes.length;_i<_len;_i++){n=nodes[_i];offset+=n.nodeValue.length}if(isEnd){return[path,offset+node.nodeValue.length]}else{return[path,offset]}};start=serialization(this.start);end=serialization(this.end,true);return new Range.SerializedRange({start:start[0],end:end[0],startOffset:start[1],endOffset:end[1]})};NormalizedRange.prototype.text=function(){var node;return function(){var _i,_len,_ref,_results;_ref=this.textNodes();_results=[];for(_i=0,_len=_ref.length;_i<_len;_i++){node=_ref[_i];_results.push(node.nodeValue)}return _results}.call(this).join("")};NormalizedRange.prototype.textNodes=function(){var end,start,textNodes,_ref;textNodes=Util.getTextNodes($(this.commonAncestor));_ref=[textNodes.index(this.start),textNodes.index(this.end)],start=_ref[0],end=_ref[1];return $.makeArray(textNodes.slice(start,+end+1||9e9))};return NormalizedRange}();Range.SerializedRange=function(){function SerializedRange(obj){this.start=obj.start;this.startOffset=obj.startOffset;this.end=obj.end;this.endOffset=obj.endOffset}SerializedRange.prototype.normalize=function(root){var contains,e,length,node,p,range,targetOffset,tn,_i,_j,_len,_len1,_ref,_ref1;range={};_ref=["start","end"];for(_i=0,_len=_ref.length;_i<_len;_i++){p=_ref[_i];try{node=xpath.toNode(this[p],root)}catch(_error){e=_error;throw new Range.RangeError(p,"Error while finding "+p+" node: "+this[p]+": "+e,e)}if(!node){throw new Range.RangeError(p,"Couldn't find "+p+" node: "+this[p])}length=0;targetOffset=this[p+"Offset"];if(p==="end"){targetOffset-=1}_ref1=Util.getTextNodes($(node));for(_j=0,_len1=_ref1.length;_j<_len1;_j++){tn=_ref1[_j];if(length+tn.nodeValue.length>targetOffset){range[p+"Container"]=tn;range[p+"Offset"]=this[p+"Offset"]-length;break}else{length+=tn.nodeValue.length}}if(range[p+"Offset"]==null){throw new Range.RangeError(""+p+"offset","Couldn't find offset "+this[p+"Offset"]+" in element "+this[p])}}contains=document.compareDocumentPosition!=null?function(a,b){return a.compareDocumentPosition(b)&Node.DOCUMENT_POSITION_CONTAINED_BY}:function(a,b){return a.contains(b)};$(range.startContainer).parents().each(function(){var endContainer;if(range.endContainer.nodeType===Util.NodeTypes.TEXT_NODE){endContainer=range.endContainer.parentNode}else{endContainer=range.endContainer}if(contains(this,endContainer)){range.commonAncestorContainer=this;return false}});return new Range.BrowserRange(range).normalize(root)};SerializedRange.prototype.serialize=function(root,ignoreSelector){return this.normalize(root).serialize(root,ignoreSelector)};SerializedRange.prototype.toObject=function(){return{start:this.start,startOffset:this.startOffset,end:this.end,endOffset:this.endOffset}};return SerializedRange}();module.exports=Range}).call(this)},{"./util":10,"./xpath":11,jquery:12}],10:[function(require,module,exports){(function(){var $,Util;$=require("jquery");Util={};Util.NodeTypes={ELEMENT_NODE:1,ATTRIBUTE_NODE:2,TEXT_NODE:3,CDATA_SECTION_NODE:4,ENTITY_REFERENCE_NODE:5,ENTITY_NODE:6,PROCESSING_INSTRUCTION_NODE:7,COMMENT_NODE:8,DOCUMENT_NODE:9,DOCUMENT_TYPE_NODE:10,DOCUMENT_FRAGMENT_NODE:11,NOTATION_NODE:12};Util.getFirstTextNodeNotBefore=function(n){var result;switch(n.nodeType){case Util.NodeTypes.TEXT_NODE:return n;case Util.NodeTypes.ELEMENT_NODE:if(n.firstChild!=null){result=Util.getFirstTextNodeNotBefore(n.firstChild);if(result!=null){return result}}break}n=n.nextSibling;if(n!=null){return Util.getFirstTextNodeNotBefore(n)}else{return null}};Util.getLastTextNodeUpTo=function(n){var result;switch(n.nodeType){case Util.NodeTypes.TEXT_NODE:return n;case Util.NodeTypes.ELEMENT_NODE:if(n.lastChild!=null){result=Util.getLastTextNodeUpTo(n.lastChild);if(result!=null){return result}}break}n=n.previousSibling;if(n!=null){return Util.getLastTextNodeUpTo(n)}else{return null}};Util.getTextNodes=function(jq){var getTextNodes;getTextNodes=function(node){var nodes;if(node&&node.nodeType!==Util.NodeTypes.TEXT_NODE){nodes=[];if(node.nodeType!==Util.NodeTypes.COMMENT_NODE){node=node.lastChild;while(node){nodes.push(getTextNodes(node));node=node.previousSibling}}return nodes.reverse()}else{return node}};return jq.map(function(){return Util.flatten(getTextNodes(this))})};Util.getGlobal=function(){return function(){return this}()};Util.contains=function(parent,child){var node;node=child;while(node!=null){if(node===parent){return true}node=node.parentNode}return false};Util.flatten=function(array){var flatten;flatten=function(ary){var el,flat,_i,_len;flat=[];for(_i=0,_len=ary.length;_i<_len;_i++){el=ary[_i];flat=flat.concat(el&&$.isArray(el)?flatten(el):el)}return flat};return flatten(array)};module.exports=Util}).call(this)},{jquery:12}],11:[function(require,module,exports){(function(){var $,Util,evaluateXPath,findChild,fromNode,getNodeName,getNodePosition,simpleXPathJQuery,simpleXPathPure,toNode;$=require("jquery");Util=require("./util");evaluateXPath=function(xp,root,nsResolver){var exception,idx,name,node,step,steps,_i,_len,_ref;if(root==null){root=document}if(nsResolver==null){nsResolver=null}try{return document.evaluate("."+xp,root,nsResolver,XPathResult.FIRST_ORDERED_NODE_TYPE,null).singleNodeValue}catch(_error){exception=_error;console.log("XPath evaluation failed.");console.log("Trying fallback...");steps=xp.substring(1).split("/");node=root;for(_i=0,_len=steps.length;_i<_len;_i++){step=steps[_i];_ref=step.split("["),name=_ref[0],idx=_ref[1];idx=idx!=null?parseInt((idx!=null?idx.split("]"):void 0)[0]):1;node=findChild(node,name.toLowerCase(),idx)}return node}};simpleXPathJQuery=function($el,relativeRoot){var jq;jq=$el.map(function(){var elem,idx,path,tagName;path="";elem=this;while((elem!=null?elem.nodeType:void 0)===Util.NodeTypes.ELEMENT_NODE&&elem!==relativeRoot){tagName=elem.tagName.replace(":","\\:");idx=$(elem.parentNode).children(tagName).index(elem)+1;idx="["+idx+"]";path="/"+elem.tagName.toLowerCase()+idx+path;elem=elem.parentNode}return path});return jq.get()};simpleXPathPure=function($el,relativeRoot){var getPathSegment,getPathTo,jq,rootNode;getPathSegment=function(node){var name,pos;name=getNodeName(node);pos=getNodePosition(node);return""+name+"["+pos+"]"};rootNode=relativeRoot;getPathTo=function(node){var xpath;xpath="";while(node!==rootNode){if(node==null){throw new Error("Called getPathTo on a node which was not a descendant of @rootNode. "+rootNode)}xpath=getPathSegment(node)+"/"+xpath;node=node.parentNode}xpath="/"+xpath;xpath=xpath.replace(/\/$/,"");return xpath};jq=$el.map(function(){var path;path=getPathTo(this);return path});return jq.get()};findChild=function(node,type,index){var child,children,found,name,_i,_len;if(!node.hasChildNodes()){throw new Error("XPath error: node has no children!")}children=node.childNodes;found=0;for(_i=0,_len=children.length;_i<_len;_i++){child=children[_i];name=getNodeName(child);if(name===type){found+=1;if(found===index){return child}}}throw new Error("XPath error: wanted child not found.")};getNodeName=function(node){var nodeName;nodeName=node.nodeName.toLowerCase();switch(nodeName){case"#text":return"text()";case"#comment":return"comment()";case"#cdata-section":return"cdata-section()";default:return nodeName}};getNodePosition=function(node){var pos,tmp;pos=0;tmp=node;while(tmp){if(tmp.nodeName===node.nodeName){pos+=1}tmp=tmp.previousSibling}return pos};fromNode=function($el,relativeRoot){var exception,result;try{result=simpleXPathJQuery($el,relativeRoot)}catch(_error){exception=_error;console.log("jQuery-based XPath construction failed! Falling back to manual.");result=simpleXPathPure($el,relativeRoot)}return result};toNode=function(path,root){var customResolver,namespace,node,segment;if(root==null){root=document}if(!$.isXMLDoc(document.documentElement)){return evaluateXPath(path,root)}else{customResolver=document.createNSResolver(document.ownerDocument===null?document.documentElement:document.ownerDocument.documentElement);node=evaluateXPath(path,root,customResolver);if(!node){path=function(){var _i,_len,_ref,_results;_ref=path.split("/");_results=[];for(_i=0,_len=_ref.length;_i<_len;_i++){segment=_ref[_i];if(segment&&segment.indexOf(":")===-1){_results.push(segment.replace(/^([a-z]+)/,"xhtml:$1"))}else{_results.push(segment)}}return _results}().join("/");namespace=document.lookupNamespaceURI(null);customResolver=function(ns){if(ns==="xhtml"){return namespace}else{return document.documentElement.getAttribute("xmlns:"+ns)}};node=evaluateXPath(path,root,customResolver)}return node}};module.exports={fromNode:fromNode,toNode:toNode}}).call(this)},{"./util":10,jquery:12}],12:[function(require,module,exports){(function(global,factory){if(typeof module==="object"&&typeof module.exports==="object"){module.exports=global.document?factory(global,true):function(w){if(!w.document){throw new Error("jQuery requires a window with a document")}return factory(w)}}else{factory(global)}})(typeof window!=="undefined"?window:this,function(window,noGlobal){var deletedIds=[];var slice=deletedIds.slice;var concat=deletedIds.concat;var push=deletedIds.push;var indexOf=deletedIds.indexOf;var class2type={};var toString=class2type.toString;var hasOwn=class2type.hasOwnProperty;var support={};var version="1.11.3",jQuery=function(selector,context){return new jQuery.fn.init(selector,context)},rtrim=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,rmsPrefix=/^-ms-/,rdashAlpha=/-([\da-z])/gi,fcamelCase=function(all,letter){return letter.toUpperCase()};jQuery.fn=jQuery.prototype={jquery:version,constructor:jQuery,selector:"",length:0,toArray:function(){return slice.call(this)},get:function(num){return num!=null?num<0?this[num+this.length]:this[num]:slice.call(this)},pushStack:function(elems){var ret=jQuery.merge(this.constructor(),elems);ret.prevObject=this;ret.context=this.context;return ret},each:function(callback,args){return jQuery.each(this,callback,args)},map:function(callback){return this.pushStack(jQuery.map(this,function(elem,i){return callback.call(elem,i,elem)}))},slice:function(){return this.pushStack(slice.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(i){var len=this.length,j=+i+(i<0?len:0);return this.pushStack(j>=0&&j=0},isEmptyObject:function(obj){var name;for(name in obj){return false}return true},isPlainObject:function(obj){var key;if(!obj||jQuery.type(obj)!=="object"||obj.nodeType||jQuery.isWindow(obj)){return false}try{if(obj.constructor&&!hasOwn.call(obj,"constructor")&&!hasOwn.call(obj.constructor.prototype,"isPrototypeOf")){return false}}catch(e){return false}if(support.ownLast){for(key in obj){return hasOwn.call(obj,key)}}for(key in obj){}return key===undefined||hasOwn.call(obj,key)},type:function(obj){if(obj==null){return obj+""}return typeof obj==="object"||typeof obj==="function"?class2type[toString.call(obj)]||"object":typeof obj},globalEval:function(data){if(data&&jQuery.trim(data)){(window.execScript||function(data){window["eval"].call(window,data)})(data)}},camelCase:function(string){return string.replace(rmsPrefix,"ms-").replace(rdashAlpha,fcamelCase)},nodeName:function(elem,name){return elem.nodeName&&elem.nodeName.toLowerCase()===name.toLowerCase()},each:function(obj,callback,args){var value,i=0,length=obj.length,isArray=isArraylike(obj);if(args){if(isArray){for(;i0&&length-1 in obj}var Sizzle=function(window){var i,support,Expr,getText,isXML,tokenize,compile,select,outermostContext,sortInput,hasDuplicate,setDocument,document,docElem,documentIsHTML,rbuggyQSA,rbuggyMatches,matches,contains,expando="sizzle"+1*new Date,preferredDoc=window.document,dirruns=0,done=0,classCache=createCache(),tokenCache=createCache(),compilerCache=createCache(),sortOrder=function(a,b){if(a===b){hasDuplicate=true}return 0},MAX_NEGATIVE=1<<31,hasOwn={}.hasOwnProperty,arr=[],pop=arr.pop,push_native=arr.push,push=arr.push,slice=arr.slice,indexOf=function(list,elem){var i=0,len=list.length;for(;i+~]|"+whitespace+")"+whitespace+"*"),rattributeQuotes=new RegExp("="+whitespace+"*([^\\]'\"]*?)"+whitespace+"*\\]","g"),rpseudo=new RegExp(pseudos),ridentifier=new RegExp("^"+identifier+"$"),matchExpr={ID:new RegExp("^#("+characterEncoding+")"),CLASS:new RegExp("^\\.("+characterEncoding+")"),TAG:new RegExp("^("+characterEncoding.replace("w","w*")+")"),ATTR:new RegExp("^"+attributes),PSEUDO:new RegExp("^"+pseudos), -CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+whitespace+"*(even|odd|(([+-]|)(\\d*)n|)"+whitespace+"*(?:([+-]|)"+whitespace+"*(\\d+)|))"+whitespace+"*\\)|)","i"),bool:new RegExp("^(?:"+booleans+")$","i"),needsContext:new RegExp("^"+whitespace+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+whitespace+"*((?:-\\d)?\\d*)"+whitespace+"*\\)|)(?=[^-]|$)","i")},rinputs=/^(?:input|select|textarea|button)$/i,rheader=/^h\d$/i,rnative=/^[^{]+\{\s*\[native \w/,rquickExpr=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,rsibling=/[+~]/,rescape=/'|\\/g,runescape=new RegExp("\\\\([\\da-f]{1,6}"+whitespace+"?|("+whitespace+")|.)","ig"),funescape=function(_,escaped,escapedWhitespace){var high="0x"+escaped-65536;return high!==high||escapedWhitespace?escaped:high<0?String.fromCharCode(high+65536):String.fromCharCode(high>>10|55296,high&1023|56320)},unloadHandler=function(){setDocument()};try{push.apply(arr=slice.call(preferredDoc.childNodes),preferredDoc.childNodes);arr[preferredDoc.childNodes.length].nodeType}catch(e){push={apply:arr.length?function(target,els){push_native.apply(target,slice.call(els))}:function(target,els){var j=target.length,i=0;while(target[j++]=els[i++]){}target.length=j-1}}}function Sizzle(selector,context,results,seed){var match,elem,m,nodeType,i,groups,old,nid,newContext,newSelector;if((context?context.ownerDocument||context:preferredDoc)!==document){setDocument(context)}context=context||document;results=results||[];nodeType=context.nodeType;if(typeof selector!=="string"||!selector||nodeType!==1&&nodeType!==9&&nodeType!==11){return results}if(!seed&&documentIsHTML){if(nodeType!==11&&(match=rquickExpr.exec(selector))){if(m=match[1]){if(nodeType===9){elem=context.getElementById(m);if(elem&&elem.parentNode){if(elem.id===m){results.push(elem);return results}}else{return results}}else{if(context.ownerDocument&&(elem=context.ownerDocument.getElementById(m))&&contains(context,elem)&&elem.id===m){results.push(elem);return results}}}else if(match[2]){push.apply(results,context.getElementsByTagName(selector));return results}else if((m=match[3])&&support.getElementsByClassName){push.apply(results,context.getElementsByClassName(m));return results}}if(support.qsa&&(!rbuggyQSA||!rbuggyQSA.test(selector))){nid=old=expando;newContext=context;newSelector=nodeType!==1&&selector;if(nodeType===1&&context.nodeName.toLowerCase()!=="object"){groups=tokenize(selector);if(old=context.getAttribute("id")){nid=old.replace(rescape,"\\$&")}else{context.setAttribute("id",nid)}nid="[id='"+nid+"'] ";i=groups.length;while(i--){groups[i]=nid+toSelector(groups[i])}newContext=rsibling.test(selector)&&testContext(context.parentNode)||context;newSelector=groups.join(",")}if(newSelector){try{push.apply(results,newContext.querySelectorAll(newSelector));return results}catch(qsaError){}finally{if(!old){context.removeAttribute("id")}}}}}return select(selector.replace(rtrim,"$1"),context,results,seed)}function createCache(){var keys=[];function cache(key,value){if(keys.push(key+" ")>Expr.cacheLength){delete cache[keys.shift()]}return cache[key+" "]=value}return cache}function markFunction(fn){fn[expando]=true;return fn}function assert(fn){var div=document.createElement("div");try{return!!fn(div)}catch(e){return false}finally{if(div.parentNode){div.parentNode.removeChild(div)}div=null}}function addHandle(attrs,handler){var arr=attrs.split("|"),i=attrs.length;while(i--){Expr.attrHandle[arr[i]]=handler}}function siblingCheck(a,b){var cur=b&&a,diff=cur&&a.nodeType===1&&b.nodeType===1&&(~b.sourceIndex||MAX_NEGATIVE)-(~a.sourceIndex||MAX_NEGATIVE);if(diff){return diff}if(cur){while(cur=cur.nextSibling){if(cur===b){return-1}}}return a?1:-1}function createInputPseudo(type){return function(elem){var name=elem.nodeName.toLowerCase();return name==="input"&&elem.type===type}}function createButtonPseudo(type){return function(elem){var name=elem.nodeName.toLowerCase();return(name==="input"||name==="button")&&elem.type===type}}function createPositionalPseudo(fn){return markFunction(function(argument){argument=+argument;return markFunction(function(seed,matches){var j,matchIndexes=fn([],seed.length,argument),i=matchIndexes.length;while(i--){if(seed[j=matchIndexes[i]]){seed[j]=!(matches[j]=seed[j])}}})})}function testContext(context){return context&&typeof context.getElementsByTagName!=="undefined"&&context}support=Sizzle.support={};isXML=Sizzle.isXML=function(elem){var documentElement=elem&&(elem.ownerDocument||elem).documentElement;return documentElement?documentElement.nodeName!=="HTML":false};setDocument=Sizzle.setDocument=function(node){var hasCompare,parent,doc=node?node.ownerDocument||node:preferredDoc;if(doc===document||doc.nodeType!==9||!doc.documentElement){return document}document=doc;docElem=doc.documentElement;parent=doc.defaultView;if(parent&&parent!==parent.top){if(parent.addEventListener){parent.addEventListener("unload",unloadHandler,false)}else if(parent.attachEvent){parent.attachEvent("onunload",unloadHandler)}}documentIsHTML=!isXML(doc);support.attributes=assert(function(div){div.className="i";return!div.getAttribute("className")});support.getElementsByTagName=assert(function(div){div.appendChild(doc.createComment(""));return!div.getElementsByTagName("*").length});support.getElementsByClassName=rnative.test(doc.getElementsByClassName);support.getById=assert(function(div){docElem.appendChild(div).id=expando;return!doc.getElementsByName||!doc.getElementsByName(expando).length});if(support.getById){Expr.find["ID"]=function(id,context){if(typeof context.getElementById!=="undefined"&&documentIsHTML){var m=context.getElementById(id);return m&&m.parentNode?[m]:[]}};Expr.filter["ID"]=function(id){var attrId=id.replace(runescape,funescape);return function(elem){return elem.getAttribute("id")===attrId}}}else{delete Expr.find["ID"];Expr.filter["ID"]=function(id){var attrId=id.replace(runescape,funescape);return function(elem){var node=typeof elem.getAttributeNode!=="undefined"&&elem.getAttributeNode("id");return node&&node.value===attrId}}}Expr.find["TAG"]=support.getElementsByTagName?function(tag,context){if(typeof context.getElementsByTagName!=="undefined"){return context.getElementsByTagName(tag)}else if(support.qsa){return context.querySelectorAll(tag)}}:function(tag,context){var elem,tmp=[],i=0,results=context.getElementsByTagName(tag);if(tag==="*"){while(elem=results[i++]){if(elem.nodeType===1){tmp.push(elem)}}return tmp}return results};Expr.find["CLASS"]=support.getElementsByClassName&&function(className,context){if(documentIsHTML){return context.getElementsByClassName(className)}};rbuggyMatches=[];rbuggyQSA=[];if(support.qsa=rnative.test(doc.querySelectorAll)){assert(function(div){docElem.appendChild(div).innerHTML=""+"";if(div.querySelectorAll("[msallowcapture^='']").length){rbuggyQSA.push("[*^$]="+whitespace+"*(?:''|\"\")")}if(!div.querySelectorAll("[selected]").length){rbuggyQSA.push("\\["+whitespace+"*(?:value|"+booleans+")")}if(!div.querySelectorAll("[id~="+expando+"-]").length){rbuggyQSA.push("~=")}if(!div.querySelectorAll(":checked").length){rbuggyQSA.push(":checked")}if(!div.querySelectorAll("a#"+expando+"+*").length){rbuggyQSA.push(".#.+[+~]")}});assert(function(div){var input=doc.createElement("input");input.setAttribute("type","hidden");div.appendChild(input).setAttribute("name","D");if(div.querySelectorAll("[name=d]").length){rbuggyQSA.push("name"+whitespace+"*[*^$|!~]?=")}if(!div.querySelectorAll(":enabled").length){rbuggyQSA.push(":enabled",":disabled")}div.querySelectorAll("*,:x");rbuggyQSA.push(",.*:")})}if(support.matchesSelector=rnative.test(matches=docElem.matches||docElem.webkitMatchesSelector||docElem.mozMatchesSelector||docElem.oMatchesSelector||docElem.msMatchesSelector)){assert(function(div){support.disconnectedMatch=matches.call(div,"div");matches.call(div,"[s!='']:x");rbuggyMatches.push("!=",pseudos)})}rbuggyQSA=rbuggyQSA.length&&new RegExp(rbuggyQSA.join("|"));rbuggyMatches=rbuggyMatches.length&&new RegExp(rbuggyMatches.join("|"));hasCompare=rnative.test(docElem.compareDocumentPosition);contains=hasCompare||rnative.test(docElem.contains)?function(a,b){var adown=a.nodeType===9?a.documentElement:a,bup=b&&b.parentNode;return a===bup||!!(bup&&bup.nodeType===1&&(adown.contains?adown.contains(bup):a.compareDocumentPosition&&a.compareDocumentPosition(bup)&16))}:function(a,b){if(b){while(b=b.parentNode){if(b===a){return true}}}return false};sortOrder=hasCompare?function(a,b){if(a===b){hasDuplicate=true;return 0}var compare=!a.compareDocumentPosition-!b.compareDocumentPosition;if(compare){return compare}compare=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1;if(compare&1||!support.sortDetached&&b.compareDocumentPosition(a)===compare){if(a===doc||a.ownerDocument===preferredDoc&&contains(preferredDoc,a)){return-1}if(b===doc||b.ownerDocument===preferredDoc&&contains(preferredDoc,b)){return 1}return sortInput?indexOf(sortInput,a)-indexOf(sortInput,b):0}return compare&4?-1:1}:function(a,b){if(a===b){hasDuplicate=true;return 0}var cur,i=0,aup=a.parentNode,bup=b.parentNode,ap=[a],bp=[b];if(!aup||!bup){return a===doc?-1:b===doc?1:aup?-1:bup?1:sortInput?indexOf(sortInput,a)-indexOf(sortInput,b):0}else if(aup===bup){return siblingCheck(a,b)}cur=a;while(cur=cur.parentNode){ap.unshift(cur)}cur=b;while(cur=cur.parentNode){bp.unshift(cur)}while(ap[i]===bp[i]){i++}return i?siblingCheck(ap[i],bp[i]):ap[i]===preferredDoc?-1:bp[i]===preferredDoc?1:0};return doc};Sizzle.matches=function(expr,elements){return Sizzle(expr,null,null,elements)};Sizzle.matchesSelector=function(elem,expr){if((elem.ownerDocument||elem)!==document){setDocument(elem)}expr=expr.replace(rattributeQuotes,"='$1']");if(support.matchesSelector&&documentIsHTML&&(!rbuggyMatches||!rbuggyMatches.test(expr))&&(!rbuggyQSA||!rbuggyQSA.test(expr))){try{var ret=matches.call(elem,expr);if(ret||support.disconnectedMatch||elem.document&&elem.document.nodeType!==11){return ret}}catch(e){}}return Sizzle(expr,document,null,[elem]).length>0};Sizzle.contains=function(context,elem){if((context.ownerDocument||context)!==document){setDocument(context)}return contains(context,elem)};Sizzle.attr=function(elem,name){if((elem.ownerDocument||elem)!==document){setDocument(elem)}var fn=Expr.attrHandle[name.toLowerCase()],val=fn&&hasOwn.call(Expr.attrHandle,name.toLowerCase())?fn(elem,name,!documentIsHTML):undefined;return val!==undefined?val:support.attributes||!documentIsHTML?elem.getAttribute(name):(val=elem.getAttributeNode(name))&&val.specified?val.value:null};Sizzle.error=function(msg){throw new Error("Syntax error, unrecognized expression: "+msg)};Sizzle.uniqueSort=function(results){var elem,duplicates=[],j=0,i=0;hasDuplicate=!support.detectDuplicates;sortInput=!support.sortStable&&results.slice(0);results.sort(sortOrder);if(hasDuplicate){while(elem=results[i++]){if(elem===results[i]){j=duplicates.push(i)}}while(j--){results.splice(duplicates[j],1)}}sortInput=null;return results};getText=Sizzle.getText=function(elem){var node,ret="",i=0,nodeType=elem.nodeType;if(!nodeType){while(node=elem[i++]){ret+=getText(node)}}else if(nodeType===1||nodeType===9||nodeType===11){if(typeof elem.textContent==="string"){return elem.textContent}else{for(elem=elem.firstChild;elem;elem=elem.nextSibling){ret+=getText(elem)}}}else if(nodeType===3||nodeType===4){return elem.nodeValue}return ret};Expr=Sizzle.selectors={cacheLength:50,createPseudo:markFunction,match:matchExpr,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:true}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:true},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(match){match[1]=match[1].replace(runescape,funescape);match[3]=(match[3]||match[4]||match[5]||"").replace(runescape,funescape);if(match[2]==="~="){match[3]=" "+match[3]+" "}return match.slice(0,4)},CHILD:function(match){match[1]=match[1].toLowerCase();if(match[1].slice(0,3)==="nth"){if(!match[3]){Sizzle.error(match[0])}match[4]=+(match[4]?match[5]+(match[6]||1):2*(match[3]==="even"||match[3]==="odd"));match[5]=+(match[7]+match[8]||match[3]==="odd")}else if(match[3]){Sizzle.error(match[0])}return match},PSEUDO:function(match){var excess,unquoted=!match[6]&&match[2];if(matchExpr["CHILD"].test(match[0])){return null}if(match[3]){match[2]=match[4]||match[5]||""}else if(unquoted&&rpseudo.test(unquoted)&&(excess=tokenize(unquoted,true))&&(excess=unquoted.indexOf(")",unquoted.length-excess)-unquoted.length)){match[0]=match[0].slice(0,excess);match[2]=unquoted.slice(0,excess)}return match.slice(0,3)}},filter:{TAG:function(nodeNameSelector){var nodeName=nodeNameSelector.replace(runescape,funescape).toLowerCase();return nodeNameSelector==="*"?function(){return true}:function(elem){return elem.nodeName&&elem.nodeName.toLowerCase()===nodeName}},CLASS:function(className){var pattern=classCache[className+" "];return pattern||(pattern=new RegExp("(^|"+whitespace+")"+className+"("+whitespace+"|$)"))&&classCache(className,function(elem){return pattern.test(typeof elem.className==="string"&&elem.className||typeof elem.getAttribute!=="undefined"&&elem.getAttribute("class")||"")})},ATTR:function(name,operator,check){return function(elem){var result=Sizzle.attr(elem,name);if(result==null){return operator==="!="}if(!operator){return true}result+="";return operator==="="?result===check:operator==="!="?result!==check:operator==="^="?check&&result.indexOf(check)===0:operator==="*="?check&&result.indexOf(check)>-1:operator==="$="?check&&result.slice(-check.length)===check:operator==="~="?(" "+result.replace(rwhitespace," ")+" ").indexOf(check)>-1:operator==="|="?result===check||result.slice(0,check.length+1)===check+"-":false}},CHILD:function(type,what,argument,first,last){var simple=type.slice(0,3)!=="nth",forward=type.slice(-4)!=="last",ofType=what==="of-type";return first===1&&last===0?function(elem){return!!elem.parentNode}:function(elem,context,xml){var cache,outerCache,node,diff,nodeIndex,start,dir=simple!==forward?"nextSibling":"previousSibling",parent=elem.parentNode,name=ofType&&elem.nodeName.toLowerCase(),useCache=!xml&&!ofType;if(parent){if(simple){while(dir){node=elem;while(node=node[dir]){if(ofType?node.nodeName.toLowerCase()===name:node.nodeType===1){return false}}start=dir=type==="only"&&!start&&"nextSibling"}return true}start=[forward?parent.firstChild:parent.lastChild];if(forward&&useCache){outerCache=parent[expando]||(parent[expando]={});cache=outerCache[type]||[];nodeIndex=cache[0]===dirruns&&cache[1];diff=cache[0]===dirruns&&cache[2];node=nodeIndex&&parent.childNodes[nodeIndex];while(node=++nodeIndex&&node&&node[dir]||(diff=nodeIndex=0)||start.pop()){if(node.nodeType===1&&++diff&&node===elem){outerCache[type]=[dirruns,nodeIndex,diff];break}}}else if(useCache&&(cache=(elem[expando]||(elem[expando]={}))[type])&&cache[0]===dirruns){diff=cache[1]}else{while(node=++nodeIndex&&node&&node[dir]||(diff=nodeIndex=0)||start.pop()){if((ofType?node.nodeName.toLowerCase()===name:node.nodeType===1)&&++diff){if(useCache){(node[expando]||(node[expando]={}))[type]=[dirruns,diff]}if(node===elem){break}}}}diff-=last;return diff===first||diff%first===0&&diff/first>=0}}},PSEUDO:function(pseudo,argument){var args,fn=Expr.pseudos[pseudo]||Expr.setFilters[pseudo.toLowerCase()]||Sizzle.error("unsupported pseudo: "+pseudo);if(fn[expando]){return fn(argument)}if(fn.length>1){args=[pseudo,pseudo,"",argument];return Expr.setFilters.hasOwnProperty(pseudo.toLowerCase())?markFunction(function(seed,matches){var idx,matched=fn(seed,argument),i=matched.length;while(i--){idx=indexOf(seed,matched[i]);seed[idx]=!(matches[idx]=matched[i])}}):function(elem){return fn(elem,0,args)}}return fn}},pseudos:{not:markFunction(function(selector){var input=[],results=[],matcher=compile(selector.replace(rtrim,"$1"));return matcher[expando]?markFunction(function(seed,matches,context,xml){var elem,unmatched=matcher(seed,null,xml,[]),i=seed.length;while(i--){if(elem=unmatched[i]){seed[i]=!(matches[i]=elem)}}}):function(elem,context,xml){input[0]=elem;matcher(input,null,xml,results);input[0]=null;return!results.pop()}}),has:markFunction(function(selector){return function(elem){return Sizzle(selector,elem).length>0}}),contains:markFunction(function(text){text=text.replace(runescape,funescape);return function(elem){return(elem.textContent||elem.innerText||getText(elem)).indexOf(text)>-1}}),lang:markFunction(function(lang){if(!ridentifier.test(lang||"")){Sizzle.error("unsupported lang: "+lang)}lang=lang.replace(runescape,funescape).toLowerCase();return function(elem){var elemLang;do{if(elemLang=documentIsHTML?elem.lang:elem.getAttribute("xml:lang")||elem.getAttribute("lang")){elemLang=elemLang.toLowerCase();return elemLang===lang||elemLang.indexOf(lang+"-")===0}}while((elem=elem.parentNode)&&elem.nodeType===1);return false}}),target:function(elem){var hash=window.location&&window.location.hash;return hash&&hash.slice(1)===elem.id},root:function(elem){return elem===docElem},focus:function(elem){return elem===document.activeElement&&(!document.hasFocus||document.hasFocus())&&!!(elem.type||elem.href||~elem.tabIndex)},enabled:function(elem){return elem.disabled===false},disabled:function(elem){return elem.disabled===true},checked:function(elem){var nodeName=elem.nodeName.toLowerCase();return nodeName==="input"&&!!elem.checked||nodeName==="option"&&!!elem.selected},selected:function(elem){if(elem.parentNode){elem.parentNode.selectedIndex}return elem.selected===true},empty:function(elem){for(elem=elem.firstChild;elem;elem=elem.nextSibling){if(elem.nodeType<6){return false}}return true},parent:function(elem){return!Expr.pseudos["empty"](elem)},header:function(elem){return rheader.test(elem.nodeName)},input:function(elem){return rinputs.test(elem.nodeName)},button:function(elem){var name=elem.nodeName.toLowerCase();return name==="input"&&elem.type==="button"||name==="button"},text:function(elem){var attr;return elem.nodeName.toLowerCase()==="input"&&elem.type==="text"&&((attr=elem.getAttribute("type"))==null||attr.toLowerCase()==="text")},first:createPositionalPseudo(function(){return[0]}),last:createPositionalPseudo(function(matchIndexes,length){return[length-1]}),eq:createPositionalPseudo(function(matchIndexes,length,argument){return[argument<0?argument+length:argument]}),even:createPositionalPseudo(function(matchIndexes,length){var i=0;for(;i=0;){matchIndexes.push(i)}return matchIndexes}),gt:createPositionalPseudo(function(matchIndexes,length,argument){var i=argument<0?argument+length:argument;for(;++i1?function(elem,context,xml){var i=matchers.length;while(i--){if(!matchers[i](elem,context,xml)){return false}}return true}:matchers[0]}function multipleContexts(selector,contexts,results){var i=0,len=contexts.length;for(;i-1){seed[temp]=!(results[temp]=elem)}}}}else{matcherOut=condense(matcherOut===results?matcherOut.splice(preexisting,matcherOut.length):matcherOut);if(postFinder){postFinder(null,results,matcherOut,xml)}else{push.apply(results,matcherOut)}}})}function matcherFromTokens(tokens){var checkContext,matcher,j,len=tokens.length,leadingRelative=Expr.relative[tokens[0].type],implicitRelative=leadingRelative||Expr.relative[" "],i=leadingRelative?1:0,matchContext=addCombinator(function(elem){return elem===checkContext},implicitRelative,true),matchAnyContext=addCombinator(function(elem){return indexOf(checkContext,elem)>-1},implicitRelative,true),matchers=[function(elem,context,xml){var ret=!leadingRelative&&(xml||context!==outermostContext)||((checkContext=context).nodeType?matchContext(elem,context,xml):matchAnyContext(elem,context,xml));checkContext=null;return ret}];for(;i1&&elementMatcher(matchers),i>1&&toSelector(tokens.slice(0,i-1).concat({value:tokens[i-2].type===" "?"*":""})).replace(rtrim,"$1"),matcher,i0,byElement=elementMatchers.length>0,superMatcher=function(seed,context,xml,results,outermost){var elem,j,matcher,matchedCount=0,i="0",unmatched=seed&&[],setMatched=[],contextBackup=outermostContext,elems=seed||byElement&&Expr.find["TAG"]("*",outermost),dirrunsUnique=dirruns+=contextBackup==null?1:Math.random()||.1,len=elems.length;if(outermost){outermostContext=context!==document&&context}for(;i!==len&&(elem=elems[i])!=null;i++){if(byElement&&elem){j=0;while(matcher=elementMatchers[j++]){if(matcher(elem,context,xml)){results.push(elem);break}}if(outermost){dirruns=dirrunsUnique}}if(bySet){if(elem=!matcher&&elem){matchedCount--}if(seed){unmatched.push(elem)}}}matchedCount+=i;if(bySet&&i!==matchedCount){j=0;while(matcher=setMatchers[j++]){matcher(unmatched,setMatched,context,xml)}if(seed){if(matchedCount>0){while(i--){if(!(unmatched[i]||setMatched[i])){setMatched[i]=pop.call(results)}}}setMatched=condense(setMatched)}push.apply(results,setMatched);if(outermost&&!seed&&setMatched.length>0&&matchedCount+setMatchers.length>1){Sizzle.uniqueSort(results)}}if(outermost){dirruns=dirrunsUnique;outermostContext=contextBackup}return unmatched};return bySet?markFunction(superMatcher):superMatcher}compile=Sizzle.compile=function(selector,match){var i,setMatchers=[],elementMatchers=[],cached=compilerCache[selector+" "];if(!cached){if(!match){match=tokenize(selector)}i=match.length;while(i--){cached=matcherFromTokens(match[i]);if(cached[expando]){setMatchers.push(cached)}else{elementMatchers.push(cached)}}cached=compilerCache(selector,matcherFromGroupMatchers(elementMatchers,setMatchers));cached.selector=selector}return cached};select=Sizzle.select=function(selector,context,results,seed){var i,tokens,token,type,find,compiled=typeof selector==="function"&&selector,match=!seed&&tokenize(selector=compiled.selector||selector);results=results||[];if(match.length===1){tokens=match[0]=match[0].slice(0);if(tokens.length>2&&(token=tokens[0]).type==="ID"&&support.getById&&context.nodeType===9&&documentIsHTML&&Expr.relative[tokens[1].type]){context=(Expr.find["ID"](token.matches[0].replace(runescape,funescape),context)||[])[0];if(!context){return results}else if(compiled){context=context.parentNode}selector=selector.slice(tokens.shift().value.length)}i=matchExpr["needsContext"].test(selector)?0:tokens.length;while(i--){token=tokens[i];if(Expr.relative[type=token.type]){break}if(find=Expr.find[type]){if(seed=find(token.matches[0].replace(runescape,funescape),rsibling.test(tokens[0].type)&&testContext(context.parentNode)||context)){tokens.splice(i,1);selector=seed.length&&toSelector(tokens);if(!selector){push.apply(results,seed);return results}break}}}}(compiled||compile(selector,match))(seed,context,!documentIsHTML,results,rsibling.test(selector)&&testContext(context.parentNode)||context);return results};support.sortStable=expando.split("").sort(sortOrder).join("")===expando;support.detectDuplicates=!!hasDuplicate;setDocument();support.sortDetached=assert(function(div1){return div1.compareDocumentPosition(document.createElement("div"))&1});if(!assert(function(div){div.innerHTML="";return div.firstChild.getAttribute("href")==="#"})){addHandle("type|href|height|width",function(elem,name,isXML){if(!isXML){return elem.getAttribute(name,name.toLowerCase()==="type"?1:2)}})}if(!support.attributes||!assert(function(div){div.innerHTML="";div.firstChild.setAttribute("value","");return div.firstChild.getAttribute("value")===""})){addHandle("value",function(elem,name,isXML){if(!isXML&&elem.nodeName.toLowerCase()==="input"){return elem.defaultValue}})}if(!assert(function(div){return div.getAttribute("disabled")==null})){addHandle(booleans,function(elem,name,isXML){var val;if(!isXML){return elem[name]===true?name.toLowerCase():(val=elem.getAttributeNode(name))&&val.specified?val.value:null}})}return Sizzle}(window);jQuery.find=Sizzle;jQuery.expr=Sizzle.selectors;jQuery.expr[":"]=jQuery.expr.pseudos;jQuery.unique=Sizzle.uniqueSort;jQuery.text=Sizzle.getText;jQuery.isXMLDoc=Sizzle.isXML;jQuery.contains=Sizzle.contains;var rneedsContext=jQuery.expr.match.needsContext;var rsingleTag=/^<(\w+)\s*\/?>(?:<\/\1>|)$/;var risSimple=/^.[^:#\[\.,]*$/;function winnow(elements,qualifier,not){if(jQuery.isFunction(qualifier)){return jQuery.grep(elements,function(elem,i){return!!qualifier.call(elem,i,elem)!==not})}if(qualifier.nodeType){return jQuery.grep(elements,function(elem){return elem===qualifier!==not})}if(typeof qualifier==="string"){if(risSimple.test(qualifier)){return jQuery.filter(qualifier,elements,not)}qualifier=jQuery.filter(qualifier,elements)}return jQuery.grep(elements,function(elem){return jQuery.inArray(elem,qualifier)>=0!==not})}jQuery.filter=function(expr,elems,not){var elem=elems[0];if(not){expr=":not("+expr+")"}return elems.length===1&&elem.nodeType===1?jQuery.find.matchesSelector(elem,expr)?[elem]:[]:jQuery.find.matches(expr,jQuery.grep(elems,function(elem){return elem.nodeType===1}))};jQuery.fn.extend({find:function(selector){var i,ret=[],self=this,len=self.length;if(typeof selector!=="string"){return this.pushStack(jQuery(selector).filter(function(){for(i=0;i1?jQuery.unique(ret):ret);ret.selector=this.selector?this.selector+" "+selector:selector;return ret},filter:function(selector){return this.pushStack(winnow(this,selector||[],false))},not:function(selector){return this.pushStack(winnow(this,selector||[],true))},is:function(selector){return!!winnow(this,typeof selector==="string"&&rneedsContext.test(selector)?jQuery(selector):selector||[],false).length}});var rootjQuery,document=window.document,rquickExpr=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,init=jQuery.fn.init=function(selector,context){var match,elem;if(!selector){return this}if(typeof selector==="string"){if(selector.charAt(0)==="<"&&selector.charAt(selector.length-1)===">"&&selector.length>=3){match=[null,selector,null]}else{match=rquickExpr.exec(selector)}if(match&&(match[1]||!context)){if(match[1]){context=context instanceof jQuery?context[0]:context;jQuery.merge(this,jQuery.parseHTML(match[1],context&&context.nodeType?context.ownerDocument||context:document,true));if(rsingleTag.test(match[1])&&jQuery.isPlainObject(context)){for(match in context){if(jQuery.isFunction(this[match])){this[match](context[match])}else{this.attr(match,context[match])}}}return this}else{elem=document.getElementById(match[2]);if(elem&&elem.parentNode){if(elem.id!==match[2]){return rootjQuery.find(selector)}this.length=1;this[0]=elem}this.context=document;this.selector=selector;return this}}else if(!context||context.jquery){return(context||rootjQuery).find(selector)}else{return this.constructor(context).find(selector)}}else if(selector.nodeType){this.context=this[0]=selector;this.length=1;return this}else if(jQuery.isFunction(selector)){return typeof rootjQuery.ready!=="undefined"?rootjQuery.ready(selector):selector(jQuery)}if(selector.selector!==undefined){this.selector=selector.selector;this.context=selector.context}return jQuery.makeArray(selector,this)};init.prototype=jQuery.fn;rootjQuery=jQuery(document);var rparentsprev=/^(?:parents|prev(?:Until|All))/,guaranteedUnique={children:true,contents:true,next:true,prev:true};jQuery.extend({dir:function(elem,dir,until){var matched=[],cur=elem[dir];while(cur&&cur.nodeType!==9&&(until===undefined||cur.nodeType!==1||!jQuery(cur).is(until))){if(cur.nodeType===1){matched.push(cur)}cur=cur[dir]}return matched},sibling:function(n,elem){var r=[];for(;n;n=n.nextSibling){if(n.nodeType===1&&n!==elem){r.push(n); -}}return r}});jQuery.fn.extend({has:function(target){var i,targets=jQuery(target,this),len=targets.length;return this.filter(function(){for(i=0;i-1:cur.nodeType===1&&jQuery.find.matchesSelector(cur,selectors))){matched.push(cur);break}}}return this.pushStack(matched.length>1?jQuery.unique(matched):matched)},index:function(elem){if(!elem){return this[0]&&this[0].parentNode?this.first().prevAll().length:-1}if(typeof elem==="string"){return jQuery.inArray(this[0],jQuery(elem))}return jQuery.inArray(elem.jquery?elem[0]:elem,this)},add:function(selector,context){return this.pushStack(jQuery.unique(jQuery.merge(this.get(),jQuery(selector,context))))},addBack:function(selector){return this.add(selector==null?this.prevObject:this.prevObject.filter(selector))}});function sibling(cur,dir){do{cur=cur[dir]}while(cur&&cur.nodeType!==1);return cur}jQuery.each({parent:function(elem){var parent=elem.parentNode;return parent&&parent.nodeType!==11?parent:null},parents:function(elem){return jQuery.dir(elem,"parentNode")},parentsUntil:function(elem,i,until){return jQuery.dir(elem,"parentNode",until)},next:function(elem){return sibling(elem,"nextSibling")},prev:function(elem){return sibling(elem,"previousSibling")},nextAll:function(elem){return jQuery.dir(elem,"nextSibling")},prevAll:function(elem){return jQuery.dir(elem,"previousSibling")},nextUntil:function(elem,i,until){return jQuery.dir(elem,"nextSibling",until)},prevUntil:function(elem,i,until){return jQuery.dir(elem,"previousSibling",until)},siblings:function(elem){return jQuery.sibling((elem.parentNode||{}).firstChild,elem)},children:function(elem){return jQuery.sibling(elem.firstChild)},contents:function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.merge([],elem.childNodes)}},function(name,fn){jQuery.fn[name]=function(until,selector){var ret=jQuery.map(this,fn,until);if(name.slice(-5)!=="Until"){selector=until}if(selector&&typeof selector==="string"){ret=jQuery.filter(selector,ret)}if(this.length>1){if(!guaranteedUnique[name]){ret=jQuery.unique(ret)}if(rparentsprev.test(name)){ret=ret.reverse()}}return this.pushStack(ret)}});var rnotwhite=/\S+/g;var optionsCache={};function createOptions(options){var object=optionsCache[options]={};jQuery.each(options.match(rnotwhite)||[],function(_,flag){object[flag]=true});return object}jQuery.Callbacks=function(options){options=typeof options==="string"?optionsCache[options]||createOptions(options):jQuery.extend({},options);var firing,memory,fired,firingLength,firingIndex,firingStart,list=[],stack=!options.once&&[],fire=function(data){memory=options.memory&&data;fired=true;firingIndex=firingStart||0;firingStart=0;firingLength=list.length;firing=true;for(;list&&firingIndex-1){list.splice(index,1);if(firing){if(index<=firingLength){firingLength--}if(index<=firingIndex){firingIndex--}}}})}return this},has:function(fn){return fn?jQuery.inArray(fn,list)>-1:!!(list&&list.length)},empty:function(){list=[];firingLength=0;return this},disable:function(){list=stack=memory=undefined;return this},disabled:function(){return!list},lock:function(){stack=undefined;if(!memory){self.disable()}return this},locked:function(){return!stack},fireWith:function(context,args){if(list&&(!fired||stack)){args=args||[];args=[context,args.slice?args.slice():args];if(firing){stack.push(args)}else{fire(args)}}return this},fire:function(){self.fireWith(this,arguments);return this},fired:function(){return!!fired}};return self};jQuery.extend({Deferred:function(func){var tuples=[["resolve","done",jQuery.Callbacks("once memory"),"resolved"],["reject","fail",jQuery.Callbacks("once memory"),"rejected"],["notify","progress",jQuery.Callbacks("memory")]],state="pending",promise={state:function(){return state},always:function(){deferred.done(arguments).fail(arguments);return this},then:function(){var fns=arguments;return jQuery.Deferred(function(newDefer){jQuery.each(tuples,function(i,tuple){var fn=jQuery.isFunction(fns[i])&&fns[i];deferred[tuple[1]](function(){var returned=fn&&fn.apply(this,arguments);if(returned&&jQuery.isFunction(returned.promise)){returned.promise().done(newDefer.resolve).fail(newDefer.reject).progress(newDefer.notify)}else{newDefer[tuple[0]+"With"](this===promise?newDefer.promise():this,fn?[returned]:arguments)}})});fns=null}).promise()},promise:function(obj){return obj!=null?jQuery.extend(obj,promise):promise}},deferred={};promise.pipe=promise.then;jQuery.each(tuples,function(i,tuple){var list=tuple[2],stateString=tuple[3];promise[tuple[1]]=list.add;if(stateString){list.add(function(){state=stateString},tuples[i^1][2].disable,tuples[2][2].lock)}deferred[tuple[0]]=function(){deferred[tuple[0]+"With"](this===deferred?promise:this,arguments);return this};deferred[tuple[0]+"With"]=list.fireWith});promise.promise(deferred);if(func){func.call(deferred,deferred)}return deferred},when:function(subordinate){var i=0,resolveValues=slice.call(arguments),length=resolveValues.length,remaining=length!==1||subordinate&&jQuery.isFunction(subordinate.promise)?length:0,deferred=remaining===1?subordinate:jQuery.Deferred(),updateFunc=function(i,contexts,values){return function(value){contexts[i]=this;values[i]=arguments.length>1?slice.call(arguments):value;if(values===progressValues){deferred.notifyWith(contexts,values)}else if(!--remaining){deferred.resolveWith(contexts,values)}}},progressValues,progressContexts,resolveContexts;if(length>1){progressValues=new Array(length);progressContexts=new Array(length);resolveContexts=new Array(length);for(;i0){return}readyList.resolveWith(document,[jQuery]);if(jQuery.fn.triggerHandler){jQuery(document).triggerHandler("ready");jQuery(document).off("ready")}}});function detach(){if(document.addEventListener){document.removeEventListener("DOMContentLoaded",completed,false);window.removeEventListener("load",completed,false)}else{document.detachEvent("onreadystatechange",completed);window.detachEvent("onload",completed)}}function completed(){if(document.addEventListener||event.type==="load"||document.readyState==="complete"){detach();jQuery.ready()}}jQuery.ready.promise=function(obj){if(!readyList){readyList=jQuery.Deferred();if(document.readyState==="complete"){setTimeout(jQuery.ready)}else if(document.addEventListener){document.addEventListener("DOMContentLoaded",completed,false);window.addEventListener("load",completed,false)}else{document.attachEvent("onreadystatechange",completed);window.attachEvent("onload",completed);var top=false;try{top=window.frameElement==null&&document.documentElement}catch(e){}if(top&&top.doScroll){(function doScrollCheck(){if(!jQuery.isReady){try{top.doScroll("left")}catch(e){return setTimeout(doScrollCheck,50)}detach();jQuery.ready()}})()}}}return readyList.promise(obj)};var strundefined=typeof undefined;var i;for(i in jQuery(support)){break}support.ownLast=i!=="0";support.inlineBlockNeedsLayout=false;jQuery(function(){var val,div,body,container;body=document.getElementsByTagName("body")[0];if(!body||!body.style){return}div=document.createElement("div");container=document.createElement("div");container.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px";body.appendChild(container).appendChild(div);if(typeof div.style.zoom!==strundefined){div.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1";support.inlineBlockNeedsLayout=val=div.offsetWidth===3;if(val){body.style.zoom=1}}body.removeChild(container)});(function(){var div=document.createElement("div");if(support.deleteExpando==null){support.deleteExpando=true;try{delete div.test}catch(e){support.deleteExpando=false}}div=null})();jQuery.acceptData=function(elem){var noData=jQuery.noData[(elem.nodeName+" ").toLowerCase()],nodeType=+elem.nodeType||1;return nodeType!==1&&nodeType!==9?false:!noData||noData!==true&&elem.getAttribute("classid")===noData};var rbrace=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,rmultiDash=/([A-Z])/g;function dataAttr(elem,key,data){if(data===undefined&&elem.nodeType===1){var name="data-"+key.replace(rmultiDash,"-$1").toLowerCase();data=elem.getAttribute(name);if(typeof data==="string"){try{data=data==="true"?true:data==="false"?false:data==="null"?null:+data+""===data?+data:rbrace.test(data)?jQuery.parseJSON(data):data}catch(e){}jQuery.data(elem,key,data)}else{data=undefined}}return data}function isEmptyDataObject(obj){var name;for(name in obj){if(name==="data"&&jQuery.isEmptyObject(obj[name])){continue}if(name!=="toJSON"){return false}}return true}function internalData(elem,name,data,pvt){if(!jQuery.acceptData(elem)){return}var ret,thisCache,internalKey=jQuery.expando,isNode=elem.nodeType,cache=isNode?jQuery.cache:elem,id=isNode?elem[internalKey]:elem[internalKey]&&internalKey;if((!id||!cache[id]||!pvt&&!cache[id].data)&&data===undefined&&typeof name==="string"){return}if(!id){if(isNode){id=elem[internalKey]=deletedIds.pop()||jQuery.guid++}else{id=internalKey}}if(!cache[id]){cache[id]=isNode?{}:{toJSON:jQuery.noop}}if(typeof name==="object"||typeof name==="function"){if(pvt){cache[id]=jQuery.extend(cache[id],name)}else{cache[id].data=jQuery.extend(cache[id].data,name)}}thisCache=cache[id];if(!pvt){if(!thisCache.data){thisCache.data={}}thisCache=thisCache.data}if(data!==undefined){thisCache[jQuery.camelCase(name)]=data}if(typeof name==="string"){ret=thisCache[name];if(ret==null){ret=thisCache[jQuery.camelCase(name)]}}else{ret=thisCache}return ret}function internalRemoveData(elem,name,pvt){if(!jQuery.acceptData(elem)){return}var thisCache,i,isNode=elem.nodeType,cache=isNode?jQuery.cache:elem,id=isNode?elem[jQuery.expando]:jQuery.expando;if(!cache[id]){return}if(name){thisCache=pvt?cache[id]:cache[id].data;if(thisCache){if(!jQuery.isArray(name)){if(name in thisCache){name=[name]}else{name=jQuery.camelCase(name);if(name in thisCache){name=[name]}else{name=name.split(" ")}}}else{name=name.concat(jQuery.map(name,jQuery.camelCase))}i=name.length;while(i--){delete thisCache[name[i]]}if(pvt?!isEmptyDataObject(thisCache):!jQuery.isEmptyObject(thisCache)){return}}}if(!pvt){delete cache[id].data;if(!isEmptyDataObject(cache[id])){return}}if(isNode){jQuery.cleanData([elem],true)}else if(support.deleteExpando||cache!=cache.window){delete cache[id]}else{cache[id]=null}}jQuery.extend({cache:{},noData:{"applet ":true,"embed ":true,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(elem){elem=elem.nodeType?jQuery.cache[elem[jQuery.expando]]:elem[jQuery.expando];return!!elem&&!isEmptyDataObject(elem)},data:function(elem,name,data){return internalData(elem,name,data)},removeData:function(elem,name){return internalRemoveData(elem,name)},_data:function(elem,name,data){return internalData(elem,name,data,true)},_removeData:function(elem,name){return internalRemoveData(elem,name,true)}});jQuery.fn.extend({data:function(key,value){var i,name,data,elem=this[0],attrs=elem&&elem.attributes;if(key===undefined){if(this.length){data=jQuery.data(elem);if(elem.nodeType===1&&!jQuery._data(elem,"parsedAttrs")){i=attrs.length;while(i--){if(attrs[i]){name=attrs[i].name;if(name.indexOf("data-")===0){name=jQuery.camelCase(name.slice(5));dataAttr(elem,name,data[name])}}}jQuery._data(elem,"parsedAttrs",true)}}return data}if(typeof key==="object"){return this.each(function(){jQuery.data(this,key)})}return arguments.length>1?this.each(function(){jQuery.data(this,key,value)}):elem?dataAttr(elem,key,jQuery.data(elem,key)):undefined},removeData:function(key){return this.each(function(){jQuery.removeData(this,key)})}});jQuery.extend({queue:function(elem,type,data){var queue;if(elem){type=(type||"fx")+"queue";queue=jQuery._data(elem,type);if(data){if(!queue||jQuery.isArray(data)){queue=jQuery._data(elem,type,jQuery.makeArray(data))}else{queue.push(data)}}return queue||[]}},dequeue:function(elem,type){type=type||"fx";var queue=jQuery.queue(elem,type),startLength=queue.length,fn=queue.shift(),hooks=jQuery._queueHooks(elem,type),next=function(){jQuery.dequeue(elem,type)};if(fn==="inprogress"){fn=queue.shift();startLength--}if(fn){if(type==="fx"){queue.unshift("inprogress")}delete hooks.stop;fn.call(elem,next,hooks)}if(!startLength&&hooks){hooks.empty.fire()}},_queueHooks:function(elem,type){var key=type+"queueHooks";return jQuery._data(elem,key)||jQuery._data(elem,key,{empty:jQuery.Callbacks("once memory").add(function(){jQuery._removeData(elem,type+"queue");jQuery._removeData(elem,key)})})}});jQuery.fn.extend({queue:function(type,data){var setter=2;if(typeof type!=="string"){data=type;type="fx";setter--}if(arguments.length
a";support.leadingWhitespace=div.firstChild.nodeType===3;support.tbody=!div.getElementsByTagName("tbody").length;support.htmlSerialize=!!div.getElementsByTagName("link").length;support.html5Clone=document.createElement("nav").cloneNode(true).outerHTML!=="<:nav>";input.type="checkbox";input.checked=true;fragment.appendChild(input);support.appendChecked=input.checked;div.innerHTML="";support.noCloneChecked=!!div.cloneNode(true).lastChild.defaultValue;fragment.appendChild(div);div.innerHTML="";support.checkClone=div.cloneNode(true).cloneNode(true).lastChild.checked;support.noCloneEvent=true;if(div.attachEvent){div.attachEvent("onclick",function(){support.noCloneEvent=false});div.cloneNode(true).click()}if(support.deleteExpando==null){support.deleteExpando=true;try{delete div.test}catch(e){support.deleteExpando=false}}})();(function(){var i,eventName,div=document.createElement("div");for(i in{submit:true,change:true,focusin:true}){eventName="on"+i;if(!(support[i+"Bubbles"]=eventName in window)){div.setAttribute(eventName,"t");support[i+"Bubbles"]=div.attributes[eventName].expando===false}}div=null})();var rformElems=/^(?:input|select|textarea)$/i,rkeyEvent=/^key/,rmouseEvent=/^(?:mouse|pointer|contextmenu)|click/,rfocusMorph=/^(?:focusinfocus|focusoutblur)$/,rtypenamespace=/^([^.]*)(?:\.(.+)|)$/;function returnTrue(){return true}function returnFalse(){return false}function safeActiveElement(){try{return document.activeElement}catch(err){}}jQuery.event={global:{},add:function(elem,types,handler,data,selector){var tmp,events,t,handleObjIn,special,eventHandle,handleObj,handlers,type,namespaces,origType,elemData=jQuery._data(elem);if(!elemData){return}if(handler.handler){handleObjIn=handler;handler=handleObjIn.handler;selector=handleObjIn.selector}if(!handler.guid){handler.guid=jQuery.guid++}if(!(events=elemData.events)){events=elemData.events={}}if(!(eventHandle=elemData.handle)){eventHandle=elemData.handle=function(e){return typeof jQuery!==strundefined&&(!e||jQuery.event.triggered!==e.type)?jQuery.event.dispatch.apply(eventHandle.elem,arguments):undefined};eventHandle.elem=elem}types=(types||"").match(rnotwhite)||[""];t=types.length;while(t--){tmp=rtypenamespace.exec(types[t])||[];type=origType=tmp[1];namespaces=(tmp[2]||"").split(".").sort();if(!type){continue}special=jQuery.event.special[type]||{};type=(selector?special.delegateType:special.bindType)||type;special=jQuery.event.special[type]||{};handleObj=jQuery.extend({type:type,origType:origType,data:data,handler:handler,guid:handler.guid,selector:selector,needsContext:selector&&jQuery.expr.match.needsContext.test(selector),namespace:namespaces.join(".")},handleObjIn);if(!(handlers=events[type])){handlers=events[type]=[];handlers.delegateCount=0;if(!special.setup||special.setup.call(elem,data,namespaces,eventHandle)===false){if(elem.addEventListener){elem.addEventListener(type,eventHandle,false)}else if(elem.attachEvent){elem.attachEvent("on"+type,eventHandle)}}}if(special.add){special.add.call(elem,handleObj);if(!handleObj.handler.guid){handleObj.handler.guid=handler.guid}}if(selector){handlers.splice(handlers.delegateCount++,0,handleObj)}else{handlers.push(handleObj)}jQuery.event.global[type]=true}elem=null},remove:function(elem,types,handler,selector,mappedTypes){var j,handleObj,tmp,origCount,t,events,special,handlers,type,namespaces,origType,elemData=jQuery.hasData(elem)&&jQuery._data(elem);if(!elemData||!(events=elemData.events)){return}types=(types||"").match(rnotwhite)||[""];t=types.length;while(t--){tmp=rtypenamespace.exec(types[t])||[];type=origType=tmp[1];namespaces=(tmp[2]||"").split(".").sort();if(!type){for(type in events){jQuery.event.remove(elem,type+types[t],handler,selector,true)}continue}special=jQuery.event.special[type]||{};type=(selector?special.delegateType:special.bindType)||type;handlers=events[type]||[];tmp=tmp[2]&&new RegExp("(^|\\.)"+namespaces.join("\\.(?:.*\\.|)")+"(\\.|$)");origCount=j=handlers.length;while(j--){handleObj=handlers[j];if((mappedTypes||origType===handleObj.origType)&&(!handler||handler.guid===handleObj.guid)&&(!tmp||tmp.test(handleObj.namespace))&&(!selector||selector===handleObj.selector||selector==="**"&&handleObj.selector)){handlers.splice(j,1);if(handleObj.selector){handlers.delegateCount--}if(special.remove){special.remove.call(elem,handleObj)}}}if(origCount&&!handlers.length){if(!special.teardown||special.teardown.call(elem,namespaces,elemData.handle)===false){jQuery.removeEvent(elem,type,elemData.handle)}delete events[type]}}if(jQuery.isEmptyObject(events)){delete elemData.handle;jQuery._removeData(elem,"events")}},trigger:function(event,data,elem,onlyHandlers){var handle,ontype,cur,bubbleType,special,tmp,i,eventPath=[elem||document],type=hasOwn.call(event,"type")?event.type:event,namespaces=hasOwn.call(event,"namespace")?event.namespace.split("."):[];cur=tmp=elem=elem||document;if(elem.nodeType===3||elem.nodeType===8){return}if(rfocusMorph.test(type+jQuery.event.triggered)){return}if(type.indexOf(".")>=0){namespaces=type.split(".");type=namespaces.shift();namespaces.sort()}ontype=type.indexOf(":")<0&&"on"+type;event=event[jQuery.expando]?event:new jQuery.Event(type,typeof event==="object"&&event);event.isTrigger=onlyHandlers?2:3;event.namespace=namespaces.join(".");event.namespace_re=event.namespace?new RegExp("(^|\\.)"+namespaces.join("\\.(?:.*\\.|)")+"(\\.|$)"):null;event.result=undefined;if(!event.target){event.target=elem}data=data==null?[event]:jQuery.makeArray(data,[event]);special=jQuery.event.special[type]||{};if(!onlyHandlers&&special.trigger&&special.trigger.apply(elem,data)===false){return}if(!onlyHandlers&&!special.noBubble&&!jQuery.isWindow(elem)){bubbleType=special.delegateType||type;if(!rfocusMorph.test(bubbleType+type)){cur=cur.parentNode}for(;cur;cur=cur.parentNode){eventPath.push(cur);tmp=cur}if(tmp===(elem.ownerDocument||document)){eventPath.push(tmp.defaultView||tmp.parentWindow||window)}}i=0;while((cur=eventPath[i++])&&!event.isPropagationStopped()){event.type=i>1?bubbleType:special.bindType||type;handle=(jQuery._data(cur,"events")||{})[event.type]&&jQuery._data(cur,"handle");if(handle){handle.apply(cur,data)}handle=ontype&&cur[ontype];if(handle&&handle.apply&&jQuery.acceptData(cur)){event.result=handle.apply(cur,data);if(event.result===false){event.preventDefault()}}}event.type=type;if(!onlyHandlers&&!event.isDefaultPrevented()){if((!special._default||special._default.apply(eventPath.pop(),data)===false)&&jQuery.acceptData(elem)){if(ontype&&elem[type]&&!jQuery.isWindow(elem)){tmp=elem[ontype];if(tmp){elem[ontype]=null}jQuery.event.triggered=type;try{elem[type]()}catch(e){}jQuery.event.triggered=undefined;if(tmp){elem[ontype]=tmp}}}}return event.result},dispatch:function(event){event=jQuery.event.fix(event);var i,ret,handleObj,matched,j,handlerQueue=[],args=slice.call(arguments),handlers=(jQuery._data(this,"events")||{})[event.type]||[],special=jQuery.event.special[event.type]||{};args[0]=event;event.delegateTarget=this;if(special.preDispatch&&special.preDispatch.call(this,event)===false){return}handlerQueue=jQuery.event.handlers.call(this,event,handlers);i=0;while((matched=handlerQueue[i++])&&!event.isPropagationStopped()){event.currentTarget=matched.elem;j=0;while((handleObj=matched.handlers[j++])&&!event.isImmediatePropagationStopped()){if(!event.namespace_re||event.namespace_re.test(handleObj.namespace)){event.handleObj=handleObj;event.data=handleObj.data;ret=((jQuery.event.special[handleObj.origType]||{}).handle||handleObj.handler).apply(matched.elem,args);if(ret!==undefined){if((event.result=ret)===false){event.preventDefault();event.stopPropagation()}}}}}if(special.postDispatch){special.postDispatch.call(this,event)}return event.result},handlers:function(event,handlers){var sel,handleObj,matches,i,handlerQueue=[],delegateCount=handlers.delegateCount,cur=event.target;if(delegateCount&&cur.nodeType&&(!event.button||event.type!=="click")){for(;cur!=this;cur=cur.parentNode||this){if(cur.nodeType===1&&(cur.disabled!==true||event.type!=="click")){matches=[];for(i=0;i=0:jQuery.find(sel,this,null,[cur]).length}if(matches[sel]){matches.push(handleObj)}}if(matches.length){handlerQueue.push({elem:cur,handlers:matches})}}}}if(delegateCount]","i"),rleadingWhitespace=/^\s+/,rxhtmlTag=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,rtagName=/<([\w:]+)/,rtbody=/\s*$/g,wrapMap={option:[1,""],legend:[1,"
","
"],area:[1,"",""],param:[1,"",""],thead:[1,"","
"],tr:[2,"","
"],col:[2,"","
"],td:[3,"","
"],_default:support.htmlSerialize?[0,"",""]:[1,"X
","
"]},safeFragment=createSafeFragment(document),fragmentDiv=safeFragment.appendChild(document.createElement("div"));wrapMap.optgroup=wrapMap.option;wrapMap.tbody=wrapMap.tfoot=wrapMap.colgroup=wrapMap.caption=wrapMap.thead;wrapMap.th=wrapMap.td;function getAll(context,tag){var elems,elem,i=0,found=typeof context.getElementsByTagName!==strundefined?context.getElementsByTagName(tag||"*"):typeof context.querySelectorAll!==strundefined?context.querySelectorAll(tag||"*"):undefined;if(!found){for(found=[],elems=context.childNodes||context;(elem=elems[i])!=null;i++){if(!tag||jQuery.nodeName(elem,tag)){found.push(elem)}else{jQuery.merge(found,getAll(elem,tag))}}}return tag===undefined||tag&&jQuery.nodeName(context,tag)?jQuery.merge([context],found):found}function fixDefaultChecked(elem){if(rcheckableType.test(elem.type)){elem.defaultChecked=elem.checked}}function manipulationTarget(elem,content){return jQuery.nodeName(elem,"table")&&jQuery.nodeName(content.nodeType!==11?content:content.firstChild,"tr")?elem.getElementsByTagName("tbody")[0]||elem.appendChild(elem.ownerDocument.createElement("tbody")):elem}function disableScript(elem){elem.type=(jQuery.find.attr(elem,"type")!==null)+"/"+elem.type;return elem}function restoreScript(elem){var match=rscriptTypeMasked.exec(elem.type);if(match){elem.type=match[1]}else{elem.removeAttribute("type")}return elem}function setGlobalEval(elems,refElements){var elem,i=0;for(;(elem=elems[i])!=null;i++){jQuery._data(elem,"globalEval",!refElements||jQuery._data(refElements[i],"globalEval"))}}function cloneCopyEvent(src,dest){if(dest.nodeType!==1||!jQuery.hasData(src)){return}var type,i,l,oldData=jQuery._data(src),curData=jQuery._data(dest,oldData),events=oldData.events;if(events){delete curData.handle;curData.events={};for(type in events){for(i=0,l=events[type].length;i")){clone=elem.cloneNode(true)}else{fragmentDiv.innerHTML=elem.outerHTML;fragmentDiv.removeChild(clone=fragmentDiv.firstChild)}if((!support.noCloneEvent||!support.noCloneChecked)&&(elem.nodeType===1||elem.nodeType===11)&&!jQuery.isXMLDoc(elem)){destElements=getAll(clone);srcElements=getAll(elem);for(i=0;(node=srcElements[i])!=null;++i){if(destElements[i]){fixCloneNodeIssues(node,destElements[i])}}}if(dataAndEvents){if(deepDataAndEvents){srcElements=srcElements||getAll(elem);destElements=destElements||getAll(clone);for(i=0;(node=srcElements[i])!=null;i++){cloneCopyEvent(node,destElements[i])}}else{cloneCopyEvent(elem,clone)}}destElements=getAll(clone,"script");if(destElements.length>0){setGlobalEval(destElements,!inPage&&getAll(elem,"script"))}destElements=srcElements=node=null;return clone},buildFragment:function(elems,context,scripts,selection){var j,elem,contains,tmp,tag,tbody,wrap,l=elems.length,safe=createSafeFragment(context),nodes=[],i=0;for(;i")+wrap[2];j=wrap[0];while(j--){tmp=tmp.lastChild}if(!support.leadingWhitespace&&rleadingWhitespace.test(elem)){nodes.push(context.createTextNode(rleadingWhitespace.exec(elem)[0]))}if(!support.tbody){elem=tag==="table"&&!rtbody.test(elem)?tmp.firstChild:wrap[1]===""&&!rtbody.test(elem)?tmp:0;j=elem&&elem.childNodes.length;while(j--){if(jQuery.nodeName(tbody=elem.childNodes[j],"tbody")&&!tbody.childNodes.length){elem.removeChild(tbody)}}}jQuery.merge(nodes,tmp.childNodes);tmp.textContent="";while(tmp.firstChild){tmp.removeChild(tmp.firstChild)}tmp=safe.lastChild}}}if(tmp){safe.removeChild(tmp)}if(!support.appendChecked){jQuery.grep(getAll(nodes,"input"),fixDefaultChecked)}i=0;while(elem=nodes[i++]){if(selection&&jQuery.inArray(elem,selection)!==-1){continue}contains=jQuery.contains(elem.ownerDocument,elem);tmp=getAll(safe.appendChild(elem),"script");if(contains){setGlobalEval(tmp)}if(scripts){j=0;while(elem=tmp[j++]){if(rscriptType.test(elem.type||"")){scripts.push(elem)}}}}tmp=null;return safe},cleanData:function(elems,acceptData){var elem,type,id,data,i=0,internalKey=jQuery.expando,cache=jQuery.cache,deleteExpando=support.deleteExpando,special=jQuery.event.special;for(;(elem=elems[i])!=null;i++){if(acceptData||jQuery.acceptData(elem)){id=elem[internalKey];data=id&&cache[id];if(data){if(data.events){for(type in data.events){if(special[type]){jQuery.event.remove(elem,type)}else{jQuery.removeEvent(elem,type,data.handle)}}}if(cache[id]){delete cache[id];if(deleteExpando){delete elem[internalKey]}else if(typeof elem.removeAttribute!==strundefined){elem.removeAttribute(internalKey)}else{elem[internalKey]=null}deletedIds.push(id)}}}}}});jQuery.fn.extend({text:function(value){return access(this,function(value){return value===undefined?jQuery.text(this):this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(value))},null,value,arguments.length)},append:function(){return this.domManip(arguments,function(elem){if(this.nodeType===1||this.nodeType===11||this.nodeType===9){var target=manipulationTarget(this,elem);target.appendChild(elem)}})},prepend:function(){return this.domManip(arguments,function(elem){if(this.nodeType===1||this.nodeType===11||this.nodeType===9){var target=manipulationTarget(this,elem);target.insertBefore(elem,target.firstChild)}})},before:function(){return this.domManip(arguments,function(elem){if(this.parentNode){this.parentNode.insertBefore(elem,this)}})},after:function(){return this.domManip(arguments,function(elem){if(this.parentNode){this.parentNode.insertBefore(elem,this.nextSibling)}})},remove:function(selector,keepData){var elem,elems=selector?jQuery.filter(selector,this):this,i=0;for(;(elem=elems[i])!=null;i++){if(!keepData&&elem.nodeType===1){jQuery.cleanData(getAll(elem))}if(elem.parentNode){if(keepData&&jQuery.contains(elem.ownerDocument,elem)){setGlobalEval(getAll(elem,"script"))}elem.parentNode.removeChild(elem)}}return this},empty:function(){var elem,i=0;for(;(elem=this[i])!=null;i++){if(elem.nodeType===1){jQuery.cleanData(getAll(elem,false))}while(elem.firstChild){elem.removeChild(elem.firstChild)}if(elem.options&&jQuery.nodeName(elem,"select")){elem.options.length=0}}return this},clone:function(dataAndEvents,deepDataAndEvents){dataAndEvents=dataAndEvents==null?false:dataAndEvents;deepDataAndEvents=deepDataAndEvents==null?dataAndEvents:deepDataAndEvents;return this.map(function(){return jQuery.clone(this,dataAndEvents,deepDataAndEvents)})},html:function(value){return access(this,function(value){var elem=this[0]||{},i=0,l=this.length;if(value===undefined){return elem.nodeType===1?elem.innerHTML.replace(rinlinejQuery,""):undefined}if(typeof value==="string"&&!rnoInnerhtml.test(value)&&(support.htmlSerialize||!rnoshimcache.test(value))&&(support.leadingWhitespace||!rleadingWhitespace.test(value))&&!wrapMap[(rtagName.exec(value)||["",""])[1].toLowerCase()]){value=value.replace(rxhtmlTag,"<$1>");try{for(;i1&&typeof value==="string"&&!support.checkClone&&rchecked.test(value)){return this.each(function(index){var self=set.eq(index);if(isFunction){args[0]=value.call(this,index,self.html())}self.domManip(args,callback)})}if(l){fragment=jQuery.buildFragment(args,this[0].ownerDocument,false,this);first=fragment.firstChild;if(fragment.childNodes.length===1){fragment=first}if(first){scripts=jQuery.map(getAll(fragment,"script"),disableScript);hasScripts=scripts.length;for(;i")).appendTo(doc.documentElement);doc=(iframe[0].contentWindow||iframe[0].contentDocument).document;doc.write();doc.close();display=actualDisplay(nodeName,doc);iframe.detach()}elemdisplay[nodeName]=display}return display}(function(){var shrinkWrapBlocksVal;support.shrinkWrapBlocks=function(){if(shrinkWrapBlocksVal!=null){return shrinkWrapBlocksVal}shrinkWrapBlocksVal=false;var div,body,container;body=document.getElementsByTagName("body")[0];if(!body||!body.style){return}div=document.createElement("div");container=document.createElement("div");container.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px";body.appendChild(container).appendChild(div);if(typeof div.style.zoom!==strundefined){div.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;"+"box-sizing:content-box;display:block;margin:0;border:0;"+"padding:1px;width:1px;zoom:1";div.appendChild(document.createElement("div")).style.width="5px";shrinkWrapBlocksVal=div.offsetWidth!==3}body.removeChild(container);return shrinkWrapBlocksVal}})();var rmargin=/^margin/;var rnumnonpx=new RegExp("^("+pnum+")(?!px)[a-z%]+$","i");var getStyles,curCSS,rposition=/^(top|right|bottom|left)$/;if(window.getComputedStyle){getStyles=function(elem){if(elem.ownerDocument.defaultView.opener){return elem.ownerDocument.defaultView.getComputedStyle(elem,null)}return window.getComputedStyle(elem,null)};curCSS=function(elem,name,computed){var width,minWidth,maxWidth,ret,style=elem.style;computed=computed||getStyles(elem);ret=computed?computed.getPropertyValue(name)||computed[name]:undefined;if(computed){if(ret===""&&!jQuery.contains(elem.ownerDocument,elem)){ret=jQuery.style(elem,name)}if(rnumnonpx.test(ret)&&rmargin.test(name)){width=style.width;minWidth=style.minWidth;maxWidth=style.maxWidth;style.minWidth=style.maxWidth=style.width=ret;ret=computed.width;style.width=width;style.minWidth=minWidth;style.maxWidth=maxWidth}}return ret===undefined?ret:ret+""}}else if(document.documentElement.currentStyle){getStyles=function(elem){return elem.currentStyle};curCSS=function(elem,name,computed){var left,rs,rsLeft,ret,style=elem.style;computed=computed||getStyles(elem);ret=computed?computed[name]:undefined;if(ret==null&&style&&style[name]){ret=style[name]}if(rnumnonpx.test(ret)&&!rposition.test(name)){left=style.left;rs=elem.runtimeStyle;rsLeft=rs&&rs.left;if(rsLeft){rs.left=elem.currentStyle.left}style.left=name==="fontSize"?"1em":ret;ret=style.pixelLeft+"px";style.left=left;if(rsLeft){rs.left=rsLeft}}return ret===undefined?ret:ret+""||"auto"}}function addGetHookIf(conditionFn,hookFn){return{get:function(){var condition=conditionFn();if(condition==null){return}if(condition){delete this.get;return}return(this.get=hookFn).apply(this,arguments)}}}(function(){var div,style,a,pixelPositionVal,boxSizingReliableVal,reliableHiddenOffsetsVal,reliableMarginRightVal;div=document.createElement("div");div.innerHTML="
a";a=div.getElementsByTagName("a")[0];style=a&&a.style;if(!style){return}style.cssText="float:left;opacity:.5";support.opacity=style.opacity==="0.5";support.cssFloat=!!style.cssFloat;div.style.backgroundClip="content-box";div.cloneNode(true).style.backgroundClip="";support.clearCloneStyle=div.style.backgroundClip==="content-box";support.boxSizing=style.boxSizing===""||style.MozBoxSizing===""||style.WebkitBoxSizing==="";jQuery.extend(support,{reliableHiddenOffsets:function(){if(reliableHiddenOffsetsVal==null){computeStyleTests()}return reliableHiddenOffsetsVal},boxSizingReliable:function(){if(boxSizingReliableVal==null){computeStyleTests()}return boxSizingReliableVal},pixelPosition:function(){if(pixelPositionVal==null){computeStyleTests()}return pixelPositionVal},reliableMarginRight:function(){if(reliableMarginRightVal==null){computeStyleTests()}return reliableMarginRightVal}});function computeStyleTests(){var div,body,container,contents;body=document.getElementsByTagName("body")[0];if(!body||!body.style){return}div=document.createElement("div");container=document.createElement("div");container.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px";body.appendChild(container).appendChild(div);div.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;"+"box-sizing:border-box;display:block;margin-top:1%;top:1%;"+"border:1px;padding:1px;width:4px;position:absolute";pixelPositionVal=boxSizingReliableVal=false;reliableMarginRightVal=true;if(window.getComputedStyle){pixelPositionVal=(window.getComputedStyle(div,null)||{}).top!=="1%";boxSizingReliableVal=(window.getComputedStyle(div,null)||{width:"4px"}).width==="4px";contents=div.appendChild(document.createElement("div"));contents.style.cssText=div.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;"+"box-sizing:content-box;display:block;margin:0;border:0;padding:0";contents.style.marginRight=contents.style.width="0";div.style.width="1px";reliableMarginRightVal=!parseFloat((window.getComputedStyle(contents,null)||{}).marginRight);div.removeChild(contents)}div.innerHTML="
t
";contents=div.getElementsByTagName("td");contents[0].style.cssText="margin:0;border:0;padding:0;display:none";reliableHiddenOffsetsVal=contents[0].offsetHeight===0;if(reliableHiddenOffsetsVal){contents[0].style.display="";contents[1].style.display="none";reliableHiddenOffsetsVal=contents[0].offsetHeight===0}body.removeChild(container)}})();jQuery.swap=function(elem,options,callback,args){var ret,name,old={};for(name in options){old[name]=elem.style[name];elem.style[name]=options[name]}ret=callback.apply(elem,args||[]);for(name in options){elem.style[name]=old[name]}return ret};var ralpha=/alpha\([^)]*\)/i,ropacity=/opacity\s*=\s*([^)]*)/,rdisplayswap=/^(none|table(?!-c[ea]).+)/,rnumsplit=new RegExp("^("+pnum+")(.*)$","i"),rrelNum=new RegExp("^([+-])=("+pnum+")","i"),cssShow={position:"absolute",visibility:"hidden",display:"block"},cssNormalTransform={letterSpacing:"0",fontWeight:"400"},cssPrefixes=["Webkit","O","Moz","ms"];function vendorPropName(style,name){if(name in style){return name}var capName=name.charAt(0).toUpperCase()+name.slice(1),origName=name,i=cssPrefixes.length;while(i--){name=cssPrefixes[i]+capName;if(name in style){return name}}return origName}function showHide(elements,show){var display,elem,hidden,values=[],index=0,length=elements.length;for(;index=1||value==="")&&jQuery.trim(filter.replace(ralpha,""))===""&&style.removeAttribute){style.removeAttribute("filter");if(value===""||currentStyle&&!currentStyle.filter){return}}style.filter=ralpha.test(filter)?filter.replace(ralpha,opacity):filter+" "+opacity}}}jQuery.cssHooks.marginRight=addGetHookIf(support.reliableMarginRight,function(elem,computed){if(computed){return jQuery.swap(elem,{display:"inline-block"},curCSS,[elem,"marginRight"])}});jQuery.each({margin:"",padding:"",border:"Width"},function(prefix,suffix){jQuery.cssHooks[prefix+suffix]={expand:function(value){var i=0,expanded={},parts=typeof value==="string"?value.split(" "):[value];for(;i<4;i++){expanded[prefix+cssExpand[i]+suffix]=parts[i]||parts[i-2]||parts[0]}return expanded}};if(!rmargin.test(prefix)){jQuery.cssHooks[prefix+suffix].set=setPositiveNumber}});jQuery.fn.extend({css:function(name,value){return access(this,function(elem,name,value){var styles,len,map={},i=0;if(jQuery.isArray(name)){styles=getStyles(elem);len=name.length;for(;i1)},show:function(){return showHide(this,true)},hide:function(){return showHide(this)},toggle:function(state){if(typeof state==="boolean"){return state?this.show():this.hide()}return this.each(function(){if(isHidden(this)){jQuery(this).show()}else{jQuery(this).hide()}})}});function Tween(elem,options,prop,end,easing){return new Tween.prototype.init(elem,options,prop,end,easing)}jQuery.Tween=Tween;Tween.prototype={constructor:Tween,init:function(elem,options,prop,end,easing,unit){this.elem=elem;this.prop=prop;this.easing=easing||"swing";this.options=options;this.start=this.now=this.cur();this.end=end;this.unit=unit||(jQuery.cssNumber[prop]?"":"px")},cur:function(){var hooks=Tween.propHooks[this.prop];return hooks&&hooks.get?hooks.get(this):Tween.propHooks._default.get(this)},run:function(percent){var eased,hooks=Tween.propHooks[this.prop];if(this.options.duration){this.pos=eased=jQuery.easing[this.easing](percent,this.options.duration*percent,0,1,this.options.duration)}else{this.pos=eased=percent}this.now=(this.end-this.start)*eased+this.start;if(this.options.step){this.options.step.call(this.elem,this.now,this)}if(hooks&&hooks.set){hooks.set(this)}else{Tween.propHooks._default.set(this)}return this}};Tween.prototype.init.prototype=Tween.prototype;Tween.propHooks={_default:{get:function(tween){var result;if(tween.elem[tween.prop]!=null&&(!tween.elem.style||tween.elem.style[tween.prop]==null)){return tween.elem[tween.prop]}result=jQuery.css(tween.elem,tween.prop,"");return!result||result==="auto"?0:result},set:function(tween){if(jQuery.fx.step[tween.prop]){jQuery.fx.step[tween.prop](tween)}else if(tween.elem.style&&(tween.elem.style[jQuery.cssProps[tween.prop]]!=null||jQuery.cssHooks[tween.prop])){jQuery.style(tween.elem,tween.prop,tween.now+tween.unit)}else{tween.elem[tween.prop]=tween.now}}}};Tween.propHooks.scrollTop=Tween.propHooks.scrollLeft={set:function(tween){if(tween.elem.nodeType&&tween.elem.parentNode){tween.elem[tween.prop]=tween.now}}};jQuery.easing={linear:function(p){return p},swing:function(p){return.5-Math.cos(p*Math.PI)/2}};jQuery.fx=Tween.prototype.init;jQuery.fx.step={};var fxNow,timerId,rfxtypes=/^(?:toggle|show|hide)$/,rfxnum=new RegExp("^(?:([+-])=|)("+pnum+")([a-z%]*)$","i"),rrun=/queueHooks$/,animationPrefilters=[defaultPrefilter],tweeners={"*":[function(prop,value){var tween=this.createTween(prop,value),target=tween.cur(),parts=rfxnum.exec(value),unit=parts&&parts[3]||(jQuery.cssNumber[prop]?"":"px"),start=(jQuery.cssNumber[prop]||unit!=="px"&&+target)&&rfxnum.exec(jQuery.css(tween.elem,prop)),scale=1,maxIterations=20;if(start&&start[3]!==unit){unit=unit||start[3];parts=parts||[];start=+target||1;do{scale=scale||".5";start=start/scale;jQuery.style(tween.elem,prop,start+unit)}while(scale!==(scale=tween.cur()/target)&&scale!==1&&--maxIterations)}if(parts){start=tween.start=+start||+target||0;tween.unit=unit;tween.end=parts[1]?start+(parts[1]+1)*parts[2]:+parts[2]}return tween}]};function createFxNow(){setTimeout(function(){fxNow=undefined});return fxNow=jQuery.now()}function genFx(type,includeWidth){var which,attrs={height:type},i=0;includeWidth=includeWidth?1:0;for(;i<4;i+=2-includeWidth){which=cssExpand[i];attrs["margin"+which]=attrs["padding"+which]=type}if(includeWidth){attrs.opacity=attrs.width=type}return attrs}function createTween(value,prop,animation){var tween,collection=(tweeners[prop]||[]).concat(tweeners["*"]),index=0,length=collection.length;for(;index
a";a=div.getElementsByTagName("a")[0];select=document.createElement("select");opt=select.appendChild(document.createElement("option"));input=div.getElementsByTagName("input")[0];a.style.cssText="top:1px";support.getSetAttribute=div.className!=="t";support.style=/top/.test(a.getAttribute("style"));support.hrefNormalized=a.getAttribute("href")==="/a";support.checkOn=!!input.value;support.optSelected=opt.selected;support.enctype=!!document.createElement("form").enctype;select.disabled=true;support.optDisabled=!opt.disabled;input=document.createElement("input");input.setAttribute("value","");support.input=input.getAttribute("value")==="";input.value="t";input.setAttribute("type","radio");support.radioValue=input.value==="t"})();var rreturn=/\r/g;jQuery.fn.extend({val:function(value){var hooks,ret,isFunction,elem=this[0];if(!arguments.length){if(elem){hooks=jQuery.valHooks[elem.type]||jQuery.valHooks[elem.nodeName.toLowerCase()];if(hooks&&"get"in hooks&&(ret=hooks.get(elem,"value"))!==undefined){return ret}ret=elem.value;return typeof ret==="string"?ret.replace(rreturn,""):ret==null?"":ret}return}isFunction=jQuery.isFunction(value);return this.each(function(i){var val;if(this.nodeType!==1){return}if(isFunction){val=value.call(this,i,jQuery(this).val())}else{val=value}if(val==null){val=""}else if(typeof val==="number"){val+=""}else if(jQuery.isArray(val)){val=jQuery.map(val,function(value){return value==null?"":value+""})}hooks=jQuery.valHooks[this.type]||jQuery.valHooks[this.nodeName.toLowerCase()];if(!hooks||!("set"in hooks)||hooks.set(this,val,"value")===undefined){this.value=val}})}});jQuery.extend({valHooks:{option:{get:function(elem){var val=jQuery.find.attr(elem,"value");return val!=null?val:jQuery.trim(jQuery.text(elem))}},select:{get:function(elem){var value,option,options=elem.options,index=elem.selectedIndex,one=elem.type==="select-one"||index<0,values=one?null:[],max=one?index+1:options.length,i=index<0?max:one?index:0;for(;i=0){try{option.selected=optionSet=true}catch(_){option.scrollHeight}}else{option.selected=false}}if(!optionSet){elem.selectedIndex=-1}return options}}}});jQuery.each(["radio","checkbox"],function(){jQuery.valHooks[this]={set:function(elem,value){if(jQuery.isArray(value)){return elem.checked=jQuery.inArray(jQuery(elem).val(),value)>=0}}};if(!support.checkOn){jQuery.valHooks[this].get=function(elem){return elem.getAttribute("value")===null?"on":elem.value}}});var nodeHook,boolHook,attrHandle=jQuery.expr.attrHandle,ruseDefault=/^(?:checked|selected)$/i,getSetAttribute=support.getSetAttribute,getSetInput=support.input;jQuery.fn.extend({attr:function(name,value){return access(this,jQuery.attr,name,value,arguments.length>1)},removeAttr:function(name){return this.each(function(){jQuery.removeAttr(this,name)})}});jQuery.extend({attr:function(elem,name,value){var hooks,ret,nType=elem.nodeType;if(!elem||nType===3||nType===8||nType===2){return}if(typeof elem.getAttribute===strundefined){return jQuery.prop(elem,name,value)}if(nType!==1||!jQuery.isXMLDoc(elem)){name=name.toLowerCase();hooks=jQuery.attrHooks[name]||(jQuery.expr.match.bool.test(name)?boolHook:nodeHook)}if(value!==undefined){if(value===null){jQuery.removeAttr(elem,name)}else if(hooks&&"set"in hooks&&(ret=hooks.set(elem,value,name))!==undefined){return ret}else{elem.setAttribute(name,value+"");return value}}else if(hooks&&"get"in hooks&&(ret=hooks.get(elem,name))!==null){return ret}else{ret=jQuery.find.attr(elem,name);return ret==null?undefined:ret}},removeAttr:function(elem,value){var name,propName,i=0,attrNames=value&&value.match(rnotwhite);if(attrNames&&elem.nodeType===1){while(name=attrNames[i++]){propName=jQuery.propFix[name]||name;if(jQuery.expr.match.bool.test(name)){if(getSetInput&&getSetAttribute||!ruseDefault.test(name)){elem[propName]=false}else{elem[jQuery.camelCase("default-"+name)]=elem[propName]=false}}else{jQuery.attr(elem,name,"")}elem.removeAttribute(getSetAttribute?name:propName)}}},attrHooks:{type:{set:function(elem,value){if(!support.radioValue&&value==="radio"&&jQuery.nodeName(elem,"input")){var val=elem.value;elem.setAttribute("type",value);if(val){elem.value=val}return value}}}}});boolHook={set:function(elem,value,name){if(value===false){jQuery.removeAttr(elem,name)}else if(getSetInput&&getSetAttribute||!ruseDefault.test(name)){elem.setAttribute(!getSetAttribute&&jQuery.propFix[name]||name,name)}else{elem[jQuery.camelCase("default-"+name)]=elem[name]=true}return name}};jQuery.each(jQuery.expr.match.bool.source.match(/\w+/g),function(i,name){var getter=attrHandle[name]||jQuery.find.attr;attrHandle[name]=getSetInput&&getSetAttribute||!ruseDefault.test(name)?function(elem,name,isXML){var ret,handle;if(!isXML){handle=attrHandle[name];attrHandle[name]=ret;ret=getter(elem,name,isXML)!=null?name.toLowerCase():null;attrHandle[name]=handle}return ret}:function(elem,name,isXML){if(!isXML){return elem[jQuery.camelCase("default-"+name)]?name.toLowerCase():null}}});if(!getSetInput||!getSetAttribute){jQuery.attrHooks.value={set:function(elem,value,name){if(jQuery.nodeName(elem,"input")){elem.defaultValue=value}else{return nodeHook&&nodeHook.set(elem,value,name)}}}}if(!getSetAttribute){nodeHook={set:function(elem,value,name){var ret=elem.getAttributeNode(name);if(!ret){elem.setAttributeNode(ret=elem.ownerDocument.createAttribute(name))}ret.value=value+="";if(name==="value"||value===elem.getAttribute(name)){return value}}};attrHandle.id=attrHandle.name=attrHandle.coords=function(elem,name,isXML){var ret;if(!isXML){return(ret=elem.getAttributeNode(name))&&ret.value!==""?ret.value:null}};jQuery.valHooks.button={get:function(elem,name){var ret=elem.getAttributeNode(name);if(ret&&ret.specified){return ret.value}},set:nodeHook.set};jQuery.attrHooks.contenteditable={set:function(elem,value,name){nodeHook.set(elem,value===""?false:value,name)}};jQuery.each(["width","height"],function(i,name){jQuery.attrHooks[name]={set:function(elem,value){if(value===""){elem.setAttribute(name,"auto");return value}}}})}if(!support.style){jQuery.attrHooks.style={get:function(elem){return elem.style.cssText||undefined},set:function(elem,value){return elem.style.cssText=value+""}}}var rfocusable=/^(?:input|select|textarea|button|object)$/i,rclickable=/^(?:a|area)$/i;jQuery.fn.extend({prop:function(name,value){return access(this,jQuery.prop,name,value,arguments.length>1)},removeProp:function(name){name=jQuery.propFix[name]||name;return this.each(function(){try{this[name]=undefined;delete this[name]}catch(e){}})}});jQuery.extend({propFix:{"for":"htmlFor","class":"className"},prop:function(elem,name,value){var ret,hooks,notxml,nType=elem.nodeType;if(!elem||nType===3||nType===8||nType===2){return}notxml=nType!==1||!jQuery.isXMLDoc(elem);if(notxml){name=jQuery.propFix[name]||name;hooks=jQuery.propHooks[name]}if(value!==undefined){return hooks&&"set"in hooks&&(ret=hooks.set(elem,value,name))!==undefined?ret:elem[name]=value}else{return hooks&&"get"in hooks&&(ret=hooks.get(elem,name))!==null?ret:elem[name]}},propHooks:{tabIndex:{get:function(elem){var tabindex=jQuery.find.attr(elem,"tabindex");return tabindex?parseInt(tabindex,10):rfocusable.test(elem.nodeName)||rclickable.test(elem.nodeName)&&elem.href?0:-1}}}});if(!support.hrefNormalized){jQuery.each(["href","src"],function(i,name){jQuery.propHooks[name]={get:function(elem){return elem.getAttribute(name,4)}}})}if(!support.optSelected){jQuery.propHooks.selected={get:function(elem){var parent=elem.parentNode;if(parent){parent.selectedIndex;if(parent.parentNode){parent.parentNode.selectedIndex}}return null}}}jQuery.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){jQuery.propFix[this.toLowerCase()]=this});if(!support.enctype){jQuery.propFix.enctype="encoding"}var rclass=/[\t\r\n\f]/g;jQuery.fn.extend({addClass:function(value){var classes,elem,cur,clazz,j,finalValue,i=0,len=this.length,proceed=typeof value==="string"&&value;if(jQuery.isFunction(value)){return this.each(function(j){jQuery(this).addClass(value.call(this,j,this.className))})}if(proceed){classes=(value||"").match(rnotwhite)||[];for(;i=0){cur=cur.replace(" "+clazz+" "," ")}}finalValue=value?jQuery.trim(cur):"";if(elem.className!==finalValue){elem.className=finalValue}}}}return this},toggleClass:function(value,stateVal){var type=typeof value;if(typeof stateVal==="boolean"&&type==="string"){return stateVal?this.addClass(value):this.removeClass(value)}if(jQuery.isFunction(value)){return this.each(function(i){jQuery(this).toggleClass(value.call(this,i,this.className,stateVal),stateVal)})}return this.each(function(){if(type==="string"){var className,i=0,self=jQuery(this),classNames=value.match(rnotwhite)||[];while(className=classNames[i++]){if(self.hasClass(className)){self.removeClass(className)}else{self.addClass(className)}}}else if(type===strundefined||type==="boolean"){if(this.className){jQuery._data(this,"__className__",this.className)}this.className=this.className||value===false?"":jQuery._data(this,"__className__")||""}})},hasClass:function(selector){var className=" "+selector+" ",i=0,l=this.length;for(;i=0){return true}}return false}});jQuery.each(("blur focus focusin focusout load resize scroll unload click dblclick "+"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave "+"change select submit keydown keypress keyup error contextmenu").split(" "),function(i,name){jQuery.fn[name]=function(data,fn){return arguments.length>0?this.on(name,null,data,fn):this.trigger(name)}});jQuery.fn.extend({hover:function(fnOver,fnOut){return this.mouseenter(fnOver).mouseleave(fnOut||fnOver)},bind:function(types,data,fn){return this.on(types,null,data,fn)},unbind:function(types,fn){return this.off(types,null,fn)},delegate:function(selector,types,data,fn){return this.on(types,selector,data,fn)},undelegate:function(selector,types,fn){return arguments.length===1?this.off(selector,"**"):this.off(types,selector||"**",fn)}});var nonce=jQuery.now();var rquery=/\?/;var rvalidtokens=/(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;jQuery.parseJSON=function(data){if(window.JSON&&window.JSON.parse){return window.JSON.parse(data+"")}var requireNonComma,depth=null,str=jQuery.trim(data+"");return str&&!jQuery.trim(str.replace(rvalidtokens,function(token,comma,open,close){if(requireNonComma&&comma){depth=0}if(depth===0){return token}requireNonComma=open||comma;depth+=!close-!open;return""}))?Function("return "+str)():jQuery.error("Invalid JSON: "+data)};jQuery.parseXML=function(data){var xml,tmp;if(!data||typeof data!=="string"){return null}try{if(window.DOMParser){tmp=new DOMParser;xml=tmp.parseFromString(data,"text/xml")}else{xml=new ActiveXObject("Microsoft.XMLDOM");xml.async="false";xml.loadXML(data)}}catch(e){xml=undefined}if(!xml||!xml.documentElement||xml.getElementsByTagName("parsererror").length){jQuery.error("Invalid XML: "+data)}return xml};var ajaxLocParts,ajaxLocation,rhash=/#.*$/,rts=/([?&])_=[^&]*/,rheaders=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,rlocalProtocol=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,rnoContent=/^(?:GET|HEAD)$/,rprotocol=/^\/\//,rurl=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,prefilters={},transports={},allTypes="*/".concat("*");try{ajaxLocation=location.href}catch(e){ajaxLocation=document.createElement("a");ajaxLocation.href="";ajaxLocation=ajaxLocation.href}ajaxLocParts=rurl.exec(ajaxLocation.toLowerCase())||[];function addToPrefiltersOrTransports(structure){return function(dataTypeExpression,func){if(typeof dataTypeExpression!=="string"){func=dataTypeExpression;dataTypeExpression="*"}var dataType,i=0,dataTypes=dataTypeExpression.toLowerCase().match(rnotwhite)||[];if(jQuery.isFunction(func)){while(dataType=dataTypes[i++]){if(dataType.charAt(0)==="+"){dataType=dataType.slice(1)||"*";(structure[dataType]=structure[dataType]||[]).unshift(func)}else{(structure[dataType]=structure[dataType]||[]).push(func)}}}}}function inspectPrefiltersOrTransports(structure,options,originalOptions,jqXHR){var inspected={},seekingTransport=structure===transports;function inspect(dataType){var selected;inspected[dataType]=true;jQuery.each(structure[dataType]||[],function(_,prefilterOrFactory){var dataTypeOrTransport=prefilterOrFactory(options,originalOptions,jqXHR);if(typeof dataTypeOrTransport==="string"&&!seekingTransport&&!inspected[dataTypeOrTransport]){options.dataTypes.unshift(dataTypeOrTransport);inspect(dataTypeOrTransport);return false}else if(seekingTransport){return!(selected=dataTypeOrTransport)}});return selected}return inspect(options.dataTypes[0])||!inspected["*"]&&inspect("*")}function ajaxExtend(target,src){var deep,key,flatOptions=jQuery.ajaxSettings.flatOptions||{};for(key in src){if(src[key]!==undefined){(flatOptions[key]?target:deep||(deep={}))[key]=src[key]}}if(deep){jQuery.extend(true,target,deep)}return target}function ajaxHandleResponses(s,jqXHR,responses){var firstDataType,ct,finalDataType,type,contents=s.contents,dataTypes=s.dataTypes;while(dataTypes[0]==="*"){dataTypes.shift();if(ct===undefined){ct=s.mimeType||jqXHR.getResponseHeader("Content-Type")}}if(ct){for(type in contents){if(contents[type]&&contents[type].test(ct)){dataTypes.unshift(type);break}}}if(dataTypes[0]in responses){finalDataType=dataTypes[0]}else{for(type in responses){if(!dataTypes[0]||s.converters[type+" "+dataTypes[0]]){finalDataType=type;break}if(!firstDataType){firstDataType=type}}finalDataType=finalDataType||firstDataType}if(finalDataType){if(finalDataType!==dataTypes[0]){dataTypes.unshift(finalDataType)}return responses[finalDataType]}}function ajaxConvert(s,response,jqXHR,isSuccess){var conv2,current,conv,tmp,prev,converters={},dataTypes=s.dataTypes.slice();if(dataTypes[1]){for(conv in s.converters){converters[conv.toLowerCase()]=s.converters[conv]}}current=dataTypes.shift();while(current){if(s.responseFields[current]){jqXHR[s.responseFields[current]]=response}if(!prev&&isSuccess&&s.dataFilter){response=s.dataFilter(response,s.dataType)}prev=current;current=dataTypes.shift();if(current){if(current==="*"){current=prev}else if(prev!=="*"&&prev!==current){conv=converters[prev+" "+current]||converters["* "+current];if(!conv){for(conv2 in converters){tmp=conv2.split(" ");if(tmp[1]===current){conv=converters[prev+" "+tmp[0]]||converters["* "+tmp[0]];if(conv){if(conv===true){conv=converters[conv2]}else if(converters[conv2]!==true){current=tmp[0];dataTypes.unshift(tmp[1])}break}}}}if(conv!==true){if(conv&&s["throws"]){response=conv(response)}else{try{response=conv(response)}catch(e){return{state:"parsererror",error:conv?e:"No conversion from "+prev+" to "+current}}}}}}}return{state:"success",data:response}}jQuery.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:ajaxLocation,type:"GET",isLocal:rlocalProtocol.test(ajaxLocParts[1]),global:true,processData:true,async:true,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":allTypes,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":true,"text json":jQuery.parseJSON,"text xml":jQuery.parseXML},flatOptions:{url:true,context:true}},ajaxSetup:function(target,settings){return settings?ajaxExtend(ajaxExtend(target,jQuery.ajaxSettings),settings):ajaxExtend(jQuery.ajaxSettings,target)},ajaxPrefilter:addToPrefiltersOrTransports(prefilters),ajaxTransport:addToPrefiltersOrTransports(transports),ajax:function(url,options){if(typeof url==="object"){options=url;url=undefined}options=options||{};var parts,i,cacheURL,responseHeadersString,timeoutTimer,fireGlobals,transport,responseHeaders,s=jQuery.ajaxSetup({},options),callbackContext=s.context||s,globalEventContext=s.context&&(callbackContext.nodeType||callbackContext.jquery)?jQuery(callbackContext):jQuery.event,deferred=jQuery.Deferred(),completeDeferred=jQuery.Callbacks("once memory"),statusCode=s.statusCode||{},requestHeaders={},requestHeadersNames={},state=0,strAbort="canceled",jqXHR={readyState:0,getResponseHeader:function(key){var match;if(state===2){if(!responseHeaders){responseHeaders={};while(match=rheaders.exec(responseHeadersString)){responseHeaders[match[1].toLowerCase()]=match[2]}}match=responseHeaders[key.toLowerCase()]}return match==null?null:match},getAllResponseHeaders:function(){return state===2?responseHeadersString:null},setRequestHeader:function(name,value){var lname=name.toLowerCase();if(!state){name=requestHeadersNames[lname]=requestHeadersNames[lname]||name;requestHeaders[name]=value}return this},overrideMimeType:function(type){if(!state){s.mimeType=type}return this},statusCode:function(map){var code;if(map){if(state<2){for(code in map){statusCode[code]=[statusCode[code],map[code]]}}else{jqXHR.always(map[jqXHR.status])}}return this},abort:function(statusText){var finalText=statusText||strAbort;if(transport){transport.abort(finalText)}done(0,finalText);return this}};deferred.promise(jqXHR).complete=completeDeferred.add;jqXHR.success=jqXHR.done;jqXHR.error=jqXHR.fail;s.url=((url||s.url||ajaxLocation)+"").replace(rhash,"").replace(rprotocol,ajaxLocParts[1]+"//");s.type=options.method||options.type||s.method||s.type;s.dataTypes=jQuery.trim(s.dataType||"*").toLowerCase().match(rnotwhite)||[""];if(s.crossDomain==null){parts=rurl.exec(s.url.toLowerCase());s.crossDomain=!!(parts&&(parts[1]!==ajaxLocParts[1]||parts[2]!==ajaxLocParts[2]||(parts[3]||(parts[1]==="http:"?"80":"443"))!==(ajaxLocParts[3]||(ajaxLocParts[1]==="http:"?"80":"443"))))}if(s.data&&s.processData&&typeof s.data!=="string"){s.data=jQuery.param(s.data,s.traditional)}inspectPrefiltersOrTransports(prefilters,s,options,jqXHR);if(state===2){return jqXHR}fireGlobals=jQuery.event&&s.global;if(fireGlobals&&jQuery.active++===0){jQuery.event.trigger("ajaxStart")}s.type=s.type.toUpperCase();s.hasContent=!rnoContent.test(s.type);cacheURL=s.url;if(!s.hasContent){if(s.data){cacheURL=s.url+=(rquery.test(cacheURL)?"&":"?")+s.data;delete s.data}if(s.cache===false){s.url=rts.test(cacheURL)?cacheURL.replace(rts,"$1_="+nonce++):cacheURL+(rquery.test(cacheURL)?"&":"?")+"_="+nonce++}}if(s.ifModified){if(jQuery.lastModified[cacheURL]){jqXHR.setRequestHeader("If-Modified-Since",jQuery.lastModified[cacheURL])}if(jQuery.etag[cacheURL]){jqXHR.setRequestHeader("If-None-Match",jQuery.etag[cacheURL])}}if(s.data&&s.hasContent&&s.contentType!==false||options.contentType){jqXHR.setRequestHeader("Content-Type",s.contentType)}jqXHR.setRequestHeader("Accept",s.dataTypes[0]&&s.accepts[s.dataTypes[0]]?s.accepts[s.dataTypes[0]]+(s.dataTypes[0]!=="*"?", "+allTypes+"; q=0.01":""):s.accepts["*"]);for(i in s.headers){jqXHR.setRequestHeader(i,s.headers[i])}if(s.beforeSend&&(s.beforeSend.call(callbackContext,jqXHR,s)===false||state===2)){return jqXHR.abort()}strAbort="abort";for(i in{success:1,error:1,complete:1}){jqXHR[i](s[i])}transport=inspectPrefiltersOrTransports(transports,s,options,jqXHR);if(!transport){done(-1,"No Transport")}else{jqXHR.readyState=1;if(fireGlobals){globalEventContext.trigger("ajaxSend",[jqXHR,s])}if(s.async&&s.timeout>0){timeoutTimer=setTimeout(function(){jqXHR.abort("timeout")},s.timeout)}try{state=1;transport.send(requestHeaders,done)}catch(e){if(state<2){done(-1,e)}else{throw e}}}function done(status,nativeStatusText,responses,headers){var isSuccess,success,error,response,modified,statusText=nativeStatusText;if(state===2){return}state=2;if(timeoutTimer){clearTimeout(timeoutTimer)}transport=undefined;responseHeadersString=headers||"";jqXHR.readyState=status>0?4:0;isSuccess=status>=200&&status<300||status===304;if(responses){response=ajaxHandleResponses(s,jqXHR,responses)}response=ajaxConvert(s,response,jqXHR,isSuccess);if(isSuccess){if(s.ifModified){modified=jqXHR.getResponseHeader("Last-Modified");if(modified){jQuery.lastModified[cacheURL]=modified}modified=jqXHR.getResponseHeader("etag");if(modified){jQuery.etag[cacheURL]=modified}}if(status===204||s.type==="HEAD"){statusText="nocontent"}else if(status===304){statusText="notmodified"}else{statusText=response.state;success=response.data;error=response.error;isSuccess=!error}}else{error=statusText;if(status||!statusText){statusText="error";if(status<0){status=0}}}jqXHR.status=status;jqXHR.statusText=(nativeStatusText||statusText)+"";if(isSuccess){deferred.resolveWith(callbackContext,[success,statusText,jqXHR])}else{deferred.rejectWith(callbackContext,[jqXHR,statusText,error])}jqXHR.statusCode(statusCode);statusCode=undefined;if(fireGlobals){globalEventContext.trigger(isSuccess?"ajaxSuccess":"ajaxError",[jqXHR,s,isSuccess?success:error])}completeDeferred.fireWith(callbackContext,[jqXHR,statusText]);if(fireGlobals){globalEventContext.trigger("ajaxComplete",[jqXHR,s]);if(!--jQuery.active){jQuery.event.trigger("ajaxStop")}}}return jqXHR},getJSON:function(url,data,callback){return jQuery.get(url,data,callback,"json")},getScript:function(url,callback){return jQuery.get(url,undefined,callback,"script")}});jQuery.each(["get","post"],function(i,method){jQuery[method]=function(url,data,callback,type){if(jQuery.isFunction(data)){type=type||callback;callback=data;data=undefined}return jQuery.ajax({url:url,type:method,dataType:type,data:data,success:callback})}});jQuery._evalUrl=function(url){return jQuery.ajax({url:url,type:"GET",dataType:"script",async:false,global:false,"throws":true})};jQuery.fn.extend({wrapAll:function(html){if(jQuery.isFunction(html)){return this.each(function(i){jQuery(this).wrapAll(html.call(this,i))})}if(this[0]){var wrap=jQuery(html,this[0].ownerDocument).eq(0).clone(true);if(this[0].parentNode){wrap.insertBefore(this[0])}wrap.map(function(){var elem=this;while(elem.firstChild&&elem.firstChild.nodeType===1){elem=elem.firstChild}return elem}).append(this)}return this},wrapInner:function(html){if(jQuery.isFunction(html)){return this.each(function(i){jQuery(this).wrapInner(html.call(this,i))})}return this.each(function(){var self=jQuery(this),contents=self.contents();if(contents.length){contents.wrapAll(html)}else{self.append(html)}})},wrap:function(html){var isFunction=jQuery.isFunction(html);return this.each(function(i){jQuery(this).wrapAll(isFunction?html.call(this,i):html)})},unwrap:function(){return this.parent().each(function(){if(!jQuery.nodeName(this,"body")){jQuery(this).replaceWith(this.childNodes)}}).end()}});jQuery.expr.filters.hidden=function(elem){return elem.offsetWidth<=0&&elem.offsetHeight<=0||!support.reliableHiddenOffsets()&&(elem.style&&elem.style.display||jQuery.css(elem,"display"))==="none"};jQuery.expr.filters.visible=function(elem){return!jQuery.expr.filters.hidden(elem)};var r20=/%20/g,rbracket=/\[\]$/,rCRLF=/\r?\n/g,rsubmitterTypes=/^(?:submit|button|image|reset|file)$/i,rsubmittable=/^(?:input|select|textarea|keygen)/i;function buildParams(prefix,obj,traditional,add){var name;if(jQuery.isArray(obj)){jQuery.each(obj,function(i,v){if(traditional||rbracket.test(prefix)){add(prefix,v)}else{buildParams(prefix+"["+(typeof v==="object"?i:"")+"]",v,traditional,add)}})}else if(!traditional&&jQuery.type(obj)==="object"){for(name in obj){buildParams(prefix+"["+name+"]",obj[name],traditional,add)}}else{add(prefix,obj)}}jQuery.param=function(a,traditional){var prefix,s=[],add=function(key,value){value=jQuery.isFunction(value)?value():value==null?"":value;s[s.length]=encodeURIComponent(key)+"="+encodeURIComponent(value)};if(traditional===undefined){traditional=jQuery.ajaxSettings&&jQuery.ajaxSettings.traditional}if(jQuery.isArray(a)||a.jquery&&!jQuery.isPlainObject(a)){jQuery.each(a,function(){add(this.name,this.value)})}else{for(prefix in a){buildParams(prefix,a[prefix],traditional,add)}}return s.join("&").replace(r20,"+")};jQuery.fn.extend({serialize:function(){return jQuery.param(this.serializeArray()); -},serializeArray:function(){return this.map(function(){var elements=jQuery.prop(this,"elements");return elements?jQuery.makeArray(elements):this}).filter(function(){var type=this.type;return this.name&&!jQuery(this).is(":disabled")&&rsubmittable.test(this.nodeName)&&!rsubmitterTypes.test(type)&&(this.checked||!rcheckableType.test(type))}).map(function(i,elem){var val=jQuery(this).val();return val==null?null:jQuery.isArray(val)?jQuery.map(val,function(val){return{name:elem.name,value:val.replace(rCRLF,"\r\n")}}):{name:elem.name,value:val.replace(rCRLF,"\r\n")}}).get()}});jQuery.ajaxSettings.xhr=window.ActiveXObject!==undefined?function(){return!this.isLocal&&/^(get|post|head|put|delete|options)$/i.test(this.type)&&createStandardXHR()||createActiveXHR()}:createStandardXHR;var xhrId=0,xhrCallbacks={},xhrSupported=jQuery.ajaxSettings.xhr();if(window.attachEvent){window.attachEvent("onunload",function(){for(var key in xhrCallbacks){xhrCallbacks[key](undefined,true)}})}support.cors=!!xhrSupported&&"withCredentials"in xhrSupported;xhrSupported=support.ajax=!!xhrSupported;if(xhrSupported){jQuery.ajaxTransport(function(options){if(!options.crossDomain||support.cors){var callback;return{send:function(headers,complete){var i,xhr=options.xhr(),id=++xhrId;xhr.open(options.type,options.url,options.async,options.username,options.password);if(options.xhrFields){for(i in options.xhrFields){xhr[i]=options.xhrFields[i]}}if(options.mimeType&&xhr.overrideMimeType){xhr.overrideMimeType(options.mimeType)}if(!options.crossDomain&&!headers["X-Requested-With"]){headers["X-Requested-With"]="XMLHttpRequest"}for(i in headers){if(headers[i]!==undefined){xhr.setRequestHeader(i,headers[i]+"")}}xhr.send(options.hasContent&&options.data||null);callback=function(_,isAbort){var status,statusText,responses;if(callback&&(isAbort||xhr.readyState===4)){delete xhrCallbacks[id];callback=undefined;xhr.onreadystatechange=jQuery.noop;if(isAbort){if(xhr.readyState!==4){xhr.abort()}}else{responses={};status=xhr.status;if(typeof xhr.responseText==="string"){responses.text=xhr.responseText}try{statusText=xhr.statusText}catch(e){statusText=""}if(!status&&options.isLocal&&!options.crossDomain){status=responses.text?200:404}else if(status===1223){status=204}}}if(responses){complete(status,statusText,responses,xhr.getAllResponseHeaders())}};if(!options.async){callback()}else if(xhr.readyState===4){setTimeout(callback)}else{xhr.onreadystatechange=xhrCallbacks[id]=callback}},abort:function(){if(callback){callback(undefined,true)}}}}})}function createStandardXHR(){try{return new window.XMLHttpRequest}catch(e){}}function createActiveXHR(){try{return new window.ActiveXObject("Microsoft.XMLHTTP")}catch(e){}}jQuery.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(text){jQuery.globalEval(text);return text}}});jQuery.ajaxPrefilter("script",function(s){if(s.cache===undefined){s.cache=false}if(s.crossDomain){s.type="GET";s.global=false}});jQuery.ajaxTransport("script",function(s){if(s.crossDomain){var script,head=document.head||jQuery("head")[0]||document.documentElement;return{send:function(_,callback){script=document.createElement("script");script.async=true;if(s.scriptCharset){script.charset=s.scriptCharset}script.src=s.url;script.onload=script.onreadystatechange=function(_,isAbort){if(isAbort||!script.readyState||/loaded|complete/.test(script.readyState)){script.onload=script.onreadystatechange=null;if(script.parentNode){script.parentNode.removeChild(script)}script=null;if(!isAbort){callback(200,"success")}}};head.insertBefore(script,head.firstChild)},abort:function(){if(script){script.onload(undefined,true)}}}}});var oldCallbacks=[],rjsonp=/(=)\?(?=&|$)|\?\?/;jQuery.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var callback=oldCallbacks.pop()||jQuery.expando+"_"+nonce++;this[callback]=true;return callback}});jQuery.ajaxPrefilter("json jsonp",function(s,originalSettings,jqXHR){var callbackName,overwritten,responseContainer,jsonProp=s.jsonp!==false&&(rjsonp.test(s.url)?"url":typeof s.data==="string"&&!(s.contentType||"").indexOf("application/x-www-form-urlencoded")&&rjsonp.test(s.data)&&"data");if(jsonProp||s.dataTypes[0]==="jsonp"){callbackName=s.jsonpCallback=jQuery.isFunction(s.jsonpCallback)?s.jsonpCallback():s.jsonpCallback;if(jsonProp){s[jsonProp]=s[jsonProp].replace(rjsonp,"$1"+callbackName)}else if(s.jsonp!==false){s.url+=(rquery.test(s.url)?"&":"?")+s.jsonp+"="+callbackName}s.converters["script json"]=function(){if(!responseContainer){jQuery.error(callbackName+" was not called")}return responseContainer[0]};s.dataTypes[0]="json";overwritten=window[callbackName];window[callbackName]=function(){responseContainer=arguments};jqXHR.always(function(){window[callbackName]=overwritten;if(s[callbackName]){s.jsonpCallback=originalSettings.jsonpCallback;oldCallbacks.push(callbackName)}if(responseContainer&&jQuery.isFunction(overwritten)){overwritten(responseContainer[0])}responseContainer=overwritten=undefined});return"script"}});jQuery.parseHTML=function(data,context,keepScripts){if(!data||typeof data!=="string"){return null}if(typeof context==="boolean"){keepScripts=context;context=false}context=context||document;var parsed=rsingleTag.exec(data),scripts=!keepScripts&&[];if(parsed){return[context.createElement(parsed[1])]}parsed=jQuery.buildFragment([data],context,scripts);if(scripts&&scripts.length){jQuery(scripts).remove()}return jQuery.merge([],parsed.childNodes)};var _load=jQuery.fn.load;jQuery.fn.load=function(url,params,callback){if(typeof url!=="string"&&_load){return _load.apply(this,arguments)}var selector,response,type,self=this,off=url.indexOf(" ");if(off>=0){selector=jQuery.trim(url.slice(off,url.length));url=url.slice(0,off)}if(jQuery.isFunction(params)){callback=params;params=undefined}else if(params&&typeof params==="object"){type="POST"}if(self.length>0){jQuery.ajax({url:url,type:type,dataType:"html",data:params}).done(function(responseText){response=arguments;self.html(selector?jQuery("
").append(jQuery.parseHTML(responseText)).find(selector):responseText)}).complete(callback&&function(jqXHR,status){self.each(callback,response||[jqXHR.responseText,status,jqXHR])})}return this};jQuery.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(i,type){jQuery.fn[type]=function(fn){return this.on(type,fn)}});jQuery.expr.filters.animated=function(elem){return jQuery.grep(jQuery.timers,function(fn){return elem===fn.elem}).length};var docElem=window.document.documentElement;function getWindow(elem){return jQuery.isWindow(elem)?elem:elem.nodeType===9?elem.defaultView||elem.parentWindow:false}jQuery.offset={setOffset:function(elem,options,i){var curPosition,curLeft,curCSSTop,curTop,curOffset,curCSSLeft,calculatePosition,position=jQuery.css(elem,"position"),curElem=jQuery(elem),props={};if(position==="static"){elem.style.position="relative"}curOffset=curElem.offset();curCSSTop=jQuery.css(elem,"top");curCSSLeft=jQuery.css(elem,"left");calculatePosition=(position==="absolute"||position==="fixed")&&jQuery.inArray("auto",[curCSSTop,curCSSLeft])>-1;if(calculatePosition){curPosition=curElem.position();curTop=curPosition.top;curLeft=curPosition.left}else{curTop=parseFloat(curCSSTop)||0;curLeft=parseFloat(curCSSLeft)||0}if(jQuery.isFunction(options)){options=options.call(elem,i,curOffset)}if(options.top!=null){props.top=options.top-curOffset.top+curTop}if(options.left!=null){props.left=options.left-curOffset.left+curLeft}if("using"in options){options.using.call(elem,props)}else{curElem.css(props)}}};jQuery.fn.extend({offset:function(options){if(arguments.length){return options===undefined?this:this.each(function(i){jQuery.offset.setOffset(this,options,i)})}var docElem,win,box={top:0,left:0},elem=this[0],doc=elem&&elem.ownerDocument;if(!doc){return}docElem=doc.documentElement;if(!jQuery.contains(docElem,elem)){return box}if(typeof elem.getBoundingClientRect!==strundefined){box=elem.getBoundingClientRect()}win=getWindow(doc);return{top:box.top+(win.pageYOffset||docElem.scrollTop)-(docElem.clientTop||0),left:box.left+(win.pageXOffset||docElem.scrollLeft)-(docElem.clientLeft||0)}},position:function(){if(!this[0]){return}var offsetParent,offset,parentOffset={top:0,left:0},elem=this[0];if(jQuery.css(elem,"position")==="fixed"){offset=elem.getBoundingClientRect()}else{offsetParent=this.offsetParent();offset=this.offset();if(!jQuery.nodeName(offsetParent[0],"html")){parentOffset=offsetParent.offset()}parentOffset.top+=jQuery.css(offsetParent[0],"borderTopWidth",true);parentOffset.left+=jQuery.css(offsetParent[0],"borderLeftWidth",true)}return{top:offset.top-parentOffset.top-jQuery.css(elem,"marginTop",true),left:offset.left-parentOffset.left-jQuery.css(elem,"marginLeft",true)}},offsetParent:function(){return this.map(function(){var offsetParent=this.offsetParent||docElem;while(offsetParent&&(!jQuery.nodeName(offsetParent,"html")&&jQuery.css(offsetParent,"position")==="static")){offsetParent=offsetParent.offsetParent}return offsetParent||docElem})}});jQuery.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(method,prop){var top=/Y/.test(prop);jQuery.fn[method]=function(val){return access(this,function(elem,method,val){var win=getWindow(elem);if(val===undefined){return win?prop in win?win[prop]:win.document.documentElement[method]:elem[method]}if(win){win.scrollTo(!top?val:jQuery(win).scrollLeft(),top?val:jQuery(win).scrollTop())}else{elem[method]=val}},method,val,arguments.length,null)}});jQuery.each(["top","left"],function(i,prop){jQuery.cssHooks[prop]=addGetHookIf(support.pixelPosition,function(elem,computed){if(computed){computed=curCSS(elem,prop);return rnumnonpx.test(computed)?jQuery(elem).position()[prop]+"px":computed}})});jQuery.each({Height:"height",Width:"width"},function(name,type){jQuery.each({padding:"inner"+name,content:type,"":"outer"+name},function(defaultExtra,funcName){jQuery.fn[funcName]=function(margin,value){var chainable=arguments.length&&(defaultExtra||typeof margin!=="boolean"),extra=defaultExtra||(margin===true||value===true?"margin":"border");return access(this,function(elem,type,value){var doc;if(jQuery.isWindow(elem)){return elem.document.documentElement["client"+name]}if(elem.nodeType===9){doc=elem.documentElement;return Math.max(elem.body["scroll"+name],doc["scroll"+name],elem.body["offset"+name],doc["offset"+name],doc["client"+name])}return value===undefined?jQuery.css(elem,type,extra):jQuery.style(elem,type,value,extra)},type,chainable?margin:undefined,chainable,null)}})});jQuery.fn.size=function(){return this.length};jQuery.fn.andSelf=jQuery.fn.addBack;if(typeof define==="function"&&define.amd){define("jquery",[],function(){return jQuery})}var _jQuery=window.jQuery,_$=window.$;jQuery.noConflict=function(deep){if(window.$===jQuery){window.$=_$}if(deep&&window.jQuery===jQuery){window.jQuery=_jQuery}return jQuery};if(typeof noGlobal===strundefined){window.jQuery=window.$=jQuery}return jQuery})},{}],13:[function(require,module,exports){"use strict";var extend=require("backbone-extend-standalone");var Promise=require("es6-promise").Promise;var authz=require("./authz");var identity=require("./identity");var notification=require("./notification");var registry=require("./registry");var storage=require("./storage");function App(){this.modules=[];this.registry=new registry.Registry;this._started=false;this.registry.registerUtility(notification.defaultNotifier,"notifier");this.include(authz.acl);this.include(identity.simple);this.include(storage.noop)}App.prototype.include=function(module,options){var mod=module(options);if(typeof mod.configure==="function"){mod.configure(this.registry)}this.modules.push(mod);return this};App.prototype.start=function(){if(this._started){return}this._started=true;var self=this;var reg=this.registry;this.authz=reg.getUtility("authorizationPolicy");this.ident=reg.getUtility("identityPolicy");this.notify=reg.getUtility("notifier");this.annotations=new storage.StorageAdapter(reg.getUtility("storage"),function(){return self.runHook.apply(self,arguments)});return this.runHook("start",[this])};App.prototype.destroy=function(){return this.runHook("destroy")};App.prototype.runHook=function(name,args){var results=[];for(var i=0,len=this.modules.length;i1){return}event.preventDefault();this.ignoreMouseup=true},_onMouseup:function(event){if(event.which>1){return}if(this.ignoreMouseup){event.stopImmediatePropagation()}},_onClick:function(event){if(event.which>1){return}event.preventDefault();this.hide();this.ignoreMouseup=false;if(this.annotation!==null&&typeof this.onCreate==="function"){this.onCreate(this.annotation,event)}}});Adder.template=['
',' ","
"].join("\n");Adder.options={onCreate:null};exports.Adder=Adder},{"../util":30,"./widget":29}],21:[function(require,module,exports){"use strict";var Widget=require("./widget").Widget,util=require("../util");var $=util.$;var _t=util.gettext;var Promise=util.Promise;var NS="annotator-editor";var id=function(){var counter;counter=-1;return function(){return counter+=1}}();function preventEventDefault(event){if(typeof event!=="undefined"&&event!==null&&typeof event.preventDefault==="function"){event.preventDefault()}}var dragTracker=exports.dragTracker=function dragTracker(handle,callback){var lastPos=null,throttled=false;function mouseMove(e){if(throttled||lastPos===null){return}var delta={y:e.pageY-lastPos.top,x:e.pageX-lastPos.left};var trackLastMove=true;if(typeof callback==="function"){trackLastMove=callback(delta)}if(trackLastMove!==false){lastPos={top:e.pageY,left:e.pageX}}throttled=true;setTimeout(function(){throttled=false},1e3/60)}function mouseUp(){lastPos=null;$(handle.ownerDocument).off("mouseup",mouseUp).off("mousemove",mouseMove)}function mouseDown(e){if(e.target!==handle){return}lastPos={top:e.pageY,left:e.pageX};$(handle.ownerDocument).on("mouseup",mouseUp).on("mousemove",mouseMove);e.preventDefault()}function destroy(){$(handle).off("mousedown",mouseDown)}$(handle).on("mousedown",mouseDown);return{destroy:destroy}};var resizer=exports.resizer=function resizer(element,handle,options){var $el=$(element);if(typeof options==="undefined"||options===null){options={}}function translate(delta){var directionX=1,directionY=-1;if(typeof options.invertedX==="function"&&options.invertedX()){directionX=-1}if(typeof options.invertedY==="function"&&options.invertedY()){directionY=1}return{x:delta.x*directionX,y:delta.y*directionY}}function resize(delta){var height=$el.height(),width=$el.width(),translated=translate(delta);if(Math.abs(translated.x)>0){$el.width(width+translated.x)}if(Math.abs(translated.y)>0){$el.height(height+translated.y)}var didChange=$el.height()!==height||$el.width()!==width;return didChange}return dragTracker(handle,resize)};var mover=exports.mover=function mover(element,handle){function move(delta){$(element).css({top:parseInt($(element).css("top"),10)+delta.y,left:parseInt($(element).css("left"),10)+delta.x})}return dragTracker(handle,move)};var Editor=exports.Editor=Widget.extend({constructor:function(options){Widget.call(this,options);this.fields=[];this.annotation={};if(this.options.defaultFields){this.addField({type:"textarea",label:_t("Comments")+"…",load:function(field,annotation){$(field).find("textarea").val(annotation.text||"")},submit:function(field,annotation){annotation.text=$(field).find("textarea").val()}})}var self=this;this.element.on("submit."+NS,"form",function(e){self._onFormSubmit(e)}).on("click."+NS,".annotator-save",function(e){self._onSaveClick(e)}).on("click."+NS,".annotator-cancel",function(e){self._onCancelClick(e)}).on("mouseover."+NS,".annotator-cancel",function(e){self._onCancelMouseover(e)}).on("keydown."+NS,"textarea",function(e){self._onTextareaKeydown(e)})},destroy:function(){this.element.off("."+NS);Widget.prototype.destroy.call(this)},show:function(position){if(typeof position!=="undefined"&&position!==null){this.element.css({top:position.top,left:position.left})}this.element.find(".annotator-save").addClass(this.classes.focus);Widget.prototype.show.call(this);this.element.find(":input:first").focus();this._setupDraggables()},load:function(annotation,position){this.annotation=annotation;for(var i=0,len=this.fields.length;i');field.element=element[0];if(field.type==="textarea"){input=$("",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U="undefined";k.focusinBubbles="onfocusin"in a;var V=/^key/,W=/^(?:mouse|pointer|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return l.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof n!==U&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(E)||[""],j=b.length;while(j--)h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g,!1)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&(delete r.handle,L.remove(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,m,o,p=[d||l],q=j.call(b,"type")?b.type:b,r=j.call(b,"namespace")?b.namespace.split("."):[];if(g=h=d=d||l,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+n.event.triggered)&&(q.indexOf(".")>=0&&(r=q.split("."),q=r.shift(),r.sort()),k=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=r.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},e||!o.trigger||o.trigger.apply(d,c)!==!1)){if(!e&&!o.noBubble&&!n.isWindow(d)){for(i=o.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||l)&&p.push(h.defaultView||h.parentWindow||a)}f=0;while((g=p[f++])&&!b.isPropagationStopped())b.type=f>1?i:o.bindType||q,m=(L.get(g,"events")||{})[b.type]&&L.get(g,"handle"),m&&m.apply(g,c),m=k&&g[k],m&&m.apply&&n.acceptData(g)&&(b.result=m.apply(g,c),b.result===!1&&b.preventDefault());return b.type=q,e||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!n.acceptData(d)||k&&n.isFunction(d[q])&&!n.isWindow(d)&&(h=d[k],h&&(d[k]=null),n.event.triggered=q,d[q](),n.event.triggered=void 0,h&&(d[k]=h)),b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(L.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(g.namespace))&&(a.handleObj=g,a.data=g.data,e=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(a.result=e)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!==this;i=i.parentNode||this)if(i.disabled!==!0||"click"!==a.type){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>=0:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]*)\/>/gi,ba=/<([\w:]+)/,ca=/<|&#?\w+;/,da=/<(?:script|style|link)/i,ea=/checked\s*(?:[^=]|=\s*.checked.)/i,fa=/^$|\/(?:java|ecma)script/i,ga=/^true\/(.*)/,ha=/^\s*\s*$/g,ia={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ia.optgroup=ia.option,ia.tbody=ia.tfoot=ia.colgroup=ia.caption=ia.thead,ia.th=ia.td;function ja(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function ka(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function la(a){var b=ga.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function ma(a,b){for(var c=0,d=a.length;d>c;c++)L.set(a[c],"globalEval",!b||L.get(b[c],"globalEval"))}function na(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(L.hasData(a)&&(f=L.access(a),g=L.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}M.hasData(a)&&(h=M.access(a),i=n.extend({},h),M.set(b,i))}}function oa(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||"*"):a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function pa(a,b){var c=b.nodeName.toLowerCase();"input"===c&&T.test(a.type)?b.checked=a.checked:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}n.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=oa(h),f=oa(a),d=0,e=f.length;e>d;d++)pa(f[d],g[d]);if(b)if(c)for(f=f||oa(a),g=g||oa(h),d=0,e=f.length;e>d;d++)na(f[d],g[d]);else na(a,h);return g=oa(h,"script"),g.length>0&&ma(g,!i&&oa(a,"script")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,o=a.length;o>m;m++)if(e=a[m],e||0===e)if("object"===n.type(e))n.merge(l,e.nodeType?[e]:e);else if(ca.test(e)){f=f||k.appendChild(b.createElement("div")),g=(ba.exec(e)||["",""])[1].toLowerCase(),h=ia[g]||ia._default,f.innerHTML=h[1]+e.replace(aa,"<$1>")+h[2],j=h[0];while(j--)f=f.lastChild;n.merge(l,f.childNodes),f=k.firstChild,f.textContent=""}else l.push(b.createTextNode(e));k.textContent="",m=0;while(e=l[m++])if((!d||-1===n.inArray(e,d))&&(i=n.contains(e.ownerDocument,e),f=oa(k.appendChild(e),"script"),i&&ma(f),c)){j=0;while(e=f[j++])fa.test(e.type||"")&&c.push(e)}return k},cleanData:function(a){for(var b,c,d,e,f=n.event.special,g=0;void 0!==(c=a[g]);g++){if(n.acceptData(c)&&(e=c[L.expando],e&&(b=L.cache[e]))){if(b.events)for(d in b.events)f[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);L.cache[e]&&delete L.cache[e]}delete M.cache[c[M.expando]]}}}),n.fn.extend({text:function(a){return J(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=a)})},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=ja(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=ja(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(oa(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&ma(oa(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(oa(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return J(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!da.test(a)&&!ia[(ba.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(aa,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(oa(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(oa(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,m=this,o=l-1,p=a[0],q=n.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&ea.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(c=n.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(f=n.map(oa(c,"script"),ka),g=f.length;l>j;j++)h=c,j!==o&&(h=n.clone(h,!0,!0),g&&n.merge(f,oa(h,"script"))),b.call(this[j],h,j);if(g)for(i=f[f.length-1].ownerDocument,n.map(f,la),j=0;g>j;j++)h=f[j],fa.test(h.type||"")&&!L.access(h,"globalEval")&&n.contains(i,h)&&(h.src?n._evalUrl&&n._evalUrl(h.src):n.globalEval(h.textContent.replace(ha,"")))}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),g=e.length-1,h=0;g>=h;h++)c=h===g?this:this.clone(!0),n(e[h])[b](c),f.apply(d,c.get());return this.pushStack(d)}});var qa,ra={};function sa(b,c){var d,e=n(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:n.css(e[0],"display");return e.detach(),f}function ta(a){var b=l,c=ra[a];return c||(c=sa(a,b),"none"!==c&&c||(qa=(qa||n("