summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md41
-rw-r--r--CREDITS.md5
-rwxr-xr-xDocker/entrypoint.sh2
-rw-r--r--README.fr.md13
-rw-r--r--README.md13
-rw-r--r--app/Controllers/categoryController.php8
-rwxr-xr-xapp/Controllers/configureController.php10
-rwxr-xr-xapp/Controllers/entryController.php17
-rwxr-xr-xapp/Controllers/feedController.php12
-rwxr-xr-xapp/Controllers/indexController.php35
-rwxr-xr-xapp/Controllers/javascriptController.php5
-rw-r--r--app/Controllers/statsController.php2
-rw-r--r--app/Controllers/subscriptionController.php3
-rw-r--r--app/Controllers/tagController.php80
-rw-r--r--app/Controllers/updateController.php8
-rw-r--r--app/Controllers/userController.php23
-rw-r--r--app/FreshRSS.php1
-rw-r--r--app/Models/Category.php6
-rw-r--r--app/Models/CategoryDAO.php17
-rw-r--r--app/Models/Context.php46
-rw-r--r--app/Models/DatabaseDAO.php89
-rw-r--r--app/Models/DatabaseDAOPGSQL.php38
-rw-r--r--app/Models/DatabaseDAOSQLite.php14
-rw-r--r--app/Models/Entry.php53
-rw-r--r--app/Models/EntryDAO.php103
-rw-r--r--app/Models/EntryDAOPGSQL.php9
-rw-r--r--app/Models/EntryDAOSQLite.php48
-rw-r--r--app/Models/Factory.php16
-rw-r--r--app/Models/Feed.php34
-rw-r--r--app/Models/FeedDAO.php9
-rw-r--r--app/Models/Search.php37
-rw-r--r--app/Models/Tag.php76
-rw-r--r--app/Models/TagDAO.php315
-rw-r--r--app/Models/TagDAOPGSQL.php9
-rw-r--r--app/Models/TagDAOSQLite.php19
-rw-r--r--app/Models/Themes.php12
-rw-r--r--app/Models/UserDAO.php7
-rw-r--r--app/Models/UserQuery.php26
-rw-r--r--app/SQL/install.sql.mysql.php108
-rw-r--r--app/SQL/install.sql.pgsql.php56
-rw-r--r--app/SQL/install.sql.sqlite.php124
-rw-r--r--app/i18n/cz/conf.php2
-rw-r--r--app/i18n/cz/gen.php2
-rw-r--r--app/i18n/cz/index.php5
-rw-r--r--app/i18n/cz/sub.php1
-rw-r--r--app/i18n/de/admin.php4
-rw-r--r--app/i18n/de/conf.php4
-rw-r--r--app/i18n/de/feedback.php4
-rw-r--r--app/i18n/de/gen.php3
-rw-r--r--app/i18n/de/index.php7
-rw-r--r--app/i18n/de/install.php4
-rw-r--r--app/i18n/de/sub.php5
-rw-r--r--app/i18n/en/conf.php2
-rw-r--r--app/i18n/en/gen.php2
-rw-r--r--app/i18n/en/index.php5
-rw-r--r--app/i18n/en/sub.php1
-rwxr-xr-xapp/i18n/es/conf.php2
-rwxr-xr-xapp/i18n/es/gen.php2
-rwxr-xr-xapp/i18n/es/index.php5
-rwxr-xr-xapp/i18n/es/sub.php1
-rw-r--r--app/i18n/fr/conf.php2
-rw-r--r--app/i18n/fr/gen.php2
-rw-r--r--app/i18n/fr/index.php5
-rw-r--r--app/i18n/fr/sub.php1
-rw-r--r--app/i18n/he/conf.php2
-rw-r--r--app/i18n/he/gen.php2
-rw-r--r--app/i18n/he/index.php5
-rw-r--r--app/i18n/he/sub.php1
-rw-r--r--app/i18n/it/conf.php2
-rw-r--r--app/i18n/it/gen.php2
-rw-r--r--app/i18n/it/index.php5
-rw-r--r--app/i18n/it/sub.php1
-rw-r--r--app/i18n/kr/conf.php2
-rw-r--r--app/i18n/kr/gen.php2
-rw-r--r--app/i18n/kr/index.php5
-rw-r--r--app/i18n/kr/sub.php1
-rw-r--r--app/i18n/nl/conf.php2
-rw-r--r--app/i18n/nl/gen.php2
-rw-r--r--app/i18n/nl/index.php4
-rw-r--r--app/i18n/nl/sub.php1
-rw-r--r--app/i18n/pt-br/conf.php2
-rw-r--r--app/i18n/pt-br/gen.php2
-rw-r--r--app/i18n/pt-br/index.php4
-rw-r--r--app/i18n/pt-br/sub.php1
-rw-r--r--app/i18n/ru/conf.php2
-rw-r--r--app/i18n/ru/gen.php2
-rw-r--r--app/i18n/ru/index.php4
-rw-r--r--app/i18n/ru/sub.php1
-rw-r--r--app/i18n/tr/conf.php2
-rw-r--r--app/i18n/tr/gen.php2
-rw-r--r--app/i18n/tr/index.php5
-rw-r--r--app/i18n/tr/sub.php1
-rw-r--r--app/i18n/zh-cn/conf.php2
-rw-r--r--app/i18n/zh-cn/gen.php2
-rw-r--r--app/i18n/zh-cn/index.php5
-rw-r--r--app/i18n/zh-cn/sub.php1
-rw-r--r--app/install.php6
-rw-r--r--app/layout/aside_feed.phtml35
-rw-r--r--app/layout/layout.phtml34
-rw-r--r--app/views/configure/display.phtml6
-rwxr-xr-xapp/views/entry/read.phtml3
-rw-r--r--app/views/helpers/export/articles.phtml2
-rw-r--r--app/views/helpers/extension/configure.phtml2
-rw-r--r--app/views/helpers/feed/update.phtml7
-rw-r--r--app/views/helpers/index/normal/entry_bottom.phtml56
-rw-r--r--app/views/index/global.phtml5
-rw-r--r--app/views/index/normal.phtml24
-rw-r--r--app/views/index/reader.phtml21
-rwxr-xr-xapp/views/index/rss.phtml18
-rw-r--r--app/views/javascript/nbUnreadsPerFeed.phtml10
-rw-r--r--app/views/tag/getTagsForEntry.phtml2
-rw-r--r--cli/README.md2
-rwxr-xr-xcli/user-info.php5
-rw-r--r--constants.php2
-rw-r--r--data/users/.gitignore2
-rw-r--r--docs/en/admins/02_Installation.md2
-rw-r--r--docs/en/users/06_Fever_API.md1
-rw-r--r--docs/fr/users/01_Installation.md2
-rw-r--r--docs/fr/users/06_Fever_API.md1
-rw-r--r--extensions/Tumblr-GDPR/extension.php2
-rw-r--r--lib/Minz/Request.php2
-rw-r--r--lib/lib_rss.php11
-rw-r--r--p/api/fever.php43
-rw-r--r--p/api/greader.php172
-rwxr-xr-xp/i/index.php2
-rw-r--r--p/scripts/bcrypt.min.js94
-rw-r--r--p/scripts/jquery.min.js6
-rw-r--r--p/scripts/main.js138
-rw-r--r--p/themes/BlueLagoon/BlueLagoon.css3
-rw-r--r--p/themes/Dark/dark.css1
-rw-r--r--p/themes/Flat/flat.css2
-rw-r--r--p/themes/Origine/origine.css1
-rw-r--r--p/themes/Pafat/pafat.css7
-rw-r--r--p/themes/Screwdriver/screwdriver.css3
-rw-r--r--p/themes/Swage/icons/add.svg7
-rw-r--r--p/themes/Swage/icons/all.svg7
-rw-r--r--p/themes/Swage/icons/bookmark-add.svg6
-rw-r--r--p/themes/Swage/icons/bookmark.svg6
-rw-r--r--p/themes/Swage/icons/category.svg12
-rw-r--r--p/themes/Swage/icons/configure.svg12
-rw-r--r--p/themes/Swage/icons/down.svg6
-rw-r--r--p/themes/Swage/icons/error.svg5
-rw-r--r--p/themes/Swage/icons/icon.svg14
-rw-r--r--p/themes/Swage/icons/import.svg6
-rw-r--r--p/themes/Swage/icons/next.svg5
-rw-r--r--p/themes/Swage/icons/non-starred.svg6
-rw-r--r--p/themes/Swage/icons/prev.svg6
-rw-r--r--p/themes/Swage/icons/read.svg5
-rw-r--r--p/themes/Swage/icons/refresh.svg6
-rw-r--r--p/themes/Swage/icons/rss.svg7
-rw-r--r--p/themes/Swage/icons/starred.svg6
-rw-r--r--p/themes/Swage/icons/unread.svg6
-rw-r--r--p/themes/Swage/icons/up.svg6
-rw-r--r--p/themes/Swage/icons/view-global.svg6
-rw-r--r--p/themes/Swage/icons/view-normal.svg8
-rw-r--r--p/themes/Swage/icons/view-reader.svg6
-rw-r--r--p/themes/Swage/loader.gifbin0 -> 10242 bytes
-rw-r--r--p/themes/Swage/metadata.json7
-rw-r--r--p/themes/Swage/swage.css1211
-rw-r--r--p/themes/Swage/swage.scss1160
-rw-r--r--p/themes/Swage/thumbs/original.pngbin0 -> 260913 bytes
-rw-r--r--p/themes/base-theme/template.css9
162 files changed, 4432 insertions, 541 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 171943c2c..5f9923d03 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,46 @@
# FreshRSS changelog
+## 2018-10-28 FreshRSS 1.12.0
+
+* Features
+ * Ability to add *labels* (custom tags) to articles [#928](https://github.com/FreshRSS/FreshRSS/issues/928)
+ * Also available through Google Reader API (full support in News+, partial in FeedMe, EasyRSS). No support in Fever API.
+ * Handle article tags containing spaces, as well as comma-separated tags [#2023](https://github.com/FreshRSS/FreshRSS/pull/2023)
+ * Handle authors containing spaces, as well as comma or semi-colon separated authors [#2025](https://github.com/FreshRSS/FreshRSS/pull/2025)
+ * Searches by tag, author, etc. accept Unicode characters [#2025](https://github.com/FreshRSS/FreshRSS/pull/2025)
+ * New option to disable cache for feeds with invalid HTTP caching [#2052](https://github.com/FreshRSS/FreshRSS/pull/2052)
+* UI
+ * New theme *Swage* [#2069](https://github.com/FreshRSS/FreshRSS/pull/2069)
+ * Click on authors to initiate a search by author [#2025](https://github.com/FreshRSS/FreshRSS/pull/2025)
+ * Fix CSS for button alignments in older Chrome versions [#2020](https://github.com/FreshRSS/FreshRSS/pull/2020)
+ * Updated to jQuery 3.3.1 [#2021](https://github.com/FreshRSS/FreshRSS/pull/2021)
+ * Updated to bcrypt.js 2.4.4 [#2022](https://github.com/FreshRSS/FreshRSS/pull/2022)
+* Security
+ * Improved flow for password change (avoid error 403) [#2056](https://github.com/FreshRSS/FreshRSS/issues/2056)
+ * Allow dot `.` in username (best to avoid, though) [#2061](https://github.com/FreshRSS/FreshRSS/issues/2061)
+* Performance
+ * Remove some counterproductive preload / prefetch rules [#2040](https://github.com/FreshRSS/FreshRSS/pull/2040)
+ * Improved fast flush (earlier transfer, fetching of resources, and rendering) [#2045](https://github.com/FreshRSS/FreshRSS/pull/2045)
+ * Only available for Apache running PHP as module (not for NGINX, or PHP as CGI / FPM) because we want to keep compression
+* Deployment
+ * Fix Docker bug with some cron values [#2032](https://github.com/FreshRSS/FreshRSS/pull/2032)
+ * Perform `git clean -f -d -f` (removes unknown files and folders) before git auto-update method [#2036](https://github.com/FreshRSS/FreshRSS/pull/2036)
+* Bug fixing
+ * Make article GUIDs case-sensitive also with MySQL [#2077](https://github.com/FreshRSS/FreshRSS/issues/2077)
+ * Ask confirmation for important configuration actions [#2048](https://github.com/FreshRSS/FreshRSS/pull/2048)
+ * Fix database size in the Web UI for users about to be deleted [#2047](https://github.com/FreshRSS/FreshRSS/pull/2047)
+ * Fix actualize bug after install [#2044](https://github.com/FreshRSS/FreshRSS/pull/2044)
+ * Fix manual / Web actualize for which the final commit coud be done too early [#2081](https://github.com/FreshRSS/FreshRSS/pull/2081)
+ * Fix regression from version 1.11.2, which might have wrongly believed that the server address was private [#2084](https://github.com/FreshRSS/FreshRSS/pull/2084)
+ * Please check in `data/config.php` that you have `'pubsubhubbub_enabled' => true,` if your server has a public address
+* Extensions
+ * Update built-in extension to again fix Tumblr feeds from European Union due to GDPR [#2053](https://github.com/FreshRSS/FreshRSS/pull/2053)
+* I18n
+ * Fix missing German translations, e.g. for *Sharing with Known* [#2059](https://github.com/FreshRSS/FreshRSS/pull/2059)
+* Misc.
+ * Better port detection behind a proxy [#2031](https://github.com/FreshRSS/FreshRSS/issues/2031)
+
+
## 2018-09-09 FreshRSS 1.11.2
* Features
diff --git a/CREDITS.md b/CREDITS.md
index d43c5a322..9d3c07c0e 100644
--- a/CREDITS.md
+++ b/CREDITS.md
@@ -13,6 +13,7 @@ People are sorted by name so please keep this order.
* [Amaury Carrade](https://github.com/AmauryCarrade): [contributions](https://github.com/FreshRSS/FreshRSS/commits?author=AmauryCarrade), [Web](https://amaury.carrade.eu/)
* [Anton Smirnov](https://github.com/sandfoxme): [contributions](https://github.com/FreshRSS/FreshRSS/pulls?q=is:pr+author:sandfoxme), [Web](http://sandfox.me/)
* [ASMfreaK](https://github.com/ASMfreaK): [contributions](https://github.com/FreshRSS/FreshRSS/commits?author=ASMfreaK)
+* [chemical1979](https://github.com/chemical1979): [contributions](https://github.com/FreshRSS/FreshRSS/commits?author=chemical1979)
* [Craig Andrews](https://github.com/candrews): [contributions](https://github.com/FreshRSS/FreshRSS/pulls?q=is:pr+author:candrews), [Web](http://candrews.integralblue.com/)
* [Crupuk](https://github.com/Crupuk): [contributions](https://github.com/FreshRSS/FreshRSS/pulls?q=is:pr+author:Crupuk)
* [Damstre](https://github.com/Damstre): [contributions](https://github.com/FreshRSS/FreshRSS/pulls?q=is:pr+author:Damstre)
@@ -25,6 +26,7 @@ People are sorted by name so please keep this order.
* [gsongsong](https://github.com/gsongsong): [contributions](https://github.com/FreshRSS/FreshRSS/pulls?q=is:pr+author:gsongsong)
* [Guillaume Fillon](https://github.com/kokaz): [contributions](https://github.com/FreshRSS/FreshRSS/pulls?q=is:pr+author:kokaz), [Web](http://www.guillaume-fillon.com/)
* [Guillaume Hayot](https://github.com/postblue): [contributions](https://github.com/FreshRSS/FreshRSS/pulls?q=is:pr+author:postblue), [Web](https://postblue.info/)
+* [Gregor Nathanael Meyer](https://github.com/spackmat): [contributions](https://github.com/FreshRSS/FreshRSS/pulls?q=is:pr+author:spackmat), [Web](https://der-meyer.de)
* [hckweb](https://github.com/hckweb): [contributions](https://github.com/FreshRSS/FreshRSS/commits?author=hckweb)
* [hoilc](https://github.com/hoilc): [contributions](https://github.com/FreshRSS/FreshRSS/pulls?q=is:pr+author:hoilc)
* [Jan van den Berg](https://github.com/jan-vandenberg): [contributions](https://github.com/FreshRSS/FreshRSS/pulls?q=is:pr+author:jan-vandenberg), [Web](https://j11g.com/)
@@ -45,6 +47,7 @@ People are sorted by name so please keep this order.
* [Nicolas Lœuillet](https://github.com/nicosomb): [contributions](https://github.com/FreshRSS/documentation/commits?author=nicosomb), [Web](http://www.loeuillet.org/)
* [Nicola Spanti](https://github.com/RyDroid): [contributions](https://github.com/FreshRSS/FreshRSS/pulls?q=is:pr+author:RyDroid), [Web](http://www.nicola-spanti.info/)
* [Olivier Dossmann](https://github.com/blankoworld): [contributions](https://github.com/FreshRSS/FreshRSS/commits?author=blankoworld), [Web](https://olivier.dossmann.net)
+* [Patrick Crandol](https://github.com/pattems): [contributions](https://github.com/FreshRSS/FreshRSS/pulls?q=is:pr+author:pattems)
* [perrinjerome](https://github.com/perrinjerome): [contributions](https://github.com/FreshRSS/FreshRSS/pulls?q=is:pr+author:perrinjerome)
* [plopoyop](https://github.com/plopoyop): [contributions](https://github.com/FreshRSS/FreshRSS/commits?author=plopoyop)
* [Paulius Šukys](https://github.com/psukys): [contributions](https://github.com/FreshRSS/FreshRSS/pulls?q=is:pr+author:psukys), [Web](http://sukys.eu)
@@ -53,9 +56,11 @@ People are sorted by name so please keep this order.
* [Quentin Dufour](https://github.com/superboum): [contributions](https://github.com/FreshRSS/documentation/commits?author=superboum), [Web](http://quentin.dufour.io/)
* [Ramón Cutanda](https://github.com/rcutanda): [contributions](https://github.com/FreshRSS/FreshRSS/pulls?q=is:pr+author:rcutanda)
* [romibi](https://github.com/romibi): [contributions](https://github.com/FreshRSS/FreshRSS/commits/dev?author=romibi)
+* [sirideain](https://github.com/sirideain): [contributions](https://github.com/FreshRSS/FreshRSS/commits/dev?author=sirideain)
* [subic](https://github.com/subic): [contributions](https://github.com/FreshRSS/documentation/commits?author=subic)
* [Tets42](https://github.com/Tets42): [contributions](https://github.com/FreshRSS/FreshRSS/commits?author=Tets42)
* [Thomas Citharel](https://github.com/tcitworld): [contributions](https://github.com/FreshRSS/FreshRSS/pulls?q=is:pr+author:tomgue), [Web](https://www.tcit.fr/)
* [tomgue](https://github.com/tomgue): [contributions](https://github.com/FreshRSS/FreshRSS/commits?author=tomgue)
+* [Twilek-de](https://github.com/Twilek-de): [contributions](https://github.com/FreshRSS/FreshRSS/pulls?q=is:pr+author:Twilek-de)
* [Uncovery](https://github.com/uncovery): [contributions](https://github.com/FreshRSS/FreshRSS/pulls?q=is:pr+author:uncovery)
* [Wanabo](https://github.com/Wanabo): [contributions](https://github.com/FreshRSS/FreshRSS/commits?author=Wanabo)
diff --git a/Docker/entrypoint.sh b/Docker/entrypoint.sh
index 5b643da93..d4e1808bc 100755
--- a/Docker/entrypoint.sh
+++ b/Docker/entrypoint.sh
@@ -6,7 +6,7 @@ chown -R :www-data .
chmod -R g+r . && chmod -R g+w ./data/
if [ -n "$CRON_MIN" ]; then
- sed -r -i "/FreshRSS/s/^[^ ]+ /$CRON_MIN /" /var/spool/cron/crontabs/root
+ sed -r -i "\#FreshRSS#s#^[^ ]+ #$CRON_MIN #" /var/spool/cron/crontabs/root
fi
exec "$@"
diff --git a/README.fr.md b/README.fr.md
index ef1092e4a..312fbac45 100644
--- a/README.fr.md
+++ b/README.fr.md
@@ -4,12 +4,12 @@
* [English version](README.md)
# FreshRSS
-FreshRSS est un agrégateur de flux RSS à auto-héberger à l’image de [Leed](http://projet.idleman.fr/leed/) ou de [Kriss Feed](https://tontof.net/kriss/feed/).
+FreshRSS est un agrégateur de flux RSS à auto-héberger à l’image de [Leed](http://leed.idleman.fr/) ou de [Kriss Feed](https://tontof.net/kriss/feed/).
Il se veut léger et facile à prendre en main tout en étant un outil puissant et paramétrable.
Il permet de gérer plusieurs utilisateurs, et dispose d’un mode de lecture anonyme.
-Il supporte [PubSubHubbub](https://github.com/pubsubhubbub/PubSubHubbub) pour des notifications instantanées depuis les sites compatibles.
+Il supporte les étiquettes personnalisées, et [PubSubHubbub](https://github.com/pubsubhubbub/PubSubHubbub) pour des notifications instantanées depuis les sites compatibles.
Il y a une API pour les clients (mobiles), ainsi qu’une [interface en ligne de commande](cli/README.md).
Enfin, il permet l’ajout d’[extensions](#extensions) pour encore plus de personnalisation.
@@ -70,13 +70,7 @@ Plus d’informations sur l’installation et la configuration serveur peuvent
sudo apt-get install apache2
sudo a2enmod headers expires rewrite ssl #Modules Apache
-# Pour Ubuntu <= 15.10, Debian <= 8 Jessie
-sudo apt-get install php5 php5-curl php5-gmp php5-intl php5-json php5-sqlite
-sudo apt-get install libapache2-mod-php5 #Pour Apache
-sudo apt-get install mysql-server mysql-client php5-mysql #Base de données MySQL optionnelle
-sudo apt-get install postgresql php5-pgsql #Base de données PostgreSQL optionnelle
-
-# Pour Ubuntu >= 16.04, Debian >= 9 Stretch
+# Exemple pour Ubuntu >= 16.04, Debian >= 9 Stretch
sudo apt install php php-curl php-gmp php-intl php-mbstring php-sqlite3 php-xml php-zip
sudo apt install libapache2-mod-php #Pour Apache
sudo apt install mysql-server mysql-client php-mysql #Base de données MySQL optionnelle
@@ -187,6 +181,7 @@ Tout client supportant une API de type Fever ; Sélection :
* iOS
* [Fiery Feeds](https://itunes.apple.com/app/fiery-feeds-rss-reader/id1158763303) (Propriétaire)
* [Unread](https://itunes.apple.com/app/unread-rss-reader/id1252376153) (Propriétaire)
+ * [Reeder-3](https://itunes.apple.com/app/reeder-3/id697846300) (Propriétaire)
* MacOS
* [Readkit](https://itunes.apple.com/app/readkit/id588726889) (Propriétaire)
diff --git a/README.md b/README.md
index 0111d6882..2c0366077 100644
--- a/README.md
+++ b/README.md
@@ -4,12 +4,12 @@
* [Version française](README.fr.md)
# FreshRSS
-FreshRSS is a self-hosted RSS feed aggregator such as [Leed](http://projet.idleman.fr/leed/) or [Kriss Feed](https://tontof.net/kriss/feed/).
+FreshRSS is a self-hosted RSS feed aggregator such as [Leed](http://leed.idleman.fr/) or [Kriss Feed](https://tontof.net/kriss/feed/).
It is at the same time lightweight, easy to work with, powerful and customizable.
It is a multi-user application with an anonymous reading mode.
-It supports [PubSubHubbub](https://github.com/pubsubhubbub/PubSubHubbub) for instant notifications from compatible Web sites.
+It supports custom tags, and [PubSubHubbub](https://github.com/pubsubhubbub/PubSubHubbub) for instant notifications from compatible Web sites.
There is an API for (mobile) clients, and a [Command-Line Interface](cli/README.md).
Finally, it supports [extensions](#extensions) for further tuning.
@@ -70,13 +70,7 @@ More information about installation and server configuration can be found in [ou
sudo apt-get install apache2
sudo a2enmod headers expires rewrite ssl #Apache modules
-# For Ubuntu <= 15.10, Debian <= 8 Jessie
-sudo apt-get install php5 php5-curl php5-gmp php5-intl php5-json php5-sqlite
-sudo apt-get install libapache2-mod-php5 #For Apache
-sudo apt-get install mysql-server mysql-client php5-mysql #Optional MySQL database
-sudo apt-get install postgresql php5-pgsql #Optional PostgreSQL database
-
-# For Ubuntu >= 16.04, Debian >= 9 Stretch
+# Example for Ubuntu >= 16.04, Debian >= 9 Stretch
sudo apt install php php-curl php-gmp php-intl php-mbstring php-sqlite3 php-xml php-zip
sudo apt install libapache2-mod-php #For Apache
sudo apt install mysql-server mysql-client php-mysql #Optional MySQL database
@@ -187,6 +181,7 @@ Supported clients are:
* iOS
* [Fiery Feeds](https://itunes.apple.com/app/fiery-feeds-rss-reader/id1158763303) (Closed source)
* [Unread](https://itunes.apple.com/app/unread-rss-reader/id1252376153) (Closed source)
+ * [Reeder-3](https://itunes.apple.com/app/reeder-3/id697846300) (Closed source)
* MacOS
* [Readkit](https://itunes.apple.com/app/readkit/id588726889) (Closed source)
diff --git a/app/Controllers/categoryController.php b/app/Controllers/categoryController.php
index f3b35a323..2551a79d4 100644
--- a/app/Controllers/categoryController.php
+++ b/app/Controllers/categoryController.php
@@ -16,7 +16,7 @@ class FreshRSS_category_Controller extends Minz_ActionController {
Minz_Error::error(403);
}
- $catDAO = new FreshRSS_CategoryDAO();
+ $catDAO = FreshRSS_Factory::createCategoryDao();
$catDAO->checkDefault();
}
@@ -27,7 +27,7 @@ class FreshRSS_category_Controller extends Minz_ActionController {
* - new-category
*/
public function createAction() {
- $catDAO = new FreshRSS_CategoryDAO();
+ $catDAO = FreshRSS_Factory::createCategoryDao();
$url_redirect = array('c' => 'subscription', 'a' => 'index');
$limits = FreshRSS_Context::$system_conf->limits;
@@ -75,7 +75,7 @@ class FreshRSS_category_Controller extends Minz_ActionController {
* - name
*/
public function updateAction() {
- $catDAO = new FreshRSS_CategoryDAO();
+ $catDAO = FreshRSS_Factory::createCategoryDao();
$url_redirect = array('c' => 'subscription', 'a' => 'index');
if (Minz_Request::isPost()) {
@@ -116,7 +116,7 @@ class FreshRSS_category_Controller extends Minz_ActionController {
*/
public function deleteAction() {
$feedDAO = FreshRSS_Factory::createFeedDao();
- $catDAO = new FreshRSS_CategoryDAO();
+ $catDAO = FreshRSS_Factory::createCategoryDao();
$url_redirect = array('c' => 'subscription', 'a' => 'index');
if (Minz_Request::isPost()) {
diff --git a/app/Controllers/configureController.php b/app/Controllers/configureController.php
index d34b5d59d..20bcd2e76 100755
--- a/app/Controllers/configureController.php
+++ b/app/Controllers/configureController.php
@@ -243,8 +243,9 @@ class FreshRSS_configure_Controller extends Minz_ActionController {
* checking if categories and feeds are still in use.
*/
public function queriesAction() {
- $category_dao = new FreshRSS_CategoryDAO();
+ $category_dao = FreshRSS_Factory::createCategoryDao();
$feed_dao = FreshRSS_Factory::createFeedDao();
+ $tag_dao = FreshRSS_Factory::createTagDao();
if (Minz_Request::isPost()) {
$params = Minz_Request::param('queries', array());
@@ -277,16 +278,17 @@ class FreshRSS_configure_Controller extends Minz_ActionController {
* lean data.
*/
public function addQueryAction() {
- $category_dao = new FreshRSS_CategoryDAO();
+ $category_dao = FreshRSS_Factory::createCategoryDao();
$feed_dao = FreshRSS_Factory::createFeedDao();
+ $tag_dao = FreshRSS_Factory::createTagDao();
$queries = array();
foreach (FreshRSS_Context::$user_conf->queries as $key => $query) {
- $queries[$key] = new FreshRSS_UserQuery($query, $feed_dao, $category_dao);
+ $queries[$key] = new FreshRSS_UserQuery($query, $feed_dao, $category_dao, $tag_dao);
}
$params = Minz_Request::fetchGET();
$params['url'] = Minz_Url::display(array('params' => $params));
$params['name'] = _t('conf.query.number', count($queries) + 1);
- $queries[] = new FreshRSS_UserQuery($params, $feed_dao, $category_dao);
+ $queries[] = new FreshRSS_UserQuery($params, $feed_dao, $category_dao, $tag_dao);
FreshRSS_Context::$user_conf->queries = $queries;
FreshRSS_Context::$user_conf->save();
diff --git a/app/Controllers/entryController.php b/app/Controllers/entryController.php
index 16a15c447..fc0af0639 100755
--- a/app/Controllers/entryController.php
+++ b/app/Controllers/entryController.php
@@ -53,6 +53,7 @@ class FreshRSS_entry_Controller extends Minz_ActionController {
}
$params = array();
+ $this->view->tags = array();
$entryDAO = FreshRSS_Factory::createEntryDao();
if ($id === false) {
@@ -81,6 +82,12 @@ class FreshRSS_entry_Controller extends Minz_ActionController {
case 'a':
$entryDAO->markReadEntries($id_max, false, 0, FreshRSS_Context::$search, FreshRSS_Context::$state, $is_read);
break;
+ case 't':
+ $entryDAO->markReadTag($get, $id_max, FreshRSS_Context::$search, FreshRSS_Context::$state, $is_read);
+ break;
+ case 'T':
+ $entryDAO->markReadTag('', $id_max, FreshRSS_Context::$search, FreshRSS_Context::$state, $is_read);
+ break;
}
if ($next_get !== 'a') {
@@ -91,6 +98,13 @@ class FreshRSS_entry_Controller extends Minz_ActionController {
}
} else {
$entryDAO->markRead($id, $is_read);
+
+ $tagDAO = FreshRSS_Factory::createTagDao();
+ foreach ($tagDAO->getTagsForEntry($id) as $tag) {
+ if (!empty($tag['checked'])) {
+ $this->view->tags[] = $tag['id'];
+ }
+ }
}
if (!$this->ajax) {
@@ -193,6 +207,9 @@ class FreshRSS_entry_Controller extends Minz_ActionController {
$feedDAO->updateCachedValues();
+ $databaseDAO = FreshRSS_Factory::createDatabaseDAO();
+ $databaseDAO->minorDbMaintenance();
+
invalidateHttpCache();
Minz_Request::good(_t('feedback.sub.purge_completed', $nb_total), array(
'c' => 'configure',
diff --git a/app/Controllers/feedController.php b/app/Controllers/feedController.php
index 2f7495884..f2b1b8960 100755
--- a/app/Controllers/feedController.php
+++ b/app/Controllers/feedController.php
@@ -43,7 +43,7 @@ class FreshRSS_feed_Controller extends Minz_ActionController {
FreshRSS_UserDAO::touch();
@set_time_limit(300);
- $catDAO = new FreshRSS_CategoryDAO();
+ $catDAO = FreshRSS_Factory::createCategoryDao();
$url = trim($url);
@@ -192,7 +192,7 @@ class FreshRSS_feed_Controller extends Minz_ActionController {
// GET request: we must ask confirmation to user before adding feed.
Minz_View::prependTitle(_t('sub.feed.title_add') . ' · ');
- $this->catDAO = new FreshRSS_CategoryDAO();
+ $this->catDAO = FreshRSS_Factory::createCategoryDao();
$this->view->categories = $this->catDAO->listCategories(false);
$this->view->feed = new FreshRSS_Feed($url);
try {
@@ -481,6 +481,9 @@ class FreshRSS_feed_Controller extends Minz_ActionController {
if ($entryDAO->inTransaction()) {
$entryDAO->commit();
}
+
+ $databaseDAO = FreshRSS_Factory::createDatabaseDAO();
+ $databaseDAO->minorDbMaintenance();
}
return array($updated_feeds, reset($feeds), $nb_new_articles);
}
@@ -511,6 +514,9 @@ class FreshRSS_feed_Controller extends Minz_ActionController {
$entryDAO->commitNewEntries();
$feedDAO->updateCachedValues();
$entryDAO->commit();
+
+ $databaseDAO = FreshRSS_Factory::createDatabaseDAO();
+ $databaseDAO->minorDbMaintenance();
} else {
list($updated_feeds, $feed, $nb_new_articles) = self::actualizeFeed($id, $url, $force, null, false, $noCommit);
}
@@ -556,7 +562,7 @@ class FreshRSS_feed_Controller extends Minz_ActionController {
}
FreshRSS_UserDAO::touch();
- $catDAO = new FreshRSS_CategoryDAO();
+ $catDAO = FreshRSS_Factory::createCategoryDao();
if ($cat_id > 0) {
$cat = $catDAO->searchById($cat_id);
$cat_id = $cat == null ? 0 : $cat->id();
diff --git a/app/Controllers/indexController.php b/app/Controllers/indexController.php
index ddffdba73..fa914ef87 100755
--- a/app/Controllers/indexController.php
+++ b/app/Controllers/indexController.php
@@ -32,7 +32,29 @@ class FreshRSS_index_Controller extends Minz_ActionController {
Minz_Error::error(404);
}
- $this->view->callbackBeforeContent = function($view) {
+ $this->view->categories = FreshRSS_Context::$categories;
+
+ $this->view->rss_title = FreshRSS_Context::$name . ' | ' . Minz_View::title();
+ $title = FreshRSS_Context::$name;
+ if (FreshRSS_Context::$get_unread > 0) {
+ $title = '(' . FreshRSS_Context::$get_unread . ') ' . $title;
+ }
+ Minz_View::prependTitle($title . ' · ');
+
+ $this->view->callbackBeforeFeeds = function ($view) {
+ try {
+ $tagDAO = FreshRSS_Factory::createTagDao();
+ $view->tags = $tagDAO->listTags(true);
+ $view->nbUnreadTags = 0;
+ foreach ($view->tags as $tag) {
+ $view->nbUnreadTags += $tag->nbUnread();
+ }
+ } catch (Exception $e) {
+ Minz_Log::notice($e->getMessage());
+ }
+ };
+
+ $this->view->callbackBeforeEntries = function ($view) {
try {
FreshRSS_Context::$number++; //+1 for pagination
$entries = FreshRSS_index_Controller::listEntriesByContext();
@@ -60,15 +82,6 @@ class FreshRSS_index_Controller extends Minz_ActionController {
Minz_Log::notice($e->getMessage());
Minz_Error::error(404);
}
-
- $view->categories = FreshRSS_Context::$categories;
-
- $view->rss_title = FreshRSS_Context::$name . ' | ' . Minz_View::title();
- $title = FreshRSS_Context::$name;
- if (FreshRSS_Context::$get_unread > 0) {
- $title = '(' . FreshRSS_Context::$get_unread . ') ' . $title;
- }
- Minz_View::prependTitle($title . ' · ');
};
}
@@ -158,7 +171,7 @@ class FreshRSS_index_Controller extends Minz_ActionController {
*/
private function updateContext() {
if (empty(FreshRSS_Context::$categories)) {
- $catDAO = new FreshRSS_CategoryDAO();
+ $catDAO = FreshRSS_Factory::createCategoryDao();
FreshRSS_Context::$categories = $catDAO->listCategories();
}
diff --git a/app/Controllers/javascriptController.php b/app/Controllers/javascriptController.php
index 9d7acf647..d56da9cbb 100755
--- a/app/Controllers/javascriptController.php
+++ b/app/Controllers/javascriptController.php
@@ -7,14 +7,17 @@ class FreshRSS_javascript_Controller extends Minz_ActionController {
public function actualizeAction() {
header('Content-Type: application/json; charset=UTF-8');
+ Minz_Session::_param('actualize_feeds', false);
$feedDAO = FreshRSS_Factory::createFeedDao();
$this->view->feeds = $feedDAO->listFeedsOrderUpdate(FreshRSS_Context::$user_conf->ttl_default);
}
public function nbUnreadsPerFeedAction() {
header('Content-Type: application/json; charset=UTF-8');
- $catDAO = new FreshRSS_CategoryDAO();
+ $catDAO = FreshRSS_Factory::createCategoryDao();
$this->view->categories = $catDAO->listCategories(true, false);
+ $tagDAO = FreshRSS_Factory::createTagDao();
+ $this->view->tags = $tagDAO->listTags(true);
}
//For Web-form login
diff --git a/app/Controllers/statsController.php b/app/Controllers/statsController.php
index 5d1dee72c..acfacb890 100644
--- a/app/Controllers/statsController.php
+++ b/app/Controllers/statsController.php
@@ -131,7 +131,7 @@ class FreshRSS_stats_Controller extends Minz_ActionController {
*/
public function repartitionAction() {
$statsDAO = FreshRSS_Factory::createStatsDAO();
- $categoryDAO = new FreshRSS_CategoryDAO();
+ $categoryDAO = FreshRSS_Factory::createCategoryDao();
$feedDAO = FreshRSS_Factory::createFeedDao();
Minz_View::appendScript(Minz_Url::display('/scripts/flotr2.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/flotr2.min.js')));
$id = Minz_Request::param('id', null);
diff --git a/app/Controllers/subscriptionController.php b/app/Controllers/subscriptionController.php
index 701a588e0..0b1439ba5 100644
--- a/app/Controllers/subscriptionController.php
+++ b/app/Controllers/subscriptionController.php
@@ -14,7 +14,7 @@ class FreshRSS_subscription_Controller extends Minz_ActionController {
Minz_Error::error(403);
}
- $catDAO = new FreshRSS_CategoryDAO();
+ $catDAO = FreshRSS_Factory::createCategoryDao();
$feedDAO = FreshRSS_Factory::createFeedDao();
$catDAO->checkDefault();
@@ -98,6 +98,7 @@ class FreshRSS_subscription_Controller extends Minz_ActionController {
$feed->_attributes('mark_updated_article_unread', Minz_Request::paramTernary('mark_updated_article_unread'));
$feed->_attributes('read_upon_reception', Minz_Request::paramTernary('read_upon_reception'));
+ $feed->_attributes('clear_cache', Minz_Request::paramTernary('clear_cache'));
if (FreshRSS_Auth::hasAccess('admin')) {
$feed->_attributes('ssl_verify', Minz_Request::paramTernary('ssl_verify'));
diff --git a/app/Controllers/tagController.php b/app/Controllers/tagController.php
new file mode 100644
index 000000000..106e0afa8
--- /dev/null
+++ b/app/Controllers/tagController.php
@@ -0,0 +1,80 @@
+<?php
+
+/**
+ * Controller to handle every tag actions.
+ */
+class FreshRSS_tag_Controller extends Minz_ActionController {
+ /**
+ * This action is called before every other action in that class. It is
+ * the common boiler plate for every action. It is triggered by the
+ * underlying framework.
+ */
+ public function firstAction() {
+ if (!FreshRSS_Auth::hasAccess()) {
+ Minz_Error::error(403);
+ }
+ // If ajax request, we do not print layout
+ $this->ajax = Minz_Request::param('ajax');
+ if ($this->ajax) {
+ $this->view->_useLayout(false);
+ Minz_Request::_param('ajax');
+ }
+ }
+
+ /**
+ * This action adds (checked=true) or removes (checked=false) a tag to an entry.
+ */
+ public function tagEntryAction() {
+ if (Minz_Request::isPost()) {
+ $id_tag = Minz_Request::param('id_tag');
+ $name_tag = trim(Minz_Request::param('name_tag'));
+ $id_entry = Minz_Request::param('id_entry');
+ $checked = Minz_Request::paramTernary('checked');
+ if ($id_entry != false) {
+ $tagDAO = FreshRSS_Factory::createTagDao();
+ if ($id_tag == 0 && $name_tag != '' && $checked) {
+ //Create new tag
+ $id_tag = $tagDAO->addTag(array('name' => $name_tag));
+ }
+ if ($id_tag != 0) {
+ $tagDAO->tagEntry($id_tag, $id_entry, $checked);
+ }
+ }
+ } else {
+ Minz_Error::error(405);
+ }
+ if (!$this->ajax) {
+ Minz_Request::forward(array(
+ 'c' => 'index',
+ 'a' => 'index',
+ ), true);
+ }
+ }
+
+ public function deleteAction() {
+ if (Minz_Request::isPost()) {
+ $id_tag = Minz_Request::param('id_tag');
+ if ($id_tag != false) {
+ $tagDAO = FreshRSS_Factory::createTagDao();
+ $tagDAO->deleteTag($id_tag);
+ }
+ } else {
+ Minz_Error::error(405);
+ }
+ if (!$this->ajax) {
+ Minz_Request::forward(array(
+ 'c' => 'index',
+ 'a' => 'index',
+ ), true);
+ }
+ }
+
+ public function getTagsForEntryAction() {
+ $this->view->_useLayout(false);
+ header('Content-Type: application/json; charset=UTF-8');
+ header('Cache-Control: private, no-cache, no-store, must-revalidate');
+ $id_entry = Minz_Request::param('id_entry', 0);
+ $tagDAO = FreshRSS_Factory::createTagDao();
+ $this->view->tags = $tagDAO->getTagsForEntry($id_entry);
+ }
+}
diff --git a/app/Controllers/updateController.php b/app/Controllers/updateController.php
index c67b358bb..2be644c85 100644
--- a/app/Controllers/updateController.php
+++ b/app/Controllers/updateController.php
@@ -32,7 +32,13 @@ class FreshRSS_update_Controller extends Minz_ActionController {
$output = array();
$return = 1;
try {
- exec('git pull --ff-only', $output, $return);
+ exec('git clean -f -d -f', $output, $return);
+ if ($return == 0) {
+ exec('git pull --ff-only', $output, $return);
+ } else {
+ $line = is_array($output) ? implode('; ', $output) : '' . $output;
+ Minz_Log::warning('git clean warning:' . $line);
+ }
} catch (Exception $e) {
Minz_Log::warning('git pull error:' . $e->getMessage());
}
diff --git a/app/Controllers/userController.php b/app/Controllers/userController.php
index 75a4303d6..2338c8b2a 100644
--- a/app/Controllers/userController.php
+++ b/app/Controllers/userController.php
@@ -38,7 +38,7 @@ class FreshRSS_user_Controller extends Minz_ActionController {
* The username is also used as folder name, file name, and part of SQL table name.
* '_' is a reserved internal username.
*/
- const USERNAME_PATTERN = '[0-9a-zA-Z_]{2,38}|[0-9a-zA-Z]';
+ const USERNAME_PATTERN = '[0-9a-zA-Z_][0-9a-zA-Z_.]{1,38}|[0-9a-zA-Z]';
public static function checkUsername($username) {
return preg_match('/^' . self::USERNAME_PATTERN . '$/', $username) === 1;
@@ -91,6 +91,10 @@ class FreshRSS_user_Controller extends Minz_ActionController {
}
public function updateAction() {
+ if (!FreshRSS_Auth::hasAccess('admin')) {
+ Minz_Error::error(403);
+ }
+
if (Minz_Request::isPost()) {
$passwordPlain = Minz_Request::param('newPasswordPlain', '', true);
Minz_Request::_param('newPasswordPlain'); //Discard plain-text password ASAP
@@ -104,8 +108,12 @@ class FreshRSS_user_Controller extends Minz_ActionController {
));
if ($ok) {
- Minz_Request::good(_t('feedback.user.updated', $username),
- array('c' => 'user', 'a' => 'manage'));
+ $isSelfUpdate = Minz_Session::param('currentUser', '_') === $username;
+ if ($passwordPlain == '' || !$isSelfUpdate) {
+ Minz_Request::good(_t('feedback.user.updated', $username), array('c' => 'user', 'a' => 'manage'));
+ } else {
+ Minz_Request::good(_t('feedback.profile.updated'), array('c' => 'index', 'a' => 'index'));
+ }
} else {
Minz_Request::bad(_t('feedback.user.updated.error', $username),
array('c' => 'user', 'a' => 'manage'));
@@ -138,8 +146,11 @@ class FreshRSS_user_Controller extends Minz_ActionController {
Minz_Session::_param('passwordHash', FreshRSS_Context::$user_conf->passwordHash);
if ($ok) {
- Minz_Request::good(_t('feedback.profile.updated'),
- array('c' => 'user', 'a' => 'profile'));
+ if ($passwordPlain == '') {
+ Minz_Request::good(_t('feedback.profile.updated'), array('c' => 'user', 'a' => 'profile'));
+ } else {
+ Minz_Request::good(_t('feedback.profile.updated'), array('c' => 'index', 'a' => 'index'));
+ }
} else {
Minz_Request::bad(_t('feedback.profile.error'),
array('c' => 'user', 'a' => 'profile'));
@@ -166,7 +177,7 @@ class FreshRSS_user_Controller extends Minz_ActionController {
$entryDAO = FreshRSS_Factory::createEntryDao($this->view->current_user);
$this->view->nb_articles = $entryDAO->count();
- $databaseDAO = FreshRSS_Factory::createDatabaseDAO();
+ $databaseDAO = FreshRSS_Factory::createDatabaseDAO($this->view->current_user);
$this->view->size_user = $databaseDAO->size();
}
}
diff --git a/app/FreshRSS.php b/app/FreshRSS.php
index 2bd5135a9..dec446a8e 100644
--- a/app/FreshRSS.php
+++ b/app/FreshRSS.php
@@ -90,7 +90,6 @@ class FreshRSS extends Minz_FrontController {
}
$filetime = @filemtime(PUBLIC_PATH . '/themes/' . $theme_id . '/' . $filename);
$url = '/themes/' . $theme_id . '/' . $filename . '?' . $filetime;
- header('Link: <' . Minz_Url::display($url, '', 'root') . '>;rel=preload', false); //HTTP2
Minz_View::prependStyle(Minz_Url::display($url));
}
}
diff --git a/app/Models/Category.php b/app/Models/Category.php
index 197faf942..240dbca73 100644
--- a/app/Models/Category.php
+++ b/app/Models/Category.php
@@ -30,7 +30,7 @@ class FreshRSS_Category extends Minz_Model {
}
public function nbFeed() {
if ($this->nbFeed < 0) {
- $catDAO = new FreshRSS_CategoryDAO();
+ $catDAO = FreshRSS_Factory::createCategoryDao();
$this->nbFeed = $catDAO->countFeed($this->id());
}
@@ -38,7 +38,7 @@ class FreshRSS_Category extends Minz_Model {
}
public function nbNotRead() {
if ($this->nbNotRead < 0) {
- $catDAO = new FreshRSS_CategoryDAO();
+ $catDAO = FreshRSS_Factory::createCategoryDao();
$this->nbNotRead = $catDAO->countNotRead($this->id());
}
@@ -68,7 +68,7 @@ class FreshRSS_Category extends Minz_Model {
$this->id = $value;
}
public function _name($value) {
- $this->name = mb_strcut(trim($value), 0, 255, 'UTF-8');
+ $this->name = trim($value);
}
public function _feeds($values) {
if (!is_array($values)) {
diff --git a/app/Models/CategoryDAO.php b/app/Models/CategoryDAO.php
index cf6b3bae3..ba7eb765e 100644
--- a/app/Models/CategoryDAO.php
+++ b/app/Models/CategoryDAO.php
@@ -5,11 +5,15 @@ class FreshRSS_CategoryDAO extends Minz_ModelPdo implements FreshRSS_Searchable
const DEFAULTCATEGORYID = 1;
public function addCategory($valuesTmp) {
- $sql = 'INSERT INTO `' . $this->prefix . 'category`(name) VALUES(?)';
+ $sql = 'INSERT INTO `' . $this->prefix . 'category`(name) '
+ . 'SELECT * FROM (SELECT TRIM(?)) c2 ' //TRIM() to provide a type hint as text for PostgreSQL
+ . 'WHERE NOT EXISTS (SELECT 1 FROM `' . $this->prefix . 'tag` WHERE name = TRIM(?))'; //No tag of the same name
$stm = $this->bd->prepare($sql);
+ $valuesTmp['name'] = mb_strcut(trim($valuesTmp['name']), 0, FreshRSS_DatabaseDAO::LENGTH_INDEX_UNICODE, 'UTF-8');
$values = array(
- mb_strcut($valuesTmp['name'], 0, 255, 'UTF-8'),
+ $valuesTmp['name'],
+ $valuesTmp['name'],
);
if ($stm && $stm->execute($values)) {
@@ -35,12 +39,15 @@ class FreshRSS_CategoryDAO extends Minz_ModelPdo implements FreshRSS_Searchable
}
public function updateCategory($id, $valuesTmp) {
- $sql = 'UPDATE `' . $this->prefix . 'category` SET name=? WHERE id=?';
+ $sql = 'UPDATE `' . $this->prefix . 'category` SET name=? WHERE id=? '
+ . 'AND NOT EXISTS (SELECT 1 FROM `' . $this->prefix . 'tag` WHERE name = ?)'; //No tag of the same name
$stm = $this->bd->prepare($sql);
+ $valuesTmp['name'] = mb_strcut(trim($valuesTmp['name']), 0, FreshRSS_DatabaseDAO::LENGTH_INDEX_UNICODE, 'UTF-8');
$values = array(
$valuesTmp['name'],
- $id
+ $id,
+ $valuesTmp['name'],
);
if ($stm && $stm->execute($values)) {
@@ -151,7 +158,7 @@ class FreshRSS_CategoryDAO extends Minz_ModelPdo implements FreshRSS_Searchable
$sql = 'INSERT INTO `' . $this->prefix . 'category`(id, name) VALUES(?, ?)';
if (parent::$sharedDbType === 'pgsql') {
//Force call to nextval()
- $sql .= " RETURNING nextval('" . $this->prefix . "category_id_seq');";
+ $sql .= ' RETURNING nextval(\'"' . $this->prefix . 'category_id_seq"\');';
}
$stm = $this->bd->prepare($sql);
diff --git a/app/Models/Context.php b/app/Models/Context.php
index 2ca8f80b0..60ec6ff77 100644
--- a/app/Models/Context.php
+++ b/app/Models/Context.php
@@ -8,6 +8,7 @@ class FreshRSS_Context {
public static $user_conf = null;
public static $system_conf = null;
public static $categories = array();
+ public static $tags = array();
public static $name = '';
public static $description = '';
@@ -25,6 +26,8 @@ class FreshRSS_Context {
'starred' => false,
'feed' => false,
'category' => false,
+ 'tag' => false,
+ 'tags' => false,
);
public static $next_get = 'a';
@@ -91,6 +94,14 @@ class FreshRSS_Context {
} else {
return 'c_' . self::$current_get['category'];
}
+ } elseif (self::$current_get['tag']) {
+ if ($array) {
+ return array('t', self::$current_get['tag']);
+ } else {
+ return 't_' . self::$current_get['tag'];
+ }
+ } elseif (self::$current_get['tags']) {
+ return 'T';
}
}
@@ -117,6 +128,10 @@ class FreshRSS_Context {
return self::$current_get['feed'] == $id;
case 'c':
return self::$current_get['category'] == $id;
+ case 't':
+ return self::$current_get['tag'] == $id;
+ case 'T':
+ return self::$current_get['tags'] || self::$current_get['tag'];
default:
return false;
}
@@ -130,6 +145,7 @@ class FreshRSS_Context {
* - s
* - f_<feed id>
* - c_<category id>
+ * - t_<tag id>
*
* $name and $get_unread attributes are also updated as $next_get
* Raise an exception if id or $get is invalid.
@@ -140,7 +156,7 @@ class FreshRSS_Context {
$nb_unread = 0;
if (empty(self::$categories)) {
- $catDAO = new FreshRSS_CategoryDAO();
+ $catDAO = FreshRSS_Factory::createCategoryDao();
self::$categories = $catDAO->listCategories();
}
@@ -166,12 +182,10 @@ class FreshRSS_Context {
if ($feed === null) {
$feedDAO = FreshRSS_Factory::createFeedDao();
$feed = $feedDAO->searchById($id);
-
if (!$feed) {
throw new FreshRSS_Context_Exception('Invalid feed: ' . $id);
}
}
-
self::$current_get['feed'] = $id;
self::$current_get['category'] = $feed->category();
self::$name = $feed->name();
@@ -182,19 +196,37 @@ class FreshRSS_Context {
// We try to find the corresponding category.
self::$current_get['category'] = $id;
if (!isset(self::$categories[$id])) {
- $catDAO = new FreshRSS_CategoryDAO();
+ $catDAO = FreshRSS_Factory::createCategoryDao();
$cat = $catDAO->searchById($id);
-
if (!$cat) {
throw new FreshRSS_Context_Exception('Invalid category: ' . $id);
}
} else {
$cat = self::$categories[$id];
}
-
self::$name = $cat->name();
self::$get_unread = $cat->nbNotRead();
break;
+ case 't':
+ // We try to find the corresponding tag.
+ self::$current_get['tag'] = $id;
+ if (!isset(self::$tags[$id])) {
+ $tagDAO = FreshRSS_Factory::createTagDao();
+ $tag = $tagDAO->searchById($id);
+ if (!$tag) {
+ throw new FreshRSS_Context_Exception('Invalid tag: ' . $id);
+ }
+ } else {
+ $tag = self::$tags[$id];
+ }
+ self::$name = $tag->name();
+ self::$get_unread = $tag->nbUnread();
+ break;
+ case 'T':
+ self::$current_get['tags'] = true;
+ self::$name = _t('index.menu.tags');
+ self::$get_unread = 0;
+ break;
default:
throw new FreshRSS_Context_Exception('Invalid getter: ' . $get);
}
@@ -211,7 +243,7 @@ class FreshRSS_Context {
self::$next_get = $get;
if (empty(self::$categories)) {
- $catDAO = new FreshRSS_CategoryDAO();
+ $catDAO = FreshRSS_Factory::createCategoryDao();
self::$categories = $catDAO->listCategories();
}
diff --git a/app/Models/DatabaseDAO.php b/app/Models/DatabaseDAO.php
index b8e5577e4..b331eccc3 100644
--- a/app/Models/DatabaseDAO.php
+++ b/app/Models/DatabaseDAO.php
@@ -4,6 +4,16 @@
* This class is used to test database is well-constructed.
*/
class FreshRSS_DatabaseDAO extends Minz_ModelPdo {
+
+ //MySQL error codes
+ const ER_BAD_FIELD_ERROR = '42S22';
+ const ER_BAD_TABLE_ERROR = '42S02';
+ const ER_TRUNCATED_WRONG_VALUE_FOR_FIELD = '1366';
+
+ //MySQL InnoDB maximum index length for UTF8MB4
+ //https://dev.mysql.com/doc/refman/8.0/en/innodb-restrictions.html
+ const LENGTH_INDEX_UNICODE = 191;
+
public function tablesAreCorrect() {
$sql = 'SHOW TABLES';
$stm = $this->bd->prepare($sql);
@@ -14,6 +24,9 @@ class FreshRSS_DatabaseDAO extends Minz_ModelPdo {
$this->prefix . 'category' => false,
$this->prefix . 'feed' => false,
$this->prefix . 'entry' => false,
+ $this->prefix . 'entrytmp' => false,
+ $this->prefix . 'tag' => false,
+ $this->prefix . 'entrytag' => false,
);
foreach ($res as $value) {
$tables[array_pop($value)] = true;
@@ -43,7 +56,7 @@ class FreshRSS_DatabaseDAO extends Minz_ModelPdo {
public function categoryIsCorrect() {
return $this->checkTable('category', array(
- 'id', 'name'
+ 'id', 'name',
));
}
@@ -51,14 +64,33 @@ class FreshRSS_DatabaseDAO extends Minz_ModelPdo {
return $this->checkTable('feed', array(
'id', 'url', 'category', 'name', 'website', 'description', 'lastUpdate',
'priority', 'pathEntries', 'httpAuth', 'error', 'keep_history', 'ttl', 'attributes',
- 'cache_nbEntries', 'cache_nbUnreads'
+ 'cache_nbEntries', 'cache_nbUnreads',
));
}
public function entryIsCorrect() {
return $this->checkTable('entry', array(
- 'id', 'guid', 'title', 'author', 'content_bin', 'link', 'date', 'is_read',
- 'is_favorite', 'id_feed', 'tags'
+ 'id', 'guid', 'title', 'author', 'content_bin', 'link', 'date', 'lastSeen', 'hash', 'is_read',
+ 'is_favorite', 'id_feed', 'tags',
+ ));
+ }
+
+ public function entrytmpIsCorrect() {
+ return $this->checkTable('entrytmp', array(
+ 'id', 'guid', 'title', 'author', 'content_bin', 'link', 'date', 'lastSeen', 'hash', 'is_read',
+ 'is_favorite', 'id_feed', 'tags',
+ ));
+ }
+
+ public function tagIsCorrect() {
+ return $this->checkTable('tag', array(
+ 'id', 'name', 'attributes',
+ ));
+ }
+
+ public function entrytagIsCorrect() {
+ return $this->checkTable('entrytag', array(
+ 'id_tag', 'id_entry',
));
}
@@ -97,28 +129,39 @@ class FreshRSS_DatabaseDAO extends Minz_ModelPdo {
public function optimize() {
$ok = true;
-
- $sql = 'OPTIMIZE TABLE `' . $this->prefix . 'entry`'; //MySQL
- $stm = $this->bd->prepare($sql);
- $ok &= $stm != false;
- if ($stm) {
- $ok &= $stm->execute();
- }
-
- $sql = 'OPTIMIZE TABLE `' . $this->prefix . 'feed`'; //MySQL
- $stm = $this->bd->prepare($sql);
- $ok &= $stm != false;
- if ($stm) {
- $ok &= $stm->execute();
+ $tables = array('category', 'feed', 'entry', 'entrytmp', 'tag', 'entrytag');
+
+ foreach ($tables as $table) {
+ $sql = 'OPTIMIZE TABLE `' . $this->prefix . $table . '`'; //MySQL
+ $stm = $this->bd->prepare($sql);
+ $ok &= $stm != false;
+ if ($stm) {
+ $ok &= $stm->execute();
+ }
}
+ return $ok;
+ }
- $sql = 'OPTIMIZE TABLE `' . $this->prefix . 'category`'; //MySQL
- $stm = $this->bd->prepare($sql);
- $ok &= $stm != false;
- if ($stm) {
- $ok &= $stm->execute();
+ public function ensureCaseInsensitiveGuids() {
+ $ok = true;
+ $db = FreshRSS_Context::$system_conf->db;
+ if ($db['type'] === 'mysql') {
+ include_once(APP_PATH . '/SQL/install.sql.mysql.php');
+ if (defined('SQL_UPDATE_GUID_LATIN1_BIN')) { //FreshRSS 1.12
+ try {
+ $sql = sprintf(SQL_UPDATE_GUID_LATIN1_BIN, $this->prefix);
+ $stm = $this->bd->prepare($sql);
+ $ok = $stm->execute();
+ } catch (Exception $e) {
+ $ok = false;
+ Minz_Log::error('FreshRSS_DatabaseDAO::ensureCaseInsensitiveGuids error: ' . $e->getMessage());
+ }
+ }
}
-
return $ok;
}
+
+ public function minorDbMaintenance() {
+ $this->ensureCaseInsensitiveGuids();
+ }
}
diff --git a/app/Models/DatabaseDAOPGSQL.php b/app/Models/DatabaseDAOPGSQL.php
index 1b3f7408d..8582b5719 100644
--- a/app/Models/DatabaseDAOPGSQL.php
+++ b/app/Models/DatabaseDAOPGSQL.php
@@ -3,7 +3,12 @@
/**
* This class is used to test database is well-constructed.
*/
-class FreshRSS_DatabaseDAOPGSQL extends FreshRSS_DatabaseDAO {
+class FreshRSS_DatabaseDAOPGSQL extends FreshRSS_DatabaseDAOSQLite {
+
+ //PostgreSQL error codes
+ const UNDEFINED_COLUMN = '42703';
+ const UNDEFINED_TABLE = '42P01';
+
public function tablesAreCorrect() {
$db = FreshRSS_Context::$system_conf->db;
$dbowner = $db['user'];
@@ -17,6 +22,9 @@ class FreshRSS_DatabaseDAOPGSQL extends FreshRSS_DatabaseDAO {
$this->prefix . 'category' => false,
$this->prefix . 'feed' => false,
$this->prefix . 'entry' => false,
+ $this->prefix . 'entrytmp' => false,
+ $this->prefix . 'tag' => false,
+ $this->prefix . 'entrytag' => false,
);
foreach ($res as $value) {
$tables[array_pop($value)] = true;
@@ -53,28 +61,16 @@ class FreshRSS_DatabaseDAOPGSQL extends FreshRSS_DatabaseDAO {
public function optimize() {
$ok = true;
+ $tables = array('category', 'feed', 'entry', 'entrytmp', 'tag', 'entrytag');
- $sql = 'VACUUM `' . $this->prefix . 'entry`';
- $stm = $this->bd->prepare($sql);
- $ok &= $stm != false;
- if ($stm) {
- $ok &= $stm->execute();
- }
-
- $sql = 'VACUUM `' . $this->prefix . 'feed`';
- $stm = $this->bd->prepare($sql);
- $ok &= $stm != false;
- if ($stm) {
- $ok &= $stm->execute();
+ foreach ($tables as $table) {
+ $sql = 'VACUUM `' . $this->prefix . $table . '`';
+ $stm = $this->bd->prepare($sql);
+ $ok &= $stm != false;
+ if ($stm) {
+ $ok &= $stm->execute();
+ }
}
-
- $sql = 'VACUUM `' . $this->prefix . 'category`';
- $stm = $this->bd->prepare($sql);
- $ok &= $stm != false;
- if ($stm) {
- $ok &= $stm->execute();
- }
-
return $ok;
}
}
diff --git a/app/Models/DatabaseDAOSQLite.php b/app/Models/DatabaseDAOSQLite.php
index d3aedb3c0..a93a209b2 100644
--- a/app/Models/DatabaseDAOSQLite.php
+++ b/app/Models/DatabaseDAOSQLite.php
@@ -14,6 +14,9 @@ class FreshRSS_DatabaseDAOSQLite extends FreshRSS_DatabaseDAO {
'category' => false,
'feed' => false,
'entry' => false,
+ 'entrytmp' => false,
+ 'tag' => false,
+ 'entrytag' => false,
);
foreach ($res as $value) {
$tables[$value['name']] = true;
@@ -32,8 +35,15 @@ class FreshRSS_DatabaseDAOSQLite extends FreshRSS_DatabaseDAO {
public function entryIsCorrect() {
return $this->checkTable('entry', array(
- 'id', 'guid', 'title', 'author', 'content', 'link', 'date', 'is_read',
- 'is_favorite', 'id_feed', 'tags'
+ 'id', 'guid', 'title', 'author', 'content', 'link', 'date', 'lastSeen', 'hash', 'is_read',
+ 'is_favorite', 'id_feed', 'tags',
+ ));
+ }
+
+ public function entrytmpIsCorrect() {
+ return $this->checkTable('entrytmp', array(
+ 'id', 'guid', 'title', 'author', 'content', 'link', 'date', 'lastSeen', 'hash', 'is_read',
+ 'is_favorite', 'id_feed', 'tags',
));
}
diff --git a/app/Models/Entry.php b/app/Models/Entry.php
index ccbad5724..985276734 100644
--- a/app/Models/Entry.php
+++ b/app/Models/Entry.php
@@ -10,7 +10,7 @@ class FreshRSS_Entry extends Minz_Model {
private $id = 0;
private $guid;
private $title;
- private $author;
+ private $authors;
private $content;
private $link;
private $date;
@@ -21,18 +21,17 @@ class FreshRSS_Entry extends Minz_Model {
private $feed;
private $tags;
- public function __construct($feedId = '', $guid = '', $title = '', $author = '', $content = '',
+ public function __construct($feedId = '', $guid = '', $title = '', $authors = '', $content = '',
$link = '', $pubdate = 0, $is_read = false, $is_favorite = false, $tags = '') {
$this->_title($title);
- $this->_author($author);
+ $this->_authors($authors);
$this->_content($content);
$this->_link($link);
$this->_date($pubdate);
$this->_isRead($is_read);
$this->_isFavorite($is_favorite);
$this->_feedId($feedId);
- $tags = mb_strcut($tags, 0, 1023, 'UTF-8');
- $this->_tags(preg_split('/[\s#]/', $tags));
+ $this->_tags($tags);
$this->_guid($guid);
}
@@ -46,7 +45,15 @@ class FreshRSS_Entry extends Minz_Model {
return $this->title;
}
public function author() {
- return $this->author === null ? '' : $this->author;
+ //Deprecated
+ return $this->authors(true);
+ }
+ public function authors($asString = false) {
+ if ($asString) {
+ return $this->authors == null ? '' : ';' . implode('; ', $this->authors);
+ } else {
+ return $this->authors;
+ }
}
public function content() {
return $this->content;
@@ -86,9 +93,9 @@ class FreshRSS_Entry extends Minz_Model {
return $this->feedId;
}
}
- public function tags($inString = false) {
- if ($inString) {
- return empty($this->tags) ? '' : '#' . implode(' #', $this->tags);
+ public function tags($asString = false) {
+ if ($asString) {
+ return $this->tags == null ? '' : '#' . implode(' #', $this->tags);
} else {
return $this->tags;
}
@@ -97,7 +104,7 @@ class FreshRSS_Entry extends Minz_Model {
public function hash() {
if ($this->hash === null) {
//Do not include $this->date because it may be automatically generated when lacking
- $this->hash = md5($this->link . $this->title . $this->author . $this->content . $this->tags(true));
+ $this->hash = md5($this->link . $this->title . $this->authors(true) . $this->content . $this->tags(true));
}
return $this->hash;
}
@@ -124,11 +131,22 @@ class FreshRSS_Entry extends Minz_Model {
}
public function _title($value) {
$this->hash = null;
- $this->title = mb_strcut($value, 0, 255, 'UTF-8');
+ $this->title = $value;
}
public function _author($value) {
+ //Deprecated
+ $this->_authors($value);
+ }
+ public function _authors($value) {
$this->hash = null;
- $this->author = mb_strcut($value, 0, 255, 'UTF-8');
+ if (!is_array($value)) {
+ if (strpos($value, ';') !== false) {
+ $value = preg_split('/\s*[;]\s*/', $value, -1, PREG_SPLIT_NO_EMPTY);
+ } else {
+ $value = preg_split('/\s*[,]\s*/', $value, -1, PREG_SPLIT_NO_EMPTY);
+ }
+ }
+ $this->authors = $value;
}
public function _content($value) {
$this->hash = null;
@@ -162,15 +180,8 @@ class FreshRSS_Entry extends Minz_Model {
public function _tags($value) {
$this->hash = null;
if (!is_array($value)) {
- $value = array($value);
- }
-
- foreach ($value as $key => $t) {
- if (!$t) {
- unset($value[$key]);
- }
+ $value = preg_split('/\s*[#,]\s*/', $value, -1, PREG_SPLIT_NO_EMPTY);
}
-
$this->tags = $value;
}
@@ -287,7 +298,7 @@ class FreshRSS_Entry extends Minz_Model {
'id' => $this->id(),
'guid' => $this->guid(),
'title' => $this->title(),
- 'author' => $this->author(),
+ 'author' => $this->authors(true),
'content' => $this->content(),
'link' => $this->link(),
'date' => $this->date(true),
diff --git a/app/Models/EntryDAO.php b/app/Models/EntryDAO.php
index f0e164995..a01c2227b 100644
--- a/app/Models/EntryDAO.php
+++ b/app/Models/EntryDAO.php
@@ -18,6 +18,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
return 'hex(' . $x . ')';
}
+ //TODO: Move the database auto-updates to DatabaseDAO
protected function addColumn($name) {
Minz_Log::warning('FreshRSS_EntryDAO::addColumn: ' . $name);
$hasTransaction = false;
@@ -56,6 +57,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
private $triedUpdateToUtf8mb4 = false;
+ //TODO: Move the database auto-updates to DatabaseDAO
protected function updateToUtf8mb4() {
if ($this->triedUpdateToUtf8mb4) {
return false;
@@ -65,7 +67,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
if ($db['type'] === 'mysql') {
include_once(APP_PATH . '/SQL/install.sql.mysql.php');
if (defined('SQL_UPDATE_UTF8MB4')) {
- Minz_Log::warning('Updating MySQL to UTF8MB4...');
+ Minz_Log::warning('Updating MySQL to UTF8MB4...'); //v1.5.0
$hadTransaction = $this->bd->inTransaction();
if ($hadTransaction) {
$this->bd->commit();
@@ -88,6 +90,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
return false;
}
+ //TODO: Move the database auto-updates to DatabaseDAO
protected function createEntryTempTable() {
$ok = false;
$hadTransaction = $this->bd->inTransaction();
@@ -120,22 +123,28 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
return $ok;
}
+ //TODO: Move the database auto-updates to DatabaseDAO
protected function autoUpdateDb($errorInfo) {
if (isset($errorInfo[0])) {
- if ($errorInfo[0] === '42S22') { //ER_BAD_FIELD_ERROR
+ if ($errorInfo[0] === FreshRSS_DatabaseDAO::ER_BAD_FIELD_ERROR) {
//autoAddColumn
foreach (array('lastSeen', 'hash') as $column) {
if (stripos($errorInfo[2], $column) !== false) {
return $this->addColumn($column);
}
}
- } elseif ($errorInfo[0] === '42S02' && stripos($errorInfo[2], 'entrytmp') !== false) { //ER_BAD_TABLE_ERROR
- return $this->createEntryTempTable(); //v1.7
+ } elseif ($errorInfo[0] === FreshRSS_DatabaseDAO::ER_BAD_TABLE_ERROR) {
+ if (stripos($errorInfo[2], 'tag') !== false) {
+ $tagDAO = FreshRSS_Factory::createTagDao();
+ return $tagDAO->createTagTable(); //v1.12.0
+ } elseif (stripos($errorInfo[2], 'entrytmp') !== false) {
+ return $this->createEntryTempTable(); //v1.7.0
+ }
}
}
if (isset($errorInfo[1])) {
- if ($errorInfo[1] == '1366') { //ER_TRUNCATED_WRONG_VALUE_FOR_FIELD
- return $this->updateToUtf8mb4();
+ if ($errorInfo[1] == FreshRSS_DatabaseDAO::ER_TRUNCATED_WRONG_VALUE_FOR_FIELD) {
+ return $this->updateToUtf8mb4(); //v1.5.0
}
}
return false;
@@ -560,11 +569,52 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
return $affected;
}
+ /**
+ * Mark all the articles in a tag as read.
+ * @param integer $id tag ID, or empty for targetting any tag
+ * @param integer $idMax max article ID
+ * @return integer affected rows
+ */
+ public function markReadTag($id = '', $idMax = 0, $filters = null, $state = 0, $is_read = true) {
+ FreshRSS_UserDAO::touch();
+ if ($idMax == 0) {
+ $idMax = time() . '000000';
+ Minz_Log::debug('Calling markReadTag(0) is deprecated!');
+ }
+
+ $sql = 'UPDATE `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'entrytag` et ON et.id_entry = e.id '
+ . 'SET e.is_read = ? '
+ . 'WHERE '
+ . ($id == '' ? '' : 'et.id_tag = ? AND ')
+ . 'e.is_read <> ? AND e.id <= ?';
+ $values = array($is_read ? 1 : 0);
+ if ($id != '') {
+ $values[] = $id;
+ }
+ $values[] = $is_read ? 1 : 0;
+ $values[] = $idMax;
+
+ list($searchValues, $search) = $this->sqlListEntriesWhere('e.', $filters, $state);
+
+ $stm = $this->bd->prepare($sql . $search);
+ if (!($stm && $stm->execute(array_merge($values, $searchValues)))) {
+ $info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo();
+ Minz_Log::error('SQL error markReadTag: ' . $info[2]);
+ return false;
+ }
+ $affected = $stm->rowCount();
+ if (($affected > 0) && (!$this->updateCacheUnreads(false, false))) {
+ return false;
+ }
+ return $affected;
+ }
+
public function cleanOldEntries($id_feed, $date_min, $keep = 15) { //Remember to call updateCachedValue($id_feed) or updateCachedValues() just after
$sql = 'DELETE FROM `' . $this->prefix . 'entry` '
. 'WHERE id_feed=:id_feed AND id<=:id_max '
. 'AND is_favorite=0 ' //Do not remove favourites
. 'AND `lastSeen` < (SELECT maxLastSeen FROM (SELECT (MAX(e3.`lastSeen`)-99) AS maxLastSeen FROM `' . $this->prefix . 'entry` e3 WHERE e3.id_feed=:id_feed) recent) ' //Do not remove the most newly seen articles, plus a few seconds of tolerance
+ . 'AND id NOT IN (SELECT id_entry FROM `' . $this->prefix . 'entrytag`) ' //Do not purge tagged entries
. 'AND id NOT IN (SELECT id FROM (SELECT e2.id FROM `' . $this->prefix . 'entry` e2 WHERE e2.id_feed=:id_feed ORDER BY id DESC LIMIT :keep) keep)'; //Double select: MySQL doesn't support 'LIMIT & IN/ALL/ANY/SOME subquery'
$stm = $this->bd->prepare($sql);
@@ -770,24 +820,31 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
$joinFeed = false;
$values = array();
switch ($type) {
- case 'a':
+ case 'a': //All PRIORITY_MAIN_STREAM
$where .= 'f.priority > ' . FreshRSS_Feed::PRIORITY_NORMAL . ' ';
break;
- case 's': //Deprecated: use $state instead
+ case 'A': //All except PRIORITY_ARCHIVED
+ $where .= 'f.priority >= ' . FreshRSS_Feed::PRIORITY_NORMAL . ' ';
+ break;
+ case 's': //Starred. Deprecated: use $state instead
$where .= 'f.priority >= ' . FreshRSS_Feed::PRIORITY_NORMAL . ' ';
$where .= 'AND e.is_favorite=1 ';
break;
- case 'c':
+ case 'c': //Category
$where .= 'f.priority >= ' . FreshRSS_Feed::PRIORITY_NORMAL . ' ';
$where .= 'AND f.category=? ';
$values[] = intval($id);
break;
- case 'f':
+ case 'f': //Feed
$where .= 'e.id_feed=? ';
$values[] = intval($id);
break;
- case 'A':
- $where .= 'f.priority >= ' . FreshRSS_Feed::PRIORITY_NORMAL . ' ';
+ case 't': //Tag
+ $where .= 'et.id_tag=? ';
+ $values[] = intval($id);
+ break;
+ case 'T': //Any tag
+ $where .= '1=1 ';
break;
default:
throw new FreshRSS_EntriesGetter_Exception('Bad type in Entry->listByType: [' . $type . ']!');
@@ -796,8 +853,11 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
list($searchValues, $search) = $this->sqlListEntriesWhere('e.', $filters, $state, $order, $firstId, $date_min);
return array(array_merge($values, $searchValues),
- 'SELECT e.id FROM `' . $this->prefix . 'entry` e '
+ 'SELECT '
+ . ($type === 'T' ? 'DISTINCT ' : '')
+ . 'e.id FROM `' . $this->prefix . 'entry` e '
. 'INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id '
+ . ($type === 't' || $type === 'T' ? 'INNER JOIN `' . $this->prefix . 'entrytag` et ON et.id_entry = e.id ' : '')
. 'WHERE ' . $where
. $search
. 'ORDER BY e.id ' . $order
@@ -817,13 +877,22 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
. 'ORDER BY e0.id ' . $order;
$stm = $this->bd->prepare($sql);
- $stm->execute($values);
- return $stm;
+ if ($stm && $stm->execute($values)) {
+ return $stm;
+ } else {
+ $info = $stm == null ? array(0 => '', 1 => '', 2 => 'syntax error') : $stm->errorInfo();
+ Minz_Log::error('SQL error listWhereRaw: ' . $info[2]);
+ return false;
+ }
}
public function listWhere($type = 'a', $id = '', $state = FreshRSS_Entry::STATE_ALL, $order = 'DESC', $limit = 1, $firstId = '', $filters = null, $date_min = 0) {
$stm = $this->listWhereRaw($type, $id, $state, $order, $limit, $firstId, $filters, $date_min);
- return self::daoToEntries($stm->fetchAll(PDO::FETCH_ASSOC));
+ if ($stm) {
+ return self::daoToEntries($stm->fetchAll(PDO::FETCH_ASSOC));
+ } else {
+ return false;
+ }
}
public function listByIds($ids, $order = 'DESC') {
@@ -923,7 +992,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
$stm = $this->bd->prepare($sql);
$stm->execute();
$res = $stm->fetchAll(PDO::FETCH_COLUMN, 0);
- return $res[0];
+ return isset($res[0]) ? $res[0] : 0;
}
public function countNotRead($minPriority = null) {
$sql = 'SELECT COUNT(e.id) AS count FROM `' . $this->prefix . 'entry` e';
diff --git a/app/Models/EntryDAOPGSQL.php b/app/Models/EntryDAOPGSQL.php
index f09fe8e75..aef258b6f 100644
--- a/app/Models/EntryDAOPGSQL.php
+++ b/app/Models/EntryDAOPGSQL.php
@@ -12,8 +12,13 @@ class FreshRSS_EntryDAOPGSQL extends FreshRSS_EntryDAOSQLite {
protected function autoUpdateDb($errorInfo) {
if (isset($errorInfo[0])) {
- if ($errorInfo[0] === '42P01' && stripos($errorInfo[2], 'entrytmp') !== false) { //undefined_table
- return $this->createEntryTempTable();
+ if ($errorInfo[0] === FreshRSS_DatabaseDAOPGSQL::UNDEFINED_TABLE) {
+ if (stripos($errorInfo[2], 'tag') !== false) {
+ $tagDAO = FreshRSS_Factory::createTagDao();
+ return $tagDAO->createTagTable(); //v1.12.0
+ } elseif (stripos($errorInfo[2], 'entrytmp') !== false) {
+ return $this->createEntryTempTable(); //v1.7.0
+ }
}
}
return false;
diff --git a/app/Models/EntryDAOSQLite.php b/app/Models/EntryDAOSQLite.php
index 944de8470..f8cd14fe6 100644
--- a/app/Models/EntryDAOSQLite.php
+++ b/app/Models/EntryDAOSQLite.php
@@ -7,10 +7,17 @@ class FreshRSS_EntryDAOSQLite extends FreshRSS_EntryDAO {
}
protected function autoUpdateDb($errorInfo) {
+ if ($tableInfo = $this->bd->query("SELECT sql FROM sqlite_master where name='tag'")) {
+ $showCreate = $tableInfo->fetchColumn();
+ if (stripos($showCreate, 'tag') === false) {
+ $tagDAO = FreshRSS_Factory::createTagDao();
+ return $tagDAO->createTagTable(); //v1.12.0
+ }
+ }
if ($tableInfo = $this->bd->query("SELECT sql FROM sqlite_master where name='entrytmp'")) {
$showCreate = $tableInfo->fetchColumn();
if (stripos($showCreate, 'entrytmp') === false) {
- return $this->createEntryTempTable();
+ return $this->createEntryTempTable(); //v1.7.0
}
}
if ($tableInfo = $this->bd->query("SELECT sql FROM sqlite_master where name='entry'")) {
@@ -228,4 +235,43 @@ DROP TABLE IF EXISTS `tmp`;
}
return $affected;
}
+
+ /**
+ * Mark all the articles in a tag as read.
+ * @param integer $id tag ID, or empty for targetting any tag
+ * @param integer $idMax max article ID
+ * @return integer affected rows
+ */
+ public function markReadTag($id = '', $idMax = 0, $filters = null, $state = 0, $is_read = true) {
+ FreshRSS_UserDAO::touch();
+ if ($idMax == 0) {
+ $idMax = time() . '000000';
+ Minz_Log::debug('Calling markReadTag(0) is deprecated!');
+ }
+
+ $sql = 'UPDATE `' . $this->prefix . 'entry` e '
+ . 'SET e.is_read = ? '
+ . 'WHERE e.is_read <> ? AND e.id <= ? AND '
+ . 'e.id IN (SELECT et.id_entry FROM `' . $this->prefix . 'entrytag` et '
+ . ($id == '' ? '' : 'WHERE et.id = ?')
+ . ')';
+ $values = array($is_read ? 1 : 0, $is_read ? 1 : 0, $idMax);
+ if ($id != '') {
+ $values[] = $id;
+ }
+
+ list($searchValues, $search) = $this->sqlListEntriesWhere('e.', $filters, $state);
+
+ $stm = $this->bd->prepare($sql . $search);
+ if (!($stm && $stm->execute(array_merge($values, $searchValues)))) {
+ $info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo();
+ Minz_Log::error('SQL error markReadTag: ' . $info[2]);
+ return false;
+ }
+ $affected = $stm->rowCount();
+ if (($affected > 0) && (!$this->updateCacheUnreads(false, false))) {
+ return false;
+ }
+ return $affected;
+ }
}
diff --git a/app/Models/Factory.php b/app/Models/Factory.php
index 764987c46..1accb491c 100644
--- a/app/Models/Factory.php
+++ b/app/Models/Factory.php
@@ -2,6 +2,10 @@
class FreshRSS_Factory {
+ public static function createCategoryDao($username = null) {
+ return new FreshRSS_CategoryDAO($username);
+ }
+
public static function createFeedDao($username = null) {
$conf = Minz_Configuration::get('system');
switch ($conf->db['type']) {
@@ -24,6 +28,18 @@ class FreshRSS_Factory {
}
}
+ public static function createTagDao($username = null) {
+ $conf = Minz_Configuration::get('system');
+ switch ($conf->db['type']) {
+ case 'sqlite':
+ return new FreshRSS_TagDAOSQLite($username);
+ case 'pgsql':
+ return new FreshRSS_TagDAOPGSQL($username);
+ default:
+ return new FreshRSS_TagDAO($username);
+ }
+ }
+
public static function createStatsDAO($username = null) {
$conf = Minz_Configuration::get('system');
switch ($conf->db['type']) {
diff --git a/app/Models/Feed.php b/app/Models/Feed.php
index ed381a867..e1dd2990d 100644
--- a/app/Models/Feed.php
+++ b/app/Models/Feed.php
@@ -286,6 +286,10 @@ class FreshRSS_Feed extends Minz_Model {
if (!$loadDetails) { //Only activates auto-discovery when adding a new feed
$feed->set_autodiscovery_level(SIMPLEPIE_LOCATOR_NONE);
}
+ if ($this->attributes('clear_cache')) {
+ // Do not use `$simplePie->enable_cache(false);` as it would prevent caching in multiuser context
+ $this->clearCache();
+ }
Minz_ExtensionManager::callHook('simplepie_before_init', $feed, $this);
$mtime = $feed->init();
@@ -345,13 +349,21 @@ class FreshRSS_Feed extends Minz_Model {
$link = $item->get_permalink();
$date = @strtotime($item->get_date());
- // gestion des tags (catégorie == tag)
- $tags_tmp = $item->get_categories();
+ //Tag processing (tag == category)
+ $categories = $item->get_categories();
$tags = array();
- if ($tags_tmp !== null) {
- foreach ($tags_tmp as $tag) {
- $tags[] = html_only_entity_decode($tag->get_label());
+ if (is_array($categories)) {
+ foreach ($categories as $category) {
+ $text = html_only_entity_decode($category->get_label());
+ //Some feeds use a single category with comma-separated tags
+ $labels = explode(',', $text);
+ if (is_array($labels)) {
+ foreach ($labels as $label) {
+ $tags[] = trim($label);
+ }
+ }
}
+ $tags = array_unique($tags);
}
$content = html_only_entity_decode($item->get_content());
@@ -412,7 +424,7 @@ class FreshRSS_Feed extends Minz_Model {
$author_names = '';
if (is_array($authors)) {
foreach ($authors as $author) {
- $author_names .= html_only_entity_decode(strip_tags($author->name == '' ? $author->email : $author->name)) . ', ';
+ $author_names .= html_only_entity_decode(strip_tags($author->name == '' ? $author->email : $author->name)) . '; ';
}
}
$author_names = substr($author_names, 0, -2);
@@ -457,8 +469,16 @@ class FreshRSS_Feed extends Minz_Model {
$this->entries = $entries;
}
+ protected function cacheFilename() {
+ return CACHE_PATH . '/' . md5($this->url) . '.spc';
+ }
+
+ public function clearCache() {
+ return @unlink($this->cacheFilename());
+ }
+
public function cacheModifiedTime() {
- return @filemtime(CACHE_PATH . '/' . md5($this->url) . '.spc');
+ return @filemtime($this->cacheFilename());
}
public function lock() {
diff --git a/app/Models/FeedDAO.php b/app/Models/FeedDAO.php
index 285f17193..e579f5881 100644
--- a/app/Models/FeedDAO.php
+++ b/app/Models/FeedDAO.php
@@ -17,7 +17,7 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
protected function autoUpdateDb($errorInfo) {
if (isset($errorInfo[0])) {
- if ($errorInfo[0] === '42S22' || $errorInfo[0] === '42703') { //ER_BAD_FIELD_ERROR (Mysql), undefined_column (PostgreSQL)
+ if ($errorInfo[0] === FreshRSS_DatabaseDAO::ER_BAD_FIELD_ERROR || $errorInfo[0] === FreshRSS_DatabaseDAOPGSQL::UNDEFINED_COLUMN) {
foreach (array('attributes') as $column) {
if (stripos($errorInfo[2], $column) !== false) {
return $this->addColumn($column);
@@ -55,7 +55,7 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
$values = array(
substr($valuesTmp['url'], 0, 511),
$valuesTmp['category'],
- mb_strcut($valuesTmp['name'], 0, 255, 'UTF-8'),
+ mb_strcut(trim($valuesTmp['name']), 0, FreshRSS_DatabaseDAO::LENGTH_INDEX_UNICODE, 'UTF-8'),
substr($valuesTmp['website'], 0, 255),
mb_strcut($valuesTmp['description'], 0, 1023, 'UTF-8'),
$valuesTmp['lastUpdate'],
@@ -109,6 +109,9 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
}
public function updateFeed($id, $valuesTmp) {
+ if (isset($valuesTmp['name'])) {
+ $valuesTmp['name'] = mb_strcut(trim($valuesTmp['name']), 0, FreshRSS_DatabaseDAO::LENGTH_INDEX_UNICODE, 'UTF-8');
+ }
if (isset($valuesTmp['url'])) {
$valuesTmp['url'] = safe_ascii($valuesTmp['url']);
}
@@ -180,7 +183,7 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
}
public function changeCategory($idOldCat, $idNewCat) {
- $catDAO = new FreshRSS_CategoryDAO();
+ $catDAO = FreshRSS_Factory::createCategoryDao();
$newCat = $catDAO->searchById($idNewCat);
if (!$newCat) {
$newCat = $catDAO->getDefault();
diff --git a/app/Models/Search.php b/app/Models/Search.php
index 5cc7f8e8d..c52e391fa 100644
--- a/app/Models/Search.php
+++ b/app/Models/Search.php
@@ -40,7 +40,7 @@ class FreshRSS_Search {
$input = $this->parseNotIntitleSearch($input);
$input = $this->parseNotAuthorSearch($input);
$input = $this->parseNotInurlSearch($input);
- $input = $this->parseNotTagsSeach($input);
+ $input = $this->parseNotTagsSearch($input);
$input = $this->parsePubdateSearch($input);
$input = $this->parseDateSearch($input);
@@ -48,7 +48,7 @@ class FreshRSS_Search {
$input = $this->parseIntitleSearch($input);
$input = $this->parseAuthorSearch($input);
$input = $this->parseInurlSearch($input);
- $input = $this->parseTagsSeach($input);
+ $input = $this->parseTagsSearch($input);
$input = $this->parseNotSearch($input);
$input = $this->parseSearch($input);
@@ -117,6 +117,17 @@ class FreshRSS_Search {
return is_array($anArray) ? array_filter($anArray, function($value) { return $value !== ''; }) : array();
}
+ private static function decodeSpaces($value) {
+ if (is_array($value)) {
+ for ($i = count($value) - 1; $i >= 0; $i--) {
+ $value[$i] = self::decodeSpaces($value[$i]);
+ }
+ } else {
+ $value = trim(str_replace('+', ' ', $value));
+ }
+ return $value;
+ }
+
/**
* Parse the search string to find intitle keyword and the search related
* to it.
@@ -130,11 +141,12 @@ class FreshRSS_Search {
$this->intitle = $matches['search'];
$input = str_replace($matches[0], '', $input);
}
- if (preg_match_all('/\bintitle:(?P<search>\w*)/', $input, $matches)) {
+ if (preg_match_all('/\bintitle:(?P<search>[^\s"]*)/', $input, $matches)) {
$this->intitle = array_merge($this->intitle ? $this->intitle : array(), $matches['search']);
$input = str_replace($matches[0], '', $input);
}
$this->intitle = self::removeEmptyValues($this->intitle);
+ $this->intitle = self::decodeSpaces($this->intitle);
return $input;
}
@@ -143,11 +155,12 @@ class FreshRSS_Search {
$this->not_intitle = $matches['search'];
$input = str_replace($matches[0], '', $input);
}
- if (preg_match_all('/[!-]intitle:(?P<search>\w*)/', $input, $matches)) {
+ if (preg_match_all('/[!-]intitle:(?P<search>[^\s"]*)/', $input, $matches)) {
$this->not_intitle = array_merge($this->not_intitle ? $this->not_intitle : array(), $matches['search']);
$input = str_replace($matches[0], '', $input);
}
$this->not_intitle = self::removeEmptyValues($this->not_intitle);
+ $this->not_intitle = self::decodeSpaces($this->not_intitle);
return $input;
}
@@ -166,11 +179,12 @@ class FreshRSS_Search {
$this->author = $matches['search'];
$input = str_replace($matches[0], '', $input);
}
- if (preg_match_all('/\bauthor:(?P<search>\w*)/', $input, $matches)) {
+ if (preg_match_all('/\bauthor:(?P<search>[^\s"]*)/', $input, $matches)) {
$this->author = array_merge($this->author ? $this->author : array(), $matches['search']);
$input = str_replace($matches[0], '', $input);
}
$this->author = self::removeEmptyValues($this->author);
+ $this->author = self::decodeSpaces($this->author);
return $input;
}
@@ -179,11 +193,12 @@ class FreshRSS_Search {
$this->not_author = $matches['search'];
$input = str_replace($matches[0], '', $input);
}
- if (preg_match_all('/[!-]author:(?P<search>\w*)/', $input, $matches)) {
+ if (preg_match_all('/[!-]author:(?P<search>[^\s"]*)/', $input, $matches)) {
$this->not_author = array_merge($this->not_author ? $this->not_author : array(), $matches['search']);
$input = str_replace($matches[0], '', $input);
}
$this->not_author = self::removeEmptyValues($this->not_author);
+ $this->not_author = self::decodeSpaces($this->not_author);
return $input;
}
@@ -201,6 +216,7 @@ class FreshRSS_Search {
$input = str_replace($matches[0], '', $input);
}
$this->inurl = self::removeEmptyValues($this->inurl);
+ $this->inurl = self::decodeSpaces($this->inurl);
return $input;
}
@@ -210,6 +226,7 @@ class FreshRSS_Search {
$input = str_replace($matches[0], '', $input);
}
$this->not_inurl = self::removeEmptyValues($this->not_inurl);
+ $this->not_inurl = self::decodeSpaces($this->not_inurl);
return $input;
}
@@ -259,21 +276,23 @@ class FreshRSS_Search {
* @param string $input
* @return string
*/
- private function parseTagsSeach($input) {
+ private function parseTagsSearch($input) {
if (preg_match_all('/#(?P<search>[^\s]+)/', $input, $matches)) {
$this->tags = $matches['search'];
$input = str_replace($matches[0], '', $input);
}
$this->tags = self::removeEmptyValues($this->tags);
+ $this->tags = self::decodeSpaces($this->tags);
return $input;
}
- private function parseNotTagsSeach($input) {
+ private function parseNotTagsSearch($input) {
if (preg_match_all('/[!-]#(?P<search>[^\s]+)/', $input, $matches)) {
$this->not_tags = $matches['search'];
$input = str_replace($matches[0], '', $input);
}
$this->not_tags = self::removeEmptyValues($this->not_tags);
+ $this->not_tags = self::decodeSpaces($this->not_tags);
return $input;
}
@@ -303,6 +322,7 @@ class FreshRSS_Search {
} else {
$this->search = explode(' ', $input);
}
+ $this->search = self::decodeSpaces($this->search);
}
private function parseNotSearch($input) {
@@ -322,6 +342,7 @@ class FreshRSS_Search {
$input = str_replace($matches[0], '', $input);
}
$this->not_search = self::removeEmptyValues($this->not_search);
+ $this->not_search = self::decodeSpaces($this->not_search);
return $input;
}
diff --git a/app/Models/Tag.php b/app/Models/Tag.php
new file mode 100644
index 000000000..3eb989cc1
--- /dev/null
+++ b/app/Models/Tag.php
@@ -0,0 +1,76 @@
+<?php
+
+class FreshRSS_Tag extends Minz_Model {
+ private $id = 0;
+ private $name;
+ private $attributes = array();
+ private $nbEntries = -1;
+ private $nbUnread = -1;
+
+ public function __construct($name = '') {
+ $this->_name($name);
+ }
+
+ public function id() {
+ return $this->id;
+ }
+
+ public function _id($value) {
+ $this->id = (int)$value;
+ }
+
+ public function name() {
+ return $this->name;
+ }
+
+ public function _name($value) {
+ $this->name = trim($value);
+ }
+
+ public function attributes($key = '') {
+ if ($key == '') {
+ return $this->attributes;
+ } else {
+ return isset($this->attributes[$key]) ? $this->attributes[$key] : null;
+ }
+ }
+
+ public function _attributes($key, $value) {
+ if ($key == '') {
+ if (is_string($value)) {
+ $value = json_decode($value, true);
+ }
+ if (is_array($value)) {
+ $this->attributes = $value;
+ }
+ } elseif ($value === null) {
+ unset($this->attributes[$key]);
+ } else {
+ $this->attributes[$key] = $value;
+ }
+ }
+
+ public function nbEntries() {
+ if ($this->nbEntries < 0) {
+ $tagDAO = FreshRSS_Factory::createTagDao();
+ $this->nbEntries = $tagDAO->countEntries($this->id());
+ }
+ return $this->nbFeed;
+ }
+
+ public function _nbEntries($value) {
+ $this->nbEntries = (int)$value;
+ }
+
+ public function nbUnread() {
+ if ($this->nbUnread < 0) {
+ $tagDAO = FreshRSS_Factory::createTagDao();
+ $this->nbUnread = $tagDAO->countNotRead($this->id());
+ }
+ return $this->nbUnread;
+ }
+
+ public function _nbUnread($value) {
+ $this->nbUnread = (int)$value;
+ }
+}
diff --git a/app/Models/TagDAO.php b/app/Models/TagDAO.php
new file mode 100644
index 000000000..1b59c8971
--- /dev/null
+++ b/app/Models/TagDAO.php
@@ -0,0 +1,315 @@
+<?php
+
+class FreshRSS_TagDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
+
+ public function sqlIgnore() {
+ return 'IGNORE';
+ }
+
+ public function createTagTable() {
+ $ok = false;
+ $hadTransaction = $this->bd->inTransaction();
+ if ($hadTransaction) {
+ $this->bd->commit();
+ }
+ try {
+ $db = FreshRSS_Context::$system_conf->db;
+ require_once(APP_PATH . '/SQL/install.sql.' . $db['type'] . '.php');
+
+ Minz_Log::warning('SQL ALTER GUID case sensitivity...');
+ $databaseDAO = FreshRSS_Factory::createDatabaseDAO();
+ $databaseDAO->ensureCaseInsensitiveGuids();
+
+ Minz_Log::warning('SQL CREATE TABLE tag...');
+ if (defined('SQL_CREATE_TABLE_TAGS')) {
+ $sql = sprintf(SQL_CREATE_TABLE_TAGS, $this->prefix);
+ $stm = $this->bd->prepare($sql);
+ $ok = $stm && $stm->execute();
+ } else {
+ global $SQL_CREATE_TABLE_TAGS;
+ $ok = !empty($SQL_CREATE_TABLE_TAGS);
+ foreach ($SQL_CREATE_TABLE_TAGS as $instruction) {
+ $sql = sprintf($instruction, $this->prefix);
+ $stm = $this->bd->prepare($sql);
+ $ok &= $stm && $stm->execute();
+ }
+ }
+ } catch (Exception $e) {
+ Minz_Log::error('FreshRSS_EntryDAO::createTagTable error: ' . $e->getMessage());
+ }
+ if ($hadTransaction) {
+ $this->bd->beginTransaction();
+ }
+ return $ok;
+ }
+
+ protected function autoUpdateDb($errorInfo) {
+ if (isset($errorInfo[0])) {
+ if ($errorInfo[0] === FreshRSS_DatabaseDAO::ER_BAD_TABLE_ERROR || $errorInfo[0] === FreshRSS_DatabaseDAOPGSQL::UNDEFINED_TABLE) {
+ if (stripos($errorInfo[2], 'tag') !== false) {
+ return $this->createTagTable(); //v1.12.0
+ }
+ }
+ }
+ return false;
+ }
+
+ public function addTag($valuesTmp) {
+ $sql = 'INSERT INTO `' . $this->prefix . 'tag`(name, attributes) '
+ . 'SELECT * FROM (SELECT TRIM(?), TRIM(?)) t2 ' //TRIM() to provide a type hint as text for PostgreSQL
+ . 'WHERE NOT EXISTS (SELECT 1 FROM `' . $this->prefix . 'category` WHERE name = TRIM(?))'; //No category of the same name
+ $stm = $this->bd->prepare($sql);
+
+ $valuesTmp['name'] = mb_strcut(trim($valuesTmp['name']), 0, 63, 'UTF-8');
+ $values = array(
+ $valuesTmp['name'],
+ isset($valuesTmp['attributes']) ? json_encode($valuesTmp['attributes']) : '',
+ $valuesTmp['name'],
+ );
+
+ if ($stm && $stm->execute($values)) {
+ return $this->bd->lastInsertId('"' . $this->prefix . 'tag_id_seq"');
+ } else {
+ $info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo();
+ Minz_Log::error('SQL error addTag: ' . $info[2]);
+ return false;
+ }
+ }
+
+ public function addTagObject($tag) {
+ $tag = $this->searchByName($tag->name());
+ if (!$tag) {
+ $values = array(
+ 'name' => $tag->name(),
+ 'attributes' => $tag->attributes(),
+ );
+ return $this->addTag($values);
+ }
+ return $tag->id();
+ }
+
+ public function updateTag($id, $valuesTmp) {
+ $sql = 'UPDATE `' . $this->prefix . 'tag` SET name=?, attributes=? WHERE id=? '
+ . 'AND NOT EXISTS (SELECT 1 FROM `' . $this->prefix . 'category` WHERE name = ?)'; //No category of the same name
+ $stm = $this->bd->prepare($sql);
+
+ $valuesTmp['name'] = mb_strcut(trim($valuesTmp['name']), 0, 63, 'UTF-8');
+ $values = array(
+ $valuesTmp['name'],
+ isset($valuesTmp['attributes']) ? json_encode($valuesTmp['attributes']) : '',
+ $id,
+ $valuesTmp['name'],
+ );
+
+ if ($stm && $stm->execute($values)) {
+ return $stm->rowCount();
+ } else {
+ $info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo();
+ Minz_Log::error('SQL error updateTag: ' . $info[2]);
+ return false;
+ }
+ }
+
+ public function updateTagAttribute($tag, $key, $value) {
+ if ($tag instanceof FreshRSS_Tag) {
+ $tag->_attributes($key, $value);
+ return $this->updateFeed(
+ $tag->id(),
+ array('attributes' => $feed->attributes())
+ );
+ }
+ return false;
+ }
+
+ public function deleteTag($id) {
+ if ($id <= 0) {
+ return false;
+ }
+ $sql = 'DELETE FROM `' . $this->prefix . 'tag` WHERE id=?';
+ $stm = $this->bd->prepare($sql);
+
+ $values = array($id);
+
+ if ($stm && $stm->execute($values)) {
+ return $stm->rowCount();
+ } else {
+ $info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo();
+ Minz_Log::error('SQL error deleteTag: ' . $info[2]);
+ return false;
+ }
+ }
+
+ public function searchById($id) {
+ $sql = 'SELECT * FROM `' . $this->prefix . 'tag` WHERE id=?';
+ $stm = $this->bd->prepare($sql);
+ $values = array($id);
+ $stm->execute($values);
+ $res = $stm->fetchAll(PDO::FETCH_ASSOC);
+ $tag = self::daoToTag($res);
+ return isset($tag[0]) ? $tag[0] : null;
+ }
+
+ public function searchByName($name) {
+ $sql = 'SELECT * FROM `' . $this->prefix . 'tag` WHERE name=?';
+ $stm = $this->bd->prepare($sql);
+ $values = array($name);
+ $stm->execute($values);
+ $res = $stm->fetchAll(PDO::FETCH_ASSOC);
+ $tag = self::daoToTag($res);
+ return isset($tag[0]) ? $tag[0] : null;
+ }
+
+ public function listTags($precounts = false) {
+ if ($precounts) {
+ $sql = 'SELECT t.id, t.name, count(e.id) AS unreads '
+ . 'FROM `' . $this->prefix . 'tag` t '
+ . 'LEFT OUTER JOIN `' . $this->prefix . 'entrytag` et ON et.id_tag = t.id '
+ . 'LEFT OUTER JOIN `' . $this->prefix . 'entry` e ON et.id_entry = e.id AND e.is_read = 0 '
+ . 'GROUP BY t.id '
+ . 'ORDER BY t.name';
+ } else {
+ $sql = 'SELECT * FROM `' . $this->prefix . 'tag` ORDER BY name';
+ }
+
+ $stm = $this->bd->prepare($sql);
+ if ($stm && $stm->execute()) {
+ return self::daoToTag($stm->fetchAll(PDO::FETCH_ASSOC));
+ } else {
+ $info = $stm == null ? array(0 => '', 1 => '', 2 => 'syntax error') : $stm->errorInfo();
+ if ($this->autoUpdateDb($info)) {
+ return $this->listTags($precounts);
+ }
+ Minz_Log::error('SQL error listTags: ' . $info[2]);
+ return false;
+ }
+ }
+
+ public function count() {
+ $sql = 'SELECT COUNT(*) AS count FROM `' . $this->prefix . 'tag`';
+ $stm = $this->bd->prepare($sql);
+ $stm->execute();
+ $res = $stm->fetchAll(PDO::FETCH_ASSOC);
+ return $res[0]['count'];
+ }
+
+ public function countEntries($id) {
+ $sql = 'SELECT COUNT(*) AS count FROM `' . $this->prefix . 'entrytag` WHERE id_tag=?';
+ $stm = $this->bd->prepare($sql);
+ $values = array($id);
+ $stm->execute($values);
+ $res = $stm->fetchAll(PDO::FETCH_ASSOC);
+ return $res[0]['count'];
+ }
+
+ public function countNotRead($id) {
+ $sql = 'SELECT COUNT(*) AS count FROM `' . $this->prefix . 'entrytag` et '
+ . 'INNER JOIN `' . $this->prefix . 'entry` e ON et.id_entry=e.id '
+ . 'WHERE et.id_tag=? AND e.is_read=0';
+ $stm = $this->bd->prepare($sql);
+ $values = array($id);
+ $stm->execute($values);
+ $res = $stm->fetchAll(PDO::FETCH_ASSOC);
+ return $res[0]['count'];
+ }
+
+ public function tagEntry($id_tag, $id_entry, $checked = true) {
+ if ($checked) {
+ $sql = 'INSERT ' . $this->sqlIgnore() . ' INTO `' . $this->prefix . 'entrytag`(id_tag, id_entry) VALUES(?, ?)';
+ } else {
+ $sql = 'DELETE FROM `' . $this->prefix . 'entrytag` WHERE id_tag=? AND id_entry=?';
+ }
+ $stm = $this->bd->prepare($sql);
+ $values = array($id_tag, $id_entry);
+
+ if ($stm && $stm->execute($values)) {
+ return true;
+ } else {
+ $info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo();
+ Minz_Log::error('SQL error tagEntry: ' . $info[2]);
+ return false;
+ }
+ }
+
+ public function getTagsForEntry($id_entry) {
+ $sql = 'SELECT t.id, t.name, et.id_entry IS NOT NULL as checked '
+ . 'FROM `' . $this->prefix . 'tag` t '
+ . 'LEFT OUTER JOIN `' . $this->prefix . 'entrytag` et ON et.id_tag = t.id AND et.id_entry=? '
+ . 'ORDER BY t.name';
+
+ $stm = $this->bd->prepare($sql);
+ $values = array($id_entry);
+
+ if ($stm && $stm->execute($values)) {
+ $lines = $stm->fetchAll(PDO::FETCH_ASSOC);
+ for ($i = count($lines) - 1; $i >= 0; $i--) {
+ $lines[$i]['id'] = intval($lines[$i]['id']);
+ $lines[$i]['checked'] = !empty($lines[$i]['checked']);
+ }
+ return $lines;
+ } else {
+ $info = $stm == null ? array(0 => '', 1 => '', 2 => 'syntax error') : $stm->errorInfo();
+ if ($this->autoUpdateDb($info)) {
+ return $this->getTagsForEntry($id_entry);
+ }
+ Minz_Log::error('SQL error getTagsForEntry: ' . $info[2]);
+ return false;
+ }
+ }
+
+ //For API
+ public function getEntryIdsTagNames($entries) {
+ $sql = 'SELECT et.id_entry, t.name '
+ . 'FROM `' . $this->prefix . 'tag` t '
+ . 'INNER JOIN `' . $this->prefix . 'entrytag` et ON et.id_tag = t.id';
+
+ $values = array();
+ if (is_array($entries) && count($entries) > 0) {
+ $sql .= ' AND et.id_entry IN (' . str_repeat('?,', count($entries) - 1). '?)';
+ foreach ($entries as $entry) {
+ $values[] = $entry->id();
+ }
+ }
+ $stm = $this->bd->prepare($sql);
+
+ if ($stm && $stm->execute($values)) {
+ $result = array();
+ foreach ($stm->fetchAll(PDO::FETCH_ASSOC) as $line) {
+ $entryId = 'e_' . $line['id_entry'];
+ $tagName = $line['name'];
+ if (empty($result[$entryId])) {
+ $result[$entryId] = array();
+ }
+ $result[$entryId][] = $tagName;
+ }
+ return $result;
+ } else {
+ $info = $stm == null ? array(0 => '', 1 => '', 2 => 'syntax error') : $stm->errorInfo();
+ if ($this->autoUpdateDb($info)) {
+ return $this->getTagNamesEntryIds($id_entry);
+ }
+ Minz_Log::error('SQL error getTagNamesEntryIds: ' . $info[2]);
+ return false;
+ }
+ }
+
+ public static function daoToTag($listDAO) {
+ $list = array();
+ if (!is_array($listDAO)) {
+ $listDAO = array($listDAO);
+ }
+ foreach ($listDAO as $key => $dao) {
+ $tag = new FreshRSS_Tag(
+ $dao['name']
+ );
+ $tag->_id($dao['id']);
+ if (!empty($dao['attributes'])) {
+ $tag->_attributes('', $dao['attributes']);
+ }
+ if (isset($dao['unreads'])) {
+ $tag->_nbUnread($dao['unreads']);
+ }
+ $list[$key] = $tag;
+ }
+ return $list;
+ }
+}
diff --git a/app/Models/TagDAOPGSQL.php b/app/Models/TagDAOPGSQL.php
new file mode 100644
index 000000000..56a28e294
--- /dev/null
+++ b/app/Models/TagDAOPGSQL.php
@@ -0,0 +1,9 @@
+<?php
+
+class FreshRSS_TagDAOPGSQL extends FreshRSS_TagDAO {
+
+ public function sqlIgnore() {
+ return ''; //TODO
+ }
+
+}
diff --git a/app/Models/TagDAOSQLite.php b/app/Models/TagDAOSQLite.php
new file mode 100644
index 000000000..b1deb6c65
--- /dev/null
+++ b/app/Models/TagDAOSQLite.php
@@ -0,0 +1,19 @@
+<?php
+
+class FreshRSS_TagDAOSQLite extends FreshRSS_TagDAO {
+
+ public function sqlIgnore() {
+ return 'OR IGNORE';
+ }
+
+ protected function autoUpdateDb($errorInfo) {
+ if ($tableInfo = $this->bd->query("SELECT sql FROM sqlite_master where name='tag'")) {
+ $showCreate = $tableInfo->fetchColumn();
+ if (stripos($showCreate, 'tag') === false) {
+ return $this->createTagTable(); //v1.12.0
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/app/Models/Themes.php b/app/Models/Themes.php
index 8920fbf7e..235269e39 100644
--- a/app/Models/Themes.php
+++ b/app/Models/Themes.php
@@ -68,7 +68,7 @@ class FreshRSS_Themes extends Minz_Model {
return $infos;
}
- public static function icon($name, $urlOnly = false) {
+ public static function alt($name) {
static $alts = array(
'add' => '✚',
'all' => '☰',
@@ -84,6 +84,7 @@ class FreshRSS_Themes extends Minz_Model {
'icon' => '⊚',
'import' => '⤓',
'key' => '⚿',
+ 'label' => '🏷️',
'link' => '↗',
'login' => '🔒',
'logout' => '🔓',
@@ -104,13 +105,18 @@ class FreshRSS_Themes extends Minz_Model {
'view-global' => '☷',
'view-reader' => '☕',
);
- if (!isset($alts[$name])) {
+ return isset($name) ? $alts[$name] : '';
+ }
+
+ public static function icon($name, $urlOnly = false, $altOnly = false) {
+ $alt = self::alt($name);
+ if ($alt == '') {
return '';
}
$url = $name . '.svg';
$url = isset(self::$themeIcons[$url]) ? (self::$themeIconsUrl . $url) : (self::$defaultIconsUrl . $url);
- return $urlOnly ? Minz_Url::display($url) : '<img class="icon" src="' . Minz_Url::display($url) . '" alt="' . $alts[$name] . '" />';
+ return $urlOnly ? Minz_Url::display($url) : '<img class="icon" src="' . Minz_Url::display($url) . '" alt="' . $alt . '" />';
}
}
diff --git a/app/Models/UserDAO.php b/app/Models/UserDAO.php
index c921d54c9..5fb46c947 100644
--- a/app/Models/UserDAO.php
+++ b/app/Models/UserDAO.php
@@ -14,14 +14,13 @@ class FreshRSS_UserDAO extends Minz_ModelPdo {
$ok = false;
$bd_prefix_user = $db['prefix'] . $username . '_';
if (defined('SQL_CREATE_TABLES')) { //E.g. MySQL
- $sql = sprintf(SQL_CREATE_TABLES . SQL_CREATE_TABLE_ENTRYTMP, $bd_prefix_user, _t('gen.short.default_category'));
+ $sql = sprintf(SQL_CREATE_TABLES . SQL_CREATE_TABLE_ENTRYTMP . SQL_CREATE_TABLE_TAGS, $bd_prefix_user, _t('gen.short.default_category'));
$stm = $userPDO->bd->prepare($sql);
$ok = $stm && $stm->execute();
} else { //E.g. SQLite
- global $SQL_CREATE_TABLES;
- global $SQL_CREATE_TABLE_ENTRYTMP;
+ global $SQL_CREATE_TABLES, $SQL_CREATE_TABLE_ENTRYTMP, $SQL_CREATE_TABLE_TAGS;
if (is_array($SQL_CREATE_TABLES)) {
- $instructions = array_merge($SQL_CREATE_TABLES, $SQL_CREATE_TABLE_ENTRYTMP);
+ $instructions = array_merge($SQL_CREATE_TABLES, $SQL_CREATE_TABLE_ENTRYTMP, $SQL_CREATE_TABLE_TAGS);
$ok = !empty($instructions);
foreach ($instructions as $instruction) {
$sql = sprintf($instruction, $bd_prefix_user, _t('gen.short.default_category'));
diff --git a/app/Models/UserQuery.php b/app/Models/UserQuery.php
index ef94fdaf6..f607084f8 100644
--- a/app/Models/UserQuery.php
+++ b/app/Models/UserQuery.php
@@ -19,15 +19,17 @@ class FreshRSS_UserQuery {
private $url;
private $feed_dao;
private $category_dao;
+ private $tag_dao;
/**
* @param array $query
* @param FreshRSS_Searchable $feed_dao
* @param FreshRSS_Searchable $category_dao
*/
- public function __construct($query, FreshRSS_Searchable $feed_dao = null, FreshRSS_Searchable $category_dao = null) {
+ public function __construct($query, FreshRSS_Searchable $feed_dao = null, FreshRSS_Searchable $category_dao = null, FreshRSS_Searchable $tag_dao = null) {
$this->category_dao = $category_dao;
$this->feed_dao = $feed_dao;
+ $this->tag_dao = $tag_dao;
if (isset($query['get'])) {
$this->parseGet($query['get']);
}
@@ -88,6 +90,9 @@ class FreshRSS_UserQuery {
case 's':
$this->parseFavorite();
break;
+ case 't':
+ $this->parseTag($matches['id']);
+ break;
}
}
}
@@ -139,6 +144,25 @@ class FreshRSS_UserQuery {
}
/**
+ * Parse the query string when it is a "tag" query
+ *
+ * @param integer $id
+ * @throws FreshRSS_DAO_Exception
+ */
+ private function parseTag($id) {
+ if ($this->tag_dao == null) {
+ throw new FreshRSS_DAO_Exception('Tag DAO is not loaded in UserQuery');
+ }
+ $category = $this->category_dao->searchById($id);
+ if ($tag) {
+ $this->get_name = $tag->name();
+ } else {
+ $this->deprecated = true;
+ }
+ $this->get_type = 'tag';
+ }
+
+ /**
* Parse the query string when it is a "favorite" query
*/
private function parseFavorite() {
diff --git a/app/SQL/install.sql.mysql.php b/app/SQL/install.sql.mysql.php
index 747a0a6b3..b3353ac95 100644
--- a/app/SQL/install.sql.mysql.php
+++ b/app/SQL/install.sql.mysql.php
@@ -1,10 +1,10 @@
<?php
-define('SQL_CREATE_DB', 'CREATE DATABASE IF NOT EXISTS %1$s DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;');
+define('SQL_CREATE_DB', 'CREATE DATABASE IF NOT EXISTS `%1$s` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;');
define('SQL_CREATE_TABLES', '
CREATE TABLE IF NOT EXISTS `%1$scategory` (
`id` SMALLINT NOT NULL AUTO_INCREMENT, -- v0.7
- `name` varchar(191) NOT NULL,
+ `name` VARCHAR(' . FreshRSS_DatabaseDAO::LENGTH_INDEX_UNICODE . ') NOT NULL, -- Max index length for Unicode is 191 characters (767 bytes)
PRIMARY KEY (`id`),
UNIQUE KEY (`name`) -- v0.7
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci
@@ -12,21 +12,21 @@ ENGINE = INNODB;
CREATE TABLE IF NOT EXISTS `%1$sfeed` (
`id` SMALLINT NOT NULL AUTO_INCREMENT, -- v0.7
- `url` varchar(511) CHARACTER SET latin1 NOT NULL,
+ `url` VARCHAR(511) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
`category` SMALLINT DEFAULT 0, -- v0.7
- `name` varchar(191) NOT NULL,
- `website` varchar(255) CHARACTER SET latin1,
- `description` text,
- `lastUpdate` int(11) DEFAULT 0, -- Until year 2038
- `priority` tinyint(2) NOT NULL DEFAULT 10,
- `pathEntries` varchar(511) DEFAULT NULL,
- `httpAuth` varchar(511) DEFAULT NULL,
- `error` boolean DEFAULT 0,
+ `name` VARCHAR(' . FreshRSS_DatabaseDAO::LENGTH_INDEX_UNICODE . ') NOT NULL,
+ `website` VARCHAR(255) CHARACTER SET latin1 COLLATE latin1_bin,
+ `description` TEXT,
+ `lastUpdate` INT(11) DEFAULT 0, -- Until year 2038
+ `priority` TINYINT(2) NOT NULL DEFAULT 10,
+ `pathEntries` VARCHAR(511) DEFAULT NULL,
+ `httpAuth` VARCHAR(511) DEFAULT NULL,
+ `error` BOOLEAN DEFAULT 0,
`keep_history` MEDIUMINT NOT NULL DEFAULT -2, -- v0.7
`ttl` INT NOT NULL DEFAULT 0, -- v0.7.3
`attributes` TEXT, -- v1.11.0
- `cache_nbEntries` int DEFAULT 0, -- v0.7
- `cache_nbUnreads` int DEFAULT 0, -- v0.7
+ `cache_nbEntries` INT DEFAULT 0, -- v0.7
+ `cache_nbUnreads` INT DEFAULT 0, -- v0.7
PRIMARY KEY (`id`),
FOREIGN KEY (`category`) REFERENCES `%1$scategory`(`id`) ON DELETE SET NULL ON UPDATE CASCADE,
UNIQUE KEY (`url`), -- v0.7
@@ -37,19 +37,19 @@ CREATE TABLE IF NOT EXISTS `%1$sfeed` (
ENGINE = INNODB;
CREATE TABLE IF NOT EXISTS `%1$sentry` (
- `id` bigint NOT NULL, -- v0.7
- `guid` varchar(760) CHARACTER SET latin1 NOT NULL, -- Maximum for UNIQUE is 767B
- `title` varchar(255) NOT NULL,
- `author` varchar(255),
- `content_bin` blob, -- v0.7
- `link` varchar(1023) CHARACTER SET latin1 NOT NULL,
- `date` int(11), -- Until year 2038
+ `id` BIGINT NOT NULL, -- v0.7
+ `guid` VARCHAR(760) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL, -- Maximum for UNIQUE is 767B
+ `title` VARCHAR(255) NOT NULL,
+ `author` VARCHAR(255),
+ `content_bin` BLOB, -- v0.7
+ `link` VARCHAR(1023) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
+ `date` INT(11), -- Until year 2038
`lastSeen` INT(11) DEFAULT 0, -- v1.1.1, Until year 2038
`hash` BINARY(16), -- v1.1.1
- `is_read` boolean NOT NULL DEFAULT 0,
- `is_favorite` boolean NOT NULL DEFAULT 0,
+ `is_read` BOOLEAN NOT NULL DEFAULT 0,
+ `is_favorite` BOOLEAN NOT NULL DEFAULT 0,
`id_feed` SMALLINT, -- v0.7
- `tags` varchar(1023),
+ `tags` VARCHAR(1023),
PRIMARY KEY (`id`),
FOREIGN KEY (`id_feed`) REFERENCES `%1$sfeed`(`id`) ON DELETE CASCADE ON UPDATE CASCADE,
UNIQUE KEY (`id_feed`,`guid`), -- v0.7
@@ -65,19 +65,19 @@ INSERT IGNORE INTO `%1$scategory` (id, name) VALUES(1, "%2$s");
define('SQL_CREATE_TABLE_ENTRYTMP', '
CREATE TABLE IF NOT EXISTS `%1$sentrytmp` ( -- v1.7
- `id` bigint NOT NULL,
- `guid` varchar(760) CHARACTER SET latin1 NOT NULL,
- `title` varchar(255) NOT NULL,
- `author` varchar(255),
- `content_bin` blob,
- `link` varchar(1023) CHARACTER SET latin1 NOT NULL,
- `date` int(11),
+ `id` BIGINT NOT NULL,
+ `guid` VARCHAR(760) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
+ `title` VARCHAR(255) NOT NULL,
+ `author` VARCHAR(255),
+ `content_bin` BLOB,
+ `link` VARCHAR(1023) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
+ `date` INT(11),
`lastSeen` INT(11) DEFAULT 0,
`hash` BINARY(16),
- `is_read` boolean NOT NULL DEFAULT 0,
- `is_favorite` boolean NOT NULL DEFAULT 0,
+ `is_read` BOOLEAN NOT NULL DEFAULT 0,
+ `is_favorite` BOOLEAN NOT NULL DEFAULT 0,
`id_feed` SMALLINT,
- `tags` varchar(1023),
+ `tags` VARCHAR(1023),
PRIMARY KEY (`id`),
FOREIGN KEY (`id_feed`) REFERENCES `%1$sfeed`(`id`) ON DELETE CASCADE ON UPDATE CASCADE,
UNIQUE KEY (`id_feed`,`guid`),
@@ -88,25 +88,46 @@ ENGINE = INNODB;
CREATE INDEX `entry_feed_read_index` ON `%1$sentry`(`id_feed`,`is_read`); -- v1.7 Located here to be auto-added
');
+define('SQL_CREATE_TABLE_TAGS', '
+CREATE TABLE IF NOT EXISTS `%1$stag` ( -- v1.12
+ `id` SMALLINT NOT NULL AUTO_INCREMENT,
+ `name` VARCHAR(63) NOT NULL,
+ `attributes` TEXT,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY (`name`)
+) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci
+ENGINE = INNODB;
+
+CREATE TABLE IF NOT EXISTS `%1$sentrytag` ( -- v1.12
+ `id_tag` SMALLINT,
+ `id_entry` BIGINT,
+ PRIMARY KEY (`id_tag`,`id_entry`),
+ FOREIGN KEY (`id_tag`) REFERENCES `%1$stag`(`id`) ON DELETE CASCADE ON UPDATE CASCADE,
+ FOREIGN KEY (`id_entry`) REFERENCES `%1$sentry`(`id`) ON DELETE CASCADE ON UPDATE CASCADE,
+ INDEX (`id_entry`)
+) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci
+ENGINE = INNODB;
+');
+
define('SQL_INSERT_FEEDS', '
-INSERT IGNORE INTO `%1$sfeed` (url, category, name, website, description, ttl) VALUES("http://freshrss.org/feeds/all.atom.xml", 1, "FreshRSS.org", "http://freshrss.org/", "FreshRSS, a free, self-hostable aggregator…", 86400);
+INSERT IGNORE INTO `%1$sfeed` (url, category, name, website, description, ttl) VALUES("https://freshrss.org/feeds/all.atom.xml", 1, "FreshRSS.org", "https://freshrss.org/", "FreshRSS, a free, self-hostable aggregator…", 86400);
INSERT IGNORE INTO `%1$sfeed` (url, category, name, website, description, ttl) VALUES("https://github.com/FreshRSS/FreshRSS/releases.atom", 1, "FreshRSS @ GitHub", "https://github.com/FreshRSS/FreshRSS/", "FreshRSS releases @ GitHub", 86400);
');
-define('SQL_DROP_TABLES', 'DROP TABLE IF EXISTS `%1$sentrytmp`, `%1$sentry`, `%1$sfeed`, `%1$scategory`');
+define('SQL_DROP_TABLES', 'DROP TABLE IF EXISTS `%1$sentrytag`, `%1$stag`, `%1$sentrytmp`, `%1$sentry`, `%1$sfeed`, `%1$scategory`');
define('SQL_UPDATE_UTF8MB4', '
-ALTER DATABASE `%2$s` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+ALTER DATABASE `%2$s` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- v1.5.0
ALTER TABLE `%1$scategory` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-UPDATE `%1$scategory` SET name=SUBSTRING(name,1,190) WHERE LENGTH(name) > 191;
-ALTER TABLE `%1$scategory` MODIFY `name` VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL;
+UPDATE `%1$scategory` SET name=SUBSTRING(name,1,' . FreshRSS_DatabaseDAO::LENGTH_INDEX_UNICODE . ') WHERE LENGTH(name) > ' . FreshRSS_DatabaseDAO::LENGTH_INDEX_UNICODE . ';
+ALTER TABLE `%1$scategory` MODIFY `name` VARCHAR(' . FreshRSS_DatabaseDAO::LENGTH_INDEX_UNICODE . ') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL;
OPTIMIZE TABLE `%1$scategory`;
ALTER TABLE `%1$sfeed` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-UPDATE `%1$sfeed` SET name=SUBSTRING(name,1,190) WHERE LENGTH(name) > 191;
-ALTER TABLE `%1$sfeed` MODIFY `name` VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL;
-ALTER TABLE `%1$sfeed` MODIFY `description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+UPDATE `%1$sfeed` SET name=SUBSTRING(name,1,' . FreshRSS_DatabaseDAO::LENGTH_INDEX_UNICODE . ') WHERE LENGTH(name) > ' . FreshRSS_DatabaseDAO::LENGTH_INDEX_UNICODE . ';
+ALTER TABLE `%1$sfeed` MODIFY `name` VARCHAR(' . FreshRSS_DatabaseDAO::LENGTH_INDEX_UNICODE . ') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL;
+ALTER TABLE `%1$sfeed` MODIFY `description` TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
OPTIMIZE TABLE `%1$sfeed`;
ALTER TABLE `%1$sentry` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
@@ -115,3 +136,8 @@ ALTER TABLE `%1$sentry` MODIFY `author` VARCHAR(255) CHARACTER SET utf8mb4 COLLA
ALTER TABLE `%1$sentry` MODIFY `tags` VARCHAR(1023) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
OPTIMIZE TABLE `%1$sentry`;
');
+
+define('SQL_UPDATE_GUID_LATIN1_BIN', ' -- v1.12
+ALTER TABLE `%1$sentrytmp` MODIFY `guid` VARCHAR(760) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL;
+ALTER TABLE `%1$sentry` MODIFY `guid` VARCHAR(760) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL;
+');
diff --git a/app/SQL/install.sql.pgsql.php b/app/SQL/install.sql.pgsql.php
index b80fbf1e7..e68e6f3be 100644
--- a/app/SQL/install.sql.pgsql.php
+++ b/app/SQL/install.sql.pgsql.php
@@ -1,5 +1,5 @@
<?php
-define('SQL_CREATE_DB', 'CREATE DATABASE %1$s ENCODING \'UTF8\';');
+define('SQL_CREATE_DB', 'CREATE DATABASE "%1$s" ENCODING \'UTF8\';');
global $SQL_CREATE_TABLES;
$SQL_CREATE_TABLES = array(
@@ -10,16 +10,16 @@ $SQL_CREATE_TABLES = array(
'CREATE TABLE IF NOT EXISTS "%1$sfeed" (
"id" SERIAL PRIMARY KEY,
- "url" varchar(511) UNIQUE NOT NULL,
+ "url" VARCHAR(511) UNIQUE NOT NULL,
"category" SMALLINT DEFAULT 0,
"name" VARCHAR(255) NOT NULL,
"website" VARCHAR(255),
- "description" text,
+ "description" TEXT,
"lastUpdate" INT DEFAULT 0,
"priority" SMALLINT NOT NULL DEFAULT 10,
"pathEntries" VARCHAR(511) DEFAULT NULL,
"httpAuth" VARCHAR(511) DEFAULT NULL,
- "error" smallint DEFAULT 0,
+ "error" SMALLINT DEFAULT 0,
"keep_history" INT NOT NULL DEFAULT -2,
"ttl" INT NOT NULL DEFAULT 0,
"attributes" TEXT, -- v1.11.0
@@ -27,9 +27,9 @@ $SQL_CREATE_TABLES = array(
"cache_nbUnreads" INT DEFAULT 0,
FOREIGN KEY ("category") REFERENCES "%1$scategory" ("id") ON DELETE SET NULL ON UPDATE CASCADE
);',
-'CREATE INDEX %1$sname_index ON "%1$sfeed" ("name");',
-'CREATE INDEX %1$spriority_index ON "%1$sfeed" ("priority");',
-'CREATE INDEX %1$skeep_history_index ON "%1$sfeed" ("keep_history");',
+'CREATE INDEX "%1$sname_index" ON "%1$sfeed" ("name");',
+'CREATE INDEX "%1$spriority_index" ON "%1$sfeed" ("priority");',
+'CREATE INDEX "%1$skeep_history_index" ON "%1$sfeed" ("keep_history");',
'CREATE TABLE IF NOT EXISTS "%1$sentry" (
"id" BIGINT NOT NULL PRIMARY KEY,
@@ -48,11 +48,14 @@ $SQL_CREATE_TABLES = array(
FOREIGN KEY ("id_feed") REFERENCES "%1$sfeed" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
UNIQUE ("id_feed","guid")
);',
-'CREATE INDEX %1$sis_favorite_index ON "%1$sentry" ("is_favorite");',
-'CREATE INDEX %1$sis_read_index ON "%1$sentry" ("is_read");',
-'CREATE INDEX %1$sentry_lastSeen_index ON "%1$sentry" ("lastSeen");',
+'CREATE INDEX "%1$sis_favorite_index" ON "%1$sentry" ("is_favorite");',
+'CREATE INDEX "%1$sis_read_index" ON "%1$sentry" ("is_read");',
+'CREATE INDEX "%1$sentry_lastSeen_index" ON "%1$sentry" ("lastSeen");',
-'INSERT INTO "%1$scategory" (id, name) SELECT 1, \'%2$s\' WHERE NOT EXISTS (SELECT id FROM "%1$scategory" WHERE id = 1) RETURNING nextval(\'%1$scategory_id_seq\');',
+'INSERT INTO "%1$scategory" (id, name)
+ SELECT 1, \'%2$s\'
+ WHERE NOT EXISTS (SELECT id FROM "%1$scategory" WHERE id = 1)
+ RETURNING nextval(\'"%1$scategory_id_seq"\');',
);
global $SQL_CREATE_TABLE_ENTRYTMP;
@@ -74,15 +77,36 @@ $SQL_CREATE_TABLE_ENTRYTMP = array(
FOREIGN KEY ("id_feed") REFERENCES "%1$sfeed" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
UNIQUE ("id_feed","guid")
);',
-'CREATE INDEX %1$sentrytmp_date_index ON "%1$sentrytmp" ("date");',
+'CREATE INDEX "%1$sentrytmp_date_index" ON "%1$sentrytmp" ("date");',
-'CREATE INDEX %1$sentry_feed_read_index ON "%1$sentry" ("id_feed","is_read");', //v1.7
+'CREATE INDEX "%1$sentry_feed_read_index" ON "%1$sentry" ("id_feed","is_read");', //v1.7
+);
+
+global $SQL_CREATE_TABLE_TAGS;
+$SQL_CREATE_TABLE_TAGS = array(
+'CREATE TABLE IF NOT EXISTS "%1$stag" ( -- v1.12
+ "id" SERIAL PRIMARY KEY,
+ "name" VARCHAR(63) UNIQUE NOT NULL,
+ "attributes" TEXT
+);',
+'CREATE TABLE IF NOT EXISTS "%1$sentrytag" (
+ "id_tag" SMALLINT,
+ "id_entry" BIGINT,
+ PRIMARY KEY ("id_tag","id_entry"),
+ FOREIGN KEY ("id_tag") REFERENCES "%1$stag" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
+ FOREIGN KEY ("id_entry") REFERENCES "%1$sentry" ("id") ON DELETE CASCADE ON UPDATE CASCADE
+);',
+'CREATE INDEX "%1$sentrytag_id_entry_index" ON "%1$sentrytag" ("id_entry");',
);
global $SQL_INSERT_FEEDS;
$SQL_INSERT_FEEDS = array(
-'INSERT INTO "%1$sfeed" (url, category, name, website, description, ttl) SELECT \'http://freshrss.org/feeds/all.atom.xml\', 1, \'FreshRSS.org\', \'http://freshrss.org/\', \'FreshRSS, a free, self-hostable aggregator…\', 86400 WHERE NOT EXISTS (SELECT id FROM "%1$sfeed" WHERE url = \'http://freshrss.org/feeds/all.atom.xml\');',
-'INSERT INTO "%1$sfeed" (url, category, name, website, description, ttl) SELECT \'https://github.com/FreshRSS/FreshRSS/releases.atom\', 1, \'FreshRSS @ GitHub\', \'https://github.com/FreshRSS/FreshRSS/\', \'FreshRSS releases @ GitHub\', 86400 WHERE NOT EXISTS (SELECT id FROM "%1$sfeed" WHERE url = \'https://github.com/FreshRSS/FreshRSS/releases.atom\');',
+'INSERT INTO "%1$sfeed" (url, category, name, website, description, ttl)
+ SELECT \'https://freshrss.org/feeds/all.atom.xml\', 1, \'FreshRSS.org\', \'https://freshrss.org/\', \'FreshRSS, a free, self-hostable aggregator…\', 86400
+ WHERE NOT EXISTS (SELECT id FROM "%1$sfeed" WHERE url = \'https://freshrss.org/feeds/all.atom.xml\');',
+'INSERT INTO "%1$sfeed" (url, category, name, website, description, ttl)
+ SELECT \'https://github.com/FreshRSS/FreshRSS/releases.atom\', 1, \'FreshRSS @ GitHub\', \'https://github.com/FreshRSS/FreshRSS/\', \'FreshRSS releases @ GitHub\', 86400
+ WHERE NOT EXISTS (SELECT id FROM "%1$sfeed" WHERE url = \'https://github.com/FreshRSS/FreshRSS/releases.atom\');',
);
-define('SQL_DROP_TABLES', 'DROP TABLE IF EXISTS "%1$sentrytmp", "%1$sentry", "%1$sfeed", "%1$scategory"');
+define('SQL_DROP_TABLES', 'DROP TABLE IF EXISTS "%1$sentrytag", "%1$stag", "%1$sentrytmp", "%1$sentry", "%1$sfeed", "%1$scategory"');
diff --git a/app/SQL/install.sql.sqlite.php b/app/SQL/install.sql.sqlite.php
index cbfb719e5..1dd5f2647 100644
--- a/app/SQL/install.sql.sqlite.php
+++ b/app/SQL/install.sql.sqlite.php
@@ -3,27 +3,27 @@ global $SQL_CREATE_TABLES;
$SQL_CREATE_TABLES = array(
'CREATE TABLE IF NOT EXISTS `category` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
- `name` varchar(255) NOT NULL,
+ `name` VARCHAR(255) NOT NULL,
UNIQUE (`name`)
);',
'CREATE TABLE IF NOT EXISTS `feed` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
- `url` varchar(511) NOT NULL,
+ `url` VARCHAR(511) NOT NULL,
`category` SMALLINT DEFAULT 0,
- `name` varchar(255) NOT NULL,
- `website` varchar(255),
- `description` text,
- `lastUpdate` int(11) DEFAULT 0, -- Until year 2038
- `priority` tinyint(2) NOT NULL DEFAULT 10,
- `pathEntries` varchar(511) DEFAULT NULL,
- `httpAuth` varchar(511) DEFAULT NULL,
- `error` boolean DEFAULT 0,
+ `name` VARCHAR(255) NOT NULL,
+ `website` VARCHAR(255),
+ `description` TEXT,
+ `lastUpdate` INT(11) DEFAULT 0, -- Until year 2038
+ `priority` TINYINT(2) NOT NULL DEFAULT 10,
+ `pathEntries` VARCHAR(511) DEFAULT NULL,
+ `httpAuth` VARCHAR(511) DEFAULT NULL,
+ `error` BOOLEAN DEFAULT 0,
`keep_history` MEDIUMINT NOT NULL DEFAULT -2,
`ttl` INT NOT NULL DEFAULT 0,
`attributes` TEXT, -- v1.11.0
- `cache_nbEntries` int DEFAULT 0,
- `cache_nbUnreads` int DEFAULT 0,
+ `cache_nbEntries` INT DEFAULT 0,
+ `cache_nbUnreads` INT DEFAULT 0,
FOREIGN KEY (`category`) REFERENCES `category`(`id`) ON DELETE SET NULL ON UPDATE CASCADE,
UNIQUE (`url`)
);',
@@ -32,19 +32,19 @@ $SQL_CREATE_TABLES = array(
'CREATE INDEX IF NOT EXISTS feed_keep_history_index ON `feed`(`keep_history`);',
'CREATE TABLE IF NOT EXISTS `entry` (
- `id` bigint NOT NULL,
- `guid` varchar(760) NOT NULL,
- `title` varchar(255) NOT NULL,
- `author` varchar(255),
- `content` text,
- `link` varchar(1023) NOT NULL,
- `date` int(11), -- Until year 2038
+ `id` BIGINT NOT NULL,
+ `guid` VARCHAR(760) NOT NULL,
+ `title` VARCHAR(255) NOT NULL,
+ `author` VARCHAR(255),
+ `content` TEXT,
+ `link` VARCHAR(1023) NOT NULL,
+ `date` INT(11), -- Until year 2038
`lastSeen` INT(11) DEFAULT 0, -- v1.1.1, Until year 2038
`hash` BINARY(16), -- v1.1.1
- `is_read` boolean NOT NULL DEFAULT 0,
- `is_favorite` boolean NOT NULL DEFAULT 0,
+ `is_read` BOOLEAN NOT NULL DEFAULT 0,
+ `is_favorite` BOOLEAN NOT NULL DEFAULT 0,
`id_feed` SMALLINT,
- `tags` varchar(1023),
+ `tags` VARCHAR(1023),
PRIMARY KEY (`id`),
FOREIGN KEY (`id_feed`) REFERENCES `feed`(`id`) ON DELETE CASCADE ON UPDATE CASCADE,
UNIQUE (`id_feed`,`guid`)
@@ -59,19 +59,19 @@ $SQL_CREATE_TABLES = array(
global $SQL_CREATE_TABLE_ENTRYTMP;
$SQL_CREATE_TABLE_ENTRYTMP = array(
'CREATE TABLE IF NOT EXISTS `entrytmp` ( -- v1.7
- `id` bigint NOT NULL,
- `guid` varchar(760) NOT NULL,
- `title` varchar(255) NOT NULL,
- `author` varchar(255),
- `content` text,
- `link` varchar(1023) NOT NULL,
- `date` int(11),
+ `id` BIGINT NOT NULL,
+ `guid` VARCHAR(760) NOT NULL,
+ `title` VARCHAR(255) NOT NULL,
+ `author` VARCHAR(255),
+ `content` TEXT,
+ `link` VARCHAR(1023) NOT NULL,
+ `date` INT(11),
`lastSeen` INT(11) DEFAULT 0,
`hash` BINARY(16),
- `is_read` boolean NOT NULL DEFAULT 0,
- `is_favorite` boolean NOT NULL DEFAULT 0,
+ `is_read` BOOLEAN NOT NULL DEFAULT 0,
+ `is_favorite` BOOLEAN NOT NULL DEFAULT 0,
`id_feed` SMALLINT,
- `tags` varchar(1023),
+ `tags` VARCHAR(1023),
PRIMARY KEY (`id`),
FOREIGN KEY (`id_feed`) REFERENCES `feed`(`id`) ON DELETE CASCADE ON UPDATE CASCADE,
UNIQUE (`id_feed`,`guid`)
@@ -81,44 +81,30 @@ $SQL_CREATE_TABLE_ENTRYTMP = array(
'CREATE INDEX IF NOT EXISTS `entry_feed_read_index` ON `entry`(`id_feed`,`is_read`);', //v1.7
);
+global $SQL_CREATE_TABLE_TAGS;
+$SQL_CREATE_TABLE_TAGS = array(
+'CREATE TABLE IF NOT EXISTS `tag` ( -- v1.12
+ `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
+ `name` VARCHAR(63) NOT NULL,
+ `attributes` TEXT,
+ UNIQUE (`name`)
+);',
+'CREATE TABLE IF NOT EXISTS `entrytag` (
+ `id_tag` SMALLINT,
+ `id_entry` SMALLINT,
+ PRIMARY KEY (`id_tag`,`id_entry`),
+ FOREIGN KEY (`id_tag`) REFERENCES `tag` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
+ FOREIGN KEY (`id_entry`) REFERENCES `entry` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
+);',
+'CREATE INDEX entrytag_id_entry_index ON `entrytag` (`id_entry`);',
+);
+
global $SQL_INSERT_FEEDS;
$SQL_INSERT_FEEDS = array(
-'INSERT OR IGNORE INTO `feed`
- (
- url,
- category,
- name,
- website,
- description,
- ttl
- )
- VALUES
- (
- "http://freshrss.org/feeds/all.atom.xml",
- 1,
- "FreshRSS.org",
- "http://freshrss.org/",
- "FreshRSS, a free, self-hostable aggregator…",
- 86400
- );',
-'INSERT OR IGNORE INTO `feed`
- (
- url,
- category,
- name,
- website,
- description,
- ttl
- )
- VALUES
- (
- "https://github.com/FreshRSS/FreshRSS/releases.atom",
- 1,
- "FreshRSS releases",
- "https://github.com/FreshRSS/FreshRSS/",
- "FreshRSS releases @ GitHub",
- 86400
- );',
+'INSERT OR IGNORE INTO `feed` (url, category, name, website, description, ttl)
+ VALUES ("https://freshrss.org/feeds/all.atom.xml", 1, "FreshRSS.org", "https://freshrss.org/", "FreshRSS, a free, self-hostable aggregator…", 86400);',
+'INSERT OR IGNORE INTO `feed` (url, category, name, website, description, ttl)
+ VALUES ("https://github.com/FreshRSS/FreshRSS/releases.atom", 1, "FreshRSS releases", "https://github.com/FreshRSS/FreshRSS/", "FreshRSS releases @ GitHub", 86400);',
);
-define('SQL_DROP_TABLES', 'DROP TABLE IF EXISTS `entrytmp`, `entry`, `feed`, `category`');
+define('SQL_DROP_TABLES', 'DROP TABLE IF EXISTS `entrytag`, `tag`, `entrytmp`, `entry`, `feed`, `category`');
diff --git a/app/i18n/cz/conf.php b/app/i18n/cz/conf.php
index e73ab168f..84ee78c73 100644
--- a/app/i18n/cz/conf.php
+++ b/app/i18n/cz/conf.php
@@ -19,7 +19,7 @@ return array(
'bottom_line' => 'Spodní řádek',
'entry' => 'Ikony článků',
'publication_date' => 'Datum vydání',
- 'related_tags' => 'Související tagy',
+ 'related_tags' => 'Související tagy', //TODO
'sharing' => 'Sdílení',
'top_line' => 'Horní řádek',
),
diff --git a/app/i18n/cz/gen.php b/app/i18n/cz/gen.php
index 66c011da3..b9a65f210 100644
--- a/app/i18n/cz/gen.php
+++ b/app/i18n/cz/gen.php
@@ -181,7 +181,7 @@ return array(
'short' => array(
'attention' => 'Upozornění!',
'blank_to_disable' => 'Zakázat - ponechte prázdné',
- 'by_author' => 'Od <em>%s</em>',
+ 'by_author' => 'Od:',
'by_default' => 'Výchozí',
'damn' => 'Sakra!',
'default_category' => 'Nezařazeno',
diff --git a/app/i18n/cz/index.php b/app/i18n/cz/index.php
index 48a28d4da..7e60ca379 100644
--- a/app/i18n/cz/index.php
+++ b/app/i18n/cz/index.php
@@ -7,7 +7,7 @@ return array(
'bugs_reports' => 'Hlášení chyb',
'credits' => 'Poděkování',
'credits_content' => 'Některé designové prvky pocházejí z <a href="http://twitter.github.io/bootstrap/">Bootstrap</a>, FreshRSS ale tuto platformu nevyužívá. <a href="https://git.gnome.org/browse/gnome-icon-theme-symbolic">Ikony</a> pocházejí z <a href="https://www.gnome.org/">GNOME projektu</a>. Font <em>Open Sans</em> vytvořil <a href="https://fonts.google.com/specimen/Open+Sans">Steve Matteson</a>. FreshRSS je založen na PHP framework <a href="https://github.com/marienfressinaud/MINZ">Minz</a>.',
- 'freshrss_description' => 'FreshRSS je čtečka RSS kanálů určená k provozu na vlastním serveru, podobná <a href="http://tontof.net/kriss/feed/">Kriss Feed</a> nebo <a href="http://projet.idleman.fr/leed/">Leed</a>. Je to nenáročný a jednoduchý, zároveň ale mocný a konfigurovatelný nástroj.',
+ 'freshrss_description' => 'FreshRSS je čtečka RSS kanálů určená k provozu na vlastním serveru, podobná <a href="http://tontof.net/kriss/feed/">Kriss Feed</a> nebo <a href="http://leed.idleman.fr/">Leed</a>. Je to nenáročný a jednoduchý, zároveň ale mocný a konfigurovatelný nástroj.',
'github' => '<a href="https://github.com/FreshRSS/FreshRSS/issues">na Github</a>',
'license' => 'Licence',
'project_website' => 'Stránka projektu',
@@ -53,10 +53,11 @@ return array(
'starred' => 'Zobrazit oblíbené',
'stats' => 'Statistika',
'subscription' => 'Správa subskripcí',
+ 'tags' => 'My labels', //TODO
'unread' => 'Zobrazovat nepřečtené',
),
'share' => 'Sdílet',
'tag' => array(
- 'related' => 'Související tagy',
+ 'related' => 'Související tagy', //TODO
),
);
diff --git a/app/i18n/cz/sub.php b/app/i18n/cz/sub.php
index 5caf9acbe..55441aaf8 100644
--- a/app/i18n/cz/sub.php
+++ b/app/i18n/cz/sub.php
@@ -27,6 +27,7 @@ return array(
'password' => 'Heslo',
'username' => 'Přihlašovací jméno',
),
+ 'clear_cache' => 'Always clear cache', //TODO
'css_help' => 'Stáhne zkrácenou verzi RSS kanálů (pozor, náročnější na čas!)',
'css_path' => 'Původní CSS soubor článku z webových stránek',
'description' => 'Popis',
diff --git a/app/i18n/de/admin.php b/app/i18n/de/admin.php
index fbeb80296..2eb4a69f6 100644
--- a/app/i18n/de/admin.php
+++ b/app/i18n/de/admin.php
@@ -67,8 +67,8 @@ return array(
'ok' => 'Sie haben die JSON-Erweiterung.',
),
'mbstring' => array(
- 'nok' => 'Cannot find the recommended library mbstring for Unicode.', //TODO
- 'ok' => 'You have the recommended library mbstring for Unicode.', //TODO
+ 'nok' => 'Ihnen fehlt die mbstring-Bibliothek für Unicode.', //TODO
+ 'ok' => 'Sie haben die empfohlene mbstring-Bliothek für Unicode.', //TODO
),
'minz' => array(
'nok' => 'Ihnen fehlt das Minz-Framework.',
diff --git a/app/i18n/de/conf.php b/app/i18n/de/conf.php
index 78f3b4510..579363cb5 100644
--- a/app/i18n/de/conf.php
+++ b/app/i18n/de/conf.php
@@ -19,7 +19,7 @@ return array(
'bottom_line' => 'Fußzeile',
'entry' => 'Artikel-Symbole',
'publication_date' => 'Datum der Veröffentlichung',
- 'related_tags' => 'Verwandte Tags',
+ 'related_tags' => 'Verwandte Tags', //TODO
'sharing' => 'Teilen',
'top_line' => 'Kopfzeile',
),
@@ -102,7 +102,7 @@ return array(
'read' => array(
'article_open_on_website' => 'wenn der Artikel auf der Original-Webseite geöffnet wird',
'article_viewed' => 'wenn der Artikel angesehen wird',
- 'scroll' => 'beim Blättern',
+ 'scroll' => 'beim Scrollen bzw. Überspringen',
'upon_reception' => 'beim Empfang des Artikels',
'when' => 'Artikel als gelesen markieren…',
),
diff --git a/app/i18n/de/feedback.php b/app/i18n/de/feedback.php
index c20f58487..dc4f679f9 100644
--- a/app/i18n/de/feedback.php
+++ b/app/i18n/de/feedback.php
@@ -53,8 +53,8 @@ return array(
'sub' => array(
'actualize' => 'Aktualisieren',
'articles' => array(
- 'marked_read' => 'The selected articles have been marked as read.', //TODO
- 'marked_unread' => 'The articles have been marked as unread.', //TODO
+ 'marked_read' => 'Die ausgewählten Artikel wurden als gelesen markiert.',
+ 'marked_unread' => 'Die ausgewählten Artikel wurden als ungelesen markiert.',
),
'category' => array(
'created' => 'Die Kategorie %s ist erstellt worden.',
diff --git a/app/i18n/de/gen.php b/app/i18n/de/gen.php
index eb1e74ed6..617b2a494 100644
--- a/app/i18n/de/gen.php
+++ b/app/i18n/de/gen.php
@@ -167,6 +167,7 @@ return array(
'g+' => 'Google+',
'gnusocial' => 'GNU social',
'jdh' => 'Journal du hacker',
+ 'Known' => 'Known-Seite (https://withknown.com)',
'linkedin' => 'LinkedIn',
'mastodon' => 'Mastodon',
'movim' => 'Movim',
@@ -180,7 +181,7 @@ return array(
'short' => array(
'attention' => 'Achtung!',
'blank_to_disable' => 'Zum Deaktivieren frei lassen',
- 'by_author' => 'Von <em>%s</em>',
+ 'by_author' => 'Von:',
'by_default' => 'standardmäßig',
'damn' => 'Verdammt!',
'default_category' => 'Unkategorisiert',
diff --git a/app/i18n/de/index.php b/app/i18n/de/index.php
index 1fa3e3933..2d0dcc2dd 100644
--- a/app/i18n/de/index.php
+++ b/app/i18n/de/index.php
@@ -7,7 +7,7 @@ return array(
'bugs_reports' => 'Fehlerberichte',
'credits' => 'Credits',
'credits_content' => 'Einige Designelemente stammen von <a href="http://twitter.github.io/bootstrap/">Bootstrap</a>, obwohl FreshRSS dieses Framework nicht nutzt. <a href="https://git.gnome.org/browse/gnome-icon-theme-symbolic">Icons</a> stammen vom <a href="https://www.gnome.org/">GNOME project</a>. <em>Open Sans</em> Font wurde von <a href="https://fonts.google.com/specimen/Open+Sans">Steve Matteson</a> erstellt. FreshRSS basiert auf <a href="https://github.com/marienfressinaud/MINZ">Minz</a>, einem PHP-Framework.',
- 'freshrss_description' => 'FreshRSS ist ein RSS-Feedsaggregator zum selbst hosten wie zum Beispiel <a href="http://tontof.net/kriss/feed/">Kriss Feed</a> oder <a href="http://projet.idleman.fr/leed/">Leed</a>. Er ist leicht und einfach zu handhaben und gleichzeitig ein leistungsstarkes und konfigurierbares Werkzeug.',
+ 'freshrss_description' => 'FreshRSS ist ein RSS-Feedsaggregator zum selbst hosten wie zum Beispiel <a href="http://tontof.net/kriss/feed/">Kriss Feed</a> oder <a href="http://leed.idleman.fr/">Leed</a>. Er ist leicht und einfach zu handhaben und gleichzeitig ein leistungsstarkes und konfigurierbares Werkzeug.',
'github' => '<a href="https://github.com/FreshRSS/FreshRSS/issues">on Github</a>',
'license' => 'Lizenz',
'project_website' => 'Projekt-Webseite',
@@ -40,7 +40,7 @@ return array(
'mark_all_read' => 'Alle als gelesen markieren',
'mark_cat_read' => 'Kategorie als gelesen markieren',
'mark_feed_read' => 'Feed als gelesen markieren',
- 'mark_selection_unread' => 'Mark selection as unread', //TODO
+ 'mark_selection_unread' => 'Auswahl als ungelesen markieren',
'newer_first' => 'Neuere zuerst',
'non-starred' => 'Alle außer Favoriten zeigen',
'normal_view' => 'Normale Ansicht',
@@ -53,10 +53,11 @@ return array(
'starred' => 'Nur Favoriten zeigen',
'stats' => 'Statistiken',
'subscription' => 'Abonnementverwaltung',
+ 'tags' => 'My labels', //TODO
'unread' => 'Nur ungelesene zeigen',
),
'share' => 'Teilen',
'tag' => array(
- 'related' => 'Verwandte Tags',
+ 'related' => 'Verwandte Tags', //TODO
),
);
diff --git a/app/i18n/de/install.php b/app/i18n/de/install.php
index d28b22840..d5a28f440 100644
--- a/app/i18n/de/install.php
+++ b/app/i18n/de/install.php
@@ -69,8 +69,8 @@ return array(
'ok' => 'Sie haben eine empfohlene Bibliothek um JSON zu parsen.',
),
'mbstring' => array(
- 'nok' => 'Cannot find the recommended library mbstring for Unicode.', //TODO
- 'ok' => 'You have the recommended library mbstring for Unicode.', //TODO
+ 'nok' => 'Es fehlt die empfohlene mbstring-Bibliothek für Unicode.',
+ 'ok' => 'Sie haben die empfohlene mbstring-Bibliothek für Unicode.',
),
'minz' => array(
'nok' => 'Ihnen fehlt das Minz-Framework.',
diff --git a/app/i18n/de/sub.php b/app/i18n/de/sub.php
index 0ba818c69..6a1100dba 100644
--- a/app/i18n/de/sub.php
+++ b/app/i18n/de/sub.php
@@ -27,6 +27,7 @@ return array(
'password' => 'HTTP-Passwort',
'username' => 'HTTP-Nutzername',
),
+ 'clear_cache' => 'Nicht cachen (für defekte Feeds)',
'css_help' => 'Ruft gekürzte RSS-Feeds ab (Achtung, benötigt mehr Zeit!)',
'css_path' => 'Pfad zur CSS-Datei des Artikels auf der Original-Webseite',
'description' => 'Beschreibung',
@@ -44,10 +45,10 @@ return array(
'main_stream' => 'In Haupt-Feeds zeigen',
'normal' => 'Zeige in eigener Kategorie',
),
- 'ssl_verify' => 'Verify SSL security', //TODO
+ 'ssl_verify' => 'Überprüfe SSL Sicherheit',
'stats' => 'Statistiken',
'think_to_add' => 'Sie können Feeds hinzufügen.',
- 'timeout' => 'Timeout in seconds', //TODO
+ 'timeout' => 'Zeitlimit in Sekunden',
'title' => 'Titel',
'title_add' => 'Einen RSS-Feed hinzufügen',
'ttl' => 'Aktualisiere automatisch nicht öfter als',
diff --git a/app/i18n/en/conf.php b/app/i18n/en/conf.php
index fd91ed8f6..5c128f8e7 100644
--- a/app/i18n/en/conf.php
+++ b/app/i18n/en/conf.php
@@ -19,7 +19,7 @@ return array(
'bottom_line' => 'Bottom line',
'entry' => 'Article icons',
'publication_date' => 'Date of publication',
- 'related_tags' => 'Related tags',
+ 'related_tags' => 'Article tags',
'sharing' => 'Sharing',
'top_line' => 'Top line',
),
diff --git a/app/i18n/en/gen.php b/app/i18n/en/gen.php
index 34e81af2e..9f7da55a5 100644
--- a/app/i18n/en/gen.php
+++ b/app/i18n/en/gen.php
@@ -181,7 +181,7 @@ return array(
'short' => array(
'attention' => 'Warning!',
'blank_to_disable' => 'Leave blank to disable',
- 'by_author' => 'By <em>%s</em>',
+ 'by_author' => 'By:',
'by_default' => 'By default',
'damn' => 'Blast!',
'default_category' => 'Uncategorized',
diff --git a/app/i18n/en/index.php b/app/i18n/en/index.php
index 1c13abdb7..427a769a0 100644
--- a/app/i18n/en/index.php
+++ b/app/i18n/en/index.php
@@ -7,7 +7,7 @@ return array(
'bugs_reports' => 'Bugs reports',
'credits' => 'Credits',
'credits_content' => 'Some design elements come from <a href="http://twitter.github.io/bootstrap/">Bootstrap</a> although FreshRSS doesn’t use this framework. <a href="https://git.gnome.org/browse/gnome-icon-theme-symbolic">Icons</a> come from <a href="https://www.gnome.org/">GNOME project</a>. <em>Open Sans</em> font police has been created by <a href="https://fonts.google.com/specimen/Open+Sans">Steve Matteson</a>. FreshRSS is based on <a href="https://github.com/marienfressinaud/MINZ">Minz</a>, a PHP framework.',
- 'freshrss_description' => 'FreshRSS is a RSS feeds aggregator to self-host like <a href="http://tontof.net/kriss/feed/">Kriss Feed</a> or <a href="http://projet.idleman.fr/leed/">Leed</a>. It is light and easy to take in hand while being powerful and configurable tool.',
+ 'freshrss_description' => 'FreshRSS is a RSS feeds aggregator to self-host like <a href="http://tontof.net/kriss/feed/">Kriss Feed</a> or <a href="http://leed.idleman.fr/">Leed</a>. It is light and easy to take in hand while being powerful and configurable tool.',
'github' => '<a href="https://github.com/FreshRSS/FreshRSS/issues">on Github</a>',
'license' => 'License',
'project_website' => 'Project website',
@@ -53,10 +53,11 @@ return array(
'starred' => 'Show favourites',
'stats' => 'Statistics',
'subscription' => 'Subscriptions management',
+ 'tags' => 'My labels',
'unread' => 'Show unread',
),
'share' => 'Share',
'tag' => array(
- 'related' => 'Related tags',
+ 'related' => 'Article tags', //TODO
),
);
diff --git a/app/i18n/en/sub.php b/app/i18n/en/sub.php
index 5ff41a4b3..22c7edc30 100644
--- a/app/i18n/en/sub.php
+++ b/app/i18n/en/sub.php
@@ -27,6 +27,7 @@ return array(
'password' => 'HTTP password',
'username' => 'HTTP username',
),
+ 'clear_cache' => 'Always clear cache',
'css_help' => 'Retrieves truncated RSS feeds (caution, requires more time!)',
'css_path' => 'Articles CSS path on original website',
'description' => 'Description',
diff --git a/app/i18n/es/conf.php b/app/i18n/es/conf.php
index 0e198caf8..095015d47 100755
--- a/app/i18n/es/conf.php
+++ b/app/i18n/es/conf.php
@@ -19,7 +19,7 @@ return array(
'bottom_line' => 'Línea inferior',
'entry' => 'Iconos de artículos',
'publication_date' => 'Fecha de publicación',
- 'related_tags' => 'Etiquetas relacionadas',
+ 'related_tags' => 'Etiquetas relacionadas', //TODO
'sharing' => 'Compartir',
'top_line' => 'Línea superior',
),
diff --git a/app/i18n/es/gen.php b/app/i18n/es/gen.php
index 4dc1145b2..fe3d62e2d 100755
--- a/app/i18n/es/gen.php
+++ b/app/i18n/es/gen.php
@@ -181,7 +181,7 @@ return array(
'short' => array(
'attention' => '¡Aviso!',
'blank_to_disable' => 'Deja en blanco para desactivar',
- 'by_author' => 'Por <em>%s</em>',
+ 'by_author' => 'Por:',
'by_default' => 'Por defecto',
'damn' => '¡Córcholis!',
'default_category' => 'Sin categorizar',
diff --git a/app/i18n/es/index.php b/app/i18n/es/index.php
index c88152459..1ed6066fb 100755
--- a/app/i18n/es/index.php
+++ b/app/i18n/es/index.php
@@ -7,7 +7,7 @@ return array(
'bugs_reports' => 'Informe de fallos',
'credits' => 'Créditos',
'credits_content' => 'Aunque FreshRSS no usa ese entorno, algunos elementos del diseño están obtenidos de <a href="http://twitter.github.io/bootstrap/">Bootstrap</a>. Los <a href="https://git.gnome.org/browse/gnome-icon-theme-symbolic">Iconos</a> han sido obtenidos del <a href="https://www.gnome.org/">proyecto GNOME</a>. La fuente <em>Open Sans</em> es una creación de <a href="https://fonts.google.com/specimen/Open+Sans">Steve Matteson</a>. FreshRSS usa el entorno PHP <a href="https://github.com/marienfressinaud/MINZ">Minz</a>.',
- 'freshrss_description' => 'FreshRSS es un agregador de fuentes RSS de alojamiento privado al estilo de <a href="http://tontof.net/kriss/feed/">Kriss Feed</a> o <a href="http://projet.idleman.fr/leed/">Leed</a>. Es una herramienta potente, pero ligera y fácil de usar y configurar.',
+ 'freshrss_description' => 'FreshRSS es un agregador de fuentes RSS de alojamiento privado al estilo de <a href="http://tontof.net/kriss/feed/">Kriss Feed</a> o <a href="http://leed.idleman.fr/">Leed</a>. Es una herramienta potente, pero ligera y fácil de usar y configurar.',
'github' => '<a href="https://github.com/FreshRSS/FreshRSS/issues">en Github</a>',
'license' => 'Licencia',
'project_website' => 'Web del proyecto',
@@ -53,10 +53,11 @@ return array(
'starred' => 'Mostrar solo los favoritos',
'stats' => 'Estadísticas',
'subscription' => 'Administración de suscripciones',
+ 'tags' => 'My labels', //TODO
'unread' => 'Mostar solo no leídos',
),
'share' => 'Compartir',
'tag' => array(
- 'related' => 'Etiquetas relacionadas',
+ 'related' => 'Etiquetas relacionadas', //TODO
),
);
diff --git a/app/i18n/es/sub.php b/app/i18n/es/sub.php
index 3abc85578..8a4fb98de 100755
--- a/app/i18n/es/sub.php
+++ b/app/i18n/es/sub.php
@@ -22,6 +22,7 @@ return array(
'password' => 'Contraseña HTTP',
'username' => 'Nombre de usuario HTTP',
),
+ 'clear_cache' => 'Always clear cache', //TODO
'css_help' => 'Recibir fuentes RSS truncadas (aviso, ¡necesita más tiempo!)',
'css_path' => 'Ruta a la CSS de los artículos en la web original',
'description' => 'Descripción',
diff --git a/app/i18n/fr/conf.php b/app/i18n/fr/conf.php
index 52b2f7e0d..01239770b 100644
--- a/app/i18n/fr/conf.php
+++ b/app/i18n/fr/conf.php
@@ -19,7 +19,7 @@ return array(
'bottom_line' => 'Ligne du bas',
'entry' => 'Icônes d’article',
'publication_date' => 'Date de publication',
- 'related_tags' => 'Tags associés',
+ 'related_tags' => 'Tags de l’article',
'sharing' => 'Partage',
'top_line' => 'Ligne du haut',
),
diff --git a/app/i18n/fr/gen.php b/app/i18n/fr/gen.php
index 13e19283f..1e1cef590 100644
--- a/app/i18n/fr/gen.php
+++ b/app/i18n/fr/gen.php
@@ -181,7 +181,7 @@ return array(
'short' => array(
'attention' => 'Attention !',
'blank_to_disable' => 'Laissez vide pour désactiver',
- 'by_author' => 'Par <em>%s</em>',
+ 'by_author' => 'Par :',
'by_default' => 'Par défaut',
'damn' => 'Arf !',
'default_category' => 'Sans catégorie',
diff --git a/app/i18n/fr/index.php b/app/i18n/fr/index.php
index bb0d14faf..c9595e449 100644
--- a/app/i18n/fr/index.php
+++ b/app/i18n/fr/index.php
@@ -7,7 +7,7 @@ return array(
'bugs_reports' => 'Rapports de bugs',
'credits' => 'Crédits',
'credits_content' => 'Des éléments de design sont issus du <a href="http://twitter.github.io/bootstrap/">projet Bootstrap</a> bien que FreshRSS n’utilise pas ce framework. Les <a href="https://git.gnome.org/browse/gnome-icon-theme-symbolic">icônes</a> sont issues du <a href="https://www.gnome.org/">projet GNOME</a>. La police <em>Open Sans</em> utilisée a été créée par <a href="https://fonts.google.com/specimen/Open+Sans">Steve Matteson</a>. FreshRSS repose sur <a href="https://github.com/marienfressinaud/MINZ">Minz</a>, un framework PHP.',
- 'freshrss_description' => 'FreshRSS est un agrégateur de flux RSS à auto-héberger à l’image de <a href="http://tontof.net/kriss/feed/">Kriss Feed</a> ou <a href="http://projet.idleman.fr/leed/">Leed</a>. Il se veut léger et facile à prendre en main tout en étant un outil puissant et paramétrable.',
+ 'freshrss_description' => 'FreshRSS est un agrégateur de flux RSS à auto-héberger à l’image de <a href="http://tontof.net/kriss/feed/">Kriss Feed</a> ou <a href="http://leed.idleman.fr/">Leed</a>. Il se veut léger et facile à prendre en main tout en étant un outil puissant et paramétrable.',
'github' => '<a href="https://github.com/FreshRSS/FreshRSS/issues">sur Github</a>',
'license' => 'Licence',
'project_website' => 'Site du projet',
@@ -53,10 +53,11 @@ return array(
'starred' => 'Afficher les favoris',
'stats' => 'Statistiques',
'subscription' => 'Gestion des abonnements',
+ 'tags' => 'Mes étiquettes',
'unread' => 'Afficher les non-lus',
),
'share' => 'Partager',
'tag' => array(
- 'related' => 'Tags associés',
+ 'related' => 'Tags de l’article',
),
);
diff --git a/app/i18n/fr/sub.php b/app/i18n/fr/sub.php
index c6af2fb90..d3921f1d9 100644
--- a/app/i18n/fr/sub.php
+++ b/app/i18n/fr/sub.php
@@ -27,6 +27,7 @@ return array(
'password' => 'Mot de passe HTTP',
'username' => 'Identifiant HTTP',
),
+ 'clear_cache' => 'Toujours vider le cache',
'css_help' => 'Permet de récupérer les flux tronqués (attention, demande plus de temps !)',
'css_path' => 'Sélecteur CSS des articles sur le site d’origine',
'description' => 'Description',
diff --git a/app/i18n/he/conf.php b/app/i18n/he/conf.php
index a682461a6..2ab8aefa9 100644
--- a/app/i18n/he/conf.php
+++ b/app/i18n/he/conf.php
@@ -19,7 +19,7 @@ return array(
'bottom_line' => 'שורה תחתונה',
'entry' => 'סמלילי מאמרים',
'publication_date' => 'תאריך הפרסום',
- 'related_tags' => 'תגיות קשורות',
+ 'related_tags' => 'תגיות קשורות', //TODO
'sharing' => 'שיתוף',
'top_line' => 'שורה עליונה',
),
diff --git a/app/i18n/he/gen.php b/app/i18n/he/gen.php
index a59f6b178..26b8f99e6 100644
--- a/app/i18n/he/gen.php
+++ b/app/i18n/he/gen.php
@@ -181,7 +181,7 @@ return array(
'short' => array(
'attention' => 'זהירות!',
'blank_to_disable' => 'יש להשאיר ריק על מנת לנטרל',
- 'by_author' => 'מאת <em>%s</em>',
+ 'by_author' => 'מאת :',
'by_default' => 'ברירת מחדל',
'damn' => 'הו לא!',
'default_category' => 'ללא קטגוריה',
diff --git a/app/i18n/he/index.php b/app/i18n/he/index.php
index 8ca6e76f7..d33c09b08 100644
--- a/app/i18n/he/index.php
+++ b/app/i18n/he/index.php
@@ -7,7 +7,7 @@ return array(
'bugs_reports' => 'דיווח באגים',
'credits' => 'קרדיטים',
'credits_content' => 'מאפייני עיצוב מסויימים הגיעו מ <a href="http://twitter.github.io/bootstrap/">Bootstrap</a> אף על פי ש FreshRSS אינו משתמש בתשתית הזו. <a href="https://git.gnome.org/browse/gnome-icon-theme-symbolic">סמלילים</a> הגיעו מ <a href="https://www.gnome.org/"> פרוייקט GNOME </a>. <em>Open Sans</em> הגופן police נוצר על ידי <a href="https://www.google.com/webfonts/specimen/Open+Sans">Steve Matteson</a>. Favicons נאספים בעזרת <a href="https://getfavicon.appspot.com/">getFavicon API</a>. FreshRSS מבוסס על <a href="https://github.com/marienfressinaud/MINZ">Minz</a>, תשתית PHP.',
- 'freshrss_description' => 'FreshRSS הוא קורא RSS לאחסון עצמי בדומה ל <a href="http://tontof.net/kriss/feed/">Kriss Feed</a> או <a href="http://projet.idleman.fr/leed/">Leed</a>. אינו צורך משאבים רבים, וקל לתפעול אך בו בזמן חזק וניתן להתאמה.',
+ 'freshrss_description' => 'FreshRSS הוא קורא RSS לאחסון עצמי בדומה ל <a href="http://tontof.net/kriss/feed/">Kriss Feed</a> או <a href="http://leed.idleman.fr/">Leed</a>. אינו צורך משאבים רבים, וקל לתפעול אך בו בזמן חזק וניתן להתאמה.',
'github' => '<a href="https://github.com/FreshRSS/FreshRSS/issues">בגיטהאב</a>',
'license' => 'רישיון',
'project_website' => 'אתר',
@@ -53,10 +53,11 @@ return array(
'starred' => 'הצגת מועדפים בלבד',
'stats' => 'סטטיסטיקות',
'subscription' => 'ניהול הרשמות',
+ 'tags' => 'My labels', //TODO
'unread' => 'הצגת מאמרים שלא נקראו בלבד',
),
'share' => 'שיתוף',
'tag' => array(
- 'related' => 'תגיות קשורות',
+ 'related' => 'תגיות קשורות', //TODO
),
);
diff --git a/app/i18n/he/sub.php b/app/i18n/he/sub.php
index a263cd728..711004662 100644
--- a/app/i18n/he/sub.php
+++ b/app/i18n/he/sub.php
@@ -27,6 +27,7 @@ return array(
'password' => 'HTTP סיסמה',
'username' => 'HTTP שם משתמש',
),
+ 'clear_cache' => 'Always clear cache', //TODO
'css_help' => 'קבלת הזנות RSS קטומות (זהירות, לוקח זמן רב יותר!)',
'css_path' => 'נתיב הCSS של המאמר באתר המקורי',
'description' => 'תיאור',
diff --git a/app/i18n/it/conf.php b/app/i18n/it/conf.php
index 65b979c51..83beb2df5 100644
--- a/app/i18n/it/conf.php
+++ b/app/i18n/it/conf.php
@@ -19,7 +19,7 @@ return array(
'bottom_line' => 'Barra in fondo',
'entry' => 'Icone degli articoli',
'publication_date' => 'Data di pubblicazione',
- 'related_tags' => 'Tags correlati',
+ 'related_tags' => 'Tags correlati', //TODO
'sharing' => 'Condivisione',
'top_line' => 'Barra in alto',
),
diff --git a/app/i18n/it/gen.php b/app/i18n/it/gen.php
index 2a90693f9..ab17441e7 100644
--- a/app/i18n/it/gen.php
+++ b/app/i18n/it/gen.php
@@ -181,7 +181,7 @@ return array(
'short' => array(
'attention' => 'Attenzione!',
'blank_to_disable' => 'Lascia vuoto per disabilitare',
- 'by_author' => 'di <em>%s</em>',
+ 'by_author' => 'di:',
'by_default' => 'predefinito',
'damn' => 'Ops!',
'default_category' => 'Senza categoria',
diff --git a/app/i18n/it/index.php b/app/i18n/it/index.php
index 718093327..909db1440 100644
--- a/app/i18n/it/index.php
+++ b/app/i18n/it/index.php
@@ -7,7 +7,7 @@ return array(
'bugs_reports' => 'Bugs',
'credits' => 'Crediti',
'credits_content' => 'Alcuni elementi di design provengono da <a href="http://twitter.github.io/bootstrap/">Bootstrap</a> sebbene FreshRSS non usi questo framework. Le <a href="https://git.gnome.org/browse/gnome-icon-theme-symbolic">icone</a> provengono dal progetto <a href="https://www.gnome.org/">GNOME</a>. Il carattere <em>Open Sans</em> è stato creato da <a href="https://fonts.google.com/specimen/Open+Sans">Steve Matteson</a>. FreshRSS è basato su <a href="https://github.com/marienfressinaud/MINZ">Minz</a>, un framework PHP.',
- 'freshrss_description' => 'FreshRSS è un aggregatore di feeds RSS da installare sul proprio host come <a href="http://tontof.net/kriss/feed/">Kriss Feed</a> o <a href="http://projet.idleman.fr/leed/">Leed</a>. Leggero e facile da mantenere pur essendo molto configurabile e potente.',
+ 'freshrss_description' => 'FreshRSS è un aggregatore di feeds RSS da installare sul proprio host come <a href="http://tontof.net/kriss/feed/">Kriss Feed</a> o <a href="http://leed.idleman.fr/">Leed</a>. Leggero e facile da mantenere pur essendo molto configurabile e potente.',
'github' => '<a href="https://github.com/FreshRSS/FreshRSS/issues">su Github</a>',
'license' => 'Licenza',
'project_website' => 'Sito del progetto',
@@ -53,10 +53,11 @@ return array(
'starred' => 'Mostra solo preferiti',
'stats' => 'Statistiche',
'subscription' => 'Gestione sottoscrizioni',
+ 'tags' => 'My labels', //TODO
'unread' => 'Mostra solo non letti',
),
'share' => 'Condividi',
'tag' => array(
- 'related' => 'Tags correlati',
+ 'related' => 'Tags correlati', //TODO
),
);
diff --git a/app/i18n/it/sub.php b/app/i18n/it/sub.php
index 22d58a27f..b22340c9b 100644
--- a/app/i18n/it/sub.php
+++ b/app/i18n/it/sub.php
@@ -27,6 +27,7 @@ return array(
'password' => 'HTTP password',
'username' => 'HTTP username',
),
+ 'clear_cache' => 'Always clear cache', //TODO
'css_help' => 'In caso di RSS feeds troncati (attenzione, richiede molto tempo!)',
'css_path' => 'Percorso del foglio di stile CSS del sito di origine',
'description' => 'Descrizione',
diff --git a/app/i18n/kr/conf.php b/app/i18n/kr/conf.php
index f618d6c96..f26e2cf09 100644
--- a/app/i18n/kr/conf.php
+++ b/app/i18n/kr/conf.php
@@ -19,7 +19,7 @@ return array(
'bottom_line' => '하단',
'entry' => '문서 아이콘',
'publication_date' => '발행일',
- 'related_tags' => '관련 태그',
+ 'related_tags' => '관련 태그', //TODO
'sharing' => '공유',
'top_line' => '상단',
),
diff --git a/app/i18n/kr/gen.php b/app/i18n/kr/gen.php
index e664eaa42..6a461bdac 100644
--- a/app/i18n/kr/gen.php
+++ b/app/i18n/kr/gen.php
@@ -181,7 +181,7 @@ return array(
'short' => array(
'attention' => '경고!',
'blank_to_disable' => '빈 칸으로 두면 비활성화',
- 'by_author' => 'By <em>%s</em>',
+ 'by_author' => 'By:',
'by_default' => '기본값',
'damn' => '이런!',
'default_category' => '분류 없음',
diff --git a/app/i18n/kr/index.php b/app/i18n/kr/index.php
index cb9684dff..87cc12eca 100644
--- a/app/i18n/kr/index.php
+++ b/app/i18n/kr/index.php
@@ -7,7 +7,7 @@ return array(
'bugs_reports' => '버그 제보하기',
'credits' => '크레딧',
'credits_content' => 'FreshRSS는 <a href="http://twitter.github.io/bootstrap/">Bootstrap</a> 프레임워크를 사용하진 않지만, 일부 디자인 요소를 가져왔습니다. <a href="https://git.gnome.org/browse/gnome-icon-theme-symbolic">아이콘들</a>은 <a href="https://www.gnome.org/">GNOME 프로젝트</a>에서 가져왔습니다. <em>Open Sans</em> 글꼴은 <a href="https://fonts.google.com/specimen/Open+Sans">Steve Matteson</a>가 제작하였습니다. FreshRSS는 PHP 프레임워크인 <a href="https://github.com/marienfressinaud/MINZ">Minz</a>에 기반하고 있습니다.',
- 'freshrss_description' => 'FreshRSS는 <a href="http://tontof.net/kriss/feed/">Kriss Feed</a> 또는 <a href="http://projet.idleman.fr/leed/">Leed</a>와 같은 셀프 호스팅 기반의 RSS 피드 수집기입니다. FreshRSS는 강력하고 다양한 설정을 할 수 있으면서 도 가볍고 사용하기 쉽습니다.',
+ 'freshrss_description' => 'FreshRSS는 <a href="http://tontof.net/kriss/feed/">Kriss Feed</a> 또는 <a href="http://leed.idleman.fr/">Leed</a>와 같은 셀프 호스팅 기반의 RSS 피드 수집기입니다. FreshRSS는 강력하고 다양한 설정을 할 수 있으면서 도 가볍고 사용하기 쉽습니다.',
'github' => '<a href="https://github.com/FreshRSS/FreshRSS/issues">Github 저장소에 제보</a>',
'license' => '라이센스',
'project_website' => '프로젝트 웹사이트',
@@ -53,10 +53,11 @@ return array(
'starred' => '즐겨찾기만 표시',
'stats' => '통계',
'subscription' => '구독 관리',
+ 'tags' => 'My labels', //TODO
'unread' => '읽지 않은 글만 표시',
),
'share' => '공유',
'tag' => array(
- 'related' => '관련 태그',
+ 'related' => '관련 태그', //TODO
),
);
diff --git a/app/i18n/kr/sub.php b/app/i18n/kr/sub.php
index de200c330..ee6b25e3f 100644
--- a/app/i18n/kr/sub.php
+++ b/app/i18n/kr/sub.php
@@ -27,6 +27,7 @@ return array(
'password' => 'HTTP 암호',
'username' => 'HTTP 사용자 이름',
),
+ 'clear_cache' => 'Always clear cache', //TODO
'css_help' => '글의 일부가 포함된 RSS 피드를 가져옵니다 (주의, 시간이 좀 더 걸립니다!)',
'css_path' => '웹사이트 상의 글 본문에 해당하는 CSS 경로',
'description' => '설명',
diff --git a/app/i18n/nl/conf.php b/app/i18n/nl/conf.php
index 041b482b9..883d932ab 100644
--- a/app/i18n/nl/conf.php
+++ b/app/i18n/nl/conf.php
@@ -19,7 +19,7 @@ return array(
'bottom_line' => 'Onderaan',
'entry' => 'Artikel pictogrammen',
'publication_date' => 'Publicatie datum',
- 'related_tags' => 'Gerelateerde labels',
+ 'related_tags' => 'Gerelateerde labels', //TODO
'sharing' => 'Delen',
'top_line' => 'Bovenaan',
),
diff --git a/app/i18n/nl/gen.php b/app/i18n/nl/gen.php
index ccbd86579..fdc4338c3 100644
--- a/app/i18n/nl/gen.php
+++ b/app/i18n/nl/gen.php
@@ -181,7 +181,7 @@ return array(
'short' => array(
'attention' => 'Attentie!',
'blank_to_disable' => 'Laat leeg om uit te zetten',
- 'by_author' => 'Door <em>%s</em>',
+ 'by_author' => 'Door:',
'by_default' => 'Door standaard',
'damn' => 'Potverdorie!',
'default_category' => 'Niet ingedeeld',
diff --git a/app/i18n/nl/index.php b/app/i18n/nl/index.php
index 67b3886ea..33fec43c0 100644
--- a/app/i18n/nl/index.php
+++ b/app/i18n/nl/index.php
@@ -7,7 +7,7 @@ return array(
'bugs_reports' => 'Rapporteer fouten',
'credits' => 'Waarderingen',
'credits_content' => 'Sommige ontwerp elementen komen van <a href="http://twitter.github.io/bootstrap/">Bootstrap</a> alhoewel FreshRSS dit raamwerk niet gebruikt. <a href="https://git.gnome.org/browse/gnome-icon-theme-symbolic">Pictogrammen</a> komen van het <a href="https://www.gnome.org/">GNOME project</a>. <em>De Open Sans</em> font police is gemaakt door <a href="https://fonts.google.com/specimen/Open+Sans">Steve Matteson</a>. FreshRSS is gebaseerd op <a href="https://github.com/marienfressinaud/MINZ">Minz</a>, een PHP raamwerk. Nederlandse vertaling door Wanabo, <a href="http://www.nieuwskop.be" title="NieuwsKop">NieuwsKop.be</a>. Link naar de Nederlandse vertaling, <a href="https://github.com/Wanabo/FreshRSS-Dutch-translation/tree/master">FreshRSS-Dutch-translation</a>.',
- 'freshrss_description' => 'FreshRSS is een RSS feed aggregator om zelf te hosten zoals <a href="http://tontof.net/kriss/feed/">Kriss Feed</a> of <a href="http://projet.idleman.fr/leed/">Leed</a>. Het gebruikt weinig systeembronnen en is makkelijk te administreren terwijl het een krachtig en makkelijk te configureren programma is.',
+ 'freshrss_description' => 'FreshRSS is een RSS feed aggregator om zelf te hosten zoals <a href="http://tontof.net/kriss/feed/">Kriss Feed</a> of <a href="http://leed.idleman.fr/">Leed</a>. Het gebruikt weinig systeembronnen en is makkelijk te administreren terwijl het een krachtig en makkelijk te configureren programma is.',
'github' => '<a href="https://github.com/FreshRSS/FreshRSS/issues">op Github</a>',
'license' => 'License',
'project_website' => 'Project website',
@@ -57,6 +57,6 @@ return array(
),
'share' => 'Delen',
'tag' => array(
- 'related' => 'Verwante labels',
+ 'related' => 'Verwante labels', //TODO
),
);
diff --git a/app/i18n/nl/sub.php b/app/i18n/nl/sub.php
index 4ce254ef5..fec7fb4e7 100644
--- a/app/i18n/nl/sub.php
+++ b/app/i18n/nl/sub.php
@@ -27,6 +27,7 @@ return array(
'password' => 'HTTP wachtwoord',
'username' => 'HTTP gebruikers naam',
),
+ 'clear_cache' => 'Always clear cache', //TODO
'css_help' => 'Haalt verstoorde RSS feeds op (attentie, heeft meer tijd nodig!)',
'css_path' => 'Artikelen CSS pad op originele website',
'description' => 'Omschrijving',
diff --git a/app/i18n/pt-br/conf.php b/app/i18n/pt-br/conf.php
index 61a12160c..2547a8624 100644
--- a/app/i18n/pt-br/conf.php
+++ b/app/i18n/pt-br/conf.php
@@ -19,7 +19,7 @@ return array(
'bottom_line' => 'Linha inferior',
'entry' => 'Ícones de artigos',
'publication_date' => 'Data da publicação',
- 'related_tags' => 'Tags relacionadas',
+ 'related_tags' => 'Tags relacionadas', //TODO
'sharing' => 'Compartilhar',
'top_line' => 'Linha superior',
),
diff --git a/app/i18n/pt-br/gen.php b/app/i18n/pt-br/gen.php
index 558482f07..59218597b 100644
--- a/app/i18n/pt-br/gen.php
+++ b/app/i18n/pt-br/gen.php
@@ -180,7 +180,7 @@ return array(
'short' => array(
'attention' => 'Atencão!',
'blank_to_disable' => 'Deixe em branco para desativar',
- 'by_author' => 'Por <em>%s</em>',
+ 'by_author' => 'Por:',
'by_default' => 'Por padrão',
'damn' => 'Buumm!',
'default_category' => 'Sem categoria',
diff --git a/app/i18n/pt-br/index.php b/app/i18n/pt-br/index.php
index 2eff8d948..9f98902ed 100644
--- a/app/i18n/pt-br/index.php
+++ b/app/i18n/pt-br/index.php
@@ -7,7 +7,7 @@ return array(
'bugs_reports' => 'Reportar Bugs',
'credits' => 'Créditos',
'credits_content' => 'Alguns elementos de design vieram do <a href="http://twitter.github.io/bootstrap/">Bootstrap</a> Embora FreshRRS não utiliza este framework. <a href="https://git.gnome.org/browse/gnome-icon-theme-symbolic">Ícones</a> vieram do <a href="https://www.gnome.org/">GNOME project</a>. <em>Open Sans</em> font police foi criada por <a href="https://fonts.google.com/specimen/Open+Sans">Steve Matteson</a>. FreshRSS é baseado no <a href="https://github.com/marienfressinaud/MINZ">Minz</a>, um framework PHP.',
- 'freshrss_description' => 'FreshRSS é um RSS feeds aggregator para um host próprio como o <a href="http://tontof.net/kriss/feed/">Kriss Feed</a> ou <a href="http://projet.idleman.fr/leed/">Leed</a>. É leve e fácil de utilizar enquanto é uma ferramenta poderosa e configurável. ',
+ 'freshrss_description' => 'FreshRSS é um RSS feeds aggregator para um host próprio como o <a href="http://tontof.net/kriss/feed/">Kriss Feed</a> ou <a href="http://leed.idleman.fr/">Leed</a>. É leve e fácil de utilizar enquanto é uma ferramenta poderosa e configurável. ',
'github' => '<a href="https://github.com/FreshRSS/FreshRSS/issues">no Github</a>',
'license' => 'licença',
'project_website' => 'Site do projeto',
@@ -57,6 +57,6 @@ return array(
),
'share' => 'Compartilhar',
'tag' => array(
- 'related' => 'Tags relacionadas',
+ 'related' => 'Tags relacionadas', //TODO
),
);
diff --git a/app/i18n/pt-br/sub.php b/app/i18n/pt-br/sub.php
index 1b084f08f..daa24e8f3 100644
--- a/app/i18n/pt-br/sub.php
+++ b/app/i18n/pt-br/sub.php
@@ -27,6 +27,7 @@ return array(
'password' => 'Senha HTTP',
'username' => 'Usuário HTTP',
),
+ 'clear_cache' => 'Always clear cache', //TODO
'css_help' => 'Retorna RSS feeds truncados (atenção, requer mais tempo!)',
'css_path' => 'Caminho do CSS do artigo no site original',
'description' => 'Descrição',
diff --git a/app/i18n/ru/conf.php b/app/i18n/ru/conf.php
index 90a1a6797..b9d45fb20 100644
--- a/app/i18n/ru/conf.php
+++ b/app/i18n/ru/conf.php
@@ -19,7 +19,7 @@ return array(
'bottom_line' => 'Bottom line',
'entry' => 'Article icons',
'publication_date' => 'Date of publication',
- 'related_tags' => 'Related tags',
+ 'related_tags' => 'Related tags', //TODO
'sharing' => 'Sharing',
'top_line' => 'Top line',
),
diff --git a/app/i18n/ru/gen.php b/app/i18n/ru/gen.php
index 911410a1c..6c8dd2adf 100644
--- a/app/i18n/ru/gen.php
+++ b/app/i18n/ru/gen.php
@@ -181,7 +181,7 @@ return array(
'short' => array(
'attention' => 'Warning!',
'blank_to_disable' => 'Leave blank to disable',
- 'by_author' => 'By <em>%s</em>',
+ 'by_author' => 'By:',
'by_default' => 'By default',
'damn' => 'Damn!',
'default_category' => 'Uncategorized',
diff --git a/app/i18n/ru/index.php b/app/i18n/ru/index.php
index 9bb327786..aaf25a3ab 100644
--- a/app/i18n/ru/index.php
+++ b/app/i18n/ru/index.php
@@ -7,7 +7,7 @@ return array(
'bugs_reports' => 'Bugs reports',
'credits' => 'Credits',
'credits_content' => 'Some design elements come from <a href="http://twitter.github.io/bootstrap/">Bootstrap</a> although FreshRSS doesn’t use this framework. <a href="https://git.gnome.org/browse/gnome-icon-theme-symbolic">Icons</a> come from <a href="https://www.gnome.org/">GNOME project</a>. <em>Open Sans</em> font police has been created by <a href="https://fonts.google.com/specimen/Open+Sans">Steve Matteson</a>. FreshRSS is based on <a href="https://github.com/marienfressinaud/MINZ">Minz</a>, a PHP framework.',
- 'freshrss_description' => 'FreshRSS is a RSS feeds aggregator to self-host like <a href="http://tontof.net/kriss/feed/">Kriss Feed</a> or <a href="http://projet.idleman.fr/leed/">Leed</a>. It is light and easy to take in hand while being powerful and configurable tool.',
+ 'freshrss_description' => 'FreshRSS is a RSS feeds aggregator to self-host like <a href="http://tontof.net/kriss/feed/">Kriss Feed</a> or <a href="http://leed.idleman.fr/">Leed</a>. It is light and easy to take in hand while being powerful and configurable tool.',
'github' => '<a href="https://github.com/FreshRSS/FreshRSS/issues">on Github</a>',
'license' => 'License',
'project_website' => 'Project website',
@@ -57,6 +57,6 @@ return array(
),
'share' => 'Share',
'tag' => array(
- 'related' => 'Related tags',
+ 'related' => 'Article tags', //TODO
),
);
diff --git a/app/i18n/ru/sub.php b/app/i18n/ru/sub.php
index bef49623f..12901998d 100644
--- a/app/i18n/ru/sub.php
+++ b/app/i18n/ru/sub.php
@@ -27,6 +27,7 @@ return array(
'password' => 'HTTP password',// TODO
'username' => 'HTTP username',// TODO
),
+ 'clear_cache' => 'Always clear cache', //TODO
'css_help' => 'Retrieves truncated RSS feeds (caution, requires more time!)',// TODO
'css_path' => 'Articles CSS path on original website',// TODO
'description' => 'Description',// TODO
diff --git a/app/i18n/tr/conf.php b/app/i18n/tr/conf.php
index cae1e4cac..49533bb6a 100644
--- a/app/i18n/tr/conf.php
+++ b/app/i18n/tr/conf.php
@@ -19,7 +19,7 @@ return array(
'bottom_line' => 'Alt çizgi',
'entry' => 'Makale ikonları',
'publication_date' => 'Yayınlama Tarihi',
- 'related_tags' => 'İlgili etiketler',
+ 'related_tags' => 'İlgili etiketler', //TODO
'sharing' => 'Paylaşım',
'top_line' => 'Üst çizgi',
),
diff --git a/app/i18n/tr/gen.php b/app/i18n/tr/gen.php
index 2e1761517..b8dc18c01 100644
--- a/app/i18n/tr/gen.php
+++ b/app/i18n/tr/gen.php
@@ -181,7 +181,7 @@ return array(
'short' => array(
'attention' => 'Tehlike!',
'blank_to_disable' => 'Devredışı bırakmak için boş bırakın',
- 'by_author' => '<em>%s</em> tarafından',
+ 'by_author' => 'Tarafından:',
'by_default' => 'Öntanımlı',
'damn' => 'Hay aksi!',
'default_category' => 'Kategorisiz',
diff --git a/app/i18n/tr/index.php b/app/i18n/tr/index.php
index 1357c05e7..e7db73b96 100644
--- a/app/i18n/tr/index.php
+++ b/app/i18n/tr/index.php
@@ -7,7 +7,7 @@ return array(
'bugs_reports' => 'Hata raporu',
'credits' => 'Tanıtım',
'credits_content' => 'Bu frameworkü kullanmamasına rağmen FreshRSS bazı tasarım ögelerini <a href="http://twitter.github.io/bootstrap/">Bootstrap</a> dan almıştır. <a href="https://git.gnome.org/browse/gnome-icon-theme-symbolic">İkonlar</a> <a href="https://www.gnome.org/">GNOME projesinden</a> alınmıştır. <em>Open Sans</em> yazı tipi <a href="https://fonts.google.com/specimen/Open+Sans">Steve Matteson</a> tarafından oluşturulmuştur. FreshRSS bir PHP framework olan <a href="https://github.com/marienfressinaud/MINZ">Minz</a> i temel alır.',
- 'freshrss_description' => 'FreshRSS <a href="http://tontof.net/kriss/feed/">Kriss Feed</a> veya <a href="http://projet.idleman.fr/leed/">Leed</a> gibi kendi hostunuzda çalışan bir RSS akış toplayıcısıdır. Güçlü ve yapılandırılabilir araçlarıyla basit ve kullanımı kolay bir uygulamadır.',
+ 'freshrss_description' => 'FreshRSS <a href="http://tontof.net/kriss/feed/">Kriss Feed</a> veya <a href="http://leed.idleman.fr/">Leed</a> gibi kendi hostunuzda çalışan bir RSS akış toplayıcısıdır. Güçlü ve yapılandırılabilir araçlarıyla basit ve kullanımı kolay bir uygulamadır.',
'github' => '<a href="https://github.com/FreshRSS/FreshRSS/issues">Github sayfası</a>',
'license' => 'Lisans',
'project_website' => 'Proje sayfası',
@@ -53,10 +53,11 @@ return array(
'starred' => 'Favorileri göster',
'stats' => 'İstatistikler',
'subscription' => 'Abonelik yönetimi',
+ 'tags' => 'My labels', //TODO
'unread' => 'Okunmamışları göster',
),
'share' => 'Share',
'tag' => array(
- 'related' => 'İlgili etiketler',
+ 'related' => 'İlgili etiketler', //TODO
),
);
diff --git a/app/i18n/tr/sub.php b/app/i18n/tr/sub.php
index e8cd15d0d..ef0c8ffbd 100644
--- a/app/i18n/tr/sub.php
+++ b/app/i18n/tr/sub.php
@@ -27,6 +27,7 @@ return array(
'password' => 'HTTP şifre',
'username' => 'HTTP kullanıcı adı',
),
+ 'clear_cache' => 'Always clear cache', //TODO
'css_help' => 'Dikkat, daha çok zaman gerekir!',
'css_path' => 'Makaleleri kendi CSS görünümü ile göster',
'description' => 'Tanım',
diff --git a/app/i18n/zh-cn/conf.php b/app/i18n/zh-cn/conf.php
index 00bea4d79..6c62349c2 100644
--- a/app/i18n/zh-cn/conf.php
+++ b/app/i18n/zh-cn/conf.php
@@ -19,7 +19,7 @@ return array(
'bottom_line' => '底栏',
'entry' => '文章图标',
'publication_date' => '更新日期',
- 'related_tags' => '相关标签',
+ 'related_tags' => '相关标签', //TODO
'sharing' => '分享',
'top_line' => '顶栏',
),
diff --git a/app/i18n/zh-cn/gen.php b/app/i18n/zh-cn/gen.php
index 4ea2d73ab..078e1d378 100644
--- a/app/i18n/zh-cn/gen.php
+++ b/app/i18n/zh-cn/gen.php
@@ -181,7 +181,7 @@ return array(
'short' => array(
'attention' => '警告!',
'blank_to_disable' => '留空以禁用',
- 'by_author' => '作者 <em>%s</em>',
+ 'by_author' => '作者',
'by_default' => '默认',
'damn' => '错误!',
'default_category' => '未分类',
diff --git a/app/i18n/zh-cn/index.php b/app/i18n/zh-cn/index.php
index 2b76961ef..dd8eafda7 100644
--- a/app/i18n/zh-cn/index.php
+++ b/app/i18n/zh-cn/index.php
@@ -7,7 +7,7 @@ return array(
'bugs_reports' => 'Bug 报告',
'credits' => '致谢',
'credits_content' => '某些设计元素来自于 <a href="http://twitter.github.io/bootstrap/">Bootstrap</a> ,尽管 FreshRSS 并没有使用此框架。<a href="https://git.gnome.org/browse/gnome-icon-theme-symbolic">图标</a> 来自于 <a href="https://www.gnome.org/">GNOME 项目</a>。<em>Open Sans</em> 字体出自 <a href="https://fonts.google.com/specimen/Open+Sans">Steve Matteson</a> 之手。FreshRSS 基于 PHP 框架 <a href="https://github.com/marienfressinaud/MINZ">Minz</a>。',
- 'freshrss_description' => 'FreshRSS 是一个自托管的 RSS 聚合服务,类似于 <a href="http://tontof.net/kriss/feed/">Kriss Feed</a> 或 <a href="http://projet.idleman.fr/leed/">Leed</a>。 它不仅轻快又易用,而且强大又易于配置。',
+ 'freshrss_description' => 'FreshRSS 是一个自托管的 RSS 聚合服务,类似于 <a href="http://tontof.net/kriss/feed/">Kriss Feed</a> 或 <a href="http://leed.idleman.fr/">Leed</a>。 它不仅轻快又易用,而且强大又易于配置。',
'github' => '<a href="https://github.com/FreshRSS/FreshRSS/issues">Github Issues</a>',
'license' => '授权',
'project_website' => '项目网站',
@@ -53,10 +53,11 @@ return array(
'starred' => '显示收藏',
'stats' => '统计',
'subscription' => '订阅管理',
+ 'tags' => 'My labels', //TODO
'unread' => '显示未读',
),
'share' => '分享',
'tag' => array(
- 'related' => '相关标签',
+ 'related' => '相关标签', //TODO
),
);
diff --git a/app/i18n/zh-cn/sub.php b/app/i18n/zh-cn/sub.php
index 034f8a9d9..4980b803a 100644
--- a/app/i18n/zh-cn/sub.php
+++ b/app/i18n/zh-cn/sub.php
@@ -27,6 +27,7 @@ return array(
'password' => 'HTTP 密码',
'username' => 'HTTP 用户名',
),
+ 'clear_cache' => 'Always clear cache', //TODO
'css_help' => '用于获取全文(注意,这将耗费更多时间!)',
'css_path' => '原文的 CSS 选择器',
'description' => '描述',
diff --git a/app/install.php b/app/install.php
index eec65be9c..dc79c2388 100644
--- a/app/install.php
+++ b/app/install.php
@@ -343,13 +343,13 @@ function checkDbUser(&$dbOptions) {
try {
$c = new PDO($str, $dbOptions['user'], $dbOptions['password'], $driver_options);
if (defined('SQL_CREATE_TABLES')) {
- $sql = sprintf(SQL_CREATE_TABLES . SQL_CREATE_TABLE_ENTRYTMP . SQL_INSERT_FEEDS,
+ $sql = sprintf(SQL_CREATE_TABLES . SQL_CREATE_TABLE_ENTRYTMP . SQL_CREATE_TABLE_TAGS . SQL_INSERT_FEEDS,
$dbOptions['prefix_user'], _t('gen.short.default_category'));
$stm = $c->prepare($sql);
$ok = $stm && $stm->execute();
} else {
- global $SQL_CREATE_TABLES, $SQL_CREATE_TABLE_ENTRYTMP, $SQL_INSERT_FEEDS;
- $instructions = array_merge($SQL_CREATE_TABLES, $SQL_CREATE_TABLE_ENTRYTMP, $SQL_INSERT_FEEDS);
+ global $SQL_CREATE_TABLES, $SQL_CREATE_TABLE_ENTRYTMP, $SQL_CREATE_TABLE_TAGS, $SQL_INSERT_FEEDS;
+ $instructions = array_merge($SQL_CREATE_TABLES, $SQL_CREATE_TABLE_ENTRYTMP, $SQL_CREATE_TABLE_TAGS, $SQL_INSERT_FEEDS);
$ok = !empty($instructions);
foreach ($instructions as $instruction) {
$sql = sprintf($instruction, $dbOptions['prefix_user'], _t('gen.short.default_category'));
diff --git a/app/layout/aside_feed.phtml b/app/layout/aside_feed.phtml
index 97c0fb0d9..ce029cfa0 100644
--- a/app/layout/aside_feed.phtml
+++ b/app/layout/aside_feed.phtml
@@ -35,6 +35,30 @@
</li>
<?php
+ $t_active = FreshRSS_Context::isCurrentGet('T');
+ ?>
+ <li class="tree-folder category tags<?php echo $t_active ? ' active' : ''; ?>">
+ <div class="tree-folder-title">
+ <a class="dropdown-toggle" href="#"><?php echo _i($t_active ? 'up' : 'down'); ?></a>
+ <a class="title" data-unread="<?php echo format_number($this->nbUnreadTags); ?>" href="<?php echo _url('index', 'index', 'get', 'T'); ?>"><?php echo _t('index.menu.tags'); ?></a>
+ </div>
+ <ul class="tree-folder-items<?php echo $t_active ? ' active' : ''; ?>">
+ <?php
+ foreach ($this->tags as $tag):
+ ?>
+ <li id="t_<?php echo $tag->id(); ?>" class="item feed<?php echo FreshRSS_Context::isCurrentGet('t_' . $tag->id()) ? ' active' : ''; ?>" data-unread="<?php echo $tag->nbUnread(); ?>">
+ <div class="dropdown no-mobile">
+ <div class="dropdown-target"></div>
+ <a class="dropdown-toggle"><?php echo _i('configure'); ?></a>
+ <?php /* tag_config_template */ ?>
+ </div>
+ <?php echo FreshRSS_Themes::alt('label'); ?> <a class="item-title" data-unread="<?php echo format_number($tag->nbUnread()); ?>" href="<?php echo _url('index', 'index', 'get', 't_' . $tag->id()); ?>"><?php echo $tag->name(); ?></a>
+ </li>
+ <?php endforeach; ?>
+ </ul>
+ </li>
+
+ <?php
foreach ($this->categories as $cat) {
$feeds = $cat->feeds();
if (!empty($feeds)) {
@@ -72,6 +96,17 @@
</form>
</div>
+<script id="tag_config_template" type="text/html">
+ <ul class="dropdown-menu">
+ <li class="dropdown-close"><a href="#close">❌</a></li>
+ <li class="item">
+ <button class="as-link confirm" disabled="disabled"
+ form="mark-read-aside" formaction="<?php echo _url('tag', 'delete', 'id_tag', '------'); ?>"
+ type="submit"><?php echo _t('gen.action.remove'); ?></button>
+ </li>
+ </ul>
+</script>
+
<script id="feed_config_template" type="text/html">
<ul class="dropdown-menu">
<li class="dropdown-close"><a href="#close">❌</a></li>
diff --git a/app/layout/layout.phtml b/app/layout/layout.phtml
index 1f11e0af1..2e16672e6 100644
--- a/app/layout/layout.phtml
+++ b/app/layout/layout.phtml
@@ -11,10 +11,6 @@
<?php echo self::headScript(); ?>
<link rel="shortcut icon" id="favicon" type="image/x-icon" sizes="16x16 64x64" href="<?php echo Minz_Url::display('/favicon.ico'); ?>" />
<link rel="icon msapplication-TileImage apple-touch-icon" type="image/png" sizes="256x256" href="<?php echo Minz_Url::display('/themes/icons/favicon-256.png'); ?>" />
- <link rel="prefetch" href="<?php echo FreshRSS_Themes::icon('starred', true); ?>" />
- <link rel="prefetch" href="<?php echo FreshRSS_Themes::icon('non-starred', true); ?>" />
- <link rel="prefetch" href="<?php echo FreshRSS_Themes::icon('read', true); ?>" />
- <link rel="prefetch" href="<?php echo FreshRSS_Themes::icon('unread', true); ?>" />
<link rel="apple-touch-icon" href="<?php echo Minz_Url::display('/themes/icons/apple-touch-icon.png'); ?>" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
@@ -22,24 +18,11 @@
<meta name="msapplication-TileColor" content="#FFF" />
<?php if (!FreshRSS_Context::$system_conf->allow_referrer) { ?>
<meta name="referrer" content="never" />
-<?php
- }
- flush();
- if (isset($this->callbackBeforeContent)) {
- call_user_func($this->callbackBeforeContent, $this);
- }
-?>
+<?php } ?>
<?php echo self::headTitle(); ?>
<?php
$url_base = Minz_Request::currentRequest();
- if (FreshRSS_Context::$next_id !== '') {
- $url_next = $url_base;
- $url_next['params']['next'] = FreshRSS_Context::$next_id;
- $url_next['params']['ajax'] = 1;
-?>
- <link id="prefetch" rel="next prefetch" href="<?php echo Minz_Url::display($url_next); ?>" />
-<?php
- } if (isset($this->rss_title)) {
+ if (isset($this->rss_title)) {
$url_rss = $url_base;
$url_rss['a'] = 'rss';
if (FreshRSS_Context::$user_conf->since_hours_posts_per_rss) {
@@ -54,10 +37,19 @@
<?php } ?>
</head>
<body class="<?php echo Minz_Request::actionName(); ?>">
-<?php $this->partial('header'); ?>
+<?php
+ flush();
+ $this->partial('header');
+?>
<div id="global">
- <?php $this->render(); ?>
+ <?php
+ flush();
+ if (isset($this->callbackBeforeFeeds)) {
+ call_user_func($this->callbackBeforeFeeds, $this);
+ }
+ $this->render();
+ ?>
</div>
<?php
diff --git a/app/views/configure/display.phtml b/app/views/configure/display.phtml
index 414fd2cd6..c6c08e3bc 100644
--- a/app/views/configure/display.phtml
+++ b/app/views/configure/display.phtml
@@ -39,7 +39,7 @@
<?php } ?>
</div>
<div class="properties">
- <div><?php echo sprintf('%s — %s', $theme['name'], _t('gen.short.by_author', $theme['author'])); ?></div>
+ <div><?php echo sprintf('%s — %s %s', $theme['name'], _t('gen.short.by_author'), $theme['author']); ?></div>
<div><?php echo $theme['description'] ?></div>
<div class="page-number"><?php echo sprintf('%d/%d', $i, $slides) ?></div>
</div>
@@ -79,8 +79,8 @@
<th> </th>
<th title="<?php echo _t('gen.action.mark_read'); ?>"><?php echo _i('read'); ?></th>
<th title="<?php echo _t('gen.action.mark_favorite'); ?>"><?php echo _i('bookmark'); ?></th>
- <th><?php echo _t('conf.display.icon.sharing'); ?></th>
<th><?php echo _t('conf.display.icon.related_tags'); ?></th>
+ <th><?php echo _t('conf.display.icon.sharing'); ?></th>
<th><?php echo _t('conf.display.icon.publication_date'); ?></th>
<th><?php echo _i('link'); ?></th>
</tr>
@@ -98,8 +98,8 @@
<th><?php echo _t('conf.display.icon.bottom_line'); ?></th>
<td><input type="checkbox" name="bottomline_read" value="1"<?php echo FreshRSS_Context::$user_conf->bottomline_read ? ' checked="checked"' : ''; ?> data-leave-validation="<?php echo FreshRSS_Context::$user_conf->bottomline_read; ?>"/></td>
<td><input type="checkbox" name="bottomline_favorite" value="1"<?php echo FreshRSS_Context::$user_conf->bottomline_favorite ? ' checked="checked"' : ''; ?> data-leave-validation="<?php echo FreshRSS_Context::$user_conf->bottomline_favorite; ?>"/></td>
- <td><input type="checkbox" name="bottomline_sharing" value="1"<?php echo FreshRSS_Context::$user_conf->bottomline_sharing ? ' checked="checked"' : ''; ?> data-leave-validation="<?php echo FreshRSS_Context::$user_conf->bottomline_sharing; ?>"/></td>
<td><input type="checkbox" name="bottomline_tags" value="1"<?php echo FreshRSS_Context::$user_conf->bottomline_tags ? ' checked="checked"' : ''; ?> data-leave-validation="<?php echo FreshRSS_Context::$user_conf->bottomline_tags; ?>"/></td>
+ <td><input type="checkbox" name="bottomline_sharing" value="1"<?php echo FreshRSS_Context::$user_conf->bottomline_sharing ? ' checked="checked"' : ''; ?> data-leave-validation="<?php echo FreshRSS_Context::$user_conf->bottomline_sharing; ?>"/></td>
<td><input type="checkbox" name="bottomline_date" value="1"<?php echo FreshRSS_Context::$user_conf->bottomline_date ? ' checked="checked"' : ''; ?> data-leave-validation="<?php echo FreshRSS_Context::$user_conf->bottomline_date; ?>"/></td>
<td><input type="checkbox" name="bottomline_link" value="1"<?php echo FreshRSS_Context::$user_conf->bottomline_link ? ' checked="checked"' : ''; ?> data-leave-validation="<?php echo FreshRSS_Context::$user_conf->bottomline_link; ?>"/></td>
</tr>
diff --git a/app/views/entry/read.phtml b/app/views/entry/read.phtml
index 73977d94b..fb9e129f2 100755
--- a/app/views/entry/read.phtml
+++ b/app/views/entry/read.phtml
@@ -12,5 +12,6 @@ $url['params']['is_read'] = Minz_Request::param('is_read', true) ? '0' : '1';
FreshRSS::loadStylesAndScripts();
echo json_encode(array(
'url' => str_ireplace('&amp;', '&', Minz_Url::display($url)),
- 'icon' => _i($url['params']['is_read'] === '1' ? 'unread' : 'read')
+ 'icon' => _i($url['params']['is_read'] === '1' ? 'unread' : 'read'),
+ 'tags' => $this->tags,
));
diff --git a/app/views/helpers/export/articles.phtml b/app/views/helpers/export/articles.phtml
index 75651483a..b8958f527 100644
--- a/app/views/helpers/export/articles.phtml
+++ b/app/views/helpers/export/articles.phtml
@@ -34,7 +34,7 @@ foreach ($this->entriesRaw as $entryRaw) {
'id' => $entry->guid(),
'categories' => array_values($entry->tags()),
'title' => $entry->title(),
- 'author' => $entry->author(),
+ 'author' => $entry->authors(true), //TODO: Make an array like tags?
'published' => $entry->date(true),
'updated' => $entry->date(true),
'alternate' => array(array(
diff --git a/app/views/helpers/extension/configure.phtml b/app/views/helpers/extension/configure.phtml
index 95d968aba..cde872aa0 100644
--- a/app/views/helpers/extension/configure.phtml
+++ b/app/views/helpers/extension/configure.phtml
@@ -5,7 +5,7 @@
: _t('admin.extensions.disabled'); ?>
</h1>
- <p class="alert alert-warn"><?php echo $this->extension->getDescription(); ?> — <?php echo _t('gen.short.by_author', $this->extension->getAuthor()); ?></p>
+ <p class="alert alert-warn"><?php echo $this->extension->getDescription(); ?> — <?php echo _t('gen.short.by_author'), ' ', $this->extension->getAuthor(); ?></p>
<h2><?php echo _t('gen.action.manage'); ?></h2>
<?php
diff --git a/app/views/helpers/feed/update.phtml b/app/views/helpers/feed/update.phtml
index 7144aab46..4dbaacd04 100644
--- a/app/views/helpers/feed/update.phtml
+++ b/app/views/helpers/feed/update.phtml
@@ -205,6 +205,13 @@
</div>
</div>
+ <div class="form-group">
+ <label class="group-name" for="clear_cache"><?php echo _t('sub.feed.clear_cache'); ?></label>
+ <div class="group-controls">
+ <input type="checkbox" name="clear_cache" id="clear_cache" value="1"<?php echo $this->feed->attributes('clear_cache') ? ' checked="checked"' : ''; ?> />
+ </div>
+ </div>
+
<?php if (FreshRSS_Auth::hasAccess('admin')) { ?>
<div class="form-group">
<label class="group-name" for="timeout"><?php echo _t('sub.feed.timeout'); ?></label>
diff --git a/app/views/helpers/index/normal/entry_bottom.phtml b/app/views/helpers/index/normal/entry_bottom.phtml
index 6417da4cb..784a41e1f 100644
--- a/app/views/helpers/index/normal/entry_bottom.phtml
+++ b/app/views/helpers/index/normal/entry_bottom.phtml
@@ -7,6 +7,7 @@
$bottomline_read = FreshRSS_Context::$user_conf->bottomline_read;
$bottomline_favorite = FreshRSS_Context::$user_conf->bottomline_favorite;
$bottomline_sharing = FreshRSS_Context::$user_conf->bottomline_sharing && (count($sharing) > 0);
+ $bottomline_labels = true; //TODO
$bottomline_tags = FreshRSS_Context::$user_conf->bottomline_tags;
$bottomline_date = FreshRSS_Context::$user_conf->bottomline_date;
$bottomline_link = FreshRSS_Context::$user_conf->bottomline_link;
@@ -32,8 +33,41 @@
echo _i($this->entry->isFavorite() ? 'starred' : 'non-starred'); ?></a><?php
?></li><?php
}
- } ?>
- <li class="item"><?php
+ }
+ if ($bottomline_labels) {
+ ?><li class="item">
+ <div class="dropdown dynamictags">
+ <div id="dropdown-labels-<?php echo $this->entry->id();?>" class="dropdown-target"></div>
+ <?php echo FreshRSS_Themes::alt('label'); ?>
+ <a class="dropdown-toggle" href="#dropdown-labels-<?php echo $this->entry->id();?>"><?php
+ echo _t('index.menu.tags');
+ ?></a>
+ <ul class="dropdown-menu">
+ <li class="dropdown-close"><a href="#close">❌</a></li>
+ <!-- Ajax -->
+ </ul>
+ </div>
+ </li><?php
+ }
+ $tags = $bottomline_tags ? $this->entry->tags() : null;
+ if (!empty($tags)) {
+ ?><li class="item">
+ <div class="dropdown">
+ <div id="dropdown-tags-<?php echo $this->entry->id();?>" class="dropdown-target"></div>
+ <?php echo _i('tag'); ?>
+ <a class="dropdown-toggle" href="#dropdown-tags-<?php echo $this->entry->id();?>"><?php
+ echo _t('index.tag.related');
+ ?></a>
+ <ul class="dropdown-menu">
+ <li class="dropdown-close"><a href="#close">❌</a></li><?php
+ foreach ($tags as $tag) {
+ ?><li class="item"><a href="<?php echo _url('index', 'index', 'search', '#' . str_replace(' ', '+', htmlspecialchars_decode($tag, ENT_QUOTES))); ?>"><?php echo $tag; ?></a></li><?php
+ } ?>
+ </ul>
+ </div>
+ </li><?php
+ }
+ ?><li class="item"><?php
if ($bottomline_sharing) {
?><div class="dropdown">
<div id="dropdown-share-<?php echo $this->entry->id();?>" class="dropdown-target"></div>
@@ -69,24 +103,6 @@
</div>
<?php } ?>
</li><?php
- $tags = $bottomline_tags ? $this->entry->tags() : null;
- if (!empty($tags)) {
- ?><li class="item">
- <div class="dropdown">
- <div id="dropdown-tags-<?php echo $this->entry->id();?>" class="dropdown-target"></div>
- <?php echo _i('tag'); ?>
- <a class="dropdown-toggle" href="#dropdown-tags-<?php echo $this->entry->id();?>"><?php
- echo _t('index.tag.related');
- ?></a>
- <ul class="dropdown-menu">
- <li class="dropdown-close"><a href="#close">❌</a></li><?php
- foreach($tags as $tag) {
- ?><li class="item"><a href="<?php echo _url('index', 'index', 'search', '#' . htmlspecialchars_decode($tag, ENT_QUOTES)); ?>"><?php echo $tag; ?></a></li><?php
- } ?>
- </ul>
- </div>
- </li><?php
- }
if ($bottomline_date) {
?><li class="item date"><?php echo $this->entry->date(); ?></li><?php
}
diff --git a/app/views/index/global.phtml b/app/views/index/global.phtml
index 2f25b6dc2..3566abe7e 100644
--- a/app/views/index/global.phtml
+++ b/app/views/index/global.phtml
@@ -1,6 +1,11 @@
<?php
$this->partial('nav_menu');
+ flush();
+ if (isset($this->callbackBeforeEntries)) {
+ call_user_func($this->callbackBeforeEntries, $this);
+ }
+
$class = '';
if (FreshRSS_Context::$user_conf->hide_read_feeds &&
FreshRSS_Context::isStateEnabled(FreshRSS_Entry::STATE_NOT_READ) &&
diff --git a/app/views/index/normal.phtml b/app/views/index/normal.phtml
index c7cab2d3f..d5ae8e2f9 100644
--- a/app/views/index/normal.phtml
+++ b/app/views/index/normal.phtml
@@ -3,6 +3,11 @@
$this->partial('aside_feed');
$this->partial('nav_menu');
+flush();
+if (isset($this->callbackBeforeEntries)) {
+ call_user_func($this->callbackBeforeEntries, $this);
+}
+
if (!empty($this->entries)) {
$display_today = true;
$display_yesterday = true;
@@ -20,7 +25,7 @@ if (!empty($this->entries)) {
</div><?php
foreach ($this->entries as $item) {
$this->entry = Minz_ExtensionManager::callHook('entry_before_display', $item);
- if (is_null($this->entry)) {
+ if ($this->entry == null) {
continue;
}
@@ -67,10 +72,19 @@ if (!empty($this->entries)) {
?><div class="flux_content">
<div class="content <?php echo $content_width; ?>">
<h1 class="title"><a target="_blank" rel="noreferrer" class="go_website" href="<?php echo $this->entry->link(); ?>"><?php echo $this->entry->title(); ?></a></h1>
- <?php
- $author = $this->entry->author();
- echo $author != '' ? '<div class="author">' . _t('gen.short.by_author', $author) . '</div>' : '',
- $lazyload && $hidePosts ? lazyimg($this->entry->content()) : $this->entry->content();
+ <div class="author"><?php
+ $authors = $this->entry->authors();
+ if (is_array($authors)):
+ $first = true;
+ foreach ($authors as $author):
+ echo $first ? _t('gen.short.by_author') . ' ' : '· ';
+ $first = false;
+ ?>
+<em><a href="<?php echo _url('index', 'index', 'search', 'author:' . str_replace(' ', '+', htmlspecialchars_decode($author, ENT_QUOTES))); ?>"><?php echo $author; ?></a></em>
+ <?php endforeach; ?>
+ </div><?php
+ endif;
+ echo $lazyload && $hidePosts ? lazyimg($this->entry->content()) : $this->entry->content();
?>
</div><?php
diff --git a/app/views/index/reader.phtml b/app/views/index/reader.phtml
index eb6613b28..c15b936ee 100644
--- a/app/views/index/reader.phtml
+++ b/app/views/index/reader.phtml
@@ -1,6 +1,11 @@
<?php
$this->partial('nav_menu');
+flush();
+if (isset($this->callbackBeforeEntries)) {
+ call_user_func($this->callbackBeforeEntries, $this);
+}
+
if (!empty($this->entries)) {
$lazyload = FreshRSS_Context::$user_conf->lazyload;
$content_width = FreshRSS_Context::$user_conf->content_width;
@@ -39,9 +44,19 @@ if (!empty($this->entries)) {
<h1 class="title"><a target="_blank" rel="noreferrer" class="go_website" href="<?php echo $item->link(); ?>"><?php echo $item->title(); ?></a></h1>
<div class="author"><?php
- $author = $item->author();
- echo $author != '' ? _t('gen.short.by_author', $author) . ' — ' : '',
- $item->date();
+ $authors = $item->authors();
+ if (is_array($authors)):
+ $first = true;
+ foreach ($authors as $author):
+ echo $first ? _t('gen.short.by_author') . ' ' : '· ';
+ $first = false;
+ ?>
+<em><a href="<?php echo _url('index', 'index', 'search', 'author:' . str_replace(' ', '+', htmlspecialchars_decode($author, ENT_QUOTES))); ?>"><?php echo $author; ?></a></em>
+ <?php
+ endforeach;
+ echo ' — ';
+ endif;
+ echo $item->date();
?></div>
<?php echo $item->content(); ?>
diff --git a/app/views/index/rss.phtml b/app/views/index/rss.phtml
index 86074517c..104e03d15 100755
--- a/app/views/index/rss.phtml
+++ b/app/views/index/rss.phtml
@@ -13,10 +13,20 @@ foreach ($this->entries as $item) {
<item>
<title><?php echo $item->title(); ?></title>
<link><?php echo $item->link(); ?></link>
- <?php $author = $item->author(); ?>
- <?php if ($author != '') { ?>
- <dc:creator><?php echo $author; ?></dc:creator>
- <?php } ?>
+ <?php
+ $authors = $item->authors();
+ if (is_array($authors)) {
+ foreach ($authors as $author) {
+ echo "\t\t\t" , '<author>', $author, '</author>', "\n";
+ }
+ }
+ $categories = $item->tags();
+ if (is_array($categories)) {
+ foreach ($categories as $category) {
+ echo "\t\t\t" , '<category>', $category, '</category>', "\n";
+ }
+ }
+ ?>
<description><![CDATA[<?php
echo $item->content();
?>]]></description>
diff --git a/app/views/javascript/nbUnreadsPerFeed.phtml b/app/views/javascript/nbUnreadsPerFeed.phtml
index 68f98ce9e..ce4db37b7 100644
--- a/app/views/javascript/nbUnreadsPerFeed.phtml
+++ b/app/views/javascript/nbUnreadsPerFeed.phtml
@@ -1,8 +1,14 @@
<?php
-$result = array();
+$result = array(
+ 'feeds' => array(),
+ 'tags' => array(),
+);
foreach ($this->categories as $cat) {
foreach ($cat->feeds() as $feed) {
- $result[$feed->id()] = $feed->nbNotRead();
+ $result['feeds'][$feed->id()] = $feed->nbNotRead();
}
}
+foreach ($this->tags as $tag) {
+ $result['tags'][$tag->id()] = $tag->nbUnread();
+}
echo json_encode($result);
diff --git a/app/views/tag/getTagsForEntry.phtml b/app/views/tag/getTagsForEntry.phtml
new file mode 100644
index 000000000..76b2ada4e
--- /dev/null
+++ b/app/views/tag/getTagsForEntry.phtml
@@ -0,0 +1,2 @@
+<?php
+echo json_encode($this->tags);
diff --git a/cli/README.md b/cli/README.md
index c314bd388..148e15be5 100644
--- a/cli/README.md
+++ b/cli/README.md
@@ -72,7 +72,7 @@ cd /usr/share/FreshRSS
# --user can be a username, or '*' to loop on all users
# Returns: 1) a * iff the user is admin, 2) the name of the user,
# 3) the date/time of last user action, 4) the size occupied,
-# and the number of: 5) categories, 6) feeds, 7) read articles, 8) unread articles, and 9) favourites
+# and the number of: 5) categories, 6) feeds, 7) read articles, 8) unread articles, 9) favourites, and 10) tags
./cli/db-optimize.php --user username
# Optimize database (reduces the size) for a given user (perform `OPTIMIZE TABLE` in MySQL, `VACUUM` in SQLite)
diff --git a/cli/user-info.php b/cli/user-info.php
index 18a415217..043bebf7c 100755
--- a/cli/user-info.php
+++ b/cli/user-info.php
@@ -16,9 +16,10 @@ foreach ($users as $username) {
$username = cliInitUser($username);
echo $username === FreshRSS_Context::$system_conf->default_user ? '*' : ' ', "\t";
- $catDAO = new FreshRSS_CategoryDAO();
+ $catDAO = FreshRSS_Factory::createCategoryDao();
$feedDAO = FreshRSS_Factory::createFeedDao($username);
$entryDAO = FreshRSS_Factory::createEntryDao($username);
+ $tagDAO = FreshRSS_Factory::createTagDao($username);
$databaseDAO = FreshRSS_Factory::createDatabaseDAO($username);
$nbEntries = $entryDAO->countUnreadRead();
@@ -34,6 +35,7 @@ foreach ($users as $username) {
$nbEntries['read'], " reads\t",
$nbEntries['unread'], " unreads\t",
$nbFavorites['all'], " favourites\t",
+ $tagDAO->count(), " tags\t",
"\n";
} else {
echo
@@ -45,6 +47,7 @@ foreach ($users as $username) {
$nbEntries['read'], "\t",
$nbEntries['unread'], "\t",
$nbFavorites['all'], "\t",
+ $tagDAO->count(), "\t",
"\n";
}
}
diff --git a/constants.php b/constants.php
index 2bd64708f..2740dc63d 100644
--- a/constants.php
+++ b/constants.php
@@ -2,7 +2,7 @@
//NB: Do not edit; use ./constants.local.php instead.
//<Not customisable>
-define('FRESHRSS_VERSION', '1.11.2');
+define('FRESHRSS_VERSION', '1.12.0');
define('FRESHRSS_WEBSITE', 'https://freshrss.org');
define('FRESHRSS_WIKI', 'https://freshrss.github.io/FreshRSS/');
diff --git a/data/users/.gitignore b/data/users/.gitignore
index 3705c06b7..03ee0bd34 100644
--- a/data/users/.gitignore
+++ b/data/users/.gitignore
@@ -1,5 +1,5 @@
*/
*/config.php
-*/db.sqlite
+*/*.sqlite
!_/
*/log*.txt
diff --git a/docs/en/admins/02_Installation.md b/docs/en/admins/02_Installation.md
index 9bf800969..7d001c3e4 100644
--- a/docs/en/admins/02_Installation.md
+++ b/docs/en/admins/02_Installation.md
@@ -122,7 +122,7 @@ server {
# php files handling
# this regex is mandatory because of the API
location ~ ^.+?\.php(/.*)?$ {
- fastcgi_pass unix:/var/run/php5-fpm.sock;
+ fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
# By default, the variable PATH_INFO is not set under PHP-FPM
# But FreshRSS API greader.php need it. If you have a “Bad Request” error, double check this var!
diff --git a/docs/en/users/06_Fever_API.md b/docs/en/users/06_Fever_API.md
index 7d2af8b02..971cf957d 100644
--- a/docs/en/users/06_Fever_API.md
+++ b/docs/en/users/06_Fever_API.md
@@ -23,6 +23,7 @@ Tested with:
- iOS
- [Fiery Feeds](https://itunes.apple.com/app/fiery-feeds-rss-reader/id1158763303)
- [Unread](https://itunes.apple.com/app/unread-rss-reader/id1252376153)
+ - [Reeder-3](https://itunes.apple.com/app/reeder-3/id697846300)
- MacOS
- [Readkit](https://itunes.apple.com/app/readkit/id588726889)
diff --git a/docs/fr/users/01_Installation.md b/docs/fr/users/01_Installation.md
index de4e687b7..7901aa698 100644
--- a/docs/fr/users/01_Installation.md
+++ b/docs/fr/users/01_Installation.md
@@ -119,7 +119,7 @@ server {
# gestion des fichiers php
# il est nécessaire d’utiliser cette expression régulière pour le bon fonctionnement de l’API
location ~ ^.+?\.php(/.*)?$ {
- fastcgi_pass unix:/var/run/php5-fpm.sock;
+ fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
# Par défaut la variable PATH_INFO n’est pas définie sous PHP-FPM
# or l’API FreshRSS greader.php en a besoin. Si vous avez un “Bad Request”, vérifiez bien cette dernière !
diff --git a/docs/fr/users/06_Fever_API.md b/docs/fr/users/06_Fever_API.md
index 6ad817041..50650ebcd 100644
--- a/docs/fr/users/06_Fever_API.md
+++ b/docs/fr/users/06_Fever_API.md
@@ -10,6 +10,7 @@ Testé avec:
- iOS
- [Fiery Feeds](https://itunes.apple.com/app/fiery-feeds-rss-reader/id1158763303)
- [Unread](https://itunes.apple.com/app/unread-rss-reader/id1252376153)
+ - [Reeder-3](https://itunes.apple.com/app/reeder-3/id697846300)
- MacOS
- [Readkit](https://itunes.apple.com/app/readkit/id588726889)
diff --git a/extensions/Tumblr-GDPR/extension.php b/extensions/Tumblr-GDPR/extension.php
index 7a7708c9f..83bdf2189 100644
--- a/extensions/Tumblr-GDPR/extension.php
+++ b/extensions/Tumblr-GDPR/extension.php
@@ -7,7 +7,7 @@ class TumblrGdprExtension extends Minz_Extension {
public static function curlHook($simplePie, $feed) {
if (preg_match('#^https?://[a-zA-Z_0-9-]+.tumblr.com/#i', $feed->url())) {
- $simplePie->set_useragent(FRESHRSS_USERAGENT . ' like Googlebot');
+ $simplePie->set_useragent(FRESHRSS_USERAGENT . ' like Baiduspider');
}
}
}
diff --git a/lib/Minz/Request.php b/lib/Minz/Request.php
index e21697e42..24e30546f 100644
--- a/lib/Minz/Request.php
+++ b/lib/Minz/Request.php
@@ -129,6 +129,8 @@ class Minz_Request {
if (!empty($_SERVER['HTTP_X_FORWARDED_PORT'])) {
$port = intval($_SERVER['HTTP_X_FORWARDED_PORT']);
+ } elseif (!empty($_SERVER['HTTP_X_FORWARDED_PROTO'])) {
+ $port = strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) === 'https' ? 443 : 80;
} elseif (!empty($_SERVER['SERVER_PORT'])) {
$port = intval($_SERVER['SERVER_PORT']);
} else {
diff --git a/lib/lib_rss.php b/lib/lib_rss.php
index 44123b746..4087f6faf 100644
--- a/lib/lib_rss.php
+++ b/lib/lib_rss.php
@@ -125,9 +125,8 @@ function server_is_public($address) {
));
if ($is_public) {
- $ip = gethostbyname($host);
- $is_public &= !preg_match('/^(10|127|172[.]16|192[.]168)[.]/', $ip);
- $is_public &= !preg_match('/^(\[)?(::1$|fc00::|fe80::)/i', $ip);
+ $is_public &= !preg_match('/^(10|127|172[.]16|192[.]168)[.]/', $host);
+ $is_public &= !preg_match('/^(\[)?(::1$|fc00::|fe80::)/i', $host);
}
return (bool)$is_public;
@@ -450,6 +449,9 @@ function check_install_database() {
'categories' => false,
'feeds' => false,
'entries' => false,
+ 'entrytmp' => false,
+ 'tag' => false,
+ 'entrytag' => false,
);
try {
@@ -459,6 +461,9 @@ function check_install_database() {
$status['categories'] = $dbDAO->categoryIsCorrect();
$status['feeds'] = $dbDAO->feedIsCorrect();
$status['entries'] = $dbDAO->entryIsCorrect();
+ $status['entrytmp'] = $dbDAO->entrytmpIsCorrect();
+ $status['tag'] = $dbDAO->tagIsCorrect();
+ $status['entrytag'] = $dbDAO->entrytagIsCorrect();
} catch(Minz_PDOConnectionException $e) {
$status['connection'] = false;
}
diff --git a/p/api/fever.php b/p/api/fever.php
index 55baa6d16..dd54a372b 100644
--- a/p/api/fever.php
+++ b/p/api/fever.php
@@ -3,6 +3,7 @@
* Fever API for FreshRSS
* Version 0.1
* Author: Kevin Papst / https://github.com/kevinpapst
+ * Documentation: https://feedafever.com/api
*
* Inspired by:
* TinyTinyRSS Fever API plugin @dasmurphy
@@ -29,6 +30,36 @@ register_shutdown_function('session_destroy');
Minz_Session::init('FreshRSS');
// ================================================================================================
+// <Debug>
+$ORIGINAL_INPUT = file_get_contents('php://input', false, null, 0, 1048576);
+
+function debugInfo() {
+ if (function_exists('getallheaders')) {
+ $ALL_HEADERS = getallheaders();
+ } else { //nginx http://php.net/getallheaders#84262
+ $ALL_HEADERS = array();
+ foreach ($_SERVER as $name => $value) {
+ if (substr($name, 0, 5) === 'HTTP_') {
+ $ALL_HEADERS[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;
+ }
+ }
+ }
+ global $ORIGINAL_INPUT;
+ return print_r(
+ array(
+ 'date' => date('c'),
+ 'headers' => $ALL_HEADERS,
+ '_SERVER' => $_SERVER,
+ '_GET' => $_GET,
+ '_POST' => $_POST,
+ '_COOKIE' => $_COOKIE,
+ 'INPUT' => $ORIGINAL_INPUT
+ ), true);
+}
+
+//Minz_Log::debug('----------------------------------------------------------------', API_LOG);
+//Minz_Log::debug(debugInfo(), API_LOG);
+// </Debug>
class FeverDAO extends Minz_ModelPdo
{
@@ -63,7 +94,7 @@ class FeverDAO extends Minz_ModelPdo
$sql = 'SELECT id, guid, title, author, '
. ($entryDAO->isCompressed() ? 'UNCOMPRESS(content_bin) AS content' : 'content')
- . ', link, date, is_read, is_favorite, id_feed, tags '
+ . ', link, date, is_read, is_favorite, id_feed '
. 'FROM `' . $this->prefix . 'entry` WHERE';
if (!empty($entry_ids)) {
@@ -311,7 +342,7 @@ class FeverAPI
{
$groups = array();
- $categoryDAO = new FreshRSS_CategoryDAO();
+ $categoryDAO = FreshRSS_Factory::createCategoryDao();
$categories = $categoryDAO->listCategories(false, false);
/** @var FreshRSS_Category $category */
@@ -456,7 +487,7 @@ class FeverAPI
}
if (isset($_REQUEST['group_ids'])) {
- $categoryDAO = new FreshRSS_CategoryDAO();
+ $categoryDAO = FreshRSS_Factory::createCategoryDao();
$group_ids = explode(',', $_REQUEST['group_ids']);
foreach ($group_ids as $id) {
/** @var FreshRSS_Category $category */
@@ -495,17 +526,17 @@ class FeverAPI
// Load list of extensions and enable the "system" ones.
Minz_ExtensionManager::init();
- foreach($entries as $item) {
+ foreach ($entries as $item) {
/** @var FreshRSS_Entry $entry */
$entry = Minz_ExtensionManager::callHook('entry_before_display', $item);
- if (is_null($entry)) {
+ if ($entry == null) {
continue;
}
$items[] = array(
'id' => $entry->id(),
'feed_id' => $entry->feed(false),
'title' => $entry->title(),
- 'author' => $entry->author(),
+ 'author' => $entry->authors(true),
'html' => $entry->content(),
'url' => $entry->link(),
'is_saved' => $entry->isFavorite() ? 1 : 0,
diff --git a/p/api/greader.php b/p/api/greader.php
index 4affc2826..c6701096c 100644
--- a/p/api/greader.php
+++ b/p/api/greader.php
@@ -18,6 +18,7 @@ Server-side API compatible with Google Reader API layer 2
* https://github.com/ericmann/gReader-Library/blob/master/greader.class.php
* https://github.com/devongovett/reader
* https://github.com/theoldreader/api
+* https://www.inoreader.com/developers/
*/
require(__DIR__ . '/../../constants.php');
@@ -41,6 +42,12 @@ if (PHP_INT_SIZE < 8) { //32-bit
}
}
+if (version_compare(PHP_VERSION, '5.4.0') >= 0) {
+ define('JSON_OPTIONS', JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
+} else {
+ define('JSON_OPTIONS', 0);
+}
+
function headerVariable($headerName, $varName) {
$header = '';
$upName = 'HTTP_' . strtoupper($headerName);
@@ -233,7 +240,7 @@ function userInfo() { //https://github.com/theoldreader/api#user-info
'userName' => $user,
'userProfileId' => $user,
'userEmail' => FreshRSS_Context::$user_conf->mail_login,
- )));
+ ), JSON_OPTIONS));
}
function tagList() {
@@ -253,10 +260,24 @@ function tagList() {
$tags[] = array(
'id' => 'user/-/label/' . $cName,
//'sortid' => $cName,
+ 'type' => 'folder', //Inoreader
);
}
- echo json_encode(array('tags' => $tags)), "\n";
+ unset($res);
+
+ $tagDAO = FreshRSS_Factory::createTagDao();
+ $labels = $tagDAO->listTags(true);
+ foreach ($labels as $label) {
+ $tags[] = array(
+ 'id' => 'user/-/label/' . $label->name(),
+ //'sortid' => $cName,
+ 'type' => 'tag', //Inoreader
+ 'unread_count' => $label->nbUnread(), //Inoreader
+ );
+ }
+
+ echo json_encode(array('tags' => $tags), JSON_OPTIONS), "\n";
exit();
}
@@ -292,7 +313,7 @@ function subscriptionList() {
);
}
- echo json_encode(array('subscriptions' => $subscriptions)), "\n";
+ echo json_encode(array('subscriptions' => $subscriptions), JSON_OPTIONS), "\n";
exit();
}
@@ -309,7 +330,7 @@ function subscriptionEdit($streamNames, $titles, $action, $add = '', $remove = '
$addCatId = 0;
$categoryDAO = null;
if ($add != '' || $remove != '') {
- $categoryDAO = new FreshRSS_CategoryDAO();
+ $categoryDAO = FreshRSS_Factory::createCategoryDao();
}
$c_name = '';
if ($add != '' && strpos($add, 'user/') === 0) { //user/-/label/Example ; user/username/label/Example
@@ -390,13 +411,13 @@ function quickadd($url) {
exit(json_encode(array(
'numResults' => 1,
'streamId' => $feed->id(),
- )));
+ ), JSON_OPTIONS));
} catch (Exception $e) {
Minz_Log::error('quickadd error: ' . $e->getMessage(), API_LOG);
die(json_encode(array(
'numResults' => 0,
'error' => $e->getMessage(),
- )));
+ ), JSON_OPTIONS));
}
}
@@ -406,7 +427,7 @@ function unreadCount() { //http://blog.martindoms.com/2009/10/16/using-the-googl
$totalUnreads = 0;
$totalLastUpdate = 0;
- $categoryDAO = new FreshRSS_CategoryDAO();
+ $categoryDAO = FreshRSS_Factory::createCategoryDao();
foreach ($categoryDAO->listCategories(true, true) as $cat) {
$catLastUpdate = 0;
foreach ($cat->feeds() as $feed) {
@@ -431,6 +452,14 @@ function unreadCount() { //http://blog.martindoms.com/2009/10/16/using-the-googl
}
}
+ $tagDAO = FreshRSS_Factory::createTagDao();
+ foreach ($tagDAO->listTags(true) as $label) {
+ $unreadcounts[] = array(
+ 'id' => 'user/-/label/' . $label->name(),
+ 'count' => $label->nbUnread(),
+ );
+ }
+
$unreadcounts[] = array(
'id' => 'user/-/state/com.google/reading-list',
'count' => $totalUnreads,
@@ -440,13 +469,21 @@ function unreadCount() { //http://blog.martindoms.com/2009/10/16/using-the-googl
echo json_encode(array(
'max' => $totalUnreads,
'unreadcounts' => $unreadcounts,
- )), "\n";
+ ), JSON_OPTIONS), "\n";
exit();
}
function entriesToArray($entries) {
+ if (empty($entries)) {
+ return array();
+ }
$feedDAO = FreshRSS_Factory::createFeedDao();
$arrayFeedCategoryNames = $feedDAO->arrayFeedCategoryNames();
+ $tagDAO = FreshRSS_Factory::createTagDao();
+ $entryIdsTagNames = $tagDAO->getEntryIdsTagNames($entries);
+ if ($entryIdsTagNames == false) {
+ $entryIdsTagNames = array();
+ }
$items = array();
foreach ($entries as $entry) {
@@ -478,8 +515,9 @@ function entriesToArray($entries) {
//'htmlUrl' => $line['f_website'],
),
);
- if ($entry->author() != '') {
- $item['author'] = $entry->author();
+ $author = $entry->authors(true);
+ if ($author != '') {
+ $item['author'] = $author;
}
if ($entry->isRead()) {
$item['categories'][] = 'user/-/state/com.google/read';
@@ -487,6 +525,10 @@ function entriesToArray($entries) {
if ($entry->isFavorite()) {
$item['categories'][] = 'user/-/state/com.google/starred';
}
+ $tagNames = isset($entryIdsTagNames['e_' . $entry->id()]) ? $entryIdsTagNames['e_' . $entry->id()] : array();
+ foreach ($tagNames as $tagName) {
+ $item['categories'][] = 'user/-/label/' . $tagName;
+ }
$items[] = $item;
}
return $items;
@@ -508,10 +550,22 @@ function streamContents($path, $include_target, $start_time, $count, $order, $ex
$type = 'f';
break;
case 'label':
- $type = 'c';
- $categoryDAO = new FreshRSS_CategoryDAO();
+ $categoryDAO = FreshRSS_Factory::createCategoryDao();
$cat = $categoryDAO->searchByName($include_target);
- $include_target = $cat == null ? -1 : $cat->id();
+ if ($cat != null) {
+ $type = 'c';
+ $include_target = $cat->id();
+ } else {
+ $tagDAO = FreshRSS_Factory::createTagDao();
+ $tag = $tagDAO->searchByName($include_target);
+ if ($tag != null) {
+ $type = 't';
+ $include_target = $tag->id();
+ } else {
+ $type = 'A';
+ $include_target = -1;
+ }
+ }
break;
default:
$type = 'A';
@@ -556,7 +610,7 @@ function streamContents($path, $include_target, $start_time, $count, $order, $ex
}
}
- echo json_encode($response), "\n";
+ echo json_encode($response, JSON_OPTIONS), "\n";
exit();
}
@@ -576,9 +630,22 @@ function streamContentsItemsIds($streamId, $start_time, $count, $order, $exclude
} elseif (strpos($streamId, 'user/-/label/') === 0) {
$type = 'c';
$c_name = substr($streamId, 13);
- $categoryDAO = new FreshRSS_CategoryDAO();
+ $categoryDAO = FreshRSS_Factory::createCategoryDao();
$cat = $categoryDAO->searchByName($c_name);
- $id = $cat == null ? -1 : $cat->id();
+ if ($cat != null) {
+ $type = 'c';
+ $id = $cat->id();
+ } else {
+ $tagDAO = FreshRSS_Factory::createTagDao();
+ $tag = $tagDAO->searchByName($c_name);
+ if ($tag != null) {
+ $type = 't';
+ $id = $tag->id();
+ } else {
+ $type = 'A';
+ $id = -1;
+ }
+ }
}
switch ($exclude_target) {
@@ -622,7 +689,7 @@ function streamContentsItemsIds($streamId, $start_time, $count, $order, $exclude
}
}
- echo json_encode($response), "\n";
+ echo json_encode($response, JSON_OPTIONS), "\n";
exit();
}
@@ -644,7 +711,7 @@ function streamContentsItems($e_ids, $order) {
'items' => $items,
);
- echo json_encode($response), "\n";
+ echo json_encode($response, JSON_OPTIONS), "\n";
exit();
}
@@ -654,6 +721,7 @@ function editTag($e_ids, $a, $r) {
}
$entryDAO = FreshRSS_Factory::createEntryDao();
+ $tagDAO = FreshRSS_Factory::createTagDao();
switch ($a) {
case 'user/-/state/com.google/read':
@@ -668,6 +736,30 @@ function editTag($e_ids, $a, $r) {
break;
case 'user/-/state/com.google/broadcast':
break;*/
+ default:
+ $tagName = '';
+ if (strpos($a, 'user/-/label/') === 0) {
+ $tagName = substr($a, 13);
+ } else {
+ $user = Minz_Session::param('currentUser', '_');
+ $prefix = 'user/' . $user . '/label/';
+ if (strpos($a, $prefix) === 0) {
+ $tagName = substr($a, strlen($prefix));
+ }
+ }
+ if ($tagName != '') {
+ $tag = $tagDAO->searchByName($tagName);
+ if ($tag == null) {
+ $tagDAO->addTag(array('name' => $tagName));
+ $tag = $tagDAO->searchByName($tagName);
+ }
+ if ($tag != null) {
+ foreach ($e_ids as $e_id) {
+ $tagDAO->tagEntry($tag->id(), $e_id, true);
+ }
+ }
+ }
+ break;
}
switch ($r) {
case 'user/-/state/com.google/read':
@@ -676,6 +768,17 @@ function editTag($e_ids, $a, $r) {
case 'user/-/state/com.google/starred':
$entryDAO->markFavorite($e_ids, false);
break;
+ default:
+ if (strpos($r, 'user/-/label/') === 0) {
+ $tagName = substr($r, 13);
+ $tag = $tagDAO->searchByName($tagName);
+ if ($tag != null) {
+ foreach ($e_ids as $e_id) {
+ $tagDAO->tagEntry($tag->id(), $e_id, false);
+ }
+ }
+ }
+ break;
}
exit('OK');
@@ -685,12 +788,20 @@ function renameTag($s, $dest) {
if ($s != '' && strpos($s, 'user/-/label/') === 0 &&
$dest != '' && strpos($dest, 'user/-/label/') === 0) {
$s = substr($s, 13);
- $categoryDAO = new FreshRSS_CategoryDAO();
+ $dest = substr($dest, 13);
+
+ $categoryDAO = FreshRSS_Factory::createCategoryDao();
$cat = $categoryDAO->searchByName($s);
if ($cat != null) {
- $dest = substr($dest, 13);
$categoryDAO->updateCategory($cat->id(), array('name' => $dest));
exit('OK');
+ } else {
+ $tagDAO = FreshRSS_Factory::createTagDao();
+ $tag = $tagDAO->searchByName($s);
+ if ($tag != null) {
+ $tagDAO->updateTag($tag->id(), array('name' => $dest));
+ exit('OK');
+ }
}
}
badRequest();
@@ -699,7 +810,7 @@ function renameTag($s, $dest) {
function disableTag($s) {
if ($s != '' && strpos($s, 'user/-/label/') === 0) {
$s = substr($s, 13);
- $categoryDAO = new FreshRSS_CategoryDAO();
+ $categoryDAO = FreshRSS_Factory::createCategoryDao();
$cat = $categoryDAO->searchByName($s);
if ($cat != null) {
$feedDAO = FreshRSS_Factory::createFeedDao();
@@ -708,6 +819,13 @@ function disableTag($s) {
$categoryDAO->deleteCategory($cat->id());
}
exit('OK');
+ } else {
+ $tagDAO = FreshRSS_Factory::createTagDao();
+ $tag = $tagDAO->searchByName($s);
+ if ($tag != null) {
+ $tagDAO->deleteTag($tag->id());
+ exit('OK');
+ }
}
}
badRequest();
@@ -720,9 +838,17 @@ function markAllAsRead($streamId, $olderThanId) {
$entryDAO->markReadFeed($f_id, $olderThanId);
} elseif (strpos($streamId, 'user/-/label/') === 0) {
$c_name = substr($streamId, 13);
- $categoryDAO = new FreshRSS_CategoryDAO();
+ $categoryDAO = FreshRSS_Factory::createCategoryDao();
$cat = $categoryDAO->searchByName($c_name);
- $entryDAO->markReadCat($cat === null ? -1 : $cat->id(), $olderThanId);
+ if ($cat != null) {
+ $entryDAO->markReadCat($cat->id(), $olderThanId);
+ } else {
+ $tagDAO = FreshRSS_Factory::createTagDao();
+ $tag = $tagDAO->searchByName($c_name);
+ if ($tag != null) {
+ $entryDAO->markReadTag($tag->id(), $olderThanId);
+ }
+ }
} elseif ($streamId === 'user/-/state/com.google/reading-list') {
$entryDAO->markReadEntries($olderThanId, false, -1);
}
diff --git a/p/i/index.php b/p/i/index.php
index ff7fcafdd..5bc9c0d76 100755
--- a/p/i/index.php
+++ b/p/i/index.php
@@ -1,4 +1,6 @@
<?php
+// > Error: FreshRSS requires PHP, which does not seem to be installed or configured correctly! <!--
+
# ***** BEGIN LICENSE BLOCK *****
# MINZ - A free PHP framework
# Copyright (C) 2011 Marien Fressinaud
diff --git a/p/scripts/bcrypt.min.js b/p/scripts/bcrypt.min.js
index 614f0c259..23d2a73aa 100644
--- a/p/scripts/bcrypt.min.js
+++ b/p/scripts/bcrypt.min.js
@@ -1,45 +1,57 @@
-(function(){/*
+/*
bcrypt.js (c) 2013 Daniel Wirtz <dcode@dcode.io>
Released under the Apache License, Version 2.0
see: https://github.com/dcodeIO/bcrypt.js for details
*/
-function l(t){throw t;}var p=null;
-(function(t){function B(c){if("undefined"!==typeof module&&module&&module.exports)try{return require("crypto").randomBytes(c)}catch(a){}try{var b;(t.crypto||t.msCrypto).getRandomValues(b=new Uint32Array(c));return Array.prototype.slice.call(b)}catch(d){}x||l(Error("Neither WebCryptoAPI nor a crypto module is available. Use bcrypt.setRandomFallback to set an alternative"));return x(c)}function F(c){var a=[],b=0;G.f(function(){return b>=c.length?p:c.charCodeAt(b++)},function(b){a.push(b)});return a}
-function y(c,a){var b=0,d=[],f,e;for((0>=a||a>c.length)&&l(Error("Illegal len: "+a));b<a;){f=c[b++]&255;d.push(u[f>>2&63]);f=(f&3)<<4;if(b>=a){d.push(u[f&63]);break}e=c[b++]&255;f|=e>>4&15;d.push(u[f&63]);f=(e&15)<<2;if(b>=a){d.push(u[f&63]);break}e=c[b++]&255;f|=e>>6&3;d.push(u[f&63]);d.push(u[e&63])}return d.join("")}function H(c){for(var a=0,b=c.length,d=0,f=[],e,k,h;a<b-1&&16>d;){h=c.charCodeAt(a++);e=h<r.length?r[h]:-1;h=c.charCodeAt(a++);k=h<r.length?r[h]:-1;if(-1==e||-1==k)break;h=e<<2>>>0;
-h|=(k&48)>>4;f.push(z(h));if(16<=++d||a>=b)break;h=c.charCodeAt(a++);e=h<r.length?r[h]:-1;if(-1==e)break;h=(k&15)<<4>>>0;h|=(e&60)>>2;f.push(z(h));if(16<=++d||a>=b)break;h=c.charCodeAt(a++);k=h<r.length?r[h]:-1;h=(e&3)<<6>>>0;h|=k;f.push(z(h));++d}c=[];for(a=0;a<d;a++)c.push(f[a].charCodeAt(0));return c}function w(c,a,b,d){for(var f,e=c[a],k=c[a+1],e=e^b[0],h=0;14>=h;)f=d[e>>24&255],f+=d[256|e>>16&255],f^=d[512|e>>8&255],f+=d[768|e&255],k^=f^b[++h],f=d[k>>24&255],f+=d[256|k>>16&255],f^=d[512|k>>8&
-255],f+=d[768|k&255],e^=f^b[++h];c[a]=k^b[17];c[a+1]=e;return c}function v(c,a){for(var b=0,d=0;4>b;++b)d=d<<8|c[a]&255,a=(a+1)%c.length;return{key:d,a:a}}function C(c,a,b){for(var d=0,f=[0,0],e=a.length,k=b.length,h,g=0;g<e;g++)h=v(c,d),d=h.a,a[g]^=h.key;for(g=0;g<e;g+=2)f=w(f,0,a,b),a[g]=f[0],a[g+1]=f[1];for(g=0;g<k;g+=2)f=w(f,0,a,b),b[g]=f[0],b[g+1]=f[1]}function I(c,a,b,d){for(var f=0,e=[0,0],k=b.length,h=d.length,g,m=0;m<k;m++)g=v(a,f),f=g.a,b[m]^=g.key;for(m=f=0;m<k;m+=2)g=v(c,f),f=g.a,e[0]^=
-g.key,g=v(c,f),f=g.a,e[1]^=g.key,e=w(e,0,b,d),b[m]=e[0],b[m+1]=e[1];for(m=0;m<h;m+=2)g=v(c,f),f=g.a,e[0]^=g.key,g=v(c,f),f=g.a,e[1]^=g.key,e=w(e,0,b,d),d[m]=e[0],d[m+1]=e[1]}function D(c,a,b,d,f){function e(){f&&f(q/b);if(q<b)for(var g=Date.now();q<b&&!(q+=1,C(c,m,n),C(a,m,n),100<Date.now()-g););else{for(q=0;64>q;q++)for(r=0;r<h>>1;r++)w(k,r<<1,m,n);g=[];for(q=0;q<h;q++)g.push((k[q]>>24&255)>>>0),g.push((k[q]>>16&255)>>>0),g.push((k[q]>>8&255)>>>0),g.push((k[q]&255)>>>0);if(d){d(p,g);return}return g}d&&
-s(e)}var k=E.slice(),h=k.length,g;if(4>b||31<b){g=Error("Illegal number of rounds (4-31): "+b);if(d){s(d.bind(this,g));return}l(g)}if(16!==a.length){g=Error("Illegal salt length: "+a.length+" != 16");if(d){s(d.bind(this,g));return}l(g)}b=1<<b;var m=J.slice(),n=K.slice(),q=0,r;I(a,c,m,n);if("undefined"!==typeof d)e();else for(;;)if("undefined"!==typeof(g=e()))return g||[]}function A(c,a,b,d){function f(a){var b=[];b.push("$2");"a"<=k&&b.push(k);b.push("$");10>g&&b.push("0");b.push(g.toString());b.push("$");
-b.push(y(m,m.length));b.push(y(a,4*E.length-1));return b.join("")}var e;if("string"!==typeof c||"string"!==typeof a){e=Error("Invalid string / salt: Not a string");if(b){s(b.bind(this,e));return}l(e)}var k,h;if("$"!==a.charAt(0)||"2"!==a.charAt(1)){e=Error("Invalid salt version: "+a.substring(0,2));if(b){s(b.bind(this,e));return}l(e)}if("$"===a.charAt(2))k=String.fromCharCode(0),h=3;else{k=a.charAt(2);if("a"!==k&&"y"!==k||"$"!==a.charAt(3)){e=Error("Invalid salt revision: "+a.substring(2,4));if(b){s(b.bind(this,
-e));return}l(e)}h=4}if("$"<a.charAt(h+2)){e=Error("Missing salt rounds");if(b){s(b.bind(this,e));return}l(e)}var g=10*parseInt(a.substring(h,h+1),10)+parseInt(a.substring(h+1,h+2),10);a=a.substring(h+3,h+25);c=F(c+("a"<=k?"\x00":""));var m=H(a);if("undefined"==typeof b)return f(D(c,m,g));D(c,m,g,function(a,d){a?b(a,p):b(p,f(d))},d)}var n={},x=p;try{B(1)}catch(L){}x=p;n.l=function(c){x=c};n.genSaltSync=function(c,a){"undefined"===typeof c?c=10:"number"!==typeof c&&l(Error("Illegal arguments: "+typeof c+
-", "+typeof a));(4>c||31<c)&&l(Error("Illegal number of rounds (4-31): "+c));var b=[];b.push("$2a$");10>c&&b.push("0");b.push(c.toString());b.push("$");b.push(y(B(16),16));return b.join("")};n.genSalt=function(c,a,b){"function"===typeof a&&(b=a,a=void 0);"function"===typeof c&&(b=c,c=10);"function"!==typeof b&&l(Error("Illegal callback: "+typeof b));"number"!==typeof c?s(b.bind(this,Error("Illegal arguments: "+typeof c))):s(function(){try{b(p,n.genSaltSync(c))}catch(a){b(a)}})};n.hashSync=function(c,
-a){"undefined"===typeof a&&(a=10);"number"===typeof a&&(a=n.genSaltSync(a));("string"!==typeof c||"string"!==typeof a)&&l(Error("Illegal arguments: "+typeof c+", "+typeof a));return A(c,a)};n.hash=function(c,a,b,d){"function"!==typeof b&&l(Error("Illegal callback: "+typeof b));"string"===typeof c&&"number"===typeof a?n.genSalt(a,function(a,e){A(c,e,b,d)}):"string"===typeof c&&"string"===typeof a?A(c,a,b,d):s(b.bind(this,Error("Illegal arguments: "+typeof c+", "+typeof a)))};n.compareSync=function(c,
-a){("string"!==typeof c||"string"!==typeof a)&&l(Error("Illegal arguments: "+typeof c+", "+typeof a));if(60!==a.length)return!1;for(var b=n.hashSync(c,a.substr(0,a.length-31)),d=b.length===a.length,f=b.length<a.length?b.length:a.length,e=0;e<f;++e)b.length>=e&&(a.length>=e&&b[e]!=a[e])&&(d=!1);return d};n.compare=function(c,a,b,d){"function"!==typeof b&&l(Error("Illegal callback: "+typeof b));"string"!==typeof c||"string"!==typeof a?s(b.bind(this,Error("Illegal arguments: "+typeof c+", "+typeof a))):
-n.hash(c,a.substr(0,29),function(d,c){b(d,a===c)},d)};n.getRounds=function(c){"string"!==typeof c&&l(Error("Illegal arguments: "+typeof c));return parseInt(c.split("$")[2],10)};n.getSalt=function(c){"string"!==typeof c&&l(Error("Illegal arguments: "+typeof c));60!==c.length&&l(Error("Illegal hash length: "+c.length+" != 60"));return c.substring(0,29)};var s="undefined"!==typeof process&&process&&"function"===typeof process.nextTick?"function"===typeof setImmediate?setImmediate:process.nextTick:setTimeout,
-u="./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".split(""),r=[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,54,55,56,57,58,59,60,61,62,63,-1,-1,-1,-1,-1,-1,-1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,-1,-1,-1,-1,-1,-1,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,-1,-1,-1,-1,-1],z=String.fromCharCode,G=function(){var c={h:1114111,
-g:function(a,b){var d=p;"number"===typeof a&&(d=a,a=function(){return p});for(;d!==p||(d=a())!==p;)128>d?b(d&127):(2048>d?b(d>>6&31|192):(65536>d?b(d>>12&15|224):(b(d>>18&7|240),b(d>>12&63|128)),b(d>>6&63|128)),b(d&63|128)),d=p},e:function(a,b){function d(a){a=a.slice(0,a.indexOf(p));var b=Error(a.toString());b.name="TruncatedError";b.bytes=a;l(b)}for(var c,e,k,h;(c=a())!==p;)0===(c&128)?b(c):192===(c&224)?((e=a())===p&&d([c,e]),b((c&31)<<6|e&63)):224===(c&240)?(((e=a())===p||(k=a())===p)&&d([c,e,
-k]),b((c&15)<<12|(e&63)<<6|k&63)):240===(c&248)?(((e=a())===p||(k=a())===p||(h=a())===p)&&d([c,e,k,h]),b((c&7)<<18|(e&63)<<12|(k&63)<<6|h&63)):l(RangeError("Illegal starting byte: "+c))},b:function(a,b){for(var c,f=p;(c=f!==p?f:a())!==p;)55296<=c&&57343>=c&&(f=a())!==p&&56320<=f&&57343>=f?(b(1024*(c-55296)+f-56320+65536),f=p):b(c);f!==p&&b(f)},d:function(a,b){var c=p;"number"===typeof a&&(c=a,a=function(){return p});for(;c!==p||(c=a())!==p;)65535>=c?b(c):(c-=65536,b((c>>10)+55296),b(c%1024+56320)),
-c=p},f:function(a,b){c.b(a,function(a){c.g(a,b)})},k:function(a,b){c.e(a,function(a){c.d(a,b)})},c:function(a){return 128>a?1:2048>a?2:65536>a?3:4},j:function(a){for(var b,d=0;(b=a())!==p;)d+=c.c(b);return d},i:function(a){var b=0,d=0;c.b(a,function(a){++b;d+=c.c(a)});return[b,d]}};return c}();Date.now=Date.now||function(){return+new Date};var J=[608135816,2242054355,320440878,57701188,2752067618,698298832,137296536,3964562569,1160258022,953160567,3193202383,887688300,3232508343,3380367581,1065670069,
-3041331479,2450970073,2306472731],K=[3509652390,2564797868,805139163,3491422135,3101798381,1780907670,3128725573,4046225305,614570311,3012652279,134345442,2240740374,1667834072,1901547113,2757295779,4103290238,227898511,1921955416,1904987480,2182433518,2069144605,3260701109,2620446009,720527379,3318853667,677414384,3393288472,3101374703,2390351024,1614419982,1822297739,2954791486,3608508353,3174124327,2024746970,1432378464,3864339955,2857741204,1464375394,1676153920,1439316330,715854006,3033291828,
-289532110,2706671279,2087905683,3018724369,1668267050,732546397,1947742710,3462151702,2609353502,2950085171,1814351708,2050118529,680887927,999245976,1800124847,3300911131,1713906067,1641548236,4213287313,1216130144,1575780402,4018429277,3917837745,3693486850,3949271944,596196993,3549867205,258830323,2213823033,772490370,2760122372,1774776394,2652871518,566650946,4142492826,1728879713,2882767088,1783734482,3629395816,2517608232,2874225571,1861159788,326777828,3124490320,2130389656,2716951837,967770486,
-1724537150,2185432712,2364442137,1164943284,2105845187,998989502,3765401048,2244026483,1075463327,1455516326,1322494562,910128902,469688178,1117454909,936433444,3490320968,3675253459,1240580251,122909385,2157517691,634681816,4142456567,3825094682,3061402683,2540495037,79693498,3249098678,1084186820,1583128258,426386531,1761308591,1047286709,322548459,995290223,1845252383,2603652396,3431023940,2942221577,3202600964,3727903485,1712269319,422464435,3234572375,1170764815,3523960633,3117677531,1434042557,
-442511882,3600875718,1076654713,1738483198,4213154764,2393238008,3677496056,1014306527,4251020053,793779912,2902807211,842905082,4246964064,1395751752,1040244610,2656851899,3396308128,445077038,3742853595,3577915638,679411651,2892444358,2354009459,1767581616,3150600392,3791627101,3102740896,284835224,4246832056,1258075500,768725851,2589189241,3069724005,3532540348,1274779536,3789419226,2764799539,1660621633,3471099624,4011903706,913787905,3497959166,737222580,2514213453,2928710040,3937242737,1804850592,
-3499020752,2949064160,2386320175,2390070455,2415321851,4061277028,2290661394,2416832540,1336762016,1754252060,3520065937,3014181293,791618072,3188594551,3933548030,2332172193,3852520463,3043980520,413987798,3465142937,3030929376,4245938359,2093235073,3534596313,375366246,2157278981,2479649556,555357303,3870105701,2008414854,3344188149,4221384143,3956125452,2067696032,3594591187,2921233993,2428461,544322398,577241275,1471733935,610547355,4027169054,1432588573,1507829418,2025931657,3646575487,545086370,
-48609733,2200306550,1653985193,298326376,1316178497,3007786442,2064951626,458293330,2589141269,3591329599,3164325604,727753846,2179363840,146436021,1461446943,4069977195,705550613,3059967265,3887724982,4281599278,3313849956,1404054877,2845806497,146425753,1854211946,1266315497,3048417604,3681880366,3289982499,290971E4,1235738493,2632868024,2414719590,3970600049,1771706367,1449415276,3266420449,422970021,1963543593,2690192192,3826793022,1062508698,1531092325,1804592342,2583117782,2714934279,4024971509,
-1294809318,4028980673,1289560198,2221992742,1669523910,35572830,157838143,1052438473,1016535060,1802137761,1753167236,1386275462,3080475397,2857371447,1040679964,2145300060,2390574316,1461121720,2956646967,4031777805,4028374788,33600511,2920084762,1018524850,629373528,3691585981,3515945977,2091462646,2486323059,586499841,988145025,935516892,3367335476,2599673255,2839830854,265290510,3972581182,2759138881,3795373465,1005194799,847297441,406762289,1314163512,1332590856,1866599683,4127851711,750260880,
-613907577,1450815602,3165620655,3734664991,3650291728,3012275730,3704569646,1427272223,778793252,1343938022,2676280711,2052605720,1946737175,3164576444,3914038668,3967478842,3682934266,1661551462,3294938066,4011595847,840292616,3712170807,616741398,312560963,711312465,1351876610,322626781,1910503582,271666773,2175563734,1594956187,70604529,3617834859,1007753275,1495573769,4069517037,2549218298,2663038764,504708206,2263041392,3941167025,2249088522,1514023603,1998579484,1312622330,694541497,2582060303,
-2151582166,1382467621,776784248,2618340202,3323268794,2497899128,2784771155,503983604,4076293799,907881277,423175695,432175456,1378068232,4145222326,3954048622,3938656102,3820766613,2793130115,2977904593,26017576,3274890735,3194772133,1700274565,1756076034,4006520079,3677328699,720338349,1533947780,354530856,688349552,3973924725,1637815568,332179504,3949051286,53804574,2852348879,3044236432,1282449977,3583942155,3416972820,4006381244,1617046695,2628476075,3002303598,1686838959,431878346,2686675385,
-1700445008,1080580658,1009431731,832498133,3223435511,2605976345,2271191193,2516031870,1648197032,4164389018,2548247927,300782431,375919233,238389289,3353747414,2531188641,2019080857,1475708069,455242339,2609103871,448939670,3451063019,1395535956,2413381860,1841049896,1491858159,885456874,4264095073,4001119347,1565136089,3898914787,1108368660,540939232,1173283510,2745871338,3681308437,4207628240,3343053890,4016749493,1699691293,1103962373,3625875870,2256883143,3830138730,1031889488,3479347698,1535977030,
-4236805024,3251091107,2132092099,1774941330,1199868427,1452454533,157007616,2904115357,342012276,595725824,1480756522,206960106,497939518,591360097,863170706,2375253569,3596610801,1814182875,2094937945,3421402208,1082520231,3463918190,2785509508,435703966,3908032597,1641649973,2842273706,3305899714,1510255612,2148256476,2655287854,3276092548,4258621189,236887753,3681803219,274041037,1734335097,3815195456,3317970021,1899903192,1026095262,4050517792,356393447,2410691914,3873677099,3682840055,3913112168,
-2491498743,4132185628,2489919796,1091903735,1979897079,3170134830,3567386728,3557303409,857797738,1136121015,1342202287,507115054,2535736646,337727348,3213592640,1301675037,2528481711,1895095763,1721773893,3216771564,62756741,2142006736,835421444,2531993523,1442658625,3659876326,2882144922,676362277,1392781812,170690266,3921047035,1759253602,3611846912,1745797284,664899054,1329594018,3901205900,3045908486,2062866102,2865634940,3543621612,3464012697,1080764994,553557557,3656615353,3996768171,991055499,
-499776247,1265440854,648242737,3940784050,980351604,3713745714,1749149687,3396870395,4211799374,3640570775,1161844396,3125318951,1431517754,545492359,4268468663,3499529547,1437099964,2702547544,3433638243,2581715763,2787789398,1060185593,1593081372,2418618748,4260947970,69676912,2159744348,86519011,2512459080,3838209314,1220612927,3339683548,133810670,1090789135,1078426020,1569222167,845107691,3583754449,4072456591,1091646820,628848692,1613405280,3757631651,526609435,236106946,48312990,2942717905,
-3402727701,1797494240,859738849,992217954,4005476642,2243076622,3870952857,3732016268,765654824,3490871365,2511836413,1685915746,3888969200,1414112111,2273134842,3281911079,4080962846,172450625,2569994100,980381355,4109958455,2819808352,2716589560,2568741196,3681446669,3329971472,1835478071,660984891,3704678404,4045999559,3422617507,3040415634,1762651403,1719377915,3470491036,2693910283,3642056355,3138596744,1364962596,2073328063,1983633131,926494387,3423689081,2150032023,4096667949,1749200295,3328846651,
-309677260,2016342300,1779581495,3079819751,111262694,1274766160,443224088,298511866,1025883608,3806446537,1145181785,168956806,3641502830,3584813610,1689216846,3666258015,3200248200,1692713982,2646376535,4042768518,1618508792,1610833997,3523052358,4130873264,2001055236,3610705100,2202168115,4028541809,2961195399,1006657119,2006996926,3186142756,1430667929,3210227297,1314452623,4074634658,4101304120,2273951170,1399257539,3367210612,3027628629,1190975929,2062231137,2333990788,2221543033,2438960610,
-1181637006,548689776,2362791313,3372408396,3104550113,3145860560,296247880,1970579870,3078560182,3769228297,1714227617,3291629107,3898220290,166772364,1251581989,493813264,448347421,195405023,2709975567,677966185,3703036547,1463355134,2715995803,1338867538,1343315457,2802222074,2684532164,233230375,2599980071,2000651841,3277868038,1638401717,4028070440,3237316320,6314154,819756386,300326615,590932579,1405279636,3267499572,3150704214,2428286686,3959192993,3461946742,1862657033,1266418056,963775037,
-2089974820,2263052895,1917689273,448879540,3550394620,3981727096,150775221,3627908307,1303187396,508620638,2975983352,2726630617,1817252668,1876281319,1457606340,908771278,3720792119,3617206836,2455994898,1729034894,1080033504,976866871,3556439503,2881648439,1522871579,1555064734,1336096578,3548522304,2579274686,3574697629,3205460757,3593280638,3338716283,3079412587,564236357,2993598910,1781952180,1464380207,3163844217,3332601554,1699332808,1393555694,1183702653,3581086237,1288719814,691649499,2847557200,
-2895455976,3193889540,2717570544,1781354906,1676643554,2592534050,3230253752,1126444790,2770207658,2633158820,2210423226,2615765581,2414155088,3127139286,673620729,2805611233,1269405062,4015350505,3341807571,4149409754,1057255273,2012875353,2162469141,2276492801,2601117357,993977747,3918593370,2654263191,753973209,36408145,2530585658,25011837,3520020182,2088578344,530523599,2918365339,1524020338,1518925132,3760827505,3759777254,1202760957,3985898139,3906192525,674977740,4174734889,2031300136,2019492241,
-3983892565,4153806404,3822280332,352677332,2297720250,60907813,90501309,3286998549,1016092578,2535922412,2839152426,457141659,509813237,4120667899,652014361,1966332200,2975202805,55981186,2327461051,676427537,3255491064,2882294119,3433927263,1307055953,942726286,933058658,2468411793,3933900994,4215176142,1361170020,2001714738,2830558078,3274259782,1222529897,1679025792,2729314320,3714953764,1770335741,151462246,3013232138,1682292957,1483529935,471910574,1539241949,458788160,3436315007,1807016891,
-3718408830,978976581,1043663428,3165965781,1927990952,4200891579,2372276910,3208408903,3533431907,1412390302,2931980059,4132332400,1947078029,3881505623,4168226417,2941484381,1077988104,1320477388,886195818,18198404,3786409E3,2509781533,112762804,3463356488,1866414978,891333506,18488651,661792760,1628790961,3885187036,3141171499,876946877,2693282273,1372485963,791857591,2686433993,3759982718,3167212022,3472953795,2716379847,445679433,3561995674,3504004811,3574258232,54117162,3331405415,2381918588,
-3769707343,4154350007,1140177722,4074052095,668550556,3214352940,367459370,261225585,2610173221,4209349473,3468074219,3265815641,314222801,3066103646,3808782860,282218597,3406013506,3773591054,379116347,1285071038,846784868,2669647154,3771962079,3550491691,2305946142,453669953,1268987020,3317592352,3279303384,3744833421,2610507566,3859509063,266596637,3847019092,517658769,3462560207,3443424879,370717030,4247526661,2224018117,4143653529,4112773975,2788324899,2477274417,1456262402,2901442914,1517677493,
-1846949527,2295493580,3734397586,2176403920,1280348187,1908823572,3871786941,846861322,1172426758,3287448474,3383383037,1655181056,3139813346,901632758,1897031941,2986607138,3066810236,3447102507,1393639104,373351379,950779232,625454576,3124240540,4148612726,2007998917,544563296,2244738638,2330496472,2058025392,1291430526,424198748,50039436,29584100,3605783033,2429876329,2791104160,1057563949,3255363231,3075367218,3463963227,1469046755,985887462],E=[1332899944,1700884034,1701343084,1684370003,1668446532,
-1869963892];"undefined"!==typeof module&&module.exports?module.exports=n:"undefined"!==typeof define&&define.amd?define(function(){return n}):(t.dcodeIO=t.dcodeIO||{}).bcrypt=n})(this);})();
+var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.ASSUME_ES5=!1;$jscomp.ASSUME_NO_NATIVE_MAP=!1;$jscomp.ASSUME_NO_NATIVE_SET=!1;$jscomp.defineProperty=$jscomp.ASSUME_ES5||"function"==typeof Object.defineProperties?Object.defineProperty:function(a,g,p){a!=Array.prototype&&a!=Object.prototype&&(a[g]=p.value)};$jscomp.getGlobal=function(a){return"undefined"!=typeof window&&window===a?a:"undefined"!=typeof global&&null!=global?global:a};$jscomp.global=$jscomp.getGlobal(this);$jscomp.SYMBOL_PREFIX="jscomp_symbol_";
+$jscomp.initSymbol=function(){$jscomp.initSymbol=function(){};$jscomp.global.Symbol||($jscomp.global.Symbol=$jscomp.Symbol)};$jscomp.Symbol=function(){var a=0;return function(g){return $jscomp.SYMBOL_PREFIX+(g||"")+a++}}();
+$jscomp.initSymbolIterator=function(){$jscomp.initSymbol();var a=$jscomp.global.Symbol.iterator;a||(a=$jscomp.global.Symbol.iterator=$jscomp.global.Symbol("iterator"));"function"!=typeof Array.prototype[a]&&$jscomp.defineProperty(Array.prototype,a,{configurable:!0,writable:!0,value:function(){return $jscomp.arrayIterator(this)}});$jscomp.initSymbolIterator=function(){}};$jscomp.arrayIterator=function(a){var g=0;return $jscomp.iteratorPrototype(function(){return g<a.length?{done:!1,value:a[g++]}:{done:!0}})};
+$jscomp.iteratorPrototype=function(a){$jscomp.initSymbolIterator();a={next:a};a[$jscomp.global.Symbol.iterator]=function(){return this};return a};$jscomp.makeIterator=function(a){$jscomp.initSymbolIterator();var g=a[Symbol.iterator];return g?g.call(a):$jscomp.arrayIterator(a)};
+$jscomp.polyfill=function(a,g,p,q){if(g){p=$jscomp.global;a=a.split(".");for(q=0;q<a.length-1;q++){var h=a[q];h in p||(p[h]={});p=p[h]}a=a[a.length-1];q=p[a];g=g(q);g!=q&&null!=g&&$jscomp.defineProperty(p,a,{configurable:!0,writable:!0,value:g})}};$jscomp.FORCE_POLYFILL_PROMISE=!1;
+$jscomp.polyfill("Promise",function(a){function g(){this.batch_=null}function p(b){return b instanceof h?b:new h(function(a,h){a(b)})}if(a&&!$jscomp.FORCE_POLYFILL_PROMISE)return a;g.prototype.asyncExecute=function(b){null==this.batch_&&(this.batch_=[],this.asyncExecuteBatch_());this.batch_.push(b);return this};g.prototype.asyncExecuteBatch_=function(){var b=this;this.asyncExecuteFunction(function(){b.executeBatch_()})};var q=$jscomp.global.setTimeout;g.prototype.asyncExecuteFunction=function(b){q(b,
+0)};g.prototype.executeBatch_=function(){for(;this.batch_&&this.batch_.length;){var b=this.batch_;this.batch_=[];for(var a=0;a<b.length;++a){var h=b[a];delete b[a];try{h()}catch(t){this.asyncThrow_(t)}}}this.batch_=null};g.prototype.asyncThrow_=function(b){this.asyncExecuteFunction(function(){throw b;})};var h=function(b){this.state_=0;this.result_=void 0;this.onSettledCallbacks_=[];var a=this.createResolveAndReject_();try{b(a.resolve,a.reject)}catch(w){a.reject(w)}};h.prototype.createResolveAndReject_=
+function(){function b(b){return function(A){h||(h=!0,b.call(a,A))}}var a=this,h=!1;return{resolve:b(this.resolveTo_),reject:b(this.reject_)}};h.prototype.resolveTo_=function(b){if(b===this)this.reject_(new TypeError("A Promise cannot resolve to itself"));else if(b instanceof h)this.settleSameAsPromise_(b);else{a:switch(typeof b){case "object":var a=null!=b;break a;case "function":a=!0;break a;default:a=!1}a?this.resolveToNonPromiseObj_(b):this.fulfill_(b)}};h.prototype.resolveToNonPromiseObj_=function(b){var a=
+void 0;try{a=b.then}catch(w){this.reject_(w);return}"function"==typeof a?this.settleSameAsThenable_(a,b):this.fulfill_(b)};h.prototype.reject_=function(a){this.settle_(2,a)};h.prototype.fulfill_=function(a){this.settle_(1,a)};h.prototype.settle_=function(a,h){if(0!=this.state_)throw Error("Cannot settle("+a+", "+h|"): Promise already settled in state"+this.state_);this.state_=a;this.result_=h;this.executeOnSettledCallbacks_()};h.prototype.executeOnSettledCallbacks_=function(){if(null!=this.onSettledCallbacks_){for(var a=
+this.onSettledCallbacks_,h=0;h<a.length;++h)a[h].call(),a[h]=null;this.onSettledCallbacks_=null}};var v=new g;h.prototype.settleSameAsPromise_=function(a){var b=this.createResolveAndReject_();a.callWhenSettled_(b.resolve,b.reject)};h.prototype.settleSameAsThenable_=function(a,h){var b=this.createResolveAndReject_();try{a.call(h,b.resolve,b.reject)}catch(t){b.reject(t)}};h.prototype.then=function(a,g){function b(a,b){return"function"==typeof a?function(b){try{t(a(b))}catch(u){m(u)}}:b}var t,m,p=new h(function(a,
+b){t=a;m=b});this.callWhenSettled_(b(a,t),b(g,m));return p};h.prototype.catch=function(a){return this.then(void 0,a)};h.prototype.callWhenSettled_=function(a,h){function b(){switch(g.state_){case 1:a(g.result_);break;case 2:h(g.result_);break;default:throw Error("Unexpected state: "+g.state_);}}var g=this;null==this.onSettledCallbacks_?v.asyncExecute(b):this.onSettledCallbacks_.push(function(){v.asyncExecute(b)})};h.resolve=p;h.reject=function(a){return new h(function(b,h){h(a)})};h.race=function(a){return new h(function(b,
+h){for(var g=$jscomp.makeIterator(a),m=g.next();!m.done;m=g.next())p(m.value).callWhenSettled_(b,h)})};h.all=function(a){var b=$jscomp.makeIterator(a),g=b.next();return g.done?p([]):new h(function(a,h){function m(b){return function(h){r[b]=h;q--;0==q&&a(r)}}var r=[],q=0;do r.push(void 0),q++,p(g.value).callWhenSettled_(m(r.length-1),h),g=b.next();while(!g.done)})};return h},"es6","es3");
+(function(a,g){"function"===typeof define&&define.amd?define([],g):"function"===typeof require&&"object"===typeof module&&module&&module.exports?module.exports=g():(a.dcodeIO=a.dcodeIO||{}).bcrypt=g()})(this,function(){function a(n){if("undefined"!==typeof module&&module&&module.exports)try{return require("crypto").randomBytes(n)}catch(l){}try{var k;(self.crypto||self.msCrypto).getRandomValues(k=new Uint32Array(n));return Array.prototype.slice.call(k)}catch(l){}if(!z)throw Error("Neither WebCryptoAPI nor a crypto module is available. Use bcrypt.setRandomFallback to set an alternative");
+return z(n)}function g(n,k){for(var a=n.length^k.length,c=0;c<n.length;++c)a|=n.charCodeAt(c)^k.charCodeAt(c);return 0===a}function p(n,k){var a=0,c=[];if(0>=k||k>n.length)throw Error("Illegal len: "+k);for(;a<k;){var e=n[a++]&255;c.push(x[e>>2&63]);e=(e&3)<<4;if(a>=k){c.push(x[e&63]);break}var f=n[a++]&255;e|=f>>4&15;c.push(x[e&63]);e=(f&15)<<2;if(a>=k){c.push(x[e&63]);break}f=n[a++]&255;e|=f>>6&3;c.push(x[e&63]);c.push(x[f&63])}return c.join("")}function q(a,k){var n=0,c=a.length,e=0,f=[];if(0>=
+k)throw Error("Illegal len: "+k);for(;n<c-1&&e<k;){var d=a.charCodeAt(n++);var b=d<u.length?u[d]:-1;d=a.charCodeAt(n++);var h=d<u.length?u[d]:-1;if(-1==b||-1==h)break;d=b<<2>>>0;d|=(h&48)>>4;f.push(B(d));if(++e>=k||n>=c)break;d=a.charCodeAt(n++);b=d<u.length?u[d]:-1;if(-1==b)break;d=(h&15)<<4>>>0;d|=(b&60)>>2;f.push(B(d));if(++e>=k||n>=c)break;d=a.charCodeAt(n++);h=d<u.length?u[d]:-1;d=(b&3)<<6>>>0;d|=h;f.push(B(d));++e}a=[];for(n=0;n<e;n++)a.push(f[n].charCodeAt(0));return a}function h(a,k,l,c){var e=
+a[k],f=a[k+1];e^=l[0];var d=c[e>>>24];d+=c[256|e>>16&255];d^=c[512|e>>8&255];d+=c[768|e&255];f^=d^l[1];d=c[f>>>24];d+=c[256|f>>16&255];d^=c[512|f>>8&255];d+=c[768|f&255];e^=d^l[2];d=c[e>>>24];d+=c[256|e>>16&255];d^=c[512|e>>8&255];d+=c[768|e&255];f^=d^l[3];d=c[f>>>24];d+=c[256|f>>16&255];d^=c[512|f>>8&255];d+=c[768|f&255];e^=d^l[4];d=c[e>>>24];d+=c[256|e>>16&255];d^=c[512|e>>8&255];d+=c[768|e&255];f^=d^l[5];d=c[f>>>24];d+=c[256|f>>16&255];d^=c[512|f>>8&255];d+=c[768|f&255];e^=d^l[6];d=c[e>>>24];d+=
+c[256|e>>16&255];d^=c[512|e>>8&255];d+=c[768|e&255];f^=d^l[7];d=c[f>>>24];d+=c[256|f>>16&255];d^=c[512|f>>8&255];d+=c[768|f&255];e^=d^l[8];d=c[e>>>24];d+=c[256|e>>16&255];d^=c[512|e>>8&255];d+=c[768|e&255];f^=d^l[9];d=c[f>>>24];d+=c[256|f>>16&255];d^=c[512|f>>8&255];d+=c[768|f&255];e^=d^l[10];d=c[e>>>24];d+=c[256|e>>16&255];d^=c[512|e>>8&255];d+=c[768|e&255];f^=d^l[11];d=c[f>>>24];d+=c[256|f>>16&255];d^=c[512|f>>8&255];d+=c[768|f&255];e^=d^l[12];d=c[e>>>24];d+=c[256|e>>16&255];d^=c[512|e>>8&255];
+d+=c[768|e&255];f^=d^l[13];d=c[f>>>24];d+=c[256|f>>16&255];d^=c[512|f>>8&255];d+=c[768|f&255];e^=d^l[14];d=c[e>>>24];d+=c[256|e>>16&255];d^=c[512|e>>8&255];d+=c[768|e&255];f^=d^l[15];d=c[f>>>24];d+=c[256|f>>16&255];d^=c[512|f>>8&255];d+=c[768|f&255];e^=d^l[16];a[k]=f^l[17];a[k+1]=e;return a}function v(a,k){for(var n=0,c=0;4>n;++n)c=c<<8|a[k]&255,k=(k+1)%a.length;return{key:c,offp:k}}function b(a,k,l){for(var c=0,e=[0,0],f=k.length,d=l.length,n,b=0;b<f;b++)n=v(a,c),c=n.offp,k[b]^=n.key;for(b=0;b<f;b+=
+2)e=h(e,0,k,l),k[b]=e[0],k[b+1]=e[1];for(b=0;b<d;b+=2)e=h(e,0,k,l),l[b]=e[0],l[b+1]=e[1]}function A(a,k,b,c){for(var e=0,f=[0,0],d=b.length,n=c.length,l,g=0;g<d;g++)l=v(k,e),e=l.offp,b[g]^=l.key;for(g=e=0;g<d;g+=2)l=v(a,e),e=l.offp,f[0]^=l.key,l=v(a,e),e=l.offp,f[1]^=l.key,f=h(f,0,b,c),b[g]=f[0],b[g+1]=f[1];for(g=0;g<n;g+=2)l=v(a,e),e=l.offp,f[0]^=l.key,l=v(a,e),e=l.offp,f[1]^=l.key,f=h(f,0,b,c),c[g]=f[0],c[g+1]=f[1]}function w(a,k,l,c,e){function f(){e&&e(m/l);if(m<l)for(var g=Date.now();m<l&&!(m+=
+1,b(a,q,y),b(k,q,y),100<Date.now()-g););else{for(m=0;64>m;m++)for(p=0;p<n>>1;p++)h(d,p<<1,q,y);g=[];for(m=0;m<n;m++)g.push((d[m]>>24&255)>>>0),g.push((d[m]>>16&255)>>>0),g.push((d[m]>>8&255)>>>0),g.push((d[m]&255)>>>0);if(c){c(null,g);return}return g}c&&r(f)}var d=C.slice(),n=d.length;if(4>l||31<l){var g=Error("Illegal number of rounds (4-31): "+l);if(c){r(c.bind(this,g));return}throw g;}if(16!==k.length){g=Error("Illegal salt length: "+k.length+" != 16");if(c){r(c.bind(this,g));return}throw g;}l=
+1<<l>>>0;var m=0,p;if(Int32Array){var q=new Int32Array(D);var y=new Int32Array(E)}else q=D.slice(),y=E.slice();A(k,a,q,y);if("undefined"!==typeof c)f();else for(;;)if("undefined"!==typeof(g=f()))return g||[]}function t(a,k,b,c){function e(a){var c=[];c.push("$2");"a"<=f&&c.push(f);c.push("$");10>l&&c.push("0");c.push(l.toString());c.push("$");c.push(p(h,h.length));c.push(p(a,4*C.length-1));return c.join("")}if("string"!==typeof a||"string"!==typeof k){c=Error("Invalid string / salt: Not a string");
+if(b){r(b.bind(this,c));return}throw c;}if("$"!==k.charAt(0)||"2"!==k.charAt(1)){c=Error("Invalid salt version: "+k.substring(0,2));if(b){r(b.bind(this,c));return}throw c;}if("$"===k.charAt(2)){var f=String.fromCharCode(0);var d=3}else{f=k.charAt(2);if("a"!==f&&"b"!==f&&"y"!==f||"$"!==k.charAt(3)){c=Error("Invalid salt revision: "+k.substring(2,4));if(b){r(b.bind(this,c));return}throw c;}d=4}if("$"<k.charAt(d+2)){c=Error("Missing salt rounds");if(b){r(b.bind(this,c));return}throw c;}var n=10*parseInt(k.substring(d,
+d+1),10),g=parseInt(k.substring(d+1,d+2),10),l=n+g;k=k.substring(d+3,d+25);a=F(a+("a"<=f?"\x00":""));var h=q(k,16);if("undefined"==typeof b)return e(w(a,h,l));w(a,h,l,function(c,a){c?b(c,null):b(null,e(a))},c)}var m={},z=null;try{a(1)}catch(n){}z=null;m.setRandomFallback=function(a){z=a};m.genSaltSync=function(b,k){b=b||10;if("number"!==typeof b)throw Error("Illegal arguments: "+typeof b+", "+typeof k);4>b?b=4:31<b&&(b=31);k=[];k.push("$2a$");10>b&&k.push("0");k.push(b.toString());k.push("$");k.push(p(a(16),
+16));return k.join("")};m.genSalt=function(a,b,g){function c(c){r(function(){try{c(null,m.genSaltSync(a))}catch(f){c(f)}})}"function"===typeof b&&(g=b,b=void 0);"function"===typeof a&&(g=a,a=void 0);if("undefined"===typeof a)a=10;else if("number"!==typeof a)throw Error("illegal arguments: "+typeof a);if(g){if("function"!==typeof g)throw Error("Illegal callback: "+typeof g);c(g)}else return new Promise(function(a,b){c(function(c,f){c?b(c):a(f)})})};m.hashSync=function(a,b){"undefined"===typeof b&&
+(b=10);"number"===typeof b&&(b=m.genSaltSync(b));if("string"!==typeof a||"string"!==typeof b)throw Error("Illegal arguments: "+typeof a+", "+typeof b);return t(a,b)};m.hash=function(a,b,g,c){function e(f){"string"===typeof a&&"number"===typeof b?m.genSalt(b,function(b,e){t(a,e,f,c)}):"string"===typeof a&&"string"===typeof b?t(a,b,f,c):r(f.bind(this,Error("Illegal arguments: "+typeof a+", "+typeof b)))}if(g){if("function"!==typeof g)throw Error("Illegal callback: "+typeof g);e(g)}else return new Promise(function(a,
+c){e(function(b,d){b?c(b):a(d)})})};m.compareSync=function(a,b){if("string"!==typeof a||"string"!==typeof b)throw Error("Illegal arguments: "+typeof a+", "+typeof b);return 60!==b.length?!1:g(m.hashSync(a,b.substr(0,b.length-31)),b)};m.compare=function(a,b,h,c){function e(f){"string"!==typeof a||"string"!==typeof b?r(f.bind(this,Error("Illegal arguments: "+typeof a+", "+typeof b))):60!==b.length?r(f.bind(this,null,!1)):m.hash(a,b.substr(0,29),function(a,c){a?f(a):f(null,g(c,b))},c)}if(h){if("function"!==
+typeof h)throw Error("Illegal callback: "+typeof h);e(h)}else return new Promise(function(a,c){e(function(b,d){b?c(b):a(d)})})};m.getRounds=function(a){if("string"!==typeof a)throw Error("Illegal arguments: "+typeof a);return parseInt(a.split("$")[2],10)};m.getSalt=function(a){if("string"!==typeof a)throw Error("Illegal arguments: "+typeof a);if(60!==a.length)throw Error("Illegal hash length: "+a.length+" != 60");return a.substring(0,29)};var r="undefined"!==typeof process&&process&&"function"===
+typeof process.nextTick?"function"===typeof setImmediate?setImmediate:process.nextTick:setTimeout,F=function(a){var b=0,g;var c=Array;for(var e=0,f,d=0;d<a.length;++d)f=a.charCodeAt(d),128>f?e+=1:2048>f?e+=2:55296===(f&64512)&&56320===(a.charCodeAt(d+1)&64512)?(++d,e+=4):e+=3;e=new c(e);f=0;for(d=a.length;f<d;++f)c=a.charCodeAt(f),128>c?e[b++]=c:(2048>c?e[b++]=c>>6|192:(55296===(c&64512)&&56320===((g=a.charCodeAt(f+1))&64512)?(c=65536+((c&1023)<<10)+(g&1023),++f,e[b++]=c>>18|240,e[b++]=c>>12&63|128):
+e[b++]=c>>12|224,e[b++]=c>>6&63|128),e[b++]=c&63|128);return e},x="./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".split(""),u=[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,54,55,56,57,58,59,60,61,62,63,-1,-1,-1,-1,-1,-1,-1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,-1,-1,-1,-1,-1,-1,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,
+53,-1,-1,-1,-1,-1],B=String.fromCharCode;Date.now=Date.now||function(){return+new Date};var D=[608135816,2242054355,320440878,57701188,2752067618,698298832,137296536,3964562569,1160258022,953160567,3193202383,887688300,3232508343,3380367581,1065670069,3041331479,2450970073,2306472731],E=[3509652390,2564797868,805139163,3491422135,3101798381,1780907670,3128725573,4046225305,614570311,3012652279,134345442,2240740374,1667834072,1901547113,2757295779,4103290238,227898511,1921955416,1904987480,2182433518,
+2069144605,3260701109,2620446009,720527379,3318853667,677414384,3393288472,3101374703,2390351024,1614419982,1822297739,2954791486,3608508353,3174124327,2024746970,1432378464,3864339955,2857741204,1464375394,1676153920,1439316330,715854006,3033291828,289532110,2706671279,2087905683,3018724369,1668267050,732546397,1947742710,3462151702,2609353502,2950085171,1814351708,2050118529,680887927,999245976,1800124847,3300911131,1713906067,1641548236,4213287313,1216130144,1575780402,4018429277,3917837745,3693486850,
+3949271944,596196993,3549867205,258830323,2213823033,772490370,2760122372,1774776394,2652871518,566650946,4142492826,1728879713,2882767088,1783734482,3629395816,2517608232,2874225571,1861159788,326777828,3124490320,2130389656,2716951837,967770486,1724537150,2185432712,2364442137,1164943284,2105845187,998989502,3765401048,2244026483,1075463327,1455516326,1322494562,910128902,469688178,1117454909,936433444,3490320968,3675253459,1240580251,122909385,2157517691,634681816,4142456567,3825094682,3061402683,
+2540495037,79693498,3249098678,1084186820,1583128258,426386531,1761308591,1047286709,322548459,995290223,1845252383,2603652396,3431023940,2942221577,3202600964,3727903485,1712269319,422464435,3234572375,1170764815,3523960633,3117677531,1434042557,442511882,3600875718,1076654713,1738483198,4213154764,2393238008,3677496056,1014306527,4251020053,793779912,2902807211,842905082,4246964064,1395751752,1040244610,2656851899,3396308128,445077038,3742853595,3577915638,679411651,2892444358,2354009459,1767581616,
+3150600392,3791627101,3102740896,284835224,4246832056,1258075500,768725851,2589189241,3069724005,3532540348,1274779536,3789419226,2764799539,1660621633,3471099624,4011903706,913787905,3497959166,737222580,2514213453,2928710040,3937242737,1804850592,3499020752,2949064160,2386320175,2390070455,2415321851,4061277028,2290661394,2416832540,1336762016,1754252060,3520065937,3014181293,791618072,3188594551,3933548030,2332172193,3852520463,3043980520,413987798,3465142937,3030929376,4245938359,2093235073,3534596313,
+375366246,2157278981,2479649556,555357303,3870105701,2008414854,3344188149,4221384143,3956125452,2067696032,3594591187,2921233993,2428461,544322398,577241275,1471733935,610547355,4027169054,1432588573,1507829418,2025931657,3646575487,545086370,48609733,2200306550,1653985193,298326376,1316178497,3007786442,2064951626,458293330,2589141269,3591329599,3164325604,727753846,2179363840,146436021,1461446943,4069977195,705550613,3059967265,3887724982,4281599278,3313849956,1404054877,2845806497,146425753,1854211946,
+1266315497,3048417604,3681880366,3289982499,290971E4,1235738493,2632868024,2414719590,3970600049,1771706367,1449415276,3266420449,422970021,1963543593,2690192192,3826793022,1062508698,1531092325,1804592342,2583117782,2714934279,4024971509,1294809318,4028980673,1289560198,2221992742,1669523910,35572830,157838143,1052438473,1016535060,1802137761,1753167236,1386275462,3080475397,2857371447,1040679964,2145300060,2390574316,1461121720,2956646967,4031777805,4028374788,33600511,2920084762,1018524850,629373528,
+3691585981,3515945977,2091462646,2486323059,586499841,988145025,935516892,3367335476,2599673255,2839830854,265290510,3972581182,2759138881,3795373465,1005194799,847297441,406762289,1314163512,1332590856,1866599683,4127851711,750260880,613907577,1450815602,3165620655,3734664991,3650291728,3012275730,3704569646,1427272223,778793252,1343938022,2676280711,2052605720,1946737175,3164576444,3914038668,3967478842,3682934266,1661551462,3294938066,4011595847,840292616,3712170807,616741398,312560963,711312465,
+1351876610,322626781,1910503582,271666773,2175563734,1594956187,70604529,3617834859,1007753275,1495573769,4069517037,2549218298,2663038764,504708206,2263041392,3941167025,2249088522,1514023603,1998579484,1312622330,694541497,2582060303,2151582166,1382467621,776784248,2618340202,3323268794,2497899128,2784771155,503983604,4076293799,907881277,423175695,432175456,1378068232,4145222326,3954048622,3938656102,3820766613,2793130115,2977904593,26017576,3274890735,3194772133,1700274565,1756076034,4006520079,
+3677328699,720338349,1533947780,354530856,688349552,3973924725,1637815568,332179504,3949051286,53804574,2852348879,3044236432,1282449977,3583942155,3416972820,4006381244,1617046695,2628476075,3002303598,1686838959,431878346,2686675385,1700445008,1080580658,1009431731,832498133,3223435511,2605976345,2271191193,2516031870,1648197032,4164389018,2548247927,300782431,375919233,238389289,3353747414,2531188641,2019080857,1475708069,455242339,2609103871,448939670,3451063019,1395535956,2413381860,1841049896,
+1491858159,885456874,4264095073,4001119347,1565136089,3898914787,1108368660,540939232,1173283510,2745871338,3681308437,4207628240,3343053890,4016749493,1699691293,1103962373,3625875870,2256883143,3830138730,1031889488,3479347698,1535977030,4236805024,3251091107,2132092099,1774941330,1199868427,1452454533,157007616,2904115357,342012276,595725824,1480756522,206960106,497939518,591360097,863170706,2375253569,3596610801,1814182875,2094937945,3421402208,1082520231,3463918190,2785509508,435703966,3908032597,
+1641649973,2842273706,3305899714,1510255612,2148256476,2655287854,3276092548,4258621189,236887753,3681803219,274041037,1734335097,3815195456,3317970021,1899903192,1026095262,4050517792,356393447,2410691914,3873677099,3682840055,3913112168,2491498743,4132185628,2489919796,1091903735,1979897079,3170134830,3567386728,3557303409,857797738,1136121015,1342202287,507115054,2535736646,337727348,3213592640,1301675037,2528481711,1895095763,1721773893,3216771564,62756741,2142006736,835421444,2531993523,1442658625,
+3659876326,2882144922,676362277,1392781812,170690266,3921047035,1759253602,3611846912,1745797284,664899054,1329594018,3901205900,3045908486,2062866102,2865634940,3543621612,3464012697,1080764994,553557557,3656615353,3996768171,991055499,499776247,1265440854,648242737,3940784050,980351604,3713745714,1749149687,3396870395,4211799374,3640570775,1161844396,3125318951,1431517754,545492359,4268468663,3499529547,1437099964,2702547544,3433638243,2581715763,2787789398,1060185593,1593081372,2418618748,4260947970,
+69676912,2159744348,86519011,2512459080,3838209314,1220612927,3339683548,133810670,1090789135,1078426020,1569222167,845107691,3583754449,4072456591,1091646820,628848692,1613405280,3757631651,526609435,236106946,48312990,2942717905,3402727701,1797494240,859738849,992217954,4005476642,2243076622,3870952857,3732016268,765654824,3490871365,2511836413,1685915746,3888969200,1414112111,2273134842,3281911079,4080962846,172450625,2569994100,980381355,4109958455,2819808352,2716589560,2568741196,3681446669,
+3329971472,1835478071,660984891,3704678404,4045999559,3422617507,3040415634,1762651403,1719377915,3470491036,2693910283,3642056355,3138596744,1364962596,2073328063,1983633131,926494387,3423689081,2150032023,4096667949,1749200295,3328846651,309677260,2016342300,1779581495,3079819751,111262694,1274766160,443224088,298511866,1025883608,3806446537,1145181785,168956806,3641502830,3584813610,1689216846,3666258015,3200248200,1692713982,2646376535,4042768518,1618508792,1610833997,3523052358,4130873264,2001055236,
+3610705100,2202168115,4028541809,2961195399,1006657119,2006996926,3186142756,1430667929,3210227297,1314452623,4074634658,4101304120,2273951170,1399257539,3367210612,3027628629,1190975929,2062231137,2333990788,2221543033,2438960610,1181637006,548689776,2362791313,3372408396,3104550113,3145860560,296247880,1970579870,3078560182,3769228297,1714227617,3291629107,3898220290,166772364,1251581989,493813264,448347421,195405023,2709975567,677966185,3703036547,1463355134,2715995803,1338867538,1343315457,2802222074,
+2684532164,233230375,2599980071,2000651841,3277868038,1638401717,4028070440,3237316320,6314154,819756386,300326615,590932579,1405279636,3267499572,3150704214,2428286686,3959192993,3461946742,1862657033,1266418056,963775037,2089974820,2263052895,1917689273,448879540,3550394620,3981727096,150775221,3627908307,1303187396,508620638,2975983352,2726630617,1817252668,1876281319,1457606340,908771278,3720792119,3617206836,2455994898,1729034894,1080033504,976866871,3556439503,2881648439,1522871579,1555064734,
+1336096578,3548522304,2579274686,3574697629,3205460757,3593280638,3338716283,3079412587,564236357,2993598910,1781952180,1464380207,3163844217,3332601554,1699332808,1393555694,1183702653,3581086237,1288719814,691649499,2847557200,2895455976,3193889540,2717570544,1781354906,1676643554,2592534050,3230253752,1126444790,2770207658,2633158820,2210423226,2615765581,2414155088,3127139286,673620729,2805611233,1269405062,4015350505,3341807571,4149409754,1057255273,2012875353,2162469141,2276492801,2601117357,
+993977747,3918593370,2654263191,753973209,36408145,2530585658,25011837,3520020182,2088578344,530523599,2918365339,1524020338,1518925132,3760827505,3759777254,1202760957,3985898139,3906192525,674977740,4174734889,2031300136,2019492241,3983892565,4153806404,3822280332,352677332,2297720250,60907813,90501309,3286998549,1016092578,2535922412,2839152426,457141659,509813237,4120667899,652014361,1966332200,2975202805,55981186,2327461051,676427537,3255491064,2882294119,3433927263,1307055953,942726286,933058658,
+2468411793,3933900994,4215176142,1361170020,2001714738,2830558078,3274259782,1222529897,1679025792,2729314320,3714953764,1770335741,151462246,3013232138,1682292957,1483529935,471910574,1539241949,458788160,3436315007,1807016891,3718408830,978976581,1043663428,3165965781,1927990952,4200891579,2372276910,3208408903,3533431907,1412390302,2931980059,4132332400,1947078029,3881505623,4168226417,2941484381,1077988104,1320477388,886195818,18198404,3786409E3,2509781533,112762804,3463356488,1866414978,891333506,
+18488651,661792760,1628790961,3885187036,3141171499,876946877,2693282273,1372485963,791857591,2686433993,3759982718,3167212022,3472953795,2716379847,445679433,3561995674,3504004811,3574258232,54117162,3331405415,2381918588,3769707343,4154350007,1140177722,4074052095,668550556,3214352940,367459370,261225585,2610173221,4209349473,3468074219,3265815641,314222801,3066103646,3808782860,282218597,3406013506,3773591054,379116347,1285071038,846784868,2669647154,3771962079,3550491691,2305946142,453669953,
+1268987020,3317592352,3279303384,3744833421,2610507566,3859509063,266596637,3847019092,517658769,3462560207,3443424879,370717030,4247526661,2224018117,4143653529,4112773975,2788324899,2477274417,1456262402,2901442914,1517677493,1846949527,2295493580,3734397586,2176403920,1280348187,1908823572,3871786941,846861322,1172426758,3287448474,3383383037,1655181056,3139813346,901632758,1897031941,2986607138,3066810236,3447102507,1393639104,373351379,950779232,625454576,3124240540,4148612726,2007998917,544563296,
+2244738638,2330496472,2058025392,1291430526,424198748,50039436,29584100,3605783033,2429876329,2791104160,1057563949,3255363231,3075367218,3463963227,1469046755,985887462],C=[1332899944,1700884034,1701343084,1684370003,1668446532,1869963892];m.encodeBase64=p;m.decodeBase64=q;return m});
diff --git a/p/scripts/jquery.min.js b/p/scripts/jquery.min.js
index 4c5be4c0f..4d9b3a258 100644
--- a/p/scripts/jquery.min.js
+++ b/p/scripts/jquery.min.js
@@ -1,4 +1,2 @@
-/*! jQuery v3.1.1 | (c) jQuery Foundation | jquery.org/license */
-!function(a,b){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){"use strict";var c=[],d=a.document,e=Object.getPrototypeOf,f=c.slice,g=c.concat,h=c.push,i=c.indexOf,j={},k=j.toString,l=j.hasOwnProperty,m=l.toString,n=m.call(Object),o={};function p(a,b){b=b||d;var c=b.createElement("script");c.text=a,b.head.appendChild(c).parentNode.removeChild(c)}var q="3.1.1",r=function(a,b){return new r.fn.init(a,b)},s=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,t=/^-ms-/,u=/-([a-z])/g,v=function(a,b){return b.toUpperCase()};r.fn=r.prototype={jquery:q,constructor:r,length:0,toArray:function(){return f.call(this)},get:function(a){return null==a?f.call(this):a<0?this[a+this.length]:this[a]},pushStack:function(a){var b=r.merge(this.constructor(),a);return b.prevObject=this,b},each:function(a){return r.each(this,a)},map:function(a){return this.pushStack(r.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(f.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(a<0?b:0);return this.pushStack(c>=0&&c<b?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:h,sort:c.sort,splice:c.splice},r.extend=r.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||r.isFunction(g)||(g={}),h===i&&(g=this,h--);h<i;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(r.isPlainObject(d)||(e=r.isArray(d)))?(e?(e=!1,f=c&&r.isArray(c)?c:[]):f=c&&r.isPlainObject(c)?c:{},g[b]=r.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},r.extend({expando:"jQuery"+(q+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===r.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){var b=r.type(a);return("number"===b||"string"===b)&&!isNaN(a-parseFloat(a))},isPlainObject:function(a){var b,c;return!(!a||"[object Object]"!==k.call(a))&&(!(b=e(a))||(c=l.call(b,"constructor")&&b.constructor,"function"==typeof c&&m.call(c)===n))},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?j[k.call(a)]||"object":typeof a},globalEval:function(a){p(a)},camelCase:function(a){return a.replace(t,"ms-").replace(u,v)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b){var c,d=0;if(w(a)){for(c=a.length;d<c;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(s,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(w(Object(a))?r.merge(c,"string"==typeof a?[a]:a):h.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:i.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;d<c;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;f<g;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,f=0,h=[];if(w(a))for(d=a.length;f<d;f++)e=b(a[f],f,c),null!=e&&h.push(e);else for(f in a)e=b(a[f],f,c),null!=e&&h.push(e);return g.apply([],h)},guid:1,proxy:function(a,b){var c,d,e;if("string"==typeof b&&(c=a[b],b=a,a=c),r.isFunction(a))return d=f.call(arguments,2),e=function(){return a.apply(b||this,d.concat(f.call(arguments)))},e.guid=a.guid=a.guid||r.guid++,e},now:Date.now,support:o}),"function"==typeof Symbol&&(r.fn[Symbol.iterator]=c[Symbol.iterator]),r.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){j["[object "+b+"]"]=b.toLowerCase()});function w(a){var b=!!a&&"length"in a&&a.length,c=r.type(a);return"function"!==c&&!r.isWindow(a)&&("array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a)}var x=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=function(a,b){for(var c=0,d=a.length;c<d;c++)if(a[c]===b)return c;return-1},J="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",K="[\\x20\\t\\r\\n\\f]",L="(?:\\\\.|[\\w-]|[^\0-\\xa0])+",M="\\["+K+"*("+L+")(?:"+K+"*([*^$|!~]?=)"+K+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+L+"))|)"+K+"*\\]",N=":("+L+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+M+")*)|.*)\\)|)",O=new RegExp(K+"+","g"),P=new RegExp("^"+K+"+|((?:^|[^\\\\])(?:\\\\.)*)"+K+"+$","g"),Q=new RegExp("^"+K+"*,"+K+"*"),R=new RegExp("^"+K+"*([>+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(N),U=new RegExp("^"+L+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L+"|[*])"),ATTR:new RegExp("^"+M),PSEUDO:new RegExp("^"+N),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),aa=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:d<0?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ba=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ca=function(a,b){return b?"\0"===a?"\ufffd":a.slice(0,-1)+"\\"+a.charCodeAt(a.length-1).toString(16)+" ":"\\"+a},da=function(){m()},ea=ta(function(a){return a.disabled===!0&&("form"in a||"label"in a)},{dir:"parentNode",next:"legend"});try{G.apply(D=H.call(v.childNodes),v.childNodes),D[v.childNodes.length].nodeType}catch(fa){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s=b&&b.ownerDocument,w=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==w&&9!==w&&11!==w)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==w&&(l=Z.exec(a)))if(f=l[1]){if(9===w){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(s&&(j=s.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(l[2])return G.apply(d,b.getElementsByTagName(a)),d;if((f=l[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==w)s=b,r=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(ba,ca):b.setAttribute("id",k=u),o=g(a),h=o.length;while(h--)o[h]="#"+k+" "+sa(o[h]);r=o.join(","),s=$.test(a)&&qa(b.parentNode)||b}if(r)try{return G.apply(d,s.querySelectorAll(r)),d}catch(x){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(P,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("fieldset");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&a.sourceIndex-b.sourceIndex;if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return function(b){return"form"in b?b.parentNode&&b.disabled===!1?"label"in b?"label"in b.parentNode?b.parentNode.disabled===a:b.disabled===a:b.isDisabled===a||b.isDisabled!==!a&&ea(b)===a:b.disabled===a:"label"in b&&b.disabled===a}}function pa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function qa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return!!b&&"HTML"!==b.nodeName},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),v!==n&&(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(n.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){return a.getAttribute("id")===b}},d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}}):(d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}},d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c,d,e,f=b.getElementById(a);if(f){if(c=f.getAttributeNode("id"),c&&c.value===a)return[f];e=b.getElementsByName(a),d=0;while(f=e[d++])if(c=f.getAttributeNode("id"),c&&c.value===a)return[f]}return[]}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){if("undefined"!=typeof b.getElementsByClassName&&p)return b.getElementsByClassName(a)},r=[],q=[],(c.qsa=Y.test(n.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="<a id='"+u+"'></a><select id='"+u+"-\r\\' msallowcapture=''><option selected=''></option></select>",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){a.innerHTML="<a href='' disabled='disabled'></a><select disabled='disabled'><option/></select>";var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+K+"*[*^$|!~]?="),2!==a.querySelectorAll(":enabled").length&&q.push(":enabled",":disabled"),o.appendChild(a).disabled=!0,2!==a.querySelectorAll(":disabled").length&&q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Y.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"*"),s.call(a,"[s!='']:x"),r.push("!=",N)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Y.test(o.compareDocumentPosition),t=b||Y.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?I(k,a)-I(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?I(k,a)-I(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?la(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(S,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.escape=function(a){return(a+"").replace(ba,ca)},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(_,aa),a[3]=(a[3]||a[4]||a[5]||"").replace(_,aa),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return V.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&T.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(_,aa).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:!b||(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(O," ")+" ").indexOf(c)>-1:"|="===b&&(e===c||e.slice(0,c.length+1)===c+"-"))}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(P,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(_,aa),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return U.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(_,aa).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:oa(!1),disabled:oa(!0),checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:pa(function(){return[0]}),last:pa(function(a,b){return[b-1]}),eq:pa(function(a,b,c){return[c<0?c+b:c]}),even:pa(function(a,b){for(var c=0;c<b;c+=2)a.push(c);return a}),odd:pa(function(a,b){for(var c=1;c<b;c+=2)a.push(c);return a}),lt:pa(function(a,b,c){for(var d=c<0?c+b:c;--d>=0;)a.push(d);return a}),gt:pa(function(a,b,c){for(var d=c<0?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=ma(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=na(b);function ra(){}ra.prototype=d.filters=d.pseudos,d.setFilters=new ra,g=ga.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){c&&!(e=Q.exec(h))||(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=R.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(P," ")}),h=h.slice(c.length));for(g in d.filter)!(e=V[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?ga.error(a):z(a,i).slice(0)};function sa(a){for(var b=0,c=a.length,d="";b<c;b++)d+=a[b].value;return d}function ta(a,b,c){var d=b.dir,e=b.next,f=e||d,g=c&&"parentNode"===f,h=x++;return b.first?function(b,c,e){while(b=b[d])if(1===b.nodeType||g)return a(b,c,e);return!1}:function(b,c,i){var j,k,l,m=[w,h];if(i){while(b=b[d])if((1===b.nodeType||g)&&a(b,c,i))return!0}else while(b=b[d])if(1===b.nodeType||g)if(l=b[u]||(b[u]={}),k=l[b.uniqueID]||(l[b.uniqueID]={}),e&&e===b.nodeName.toLowerCase())b=b[d]||b;else{if((j=k[f])&&j[0]===w&&j[1]===h)return m[2]=j[2];if(k[f]=m,m[2]=a(b,c,i))return!0}return!1}}function ua(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function va(a,b,c){for(var d=0,e=b.length;d<e;d++)ga(a,b[d],c);return c}function wa(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;h<i;h++)(f=a[h])&&(c&&!c(f,d,e)||(g.push(f),j&&b.push(h)));return g}function xa(a,b,c,d,e,f){return d&&!d[u]&&(d=xa(d)),e&&!e[u]&&(e=xa(e,f)),ia(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||va(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:wa(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=wa(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?I(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=wa(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ya(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ta(function(a){return a===b},h,!0),l=ta(function(a){return I(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];i<f;i++)if(c=d.relative[a[i].type])m=[ta(ua(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;e<f;e++)if(d.relative[a[e].type])break;return xa(i>1&&ua(m),i>1&&sa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(P,"$1"),c,i<e&&ya(a.slice(i,e)),e<f&&ya(a=a.slice(e)),e<f&&sa(a))}m.push(c)}return ua(m)}function za(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=E.call(i));u=wa(u)}G.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&ga.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=ya(b[c]),f[u]?d.push(f):e.push(f);f=A(a,za(e,d)),f.selector=a}return f},i=ga.select=function(a,b,c,e){var f,i,j,k,l,m="function"==typeof a&&a,n=!e&&g(a=m.selector||a);if(c=c||[],1===n.length){if(i=n[0]=n[0].slice(0),i.length>2&&"ID"===(j=i[0]).type&&9===b.nodeType&&p&&d.relative[i[1].type]){if(b=(d.find.ID(j.matches[0].replace(_,aa),b)||[])[0],!b)return c;m&&(b=b.parentNode),a=a.slice(i.shift().value.length)}f=V.needsContext.test(a)?0:i.length;while(f--){if(j=i[f],d.relative[k=j.type])break;if((l=d.find[k])&&(e=l(j.matches[0].replace(_,aa),$.test(i[0].type)&&qa(b.parentNode)||b))){if(i.splice(f,1),a=e.length&&sa(i),!a)return G.apply(c,e),c;break}}}return(m||h(a,n))(e,b,!p,c,!b||$.test(a)&&qa(b.parentNode)||b),c},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("fieldset"))}),ja(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){if(!c)return a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){if(!c&&"input"===a.nodeName.toLowerCase())return a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(J,function(a,b,c){var d;if(!c)return a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);r.find=x,r.expr=x.selectors,r.expr[":"]=r.expr.pseudos,r.uniqueSort=r.unique=x.uniqueSort,r.text=x.getText,r.isXMLDoc=x.isXML,r.contains=x.contains,r.escapeSelector=x.escape;var y=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&r(a).is(c))break;d.push(a)}return d},z=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},A=r.expr.match.needsContext,B=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i,C=/^.[^:#\[\.,]*$/;function D(a,b,c){return r.isFunction(b)?r.grep(a,function(a,d){return!!b.call(a,d,a)!==c}):b.nodeType?r.grep(a,function(a){return a===b!==c}):"string"!=typeof b?r.grep(a,function(a){return i.call(b,a)>-1!==c}):C.test(b)?r.filter(b,a,c):(b=r.filter(b,a),r.grep(a,function(a){return i.call(b,a)>-1!==c&&1===a.nodeType}))}r.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?r.find.matchesSelector(d,a)?[d]:[]:r.find.matches(a,r.grep(b,function(a){return 1===a.nodeType}))},r.fn.extend({find:function(a){var b,c,d=this.length,e=this;if("string"!=typeof a)return this.pushStack(r(a).filter(function(){for(b=0;b<d;b++)if(r.contains(e[b],this))return!0}));for(c=this.pushStack([]),b=0;b<d;b++)r.find(a,e[b],c);return d>1?r.uniqueSort(c):c},filter:function(a){return this.pushStack(D(this,a||[],!1))},not:function(a){return this.pushStack(D(this,a||[],!0))},is:function(a){return!!D(this,"string"==typeof a&&A.test(a)?r(a):a||[],!1).length}});var E,F=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,G=r.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||E,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:F.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof r?b[0]:b,r.merge(this,r.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),B.test(e[1])&&r.isPlainObject(b))for(e in b)r.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&(this[0]=f,this.length=1),this}return a.nodeType?(this[0]=a,this.length=1,this):r.isFunction(a)?void 0!==c.ready?c.ready(a):a(r):r.makeArray(a,this)};G.prototype=r.fn,E=r(d);var H=/^(?:parents|prev(?:Until|All))/,I={children:!0,contents:!0,next:!0,prev:!0};r.fn.extend({has:function(a){var b=r(a,this),c=b.length;return this.filter(function(){for(var a=0;a<c;a++)if(r.contains(this,b[a]))return!0})},closest:function(a,b){var c,d=0,e=this.length,f=[],g="string"!=typeof a&&r(a);if(!A.test(a))for(;d<e;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&r.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?r.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?i.call(r(a),this[0]):i.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(r.uniqueSort(r.merge(this.get(),r(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function J(a,b){while((a=a[b])&&1!==a.nodeType);return a}r.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return y(a,"parentNode")},parentsUntil:function(a,b,c){return y(a,"parentNode",c)},next:function(a){return J(a,"nextSibling")},prev:function(a){return J(a,"previousSibling")},nextAll:function(a){return y(a,"nextSibling")},prevAll:function(a){return y(a,"previousSibling")},nextUntil:function(a,b,c){return y(a,"nextSibling",c)},prevUntil:function(a,b,c){return y(a,"previousSibling",c)},siblings:function(a){return z((a.parentNode||{}).firstChild,a)},children:function(a){return z(a.firstChild)},contents:function(a){return a.contentDocument||r.merge([],a.childNodes)}},function(a,b){r.fn[a]=function(c,d){var e=r.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=r.filter(d,e)),this.length>1&&(I[a]||r.uniqueSort(e),H.test(a)&&e.reverse()),this.pushStack(e)}});var K=/[^\x20\t\r\n\f]+/g;function L(a){var b={};return r.each(a.match(K)||[],function(a,c){b[c]=!0}),b}r.Callbacks=function(a){a="string"==typeof a?L(a):r.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h<f.length)f[h].apply(c[0],c[1])===!1&&a.stopOnFalse&&(h=f.length,c=!1)}a.memory||(c=!1),b=!1,e&&(f=c?[]:"")},j={add:function(){return f&&(c&&!b&&(h=f.length-1,g.push(c)),function d(b){r.each(b,function(b,c){r.isFunction(c)?a.unique&&j.has(c)||f.push(c):c&&c.length&&"string"!==r.type(c)&&d(c)})}(arguments),c&&!b&&i()),this},remove:function(){return r.each(arguments,function(a,b){var c;while((c=r.inArray(b,f,c))>-1)f.splice(c,1),c<=h&&h--}),this},has:function(a){return a?r.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=g=[],c||b||(f=c=""),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j};function M(a){return a}function N(a){throw a}function O(a,b,c){var d;try{a&&r.isFunction(d=a.promise)?d.call(a).done(b).fail(c):a&&r.isFunction(d=a.then)?d.call(a,b,c):b.call(void 0,a)}catch(a){c.call(void 0,a)}}r.extend({Deferred:function(b){var c=[["notify","progress",r.Callbacks("memory"),r.Callbacks("memory"),2],["resolve","done",r.Callbacks("once memory"),r.Callbacks("once memory"),0,"resolved"],["reject","fail",r.Callbacks("once memory"),r.Callbacks("once memory"),1,"rejected"]],d="pending",e={state:function(){return d},always:function(){return f.done(arguments).fail(arguments),this},"catch":function(a){return e.then(null,a)},pipe:function(){var a=arguments;return r.Deferred(function(b){r.each(c,function(c,d){var e=r.isFunction(a[d[4]])&&a[d[4]];f[d[1]](function(){var a=e&&e.apply(this,arguments);a&&r.isFunction(a.promise)?a.promise().progress(b.notify).done(b.resolve).fail(b.reject):b[d[0]+"With"](this,e?[a]:arguments)})}),a=null}).promise()},then:function(b,d,e){var f=0;function g(b,c,d,e){return function(){var h=this,i=arguments,j=function(){var a,j;if(!(b<f)){if(a=d.apply(h,i),a===c.promise())throw new TypeError("Thenable self-resolution");j=a&&("object"==typeof a||"function"==typeof a)&&a.then,r.isFunction(j)?e?j.call(a,g(f,c,M,e),g(f,c,N,e)):(f++,j.call(a,g(f,c,M,e),g(f,c,N,e),g(f,c,M,c.notifyWith))):(d!==M&&(h=void 0,i=[a]),(e||c.resolveWith)(h,i))}},k=e?j:function(){try{j()}catch(a){r.Deferred.exceptionHook&&r.Deferred.exceptionHook(a,k.stackTrace),b+1>=f&&(d!==N&&(h=void 0,i=[a]),c.rejectWith(h,i))}};b?k():(r.Deferred.getStackHook&&(k.stackTrace=r.Deferred.getStackHook()),a.setTimeout(k))}}return r.Deferred(function(a){c[0][3].add(g(0,a,r.isFunction(e)?e:M,a.notifyWith)),c[1][3].add(g(0,a,r.isFunction(b)?b:M)),c[2][3].add(g(0,a,r.isFunction(d)?d:N))}).promise()},promise:function(a){return null!=a?r.extend(a,e):e}},f={};return r.each(c,function(a,b){var g=b[2],h=b[5];e[b[1]]=g.add,h&&g.add(function(){d=h},c[3-a][2].disable,c[0][2].lock),g.add(b[3].fire),f[b[0]]=function(){return f[b[0]+"With"](this===f?void 0:this,arguments),this},f[b[0]+"With"]=g.fireWith}),e.promise(f),b&&b.call(f,f),f},when:function(a){var b=arguments.length,c=b,d=Array(c),e=f.call(arguments),g=r.Deferred(),h=function(a){return function(c){d[a]=this,e[a]=arguments.length>1?f.call(arguments):c,--b||g.resolveWith(d,e)}};if(b<=1&&(O(a,g.done(h(c)).resolve,g.reject),"pending"===g.state()||r.isFunction(e[c]&&e[c].then)))return g.then();while(c--)O(e[c],h(c),g.reject);return g.promise()}});var P=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;r.Deferred.exceptionHook=function(b,c){a.console&&a.console.warn&&b&&P.test(b.name)&&a.console.warn("jQuery.Deferred exception: "+b.message,b.stack,c)},r.readyException=function(b){a.setTimeout(function(){throw b})};var Q=r.Deferred();r.fn.ready=function(a){return Q.then(a)["catch"](function(a){r.readyException(a)}),this},r.extend({isReady:!1,readyWait:1,holdReady:function(a){a?r.readyWait++:r.ready(!0)},ready:function(a){(a===!0?--r.readyWait:r.isReady)||(r.isReady=!0,a!==!0&&--r.readyWait>0||Q.resolveWith(d,[r]))}}),r.ready.then=Q.then;function R(){d.removeEventListener("DOMContentLoaded",R),
-a.removeEventListener("load",R),r.ready()}"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(r.ready):(d.addEventListener("DOMContentLoaded",R),a.addEventListener("load",R));var S=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===r.type(c)){e=!0;for(h in c)S(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,r.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(r(a),c)})),b))for(;h<i;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},T=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function U(){this.expando=r.expando+U.uid++}U.uid=1,U.prototype={cache:function(a){var b=a[this.expando];return b||(b={},T(a)&&(a.nodeType?a[this.expando]=b:Object.defineProperty(a,this.expando,{value:b,configurable:!0}))),b},set:function(a,b,c){var d,e=this.cache(a);if("string"==typeof b)e[r.camelCase(b)]=c;else for(d in b)e[r.camelCase(d)]=b[d];return e},get:function(a,b){return void 0===b?this.cache(a):a[this.expando]&&a[this.expando][r.camelCase(b)]},access:function(a,b,c){return void 0===b||b&&"string"==typeof b&&void 0===c?this.get(a,b):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d=a[this.expando];if(void 0!==d){if(void 0!==b){r.isArray(b)?b=b.map(r.camelCase):(b=r.camelCase(b),b=b in d?[b]:b.match(K)||[]),c=b.length;while(c--)delete d[b[c]]}(void 0===b||r.isEmptyObject(d))&&(a.nodeType?a[this.expando]=void 0:delete a[this.expando])}},hasData:function(a){var b=a[this.expando];return void 0!==b&&!r.isEmptyObject(b)}};var V=new U,W=new U,X=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,Y=/[A-Z]/g;function Z(a){return"true"===a||"false"!==a&&("null"===a?null:a===+a+""?+a:X.test(a)?JSON.parse(a):a)}function $(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(Y,"-$&").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c=Z(c)}catch(e){}W.set(a,b,c)}else c=void 0;return c}r.extend({hasData:function(a){return W.hasData(a)||V.hasData(a)},data:function(a,b,c){return W.access(a,b,c)},removeData:function(a,b){W.remove(a,b)},_data:function(a,b,c){return V.access(a,b,c)},_removeData:function(a,b){V.remove(a,b)}}),r.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=W.get(f),1===f.nodeType&&!V.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=r.camelCase(d.slice(5)),$(f,d,e[d])));V.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){W.set(this,a)}):S(this,function(b){var c;if(f&&void 0===b){if(c=W.get(f,a),void 0!==c)return c;if(c=$(f,a),void 0!==c)return c}else this.each(function(){W.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){W.remove(this,a)})}}),r.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=V.get(a,b),c&&(!d||r.isArray(c)?d=V.access(a,b,r.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=r.queue(a,b),d=c.length,e=c.shift(),f=r._queueHooks(a,b),g=function(){r.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return V.get(a,c)||V.access(a,c,{empty:r.Callbacks("once memory").add(function(){V.remove(a,[b+"queue",c])})})}}),r.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?r.queue(this[0],a):void 0===b?this:this.each(function(){var c=r.queue(this,a,b);r._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&r.dequeue(this,a)})},dequeue:function(a){return this.each(function(){r.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=r.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=V.get(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var _=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,aa=new RegExp("^(?:([+-])=|)("+_+")([a-z%]*)$","i"),ba=["Top","Right","Bottom","Left"],ca=function(a,b){return a=b||a,"none"===a.style.display||""===a.style.display&&r.contains(a.ownerDocument,a)&&"none"===r.css(a,"display")},da=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e};function ea(a,b,c,d){var e,f=1,g=20,h=d?function(){return d.cur()}:function(){return r.css(a,b,"")},i=h(),j=c&&c[3]||(r.cssNumber[b]?"":"px"),k=(r.cssNumber[b]||"px"!==j&&+i)&&aa.exec(r.css(a,b));if(k&&k[3]!==j){j=j||k[3],c=c||[],k=+i||1;do f=f||".5",k/=f,r.style(a,b,k+j);while(f!==(f=h()/i)&&1!==f&&--g)}return c&&(k=+k||+i||0,e=c[1]?k+(c[1]+1)*c[2]:+c[2],d&&(d.unit=j,d.start=k,d.end=e)),e}var fa={};function ga(a){var b,c=a.ownerDocument,d=a.nodeName,e=fa[d];return e?e:(b=c.body.appendChild(c.createElement(d)),e=r.css(b,"display"),b.parentNode.removeChild(b),"none"===e&&(e="block"),fa[d]=e,e)}function ha(a,b){for(var c,d,e=[],f=0,g=a.length;f<g;f++)d=a[f],d.style&&(c=d.style.display,b?("none"===c&&(e[f]=V.get(d,"display")||null,e[f]||(d.style.display="")),""===d.style.display&&ca(d)&&(e[f]=ga(d))):"none"!==c&&(e[f]="none",V.set(d,"display",c)));for(f=0;f<g;f++)null!=e[f]&&(a[f].style.display=e[f]);return a}r.fn.extend({show:function(){return ha(this,!0)},hide:function(){return ha(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){ca(this)?r(this).show():r(this).hide()})}});var ia=/^(?:checkbox|radio)$/i,ja=/<([a-z][^\/\0>\x20\t\r\n\f]+)/i,ka=/^$|\/(?:java|ecma)script/i,la={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};la.optgroup=la.option,la.tbody=la.tfoot=la.colgroup=la.caption=la.thead,la.th=la.td;function ma(a,b){var c;return c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[],void 0===b||b&&r.nodeName(a,b)?r.merge([a],c):c}function na(a,b){for(var c=0,d=a.length;c<d;c++)V.set(a[c],"globalEval",!b||V.get(b[c],"globalEval"))}var oa=/<|&#?\w+;/;function pa(a,b,c,d,e){for(var f,g,h,i,j,k,l=b.createDocumentFragment(),m=[],n=0,o=a.length;n<o;n++)if(f=a[n],f||0===f)if("object"===r.type(f))r.merge(m,f.nodeType?[f]:f);else if(oa.test(f)){g=g||l.appendChild(b.createElement("div")),h=(ja.exec(f)||["",""])[1].toLowerCase(),i=la[h]||la._default,g.innerHTML=i[1]+r.htmlPrefilter(f)+i[2],k=i[0];while(k--)g=g.lastChild;r.merge(m,g.childNodes),g=l.firstChild,g.textContent=""}else m.push(b.createTextNode(f));l.textContent="",n=0;while(f=m[n++])if(d&&r.inArray(f,d)>-1)e&&e.push(f);else if(j=r.contains(f.ownerDocument,f),g=ma(l.appendChild(f),"script"),j&&na(g),c){k=0;while(f=g[k++])ka.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),o.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="<textarea>x</textarea>",o.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var qa=d.documentElement,ra=/^key/,sa=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,ta=/^([^.]*)(?:\.(.+)|)/;function ua(){return!0}function va(){return!1}function wa(){try{return d.activeElement}catch(a){}}function xa(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)xa(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=va;else if(!e)return a;return 1===f&&(g=e,e=function(a){return r().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=r.guid++)),a.each(function(){r.event.add(this,b,e,d,c)})}r.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=V.get(a);if(q){c.handler&&(f=c,c=f.handler,e=f.selector),e&&r.find.matchesSelector(qa,e),c.guid||(c.guid=r.guid++),(i=q.events)||(i=q.events={}),(g=q.handle)||(g=q.handle=function(b){return"undefined"!=typeof r&&r.event.triggered!==b.type?r.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(K)||[""],j=b.length;while(j--)h=ta.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n&&(l=r.event.special[n]||{},n=(e?l.delegateType:l.bindType)||n,l=r.event.special[n]||{},k=r.extend({type:n,origType:p,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&r.expr.match.needsContext.test(e),namespace:o.join(".")},f),(m=i[n])||(m=i[n]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,o,g)!==!1||a.addEventListener&&a.addEventListener(n,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),r.event.global[n]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=V.hasData(a)&&V.get(a);if(q&&(i=q.events)){b=(b||"").match(K)||[""],j=b.length;while(j--)if(h=ta.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n){l=r.event.special[n]||{},n=(d?l.delegateType:l.bindType)||n,m=i[n]||[],h=h[2]&&new RegExp("(^|\\.)"+o.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&p!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,o,q.handle)!==!1||r.removeEvent(a,n,q.handle),delete i[n])}else for(n in i)r.event.remove(a,n+b[j],c,d,!0);r.isEmptyObject(i)&&V.remove(a,"handle events")}},dispatch:function(a){var b=r.event.fix(a),c,d,e,f,g,h,i=new Array(arguments.length),j=(V.get(this,"events")||{})[b.type]||[],k=r.event.special[b.type]||{};for(i[0]=b,c=1;c<arguments.length;c++)i[c]=arguments[c];if(b.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,b)!==!1){h=r.event.handlers.call(this,b,j),c=0;while((f=h[c++])&&!b.isPropagationStopped()){b.currentTarget=f.elem,d=0;while((g=f.handlers[d++])&&!b.isImmediatePropagationStopped())b.rnamespace&&!b.rnamespace.test(g.namespace)||(b.handleObj=g,b.data=g.data,e=((r.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(b.result=e)===!1&&(b.preventDefault(),b.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,b),b.result}},handlers:function(a,b){var c,d,e,f,g,h=[],i=b.delegateCount,j=a.target;if(i&&j.nodeType&&!("click"===a.type&&a.button>=1))for(;j!==this;j=j.parentNode||this)if(1===j.nodeType&&("click"!==a.type||j.disabled!==!0)){for(f=[],g={},c=0;c<i;c++)d=b[c],e=d.selector+" ",void 0===g[e]&&(g[e]=d.needsContext?r(e,this).index(j)>-1:r.find(e,this,null,[j]).length),g[e]&&f.push(d);f.length&&h.push({elem:j,handlers:f})}return j=this,i<b.length&&h.push({elem:j,handlers:b.slice(i)}),h},addProp:function(a,b){Object.defineProperty(r.Event.prototype,a,{enumerable:!0,configurable:!0,get:r.isFunction(b)?function(){if(this.originalEvent)return b(this.originalEvent)}:function(){if(this.originalEvent)return this.originalEvent[a]},set:function(b){Object.defineProperty(this,a,{enumerable:!0,configurable:!0,writable:!0,value:b})}})},fix:function(a){return a[r.expando]?a:new r.Event(a)},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==wa()&&this.focus)return this.focus(),!1},delegateType:"focusin"},blur:{trigger:function(){if(this===wa()&&this.blur)return this.blur(),!1},delegateType:"focusout"},click:{trigger:function(){if("checkbox"===this.type&&this.click&&r.nodeName(this,"input"))return this.click(),!1},_default:function(a){return r.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}}},r.removeEvent=function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c)},r.Event=function(a,b){return this instanceof r.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?ua:va,this.target=a.target&&3===a.target.nodeType?a.target.parentNode:a.target,this.currentTarget=a.currentTarget,this.relatedTarget=a.relatedTarget):this.type=a,b&&r.extend(this,b),this.timeStamp=a&&a.timeStamp||r.now(),void(this[r.expando]=!0)):new r.Event(a,b)},r.Event.prototype={constructor:r.Event,isDefaultPrevented:va,isPropagationStopped:va,isImmediatePropagationStopped:va,isSimulated:!1,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=ua,a&&!this.isSimulated&&a.preventDefault()},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=ua,a&&!this.isSimulated&&a.stopPropagation()},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=ua,a&&!this.isSimulated&&a.stopImmediatePropagation(),this.stopPropagation()}},r.each({altKey:!0,bubbles:!0,cancelable:!0,changedTouches:!0,ctrlKey:!0,detail:!0,eventPhase:!0,metaKey:!0,pageX:!0,pageY:!0,shiftKey:!0,view:!0,"char":!0,charCode:!0,key:!0,keyCode:!0,button:!0,buttons:!0,clientX:!0,clientY:!0,offsetX:!0,offsetY:!0,pointerId:!0,pointerType:!0,screenX:!0,screenY:!0,targetTouches:!0,toElement:!0,touches:!0,which:function(a){var b=a.button;return null==a.which&&ra.test(a.type)?null!=a.charCode?a.charCode:a.keyCode:!a.which&&void 0!==b&&sa.test(a.type)?1&b?1:2&b?3:4&b?2:0:a.which}},r.event.addProp),r.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){r.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return e&&(e===d||r.contains(d,e))||(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),r.fn.extend({on:function(a,b,c,d){return xa(this,a,b,c,d)},one:function(a,b,c,d){return xa(this,a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,r(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return b!==!1&&"function"!=typeof b||(c=b,b=void 0),c===!1&&(c=va),this.each(function(){r.event.remove(this,a,c,b)})}});var ya=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,za=/<script|<style|<link/i,Aa=/checked\s*(?:[^=]|=\s*.checked.)/i,Ba=/^true\/(.*)/,Ca=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;function Da(a,b){return r.nodeName(a,"table")&&r.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a:a}function Ea(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function Fa(a){var b=Ba.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Ga(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(V.hasData(a)&&(f=V.access(a),g=V.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;c<d;c++)r.event.add(b,e,j[e][c])}W.hasData(a)&&(h=W.access(a),i=r.extend({},h),W.set(b,i))}}function Ha(a,b){var c=b.nodeName.toLowerCase();"input"===c&&ia.test(a.type)?b.checked=a.checked:"input"!==c&&"textarea"!==c||(b.defaultValue=a.defaultValue)}function Ia(a,b,c,d){b=g.apply([],b);var e,f,h,i,j,k,l=0,m=a.length,n=m-1,q=b[0],s=r.isFunction(q);if(s||m>1&&"string"==typeof q&&!o.checkClone&&Aa.test(q))return a.each(function(e){var f=a.eq(e);s&&(b[0]=q.call(this,e,f.html())),Ia(f,b,c,d)});if(m&&(e=pa(b,a[0].ownerDocument,!1,a,d),f=e.firstChild,1===e.childNodes.length&&(e=f),f||d)){for(h=r.map(ma(e,"script"),Ea),i=h.length;l<m;l++)j=e,l!==n&&(j=r.clone(j,!0,!0),i&&r.merge(h,ma(j,"script"))),c.call(a[l],j,l);if(i)for(k=h[h.length-1].ownerDocument,r.map(h,Fa),l=0;l<i;l++)j=h[l],ka.test(j.type||"")&&!V.access(j,"globalEval")&&r.contains(k,j)&&(j.src?r._evalUrl&&r._evalUrl(j.src):p(j.textContent.replace(Ca,""),k))}return a}function Ja(a,b,c){for(var d,e=b?r.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||r.cleanData(ma(d)),d.parentNode&&(c&&r.contains(d.ownerDocument,d)&&na(ma(d,"script")),d.parentNode.removeChild(d));return a}r.extend({htmlPrefilter:function(a){return a.replace(ya,"<$1></$2>")},clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=r.contains(a.ownerDocument,a);if(!(o.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||r.isXMLDoc(a)))for(g=ma(h),f=ma(a),d=0,e=f.length;d<e;d++)Ha(f[d],g[d]);if(b)if(c)for(f=f||ma(a),g=g||ma(h),d=0,e=f.length;d<e;d++)Ga(f[d],g[d]);else Ga(a,h);return g=ma(h,"script"),g.length>0&&na(g,!i&&ma(a,"script")),h},cleanData:function(a){for(var b,c,d,e=r.event.special,f=0;void 0!==(c=a[f]);f++)if(T(c)){if(b=c[V.expando]){if(b.events)for(d in b.events)e[d]?r.event.remove(c,d):r.removeEvent(c,d,b.handle);c[V.expando]=void 0}c[W.expando]&&(c[W.expando]=void 0)}}}),r.fn.extend({detach:function(a){return Ja(this,a,!0)},remove:function(a){return Ja(this,a)},text:function(a){return S(this,function(a){return void 0===a?r.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return Ia(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Da(this,a);b.appendChild(a)}})},prepend:function(){return Ia(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Da(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ia(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ia(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(r.cleanData(ma(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null!=a&&a,b=null==b?a:b,this.map(function(){return r.clone(this,a,b)})},html:function(a){return S(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!za.test(a)&&!la[(ja.exec(a)||["",""])[1].toLowerCase()]){a=r.htmlPrefilter(a);try{for(;c<d;c++)b=this[c]||{},1===b.nodeType&&(r.cleanData(ma(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return Ia(this,arguments,function(b){var c=this.parentNode;r.inArray(this,a)<0&&(r.cleanData(ma(this)),c&&c.replaceChild(b,this))},a)}}),r.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){r.fn[a]=function(a){for(var c,d=[],e=r(a),f=e.length-1,g=0;g<=f;g++)c=g===f?this:this.clone(!0),r(e[g])[b](c),h.apply(d,c.get());return this.pushStack(d)}});var Ka=/^margin/,La=new RegExp("^("+_+")(?!px)[a-z%]+$","i"),Ma=function(b){var c=b.ownerDocument.defaultView;return c&&c.opener||(c=a),c.getComputedStyle(b)};!function(){function b(){if(i){i.style.cssText="box-sizing:border-box;position:relative;display:block;margin:auto;border:1px;padding:1px;top:1%;width:50%",i.innerHTML="",qa.appendChild(h);var b=a.getComputedStyle(i);c="1%"!==b.top,g="2px"===b.marginLeft,e="4px"===b.width,i.style.marginRight="50%",f="4px"===b.marginRight,qa.removeChild(h),i=null}}var c,e,f,g,h=d.createElement("div"),i=d.createElement("div");i.style&&(i.style.backgroundClip="content-box",i.cloneNode(!0).style.backgroundClip="",o.clearCloneStyle="content-box"===i.style.backgroundClip,h.style.cssText="border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute",h.appendChild(i),r.extend(o,{pixelPosition:function(){return b(),c},boxSizingReliable:function(){return b(),e},pixelMarginRight:function(){return b(),f},reliableMarginLeft:function(){return b(),g}}))}();function Na(a,b,c){var d,e,f,g,h=a.style;return c=c||Ma(a),c&&(g=c.getPropertyValue(b)||c[b],""!==g||r.contains(a.ownerDocument,a)||(g=r.style(a,b)),!o.pixelMarginRight()&&La.test(g)&&Ka.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0!==g?g+"":g}function Oa(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}var Pa=/^(none|table(?!-c[ea]).+)/,Qa={position:"absolute",visibility:"hidden",display:"block"},Ra={letterSpacing:"0",fontWeight:"400"},Sa=["Webkit","Moz","ms"],Ta=d.createElement("div").style;function Ua(a){if(a in Ta)return a;var b=a[0].toUpperCase()+a.slice(1),c=Sa.length;while(c--)if(a=Sa[c]+b,a in Ta)return a}function Va(a,b,c){var d=aa.exec(b);return d?Math.max(0,d[2]-(c||0))+(d[3]||"px"):b}function Wa(a,b,c,d,e){var f,g=0;for(f=c===(d?"border":"content")?4:"width"===b?1:0;f<4;f+=2)"margin"===c&&(g+=r.css(a,c+ba[f],!0,e)),d?("content"===c&&(g-=r.css(a,"padding"+ba[f],!0,e)),"margin"!==c&&(g-=r.css(a,"border"+ba[f]+"Width",!0,e))):(g+=r.css(a,"padding"+ba[f],!0,e),"padding"!==c&&(g+=r.css(a,"border"+ba[f]+"Width",!0,e)));return g}function Xa(a,b,c){var d,e=!0,f=Ma(a),g="border-box"===r.css(a,"boxSizing",!1,f);if(a.getClientRects().length&&(d=a.getBoundingClientRect()[b]),d<=0||null==d){if(d=Na(a,b,f),(d<0||null==d)&&(d=a.style[b]),La.test(d))return d;e=g&&(o.boxSizingReliable()||d===a.style[b]),d=parseFloat(d)||0}return d+Wa(a,b,c||(g?"border":"content"),e,f)+"px"}r.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Na(a,"opacity");return""===c?"1":c}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=r.camelCase(b),i=a.style;return b=r.cssProps[h]||(r.cssProps[h]=Ua(h)||h),g=r.cssHooks[b]||r.cssHooks[h],void 0===c?g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b]:(f=typeof c,"string"===f&&(e=aa.exec(c))&&e[1]&&(c=ea(a,b,e),f="number"),null!=c&&c===c&&("number"===f&&(c+=e&&e[3]||(r.cssNumber[h]?"":"px")),o.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),g&&"set"in g&&void 0===(c=g.set(a,c,d))||(i[b]=c)),void 0)}},css:function(a,b,c,d){var e,f,g,h=r.camelCase(b);return b=r.cssProps[h]||(r.cssProps[h]=Ua(h)||h),g=r.cssHooks[b]||r.cssHooks[h],g&&"get"in g&&(e=g.get(a,!0,c)),void 0===e&&(e=Na(a,b,d)),"normal"===e&&b in Ra&&(e=Ra[b]),""===c||c?(f=parseFloat(e),c===!0||isFinite(f)?f||0:e):e}}),r.each(["height","width"],function(a,b){r.cssHooks[b]={get:function(a,c,d){if(c)return!Pa.test(r.css(a,"display"))||a.getClientRects().length&&a.getBoundingClientRect().width?Xa(a,b,d):da(a,Qa,function(){return Xa(a,b,d)})},set:function(a,c,d){var e,f=d&&Ma(a),g=d&&Wa(a,b,d,"border-box"===r.css(a,"boxSizing",!1,f),f);return g&&(e=aa.exec(c))&&"px"!==(e[3]||"px")&&(a.style[b]=c,c=r.css(a,b)),Va(a,c,g)}}}),r.cssHooks.marginLeft=Oa(o.reliableMarginLeft,function(a,b){if(b)return(parseFloat(Na(a,"marginLeft"))||a.getBoundingClientRect().left-da(a,{marginLeft:0},function(){return a.getBoundingClientRect().left}))+"px"}),r.each({margin:"",padding:"",border:"Width"},function(a,b){r.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];d<4;d++)e[a+ba[d]+b]=f[d]||f[d-2]||f[0];return e}},Ka.test(a)||(r.cssHooks[a+b].set=Va)}),r.fn.extend({css:function(a,b){return S(this,function(a,b,c){var d,e,f={},g=0;if(r.isArray(b)){for(d=Ma(a),e=b.length;g<e;g++)f[b[g]]=r.css(a,b[g],!1,d);return f}return void 0!==c?r.style(a,b,c):r.css(a,b)},a,b,arguments.length>1)}});function Ya(a,b,c,d,e){return new Ya.prototype.init(a,b,c,d,e)}r.Tween=Ya,Ya.prototype={constructor:Ya,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||r.easing._default,this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(r.cssNumber[c]?"":"px")},cur:function(){var a=Ya.propHooks[this.prop];return a&&a.get?a.get(this):Ya.propHooks._default.get(this)},run:function(a){var b,c=Ya.propHooks[this.prop];return this.options.duration?this.pos=b=r.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Ya.propHooks._default.set(this),this}},Ya.prototype.init.prototype=Ya.prototype,Ya.propHooks={_default:{get:function(a){var b;return 1!==a.elem.nodeType||null!=a.elem[a.prop]&&null==a.elem.style[a.prop]?a.elem[a.prop]:(b=r.css(a.elem,a.prop,""),b&&"auto"!==b?b:0)},set:function(a){r.fx.step[a.prop]?r.fx.step[a.prop](a):1!==a.elem.nodeType||null==a.elem.style[r.cssProps[a.prop]]&&!r.cssHooks[a.prop]?a.elem[a.prop]=a.now:r.style(a.elem,a.prop,a.now+a.unit)}}},Ya.propHooks.scrollTop=Ya.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},r.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2},_default:"swing"},r.fx=Ya.prototype.init,r.fx.step={};var Za,$a,_a=/^(?:toggle|show|hide)$/,ab=/queueHooks$/;function bb(){$a&&(a.requestAnimationFrame(bb),r.fx.tick())}function cb(){return a.setTimeout(function(){Za=void 0}),Za=r.now()}function db(a,b){var c,d=0,e={height:a};for(b=b?1:0;d<4;d+=2-b)c=ba[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function eb(a,b,c){for(var d,e=(hb.tweeners[b]||[]).concat(hb.tweeners["*"]),f=0,g=e.length;f<g;f++)if(d=e[f].call(c,b,a))return d}function fb(a,b,c){var d,e,f,g,h,i,j,k,l="width"in b||"height"in b,m=this,n={},o=a.style,p=a.nodeType&&ca(a),q=V.get(a,"fxshow");c.queue||(g=r._queueHooks(a,"fx"),null==g.unqueued&&(g.unqueued=0,h=g.empty.fire,g.empty.fire=function(){g.unqueued||h()}),g.unqueued++,m.always(function(){m.always(function(){g.unqueued--,r.queue(a,"fx").length||g.empty.fire()})}));for(d in b)if(e=b[d],_a.test(e)){if(delete b[d],f=f||"toggle"===e,e===(p?"hide":"show")){if("show"!==e||!q||void 0===q[d])continue;p=!0}n[d]=q&&q[d]||r.style(a,d)}if(i=!r.isEmptyObject(b),i||!r.isEmptyObject(n)){l&&1===a.nodeType&&(c.overflow=[o.overflow,o.overflowX,o.overflowY],j=q&&q.display,null==j&&(j=V.get(a,"display")),k=r.css(a,"display"),"none"===k&&(j?k=j:(ha([a],!0),j=a.style.display||j,k=r.css(a,"display"),ha([a]))),("inline"===k||"inline-block"===k&&null!=j)&&"none"===r.css(a,"float")&&(i||(m.done(function(){o.display=j}),null==j&&(k=o.display,j="none"===k?"":k)),o.display="inline-block")),c.overflow&&(o.overflow="hidden",m.always(function(){o.overflow=c.overflow[0],o.overflowX=c.overflow[1],o.overflowY=c.overflow[2]})),i=!1;for(d in n)i||(q?"hidden"in q&&(p=q.hidden):q=V.access(a,"fxshow",{display:j}),f&&(q.hidden=!p),p&&ha([a],!0),m.done(function(){p||ha([a]),V.remove(a,"fxshow");for(d in n)r.style(a,d,n[d])})),i=eb(p?q[d]:0,d,m),d in q||(q[d]=i.start,p&&(i.end=i.start,i.start=0))}}function gb(a,b){var c,d,e,f,g;for(c in a)if(d=r.camelCase(c),e=b[d],f=a[c],r.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=r.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function hb(a,b,c){var d,e,f=0,g=hb.prefilters.length,h=r.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=Za||cb(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;g<i;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),f<1&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:r.extend({},b),opts:r.extend(!0,{specialEasing:{},easing:r.easing._default},c),originalProperties:b,originalOptions:c,startTime:Za||cb(),duration:c.duration,tweens:[],createTween:function(b,c){var d=r.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;c<d;c++)j.tweens[c].run(1);return b?(h.notifyWith(a,[j,1,0]),h.resolveWith(a,[j,b])):h.rejectWith(a,[j,b]),this}}),k=j.props;for(gb(k,j.opts.specialEasing);f<g;f++)if(d=hb.prefilters[f].call(j,a,k,j.opts))return r.isFunction(d.stop)&&(r._queueHooks(j.elem,j.opts.queue).stop=r.proxy(d.stop,d)),d;return r.map(k,eb,j),r.isFunction(j.opts.start)&&j.opts.start.call(a,j),r.fx.timer(r.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}r.Animation=r.extend(hb,{tweeners:{"*":[function(a,b){var c=this.createTween(a,b);return ea(c.elem,a,aa.exec(b),c),c}]},tweener:function(a,b){r.isFunction(a)?(b=a,a=["*"]):a=a.match(K);for(var c,d=0,e=a.length;d<e;d++)c=a[d],hb.tweeners[c]=hb.tweeners[c]||[],hb.tweeners[c].unshift(b)},prefilters:[fb],prefilter:function(a,b){b?hb.prefilters.unshift(a):hb.prefilters.push(a)}}),r.speed=function(a,b,c){var e=a&&"object"==typeof a?r.extend({},a):{complete:c||!c&&b||r.isFunction(a)&&a,duration:a,easing:c&&b||b&&!r.isFunction(b)&&b};return r.fx.off||d.hidden?e.duration=0:"number"!=typeof e.duration&&(e.duration in r.fx.speeds?e.duration=r.fx.speeds[e.duration]:e.duration=r.fx.speeds._default),null!=e.queue&&e.queue!==!0||(e.queue="fx"),e.old=e.complete,e.complete=function(){r.isFunction(e.old)&&e.old.call(this),e.queue&&r.dequeue(this,e.queue)},e},r.fn.extend({fadeTo:function(a,b,c,d){return this.filter(ca).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=r.isEmptyObject(a),f=r.speed(b,c,d),g=function(){var b=hb(this,r.extend({},a),f);(e||V.get(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=r.timers,g=V.get(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&ab.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));!b&&c||r.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=V.get(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=r.timers,g=d?d.length:0;for(c.finish=!0,r.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;b<g;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),r.each(["toggle","show","hide"],function(a,b){var c=r.fn[b];r.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(db(b,!0),a,d,e)}}),r.each({slideDown:db("show"),slideUp:db("hide"),slideToggle:db("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){r.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),r.timers=[],r.fx.tick=function(){var a,b=0,c=r.timers;for(Za=r.now();b<c.length;b++)a=c[b],a()||c[b]!==a||c.splice(b--,1);c.length||r.fx.stop(),Za=void 0},r.fx.timer=function(a){r.timers.push(a),a()?r.fx.start():r.timers.pop()},r.fx.interval=13,r.fx.start=function(){$a||($a=a.requestAnimationFrame?a.requestAnimationFrame(bb):a.setInterval(r.fx.tick,r.fx.interval))},r.fx.stop=function(){a.cancelAnimationFrame?a.cancelAnimationFrame($a):a.clearInterval($a),$a=null},r.fx.speeds={slow:600,fast:200,_default:400},r.fn.delay=function(b,c){return b=r.fx?r.fx.speeds[b]||b:b,c=c||"fx",this.queue(c,function(c,d){var e=a.setTimeout(c,b);d.stop=function(){a.clearTimeout(e)}})},function(){var a=d.createElement("input"),b=d.createElement("select"),c=b.appendChild(d.createElement("option"));a.type="checkbox",o.checkOn=""!==a.value,o.optSelected=c.selected,a=d.createElement("input"),a.value="t",a.type="radio",o.radioValue="t"===a.value}();var ib,jb=r.expr.attrHandle;r.fn.extend({attr:function(a,b){return S(this,r.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){r.removeAttr(this,a)})}}),r.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return"undefined"==typeof a.getAttribute?r.prop(a,b,c):(1===f&&r.isXMLDoc(a)||(e=r.attrHooks[b.toLowerCase()]||(r.expr.match.bool.test(b)?ib:void 0)),
-void 0!==c?null===c?void r.removeAttr(a,b):e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:(a.setAttribute(b,c+""),c):e&&"get"in e&&null!==(d=e.get(a,b))?d:(d=r.find.attr(a,b),null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!o.radioValue&&"radio"===b&&r.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d=0,e=b&&b.match(K);if(e&&1===a.nodeType)while(c=e[d++])a.removeAttribute(c)}}),ib={set:function(a,b,c){return b===!1?r.removeAttr(a,c):a.setAttribute(c,c),c}},r.each(r.expr.match.bool.source.match(/\w+/g),function(a,b){var c=jb[b]||r.find.attr;jb[b]=function(a,b,d){var e,f,g=b.toLowerCase();return d||(f=jb[g],jb[g]=e,e=null!=c(a,b,d)?g:null,jb[g]=f),e}});var kb=/^(?:input|select|textarea|button)$/i,lb=/^(?:a|area)$/i;r.fn.extend({prop:function(a,b){return S(this,r.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[r.propFix[a]||a]})}}),r.extend({prop:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return 1===f&&r.isXMLDoc(a)||(b=r.propFix[b]||b,e=r.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=r.find.attr(a,"tabindex");return b?parseInt(b,10):kb.test(a.nodeName)||lb.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),o.optSelected||(r.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null},set:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}}),r.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){r.propFix[this.toLowerCase()]=this});function mb(a){var b=a.match(K)||[];return b.join(" ")}function nb(a){return a.getAttribute&&a.getAttribute("class")||""}r.fn.extend({addClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).addClass(a.call(this,b,nb(this)))});if("string"==typeof a&&a){b=a.match(K)||[];while(c=this[i++])if(e=nb(c),d=1===c.nodeType&&" "+mb(e)+" "){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=mb(d),e!==h&&c.setAttribute("class",h)}}return this},removeClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).removeClass(a.call(this,b,nb(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(K)||[];while(c=this[i++])if(e=nb(c),d=1===c.nodeType&&" "+mb(e)+" "){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=mb(d),e!==h&&c.setAttribute("class",h)}}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):r.isFunction(a)?this.each(function(c){r(this).toggleClass(a.call(this,c,nb(this),b),b)}):this.each(function(){var b,d,e,f;if("string"===c){d=0,e=r(this),f=a.match(K)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else void 0!==a&&"boolean"!==c||(b=nb(this),b&&V.set(this,"__className__",b),this.setAttribute&&this.setAttribute("class",b||a===!1?"":V.get(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+mb(nb(c))+" ").indexOf(b)>-1)return!0;return!1}});var ob=/\r/g;r.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=r.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,r(this).val()):a,null==e?e="":"number"==typeof e?e+="":r.isArray(e)&&(e=r.map(e,function(a){return null==a?"":a+""})),b=r.valHooks[this.type]||r.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=r.valHooks[e.type]||r.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(ob,""):null==c?"":c)}}}),r.extend({valHooks:{option:{get:function(a){var b=r.find.attr(a,"value");return null!=b?b:mb(r.text(a))}},select:{get:function(a){var b,c,d,e=a.options,f=a.selectedIndex,g="select-one"===a.type,h=g?null:[],i=g?f+1:e.length;for(d=f<0?i:g?f:0;d<i;d++)if(c=e[d],(c.selected||d===f)&&!c.disabled&&(!c.parentNode.disabled||!r.nodeName(c.parentNode,"optgroup"))){if(b=r(c).val(),g)return b;h.push(b)}return h},set:function(a,b){var c,d,e=a.options,f=r.makeArray(b),g=e.length;while(g--)d=e[g],(d.selected=r.inArray(r.valHooks.option.get(d),f)>-1)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),r.each(["radio","checkbox"],function(){r.valHooks[this]={set:function(a,b){if(r.isArray(b))return a.checked=r.inArray(r(a).val(),b)>-1}},o.checkOn||(r.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var pb=/^(?:focusinfocus|focusoutblur)$/;r.extend(r.event,{trigger:function(b,c,e,f){var g,h,i,j,k,m,n,o=[e||d],p=l.call(b,"type")?b.type:b,q=l.call(b,"namespace")?b.namespace.split("."):[];if(h=i=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!pb.test(p+r.event.triggered)&&(p.indexOf(".")>-1&&(q=p.split("."),p=q.shift(),q.sort()),k=p.indexOf(":")<0&&"on"+p,b=b[r.expando]?b:new r.Event(p,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=q.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:r.makeArray(c,[b]),n=r.event.special[p]||{},f||!n.trigger||n.trigger.apply(e,c)!==!1)){if(!f&&!n.noBubble&&!r.isWindow(e)){for(j=n.delegateType||p,pb.test(j+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),i=h;i===(e.ownerDocument||d)&&o.push(i.defaultView||i.parentWindow||a)}g=0;while((h=o[g++])&&!b.isPropagationStopped())b.type=g>1?j:n.bindType||p,m=(V.get(h,"events")||{})[b.type]&&V.get(h,"handle"),m&&m.apply(h,c),m=k&&h[k],m&&m.apply&&T(h)&&(b.result=m.apply(h,c),b.result===!1&&b.preventDefault());return b.type=p,f||b.isDefaultPrevented()||n._default&&n._default.apply(o.pop(),c)!==!1||!T(e)||k&&r.isFunction(e[p])&&!r.isWindow(e)&&(i=e[k],i&&(e[k]=null),r.event.triggered=p,e[p](),r.event.triggered=void 0,i&&(e[k]=i)),b.result}},simulate:function(a,b,c){var d=r.extend(new r.Event,c,{type:a,isSimulated:!0});r.event.trigger(d,null,b)}}),r.fn.extend({trigger:function(a,b){return this.each(function(){r.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];if(c)return r.event.trigger(a,b,c,!0)}}),r.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(a,b){r.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),r.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),o.focusin="onfocusin"in a,o.focusin||r.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){r.event.simulate(b,a.target,r.event.fix(a))};r.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=V.access(d,b);e||d.addEventListener(a,c,!0),V.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=V.access(d,b)-1;e?V.access(d,b,e):(d.removeEventListener(a,c,!0),V.remove(d,b))}}});var qb=a.location,rb=r.now(),sb=/\?/;r.parseXML=function(b){var c;if(!b||"string"!=typeof b)return null;try{c=(new a.DOMParser).parseFromString(b,"text/xml")}catch(d){c=void 0}return c&&!c.getElementsByTagName("parsererror").length||r.error("Invalid XML: "+b),c};var tb=/\[\]$/,ub=/\r?\n/g,vb=/^(?:submit|button|image|reset|file)$/i,wb=/^(?:input|select|textarea|keygen)/i;function xb(a,b,c,d){var e;if(r.isArray(b))r.each(b,function(b,e){c||tb.test(a)?d(a,e):xb(a+"["+("object"==typeof e&&null!=e?b:"")+"]",e,c,d)});else if(c||"object"!==r.type(b))d(a,b);else for(e in b)xb(a+"["+e+"]",b[e],c,d)}r.param=function(a,b){var c,d=[],e=function(a,b){var c=r.isFunction(b)?b():b;d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(null==c?"":c)};if(r.isArray(a)||a.jquery&&!r.isPlainObject(a))r.each(a,function(){e(this.name,this.value)});else for(c in a)xb(c,a[c],b,e);return d.join("&")},r.fn.extend({serialize:function(){return r.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=r.prop(this,"elements");return a?r.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!r(this).is(":disabled")&&wb.test(this.nodeName)&&!vb.test(a)&&(this.checked||!ia.test(a))}).map(function(a,b){var c=r(this).val();return null==c?null:r.isArray(c)?r.map(c,function(a){return{name:b.name,value:a.replace(ub,"\r\n")}}):{name:b.name,value:c.replace(ub,"\r\n")}}).get()}});var yb=/%20/g,zb=/#.*$/,Ab=/([?&])_=[^&]*/,Bb=/^(.*?):[ \t]*([^\r\n]*)$/gm,Cb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Db=/^(?:GET|HEAD)$/,Eb=/^\/\//,Fb={},Gb={},Hb="*/".concat("*"),Ib=d.createElement("a");Ib.href=qb.href;function Jb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(K)||[];if(r.isFunction(c))while(d=f[e++])"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Kb(a,b,c,d){var e={},f=a===Gb;function g(h){var i;return e[h]=!0,r.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Lb(a,b){var c,d,e=r.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&r.extend(!0,a,d),a}function Mb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader("Content-Type"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+" "+i[0]]){f=e;break}g||(g=e)}f=f||g}if(f)return f!==i[0]&&i.unshift(f),c[f]}function Nb(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}r.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:qb.href,type:"GET",isLocal:Cb.test(qb.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Hb,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":r.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Lb(Lb(a,r.ajaxSettings),b):Lb(r.ajaxSettings,a)},ajaxPrefilter:Jb(Fb),ajaxTransport:Jb(Gb),ajax:function(b,c){"object"==typeof b&&(c=b,b=void 0),c=c||{};var e,f,g,h,i,j,k,l,m,n,o=r.ajaxSetup({},c),p=o.context||o,q=o.context&&(p.nodeType||p.jquery)?r(p):r.event,s=r.Deferred(),t=r.Callbacks("once memory"),u=o.statusCode||{},v={},w={},x="canceled",y={readyState:0,getResponseHeader:function(a){var b;if(k){if(!h){h={};while(b=Bb.exec(g))h[b[1].toLowerCase()]=b[2]}b=h[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return k?g:null},setRequestHeader:function(a,b){return null==k&&(a=w[a.toLowerCase()]=w[a.toLowerCase()]||a,v[a]=b),this},overrideMimeType:function(a){return null==k&&(o.mimeType=a),this},statusCode:function(a){var b;if(a)if(k)y.always(a[y.status]);else for(b in a)u[b]=[u[b],a[b]];return this},abort:function(a){var b=a||x;return e&&e.abort(b),A(0,b),this}};if(s.promise(y),o.url=((b||o.url||qb.href)+"").replace(Eb,qb.protocol+"//"),o.type=c.method||c.type||o.method||o.type,o.dataTypes=(o.dataType||"*").toLowerCase().match(K)||[""],null==o.crossDomain){j=d.createElement("a");try{j.href=o.url,j.href=j.href,o.crossDomain=Ib.protocol+"//"+Ib.host!=j.protocol+"//"+j.host}catch(z){o.crossDomain=!0}}if(o.data&&o.processData&&"string"!=typeof o.data&&(o.data=r.param(o.data,o.traditional)),Kb(Fb,o,c,y),k)return y;l=r.event&&o.global,l&&0===r.active++&&r.event.trigger("ajaxStart"),o.type=o.type.toUpperCase(),o.hasContent=!Db.test(o.type),f=o.url.replace(zb,""),o.hasContent?o.data&&o.processData&&0===(o.contentType||"").indexOf("application/x-www-form-urlencoded")&&(o.data=o.data.replace(yb,"+")):(n=o.url.slice(f.length),o.data&&(f+=(sb.test(f)?"&":"?")+o.data,delete o.data),o.cache===!1&&(f=f.replace(Ab,"$1"),n=(sb.test(f)?"&":"?")+"_="+rb++ +n),o.url=f+n),o.ifModified&&(r.lastModified[f]&&y.setRequestHeader("If-Modified-Since",r.lastModified[f]),r.etag[f]&&y.setRequestHeader("If-None-Match",r.etag[f])),(o.data&&o.hasContent&&o.contentType!==!1||c.contentType)&&y.setRequestHeader("Content-Type",o.contentType),y.setRequestHeader("Accept",o.dataTypes[0]&&o.accepts[o.dataTypes[0]]?o.accepts[o.dataTypes[0]]+("*"!==o.dataTypes[0]?", "+Hb+"; q=0.01":""):o.accepts["*"]);for(m in o.headers)y.setRequestHeader(m,o.headers[m]);if(o.beforeSend&&(o.beforeSend.call(p,y,o)===!1||k))return y.abort();if(x="abort",t.add(o.complete),y.done(o.success),y.fail(o.error),e=Kb(Gb,o,c,y)){if(y.readyState=1,l&&q.trigger("ajaxSend",[y,o]),k)return y;o.async&&o.timeout>0&&(i=a.setTimeout(function(){y.abort("timeout")},o.timeout));try{k=!1,e.send(v,A)}catch(z){if(k)throw z;A(-1,z)}}else A(-1,"No Transport");function A(b,c,d,h){var j,m,n,v,w,x=c;k||(k=!0,i&&a.clearTimeout(i),e=void 0,g=h||"",y.readyState=b>0?4:0,j=b>=200&&b<300||304===b,d&&(v=Mb(o,y,d)),v=Nb(o,v,y,j),j?(o.ifModified&&(w=y.getResponseHeader("Last-Modified"),w&&(r.lastModified[f]=w),w=y.getResponseHeader("etag"),w&&(r.etag[f]=w)),204===b||"HEAD"===o.type?x="nocontent":304===b?x="notmodified":(x=v.state,m=v.data,n=v.error,j=!n)):(n=x,!b&&x||(x="error",b<0&&(b=0))),y.status=b,y.statusText=(c||x)+"",j?s.resolveWith(p,[m,x,y]):s.rejectWith(p,[y,x,n]),y.statusCode(u),u=void 0,l&&q.trigger(j?"ajaxSuccess":"ajaxError",[y,o,j?m:n]),t.fireWith(p,[y,x]),l&&(q.trigger("ajaxComplete",[y,o]),--r.active||r.event.trigger("ajaxStop")))}return y},getJSON:function(a,b,c){return r.get(a,b,c,"json")},getScript:function(a,b){return r.get(a,void 0,b,"script")}}),r.each(["get","post"],function(a,b){r[b]=function(a,c,d,e){return r.isFunction(c)&&(e=e||d,d=c,c=void 0),r.ajax(r.extend({url:a,type:b,dataType:e,data:c,success:d},r.isPlainObject(a)&&a))}}),r._evalUrl=function(a){return r.ajax({url:a,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},r.fn.extend({wrapAll:function(a){var b;return this[0]&&(r.isFunction(a)&&(a=a.call(this[0])),b=r(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this},wrapInner:function(a){return r.isFunction(a)?this.each(function(b){r(this).wrapInner(a.call(this,b))}):this.each(function(){var b=r(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=r.isFunction(a);return this.each(function(c){r(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(a){return this.parent(a).not("body").each(function(){r(this).replaceWith(this.childNodes)}),this}}),r.expr.pseudos.hidden=function(a){return!r.expr.pseudos.visible(a)},r.expr.pseudos.visible=function(a){return!!(a.offsetWidth||a.offsetHeight||a.getClientRects().length)},r.ajaxSettings.xhr=function(){try{return new a.XMLHttpRequest}catch(b){}};var Ob={0:200,1223:204},Pb=r.ajaxSettings.xhr();o.cors=!!Pb&&"withCredentials"in Pb,o.ajax=Pb=!!Pb,r.ajaxTransport(function(b){var c,d;if(o.cors||Pb&&!b.crossDomain)return{send:function(e,f){var g,h=b.xhr();if(h.open(b.type,b.url,b.async,b.username,b.password),b.xhrFields)for(g in b.xhrFields)h[g]=b.xhrFields[g];b.mimeType&&h.overrideMimeType&&h.overrideMimeType(b.mimeType),b.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest");for(g in e)h.setRequestHeader(g,e[g]);c=function(a){return function(){c&&(c=d=h.onload=h.onerror=h.onabort=h.onreadystatechange=null,"abort"===a?h.abort():"error"===a?"number"!=typeof h.status?f(0,"error"):f(h.status,h.statusText):f(Ob[h.status]||h.status,h.statusText,"text"!==(h.responseType||"text")||"string"!=typeof h.responseText?{binary:h.response}:{text:h.responseText},h.getAllResponseHeaders()))}},h.onload=c(),d=h.onerror=c("error"),void 0!==h.onabort?h.onabort=d:h.onreadystatechange=function(){4===h.readyState&&a.setTimeout(function(){c&&d()})},c=c("abort");try{h.send(b.hasContent&&b.data||null)}catch(i){if(c)throw i}},abort:function(){c&&c()}}}),r.ajaxPrefilter(function(a){a.crossDomain&&(a.contents.script=!1)}),r.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(a){return r.globalEval(a),a}}}),r.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),r.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(e,f){b=r("<script>").prop({charset:a.scriptCharset,src:a.url}).on("load error",c=function(a){b.remove(),c=null,a&&f("error"===a.type?404:200,a.type)}),d.head.appendChild(b[0])},abort:function(){c&&c()}}}});var Qb=[],Rb=/(=)\?(?=&|$)|\?\?/;r.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=Qb.pop()||r.expando+"_"+rb++;return this[a]=!0,a}}),r.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(Rb.test(b.url)?"url":"string"==typeof b.data&&0===(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&Rb.test(b.data)&&"data");if(h||"jsonp"===b.dataTypes[0])return e=b.jsonpCallback=r.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(Rb,"$1"+e):b.jsonp!==!1&&(b.url+=(sb.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||r.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){void 0===f?r(a).removeProp(e):a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,Qb.push(e)),g&&r.isFunction(f)&&f(g[0]),g=f=void 0}),"script"}),o.createHTMLDocument=function(){var a=d.implementation.createHTMLDocument("").body;return a.innerHTML="<form></form><form></form>",2===a.childNodes.length}(),r.parseHTML=function(a,b,c){if("string"!=typeof a)return[];"boolean"==typeof b&&(c=b,b=!1);var e,f,g;return b||(o.createHTMLDocument?(b=d.implementation.createHTMLDocument(""),e=b.createElement("base"),e.href=d.location.href,b.head.appendChild(e)):b=d),f=B.exec(a),g=!c&&[],f?[b.createElement(f[1])]:(f=pa([a],b,g),g&&g.length&&r(g).remove(),r.merge([],f.childNodes))},r.fn.load=function(a,b,c){var d,e,f,g=this,h=a.indexOf(" ");return h>-1&&(d=mb(a.slice(h)),a=a.slice(0,h)),r.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(e="POST"),g.length>0&&r.ajax({url:a,type:e||"GET",dataType:"html",data:b}).done(function(a){f=arguments,g.html(d?r("<div>").append(r.parseHTML(a)).find(d):a)}).always(c&&function(a,b){g.each(function(){c.apply(this,f||[a.responseText,b,a])})}),this},r.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){r.fn[b]=function(a){return this.on(b,a)}}),r.expr.pseudos.animated=function(a){return r.grep(r.timers,function(b){return a===b.elem}).length};function Sb(a){return r.isWindow(a)?a:9===a.nodeType&&a.defaultView}r.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=r.css(a,"position"),l=r(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=r.css(a,"top"),i=r.css(a,"left"),j=("absolute"===k||"fixed"===k)&&(f+i).indexOf("auto")>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),r.isFunction(b)&&(b=b.call(a,c,r.extend({},h))),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using"in b?b.using.call(a,m):l.css(m)}},r.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){r.offset.setOffset(this,a,b)});var b,c,d,e,f=this[0];if(f)return f.getClientRects().length?(d=f.getBoundingClientRect(),d.width||d.height?(e=f.ownerDocument,c=Sb(e),b=e.documentElement,{top:d.top+c.pageYOffset-b.clientTop,left:d.left+c.pageXOffset-b.clientLeft}):d):{top:0,left:0}},position:function(){if(this[0]){var a,b,c=this[0],d={top:0,left:0};return"fixed"===r.css(c,"position")?b=c.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),r.nodeName(a[0],"html")||(d=a.offset()),d={top:d.top+r.css(a[0],"borderTopWidth",!0),left:d.left+r.css(a[0],"borderLeftWidth",!0)}),{top:b.top-d.top-r.css(c,"marginTop",!0),left:b.left-d.left-r.css(c,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent;while(a&&"static"===r.css(a,"position"))a=a.offsetParent;return a||qa})}}),r.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c="pageYOffset"===b;r.fn[a]=function(d){return S(this,function(a,d,e){var f=Sb(a);return void 0===e?f?f[b]:a[d]:void(f?f.scrollTo(c?f.pageXOffset:e,c?e:f.pageYOffset):a[d]=e)},a,d,arguments.length)}}),r.each(["top","left"],function(a,b){r.cssHooks[b]=Oa(o.pixelPosition,function(a,c){if(c)return c=Na(a,b),La.test(c)?r(a).position()[b]+"px":c})}),r.each({Height:"height",Width:"width"},function(a,b){r.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){r.fn[d]=function(e,f){var g=arguments.length&&(c||"boolean"!=typeof e),h=c||(e===!0||f===!0?"margin":"border");return S(this,function(b,c,e){var f;return r.isWindow(b)?0===d.indexOf("outer")?b["inner"+a]:b.document.documentElement["client"+a]:9===b.nodeType?(f=b.documentElement,Math.max(b.body["scroll"+a],f["scroll"+a],b.body["offset"+a],f["offset"+a],f["client"+a])):void 0===e?r.css(b,c,h):r.style(b,c,e,h)},b,g?e:void 0,g)}})}),r.fn.extend({bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}}),r.parseJSON=JSON.parse,"function"==typeof define&&define.amd&&define("jquery",[],function(){return r});var Tb=a.jQuery,Ub=a.$;return r.noConflict=function(b){return a.$===r&&(a.$=Ub),b&&a.jQuery===r&&(a.jQuery=Tb),r},b||(a.jQuery=a.$=r),r});
+/*! jQuery v3.3.1 | (c) JS Foundation and other contributors | jquery.org/license */
+!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(e,t){"use strict";var n=[],r=e.document,i=Object.getPrototypeOf,o=n.slice,a=n.concat,s=n.push,u=n.indexOf,l={},c=l.toString,f=l.hasOwnProperty,p=f.toString,d=p.call(Object),h={},g=function e(t){return"function"==typeof t&&"number"!=typeof t.nodeType},y=function e(t){return null!=t&&t===t.window},v={type:!0,src:!0,noModule:!0};function m(e,t,n){var i,o=(t=t||r).createElement("script");if(o.text=e,n)for(i in v)n[i]&&(o[i]=n[i]);t.head.appendChild(o).parentNode.removeChild(o)}function x(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[c.call(e)]||"object":typeof e}var b="3.3.1",w=function(e,t){return new w.fn.init(e,t)},T=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;w.fn=w.prototype={jquery:"3.3.1",constructor:w,length:0,toArray:function(){return o.call(this)},get:function(e){return null==e?o.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=w.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return w.each(this,e)},map:function(e){return this.pushStack(w.map(this,function(t,n){return e.call(t,n,t)}))},slice:function(){return this.pushStack(o.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(n>=0&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:s,sort:n.sort,splice:n.splice},w.extend=w.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for("boolean"==typeof a&&(l=a,a=arguments[s]||{},s++),"object"==typeof a||g(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(e=arguments[s]))for(t in e)n=a[t],a!==(r=e[t])&&(l&&r&&(w.isPlainObject(r)||(i=Array.isArray(r)))?(i?(i=!1,o=n&&Array.isArray(n)?n:[]):o=n&&w.isPlainObject(n)?n:{},a[t]=w.extend(l,o,r)):void 0!==r&&(a[t]=r));return a},w.extend({expando:"jQuery"+("3.3.1"+Math.random()).replace(/\D/g,""),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isPlainObject:function(e){var t,n;return!(!e||"[object Object]"!==c.call(e))&&(!(t=i(e))||"function"==typeof(n=f.call(t,"constructor")&&t.constructor)&&p.call(n)===d)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},globalEval:function(e){m(e)},each:function(e,t){var n,r=0;if(C(e)){for(n=e.length;r<n;r++)if(!1===t.call(e[r],r,e[r]))break}else for(r in e)if(!1===t.call(e[r],r,e[r]))break;return e},trim:function(e){return null==e?"":(e+"").replace(T,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(C(Object(e))?w.merge(n,"string"==typeof e?[e]:e):s.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:u.call(t,e,n)},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;r++)e[i++]=t[r];return e.length=i,e},grep:function(e,t,n){for(var r,i=[],o=0,a=e.length,s=!n;o<a;o++)(r=!t(e[o],o))!==s&&i.push(e[o]);return i},map:function(e,t,n){var r,i,o=0,s=[];if(C(e))for(r=e.length;o<r;o++)null!=(i=t(e[o],o,n))&&s.push(i);else for(o in e)null!=(i=t(e[o],o,n))&&s.push(i);return a.apply([],s)},guid:1,support:h}),"function"==typeof Symbol&&(w.fn[Symbol.iterator]=n[Symbol.iterator]),w.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function C(e){var t=!!e&&"length"in e&&e.length,n=x(e);return!g(e)&&!y(e)&&("array"===n||0===t||"number"==typeof t&&t>0&&t-1 in e)}var E=function(e){var t,n,r,i,o,a,s,u,l,c,f,p,d,h,g,y,v,m,x,b="sizzle"+1*new Date,w=e.document,T=0,C=0,E=ae(),k=ae(),S=ae(),D=function(e,t){return e===t&&(f=!0),0},N={}.hasOwnProperty,A=[],j=A.pop,q=A.push,L=A.push,H=A.slice,O=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},P="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",R="(?:\\\\.|[\\w-]|[^\0-\\xa0])+",I="\\["+M+"*("+R+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+R+"))|)"+M+"*\\]",W=":("+R+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+I+")*)|.*)\\)|)",$=new RegExp(M+"+","g"),B=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),F=new RegExp("^"+M+"*,"+M+"*"),_=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),z=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),X=new RegExp(W),U=new RegExp("^"+R+"$"),V={ID:new RegExp("^#("+R+")"),CLASS:new RegExp("^\\.("+R+")"),TAG:new RegExp("^("+R+"|[*])"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+W),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+P+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},G=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Q=/^[^{]+\{\s*\[native \w/,J=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,K=/[+~]/,Z=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ee=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},te=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ne=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},re=function(){p()},ie=me(function(e){return!0===e.disabled&&("form"in e||"label"in e)},{dir:"parentNode",next:"legend"});try{L.apply(A=H.call(w.childNodes),w.childNodes),A[w.childNodes.length].nodeType}catch(e){L={apply:A.length?function(e,t){q.apply(e,H.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function oe(e,t,r,i){var o,s,l,c,f,h,v,m=t&&t.ownerDocument,T=t?t.nodeType:9;if(r=r||[],"string"!=typeof e||!e||1!==T&&9!==T&&11!==T)return r;if(!i&&((t?t.ownerDocument||t:w)!==d&&p(t),t=t||d,g)){if(11!==T&&(f=J.exec(e)))if(o=f[1]){if(9===T){if(!(l=t.getElementById(o)))return r;if(l.id===o)return r.push(l),r}else if(m&&(l=m.getElementById(o))&&x(t,l)&&l.id===o)return r.push(l),r}else{if(f[2])return L.apply(r,t.getElementsByTagName(e)),r;if((o=f[3])&&n.getElementsByClassName&&t.getElementsByClassName)return L.apply(r,t.getElementsByClassName(o)),r}if(n.qsa&&!S[e+" "]&&(!y||!y.test(e))){if(1!==T)m=t,v=e;else if("object"!==t.nodeName.toLowerCase()){(c=t.getAttribute("id"))?c=c.replace(te,ne):t.setAttribute("id",c=b),s=(h=a(e)).length;while(s--)h[s]="#"+c+" "+ve(h[s]);v=h.join(","),m=K.test(e)&&ge(t.parentNode)||t}if(v)try{return L.apply(r,m.querySelectorAll(v)),r}catch(e){}finally{c===b&&t.removeAttribute("id")}}}return u(e.replace(B,"$1"),t,r,i)}function ae(){var e=[];function t(n,i){return e.push(n+" ")>r.cacheLength&&delete t[e.shift()],t[n+" "]=i}return t}function se(e){return e[b]=!0,e}function ue(e){var t=d.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function le(e,t){var n=e.split("|"),i=n.length;while(i--)r.attrHandle[n[i]]=t}function ce(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function fe(e){return function(t){return"input"===t.nodeName.toLowerCase()&&t.type===e}}function pe(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function de(e){return function(t){return"form"in t?t.parentNode&&!1===t.disabled?"label"in t?"label"in t.parentNode?t.parentNode.disabled===e:t.disabled===e:t.isDisabled===e||t.isDisabled!==!e&&ie(t)===e:t.disabled===e:"label"in t&&t.disabled===e}}function he(e){return se(function(t){return t=+t,se(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function ge(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}n=oe.support={},o=oe.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&"HTML"!==t.nodeName},p=oe.setDocument=function(e){var t,i,a=e?e.ownerDocument||e:w;return a!==d&&9===a.nodeType&&a.documentElement?(d=a,h=d.documentElement,g=!o(d),w!==d&&(i=d.defaultView)&&i.top!==i&&(i.addEventListener?i.addEventListener("unload",re,!1):i.attachEvent&&i.attachEvent("onunload",re)),n.attributes=ue(function(e){return e.className="i",!e.getAttribute("className")}),n.getElementsByTagName=ue(function(e){return e.appendChild(d.createComment("")),!e.getElementsByTagName("*").length}),n.getElementsByClassName=Q.test(d.getElementsByClassName),n.getById=ue(function(e){return h.appendChild(e).id=b,!d.getElementsByName||!d.getElementsByName(b).length}),n.getById?(r.filter.ID=function(e){var t=e.replace(Z,ee);return function(e){return e.getAttribute("id")===t}},r.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&g){var n=t.getElementById(e);return n?[n]:[]}}):(r.filter.ID=function(e){var t=e.replace(Z,ee);return function(e){var n="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return n&&n.value===t}},r.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&g){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),r.find.TAG=n.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):n.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},r.find.CLASS=n.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&g)return t.getElementsByClassName(e)},v=[],y=[],(n.qsa=Q.test(d.querySelectorAll))&&(ue(function(e){h.appendChild(e).innerHTML="<a id='"+b+"'></a><select id='"+b+"-\r\\' msallowcapture=''><option selected=''></option></select>",e.querySelectorAll("[msallowcapture^='']").length&&y.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||y.push("\\["+M+"*(?:value|"+P+")"),e.querySelectorAll("[id~="+b+"-]").length||y.push("~="),e.querySelectorAll(":checked").length||y.push(":checked"),e.querySelectorAll("a#"+b+"+*").length||y.push(".#.+[+~]")}),ue(function(e){e.innerHTML="<a href='' disabled='disabled'></a><select disabled='disabled'><option/></select>";var t=d.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&y.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&y.push(":enabled",":disabled"),h.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&y.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),y.push(",.*:")})),(n.matchesSelector=Q.test(m=h.matches||h.webkitMatchesSelector||h.mozMatchesSelector||h.oMatchesSelector||h.msMatchesSelector))&&ue(function(e){n.disconnectedMatch=m.call(e,"*"),m.call(e,"[s!='']:x"),v.push("!=",W)}),y=y.length&&new RegExp(y.join("|")),v=v.length&&new RegExp(v.join("|")),t=Q.test(h.compareDocumentPosition),x=t||Q.test(h.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return f=!0,0;var r=!e.compareDocumentPosition-!t.compareDocumentPosition;return r||(1&(r=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!n.sortDetached&&t.compareDocumentPosition(e)===r?e===d||e.ownerDocument===w&&x(w,e)?-1:t===d||t.ownerDocument===w&&x(w,t)?1:c?O(c,e)-O(c,t):0:4&r?-1:1)}:function(e,t){if(e===t)return f=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===d?-1:t===d?1:i?-1:o?1:c?O(c,e)-O(c,t):0;if(i===o)return ce(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?ce(a[r],s[r]):a[r]===w?-1:s[r]===w?1:0},d):d},oe.matches=function(e,t){return oe(e,null,null,t)},oe.matchesSelector=function(e,t){if((e.ownerDocument||e)!==d&&p(e),t=t.replace(z,"='$1']"),n.matchesSelector&&g&&!S[t+" "]&&(!v||!v.test(t))&&(!y||!y.test(t)))try{var r=m.call(e,t);if(r||n.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(e){}return oe(t,d,null,[e]).length>0},oe.contains=function(e,t){return(e.ownerDocument||e)!==d&&p(e),x(e,t)},oe.attr=function(e,t){(e.ownerDocument||e)!==d&&p(e);var i=r.attrHandle[t.toLowerCase()],o=i&&N.call(r.attrHandle,t.toLowerCase())?i(e,t,!g):void 0;return void 0!==o?o:n.attributes||!g?e.getAttribute(t):(o=e.getAttributeNode(t))&&o.specified?o.value:null},oe.escape=function(e){return(e+"").replace(te,ne)},oe.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},oe.uniqueSort=function(e){var t,r=[],i=0,o=0;if(f=!n.detectDuplicates,c=!n.sortStable&&e.slice(0),e.sort(D),f){while(t=e[o++])t===e[o]&&(i=r.push(o));while(i--)e.splice(r[i],1)}return c=null,e},i=oe.getText=function(e){var t,n="",r=0,o=e.nodeType;if(o){if(1===o||9===o||11===o){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=i(e)}else if(3===o||4===o)return e.nodeValue}else while(t=e[r++])n+=i(t);return n},(r=oe.selectors={cacheLength:50,createPseudo:se,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(Z,ee),e[3]=(e[3]||e[4]||e[5]||"").replace(Z,ee),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||oe.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&oe.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return V.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=a(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(Z,ee).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=E[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&E(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=oe.attr(r,e);return null==i?"!="===t:!t||(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i.replace($," ")+" ").indexOf(n)>-1:"|="===t&&(i===n||i.slice(0,n.length+1)===n+"-"))}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,f,p,d,h,g=o!==a?"nextSibling":"previousSibling",y=t.parentNode,v=s&&t.nodeName.toLowerCase(),m=!u&&!s,x=!1;if(y){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===v:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?y.firstChild:y.lastChild],a&&m){x=(d=(l=(c=(f=(p=y)[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]||[])[0]===T&&l[1])&&l[2],p=d&&y.childNodes[d];while(p=++d&&p&&p[g]||(x=d=0)||h.pop())if(1===p.nodeType&&++x&&p===t){c[e]=[T,d,x];break}}else if(m&&(x=d=(l=(c=(f=(p=t)[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]||[])[0]===T&&l[1]),!1===x)while(p=++d&&p&&p[g]||(x=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===v:1===p.nodeType)&&++x&&(m&&((c=(f=p[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]=[T,x]),p===t))break;return(x-=i)===r||x%r==0&&x/r>=0}}},PSEUDO:function(e,t){var n,i=r.pseudos[e]||r.setFilters[e.toLowerCase()]||oe.error("unsupported pseudo: "+e);return i[b]?i(t):i.length>1?(n=[e,e,"",t],r.setFilters.hasOwnProperty(e.toLowerCase())?se(function(e,n){var r,o=i(e,t),a=o.length;while(a--)e[r=O(e,o[a])]=!(n[r]=o[a])}):function(e){return i(e,0,n)}):i}},pseudos:{not:se(function(e){var t=[],n=[],r=s(e.replace(B,"$1"));return r[b]?se(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),t[0]=null,!n.pop()}}),has:se(function(e){return function(t){return oe(e,t).length>0}}),contains:se(function(e){return e=e.replace(Z,ee),function(t){return(t.textContent||t.innerText||i(t)).indexOf(e)>-1}}),lang:se(function(e){return U.test(e||"")||oe.error("unsupported lang: "+e),e=e.replace(Z,ee).toLowerCase(),function(t){var n;do{if(n=g?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return(n=n.toLowerCase())===e||0===n.indexOf(e+"-")}while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===h},focus:function(e){return e===d.activeElement&&(!d.hasFocus||d.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:de(!1),disabled:de(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!r.pseudos.empty(e)},header:function(e){return Y.test(e.nodeName)},input:function(e){return G.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:he(function(){return[0]}),last:he(function(e,t){return[t-1]}),eq:he(function(e,t,n){return[n<0?n+t:n]}),even:he(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:he(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:he(function(e,t,n){for(var r=n<0?n+t:n;--r>=0;)e.push(r);return e}),gt:he(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}}).pseudos.nth=r.pseudos.eq;for(t in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})r.pseudos[t]=fe(t);for(t in{submit:!0,reset:!0})r.pseudos[t]=pe(t);function ye(){}ye.prototype=r.filters=r.pseudos,r.setFilters=new ye,a=oe.tokenize=function(e,t){var n,i,o,a,s,u,l,c=k[e+" "];if(c)return t?0:c.slice(0);s=e,u=[],l=r.preFilter;while(s){n&&!(i=F.exec(s))||(i&&(s=s.slice(i[0].length)||s),u.push(o=[])),n=!1,(i=_.exec(s))&&(n=i.shift(),o.push({value:n,type:i[0].replace(B," ")}),s=s.slice(n.length));for(a in r.filter)!(i=V[a].exec(s))||l[a]&&!(i=l[a](i))||(n=i.shift(),o.push({value:n,type:a,matches:i}),s=s.slice(n.length));if(!n)break}return t?s.length:s?oe.error(e):k(e,u).slice(0)};function ve(e){for(var t=0,n=e.length,r="";t<n;t++)r+=e[t].value;return r}function me(e,t,n){var r=t.dir,i=t.next,o=i||r,a=n&&"parentNode"===o,s=C++;return t.first?function(t,n,i){while(t=t[r])if(1===t.nodeType||a)return e(t,n,i);return!1}:function(t,n,u){var l,c,f,p=[T,s];if(u){while(t=t[r])if((1===t.nodeType||a)&&e(t,n,u))return!0}else while(t=t[r])if(1===t.nodeType||a)if(f=t[b]||(t[b]={}),c=f[t.uniqueID]||(f[t.uniqueID]={}),i&&i===t.nodeName.toLowerCase())t=t[r]||t;else{if((l=c[o])&&l[0]===T&&l[1]===s)return p[2]=l[2];if(c[o]=p,p[2]=e(t,n,u))return!0}return!1}}function xe(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function be(e,t,n){for(var r=0,i=t.length;r<i;r++)oe(e,t[r],n);return n}function we(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;s<u;s++)(o=e[s])&&(n&&!n(o,r,i)||(a.push(o),l&&t.push(s)));return a}function Te(e,t,n,r,i,o){return r&&!r[b]&&(r=Te(r)),i&&!i[b]&&(i=Te(i,o)),se(function(o,a,s,u){var l,c,f,p=[],d=[],h=a.length,g=o||be(t||"*",s.nodeType?[s]:s,[]),y=!e||!o&&t?g:we(g,p,e,s,u),v=n?i||(o?e:h||r)?[]:a:y;if(n&&n(y,v,s,u),r){l=we(v,d),r(l,[],s,u),c=l.length;while(c--)(f=l[c])&&(v[d[c]]=!(y[d[c]]=f))}if(o){if(i||e){if(i){l=[],c=v.length;while(c--)(f=v[c])&&l.push(y[c]=f);i(null,v=[],l,u)}c=v.length;while(c--)(f=v[c])&&(l=i?O(o,f):p[c])>-1&&(o[l]=!(a[l]=f))}}else v=we(v===a?v.splice(h,v.length):v),i?i(null,a,v,u):L.apply(a,v)})}function Ce(e){for(var t,n,i,o=e.length,a=r.relative[e[0].type],s=a||r.relative[" "],u=a?1:0,c=me(function(e){return e===t},s,!0),f=me(function(e){return O(t,e)>-1},s,!0),p=[function(e,n,r){var i=!a&&(r||n!==l)||((t=n).nodeType?c(e,n,r):f(e,n,r));return t=null,i}];u<o;u++)if(n=r.relative[e[u].type])p=[me(xe(p),n)];else{if((n=r.filter[e[u].type].apply(null,e[u].matches))[b]){for(i=++u;i<o;i++)if(r.relative[e[i].type])break;return Te(u>1&&xe(p),u>1&&ve(e.slice(0,u-1).concat({value:" "===e[u-2].type?"*":""})).replace(B,"$1"),n,u<i&&Ce(e.slice(u,i)),i<o&&Ce(e=e.slice(i)),i<o&&ve(e))}p.push(n)}return xe(p)}function Ee(e,t){var n=t.length>0,i=e.length>0,o=function(o,a,s,u,c){var f,h,y,v=0,m="0",x=o&&[],b=[],w=l,C=o||i&&r.find.TAG("*",c),E=T+=null==w?1:Math.random()||.1,k=C.length;for(c&&(l=a===d||a||c);m!==k&&null!=(f=C[m]);m++){if(i&&f){h=0,a||f.ownerDocument===d||(p(f),s=!g);while(y=e[h++])if(y(f,a||d,s)){u.push(f);break}c&&(T=E)}n&&((f=!y&&f)&&v--,o&&x.push(f))}if(v+=m,n&&m!==v){h=0;while(y=t[h++])y(x,b,a,s);if(o){if(v>0)while(m--)x[m]||b[m]||(b[m]=j.call(u));b=we(b)}L.apply(u,b),c&&!o&&b.length>0&&v+t.length>1&&oe.uniqueSort(u)}return c&&(T=E,l=w),x};return n?se(o):o}return s=oe.compile=function(e,t){var n,r=[],i=[],o=S[e+" "];if(!o){t||(t=a(e)),n=t.length;while(n--)(o=Ce(t[n]))[b]?r.push(o):i.push(o);(o=S(e,Ee(i,r))).selector=e}return o},u=oe.select=function(e,t,n,i){var o,u,l,c,f,p="function"==typeof e&&e,d=!i&&a(e=p.selector||e);if(n=n||[],1===d.length){if((u=d[0]=d[0].slice(0)).length>2&&"ID"===(l=u[0]).type&&9===t.nodeType&&g&&r.relative[u[1].type]){if(!(t=(r.find.ID(l.matches[0].replace(Z,ee),t)||[])[0]))return n;p&&(t=t.parentNode),e=e.slice(u.shift().value.length)}o=V.needsContext.test(e)?0:u.length;while(o--){if(l=u[o],r.relative[c=l.type])break;if((f=r.find[c])&&(i=f(l.matches[0].replace(Z,ee),K.test(u[0].type)&&ge(t.parentNode)||t))){if(u.splice(o,1),!(e=i.length&&ve(u)))return L.apply(n,i),n;break}}}return(p||s(e,d))(i,t,!g,n,!t||K.test(e)&&ge(t.parentNode)||t),n},n.sortStable=b.split("").sort(D).join("")===b,n.detectDuplicates=!!f,p(),n.sortDetached=ue(function(e){return 1&e.compareDocumentPosition(d.createElement("fieldset"))}),ue(function(e){return e.innerHTML="<a href='#'></a>","#"===e.firstChild.getAttribute("href")})||le("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),n.attributes&&ue(function(e){return e.innerHTML="<input/>",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||le("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),ue(function(e){return null==e.getAttribute("disabled")})||le(P,function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),oe}(e);w.find=E,w.expr=E.selectors,w.expr[":"]=w.expr.pseudos,w.uniqueSort=w.unique=E.uniqueSort,w.text=E.getText,w.isXMLDoc=E.isXML,w.contains=E.contains,w.escapeSelector=E.escape;var k=function(e,t,n){var r=[],i=void 0!==n;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&w(e).is(n))break;r.push(e)}return r},S=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},D=w.expr.match.needsContext;function N(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var A=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,t,n){return g(t)?w.grep(e,function(e,r){return!!t.call(e,r,e)!==n}):t.nodeType?w.grep(e,function(e){return e===t!==n}):"string"!=typeof t?w.grep(e,function(e){return u.call(t,e)>-1!==n}):w.filter(t,e,n)}w.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?w.find.matchesSelector(r,e)?[r]:[]:w.find.matches(e,w.grep(t,function(e){return 1===e.nodeType}))},w.fn.extend({find:function(e){var t,n,r=this.length,i=this;if("string"!=typeof e)return this.pushStack(w(e).filter(function(){for(t=0;t<r;t++)if(w.contains(i[t],this))return!0}));for(n=this.pushStack([]),t=0;t<r;t++)w.find(e,i[t],n);return r>1?w.uniqueSort(n):n},filter:function(e){return this.pushStack(j(this,e||[],!1))},not:function(e){return this.pushStack(j(this,e||[],!0))},is:function(e){return!!j(this,"string"==typeof e&&D.test(e)?w(e):e||[],!1).length}});var q,L=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(w.fn.init=function(e,t,n){var i,o;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(i="<"===e[0]&&">"===e[e.length-1]&&e.length>=3?[null,e,null]:L.exec(e))||!i[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(i[1]){if(t=t instanceof w?t[0]:t,w.merge(this,w.parseHTML(i[1],t&&t.nodeType?t.ownerDocument||t:r,!0)),A.test(i[1])&&w.isPlainObject(t))for(i in t)g(this[i])?this[i](t[i]):this.attr(i,t[i]);return this}return(o=r.getElementById(i[2]))&&(this[0]=o,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):g(e)?void 0!==n.ready?n.ready(e):e(w):w.makeArray(e,this)}).prototype=w.fn,q=w(r);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};w.fn.extend({has:function(e){var t=w(e,this),n=t.length;return this.filter(function(){for(var e=0;e<n;e++)if(w.contains(this,t[e]))return!0})},closest:function(e,t){var n,r=0,i=this.length,o=[],a="string"!=typeof e&&w(e);if(!D.test(e))for(;r<i;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(n.nodeType<11&&(a?a.index(n)>-1:1===n.nodeType&&w.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(o.length>1?w.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?u.call(w(e),this[0]):u.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(w.uniqueSort(w.merge(this.get(),w(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}w.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return k(e,"parentNode")},parentsUntil:function(e,t,n){return k(e,"parentNode",n)},next:function(e){return P(e,"nextSibling")},prev:function(e){return P(e,"previousSibling")},nextAll:function(e){return k(e,"nextSibling")},prevAll:function(e){return k(e,"previousSibling")},nextUntil:function(e,t,n){return k(e,"nextSibling",n)},prevUntil:function(e,t,n){return k(e,"previousSibling",n)},siblings:function(e){return S((e.parentNode||{}).firstChild,e)},children:function(e){return S(e.firstChild)},contents:function(e){return N(e,"iframe")?e.contentDocument:(N(e,"template")&&(e=e.content||e),w.merge([],e.childNodes))}},function(e,t){w.fn[e]=function(n,r){var i=w.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=w.filter(r,i)),this.length>1&&(O[e]||w.uniqueSort(i),H.test(e)&&i.reverse()),this.pushStack(i)}});var M=/[^\x20\t\r\n\f]+/g;function R(e){var t={};return w.each(e.match(M)||[],function(e,n){t[n]=!0}),t}w.Callbacks=function(e){e="string"==typeof e?R(e):w.extend({},e);var t,n,r,i,o=[],a=[],s=-1,u=function(){for(i=i||e.once,r=t=!0;a.length;s=-1){n=a.shift();while(++s<o.length)!1===o[s].apply(n[0],n[1])&&e.stopOnFalse&&(s=o.length,n=!1)}e.memory||(n=!1),t=!1,i&&(o=n?[]:"")},l={add:function(){return o&&(n&&!t&&(s=o.length-1,a.push(n)),function t(n){w.each(n,function(n,r){g(r)?e.unique&&l.has(r)||o.push(r):r&&r.length&&"string"!==x(r)&&t(r)})}(arguments),n&&!t&&u()),this},remove:function(){return w.each(arguments,function(e,t){var n;while((n=w.inArray(t,o,n))>-1)o.splice(n,1),n<=s&&s--}),this},has:function(e){return e?w.inArray(e,o)>-1:o.length>0},empty:function(){return o&&(o=[]),this},disable:function(){return i=a=[],o=n="",this},disabled:function(){return!o},lock:function(){return i=a=[],n||t||(o=n=""),this},locked:function(){return!!i},fireWith:function(e,n){return i||(n=[e,(n=n||[]).slice?n.slice():n],a.push(n),t||u()),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!r}};return l};function I(e){return e}function W(e){throw e}function $(e,t,n,r){var i;try{e&&g(i=e.promise)?i.call(e).done(t).fail(n):e&&g(i=e.then)?i.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n.apply(void 0,[e])}}w.extend({Deferred:function(t){var n=[["notify","progress",w.Callbacks("memory"),w.Callbacks("memory"),2],["resolve","done",w.Callbacks("once memory"),w.Callbacks("once memory"),0,"resolved"],["reject","fail",w.Callbacks("once memory"),w.Callbacks("once memory"),1,"rejected"]],r="pending",i={state:function(){return r},always:function(){return o.done(arguments).fail(arguments),this},"catch":function(e){return i.then(null,e)},pipe:function(){var e=arguments;return w.Deferred(function(t){w.each(n,function(n,r){var i=g(e[r[4]])&&e[r[4]];o[r[1]](function(){var e=i&&i.apply(this,arguments);e&&g(e.promise)?e.promise().progress(t.notify).done(t.resolve).fail(t.reject):t[r[0]+"With"](this,i?[e]:arguments)})}),e=null}).promise()},then:function(t,r,i){var o=0;function a(t,n,r,i){return function(){var s=this,u=arguments,l=function(){var e,l;if(!(t<o)){if((e=r.apply(s,u))===n.promise())throw new TypeError("Thenable self-resolution");l=e&&("object"==typeof e||"function"==typeof e)&&e.then,g(l)?i?l.call(e,a(o,n,I,i),a(o,n,W,i)):(o++,l.call(e,a(o,n,I,i),a(o,n,W,i),a(o,n,I,n.notifyWith))):(r!==I&&(s=void 0,u=[e]),(i||n.resolveWith)(s,u))}},c=i?l:function(){try{l()}catch(e){w.Deferred.exceptionHook&&w.Deferred.exceptionHook(e,c.stackTrace),t+1>=o&&(r!==W&&(s=void 0,u=[e]),n.rejectWith(s,u))}};t?c():(w.Deferred.getStackHook&&(c.stackTrace=w.Deferred.getStackHook()),e.setTimeout(c))}}return w.Deferred(function(e){n[0][3].add(a(0,e,g(i)?i:I,e.notifyWith)),n[1][3].add(a(0,e,g(t)?t:I)),n[2][3].add(a(0,e,g(r)?r:W))}).promise()},promise:function(e){return null!=e?w.extend(e,i):i}},o={};return w.each(n,function(e,t){var a=t[2],s=t[5];i[t[1]]=a.add,s&&a.add(function(){r=s},n[3-e][2].disable,n[3-e][3].disable,n[0][2].lock,n[0][3].lock),a.add(t[3].fire),o[t[0]]=function(){return o[t[0]+"With"](this===o?void 0:this,arguments),this},o[t[0]+"With"]=a.fireWith}),i.promise(o),t&&t.call(o,o),o},when:function(e){var t=arguments.length,n=t,r=Array(n),i=o.call(arguments),a=w.Deferred(),s=function(e){return function(n){r[e]=this,i[e]=arguments.length>1?o.call(arguments):n,--t||a.resolveWith(r,i)}};if(t<=1&&($(e,a.done(s(n)).resolve,a.reject,!t),"pending"===a.state()||g(i[n]&&i[n].then)))return a.then();while(n--)$(i[n],s(n),a.reject);return a.promise()}});var B=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;w.Deferred.exceptionHook=function(t,n){e.console&&e.console.warn&&t&&B.test(t.name)&&e.console.warn("jQuery.Deferred exception: "+t.message,t.stack,n)},w.readyException=function(t){e.setTimeout(function(){throw t})};var F=w.Deferred();w.fn.ready=function(e){return F.then(e)["catch"](function(e){w.readyException(e)}),this},w.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--w.readyWait:w.isReady)||(w.isReady=!0,!0!==e&&--w.readyWait>0||F.resolveWith(r,[w]))}}),w.ready.then=F.then;function _(){r.removeEventListener("DOMContentLoaded",_),e.removeEventListener("load",_),w.ready()}"complete"===r.readyState||"loading"!==r.readyState&&!r.documentElement.doScroll?e.setTimeout(w.ready):(r.addEventListener("DOMContentLoaded",_),e.addEventListener("load",_));var z=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if("object"===x(n)){i=!0;for(s in n)z(e,t,s,n[s],!0,o,a)}else if(void 0!==r&&(i=!0,g(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(w(e),n)})),t))for(;s<u;s++)t(e[s],n,a?r:r.call(e[s],s,t(e[s],n)));return i?e:l?t.call(e):u?t(e[0],n):o},X=/^-ms-/,U=/-([a-z])/g;function V(e,t){return t.toUpperCase()}function G(e){return e.replace(X,"ms-").replace(U,V)}var Y=function(e){return 1===e.nodeType||9===e.nodeType||!+e.nodeType};function Q(){this.expando=w.expando+Q.uid++}Q.uid=1,Q.prototype={cache:function(e){var t=e[this.expando];return t||(t={},Y(e)&&(e.nodeType?e[this.expando]=t:Object.defineProperty(e,this.expando,{value:t,configurable:!0}))),t},set:function(e,t,n){var r,i=this.cache(e);if("string"==typeof t)i[G(t)]=n;else for(r in t)i[G(r)]=t[r];return i},get:function(e,t){return void 0===t?this.cache(e):e[this.expando]&&e[this.expando][G(t)]},access:function(e,t,n){return void 0===t||t&&"string"==typeof t&&void 0===n?this.get(e,t):(this.set(e,t,n),void 0!==n?n:t)},remove:function(e,t){var n,r=e[this.expando];if(void 0!==r){if(void 0!==t){n=(t=Array.isArray(t)?t.map(G):(t=G(t))in r?[t]:t.match(M)||[]).length;while(n--)delete r[t[n]]}(void 0===t||w.isEmptyObject(r))&&(e.nodeType?e[this.expando]=void 0:delete e[this.expando])}},hasData:function(e){var t=e[this.expando];return void 0!==t&&!w.isEmptyObject(t)}};var J=new Q,K=new Q,Z=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,ee=/[A-Z]/g;function te(e){return"true"===e||"false"!==e&&("null"===e?null:e===+e+""?+e:Z.test(e)?JSON.parse(e):e)}function ne(e,t,n){var r;if(void 0===n&&1===e.nodeType)if(r="data-"+t.replace(ee,"-$&").toLowerCase(),"string"==typeof(n=e.getAttribute(r))){try{n=te(n)}catch(e){}K.set(e,t,n)}else n=void 0;return n}w.extend({hasData:function(e){return K.hasData(e)||J.hasData(e)},data:function(e,t,n){return K.access(e,t,n)},removeData:function(e,t){K.remove(e,t)},_data:function(e,t,n){return J.access(e,t,n)},_removeData:function(e,t){J.remove(e,t)}}),w.fn.extend({data:function(e,t){var n,r,i,o=this[0],a=o&&o.attributes;if(void 0===e){if(this.length&&(i=K.get(o),1===o.nodeType&&!J.get(o,"hasDataAttrs"))){n=a.length;while(n--)a[n]&&0===(r=a[n].name).indexOf("data-")&&(r=G(r.slice(5)),ne(o,r,i[r]));J.set(o,"hasDataAttrs",!0)}return i}return"object"==typeof e?this.each(function(){K.set(this,e)}):z(this,function(t){var n;if(o&&void 0===t){if(void 0!==(n=K.get(o,e)))return n;if(void 0!==(n=ne(o,e)))return n}else this.each(function(){K.set(this,e,t)})},null,t,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){K.remove(this,e)})}}),w.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=J.get(e,t),n&&(!r||Array.isArray(n)?r=J.access(e,t,w.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=w.queue(e,t),r=n.length,i=n.shift(),o=w._queueHooks(e,t),a=function(){w.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return J.get(e,n)||J.access(e,n,{empty:w.Callbacks("once memory").add(function(){J.remove(e,[t+"queue",n])})})}}),w.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),arguments.length<n?w.queue(this[0],e):void 0===t?this:this.each(function(){var n=w.queue(this,e,t);w._queueHooks(this,e),"fx"===e&&"inprogress"!==n[0]&&w.dequeue(this,e)})},dequeue:function(e){return this.each(function(){w.dequeue(this,e)})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=w.Deferred(),o=this,a=this.length,s=function(){--r||i.resolveWith(o,[o])};"string"!=typeof e&&(t=e,e=void 0),e=e||"fx";while(a--)(n=J.get(o[a],e+"queueHooks"))&&n.empty&&(r++,n.empty.add(s));return s(),i.promise(t)}});var re=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,ie=new RegExp("^(?:([+-])=|)("+re+")([a-z%]*)$","i"),oe=["Top","Right","Bottom","Left"],ae=function(e,t){return"none"===(e=t||e).style.display||""===e.style.display&&w.contains(e.ownerDocument,e)&&"none"===w.css(e,"display")},se=function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i};function ue(e,t,n,r){var i,o,a=20,s=r?function(){return r.cur()}:function(){return w.css(e,t,"")},u=s(),l=n&&n[3]||(w.cssNumber[t]?"":"px"),c=(w.cssNumber[t]||"px"!==l&&+u)&&ie.exec(w.css(e,t));if(c&&c[3]!==l){u/=2,l=l||c[3],c=+u||1;while(a--)w.style(e,t,c+l),(1-o)*(1-(o=s()/u||.5))<=0&&(a=0),c/=o;c*=2,w.style(e,t,c+l),n=n||[]}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}var le={};function ce(e){var t,n=e.ownerDocument,r=e.nodeName,i=le[r];return i||(t=n.body.appendChild(n.createElement(r)),i=w.css(t,"display"),t.parentNode.removeChild(t),"none"===i&&(i="block"),le[r]=i,i)}function fe(e,t){for(var n,r,i=[],o=0,a=e.length;o<a;o++)(r=e[o]).style&&(n=r.style.display,t?("none"===n&&(i[o]=J.get(r,"display")||null,i[o]||(r.style.display="")),""===r.style.display&&ae(r)&&(i[o]=ce(r))):"none"!==n&&(i[o]="none",J.set(r,"display",n)));for(o=0;o<a;o++)null!=i[o]&&(e[o].style.display=i[o]);return e}w.fn.extend({show:function(){return fe(this,!0)},hide:function(){return fe(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){ae(this)?w(this).show():w(this).hide()})}});var pe=/^(?:checkbox|radio)$/i,de=/<([a-z][^\/\0>\x20\t\r\n\f]+)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};ge.optgroup=ge.option,ge.tbody=ge.tfoot=ge.colgroup=ge.caption=ge.thead,ge.th=ge.td;function ye(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&N(e,t)?w.merge([e],n):n}function ve(e,t){for(var n=0,r=e.length;n<r;n++)J.set(e[n],"globalEval",!t||J.get(t[n],"globalEval"))}var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d<h;d++)if((o=e[d])||0===o)if("object"===x(o))w.merge(p,o.nodeType?[o]:o);else if(me.test(o)){a=a||f.appendChild(t.createElement("div")),s=(de.exec(o)||["",""])[1].toLowerCase(),u=ge[s]||ge._default,a.innerHTML=u[1]+w.htmlPrefilter(o)+u[2],c=u[0];while(c--)a=a.lastChild;w.merge(p,a.childNodes),(a=f.firstChild).textContent=""}else p.push(t.createTextNode(o));f.textContent="",d=0;while(o=p[d++])if(r&&w.inArray(o,r)>-1)i&&i.push(o);else if(l=w.contains(o.ownerDocument,o),a=ye(f.appendChild(o),"script"),l&&ve(a),n){c=0;while(o=a[c++])he.test(o.type||"")&&n.push(o)}return f}!function(){var e=r.createDocumentFragment().appendChild(r.createElement("div")),t=r.createElement("input");t.setAttribute("type","radio"),t.setAttribute("checked","checked"),t.setAttribute("name","t"),e.appendChild(t),h.checkClone=e.cloneNode(!0).cloneNode(!0).lastChild.checked,e.innerHTML="<textarea>x</textarea>",h.noCloneChecked=!!e.cloneNode(!0).lastChild.defaultValue}();var be=r.documentElement,we=/^key/,Te=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ce=/^([^.]*)(?:\.(.+)|)/;function Ee(){return!0}function ke(){return!1}function Se(){try{return r.activeElement}catch(e){}}function De(e,t,n,r,i,o){var a,s;if("object"==typeof t){"string"!=typeof n&&(r=r||n,n=void 0);for(s in t)De(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=ke;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return w().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=w.guid++)),e.each(function(){w.event.add(this,t,i,r,n)})}w.event={global:{},add:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,y=J.get(e);if(y){n.handler&&(n=(o=n).handler,i=o.selector),i&&w.find.matchesSelector(be,i),n.guid||(n.guid=w.guid++),(u=y.events)||(u=y.events={}),(a=y.handle)||(a=y.handle=function(t){return"undefined"!=typeof w&&w.event.triggered!==t.type?w.event.dispatch.apply(e,arguments):void 0}),l=(t=(t||"").match(M)||[""]).length;while(l--)d=g=(s=Ce.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=w.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=w.event.special[d]||{},c=w.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&w.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(e,r,h,a)||e.addEventListener&&e.addEventListener(d,a)),f.add&&(f.add.call(e,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),w.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,y=J.hasData(e)&&J.get(e);if(y&&(u=y.events)){l=(t=(t||"").match(M)||[""]).length;while(l--)if(s=Ce.exec(t[l])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){f=w.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,y.handle)||w.removeEvent(e,d,y.handle),delete u[d])}else for(d in u)w.event.remove(e,d+t[l],n,r,!0);w.isEmptyObject(u)&&J.remove(e,"handle events")}},dispatch:function(e){var t=w.event.fix(e),n,r,i,o,a,s,u=new Array(arguments.length),l=(J.get(this,"events")||{})[t.type]||[],c=w.event.special[t.type]||{};for(u[0]=t,n=1;n<arguments.length;n++)u[n]=arguments[n];if(t.delegateTarget=this,!c.preDispatch||!1!==c.preDispatch.call(this,t)){s=w.event.handlers.call(this,t,l),n=0;while((o=s[n++])&&!t.isPropagationStopped()){t.currentTarget=o.elem,r=0;while((a=o.handlers[r++])&&!t.isImmediatePropagationStopped())t.rnamespace&&!t.rnamespace.test(a.namespace)||(t.handleObj=a,t.data=a.data,void 0!==(i=((w.event.special[a.origType]||{}).handle||a.handler).apply(o.elem,u))&&!1===(t.result=i)&&(t.preventDefault(),t.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,t),t.result}},handlers:function(e,t){var n,r,i,o,a,s=[],u=t.delegateCount,l=e.target;if(u&&l.nodeType&&!("click"===e.type&&e.button>=1))for(;l!==this;l=l.parentNode||this)if(1===l.nodeType&&("click"!==e.type||!0!==l.disabled)){for(o=[],a={},n=0;n<u;n++)void 0===a[i=(r=t[n]).selector+" "]&&(a[i]=r.needsContext?w(i,this).index(l)>-1:w.find(i,this,null,[l]).length),a[i]&&o.push(r);o.length&&s.push({elem:l,handlers:o})}return l=this,u<t.length&&s.push({elem:l,handlers:t.slice(u)}),s},addProp:function(e,t){Object.defineProperty(w.Event.prototype,e,{enumerable:!0,configurable:!0,get:g(t)?function(){if(this.originalEvent)return t(this.originalEvent)}:function(){if(this.originalEvent)return this.originalEvent[e]},set:function(t){Object.defineProperty(this,e,{enumerable:!0,configurable:!0,writable:!0,value:t})}})},fix:function(e){return e[w.expando]?e:new w.Event(e)},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==Se()&&this.focus)return this.focus(),!1},delegateType:"focusin"},blur:{trigger:function(){if(this===Se()&&this.blur)return this.blur(),!1},delegateType:"focusout"},click:{trigger:function(){if("checkbox"===this.type&&this.click&&N(this,"input"))return this.click(),!1},_default:function(e){return N(e.target,"a")}},beforeunload:{postDispatch:function(e){void 0!==e.result&&e.originalEvent&&(e.originalEvent.returnValue=e.result)}}}},w.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n)},w.Event=function(e,t){if(!(this instanceof w.Event))return new w.Event(e,t);e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||void 0===e.defaultPrevented&&!1===e.returnValue?Ee:ke,this.target=e.target&&3===e.target.nodeType?e.target.parentNode:e.target,this.currentTarget=e.currentTarget,this.relatedTarget=e.relatedTarget):this.type=e,t&&w.extend(this,t),this.timeStamp=e&&e.timeStamp||Date.now(),this[w.expando]=!0},w.Event.prototype={constructor:w.Event,isDefaultPrevented:ke,isPropagationStopped:ke,isImmediatePropagationStopped:ke,isSimulated:!1,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=Ee,e&&!this.isSimulated&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=Ee,e&&!this.isSimulated&&e.stopPropagation()},stopImmediatePropagation:function(){var e=this.originalEvent;this.isImmediatePropagationStopped=Ee,e&&!this.isSimulated&&e.stopImmediatePropagation(),this.stopPropagation()}},w.each({altKey:!0,bubbles:!0,cancelable:!0,changedTouches:!0,ctrlKey:!0,detail:!0,eventPhase:!0,metaKey:!0,pageX:!0,pageY:!0,shiftKey:!0,view:!0,"char":!0,charCode:!0,key:!0,keyCode:!0,button:!0,buttons:!0,clientX:!0,clientY:!0,offsetX:!0,offsetY:!0,pointerId:!0,pointerType:!0,screenX:!0,screenY:!0,targetTouches:!0,toElement:!0,touches:!0,which:function(e){var t=e.button;return null==e.which&&we.test(e.type)?null!=e.charCode?e.charCode:e.keyCode:!e.which&&void 0!==t&&Te.test(e.type)?1&t?1:2&t?3:4&t?2:0:e.which}},w.event.addProp),w.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(e,t){w.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return i&&(i===r||w.contains(r,i))||(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),w.fn.extend({on:function(e,t,n,r){return De(this,e,t,n,r)},one:function(e,t,n,r){return De(this,e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,w(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return!1!==t&&"function"!=typeof t||(n=t,t=void 0),!1===n&&(n=ke),this.each(function(){w.event.remove(this,e,n,t)})}});var Ne=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,Ae=/<script|<style|<link/i,je=/checked\s*(?:[^=]|=\s*.checked.)/i,qe=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;function Le(e,t){return N(e,"table")&&N(11!==t.nodeType?t:t.firstChild,"tr")?w(e).children("tbody")[0]||e:e}function He(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Oe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Pe(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(J.hasData(e)&&(o=J.access(e),a=J.set(t,o),l=o.events)){delete a.handle,a.events={};for(i in l)for(n=0,r=l[i].length;n<r;n++)w.event.add(t,i,l[i][n])}K.hasData(e)&&(s=K.access(e),u=w.extend({},s),K.set(t,u))}}function Me(e,t){var n=t.nodeName.toLowerCase();"input"===n&&pe.test(e.type)?t.checked=e.checked:"input"!==n&&"textarea"!==n||(t.defaultValue=e.defaultValue)}function Re(e,t,n,r){t=a.apply([],t);var i,o,s,u,l,c,f=0,p=e.length,d=p-1,y=t[0],v=g(y);if(v||p>1&&"string"==typeof y&&!h.checkClone&&je.test(y))return e.each(function(i){var o=e.eq(i);v&&(t[0]=y.call(this,i,o.html())),Re(o,t,n,r)});if(p&&(i=xe(t,e[0].ownerDocument,!1,e,r),o=i.firstChild,1===i.childNodes.length&&(i=o),o||r)){for(u=(s=w.map(ye(i,"script"),He)).length;f<p;f++)l=i,f!==d&&(l=w.clone(l,!0,!0),u&&w.merge(s,ye(l,"script"))),n.call(e[f],l,f);if(u)for(c=s[s.length-1].ownerDocument,w.map(s,Oe),f=0;f<u;f++)l=s[f],he.test(l.type||"")&&!J.access(l,"globalEval")&&w.contains(c,l)&&(l.src&&"module"!==(l.type||"").toLowerCase()?w._evalUrl&&w._evalUrl(l.src):m(l.textContent.replace(qe,""),c,l))}return e}function Ie(e,t,n){for(var r,i=t?w.filter(t,e):e,o=0;null!=(r=i[o]);o++)n||1!==r.nodeType||w.cleanData(ye(r)),r.parentNode&&(n&&w.contains(r.ownerDocument,r)&&ve(ye(r,"script")),r.parentNode.removeChild(r));return e}w.extend({htmlPrefilter:function(e){return e.replace(Ne,"<$1></$2>")},clone:function(e,t,n){var r,i,o,a,s=e.cloneNode(!0),u=w.contains(e.ownerDocument,e);if(!(h.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||w.isXMLDoc(e)))for(a=ye(s),r=0,i=(o=ye(e)).length;r<i;r++)Me(o[r],a[r]);if(t)if(n)for(o=o||ye(e),a=a||ye(s),r=0,i=o.length;r<i;r++)Pe(o[r],a[r]);else Pe(e,s);return(a=ye(s,"script")).length>0&&ve(a,!u&&ye(e,"script")),s},cleanData:function(e){for(var t,n,r,i=w.event.special,o=0;void 0!==(n=e[o]);o++)if(Y(n)){if(t=n[J.expando]){if(t.events)for(r in t.events)i[r]?w.event.remove(n,r):w.removeEvent(n,r,t.handle);n[J.expando]=void 0}n[K.expando]&&(n[K.expando]=void 0)}}}),w.fn.extend({detach:function(e){return Ie(this,e,!0)},remove:function(e){return Ie(this,e)},text:function(e){return z(this,function(e){return void 0===e?w.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return Re(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||Le(this,e).appendChild(e)})},prepend:function(){return Re(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Le(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return Re(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return Re(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(w.cleanData(ye(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return w.clone(this,e,t)})},html:function(e){return z(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!Ae.test(e)&&!ge[(de.exec(e)||["",""])[1].toLowerCase()]){e=w.htmlPrefilter(e);try{for(;n<r;n++)1===(t=this[n]||{}).nodeType&&(w.cleanData(ye(t,!1)),t.innerHTML=e);t=0}catch(e){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=[];return Re(this,arguments,function(t){var n=this.parentNode;w.inArray(this,e)<0&&(w.cleanData(ye(this)),n&&n.replaceChild(t,this))},e)}}),w.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){w.fn[e]=function(e){for(var n,r=[],i=w(e),o=i.length-1,a=0;a<=o;a++)n=a===o?this:this.clone(!0),w(i[a])[t](n),s.apply(r,n.get());return this.pushStack(r)}});var We=new RegExp("^("+re+")(?!px)[a-z%]+$","i"),$e=function(t){var n=t.ownerDocument.defaultView;return n&&n.opener||(n=e),n.getComputedStyle(t)},Be=new RegExp(oe.join("|"),"i");!function(){function t(){if(c){l.style.cssText="position:absolute;left:-11111px;width:60px;margin-top:1px;padding:0;border:0",c.style.cssText="position:relative;display:block;box-sizing:border-box;overflow:scroll;margin:auto;border:1px;padding:1px;width:60%;top:1%",be.appendChild(l).appendChild(c);var t=e.getComputedStyle(c);i="1%"!==t.top,u=12===n(t.marginLeft),c.style.right="60%",s=36===n(t.right),o=36===n(t.width),c.style.position="absolute",a=36===c.offsetWidth||"absolute",be.removeChild(l),c=null}}function n(e){return Math.round(parseFloat(e))}var i,o,a,s,u,l=r.createElement("div"),c=r.createElement("div");c.style&&(c.style.backgroundClip="content-box",c.cloneNode(!0).style.backgroundClip="",h.clearCloneStyle="content-box"===c.style.backgroundClip,w.extend(h,{boxSizingReliable:function(){return t(),o},pixelBoxStyles:function(){return t(),s},pixelPosition:function(){return t(),i},reliableMarginLeft:function(){return t(),u},scrollboxSize:function(){return t(),a}}))}();function Fe(e,t,n){var r,i,o,a,s=e.style;return(n=n||$e(e))&&(""!==(a=n.getPropertyValue(t)||n[t])||w.contains(e.ownerDocument,e)||(a=w.style(e,t)),!h.pixelBoxStyles()&&We.test(a)&&Be.test(t)&&(r=s.width,i=s.minWidth,o=s.maxWidth,s.minWidth=s.maxWidth=s.width=a,a=n.width,s.width=r,s.minWidth=i,s.maxWidth=o)),void 0!==a?a+"":a}function _e(e,t){return{get:function(){if(!e())return(this.get=t).apply(this,arguments);delete this.get}}}var ze=/^(none|table(?!-c[ea]).+)/,Xe=/^--/,Ue={position:"absolute",visibility:"hidden",display:"block"},Ve={letterSpacing:"0",fontWeight:"400"},Ge=["Webkit","Moz","ms"],Ye=r.createElement("div").style;function Qe(e){if(e in Ye)return e;var t=e[0].toUpperCase()+e.slice(1),n=Ge.length;while(n--)if((e=Ge[n]+t)in Ye)return e}function Je(e){var t=w.cssProps[e];return t||(t=w.cssProps[e]=Qe(e)||e),t}function Ke(e,t,n){var r=ie.exec(t);return r?Math.max(0,r[2]-(n||0))+(r[3]||"px"):t}function Ze(e,t,n,r,i,o){var a="width"===t?1:0,s=0,u=0;if(n===(r?"border":"content"))return 0;for(;a<4;a+=2)"margin"===n&&(u+=w.css(e,n+oe[a],!0,i)),r?("content"===n&&(u-=w.css(e,"padding"+oe[a],!0,i)),"margin"!==n&&(u-=w.css(e,"border"+oe[a]+"Width",!0,i))):(u+=w.css(e,"padding"+oe[a],!0,i),"padding"!==n?u+=w.css(e,"border"+oe[a]+"Width",!0,i):s+=w.css(e,"border"+oe[a]+"Width",!0,i));return!r&&o>=0&&(u+=Math.max(0,Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-o-u-s-.5))),u}function et(e,t,n){var r=$e(e),i=Fe(e,t,r),o="border-box"===w.css(e,"boxSizing",!1,r),a=o;if(We.test(i)){if(!n)return i;i="auto"}return a=a&&(h.boxSizingReliable()||i===e.style[t]),("auto"===i||!parseFloat(i)&&"inline"===w.css(e,"display",!1,r))&&(i=e["offset"+t[0].toUpperCase()+t.slice(1)],a=!0),(i=parseFloat(i)||0)+Ze(e,t,n||(o?"border":"content"),a,r,i)+"px"}w.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Fe(e,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=G(t),u=Xe.test(t),l=e.style;if(u||(t=Je(s)),a=w.cssHooks[t]||w.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];"string"==(o=typeof n)&&(i=ie.exec(n))&&i[1]&&(n=ue(e,t,i),o="number"),null!=n&&n===n&&("number"===o&&(n+=i&&i[3]||(w.cssNumber[s]?"":"px")),h.clearCloneStyle||""!==n||0!==t.indexOf("background")||(l[t]="inherit"),a&&"set"in a&&void 0===(n=a.set(e,n,r))||(u?l.setProperty(t,n):l[t]=n))}},css:function(e,t,n,r){var i,o,a,s=G(t);return Xe.test(t)||(t=Je(s)),(a=w.cssHooks[t]||w.cssHooks[s])&&"get"in a&&(i=a.get(e,!0,n)),void 0===i&&(i=Fe(e,t,r)),"normal"===i&&t in Ve&&(i=Ve[t]),""===n||n?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),w.each(["height","width"],function(e,t){w.cssHooks[t]={get:function(e,n,r){if(n)return!ze.test(w.css(e,"display"))||e.getClientRects().length&&e.getBoundingClientRect().width?et(e,t,r):se(e,Ue,function(){return et(e,t,r)})},set:function(e,n,r){var i,o=$e(e),a="border-box"===w.css(e,"boxSizing",!1,o),s=r&&Ze(e,t,r,a,o);return a&&h.scrollboxSize()===o.position&&(s-=Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-parseFloat(o[t])-Ze(e,t,"border",!1,o)-.5)),s&&(i=ie.exec(n))&&"px"!==(i[3]||"px")&&(e.style[t]=n,n=w.css(e,t)),Ke(e,n,s)}}}),w.cssHooks.marginLeft=_e(h.reliableMarginLeft,function(e,t){if(t)return(parseFloat(Fe(e,"marginLeft"))||e.getBoundingClientRect().left-se(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}))+"px"}),w.each({margin:"",padding:"",border:"Width"},function(e,t){w.cssHooks[e+t]={expand:function(n){for(var r=0,i={},o="string"==typeof n?n.split(" "):[n];r<4;r++)i[e+oe[r]+t]=o[r]||o[r-2]||o[0];return i}},"margin"!==e&&(w.cssHooks[e+t].set=Ke)}),w.fn.extend({css:function(e,t){return z(this,function(e,t,n){var r,i,o={},a=0;if(Array.isArray(t)){for(r=$e(e),i=t.length;a<i;a++)o[t[a]]=w.css(e,t[a],!1,r);return o}return void 0!==n?w.style(e,t,n):w.css(e,t)},e,t,arguments.length>1)}});function tt(e,t,n,r,i){return new tt.prototype.init(e,t,n,r,i)}w.Tween=tt,tt.prototype={constructor:tt,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||w.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(w.cssNumber[n]?"":"px")},cur:function(){var e=tt.propHooks[this.prop];return e&&e.get?e.get(this):tt.propHooks._default.get(this)},run:function(e){var t,n=tt.propHooks[this.prop];return this.options.duration?this.pos=t=w.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):tt.propHooks._default.set(this),this}},tt.prototype.init.prototype=tt.prototype,tt.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=w.css(e.elem,e.prop,""))&&"auto"!==t?t:0},set:function(e){w.fx.step[e.prop]?w.fx.step[e.prop](e):1!==e.elem.nodeType||null==e.elem.style[w.cssProps[e.prop]]&&!w.cssHooks[e.prop]?e.elem[e.prop]=e.now:w.style(e.elem,e.prop,e.now+e.unit)}}},tt.propHooks.scrollTop=tt.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},w.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},w.fx=tt.prototype.init,w.fx.step={};var nt,rt,it=/^(?:toggle|show|hide)$/,ot=/queueHooks$/;function at(){rt&&(!1===r.hidden&&e.requestAnimationFrame?e.requestAnimationFrame(at):e.setTimeout(at,w.fx.interval),w.fx.tick())}function st(){return e.setTimeout(function(){nt=void 0}),nt=Date.now()}function ut(e,t){var n,r=0,i={height:e};for(t=t?1:0;r<4;r+=2-t)i["margin"+(n=oe[r])]=i["padding"+n]=e;return t&&(i.opacity=i.width=e),i}function lt(e,t,n){for(var r,i=(pt.tweeners[t]||[]).concat(pt.tweeners["*"]),o=0,a=i.length;o<a;o++)if(r=i[o].call(n,t,e))return r}function ct(e,t,n){var r,i,o,a,s,u,l,c,f="width"in t||"height"in t,p=this,d={},h=e.style,g=e.nodeType&&ae(e),y=J.get(e,"fxshow");n.queue||(null==(a=w._queueHooks(e,"fx")).unqueued&&(a.unqueued=0,s=a.empty.fire,a.empty.fire=function(){a.unqueued||s()}),a.unqueued++,p.always(function(){p.always(function(){a.unqueued--,w.queue(e,"fx").length||a.empty.fire()})}));for(r in t)if(i=t[r],it.test(i)){if(delete t[r],o=o||"toggle"===i,i===(g?"hide":"show")){if("show"!==i||!y||void 0===y[r])continue;g=!0}d[r]=y&&y[r]||w.style(e,r)}if((u=!w.isEmptyObject(t))||!w.isEmptyObject(d)){f&&1===e.nodeType&&(n.overflow=[h.overflow,h.overflowX,h.overflowY],null==(l=y&&y.display)&&(l=J.get(e,"display")),"none"===(c=w.css(e,"display"))&&(l?c=l:(fe([e],!0),l=e.style.display||l,c=w.css(e,"display"),fe([e]))),("inline"===c||"inline-block"===c&&null!=l)&&"none"===w.css(e,"float")&&(u||(p.done(function(){h.display=l}),null==l&&(c=h.display,l="none"===c?"":c)),h.display="inline-block")),n.overflow&&(h.overflow="hidden",p.always(function(){h.overflow=n.overflow[0],h.overflowX=n.overflow[1],h.overflowY=n.overflow[2]})),u=!1;for(r in d)u||(y?"hidden"in y&&(g=y.hidden):y=J.access(e,"fxshow",{display:l}),o&&(y.hidden=!g),g&&fe([e],!0),p.done(function(){g||fe([e]),J.remove(e,"fxshow");for(r in d)w.style(e,r,d[r])})),u=lt(g?y[r]:0,r,p),r in y||(y[r]=u.start,g&&(u.end=u.start,u.start=0))}}function ft(e,t){var n,r,i,o,a;for(n in e)if(r=G(n),i=t[r],o=e[n],Array.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),(a=w.cssHooks[r])&&"expand"in a){o=a.expand(o),delete e[r];for(n in o)n in e||(e[n]=o[n],t[n]=i)}else t[r]=i}function pt(e,t,n){var r,i,o=0,a=pt.prefilters.length,s=w.Deferred().always(function(){delete u.elem}),u=function(){if(i)return!1;for(var t=nt||st(),n=Math.max(0,l.startTime+l.duration-t),r=1-(n/l.duration||0),o=0,a=l.tweens.length;o<a;o++)l.tweens[o].run(r);return s.notifyWith(e,[l,r,n]),r<1&&a?n:(a||s.notifyWith(e,[l,1,0]),s.resolveWith(e,[l]),!1)},l=s.promise({elem:e,props:w.extend({},t),opts:w.extend(!0,{specialEasing:{},easing:w.easing._default},n),originalProperties:t,originalOptions:n,startTime:nt||st(),duration:n.duration,tweens:[],createTween:function(t,n){var r=w.Tween(e,l.opts,t,n,l.opts.specialEasing[t]||l.opts.easing);return l.tweens.push(r),r},stop:function(t){var n=0,r=t?l.tweens.length:0;if(i)return this;for(i=!0;n<r;n++)l.tweens[n].run(1);return t?(s.notifyWith(e,[l,1,0]),s.resolveWith(e,[l,t])):s.rejectWith(e,[l,t]),this}}),c=l.props;for(ft(c,l.opts.specialEasing);o<a;o++)if(r=pt.prefilters[o].call(l,e,c,l.opts))return g(r.stop)&&(w._queueHooks(l.elem,l.opts.queue).stop=r.stop.bind(r)),r;return w.map(c,lt,l),g(l.opts.start)&&l.opts.start.call(e,l),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always),w.fx.timer(w.extend(u,{elem:e,anim:l,queue:l.opts.queue})),l}w.Animation=w.extend(pt,{tweeners:{"*":[function(e,t){var n=this.createTween(e,t);return ue(n.elem,e,ie.exec(t),n),n}]},tweener:function(e,t){g(e)?(t=e,e=["*"]):e=e.match(M);for(var n,r=0,i=e.length;r<i;r++)n=e[r],pt.tweeners[n]=pt.tweeners[n]||[],pt.tweeners[n].unshift(t)},prefilters:[ct],prefilter:function(e,t){t?pt.prefilters.unshift(e):pt.prefilters.push(e)}}),w.speed=function(e,t,n){var r=e&&"object"==typeof e?w.extend({},e):{complete:n||!n&&t||g(e)&&e,duration:e,easing:n&&t||t&&!g(t)&&t};return w.fx.off?r.duration=0:"number"!=typeof r.duration&&(r.duration in w.fx.speeds?r.duration=w.fx.speeds[r.duration]:r.duration=w.fx.speeds._default),null!=r.queue&&!0!==r.queue||(r.queue="fx"),r.old=r.complete,r.complete=function(){g(r.old)&&r.old.call(this),r.queue&&w.dequeue(this,r.queue)},r},w.fn.extend({fadeTo:function(e,t,n,r){return this.filter(ae).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=w.isEmptyObject(e),o=w.speed(t,n,r),a=function(){var t=pt(this,w.extend({},e),o);(i||J.get(this,"finish"))&&t.stop(!0)};return a.finish=a,i||!1===o.queue?this.each(a):this.queue(o.queue,a)},stop:function(e,t,n){var r=function(e){var t=e.stop;delete e.stop,t(n)};return"string"!=typeof e&&(n=t,t=e,e=void 0),t&&!1!==e&&this.queue(e||"fx",[]),this.each(function(){var t=!0,i=null!=e&&e+"queueHooks",o=w.timers,a=J.get(this);if(i)a[i]&&a[i].stop&&r(a[i]);else for(i in a)a[i]&&a[i].stop&&ot.test(i)&&r(a[i]);for(i=o.length;i--;)o[i].elem!==this||null!=e&&o[i].queue!==e||(o[i].anim.stop(n),t=!1,o.splice(i,1));!t&&n||w.dequeue(this,e)})},finish:function(e){return!1!==e&&(e=e||"fx"),this.each(function(){var t,n=J.get(this),r=n[e+"queue"],i=n[e+"queueHooks"],o=w.timers,a=r?r.length:0;for(n.finish=!0,w.queue(this,e,[]),i&&i.stop&&i.stop.call(this,!0),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;t<a;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}}),w.each(["toggle","show","hide"],function(e,t){var n=w.fn[t];w.fn[t]=function(e,r,i){return null==e||"boolean"==typeof e?n.apply(this,arguments):this.animate(ut(t,!0),e,r,i)}}),w.each({slideDown:ut("show"),slideUp:ut("hide"),slideToggle:ut("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){w.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),w.timers=[],w.fx.tick=function(){var e,t=0,n=w.timers;for(nt=Date.now();t<n.length;t++)(e=n[t])()||n[t]!==e||n.splice(t--,1);n.length||w.fx.stop(),nt=void 0},w.fx.timer=function(e){w.timers.push(e),w.fx.start()},w.fx.interval=13,w.fx.start=function(){rt||(rt=!0,at())},w.fx.stop=function(){rt=null},w.fx.speeds={slow:600,fast:200,_default:400},w.fn.delay=function(t,n){return t=w.fx?w.fx.speeds[t]||t:t,n=n||"fx",this.queue(n,function(n,r){var i=e.setTimeout(n,t);r.stop=function(){e.clearTimeout(i)}})},function(){var e=r.createElement("input"),t=r.createElement("select").appendChild(r.createElement("option"));e.type="checkbox",h.checkOn=""!==e.value,h.optSelected=t.selected,(e=r.createElement("input")).value="t",e.type="radio",h.radioValue="t"===e.value}();var dt,ht=w.expr.attrHandle;w.fn.extend({attr:function(e,t){return z(this,w.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){w.removeAttr(this,e)})}}),w.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return"undefined"==typeof e.getAttribute?w.prop(e,t,n):(1===o&&w.isXMLDoc(e)||(i=w.attrHooks[t.toLowerCase()]||(w.expr.match.bool.test(t)?dt:void 0)),void 0!==n?null===n?void w.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:null==(r=w.find.attr(e,t))?void 0:r)},attrHooks:{type:{set:function(e,t){if(!h.radioValue&&"radio"===t&&N(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(M);if(i&&1===e.nodeType)while(n=i[r++])e.removeAttribute(n)}}),dt={set:function(e,t,n){return!1===t?w.removeAttr(e,n):e.setAttribute(n,n),n}},w.each(w.expr.match.bool.source.match(/\w+/g),function(e,t){var n=ht[t]||w.find.attr;ht[t]=function(e,t,r){var i,o,a=t.toLowerCase();return r||(o=ht[a],ht[a]=i,i=null!=n(e,t,r)?a:null,ht[a]=o),i}});var gt=/^(?:input|select|textarea|button)$/i,yt=/^(?:a|area)$/i;w.fn.extend({prop:function(e,t){return z(this,w.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[w.propFix[e]||e]})}}),w.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&w.isXMLDoc(e)||(t=w.propFix[t]||t,i=w.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=w.find.attr(e,"tabindex");return t?parseInt(t,10):gt.test(e.nodeName)||yt.test(e.nodeName)&&e.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),h.optSelected||(w.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),w.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){w.propFix[this.toLowerCase()]=this});function vt(e){return(e.match(M)||[]).join(" ")}function mt(e){return e.getAttribute&&e.getAttribute("class")||""}function xt(e){return Array.isArray(e)?e:"string"==typeof e?e.match(M)||[]:[]}w.fn.extend({addClass:function(e){var t,n,r,i,o,a,s,u=0;if(g(e))return this.each(function(t){w(this).addClass(e.call(this,t,mt(this)))});if((t=xt(e)).length)while(n=this[u++])if(i=mt(n),r=1===n.nodeType&&" "+vt(i)+" "){a=0;while(o=t[a++])r.indexOf(" "+o+" ")<0&&(r+=o+" ");i!==(s=vt(r))&&n.setAttribute("class",s)}return this},removeClass:function(e){var t,n,r,i,o,a,s,u=0;if(g(e))return this.each(function(t){w(this).removeClass(e.call(this,t,mt(this)))});if(!arguments.length)return this.attr("class","");if((t=xt(e)).length)while(n=this[u++])if(i=mt(n),r=1===n.nodeType&&" "+vt(i)+" "){a=0;while(o=t[a++])while(r.indexOf(" "+o+" ")>-1)r=r.replace(" "+o+" "," ");i!==(s=vt(r))&&n.setAttribute("class",s)}return this},toggleClass:function(e,t){var n=typeof e,r="string"===n||Array.isArray(e);return"boolean"==typeof t&&r?t?this.addClass(e):this.removeClass(e):g(e)?this.each(function(n){w(this).toggleClass(e.call(this,n,mt(this),t),t)}):this.each(function(){var t,i,o,a;if(r){i=0,o=w(this),a=xt(e);while(t=a[i++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else void 0!==e&&"boolean"!==n||((t=mt(this))&&J.set(this,"__className__",t),this.setAttribute&&this.setAttribute("class",t||!1===e?"":J.get(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;t=" "+e+" ";while(n=this[r++])if(1===n.nodeType&&(" "+vt(mt(n))+" ").indexOf(t)>-1)return!0;return!1}});var bt=/\r/g;w.fn.extend({val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=g(e),this.each(function(n){var i;1===this.nodeType&&(null==(i=r?e.call(this,n,w(this).val()):e)?i="":"number"==typeof i?i+="":Array.isArray(i)&&(i=w.map(i,function(e){return null==e?"":e+""})),(t=w.valHooks[this.type]||w.valHooks[this.nodeName.toLowerCase()])&&"set"in t&&void 0!==t.set(this,i,"value")||(this.value=i))});if(i)return(t=w.valHooks[i.type]||w.valHooks[i.nodeName.toLowerCase()])&&"get"in t&&void 0!==(n=t.get(i,"value"))?n:"string"==typeof(n=i.value)?n.replace(bt,""):null==n?"":n}}}),w.extend({valHooks:{option:{get:function(e){var t=w.find.attr(e,"value");return null!=t?t:vt(w.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a="select-one"===e.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r<u;r++)if(((n=i[r]).selected||r===o)&&!n.disabled&&(!n.parentNode.disabled||!N(n.parentNode,"optgroup"))){if(t=w(n).val(),a)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=w.makeArray(t),a=i.length;while(a--)((r=i[a]).selected=w.inArray(w.valHooks.option.get(r),o)>-1)&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),w.each(["radio","checkbox"],function(){w.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=w.inArray(w(e).val(),t)>-1}},h.checkOn||(w.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})}),h.focusin="onfocusin"in e;var wt=/^(?:focusinfocus|focusoutblur)$/,Tt=function(e){e.stopPropagation()};w.extend(w.event,{trigger:function(t,n,i,o){var a,s,u,l,c,p,d,h,v=[i||r],m=f.call(t,"type")?t.type:t,x=f.call(t,"namespace")?t.namespace.split("."):[];if(s=h=u=i=i||r,3!==i.nodeType&&8!==i.nodeType&&!wt.test(m+w.event.triggered)&&(m.indexOf(".")>-1&&(m=(x=m.split(".")).shift(),x.sort()),c=m.indexOf(":")<0&&"on"+m,t=t[w.expando]?t:new w.Event(m,"object"==typeof t&&t),t.isTrigger=o?2:3,t.namespace=x.join("."),t.rnamespace=t.namespace?new RegExp("(^|\\.)"+x.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=void 0,t.target||(t.target=i),n=null==n?[t]:w.makeArray(n,[t]),d=w.event.special[m]||{},o||!d.trigger||!1!==d.trigger.apply(i,n))){if(!o&&!d.noBubble&&!y(i)){for(l=d.delegateType||m,wt.test(l+m)||(s=s.parentNode);s;s=s.parentNode)v.push(s),u=s;u===(i.ownerDocument||r)&&v.push(u.defaultView||u.parentWindow||e)}a=0;while((s=v[a++])&&!t.isPropagationStopped())h=s,t.type=a>1?l:d.bindType||m,(p=(J.get(s,"events")||{})[t.type]&&J.get(s,"handle"))&&p.apply(s,n),(p=c&&s[c])&&p.apply&&Y(s)&&(t.result=p.apply(s,n),!1===t.result&&t.preventDefault());return t.type=m,o||t.isDefaultPrevented()||d._default&&!1!==d._default.apply(v.pop(),n)||!Y(i)||c&&g(i[m])&&!y(i)&&((u=i[c])&&(i[c]=null),w.event.triggered=m,t.isPropagationStopped()&&h.addEventListener(m,Tt),i[m](),t.isPropagationStopped()&&h.removeEventListener(m,Tt),w.event.triggered=void 0,u&&(i[c]=u)),t.result}},simulate:function(e,t,n){var r=w.extend(new w.Event,n,{type:e,isSimulated:!0});w.event.trigger(r,null,t)}}),w.fn.extend({trigger:function(e,t){return this.each(function(){w.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return w.event.trigger(e,t,n,!0)}}),h.focusin||w.each({focus:"focusin",blur:"focusout"},function(e,t){var n=function(e){w.event.simulate(t,e.target,w.event.fix(e))};w.event.special[t]={setup:function(){var r=this.ownerDocument||this,i=J.access(r,t);i||r.addEventListener(e,n,!0),J.access(r,t,(i||0)+1)},teardown:function(){var r=this.ownerDocument||this,i=J.access(r,t)-1;i?J.access(r,t,i):(r.removeEventListener(e,n,!0),J.remove(r,t))}}});var Ct=e.location,Et=Date.now(),kt=/\?/;w.parseXML=function(t){var n;if(!t||"string"!=typeof t)return null;try{n=(new e.DOMParser).parseFromString(t,"text/xml")}catch(e){n=void 0}return n&&!n.getElementsByTagName("parsererror").length||w.error("Invalid XML: "+t),n};var St=/\[\]$/,Dt=/\r?\n/g,Nt=/^(?:submit|button|image|reset|file)$/i,At=/^(?:input|select|textarea|keygen)/i;function jt(e,t,n,r){var i;if(Array.isArray(t))w.each(t,function(t,i){n||St.test(e)?r(e,i):jt(e+"["+("object"==typeof i&&null!=i?t:"")+"]",i,n,r)});else if(n||"object"!==x(t))r(e,t);else for(i in t)jt(e+"["+i+"]",t[i],n,r)}w.param=function(e,t){var n,r=[],i=function(e,t){var n=g(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(Array.isArray(e)||e.jquery&&!w.isPlainObject(e))w.each(e,function(){i(this.name,this.value)});else for(n in e)jt(n,e[n],t,i);return r.join("&")},w.fn.extend({serialize:function(){return w.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=w.prop(this,"elements");return e?w.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!w(this).is(":disabled")&&At.test(this.nodeName)&&!Nt.test(e)&&(this.checked||!pe.test(e))}).map(function(e,t){var n=w(this).val();return null==n?null:Array.isArray(n)?w.map(n,function(e){return{name:t.name,value:e.replace(Dt,"\r\n")}}):{name:t.name,value:n.replace(Dt,"\r\n")}}).get()}});var qt=/%20/g,Lt=/#.*$/,Ht=/([?&])_=[^&]*/,Ot=/^(.*?):[ \t]*([^\r\n]*)$/gm,Pt=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Mt=/^(?:GET|HEAD)$/,Rt=/^\/\//,It={},Wt={},$t="*/".concat("*"),Bt=r.createElement("a");Bt.href=Ct.href;function Ft(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(M)||[];if(g(n))while(r=o[i++])"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function _t(e,t,n,r){var i={},o=e===Wt;function a(s){var u;return i[s]=!0,w.each(e[s]||[],function(e,s){var l=s(t,n,r);return"string"!=typeof l||o||i[l]?o?!(u=l):void 0:(t.dataTypes.unshift(l),a(l),!1)}),u}return a(t.dataTypes[0])||!i["*"]&&a("*")}function zt(e,t){var n,r,i=w.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&w.extend(!0,e,r),e}function Xt(e,t,n){var r,i,o,a,s=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader("Content-Type"));if(r)for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+" "+u[0]]){o=i;break}a||(a=i)}o=o||a}if(o)return o!==u[0]&&u.unshift(o),n[o]}function Ut(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if("*"===o)o=u;else if("*"!==u&&u!==o){if(!(a=l[u+" "+o]||l["* "+o]))for(i in l)if((s=i.split(" "))[1]===o&&(a=l[u+" "+s[0]]||l["* "+s[0]])){!0===a?a=l[i]:!0!==l[i]&&(o=s[0],c.unshift(s[1]));break}if(!0!==a)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(e){return{state:"parsererror",error:a?e:"No conversion from "+u+" to "+o}}}return{state:"success",data:t}}w.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Ct.href,type:"GET",isLocal:Pt.test(Ct.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":$t,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":w.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?zt(zt(e,w.ajaxSettings),t):zt(w.ajaxSettings,e)},ajaxPrefilter:Ft(It),ajaxTransport:Ft(Wt),ajax:function(t,n){"object"==typeof t&&(n=t,t=void 0),n=n||{};var i,o,a,s,u,l,c,f,p,d,h=w.ajaxSetup({},n),g=h.context||h,y=h.context&&(g.nodeType||g.jquery)?w(g):w.event,v=w.Deferred(),m=w.Callbacks("once memory"),x=h.statusCode||{},b={},T={},C="canceled",E={readyState:0,getResponseHeader:function(e){var t;if(c){if(!s){s={};while(t=Ot.exec(a))s[t[1].toLowerCase()]=t[2]}t=s[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return c?a:null},setRequestHeader:function(e,t){return null==c&&(e=T[e.toLowerCase()]=T[e.toLowerCase()]||e,b[e]=t),this},overrideMimeType:function(e){return null==c&&(h.mimeType=e),this},statusCode:function(e){var t;if(e)if(c)E.always(e[E.status]);else for(t in e)x[t]=[x[t],e[t]];return this},abort:function(e){var t=e||C;return i&&i.abort(t),k(0,t),this}};if(v.promise(E),h.url=((t||h.url||Ct.href)+"").replace(Rt,Ct.protocol+"//"),h.type=n.method||n.type||h.method||h.type,h.dataTypes=(h.dataType||"*").toLowerCase().match(M)||[""],null==h.crossDomain){l=r.createElement("a");try{l.href=h.url,l.href=l.href,h.crossDomain=Bt.protocol+"//"+Bt.host!=l.protocol+"//"+l.host}catch(e){h.crossDomain=!0}}if(h.data&&h.processData&&"string"!=typeof h.data&&(h.data=w.param(h.data,h.traditional)),_t(It,h,n,E),c)return E;(f=w.event&&h.global)&&0==w.active++&&w.event.trigger("ajaxStart"),h.type=h.type.toUpperCase(),h.hasContent=!Mt.test(h.type),o=h.url.replace(Lt,""),h.hasContent?h.data&&h.processData&&0===(h.contentType||"").indexOf("application/x-www-form-urlencoded")&&(h.data=h.data.replace(qt,"+")):(d=h.url.slice(o.length),h.data&&(h.processData||"string"==typeof h.data)&&(o+=(kt.test(o)?"&":"?")+h.data,delete h.data),!1===h.cache&&(o=o.replace(Ht,"$1"),d=(kt.test(o)?"&":"?")+"_="+Et+++d),h.url=o+d),h.ifModified&&(w.lastModified[o]&&E.setRequestHeader("If-Modified-Since",w.lastModified[o]),w.etag[o]&&E.setRequestHeader("If-None-Match",w.etag[o])),(h.data&&h.hasContent&&!1!==h.contentType||n.contentType)&&E.setRequestHeader("Content-Type",h.contentType),E.setRequestHeader("Accept",h.dataTypes[0]&&h.accepts[h.dataTypes[0]]?h.accepts[h.dataTypes[0]]+("*"!==h.dataTypes[0]?", "+$t+"; q=0.01":""):h.accepts["*"]);for(p in h.headers)E.setRequestHeader(p,h.headers[p]);if(h.beforeSend&&(!1===h.beforeSend.call(g,E,h)||c))return E.abort();if(C="abort",m.add(h.complete),E.done(h.success),E.fail(h.error),i=_t(Wt,h,n,E)){if(E.readyState=1,f&&y.trigger("ajaxSend",[E,h]),c)return E;h.async&&h.timeout>0&&(u=e.setTimeout(function(){E.abort("timeout")},h.timeout));try{c=!1,i.send(b,k)}catch(e){if(c)throw e;k(-1,e)}}else k(-1,"No Transport");function k(t,n,r,s){var l,p,d,b,T,C=n;c||(c=!0,u&&e.clearTimeout(u),i=void 0,a=s||"",E.readyState=t>0?4:0,l=t>=200&&t<300||304===t,r&&(b=Xt(h,E,r)),b=Ut(h,b,E,l),l?(h.ifModified&&((T=E.getResponseHeader("Last-Modified"))&&(w.lastModified[o]=T),(T=E.getResponseHeader("etag"))&&(w.etag[o]=T)),204===t||"HEAD"===h.type?C="nocontent":304===t?C="notmodified":(C=b.state,p=b.data,l=!(d=b.error))):(d=C,!t&&C||(C="error",t<0&&(t=0))),E.status=t,E.statusText=(n||C)+"",l?v.resolveWith(g,[p,C,E]):v.rejectWith(g,[E,C,d]),E.statusCode(x),x=void 0,f&&y.trigger(l?"ajaxSuccess":"ajaxError",[E,h,l?p:d]),m.fireWith(g,[E,C]),f&&(y.trigger("ajaxComplete",[E,h]),--w.active||w.event.trigger("ajaxStop")))}return E},getJSON:function(e,t,n){return w.get(e,t,n,"json")},getScript:function(e,t){return w.get(e,void 0,t,"script")}}),w.each(["get","post"],function(e,t){w[t]=function(e,n,r,i){return g(n)&&(i=i||r,r=n,n=void 0),w.ajax(w.extend({url:e,type:t,dataType:i,data:n,success:r},w.isPlainObject(e)&&e))}}),w._evalUrl=function(e){return w.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},w.fn.extend({wrapAll:function(e){var t;return this[0]&&(g(e)&&(e=e.call(this[0])),t=w(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(e){return g(e)?this.each(function(t){w(this).wrapInner(e.call(this,t))}):this.each(function(){var t=w(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=g(e);return this.each(function(n){w(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(e){return this.parent(e).not("body").each(function(){w(this).replaceWith(this.childNodes)}),this}}),w.expr.pseudos.hidden=function(e){return!w.expr.pseudos.visible(e)},w.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},w.ajaxSettings.xhr=function(){try{return new e.XMLHttpRequest}catch(e){}};var Vt={0:200,1223:204},Gt=w.ajaxSettings.xhr();h.cors=!!Gt&&"withCredentials"in Gt,h.ajax=Gt=!!Gt,w.ajaxTransport(function(t){var n,r;if(h.cors||Gt&&!t.crossDomain)return{send:function(i,o){var a,s=t.xhr();if(s.open(t.type,t.url,t.async,t.username,t.password),t.xhrFields)for(a in t.xhrFields)s[a]=t.xhrFields[a];t.mimeType&&s.overrideMimeType&&s.overrideMimeType(t.mimeType),t.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");for(a in i)s.setRequestHeader(a,i[a]);n=function(e){return function(){n&&(n=r=s.onload=s.onerror=s.onabort=s.ontimeout=s.onreadystatechange=null,"abort"===e?s.abort():"error"===e?"number"!=typeof s.status?o(0,"error"):o(s.status,s.statusText):o(Vt[s.status]||s.status,s.statusText,"text"!==(s.responseType||"text")||"string"!=typeof s.responseText?{binary:s.response}:{text:s.responseText},s.getAllResponseHeaders()))}},s.onload=n(),r=s.onerror=s.ontimeout=n("error"),void 0!==s.onabort?s.onabort=r:s.onreadystatechange=function(){4===s.readyState&&e.setTimeout(function(){n&&r()})},n=n("abort");try{s.send(t.hasContent&&t.data||null)}catch(e){if(n)throw e}},abort:function(){n&&n()}}}),w.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),w.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return w.globalEval(e),e}}}),w.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),w.ajaxTransport("script",function(e){if(e.crossDomain){var t,n;return{send:function(i,o){t=w("<script>").prop({charset:e.scriptCharset,src:e.url}).on("load error",n=function(e){t.remove(),n=null,e&&o("error"===e.type?404:200,e.type)}),r.head.appendChild(t[0])},abort:function(){n&&n()}}}});var Yt=[],Qt=/(=)\?(?=&|$)|\?\?/;w.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Yt.pop()||w.expando+"_"+Et++;return this[e]=!0,e}}),w.ajaxPrefilter("json jsonp",function(t,n,r){var i,o,a,s=!1!==t.jsonp&&(Qt.test(t.url)?"url":"string"==typeof t.data&&0===(t.contentType||"").indexOf("application/x-www-form-urlencoded")&&Qt.test(t.data)&&"data");if(s||"jsonp"===t.dataTypes[0])return i=t.jsonpCallback=g(t.jsonpCallback)?t.jsonpCallback():t.jsonpCallback,s?t[s]=t[s].replace(Qt,"$1"+i):!1!==t.jsonp&&(t.url+=(kt.test(t.url)?"&":"?")+t.jsonp+"="+i),t.converters["script json"]=function(){return a||w.error(i+" was not called"),a[0]},t.dataTypes[0]="json",o=e[i],e[i]=function(){a=arguments},r.always(function(){void 0===o?w(e).removeProp(i):e[i]=o,t[i]&&(t.jsonpCallback=n.jsonpCallback,Yt.push(i)),a&&g(o)&&o(a[0]),a=o=void 0}),"script"}),h.createHTMLDocument=function(){var e=r.implementation.createHTMLDocument("").body;return e.innerHTML="<form></form><form></form>",2===e.childNodes.length}(),w.parseHTML=function(e,t,n){if("string"!=typeof e)return[];"boolean"==typeof t&&(n=t,t=!1);var i,o,a;return t||(h.createHTMLDocument?((i=(t=r.implementation.createHTMLDocument("")).createElement("base")).href=r.location.href,t.head.appendChild(i)):t=r),o=A.exec(e),a=!n&&[],o?[t.createElement(o[1])]:(o=xe([e],t,a),a&&a.length&&w(a).remove(),w.merge([],o.childNodes))},w.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return s>-1&&(r=vt(e.slice(s)),e=e.slice(0,s)),g(t)?(n=t,t=void 0):t&&"object"==typeof t&&(i="POST"),a.length>0&&w.ajax({url:e,type:i||"GET",dataType:"html",data:t}).done(function(e){o=arguments,a.html(r?w("<div>").append(w.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},w.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){w.fn[t]=function(e){return this.on(t,e)}}),w.expr.pseudos.animated=function(e){return w.grep(w.timers,function(t){return e===t.elem}).length},w.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l,c=w.css(e,"position"),f=w(e),p={};"static"===c&&(e.style.position="relative"),s=f.offset(),o=w.css(e,"top"),u=w.css(e,"left"),(l=("absolute"===c||"fixed"===c)&&(o+u).indexOf("auto")>-1)?(a=(r=f.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),g(t)&&(t=t.call(e,n,w.extend({},s))),null!=t.top&&(p.top=t.top-s.top+a),null!=t.left&&(p.left=t.left-s.left+i),"using"in t?t.using.call(e,p):f.css(p)}},w.fn.extend({offset:function(e){if(arguments.length)return void 0===e?this:this.each(function(t){w.offset.setOffset(this,e,t)});var t,n,r=this[0];if(r)return r.getClientRects().length?(t=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:t.top+n.pageYOffset,left:t.left+n.pageXOffset}):{top:0,left:0}},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===w.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===w.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=w(e).offset()).top+=w.css(e,"borderTopWidth",!0),i.left+=w.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-w.css(r,"marginTop",!0),left:t.left-i.left-w.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===w.css(e,"position"))e=e.offsetParent;return e||be})}}),w.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,t){var n="pageYOffset"===t;w.fn[e]=function(r){return z(this,function(e,r,i){var o;if(y(e)?o=e:9===e.nodeType&&(o=e.defaultView),void 0===i)return o?o[t]:e[r];o?o.scrollTo(n?o.pageXOffset:i,n?i:o.pageYOffset):e[r]=i},e,r,arguments.length)}}),w.each(["top","left"],function(e,t){w.cssHooks[t]=_e(h.pixelPosition,function(e,n){if(n)return n=Fe(e,t),We.test(n)?w(e).position()[t]+"px":n})}),w.each({Height:"height",Width:"width"},function(e,t){w.each({padding:"inner"+e,content:t,"":"outer"+e},function(n,r){w.fn[r]=function(i,o){var a=arguments.length&&(n||"boolean"!=typeof i),s=n||(!0===i||!0===o?"margin":"border");return z(this,function(t,n,i){var o;return y(t)?0===r.indexOf("outer")?t["inner"+e]:t.document.documentElement["client"+e]:9===t.nodeType?(o=t.documentElement,Math.max(t.body["scroll"+e],o["scroll"+e],t.body["offset"+e],o["offset"+e],o["client"+e])):void 0===i?w.css(t,n,s):w.style(t,n,i,s)},t,a?i:void 0,a)}})}),w.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,t){w.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),w.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),w.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)}}),w.proxy=function(e,t){var n,r,i;if("string"==typeof t&&(n=e[t],t=e,e=n),g(e))return r=o.call(arguments,2),i=function(){return e.apply(t||this,r.concat(o.call(arguments)))},i.guid=e.guid=e.guid||w.guid++,i},w.holdReady=function(e){e?w.readyWait++:w.ready(!0)},w.isArray=Array.isArray,w.parseJSON=JSON.parse,w.nodeName=N,w.isFunction=g,w.isWindow=y,w.camelCase=G,w.type=x,w.now=Date.now,w.isNumeric=function(e){var t=w.type(e);return("number"===t||"string"===t)&&!isNaN(e-parseFloat(e))},"function"==typeof define&&define.amd&&define("jquery",[],function(){return w});var Jt=e.jQuery,Kt=e.$;return w.noConflict=function(t){return e.$===w&&(e.$=Kt),t&&e.jQuery===w&&(e.jQuery=Jt),w},t||(e.jQuery=e.$=w),w});
diff --git a/p/scripts/main.js b/p/scripts/main.js
index f8d20767a..f96828048 100644
--- a/p/scripts/main.js
+++ b/p/scripts/main.js
@@ -114,6 +114,17 @@ function incUnreadsFeed(article, feed_id, nb) {
return isCurrentView;
}
+function incUnreadsTag(tag_id, nb) {
+ var $t = $('#t_' + tag_id);
+ var unreads = str2int($t.attr('data-unread'));
+ $t.attr('data-unread', unreads + nb)
+ .children('.item-title').attr('data-unread', numberFormat(unreads + nb));
+
+ $t = $('.category.tags').find('.title');
+ unreads = str2int($t.attr('data-unread'));
+ $t.attr('data-unread', numberFormat(unreads + nb));
+}
+
var pending_entries = {};
function mark_read(active, only_not_read) {
if ((active.length === 0) || (!active.attr('id')) ||
@@ -157,6 +168,12 @@ function mark_read(active, only_not_read) {
}
faviconNbUnread();
+ if (data.tags) {
+ for (var i = data.tags.length - 1; i >= 0; i--) {
+ incUnreadsTag(data.tags[i], inc);
+ }
+ }
+
delete pending_entries[active.attr('id')];
}).fail(function (data) {
openNotification(i18n.notif_request_failed, 'bad');
@@ -529,12 +546,16 @@ function init_column_categories() {
$(this).parent().next(".tree-folder-items").slideToggle(300 , function() { $(document.body).trigger("sticky_kit:recalc"); });
return false;
});
- $('#aside_feed').on('click', '.tree-folder-items .item .dropdown-toggle', function () {
+ $('#aside_feed').on('click', '.tree-folder-items .feed .dropdown-toggle', function () {
if ($(this).nextAll('.dropdown-menu').length === 0) {
- var feed_id = $(this).closest('.item').attr('id').substr(2),
+ var itemId = $(this).closest('.item').attr('id'),
+ templateId = itemId.substring(0, 2) === 't_' ? 'tag_config_template' : 'feed_config_template',
+ id = itemId.substr(2),
feed_web = $(this).data('fweb'),
- template = $('#feed_config_template').html().replace(/------/g, feed_id).replace('http://example.net/', feed_web);
- $(this).attr('href', '#dropdown-' + feed_id).prev('.dropdown-target').attr('id', 'dropdown-' + feed_id).parent().append(template);
+ template = $('#' + templateId)
+ .html().replace(/------/g, id).replace('http://example.net/', feed_web);
+ $(this).attr('href', '#dropdown-' + id).prev('.dropdown-target').attr('id', 'dropdown-' + id).parent()
+ .append(template).find('button.confirm').removeAttr('disabled');
$('.tree-folder-items .dropdown-close a').click(function(){
$('.tree').removeClass('treepadding');
$(document.body).trigger("sticky_kit:recalc");
@@ -606,7 +627,7 @@ function init_shortcuts() {
auto_share(String.fromCharCode(evt.keyCode));
}
}
- for(var i = 1; i < 10; i++) {
+ for (var i = 1; i < 10; i++) {
shortcut.add(i.toString(), addShortcut, {
'disable_in_input': true
});
@@ -731,7 +752,7 @@ function init_shortcuts() {
function init_stream(divStream) {
divStream.on('click', '.flux_header,.flux_content', function (e) { //flux_toggle
- if ($(e.target).closest('.content, .item.website, .item.link').length > 0) {
+ if ($(e.target).closest('.keep_unread, .content, .item.website, .item.link, .dropdown-menu').length > 0) {
return;
}
if (!context.sides_close_article && $(e.target).is('div.flux_content')) {
@@ -788,7 +809,9 @@ function init_stream(divStream) {
});
divStream.on('click', '.flux .content a', function () {
- $(this).attr('target', '_blank').attr('rel', 'noreferrer');
+ if (!$(this).closest('div').hasClass('author')) {
+ $(this).attr('target', '_blank').attr('rel', 'noreferrer');
+ }
});
if (context.auto_mark_site) {
@@ -828,6 +851,69 @@ function init_nav_entries() {
});
}
+function loadDynamicTags($div) {
+ $div.removeClass('dynamictags');
+ $div.find('li.item').remove();
+ var entryId = $div.closest('div.flux').attr('id').replace(/^flux_/, '');
+ $.getJSON('./?c=tag&a=getTagsForEntry&id_entry=' + entryId)
+ .done(function (data) {
+ var $ul = $div.find('.dropdown-menu');
+ $ul.append('<li class="item"><label><input class="checkboxTag" name="t_0" type="checkbox" /> <input type="text" name="newTag" /></label></li>');
+ if (data && data.length) {
+ for (var i = 0; i < data.length; i++) {
+ var tag = data[i];
+ $ul.append('<li class="item"><label><input class="checkboxTag" name="t_' + tag.id + '" type="checkbox"' +
+ (tag.checked ? ' checked="checked"' : '') + '> ' + tag.name + '</label></li>');
+ }
+ }
+ })
+ .fail(function () {
+ $div.find('li.item').remove();
+ $div.addClass('dynamictags');
+ });
+}
+
+function init_dynamic_tags() {
+ $stream.on('click', '.dynamictags', function () {
+ loadDynamicTags($(this));
+ });
+
+ $stream.on('change', '.checkboxTag', function (ev) {
+ var $checkbox = $(this);
+ $checkbox.prop('disabled', true);
+ var isChecked = $checkbox.prop('checked');
+ var tagId = $checkbox.attr('name').replace(/^t_/, '');
+ var tagName = $checkbox.siblings('input[name]').val();
+ var $entry = $checkbox.closest('div.flux');
+ var entryId = $entry.attr('id').replace(/^flux_/, '');
+ $.ajax({
+ type: 'POST',
+ url: './?c=tag&a=tagEntry',
+ data: {
+ _csrf: context.csrf,
+ id_tag: tagId,
+ name_tag: tagId == 0 ? tagName : '',
+ id_entry: entryId,
+ checked: isChecked,
+ },
+ })
+ .done(function () {
+ if ($entry.hasClass('not_read')) {
+ incUnreadsTag(tagId, isChecked ? 1 : -1);
+ }
+ })
+ .fail(function () {
+ $checkbox.prop('checked', !isChecked);
+ })
+ .always(function () {
+ $checkbox.prop('disabled', false);
+ if (tagId == 0) {
+ loadDynamicTags($checkbox.closest('div.dropdown'));
+ }
+ });
+ });
+}
+
// <actualize>
var feed_processed = 0;
@@ -841,7 +927,7 @@ function updateFeed(feeds, feeds_count) {
url: feed.url,
data: {
_csrf: context.csrf,
- noCommit: feeds.length > 0 ? 1 : 0,
+ noCommit: 1,
},
}).always(function (data) {
feed_processed++;
@@ -849,7 +935,16 @@ function updateFeed(feeds, feeds_count) {
$("#actualizeProgress .title").html(feed.title);
if (feed_processed === feeds_count) {
- window.location.reload();
+ $.ajax({ //Empty request to commit new articles
+ type: 'POST',
+ url: './?c=feed&a=actualize&id=-1&ajax=1',
+ data: {
+ _csrf: context.csrf,
+ noCommit: 0,
+ },
+ }).always(function (data) {
+ window.location.reload();
+ });
} else {
updateFeed(feeds, feeds_count);
}
@@ -875,7 +970,7 @@ function init_actualize() {
openNotification(data.feedback_no_refresh, "good");
$.ajax({ //Empty request to force refresh server database cache
type: 'POST',
- url: './?c=feed&a=actualize&id=-1',
+ url: './?c=feed&a=actualize&id=-1&ajax=1',
data: {
_csrf: context.csrf,
noCommit: 0,
@@ -1002,7 +1097,7 @@ function refreshUnreads() {
var isAll = $('.category.all.active').length > 0,
new_articles = false;
- $.each(data, function(feed_id, nbUnreads) {
+ $.each(data.feeds, function(feed_id, nbUnreads) {
feed_id = 'f_' + feed_id;
var elem = $('#' + feed_id).get(0),
feed_unreads = elem ? str2int(elem.getAttribute('data-unread')) : 0;
@@ -1014,6 +1109,17 @@ function refreshUnreads() {
}
});
+ var nbUnreadTags = 0;
+
+ $.each(data.tags, function(tag_id, nbUnreads) {
+ nbUnreadTags += nbUnreads;
+ $('#t_' + tag_id).attr('data-unread', nbUnreads)
+ .children('.item-title').attr('data-unread', numberFormat(nbUnreads));
+ });
+
+ $('.category.tags').attr('data-unread', nbUnreadTags)
+ .find('.title').attr('data-unread', numberFormat(nbUnreadTags));
+
var nb_unreads = str2int($('.category.all .title').attr('data-unread'));
if (nb_unreads > 0 && new_articles) {
@@ -1073,7 +1179,6 @@ freshrssLoadMoreEvent.initEvent('freshrss:load-more', true, true);
function init_load_more(box) {
box_load_more = box;
-
document.body.dispatchEvent(freshrssLoadMoreEvent);
var $next_link = $("#load_more");
@@ -1084,12 +1189,6 @@ function init_load_more(box) {
}
url_load_more = $next_link.attr("href");
- var $prefetch = $('#prefetch');
- if ($prefetch.attr('href') !== url_load_more) {
- $prefetch.attr('rel', 'next'); //Remove prefetch
- $.ajax({url: url_load_more, ifModified: true }); //TODO: Try to find a less agressive solution
- $prefetch.attr('href', url_load_more);
- }
$next_link.click(function () {
load_more_posts();
@@ -1424,12 +1523,13 @@ function init_afterDOM() {
return;
}
init_notifications();
+ init_confirm_action();
$stream = $('#stream');
if ($stream.length > 0) {
- init_confirm_action();
init_load_more($stream);
init_posts();
init_nav_entries();
+ init_dynamic_tags();
init_print_action();
init_post_action();
init_notifs_html5();
diff --git a/p/themes/BlueLagoon/BlueLagoon.css b/p/themes/BlueLagoon/BlueLagoon.css
index 424970501..164088f4b 100644
--- a/p/themes/BlueLagoon/BlueLagoon.css
+++ b/p/themes/BlueLagoon/BlueLagoon.css
@@ -373,6 +373,9 @@ a.btn {
color: #ccc;
font-size: 0.8rem;
}
+.dropdown-menu > .item > label {
+ color: #ccc;
+}
.dropdown-menu > .item:hover {
background: linear-gradient(180deg, #0090FF 0%, #0062BE 100%) #E4992C;
background: -webkit-linear-gradient(top, #0090FF 0%, #0062BE 100%);
diff --git a/p/themes/Dark/dark.css b/p/themes/Dark/dark.css
index 38a78a277..31ff514a2 100644
--- a/p/themes/Dark/dark.css
+++ b/p/themes/Dark/dark.css
@@ -161,6 +161,7 @@ button.as-link[disabled] {
display: inline-block;
min-height: 37px;
min-width: 15px;
+ line-height: 25px;
margin: 0;
padding: 5px 10px;
font-size: 0.9rem;
diff --git a/p/themes/Flat/flat.css b/p/themes/Flat/flat.css
index 62c4808a4..be047a394 100644
--- a/p/themes/Flat/flat.css
+++ b/p/themes/Flat/flat.css
@@ -167,6 +167,7 @@ form th {
display: inline-block;
min-height: 38px;
min-width: 15px;
+ line-height: 25px;
margin: 0;
padding: 5px 10px;
font-size: 0.9rem;
@@ -299,6 +300,7 @@ a.btn {
/*=== Dropdown */
.dropdown-menu {
+ background: #fafafa;
margin: 5px 0 0;
padding: 5px 0;
font-size: 0.8rem;
diff --git a/p/themes/Origine/origine.css b/p/themes/Origine/origine.css
index 4a697e811..d5f644a1b 100644
--- a/p/themes/Origine/origine.css
+++ b/p/themes/Origine/origine.css
@@ -148,6 +148,7 @@ form th {
display: inline-block;
min-height: 37px;
min-width: 15px;
+ line-height: 25px;
margin: 0;
padding: 5px 10px;
background: #fff;
diff --git a/p/themes/Pafat/pafat.css b/p/themes/Pafat/pafat.css
index 1b6ebca29..64da9f2dc 100644
--- a/p/themes/Pafat/pafat.css
+++ b/p/themes/Pafat/pafat.css
@@ -151,6 +151,7 @@ form th {
display: inline-block;
min-height: 29px;
min-width: 15px;
+ line-height: 25px;
margin: 0;
padding: 1px 5px;
background: #fff;
@@ -168,12 +169,6 @@ a.btn {
line-height: 25px;
}
-
-a.btn {
- min-height: 25px;
- line-height: 25px;
-}
-
.read_all.btn {
height:29px;
}
diff --git a/p/themes/Screwdriver/screwdriver.css b/p/themes/Screwdriver/screwdriver.css
index a142c3860..1bc49c2db 100644
--- a/p/themes/Screwdriver/screwdriver.css
+++ b/p/themes/Screwdriver/screwdriver.css
@@ -373,6 +373,9 @@ a.btn {
color: #ccc;
font-size: 0.8rem;
}
+.dropdown-menu > .item > label {
+ color: #ccc;
+}
.dropdown-menu > .item:hover {
background: #171717;
color: #fff;
diff --git a/p/themes/Swage/icons/add.svg b/p/themes/Swage/icons/add.svg
new file mode 100644
index 000000000..49ca39bb4
--- /dev/null
+++ b/p/themes/Swage/icons/add.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 16 16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
+<style type="text/css">.st0{fill:#FFFFFF;}</style>
+<g transform="translate(-60 -726)">
+<path class="st0" d="m67 729.5v3c0 0.3-0.2 0.5-0.5 0.5h-3c-0.3 0-0.5 0.2-0.5 0.5v1c0 0.3 0.2 0.5 0.5 0.5h3c0.3 0 0.5 0.2 0.5 0.5v3c0 0.3 0.2 0.5 0.5 0.5h1c0.3 0 0.5-0.2 0.5-0.5v-3c0-0.3 0.2-0.5 0.5-0.5h3c0.3 0 0.5-0.2 0.5-0.5v-1c0-0.3-0.2-0.5-0.5-0.5h-3c-0.3 0-0.5-0.2-0.5-0.5v-3c0-0.3-0.2-0.5-0.5-0.5h-1c-0.3 0-0.5 0.2-0.5 0.5z"/>
+</g>
+</svg>
diff --git a/p/themes/Swage/icons/all.svg b/p/themes/Swage/icons/all.svg
new file mode 100644
index 000000000..df7d903b1
--- /dev/null
+++ b/p/themes/Swage/icons/all.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 16 16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
+<style type="text/css"> .st0{fill:#FFFFFF;}</style>
+<rect class="st0" width="16" height="2.6"/>
+<rect class="st0" y="6.7" width="16" height="2.6"/>
+<rect class="st0" y="13.4" width="16" height="2.6"/>
+</svg>
diff --git a/p/themes/Swage/icons/bookmark-add.svg b/p/themes/Swage/icons/bookmark-add.svg
new file mode 100644
index 000000000..ee23bff9b
--- /dev/null
+++ b/p/themes/Swage/icons/bookmark-add.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 16 16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
+<style type="text/css">.st0{fill:#FFFFFF;}</style>
+<polygon class="st0" points="16 5.3 13.7 5.3 13.7 3 12 3 12 5.3 9.8 5.3 9.8 6.9 12 6.9 12 9.2 13.7 9.2 13.7 6.9 16 6.9"/>
+<path class="st0" d="M11,10.2V7.9H8.8V4.3H11V2h1.8V1.7c0-1-0.8-1.7-1.7-1.7H2.5c-1,0-1.7,0.8-1.7,1.7l0,13.9L6.8,13l6.1,2.6v-5.4 H11z"/>
+</svg>
diff --git a/p/themes/Swage/icons/bookmark.svg b/p/themes/Swage/icons/bookmark.svg
new file mode 100644
index 000000000..09bf263fd
--- /dev/null
+++ b/p/themes/Swage/icons/bookmark.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 16 16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
+<style type="text/css">.st0{fill:#FFD255;}</style>
+<path class="st0" d="M8,12.6l4.9,3L11.6,10L16,6.2l-5.7-0.5L8,0.4L5.8,5.7L0,6.2L4.4,10l-1.3,5.6L8,12.6z"/>
+</svg>
+
diff --git a/p/themes/Swage/icons/category.svg b/p/themes/Swage/icons/category.svg
new file mode 100644
index 000000000..f0b57d5a1
--- /dev/null
+++ b/p/themes/Swage/icons/category.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 16 16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
+<style type="text/css">.st0{fill:#FFFFFF;}
+</style>
+<rect class="st0" y="5.9" width="3.8" height="3.8"/>
+<rect class="st0" x="5.9" y="5.9" width="10.1" height="3.8"/>
+<rect class="st0" width="3.8" height="3.8"/>
+<rect class="st0" x="5.9" width="10.1" height="3.8"/>
+<rect class="st0" y="11.8" width="3.8" height="3.8"/>
+<rect class="st0" x="5.9" y="11.8" width="10.1" height="3.8"/>
+</svg>
+
diff --git a/p/themes/Swage/icons/configure.svg b/p/themes/Swage/icons/configure.svg
new file mode 100644
index 000000000..a1a87180e
--- /dev/null
+++ b/p/themes/Swage/icons/configure.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 16 16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
+<style type="text/css">
+ .st0{fill:none;}
+ .st1{fill:#FFFFFF;}
+</style>
+<path class="st0" d="M-2-1h20v20H-2V-1z"/>
+<path class="st1" d="M13.9,8.8C14,8.5,14,8.3,14,8s0-0.5-0.1-0.8l1.7-1.3c0.1-0.1,0.2-0.3,0.1-0.5l-1.6-2.8 c-0.1-0.2-0.3-0.2-0.5-0.2l-2,0.8c-0.4-0.3-0.9-0.6-1.4-0.8L10,0.3C10,0.1,9.8,0,9.6,0H6.4C6.2,0,6,0.1,6,0.3L5.7,2.5
+C5.2,2.7,4.8,2.9,4.4,3.2l-2-0.8C2.2,2.4,2,2.4,1.9,2.6L0.3,5.4C0.2,5.6,0.2,5.8,0.4,5.9l1.7,1.3C2,7.5,2,7.7,2,8s0,0.5,0.1,0.8 l-1.7,1.3c-0.2,0.1-0.2,0.3-0.1,0.5l1.6,2.8c0.1,0.2,0.3,0.2,0.5,0.2l2-0.8c0.4,0.3,0.9,0.6,1.3,0.8L6,15.7C6,15.9,6.2,16,6.4,16
+h3.2c0.2,0,0.4-0.1,0.4-0.3l0.3-2.1c0.5-0.2,0.9-0.5,1.4-0.8l2,0.8c0.2,0.1,0.4,0,0.5-0.2l1.6-2.8c0.1-0.2,0.1-0.4-0.1-0.5 C15.6,10.1,14,8.8,13.9,8.8z M8,11c-1.6,0-3-1.4-3-3s1.4-3,3-3s3,1.4,3,3S9.6,11,8,11z"/>
+</svg>
+
diff --git a/p/themes/Swage/icons/down.svg b/p/themes/Swage/icons/down.svg
new file mode 100644
index 000000000..6450ee37e
--- /dev/null
+++ b/p/themes/Swage/icons/down.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 16 16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
+<style type="text/css">.st0{fill:#FFFFFF;}</style>
+<path class="st0" d="m12.2 5.3l-4.2 6.6-4.2-6.6h8.4m3.6-2h-15.6l7.8 12.3 7.8-12.3z"/>
+</svg>
+
diff --git a/p/themes/Swage/icons/error.svg b/p/themes/Swage/icons/error.svg
new file mode 100644
index 000000000..840c8c57b
--- /dev/null
+++ b/p/themes/Swage/icons/error.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<style type="text/css">.st0{fill:#B0425B;}</style>
+<path class="st0" d="M0,16h16L8,2.2L0,16z M8.7,13.8H7.3v-1.5h1.5V13.8z M8.7,10.9H7.3V8h1.5V10.9z"/>
+</svg>
diff --git a/p/themes/Swage/icons/icon.svg b/p/themes/Swage/icons/icon.svg
new file mode 100644
index 000000000..c6bbd08bd
--- /dev/null
+++ b/p/themes/Swage/icons/icon.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 256 256" version="1.1" viewBox="0 0 256 256" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
+<style type="text/css">
+.st0{fill:#FFFFFF;}
+.st1{fill:none;stroke:#FFFFFF;stroke-width:24;stroke-opacity:0.3;}
+.st2{fill:none;stroke:#FFFFFF;stroke-width:24;}
+</style>
+<title>Logo FreshRSS</title>
+<circle class="st0" cx="128" cy="128" r="33"/>
+<path class="st1" d="m12 128c0-64.1 51.9-116 116-116s116 51.9 116 116-51.9 116-116 116"/>
+<path class="st1" d="m54 128c0-40.9 33.1-74 74-74s74 33.1 74 74-33.1 74-74 74"/>
+<path class="st2" d="m128 12c64.1 0 116 51.9 116 116"/>
+<path class="st2" d="m128 54c40.9 0 74 33.1 74 74"/>
+</svg>
diff --git a/p/themes/Swage/icons/import.svg b/p/themes/Swage/icons/import.svg
new file mode 100644
index 000000000..1f26448ff
--- /dev/null
+++ b/p/themes/Swage/icons/import.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 16 16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
+<style type="text/css">.st0{fill:#FFFFFF;}</style>
+<path class="st0" d="M15,16v-2H1v2H15z M15,6h-4V0H5v6H1l7,7L15,6z"/>
+</svg>
+
diff --git a/p/themes/Swage/icons/next.svg b/p/themes/Swage/icons/next.svg
new file mode 100644
index 000000000..056e70f3c
--- /dev/null
+++ b/p/themes/Swage/icons/next.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 16 16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
+<style type="text/css">.st0{fill:#FFFFFF;}</style>
+ <path class="st0" d="m5.2 7l4 2.5-4 2.5v-5m-2-3.7v12.3l9.7-6.1-9.7-6.2z"/>
+</svg>
diff --git a/p/themes/Swage/icons/non-starred.svg b/p/themes/Swage/icons/non-starred.svg
new file mode 100644
index 000000000..714697060
--- /dev/null
+++ b/p/themes/Swage/icons/non-starred.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 16 16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
+<style type="text/css">.st0{fill:#DDDDDD;}</style>
+<path class="st0" d="m16 6.2l-5.7-0.5-2.3-5.3-2.2 5.3-5.8 0.5 4.4 3.8-1.3 5.6 4.9-3 4.9 3-1.3-5.6 4.4-3.8zm-8 4.9l-3 1.8 0.8-3.4-2.7-2.3 3.5-0.3 1.4-3.2 1.4 3.2 3.5 0.3-2.7 2.3 0.8 3.4-3-1.8z"/>
+</svg>
+
diff --git a/p/themes/Swage/icons/prev.svg b/p/themes/Swage/icons/prev.svg
new file mode 100644
index 000000000..2f6ed886c
--- /dev/null
+++ b/p/themes/Swage/icons/prev.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 16 16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
+<style type="text/css">.st0{fill:#FFFFFF;}</style>
+<path class="st0" d="m10.8 6.9v5l-3.9-2.5 3.9-2.5m2-3.6l-9.6 6.1 9.6 6.2v-12.3z"/>
+</svg>
+
diff --git a/p/themes/Swage/icons/read.svg b/p/themes/Swage/icons/read.svg
new file mode 100644
index 000000000..86f3e60f3
--- /dev/null
+++ b/p/themes/Swage/icons/read.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 16 16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
+<style type="text/css">.st0{fill:#DDDDDD;}</style>
+<path class="st0" d="M15.9,6c0-0.6-0.3-1.1-0.7-1.4L8,0.4L0.8,4.6C0.3,4.9,0,5.4,0,6v8c0,0.9,0.7,1.6,1.6,1.6h12.8,c0.9,0,1.6-0.7,1.6-1.6L15.9,6z M8,10L1.4,5.9L8,2l6.6,3.9L8,10z"/>
+</svg>
diff --git a/p/themes/Swage/icons/refresh.svg b/p/themes/Swage/icons/refresh.svg
new file mode 100644
index 000000000..858a1f50f
--- /dev/null
+++ b/p/themes/Swage/icons/refresh.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 16 16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
+<style type="text/css">.st0{fill:#FFFFFF;}</style>
+<path class="st0" d="M13.5,2.4C12.1,1,10.1,0.1,8,0.1c-4.3,0-7.7,3.5-7.7,7.7s3.5,7.7,7.7,7.7c3.6,0,6.6-2.5,7.5-5.8h-2,c-0.8,2.3-2.9,3.9-5.5,3.9c-3.2,0-5.8-2.6-5.8-5.8S4.8,2.1,8,2.1c1.6,0,3,0.7,4.1,1.7L9,6.9h6.8V0.1L13.5,2.4z"/>
+</svg>
+
diff --git a/p/themes/Swage/icons/rss.svg b/p/themes/Swage/icons/rss.svg
new file mode 100644
index 000000000..0be960048
--- /dev/null
+++ b/p/themes/Swage/icons/rss.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 16 16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
+<style type="text/css">.st0{fill:#FFFFFF;}</style>
+<circle class="st0" cx="2.4" cy="13.4" r="2.2"/>
+<path class="st0" d="m0.2 0v2.8c7 0 12.7 5.7 12.7 12.7h2.8c0.1-8.5-6.9-15.5-15.5-15.5zm0 5.7v2.8c3.9 0 7.1 3.2 7.1 7.1h2.8c0-5.5-4.4-9.9-9.9-9.9z"/>
+</svg>
+
diff --git a/p/themes/Swage/icons/starred.svg b/p/themes/Swage/icons/starred.svg
new file mode 100644
index 000000000..09bf263fd
--- /dev/null
+++ b/p/themes/Swage/icons/starred.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 16 16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
+<style type="text/css">.st0{fill:#FFD255;}</style>
+<path class="st0" d="M8,12.6l4.9,3L11.6,10L16,6.2l-5.7-0.5L8,0.4L5.8,5.7L0,6.2L4.4,10l-1.3,5.6L8,12.6z"/>
+</svg>
+
diff --git a/p/themes/Swage/icons/unread.svg b/p/themes/Swage/icons/unread.svg
new file mode 100644
index 000000000..28c654176
--- /dev/null
+++ b/p/themes/Swage/icons/unread.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 16 16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
+<style type="text/css">.st0{fill:#FF6633;}</style>
+<path class="st0" d="m14.4 2.8h-12.8c-0.9 0-1.6 0.6-1.6 1.5v9.7c0 0.9 0.7 1.6 1.6 1.6h12.8c0.9 0 1.6-0.7 1.6-1.6v-9.7c0.1-0.9-0.7-1.5-1.6-1.5zm0 3.1l-6.4 4.1-6.4-4v-1.7l6.4 4 6.4-4v1.6z"/>
+</svg>
+
diff --git a/p/themes/Swage/icons/up.svg b/p/themes/Swage/icons/up.svg
new file mode 100644
index 000000000..2b89c550c
--- /dev/null
+++ b/p/themes/Swage/icons/up.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 16 16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
+<style type="text/css">.st0{fill:#FFFFFF;}</style>
+<path class="st0" d="M8,7l4.2,6.6H3.8L8,7 M8,3.3L0.2,15.6h15.6L8,3.3L8,3.3z"/>
+</svg>
+
diff --git a/p/themes/Swage/icons/view-global.svg b/p/themes/Swage/icons/view-global.svg
new file mode 100644
index 000000000..c289498e6
--- /dev/null
+++ b/p/themes/Swage/icons/view-global.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 16 16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
+<style type="text/css">.st0{fill:#FFFFFF;}</style>
+<path class="st0" d="M0.2,8.7h6.9V0H0.2V8.7z M0.2,15.6h6.9v-5.2H0.2V15.6z M8.9,15.6h6.9V6.9H8.9V15.6z M8.9,0v5.2h6.9V0H8.9z"/>
+</svg>
+
diff --git a/p/themes/Swage/icons/view-normal.svg b/p/themes/Swage/icons/view-normal.svg
new file mode 100644
index 000000000..9135c070f
--- /dev/null
+++ b/p/themes/Swage/icons/view-normal.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 16 16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
+<style type="text/css">.st0{fill:#FFFFFF;}</style>
+<rect class="st0" width="16" height="2.6"/>
+<rect class="st0" y="6.5" width="16" height="2.6"/>
+<rect class="st0" y="13" width="16" height="2.6"/>
+</svg>
+
diff --git a/p/themes/Swage/icons/view-reader.svg b/p/themes/Swage/icons/view-reader.svg
new file mode 100644
index 000000000..f8f9e7af5
--- /dev/null
+++ b/p/themes/Swage/icons/view-reader.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 16 16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
+<style type="text/css">.st0{fill:#FFFFFF;}</style>
+<path class="st0" d="M8.7,7.3h5.1v1.4H8.7V7.3z M8.7,5h5.1v1.4H8.7V5z M8.7,9.6h5.1V11H8.7V9.6z M14.5,0H1.5C0.7,0,0,0.8,0,1.8v11.9,c0,1,0.7,1.8,1.5,1.8h13.1c0.8,0,1.5-0.8,1.5-1.8V1.8C16,0.8,15.3,0,14.5,0z M14.5,13.8H8V1.8h6.5V13.8z"/>
+</svg>
+
diff --git a/p/themes/Swage/loader.gif b/p/themes/Swage/loader.gif
new file mode 100644
index 000000000..b7c6647cd
--- /dev/null
+++ b/p/themes/Swage/loader.gif
Binary files differ
diff --git a/p/themes/Swage/metadata.json b/p/themes/Swage/metadata.json
new file mode 100644
index 000000000..a81c10cfd
--- /dev/null
+++ b/p/themes/Swage/metadata.json
@@ -0,0 +1,7 @@
+{
+ "name": "Swage",
+ "author": "Patrick Crandol",
+ "description": "A Fresh take on the interface, inspired by the Flat Theme.",
+ "version": 1.0,
+ "files": ["_template.css", "swage.css"]
+}
diff --git a/p/themes/Swage/swage.css b/p/themes/Swage/swage.css
new file mode 100644
index 000000000..5cab13bd7
--- /dev/null
+++ b/p/themes/Swage/swage.css
@@ -0,0 +1,1211 @@
+textarea,input,select {
+min-height:25px;
+margin-top:4px;
+line-height:25px;
+vertical-align:middle;
+background:#FCFCFC;
+border:none;
+padding-left:5px
+}
+
+input:invalid,select:invalid {
+color:#B0425B;
+border-color:#B0425B;
+box-shadow:none
+}
+
+.nav-list .nav-header,.nav-list .item {
+height:2.5em;
+line-height:2.5em;
+font-size:.9rem
+}
+
+.dropdown-menu > .item,.dropdown-menu > .item > a,.dropdown-menu > .item > span,.dropdown-menu > .item > as-link,.dropdown-menu > .item button {
+padding:0 22px;
+line-height:2.5em;
+font-size:.8rem;
+color:#FCFCFC
+}
+
+.form-group::after,.flux::after {
+content:"";
+display:block;
+clear:both
+}
+
+html,body {
+height:100%;
+font-family:Helvetica,Arial,sans-serif
+}
+
+a {
+color:#00488b;
+outline:none
+}
+
+a.btn {
+min-height:25px;
+line-height:25px;
+text-decoration:none
+}
+
+a.btn:hover {
+background:#00488b
+}
+
+img.icon:hover {
+background:none
+}
+
+div#stream {
+margin-top:35px
+}
+
+sup {
+top:-.3em
+}
+
+legend {
+display:inline-block;
+width:auto;
+margin:20px 0 5px;
+padding:5px 20px;
+font-size:1.4em;
+clear:both;
+background:#e3e3e3
+}
+
+label {
+min-height:25px
+}
+
+textarea {
+width:360px;
+height:100px;
+background:#e3e3e3
+}
+
+textarea:focus {
+border-color:#00488b
+}
+
+input:focus,select:focus {
+border-color:#00488b
+}
+
+input:disabled,select:disabled {
+background:#FCFCFC
+}
+
+select {
+background:#e3e3e3
+}
+
+input.extend {
+transition:width 200ms linear
+}
+
+option {
+padding:0 .5em
+}
+
+table {
+border-collapse:collapse
+}
+
+tr,td,th {
+padding:.5em;
+border:1px solid #e3e3e3
+}
+
+th {
+background:#FCFCFC
+}
+
+form td,form th {
+font-weight:400;
+text-align:center
+}
+
+.category .title.error::before {
+display:inline-block;
+padding-right:7px;
+width:16px;
+content:url(../Swage/icons/error.svg)
+}
+
+.form-group {
+padding:5px;
+border:1px solid transparent
+}
+
+.form-group:hover {
+background:#FCFCFC;
+border:1px solid #FCFCFC
+}
+
+.form-group.form-actions {
+margin:15px 0 25px;
+padding:5px 0;
+background:#e3e3e3;
+border-top:3px solid #e3e3e3
+}
+
+.form-group.form-actions .btn {
+margin:0 10px
+}
+
+.form-group .group-name {
+padding:10px 0;
+text-align:right
+}
+
+.form-group .group-controls {
+min-height:25px;
+padding:5px 0
+}
+
+.form-group .group-controls .control {
+line-height:2em
+}
+
+.form-group table {
+margin:10px 0 0 220px
+}
+
+.stick {
+vertical-align:middle;
+font-size:0
+}
+
+.btn {
+display:inline-block;
+min-height:35px;
+min-width:15px;
+margin:0;
+padding:5px 10px;
+font-size:.9rem;
+vertical-align:middle;
+cursor:pointer;
+overflow:hidden;
+background:#0062be;
+border:none;
+color:#FCFCFC
+}
+
+.btn.active,.btn :active,.btn :hover {
+background:#00488b;
+text-decoration:none
+}
+
+.btn-important,.btn-attention {
+font-weight:400;
+background:#FA8052;
+color:#FCFCFC
+}
+
+.btn-important:hover,.btn-important :active,.btn-attention:hover,.btn-attention :active {
+background:#f95c20!important
+}
+
+.nav-list .nav-header {
+padding:0 10px;
+font-weight:700;
+background:#22303d;
+color:#FCFCFC;
+cursor:default
+}
+
+.nav-list .item:hover,.nav-list .item .active {
+background:#00488b;
+color:#FCFCFC
+}
+
+.nav-list .item:hover a,.nav-list .item .active a {
+color:#FCFCFC
+}
+
+.nav-list .item:hover.empty a,.nav-list .item:hover .error a,.nav-list .item .active.empty a,.nav-list .item .active .error a {
+color:#FCFCFC
+}
+
+.nav-list .item:hover.empty a,.nav-list .item .active.empty a {
+background:#FA8052
+}
+
+.nav-list .item:hover.error a,.nav-list .item .active.error a {
+background:#c46178
+}
+
+.nav-list .item > a {
+padding:0 10px
+}
+
+.nav-list .item.empty a {
+color:#FA8052
+}
+
+.nav-list .item.error a {
+color:#c46178
+}
+
+.nav-list .disable {
+text-align:center;
+background:#FCFCFC;
+color:#969696
+}
+
+.nav-list .nav-form {
+padding:3px;
+text-align:center
+}
+
+.nav-list a:hover {
+text-decoration:none
+}
+
+.nav-head {
+margin:0;
+text-align:right;
+background:#22303d;
+color:#FCFCFC
+}
+
+.nav-head a {
+color:#FCFCFC
+}
+
+.nav-head .item {
+padding:5px 10px;
+font-size:.9rem;
+line-height:1.5rem
+}
+
+.horizontal-list {
+margin:0;
+padding:0
+}
+
+.horizontal-list .item {
+vertical-align:middle
+}
+
+.dropdown-menu {
+padding:5px 0;
+font-size:.8rem;
+text-align:left;
+border:none;
+background-color:#00488b
+}
+
+.dropdown-menu .dropdown-header {
+cursor:default
+}
+
+.dropdown-menu > .item {
+padding:0;
+margin-left:10px
+}
+
+.dropdown-menu > .item > a {
+min-width:initial;
+white-space:nowrap
+}
+
+.dropdown-menu > .item:hover {
+background:#0062be;
+color:#FCFCFC
+}
+
+.dropdown-menu > .item:hover > a {
+text-decoration:none;
+color:#FCFCFC
+}
+
+.dropdown-menu > .item[aria-checked="true"] > a::before {
+font-weight:700;
+margin:0 0 0 -14px
+}
+
+.dropdown-menu .input select,.dropdown-menu .input input {
+margin:0 auto 5px;
+padding:2px 5px
+}
+
+.dropdown-header {
+padding:0 5px 5px;
+font-weight:700;
+text-align:left;
+color:#FCFCFC
+}
+
+.separator {
+margin:5px 0;
+border-bottom:1px solid #e3e3e3;
+cursor:default
+}
+
+.alert {
+margin:5px auto;
+padding:10px 15px;
+font-size:.9em;
+background:#FCFCFC;
+border:none;
+color:#969696;
+text-shadow:0 0 1px #FCFCFC
+}
+
+.alert > a {
+text-decoration:underline;
+color:inherit
+}
+
+.alert-head {
+font-size:1.15em
+}
+
+.alert-warn,.alert-success,.alert-error {
+border:none
+}
+
+.alert-warn {
+background:#FCFCFC;
+color:#FA8052
+}
+
+.alert-success {
+background:#FCFCFC;
+color:#5EAABF
+}
+
+.alert-error {
+background:#FCFCFC;
+color:#B0425B
+}
+
+.pagination {
+text-align:center;
+font-size:.8em;
+background:#e3e3e3;
+color:#181621
+}
+
+.pagination .item.pager-current {
+font-weight:700;
+font-size:1.5em;
+background:#22303d;
+color:#e3e3e3
+}
+
+.pagination .item a {
+display:block;
+font-style:italic;
+line-height:3em;
+text-decoration:none;
+color:#181621
+}
+
+.pagination .item a:hover {
+background:#22303d;
+color:#e3e3e3
+}
+
+.pagination .loading,.pagination a:hover.loading {
+font-size:0;
+background:url(loader.gif) center center no-repeat #22303d
+}
+
+.content {
+padding:20px 10px
+}
+
+.content .pagination {
+margin:0;
+padding:0
+}
+
+.content hr {
+margin:30px 10px;
+height:1px;
+background:#e3e3e3;
+border:0;
+box-shadow:0 2px 5px #e3e3e3
+}
+
+.content pre {
+margin:10px auto;
+padding:10px 20px;
+overflow:auto;
+background:#181621;
+color:#FCFCFC;
+font-size:.9rem
+}
+
+.content pre code {
+background:transparent;
+color:#FCFCFC;
+border:none
+}
+
+.content code {
+padding:2px 5px;
+color:#B0425B;
+background:#FCFCFC;
+border:1px solid #FCFCFC
+}
+
+.content blockquote {
+display:block;
+margin:0;
+padding:5px 20px;
+border-top:1px solid #e3e3e3;
+border-bottom:1px solid #e3e3e3;
+background:#FCFCFC;
+color:#969696
+}
+
+.content blockquote p {
+margin:0
+}
+
+.content > h1.title > a {
+color:#181621
+}
+
+.box {
+border:1px solid #e3e3e3
+}
+
+.box .box-title {
+margin:0;
+padding:5px 10px;
+background:#e3e3e3;
+color:#969696;
+border-bottom:1px solid #e3e3e3
+}
+
+.box .box-content {
+max-height:260px
+}
+
+.box .box-content .item {
+padding:0 10px;
+font-size:.9rem;
+line-height:2.5em
+}
+
+.box .box-content .item .configure {
+visibility:hidden
+}
+
+.box .box-content .item .configure .icon {
+vertical-align:middle;
+background-color:#e3e3e3
+}
+
+.box .box-content .item:hover .configure {
+visibility:visible
+}
+
+.box.category .box-title .title {
+font-weight:400;
+text-decoration:none;
+text-align:left
+}
+
+.box.category:not([data-unread="0"]) .box-title {
+background:#0062be
+}
+
+.box.category:not([data-unread="0"]) .box-title:active {
+background:#00488b
+}
+
+.box.category:not([data-unread="0"]) .box-title .title {
+font-weight:700;
+color:#FCFCFC
+}
+
+.box.category .title:not([data-unread="0"])::after {
+position:absolute;
+top:5px;
+right:10px;
+border:0;
+background:none;
+font-weight:700;
+box-shadow:none;
+text-shadow:none
+}
+
+.box.category .item.feed {
+padding:2px 10px;
+font-size:.8rem
+}
+
+.tree {
+margin:10px 0
+}
+
+.tree-folder-title {
+position:relative;
+padding:0 10px;
+background:#22303d;
+line-height:2.3rem;
+font-size:1rem;
+height:35px
+}
+
+.tree-folder-title .title {
+background:inherit;
+color:#FCFCFC
+}
+
+.tree-folder-title .title:hover {
+text-decoration:none
+}
+
+.tree-folder-items {
+background:#22303d
+}
+
+.tree-folder-items > .item {
+padding:0 10px;
+line-height:2.5rem;
+font-size:.8rem
+}
+
+.tree-folder-items > .item.active {
+background:#00488b
+}
+
+.tree-folder-items > .item > a {
+text-decoration:none;
+color:#FCFCFC
+}
+
+.header > .item {
+vertical-align:middle
+}
+
+.header > .item.title {
+width:231px;
+position:absolute
+}
+
+.header > .item.title h1 {
+margin:0;
+display:block
+}
+
+.header > .item.title h1 a {
+text-decoration:none;
+color:#FCFCFC
+}
+
+.header > .item.title .logo {
+display:inline-block;
+height:26px;
+vertical-align:top;
+position:relative;
+top:5px
+}
+
+.header > .item.search input {
+width:230px
+}
+
+.header .item.search input:focus {
+width:350px
+}
+
+.header .item.search {
+display:none
+}
+
+.header .item.configure {
+position:fixed;
+right:0;
+z-index:1000;
+width:35px
+}
+
+.header h1 {
+text-align:center;
+font-size:1.5em
+}
+
+.aside {
+background:#22303d;
+padding:35px 0;
+width:231px
+}
+
+.aside.aside_feed .tree {
+margin:0 0 50px
+}
+
+.aside.aside_feed .nav-form input,.aside.aside_feed .nav-form select {
+width:140px
+}
+
+.aside.aside_feed .nav-form .dropdown .dropdown-menu {
+right:-20px
+}
+
+.aside.aside_feed .nav-form .dropdown .dropdown-menu::after {
+right:33px
+}
+
+.aside_feed .tree-folder-title > .title:not([data-unread="0"])::after {
+position:absolute;
+right:0;
+margin:6px 0;
+padding:0 10px;
+font-size:.9rem;
+line-height:1.5rem;
+background:inherit
+}
+
+.aside_feed .tree-folder-items .dropdown-menu::after {
+left:2px
+}
+
+.post {
+padding:10px 50px;
+font-size:.9em
+}
+
+.post input {
+background:#e3e3e3
+}
+
+.post form {
+margin:10px 0
+}
+
+.post.content {
+max-width:550px
+}
+
+.prompt {
+text-align:center
+}
+
+.prompt label {
+text-align:left
+}
+
+.prompt form {
+margin:10px auto 20px;
+width:200px
+}
+
+.prompt input {
+margin:5px auto;
+width:100%
+}
+
+.prompt p {
+margin:20px 0
+}
+
+#new-article {
+text-align:center;
+font-size:1em;
+background:#0062be;
+position:fixed;
+bottom:48px;
+z-index:900;
+left:0;
+width:231px;
+line-height:1.5em
+}
+
+#new-article:hover {
+background:#00488b
+}
+
+#new-article > a {
+line-height:1.5em;
+font-weight:700;
+color:#FCFCFC
+}
+
+#new-article > a:hover {
+text-decoration:none
+}
+
+.day {
+padding:0 10px;
+font-weight:700;
+line-height:3em;
+text-align:center
+}
+
+.day .name {
+display:none
+}
+
+.nav a {
+color:#FCFCFC
+}
+
+.nav_menu {
+font-size:0;
+background-color:#0062be;
+position:fixed;
+width:100%;
+z-index:900
+}
+
+.nav_menu .item.search {
+display:inline-block;
+position:fixed;
+right:40px
+}
+
+.flux {
+padding-right:10px;
+background:#FCFCFC
+}
+
+.flux::after {
+margin:0 auto;
+width:90%;
+border-top:1px solid #e3e3e3
+}
+
+.flux:hover,.flux .current {
+background:#FFF
+}
+
+.flux:hover:not(.current):hover .item.title,.flux .current:not(.current):hover .item.title {
+background:#FFF
+}
+
+.flux.not_read {
+background:#FFF3ED
+}
+
+.flux.not_read:not(.current):hover .item.title {
+background:#FFF3ED
+}
+
+.flux.favorite {
+background:#FFF6DA
+}
+
+.flux.favorite:not(.current):hover .item.title {
+background:#FFF6DA
+}
+
+.flux .date {
+font-size:.7rem;
+color:#969696
+}
+
+.flux .bottom {
+font-size:.8rem;
+text-align:center
+}
+
+.flux .website .favicon {
+padding:5px
+}
+
+.flux label {
+color:#FCFCFC;
+cursor:pointer
+}
+
+.flux_header {
+font-size:.8rem;
+cursor:pointer
+}
+
+.flux_header .title {
+font-size:.9rem
+}
+
+.notification {
+text-align:center;
+font-weight:700;
+font-size:1em;
+padding:10px 0;
+z-index:10;
+vertical-align:middle;
+background:#e3e3e3;
+color:#969696;
+border:none;
+position:fixed;
+bottom:48px;
+left:0;
+top:auto;
+width:231px;
+height:auto
+}
+
+.notification.good,.notification .bad {
+color:#FCFCFC
+}
+
+.notification.good {
+background:#5EAABF
+}
+
+.notification.good a.close:hover {
+background:#5EAABF
+}
+
+.notification.bad {
+background:#c46178
+}
+
+.notification.bad a.close:hover {
+background:#c46178
+}
+
+.notification#actualizeProgress {
+line-height:2em
+}
+
+.notification a.close {
+display:none
+}
+
+#bigMarkAsRead {
+text-align:center;
+text-decoration:none;
+background:#e3e3e3;
+padding:20px!important
+}
+
+#bigMarkAsRead:hover {
+background:#22303d;
+color:#FCFCFC
+}
+
+#nav_entries {
+margin:0;
+text-align:center;
+line-height:3em;
+table-layout:fixed;
+width:231px;
+background:#22303d
+}
+
+.stat {
+margin:10px 0 20px
+}
+
+.stat th,.stat td,.stat tr {
+border:none
+}
+
+.stat > table td,.stat > table th {
+border-bottom:1px solid #e3e3e3
+}
+
+.stat > .horizontal-list {
+margin:0 0 5px
+}
+
+.stat > .horizontal-list .item {
+overflow:hidden;
+white-space:nowrap;
+text-overflow:ellipsis
+}
+
+.stat > .horizontal-list .item:first-child {
+width:270px
+}
+
+.loglist {
+overflow:hidden;
+border:1px solid #969696
+}
+
+.log {
+padding:5px 2%;
+overflow:auto;
+font-size:.8rem;
+background:#FCFCFC
+}
+
+.log > .date {
+margin:0 10px 0 0;
+padding:5px 10px
+}
+
+.log.error > .date {
+background:#c46178;
+color:#FCFCFC
+}
+
+.log.warning > .date {
+background:#FA8052;
+color:#FCFCFC
+}
+
+.log.notice > .date {
+background:#e3e3e3;
+color:#FCFCFC
+}
+
+.log.debug > .date {
+background:#181621;
+color:#FCFCFC
+}
+
+@media (max-width: 840px) {
+.dropdown-header,.dropdown-menu > .item {
+padding:12px
+}
+
+#new-article {
+width:100%;
+bottom:initial
+}
+
+.header {
+display:table
+}
+
+.header .item.title .logo {
+display:none
+}
+
+.header > .item.title h1 a {
+display:block;
+position:absolute;
+top:-35px;
+left:10px;
+font-size:.6em
+}
+
+.header .item.configure,button.read_all.btn {
+display:none
+}
+
+.flux .item.manage,.flux_header .item.website {
+width:35px;
+text-align:center
+}
+
+.aside {
+width:0;
+transition:width 200ms linear
+}
+
+.aside .toggle_aside {
+display:block;
+height:50px;
+line-height:50px;
+text-align:right;
+padding-right:10px;
+background:#22303d
+}
+
+.aside.aside_feed {
+padding:0
+}
+
+.aside:target {
+width:78%
+}
+
+.nav_menu {
+position:initial;
+height:71px
+}
+
+.nav_menu .btn {
+margin:5px 10px
+}
+
+.nav_menu .stick {
+margin:0 10px
+}
+
+.nav_menu .stick .btn {
+margin:5px 0
+}
+
+.nav_menu .search {
+position:absolute!important;
+top:35px;
+left:55px
+}
+
+.nav_menu .search input {
+width:85%
+}
+
+.pagination {
+margin:0 0 3.5em
+}
+
+#panel .close {
+display:block;
+height:50px;
+line-height:50px;
+text-align:right;
+padding-right:10px;
+background:#22303d
+}
+
+.day .name {
+font-size:1.1rem
+}
+
+.notification {
+width:100%
+}
+
+.notification a.close {
+display:block;
+left:0;
+background:transparent
+}
+
+.notification a.close:hover {
+opacity:.5
+}
+
+.notification a.close .icon {
+display:none
+}
+
+#nav_entries {
+width:100%!important
+}
+
+div#stream {
+margin-top:0
+}
+
+a.btn.toggle_aside {
+position:absolute;
+top:29px
+}
+
+form#mark-read-menu,a#actualize,a#toggle-order,div#nav_menu_actions,div#nav_menu_views {
+position:absolute
+}
+
+form#mark-read-menu {
+right:46px;
+top:30px;
+z-index:1100
+}
+
+a#actualize,a#toggle-order {
+right:0
+}
+
+a#actualize {
+top:29px
+}
+
+a#toggle-order,div#nav_menu_actions,div#nav_menu_views {
+top:65px
+}
+
+div#nav_menu_actions {
+left:0
+}
+
+div#nav_menu_views {
+right:50px
+}
+}
+
+@media (max-width: 410px) {
+.nav_menu .stick {
+margin:0
+}
+}
+
+@media (max-width: 374px) {
+#nav_menu_views {
+display:none
+}
+}
+
+button.as-link {
+color:#FCFCFC;
+outline:none
+}
+
+.dropdown-target:target ~ .btn.dropdown-toggle {
+background:#00488b
+}
+
+.tree-folder.active .tree-folder-title {
+background:#00488b;
+font-weight:700
+}
+
+.feed.item.empty {
+color:#FA8052
+}
+
+.feed.item.empty.active {
+background:#FA8052;
+color:#FCFCFC
+}
+
+.feed.item.empty.active > a {
+color:#FCFCFC
+}
+
+.feed.item.empty > a {
+color:#FA8052
+}
+
+.feed.item.error {
+color:#c46178
+}
+
+.feed.item.error.active {
+background:#c46178;
+color:#FCFCFC
+}
+
+.feed.item.error.active > a {
+color:#FCFCFC
+}
+
+.feed.item.error > a {
+color:#c46178
+}
+
+#dropdown-query ~ .dropdown-menu .dropdown-header .icon {
+vertical-align:middle;
+float:right
+}
+
+#stream.reader .flux {
+padding:0 0 50px;
+background:#FCFCFC;
+color:#22303d;
+border:none
+}
+
+#stream.reader .flux .author {
+margin:0 0 10px;
+font-size:90%;
+color:#969696
+}
+
+#nav_menu_actions ul.dropdown-menu,#nav_menu_read_all ul.dropdown-menu {
+left:0
+}
+
+#slider label {
+min-height:initial
+}
+
+#slider .form-group:hover {
+background:inital
+} \ No newline at end of file
diff --git a/p/themes/Swage/swage.scss b/p/themes/Swage/swage.scss
new file mode 100644
index 000000000..9bd0326d9
--- /dev/null
+++ b/p/themes/Swage/swage.scss
@@ -0,0 +1,1160 @@
+@charset "UTF-8";
+//colors
+
+$color_text: #181621;
+$color_light: #FCFCFC;
+$color_nav: #0062be;
+$color_aside: #22303d;
+$color_alert: #FA8052;
+$color_good: #5EAABF;
+$color_bad: #B0425B;
+$color_stared: #FFF6DA;
+$color_unread: #FFF3ED;
+$color_hover: #FFFFFF;
+
+// @extend-elements
+%input {
+ min-height: 25px;
+ margin-top: 4px;
+ line-height: 25px;
+ vertical-align: middle;
+ background: $color_light;
+ border: none;
+ padding-left: 5px;
+}
+
+%invalid {
+ color: $color_bad;
+ border-color: $color_bad;
+ box-shadow: none;
+}
+
+%nav-list {
+ height: 2.5em;
+ line-height: 2.5em;
+ font-size: 0.9rem;
+}
+
+%dropdown {
+ padding: 0 22px;
+ line-height: 2.5em;
+ font-size: 0.8rem;
+ color: $color_light;
+}
+
+%after {
+ content: "";
+ display: block;
+ clear: both;
+}
+
+// /@extend-elements
+html,
+body {
+ height: 100%;
+ font-family: Helvetica, Arial, sans-serif;
+}
+
+a {
+ color: darken( $color_nav, 10%);
+ outline: none;
+ &.btn {
+ min-height: 25px;
+ line-height: 25px;
+ text-decoration: none;
+ &:hover {
+ background: darken( $color_nav, 10%);
+ }
+ }
+}
+
+img {
+ &.icon:hover {
+ background: none;
+ }
+}
+
+div#stream {
+ margin-top: 35px;
+}
+
+sup {
+ top: -0.3em;
+}
+
+legend {
+ display: inline-block;
+ width: auto;
+ margin: 20px 0 5px;
+ padding: 5px 20px;
+ font-size: 1.4em;
+ clear: both;
+ background: darken( $color_light, 10%);
+}
+
+label {
+ min-height: 25px;
+}
+
+textarea {
+ width: 360px;
+ height: 100px;
+ @extend %input;
+ background: darken( $color_light, 10% );
+ &:focus {
+ border-color: darken( $color_nav, 10%);
+ }
+}
+
+input,
+select {
+ @extend %input;
+ &:focus {
+ border-color: darken( $color_nav, 10%);
+ }
+ &:invalid {
+ @extend %invalid;
+ }
+ &:disabled {
+ background: $color_light;
+ }
+}
+
+select {
+ background: darken( $color_light, 10% );
+}
+
+input {
+ &.extend {
+ transition: width 200ms linear;
+ }
+}
+
+option {
+ padding: 0 .5em;
+}
+
+table {
+ border-collapse: collapse;
+}
+
+tr,
+td,
+th {
+ padding: 0.5em;
+ border: 1px solid darken( $color_light, 10%);
+}
+
+th {
+ background: $color_light;
+}
+
+form {
+ td,
+ th {
+ font-weight: normal;
+ text-align: center;
+ }
+}
+.category {
+ .title.error::before {
+ display: inline-block;
+ padding-right: 7px;
+ width: 16px;
+ content: url(../Swage/icons/error.svg);
+ }
+}
+
+
+.form-group {
+ padding: 5px;
+ border: 1px solid transparent;
+ &:hover {
+ background: $color_light;
+ border: 1px solid $color_light;
+ }
+ &.form-actions {
+ margin: 15px 0 25px;
+ padding: 5px 0;
+ background: darken( $color_light, 10%);
+ border-top: 3px solid darken( $color_light, 10%);
+ .btn {
+ margin: 0 10px;
+ }
+ }
+ .group-name {
+ padding: 10px 0;
+ text-align: right;
+ }
+ .group-controls {
+ min-height: 25px;
+ padding: 5px 0;
+ .control {
+ line-height: 2.0em;
+ }
+ }
+ table {
+ margin: 10px 0 0 220px;
+ }
+}
+
+.form-group::after {
+ @extend %after;
+}
+
+.stick {
+ vertical-align: middle;
+ font-size: 0;
+}
+
+.btn {
+ display: inline-block;
+ min-height: 35px;
+ min-width: 15px;
+ margin: 0;
+ padding: 5px 10px;
+ font-size: 0.9rem;
+ vertical-align: middle;
+ cursor: pointer;
+ overflow: hidden;
+ background: $color_nav;
+ border: none;
+ color: $color_light;
+ &.active,
+ :active,
+ :hover {
+ background: darken( $color_nav, 10%);
+ text-decoration: none;
+ }
+}
+
+.btn-important, .btn-attention {
+ font-weight: normal;
+ background: $color_alert;
+ color: $color_light;
+ &:hover,
+ :active {
+ background: darken( $color_alert, 10%) !important;
+ }
+}
+
+.nav-list {
+ .nav-header {
+ @extend %nav-list;
+ padding: 0 10px;
+ font-weight: bold;
+ background: $color_aside;
+ color: $color_light;
+ cursor: default;
+ }
+ .item {
+ @extend %nav-list;
+ &:hover,
+ .active {
+ background: darken( $color_nav, 10%);
+ color: $color_light;
+ a {
+ color: $color_light;
+ }
+ &.empty a,
+ .error a {
+ color: $color_light;
+ }
+ &.empty a {
+ background: $color_alert;
+ }
+ &.error a {
+ background: lighten( $color_bad, 10%);
+ }
+ }
+ > a {
+ padding: 0 10px;
+ }
+ &.empty a {
+ color: $color_alert;
+ }
+ &.error a {
+ color: lighten( $color_bad, 10%);
+ }
+ }
+ .disable {
+ text-align: center;
+ background: $color_light;
+ color: darken( $color_light, 40% );
+ }
+ .nav-form {
+ padding: 3px;
+ text-align: center;
+ }
+ a:hover {
+ text-decoration: none;
+ }
+}
+
+.nav-head {
+ margin: 0;
+ text-align: right;
+ background: $color_aside;
+ color: $color_light;
+ a {
+ color: $color_light;
+ }
+ .item {
+ padding: 5px 10px;
+ font-size: 0.9rem;
+ line-height: 1.5rem;
+ }
+}
+
+.horizontal-list {
+ margin: 0;
+ padding: 0;
+ .item {
+ vertical-align: middle;
+ }
+}
+
+.dropdown-menu {
+ padding: 5px 0;
+ font-size: 0.8rem;
+ text-align: left;
+ border: none;
+ background-color: darken( $color_nav, 10%);
+ .dropdown-header {
+ cursor: default;
+ }
+ > {
+ .item {
+ @extend %dropdown;
+ padding: 0;
+ margin-left: 10px;
+ > a,
+ > span,
+ > as-link,
+ button {
+ @extend %dropdown;
+ }
+ > a {
+ min-width: initial;
+ white-space: nowrap;
+ }
+ &:hover {
+ background: $color_nav;
+ color: $color_light;
+ > a {
+ text-decoration: none;
+ color: $color_light;
+ }
+ }
+ }
+ .item[aria-checked="true"] > a::before {
+ font-weight: bold;
+ margin: 0 0 0 -14px;
+ }
+ }
+ .input {
+ select,
+ input {
+ margin: 0 auto 5px;
+ padding: 2px 5px;
+ }
+ }
+}
+
+.dropdown-header {
+ padding: 0 5px 5px;
+ font-weight: bold;
+ text-align: left;
+ color: $color_light;
+}
+
+.separator {
+ margin: 5px 0;
+ border-bottom: 1px solid darken( $color_light, 10%);
+ cursor: default;
+}
+
+.alert {
+ margin: 5px auto;
+ padding: 10px 15px;
+ font-size: 0.9em;
+ background: $color_light;
+ border: none;
+ color: darken( $color_light, 40% );
+ text-shadow: 0 0 1px $color_light;
+ > a {
+ text-decoration: underline;
+ color: inherit;
+ }
+}
+
+.alert-head {
+ font-size: 1.15em;
+}
+
+.alert-warn,
+.alert-success,
+.alert-error {
+ border: none;
+}
+
+.alert-warn {
+ background: $color_light;
+ color: $color_alert;
+}
+
+.alert-success {
+ background: $color_light;
+ color: $color_good;
+}
+
+.alert-error {
+ background: $color_light;
+ color: $color_bad;
+}
+
+.pagination {
+ text-align: center;
+ font-size: 0.8em;
+ background: darken( $color_light, 10%);
+ color: $color_text;
+ .item {
+ &.pager-current {
+ font-weight: bold;
+ font-size: 1.5em;
+ background: $color_aside;
+ color: darken( $color_light, 10%);
+ }
+ a {
+ display: block;
+ font-style: italic;
+ line-height: 3em;
+ text-decoration: none;
+ color: $color_text;
+ &:hover {
+ background: $color_aside;
+ color: darken( $color_light, 10%);
+ }
+ }
+ }
+ .loading,
+ a:hover.loading {
+ font-size: 0;
+ background: url(loader.gif) center center no-repeat $color_aside;
+ }
+}
+
+.content {
+ padding: 20px 10px;
+ .pagination {
+ margin: 0;
+ padding: 0;
+ }
+ hr {
+ margin: 30px 10px;
+ height: 1px;
+ background: darken( $color_light, 10%);
+ border: 0;
+ box-shadow: 0 2px 5px darken( $color_light, 10%);
+ }
+ pre {
+ margin: 10px auto;
+ padding: 10px 20px;
+ overflow: auto;
+ background: $color_text;
+ color: $color_light;
+ font-size: 0.9rem;
+ code {
+ background: transparent;
+ color: $color_light;
+ border: none;
+ }
+ }
+ code {
+ padding: 2px 5px;
+ color: $color_bad;
+ background: $color_light;
+ border: 1px solid $color_light;
+ }
+ blockquote {
+ display: block;
+ margin: 0;
+ padding: 5px 20px;
+ border-top: 1px solid darken( $color_light, 10%);
+ border-bottom: 1px solid darken( $color_light, 10%);
+ background: $color_light;
+ color: darken( $color_light, 40% );
+ p {
+ margin: 0;
+ }
+ }
+ > h1.title > a {
+ color: $color_text;
+ }
+}
+
+.box {
+ border: 1px solid darken( $color_light, 10%);
+ .box-title {
+ margin: 0;
+ padding: 5px 10px;
+ background: darken( $color_light, 10%);
+ color: darken( $color_light, 40% );
+ border-bottom: 1px solid darken( $color_light, 10%);
+ }
+ .box-content {
+ max-height: 260px;
+ .item {
+ padding: 0 10px;
+ font-size: 0.9rem;
+ line-height: 2.5em;
+ .configure {
+ visibility: hidden;
+ .icon {
+ vertical-align: middle;
+ background-color: darken( $color_light, 10%);
+ }
+ }
+ &:hover .configure {
+ visibility: visible;
+ }
+ }
+ }
+ &.category {
+ .box-title .title {
+ font-weight: normal;
+ text-decoration: none;
+ text-align: left;
+ }
+ &:not([data-unread="0"]) .box-title {
+ background: $color_nav;
+ &:active {
+ background: darken( $color_nav, 10%);
+ }
+ .title {
+ font-weight: bold;
+ color: $color_light;
+ }
+ }
+ .title:not([data-unread="0"])::after {
+ position: absolute;
+ top: 5px;
+ right: 10px;
+ border: 0;
+ background: none;
+ font-weight: bold;
+ box-shadow: none;
+ text-shadow: none;
+ }
+ .item.feed {
+ padding: 2px 10px;
+ font-size: 0.8rem;
+ }
+ }
+}
+
+.tree {
+ margin: 10px 0;
+}
+
+.tree-folder-title {
+ position: relative;
+ padding: 0 10px;
+ background: $color_aside;
+ line-height: 2.3rem;
+ font-size: 1rem;
+ height: 35px;
+ .title {
+ background: inherit;
+ color: $color_light;
+ &:hover {
+ text-decoration: none;
+ }
+ }
+}
+
+.tree-folder-items {
+ background: $color_aside;
+ > .item {
+ padding: 0 10px;
+ line-height: 2.5rem;
+ font-size: 0.8rem;
+ &.active {
+ background: darken( $color_nav, 10%);
+ }
+ > a {
+ text-decoration: none;
+ color: $color_light;
+ }
+ }
+}
+
+.header {
+ > .item {
+ vertical-align: middle;
+ &.title {
+ width: 231px;
+ position: absolute;
+ h1 {
+ margin: 0;
+ display: block;
+ a {
+ text-decoration: none;
+ color: $color_light;
+ }
+ }
+ .logo {
+ display: inline-block;
+ height: 26px;
+ vertical-align: top;
+ position: relative;
+ top: 5px;
+ }
+ }
+ &.search input {
+ width: 230px;
+ }
+ }
+ .item.search input:focus {
+ width: 350px;
+ }
+ .item.search {
+ display: none;
+ }
+ .item.configure {
+ position: fixed;
+ right: 0px;
+ z-index: 1000;
+ width: 35px;
+ }
+ h1 {
+ text-align: center;
+ font-size: 1.5em;
+ }
+}
+
+.aside {
+ background: $color_aside;
+ padding: 35px 0;
+ width: 231px;
+ &.aside_feed {
+ .tree {
+ margin: 0 0 50px;
+ }
+ .nav-form {
+ input,
+ select {
+ width: 140px;
+ }
+ .dropdown {
+ .dropdown-menu {
+ right: -20px;
+ }
+ .dropdown-menu::after {
+ right: 33px;
+ }
+ }
+ }
+ }
+}
+
+.aside_feed {
+ .tree-folder-title > .title:not([data-unread="0"])::after {
+ position: absolute;
+ right: 0;
+ margin: 6px 0;
+ padding: 0 10px;
+ font-size: 0.9rem;
+ line-height: 1.5rem;
+ background: inherit;
+ }
+ .tree-folder-items .dropdown-menu::after {
+ left: 2px;
+ }
+}
+
+.post {
+ padding: 10px 50px;
+ font-size: 0.9em;
+ input {
+ background: darken( $color_light, 10% );
+ }
+ form {
+ margin: 10px 0;
+ }
+ &.content {
+ max-width: 550px;
+ }
+}
+
+.prompt {
+ text-align: center;
+ label {
+ text-align: left;
+ }
+ form {
+ margin: 10px auto 20px auto;
+ width: 200px;
+ }
+ input {
+ margin: 5px auto;
+ width: 100%;
+ }
+ p {
+ margin: 20px 0;
+ }
+}
+
+#new-article {
+ text-align: center;
+ font-size: 1em;
+ background: $color_nav;
+ position: fixed;
+ bottom: 48px;
+ z-index: 900;
+ left: 0;
+ width: 231px;
+ line-height: 1.5em;
+ &:hover {
+ background: darken( $color_nav, 10%);
+ }
+ > a {
+ line-height: 1.5em;
+ font-weight: bold;
+ color: $color_light;
+ &:hover {
+ text-decoration: none;
+ }
+ }
+}
+
+.day {
+ padding: 0 10px;
+ font-weight: bold;
+ line-height: 3em;
+ text-align: center;
+ .name {
+ display: none;
+ }
+}
+
+.nav {
+ a {
+ color: $color_light;
+ }
+}
+
+
+.nav_menu {
+ font-size: 0;
+ background-color: $color_nav;
+ position: fixed;
+ width: 100%;
+ z-index: 900;
+ .item.search {
+ display: inline-block;
+ position: fixed;
+ right: 40px;
+ }
+}
+
+.flux {
+ padding-right: 10px;
+ background: $color_light;
+ &::after {
+ @extend %after;
+ margin: 0 auto;
+ width: 90%;
+ border-top: 1px solid darken( $color_light, 10%);
+ }
+ &:hover,
+ .current {
+ background: $color_hover;
+ &:not(.current):hover .item.title {
+ background: $color_hover;
+ }
+ }
+ &.not_read {
+ background: $color_unread;
+ &:not(.current):hover .item.title {
+ background: $color_unread;
+ }
+ }
+ &.favorite,{
+ background: $color_stared;
+ &:not(.current):hover .item.title {
+ background: $color_stared;
+ }
+ }
+ .date {
+ font-size: 0.7rem;
+ color: darken( $color_light, 40% );
+ }
+ .bottom {
+ font-size: 0.8rem;
+ text-align: center;
+ }
+ .website .favicon {
+ padding: 5px;
+ }
+ label {
+ color: $color_light;
+ cursor: pointer;
+ }
+}
+
+.flux_header {
+ font-size: 0.8rem;
+ cursor: pointer;
+ .title {
+ font-size: 0.9rem;
+ }
+}
+
+.notification {
+ text-align: center;
+ font-weight: bold;
+ font-size: 1em;
+ padding: 10px 0;
+ z-index: 10;
+ vertical-align: middle;
+ background: darken( $color_light, 10%);
+ color: darken( $color_light, 40% );
+ border: none;
+ position: fixed;
+ bottom: 48px;
+ left: 0;
+ top: auto;
+ width: 231px;
+ height: auto;
+ &.good,
+ .bad {
+ color: $color_light;
+ }
+ &.good {
+ background: $color_good;
+ a.close:hover {
+ background: $color_good;
+ }
+ }
+ &.bad {
+ background: lighten( $color_bad, 10%);
+ a.close:hover {
+ background: lighten( $color_bad, 10%);
+ }
+ }
+ &#actualizeProgress {
+ line-height: 2em;
+ }
+ a.close {
+ display: none;
+ }
+}
+
+#bigMarkAsRead {
+ text-align: center;
+ text-decoration: none;
+ background: darken( $color_light, 10%);
+ padding: 20px !IMPORTANT;
+ &:hover {
+ background: $color_aside;
+ color: $color_light;
+ }
+}
+
+#nav_entries {
+ margin: 0;
+ text-align: center;
+ line-height: 3em;
+ table-layout: fixed;
+ width: 231px;
+ background: $color_aside;
+}
+
+.stat {
+ margin: 10px 0 20px;
+ th,
+ td,
+ tr {
+ border: none;
+ }
+ > table {
+ td,
+ th {
+ border-bottom: 1px solid darken( $color_light, 10%);
+ }
+ }
+ > .horizontal-list {
+ margin: 0 0 5px;
+ .item {
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ &:first-child {
+ width: 270px;
+ }
+ }
+ }
+}
+
+.loglist {
+ overflow: hidden;
+ border: 1px solid darken( $color_light, 40% );
+}
+
+.log {
+ padding: 5px 2%;
+ overflow: auto;
+ font-size: 0.8rem;
+ background: $color_light;
+ > .date {
+ margin: 0 10px 0 0;
+ padding: 5px 10px;
+ }
+ &.error > .date {
+ background: lighten( $color_bad, 10%);
+ color: $color_light;
+ }
+ &.warning > .date {
+ background: $color_alert;
+ color: $color_light;
+ }
+ &.notice > .date {
+ background: darken( $color_light, 10%);
+ color: $color_light;
+ }
+ &.debug > .date {
+ background: $color_text;
+ color: $color_light;
+ }
+}
+
+@media(max-width: 840px) {
+ .dropdown-header, .dropdown-menu > .item {
+ padding: 12px;
+ }
+
+ #new-article {
+ width: 100%;
+ bottom: initial;
+ }
+ .header {
+ display: table;
+ .item.title .logo {
+ display: none;
+ }
+ }
+ .header > .item.title h1 a {
+ display: block;
+ position: absolute;
+ top: -35px;
+ left: 10px;
+ font-size: 0.6em;
+ }
+ .header .item.configure,
+ button.read_all.btn {
+ display: none;
+ }
+ .flux .item.manage,
+ .flux_header .item.website {
+ width: 35px;
+ text-align: center;
+ }
+ .aside {
+ width: 0;
+ transition: width 200ms linear;
+ .toggle_aside {
+ display: block;
+ height: 50px;
+ line-height: 50px;
+ text-align: right;
+ padding-right: 10px;
+ background: $color_aside;
+ }
+ &.aside_feed {
+ padding: 0;
+ }
+ &:target {
+ width: 78%;
+ }
+ }
+ .nav_menu {
+ position: initial;
+ height: 71px;
+ .btn {
+ margin: 5px 10px;
+ }
+ .stick {
+ margin: 0 10px;
+ .btn {
+ margin: 5px 0;
+ }
+ }
+ .search {
+ position: absolute !important;
+ top: 35px;
+ left: 55px;
+ input {
+ width: 85%;
+ }
+ }
+ }
+ .pagination {
+ margin: 0 0 3.5em;
+ }
+ #panel .close {
+ display: block;
+ height: 50px;
+ line-height: 50px;
+ text-align: right;
+ padding-right: 10px;
+ background: $color_aside;
+ }
+ .day .name {
+ font-size: 1.1rem;
+ }
+ .notification {
+ width: 100%;
+ a.close {
+ display: block;
+ left: 0;
+ background: transparent;
+ &:hover {
+ opacity: 0.5;
+ }
+ .icon {
+ display: none;
+ }
+ }
+ }
+ #nav_entries {
+ width: 100% !important;
+ }
+ div#stream {
+ margin-top: 0px;
+ }
+ a.btn.toggle_aside {
+ position: absolute;
+ top: 29px;
+ }
+ form#mark-read-menu,
+ a#actualize,
+ a#toggle-order,
+ div#nav_menu_actions,
+ div#nav_menu_views {
+ position: absolute;
+ }
+ form#mark-read-menu {
+ right: 46px;
+ top: 30px;
+ z-index: 1100;
+ }
+ a#actualize,
+ a#toggle-order {
+ right: 0px;
+ }
+ a#actualize {
+ top: 29px;
+ }
+ a#toggle-order,
+ div#nav_menu_actions,
+ div#nav_menu_views {
+ top: 65px;
+ }
+ div#nav_menu_actions {
+ left: 0px;
+ }
+ div#nav_menu_views {
+ right: 50px;
+ }
+}
+
+@media(max-width: 410px) {
+ .nav_menu .stick {
+ margin: 0;
+ }
+}
+
+@media(max-width: 374px) {
+ #nav_menu_views {
+ display: none;
+ }
+}
+
+button.as-link {
+ color: $color_light;
+ outline: none;
+}
+
+.dropdown-target:target ~ .btn.dropdown-toggle {
+ background: darken( $color_nav, 10%);
+}
+
+.tree-folder.active .tree-folder-title {
+ background: darken( $color_nav, 10%);
+ font-weight: bold;
+}
+
+.feed.item {
+ &.empty {
+ color: $color_alert;
+ &.active {
+ background: $color_alert;
+ color: $color_light;
+ > a {
+ color: $color_light;
+ }
+ }
+ > a {
+ color: $color_alert;
+ }
+ }
+ &.error {
+ color: lighten( $color_bad, 10%);
+ &.active {
+ background: lighten( $color_bad, 10%);
+ color: $color_light;
+ > a {
+ color: $color_light;
+ }
+ }
+ > a {
+ color: lighten( $color_bad, 10%);
+ }
+ }
+}
+
+#dropdown-query ~ .dropdown-menu .dropdown-header .icon {
+ vertical-align: middle;
+ float: right;
+}
+
+#stream.reader .flux {
+ padding: 0 0 50px;
+ background: $color_light;
+ color: $color_aside;
+ border: none;
+ .author {
+ margin: 0 0 10px;
+ font-size: 90%;
+ color: darken( $color_light, 40% );
+ }
+}
+
+#nav_menu_actions, #nav_menu_read_all {
+ ul.dropdown-menu {
+ left: 0px;
+ }
+}
+
+#slider {
+ label {
+ min-height: initial;
+ }
+ .form-group {
+ &:hover {
+ background: inital;
+ }
+ }
+
+} \ No newline at end of file
diff --git a/p/themes/Swage/thumbs/original.png b/p/themes/Swage/thumbs/original.png
new file mode 100644
index 000000000..1b4df3963
--- /dev/null
+++ b/p/themes/Swage/thumbs/original.png
Binary files differ
diff --git a/p/themes/base-theme/template.css b/p/themes/base-theme/template.css
index 26143a5d5..b211d0516 100644
--- a/p/themes/base-theme/template.css
+++ b/p/themes/base-theme/template.css
@@ -108,6 +108,14 @@ input[type="checkbox"] {
width: 15px !important;
min-height: 15px !important;
}
+.dropdown-menu label > input[type="text"] {
+ with: 150px;
+ width: calc(99% - 5em);
+}
+.dropdown-menu input[type="checkbox"] {
+ margin-left: 1em;
+ margin-right: .5em;
+}
button.as-link,
button.as-link:hover,
button.as-link:active {
@@ -233,6 +241,7 @@ a.btn {
.dropdown-menu > .item > span {
display: block;
min-width: 200px;
+ white-space: nowrap;
}
.dropdown-menu > .item[aria-checked="true"] > a::before {
content: '✓';