From e2a48d8701f91b8e24fbe9e99e91eb72a87bb749 Mon Sep 17 00:00:00 2001 From: horchi Date: Sun, 5 Mar 2017 16:39:28 +0100 Subject: git init --- .gitignore | 23 + COPYING | 340 + HISTORY.h | 1285 ++ Make.config | 87 + Makefile | 268 + PLUGINS/epgdata/Makefile | 52 + .../epgdata/configs/channelmap.conf-epgdata-astra | 176 + PLUGINS/epgdata/configs/epgd.conf | 10 + PLUGINS/epgdata/configs/epgdata-category.xml | 143 + PLUGINS/epgdata/configs/epgdata-genre.xml | 507 + PLUGINS/epgdata/configs/epgdata-iso-8859-1.xsl | 8 + PLUGINS/epgdata/configs/epgdata-utf-8.xsl | 8 + PLUGINS/epgdata/configs/epgdata.xsl | 208 + PLUGINS/epgdata/epgdata.c | 760 ++ PLUGINS/epgdata/epgdata.h | 52 + PLUGINS/epgdata/scripts/getepgdataids | 37 + PLUGINS/epgdata/scripts/getincludes | 6 + README | 387 + README-import-epgsearch | 62 + TODO | 187 + alter/alter.sql | 9 + channelmap.c | 305 + configs/channelmap.conf | 49 + configs/epg.dat | 981 ++ configs/epgd.conf | 49 + configs/eventsview-3po.sql | 75 + configs/eventsview-ck.sql | 67 + configs/eventsview-horchi.sql | 67 + configs/eventsview-uti.sql | 68 + configs/eventsview.sql | 66 + configs/eventsviewplain-3po.sql | 99 + configs/eventsviewplain.sql | 78 + configs/getcrosslvr.sql | 34 + configs/getlvrmin.sql | 51 + configs/getupdflg.sql | 33 + configs/mergeepg.sql | 401 + configs/recording.py | 155 + configs/reverseepg.sql | 42 + configs/thetvdbview.sql | 33 + contrib/40-epgd.conf | 2 + contrib/README.fedora | 122 + contrib/README.openrc | 9 + contrib/epgd.SuSE | 115 + contrib/epgd.conf | 19 + contrib/epgd.conf.d.openrc | 3 + contrib/epgd.debian | 68 + contrib/epgd.ignore | 48 + contrib/epgd.init.d | 86 + contrib/epgd.init.d.openrc | 30 + contrib/epgd.service | 13 + contrib/epghttpd.conf | 17 + contrib/epghttpd.init.d | 73 + contrib/epghttpd.service | 13 + contrib/gentoo/README.txt | 108 + contrib/gentoo/epgd-ebuild.tgz | Bin 0 -> 2732 bytes epgd.h | 277 + epgdconfig.c | 57 + epgdconfig.h | 63 + epglv/COPYING | 340 + epglv/Makefile | 60 + epglv/README | 57 + epglv/src/epglv.c | 57 + epglv/src/epglv.h | 52 + epglv/src/epglvbase.c | 295 + epgtest.cc | 847 ++ episode.c | 298 + eptest.c | 126 + http/3rdParty/boilerplate5/css/main_post.min.css | 1 + http/3rdParty/boilerplate5/css/main_pre.min.css | 1 + http/3rdParty/boilerplate5/css/normalize.min.css | 1 + http/3rdParty/fontello/LICENSE.txt | 75 + http/3rdParty/fontello/README.txt | 75 + http/3rdParty/fontello/config.json | 350 + http/3rdParty/fontello/css/animation.css | 85 + http/3rdParty/fontello/css/epgd-codes.css | 47 + http/3rdParty/fontello/css/epgd-embedded.css | 100 + http/3rdParty/fontello/css/epgd-ie7-codes.css | 47 + http/3rdParty/fontello/css/epgd-ie7.css | 58 + http/3rdParty/fontello/css/epgd.css | 103 + http/3rdParty/fontello/demo.html | 376 + http/3rdParty/fontello/font/epgd.eot | Bin 0 -> 16972 bytes http/3rdParty/fontello/font/epgd.svg | 102 + http/3rdParty/fontello/font/epgd.ttf | Bin 0 -> 16820 bytes http/3rdParty/fontello/font/epgd.woff | Bin 0 -> 10484 bytes .../dist/jquery-ui-timepicker-addon.min.css | 5 + .../dist/jquery-ui-timepicker-addon.min.js | 5 + http/3rdParty/jquery-2.1.4.min.js | 4 + http/3rdParty/jquery-2.2.3.min.js | 4 + http/3rdParty/jquery-scrollstop-master/LICENSE.md | 24 + http/3rdParty/jquery-scrollstop-master/README.md | 66 + http/3rdParty/jquery-scrollstop-master/index.html | 159 + .../jquery-scrollstop-master/jquery.scrollstop.js | 78 + .../jquery.scrollstop.min.js | 5 + .../scrollstop.jquery.json | 19 + .../external/jquery/jquery.js | 9789 ++++++++++++++ .../images/ui-bg_glass_100_f5f0e5_1x400.png | Bin 0 -> 354 bytes .../images/ui-bg_glass_25_cb842e_1x400.png | Bin 0 -> 335 bytes .../images/ui-bg_glass_70_ede4d4_1x400.png | Bin 0 -> 351 bytes .../ui-bg_highlight-hard_100_f4f0ec_1x100.png | Bin 0 -> 327 bytes .../ui-bg_highlight-hard_65_fee4bd_1x100.png | Bin 0 -> 314 bytes .../ui-bg_highlight-hard_75_f5f5b5_1x100.png | Bin 0 -> 323 bytes .../images/ui-bg_inset-soft_100_f4f0ec_1x100.png | Bin 0 -> 403 bytes .../images/ui-icons_c47a23_256x240.png | Bin 0 -> 4549 bytes .../images/ui-icons_cb672b_256x240.png | Bin 0 -> 4549 bytes .../images/ui-icons_f08000_256x240.png | Bin 0 -> 4549 bytes .../images/ui-icons_f35f07_256x240.png | Bin 0 -> 4549 bytes .../images/ui-icons_ff7519_256x240.png | Bin 0 -> 4549 bytes .../images/ui-icons_ffffff_256x240.png | Bin 0 -> 6299 bytes http/3rdParty/jquery-ui-1.11.4.custom/index.html | 484 + .../3rdParty/jquery-ui-1.11.4.custom/jquery-ui.css | 1093 ++ http/3rdParty/jquery-ui-1.11.4.custom/jquery-ui.js | 12749 +++++++++++++++++++ .../jquery-ui-1.11.4.custom/jquery-ui.min.css | 7 + .../jquery-ui-1.11.4.custom/jquery-ui.min.js | 12 + .../jquery-ui.structure.css | 701 + .../jquery-ui.structure.min.css | 5 + .../jquery-ui-1.11.4.custom/jquery-ui.theme.css | 410 + .../jquery-ui.theme.min.css | 5 + http/3rdParty/jquery.ui.touch-punch.min.js | 11 + http/3rdParty/jqueryUI-download.txt | 12 + http/3rdParty/modernizr.custom.js | 4 + http/3rdParty/yaMD5/README.md | 90 + http/3rdParty/yaMD5/test/lib/ireal-md5.js | 346 + http/3rdParty/yaMD5/test/lib/izumo-md5.js | 206 + http/3rdParty/yaMD5/test/lib/jbt-md5.js | 74 + http/3rdParty/yaMD5/test/lib/jkm-md5.js | 191 + http/3rdParty/yaMD5/test/lib/paj-md5.js | 360 + http/3rdParty/yaMD5/test/lib/satazor-md5.js | 600 + http/3rdParty/yaMD5/test/lib/valums-md5.js | 218 + http/3rdParty/yaMD5/test/test.html | 99 + http/3rdParty/yaMD5/yamd5.js | 402 + http/3rdParty/yaMD5/yamd5.min.js | 46 + http/Makefile | 84 + http/README | 77 + http/custom.sample.css | 1 + http/dev-watch.sh | 22 + http/src/css/epgd.less | 1724 +++ http/src/css/theme/default.less | 7 + http/src/js/1_main.js | 714 ++ http/src/js/5_timerDialog.js | 640 + http/src/js/channels.js | 46 + http/src/js/epgd | 3 + http/src/js/eventDetail.js | 523 + http/src/js/pages.editChannels.js | 313 + http/src/js/pages.editUser.js | 96 + http/src/js/pages.help.js | 49 + http/src/js/pages.login.js | 114 + http/src/js/pages.magazine.js | 413 + http/src/js/pages.now.js | 135 + http/src/js/pages.profile.js | 251 + http/src/js/pages.records.js | 453 + http/src/js/pages.timer.js | 743 ++ http/src/js/vdr.js | 57 + http/src/lang/de.js | 299 + http/src/lang/hilfe.html | 303 + http/tools/less-rhino-1.7.0.js | 9301 ++++++++++++++ http/tools/lessc-rhino-1.7.0.js | 449 + http/tools/yuicompressor-2.4.8.jar | Bin 0 -> 787524 bytes http/www/common.js | 79 + http/www/epgd.css | 1554 +++ http/www/epgd.js | 1 + http/www/favicon.ico | Bin 0 -> 596 bytes http/www/font/LICENSE.txt | 75 + http/www/font/epgd.eot | Bin 0 -> 16972 bytes http/www/font/epgd.svg | 102 + http/www/font/epgd.ttf | Bin 0 -> 16820 bytes http/www/font/epgd.woff | Bin 0 -> 10484 bytes http/www/font/epgd.woff2 | Bin 0 -> 8848 bytes http/www/images/169.png | Bin 0 -> 3590 bytes http/www/images/2kanal.png | Bin 0 -> 2245 bytes http/www/images/43.png | Bin 0 -> 2980 bytes http/www/images/TagesTipp_32.png | Bin 0 -> 3307 bytes http/www/images/Tipp_32.png | Bin 0 -> 1043 bytes http/www/images/TopTipp_32.png | Bin 0 -> 1951 bytes http/www/images/animated-overlay.gif | Bin 0 -> 1738 bytes http/www/images/audio_description.png | Bin 0 -> 3705 bytes http/www/images/dd.png | Bin 0 -> 2477 bytes http/www/images/epg_icons_24x24_orange.png | Bin 0 -> 48518 bytes http/www/images/epgd-4x.png | Bin 0 -> 6243 bytes http/www/images/hd.png | Bin 0 -> 4412 bytes http/www/images/loader.png | Bin 0 -> 7531 bytes http/www/images/stereo.png | Bin 0 -> 3528 bytes http/www/images/sw.png | Bin 0 -> 3572 bytes http/www/images/thumb-rate1.svg | 6 + http/www/images/thumb-rate2.svg | 6 + http/www/images/thumb-rate3.svg | 6 + http/www/images/thumb-rate4.svg | 6 + http/www/images/thumb-rate5.svg | 6 + http/www/images/ui-bg_flat_75_aaaaaa_40x100.png | Bin 0 -> 212 bytes http/www/images/ui-bg_glass_100_f5f0e5_1x400.png | Bin 0 -> 354 bytes http/www/images/ui-bg_glass_25_cb842e_1x400.png | Bin 0 -> 335 bytes http/www/images/ui-bg_glass_70_ede4d4_1x400.png | Bin 0 -> 351 bytes .../ui-bg_highlight-hard_100_f4f0ec_1x100.png | Bin 0 -> 327 bytes .../ui-bg_highlight-hard_65_fee4bd_1x100.png | Bin 0 -> 314 bytes .../ui-bg_highlight-hard_75_f5f5b5_1x100.png | Bin 0 -> 323 bytes .../images/ui-bg_inset-soft_100_f4f0ec_1x100.png | Bin 0 -> 403 bytes http/www/images/ui-icons_c47a23_256x240.png | Bin 0 -> 4549 bytes http/www/images/ui-icons_cb672b_256x240.png | Bin 0 -> 4549 bytes http/www/images/ui-icons_f08000_256x240.png | Bin 0 -> 4549 bytes http/www/images/ui-icons_f35f07_256x240.png | Bin 0 -> 4549 bytes http/www/images/ui-icons_ff7519_256x240.png | Bin 0 -> 4549 bytes http/www/images/ui-icons_ffffff_256x240.png | Bin 0 -> 6299 bytes http/www/images/untertitel.png | Bin 0 -> 2349 bytes http/www/index.html | 28 + http/www/lang/de.js | 299 + http/www/lang/hilfe.html | 303 + httpd.c | 2287 ++++ httpd.h | 383 + json.examples | 66 + levenshtein.c | 107 + levenshtein.h | 20 + lib/Makefile | 119 + lib/common.c | 1921 +++ lib/common.h | 560 + lib/config.c | 59 + lib/config.h | 47 + lib/configuration.c | 238 + lib/configuration.h | 164 + lib/curl.c | 454 + lib/curl.h | 77 + lib/db.c | 1646 +++ lib/db.h | 1367 ++ lib/dbdict.c | 527 + lib/dbdict.h | 471 + lib/demo.c | 531 + lib/demo.dat | 17 + lib/epgservice.c | 121 + lib/epgservice.h | 469 + lib/imgtools.c | 217 + lib/imgtools.h | 31 + lib/json.c | 168 + lib/json.h | 36 + lib/parameters.c | 257 + lib/parameters.h | 59 + lib/python.c | 421 + lib/python.h | 78 + lib/pytst.c | 128 + lib/searchtimer.c | 1777 +++ lib/searchtimer.h | 111 + lib/semtst.c | 42 + lib/test.c | 738 ++ lib/thread.c | 342 + lib/thread.h | 92 + lib/wol.c | 116 + lib/wol.h | 31 + main.c | 219 + moviedbmanager.c | 564 + moviedbmanager.h | 82 + plugin.c | 65 + scraper/themoviedbscraper/moviedbactor.c | 49 + scraper/themoviedbscraper/moviedbactor.h | 44 + scraper/themoviedbscraper/moviedbmovie.c | 255 + scraper/themoviedbscraper/moviedbmovie.h | 68 + scraper/themoviedbscraper/themoviedbscraper.c | 103 + scraper/themoviedbscraper/themoviedbscraper.h | 31 + scraper/thetvdbscraper/thetvdbscraper.c | 188 + scraper/thetvdbscraper/thetvdbscraper.h | 39 + scraper/thetvdbscraper/tvdbactor.c | 66 + scraper/thetvdbscraper/tvdbactor.h | 54 + scraper/thetvdbscraper/tvdbepisode.c | 147 + scraper/thetvdbscraper/tvdbepisode.h | 45 + scraper/thetvdbscraper/tvdbmedia.c | 202 + scraper/thetvdbscraper/tvdbmedia.h | 111 + scraper/thetvdbscraper/tvdbmirrors.c | 88 + scraper/thetvdbscraper/tvdbmirrors.h | 32 + scraper/thetvdbscraper/tvdbseries.c | 281 + scraper/thetvdbscraper/tvdbseries.h | 69 + scripts/epgd-conflictsof | 31 + scripts/epgd-dropall | 156 + scripts/epgd-import-epglv | 10 + scripts/epgd-ls-channelids | 39 + scripts/epgd-sendmail | 6 + scripts/epgd-showdones | 5 + scripts/epgd-showmerge | 32 + scripts/epgd-showtimer | 18 + scripts/epgd-showtimerat | 14 + scripts/epgd-tool | 315 + scripts/epgh-login | 43 + scripts/epgh-request | 28 + scripts/epgsearchdone.pl | 140 + series.c | 370 + series.h | 190 + svdrpclient.c | 685 + svdrpclient.h | 142 + tools/fuzzy.c | 70 + tools/fuzzy.h | 10 + tools/stringhelpers.c | 53 + tools/stringhelpers.h | 31 + tvdbmanager.c | 926 ++ tvdbmanager.h | 108 + update.c | 2972 +++++ webauth.c | 123 + webdo.c | 1964 +++ webstore.c | 786 ++ webtools.c | 135 + 294 files changed, 88014 insertions(+) create mode 100644 .gitignore create mode 100644 COPYING create mode 100644 HISTORY.h create mode 100644 Make.config create mode 100644 Makefile create mode 100644 PLUGINS/epgdata/Makefile create mode 100644 PLUGINS/epgdata/configs/channelmap.conf-epgdata-astra create mode 100644 PLUGINS/epgdata/configs/epgd.conf create mode 100644 PLUGINS/epgdata/configs/epgdata-category.xml create mode 100644 PLUGINS/epgdata/configs/epgdata-genre.xml create mode 100644 PLUGINS/epgdata/configs/epgdata-iso-8859-1.xsl create mode 100644 PLUGINS/epgdata/configs/epgdata-utf-8.xsl create mode 100644 PLUGINS/epgdata/configs/epgdata.xsl create mode 100644 PLUGINS/epgdata/epgdata.c create mode 100644 PLUGINS/epgdata/epgdata.h create mode 100755 PLUGINS/epgdata/scripts/getepgdataids create mode 100755 PLUGINS/epgdata/scripts/getincludes create mode 100644 README create mode 100644 README-import-epgsearch create mode 100644 TODO create mode 100755 alter/alter.sql create mode 100644 channelmap.c create mode 100644 configs/channelmap.conf create mode 100644 configs/epg.dat create mode 100644 configs/epgd.conf create mode 100644 configs/eventsview-3po.sql create mode 100644 configs/eventsview-ck.sql create mode 100644 configs/eventsview-horchi.sql create mode 100644 configs/eventsview-uti.sql create mode 100644 configs/eventsview.sql create mode 100644 configs/eventsviewplain-3po.sql create mode 100644 configs/eventsviewplain.sql create mode 100644 configs/getcrosslvr.sql create mode 100644 configs/getlvrmin.sql create mode 100644 configs/getupdflg.sql create mode 100644 configs/mergeepg.sql create mode 100644 configs/recording.py create mode 100644 configs/reverseepg.sql create mode 100644 configs/thetvdbview.sql create mode 100644 contrib/40-epgd.conf create mode 100644 contrib/README.fedora create mode 100644 contrib/README.openrc create mode 100644 contrib/epgd.SuSE create mode 100644 contrib/epgd.conf create mode 100644 contrib/epgd.conf.d.openrc create mode 100644 contrib/epgd.debian create mode 100644 contrib/epgd.ignore create mode 100755 contrib/epgd.init.d create mode 100755 contrib/epgd.init.d.openrc create mode 100644 contrib/epgd.service create mode 100644 contrib/epghttpd.conf create mode 100755 contrib/epghttpd.init.d create mode 100644 contrib/epghttpd.service create mode 100644 contrib/gentoo/README.txt create mode 100644 contrib/gentoo/epgd-ebuild.tgz create mode 100644 epgd.h create mode 100644 epgdconfig.c create mode 100644 epgdconfig.h create mode 100644 epglv/COPYING create mode 100644 epglv/Makefile create mode 100644 epglv/README create mode 100644 epglv/src/epglv.c create mode 100644 epglv/src/epglv.h create mode 100644 epglv/src/epglvbase.c create mode 100644 epgtest.cc create mode 100644 episode.c create mode 100644 eptest.c create mode 100644 http/3rdParty/boilerplate5/css/main_post.min.css create mode 100644 http/3rdParty/boilerplate5/css/main_pre.min.css create mode 100644 http/3rdParty/boilerplate5/css/normalize.min.css create mode 100644 http/3rdParty/fontello/LICENSE.txt create mode 100644 http/3rdParty/fontello/README.txt create mode 100644 http/3rdParty/fontello/config.json create mode 100644 http/3rdParty/fontello/css/animation.css create mode 100644 http/3rdParty/fontello/css/epgd-codes.css create mode 100644 http/3rdParty/fontello/css/epgd-embedded.css create mode 100644 http/3rdParty/fontello/css/epgd-ie7-codes.css create mode 100644 http/3rdParty/fontello/css/epgd-ie7.css create mode 100644 http/3rdParty/fontello/css/epgd.css create mode 100644 http/3rdParty/fontello/demo.html create mode 100644 http/3rdParty/fontello/font/epgd.eot create mode 100644 http/3rdParty/fontello/font/epgd.svg create mode 100644 http/3rdParty/fontello/font/epgd.ttf create mode 100644 http/3rdParty/fontello/font/epgd.woff create mode 100644 http/3rdParty/jQuery-Timepicker-Addon-master/dist/jquery-ui-timepicker-addon.min.css create mode 100644 http/3rdParty/jQuery-Timepicker-Addon-master/dist/jquery-ui-timepicker-addon.min.js create mode 100644 http/3rdParty/jquery-2.1.4.min.js create mode 100644 http/3rdParty/jquery-2.2.3.min.js create mode 100644 http/3rdParty/jquery-scrollstop-master/LICENSE.md create mode 100644 http/3rdParty/jquery-scrollstop-master/README.md create mode 100644 http/3rdParty/jquery-scrollstop-master/index.html create mode 100644 http/3rdParty/jquery-scrollstop-master/jquery.scrollstop.js create mode 100644 http/3rdParty/jquery-scrollstop-master/jquery.scrollstop.min.js create mode 100644 http/3rdParty/jquery-scrollstop-master/scrollstop.jquery.json create mode 100644 http/3rdParty/jquery-ui-1.11.4.custom/external/jquery/jquery.js create mode 100644 http/3rdParty/jquery-ui-1.11.4.custom/images/ui-bg_glass_100_f5f0e5_1x400.png create mode 100644 http/3rdParty/jquery-ui-1.11.4.custom/images/ui-bg_glass_25_cb842e_1x400.png create mode 100644 http/3rdParty/jquery-ui-1.11.4.custom/images/ui-bg_glass_70_ede4d4_1x400.png create mode 100644 http/3rdParty/jquery-ui-1.11.4.custom/images/ui-bg_highlight-hard_100_f4f0ec_1x100.png create mode 100644 http/3rdParty/jquery-ui-1.11.4.custom/images/ui-bg_highlight-hard_65_fee4bd_1x100.png create mode 100644 http/3rdParty/jquery-ui-1.11.4.custom/images/ui-bg_highlight-hard_75_f5f5b5_1x100.png create mode 100644 http/3rdParty/jquery-ui-1.11.4.custom/images/ui-bg_inset-soft_100_f4f0ec_1x100.png create mode 100644 http/3rdParty/jquery-ui-1.11.4.custom/images/ui-icons_c47a23_256x240.png create mode 100644 http/3rdParty/jquery-ui-1.11.4.custom/images/ui-icons_cb672b_256x240.png create mode 100644 http/3rdParty/jquery-ui-1.11.4.custom/images/ui-icons_f08000_256x240.png create mode 100644 http/3rdParty/jquery-ui-1.11.4.custom/images/ui-icons_f35f07_256x240.png create mode 100644 http/3rdParty/jquery-ui-1.11.4.custom/images/ui-icons_ff7519_256x240.png create mode 100644 http/3rdParty/jquery-ui-1.11.4.custom/images/ui-icons_ffffff_256x240.png create mode 100644 http/3rdParty/jquery-ui-1.11.4.custom/index.html create mode 100644 http/3rdParty/jquery-ui-1.11.4.custom/jquery-ui.css create mode 100644 http/3rdParty/jquery-ui-1.11.4.custom/jquery-ui.js create mode 100644 http/3rdParty/jquery-ui-1.11.4.custom/jquery-ui.min.css create mode 100644 http/3rdParty/jquery-ui-1.11.4.custom/jquery-ui.min.js create mode 100644 http/3rdParty/jquery-ui-1.11.4.custom/jquery-ui.structure.css create mode 100644 http/3rdParty/jquery-ui-1.11.4.custom/jquery-ui.structure.min.css create mode 100644 http/3rdParty/jquery-ui-1.11.4.custom/jquery-ui.theme.css create mode 100644 http/3rdParty/jquery-ui-1.11.4.custom/jquery-ui.theme.min.css create mode 100644 http/3rdParty/jquery.ui.touch-punch.min.js create mode 100644 http/3rdParty/jqueryUI-download.txt create mode 100644 http/3rdParty/modernizr.custom.js create mode 100644 http/3rdParty/yaMD5/README.md create mode 100644 http/3rdParty/yaMD5/test/lib/ireal-md5.js create mode 100644 http/3rdParty/yaMD5/test/lib/izumo-md5.js create mode 100644 http/3rdParty/yaMD5/test/lib/jbt-md5.js create mode 100644 http/3rdParty/yaMD5/test/lib/jkm-md5.js create mode 100644 http/3rdParty/yaMD5/test/lib/paj-md5.js create mode 100644 http/3rdParty/yaMD5/test/lib/satazor-md5.js create mode 100644 http/3rdParty/yaMD5/test/lib/valums-md5.js create mode 100644 http/3rdParty/yaMD5/test/test.html create mode 100644 http/3rdParty/yaMD5/yamd5.js create mode 100644 http/3rdParty/yaMD5/yamd5.min.js create mode 100644 http/Makefile create mode 100644 http/README create mode 100644 http/custom.sample.css create mode 100644 http/dev-watch.sh create mode 100644 http/src/css/epgd.less create mode 100644 http/src/css/theme/default.less create mode 100644 http/src/js/1_main.js create mode 100644 http/src/js/5_timerDialog.js create mode 100644 http/src/js/channels.js create mode 100644 http/src/js/epgd create mode 100644 http/src/js/eventDetail.js create mode 100644 http/src/js/pages.editChannels.js create mode 100644 http/src/js/pages.editUser.js create mode 100644 http/src/js/pages.help.js create mode 100644 http/src/js/pages.login.js create mode 100644 http/src/js/pages.magazine.js create mode 100644 http/src/js/pages.now.js create mode 100644 http/src/js/pages.profile.js create mode 100644 http/src/js/pages.records.js create mode 100644 http/src/js/pages.timer.js create mode 100644 http/src/js/vdr.js create mode 100644 http/src/lang/de.js create mode 100644 http/src/lang/hilfe.html create mode 100644 http/tools/less-rhino-1.7.0.js create mode 100644 http/tools/lessc-rhino-1.7.0.js create mode 100644 http/tools/yuicompressor-2.4.8.jar create mode 100644 http/www/common.js create mode 100644 http/www/epgd.css create mode 100644 http/www/epgd.js create mode 100644 http/www/favicon.ico create mode 100644 http/www/font/LICENSE.txt create mode 100644 http/www/font/epgd.eot create mode 100644 http/www/font/epgd.svg create mode 100644 http/www/font/epgd.ttf create mode 100644 http/www/font/epgd.woff create mode 100644 http/www/font/epgd.woff2 create mode 100644 http/www/images/169.png create mode 100644 http/www/images/2kanal.png create mode 100644 http/www/images/43.png create mode 100644 http/www/images/TagesTipp_32.png create mode 100644 http/www/images/Tipp_32.png create mode 100644 http/www/images/TopTipp_32.png create mode 100644 http/www/images/animated-overlay.gif create mode 100644 http/www/images/audio_description.png create mode 100644 http/www/images/dd.png create mode 100644 http/www/images/epg_icons_24x24_orange.png create mode 100644 http/www/images/epgd-4x.png create mode 100644 http/www/images/hd.png create mode 100644 http/www/images/loader.png create mode 100644 http/www/images/stereo.png create mode 100644 http/www/images/sw.png create mode 100644 http/www/images/thumb-rate1.svg create mode 100644 http/www/images/thumb-rate2.svg create mode 100644 http/www/images/thumb-rate3.svg create mode 100644 http/www/images/thumb-rate4.svg create mode 100644 http/www/images/thumb-rate5.svg create mode 100644 http/www/images/ui-bg_flat_75_aaaaaa_40x100.png create mode 100644 http/www/images/ui-bg_glass_100_f5f0e5_1x400.png create mode 100644 http/www/images/ui-bg_glass_25_cb842e_1x400.png create mode 100644 http/www/images/ui-bg_glass_70_ede4d4_1x400.png create mode 100644 http/www/images/ui-bg_highlight-hard_100_f4f0ec_1x100.png create mode 100644 http/www/images/ui-bg_highlight-hard_65_fee4bd_1x100.png create mode 100644 http/www/images/ui-bg_highlight-hard_75_f5f5b5_1x100.png create mode 100644 http/www/images/ui-bg_inset-soft_100_f4f0ec_1x100.png create mode 100644 http/www/images/ui-icons_c47a23_256x240.png create mode 100644 http/www/images/ui-icons_cb672b_256x240.png create mode 100644 http/www/images/ui-icons_f08000_256x240.png create mode 100644 http/www/images/ui-icons_f35f07_256x240.png create mode 100644 http/www/images/ui-icons_ff7519_256x240.png create mode 100644 http/www/images/ui-icons_ffffff_256x240.png create mode 100644 http/www/images/untertitel.png create mode 100644 http/www/index.html create mode 100644 http/www/lang/de.js create mode 100644 http/www/lang/hilfe.html create mode 100644 httpd.c create mode 100644 httpd.h create mode 100644 json.examples create mode 100644 levenshtein.c create mode 100644 levenshtein.h create mode 100644 lib/Makefile create mode 100644 lib/common.c create mode 100644 lib/common.h create mode 100644 lib/config.c create mode 100644 lib/config.h create mode 100644 lib/configuration.c create mode 100644 lib/configuration.h create mode 100644 lib/curl.c create mode 100644 lib/curl.h create mode 100644 lib/db.c create mode 100644 lib/db.h create mode 100644 lib/dbdict.c create mode 100644 lib/dbdict.h create mode 100644 lib/demo.c create mode 100644 lib/demo.dat create mode 100644 lib/epgservice.c create mode 100644 lib/epgservice.h create mode 100644 lib/imgtools.c create mode 100644 lib/imgtools.h create mode 100644 lib/json.c create mode 100644 lib/json.h create mode 100644 lib/parameters.c create mode 100644 lib/parameters.h create mode 100644 lib/python.c create mode 100644 lib/python.h create mode 100644 lib/pytst.c create mode 100644 lib/searchtimer.c create mode 100644 lib/searchtimer.h create mode 100644 lib/semtst.c create mode 100644 lib/test.c create mode 100644 lib/thread.c create mode 100644 lib/thread.h create mode 100644 lib/wol.c create mode 100644 lib/wol.h create mode 100644 main.c create mode 100644 moviedbmanager.c create mode 100644 moviedbmanager.h create mode 100644 plugin.c create mode 100644 scraper/themoviedbscraper/moviedbactor.c create mode 100644 scraper/themoviedbscraper/moviedbactor.h create mode 100644 scraper/themoviedbscraper/moviedbmovie.c create mode 100644 scraper/themoviedbscraper/moviedbmovie.h create mode 100644 scraper/themoviedbscraper/themoviedbscraper.c create mode 100644 scraper/themoviedbscraper/themoviedbscraper.h create mode 100644 scraper/thetvdbscraper/thetvdbscraper.c create mode 100644 scraper/thetvdbscraper/thetvdbscraper.h create mode 100644 scraper/thetvdbscraper/tvdbactor.c create mode 100644 scraper/thetvdbscraper/tvdbactor.h create mode 100644 scraper/thetvdbscraper/tvdbepisode.c create mode 100644 scraper/thetvdbscraper/tvdbepisode.h create mode 100644 scraper/thetvdbscraper/tvdbmedia.c create mode 100644 scraper/thetvdbscraper/tvdbmedia.h create mode 100644 scraper/thetvdbscraper/tvdbmirrors.c create mode 100644 scraper/thetvdbscraper/tvdbmirrors.h create mode 100644 scraper/thetvdbscraper/tvdbseries.c create mode 100644 scraper/thetvdbscraper/tvdbseries.h create mode 100755 scripts/epgd-conflictsof create mode 100755 scripts/epgd-dropall create mode 100755 scripts/epgd-import-epglv create mode 100755 scripts/epgd-ls-channelids create mode 100755 scripts/epgd-sendmail create mode 100755 scripts/epgd-showdones create mode 100755 scripts/epgd-showmerge create mode 100755 scripts/epgd-showtimer create mode 100755 scripts/epgd-showtimerat create mode 100755 scripts/epgd-tool create mode 100755 scripts/epgh-login create mode 100755 scripts/epgh-request create mode 100755 scripts/epgsearchdone.pl create mode 100644 series.c create mode 100644 series.h create mode 100644 svdrpclient.c create mode 100644 svdrpclient.h create mode 100644 tools/fuzzy.c create mode 100644 tools/fuzzy.h create mode 100644 tools/stringhelpers.c create mode 100644 tools/stringhelpers.h create mode 100644 tvdbmanager.c create mode 100644 tvdbmanager.h create mode 100644 update.c create mode 100644 webauth.c create mode 100644 webdo.c create mode 100644 webstore.c create mode 100644 webtools.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..572e06e --- /dev/null +++ b/.gitignore @@ -0,0 +1,23 @@ +*.o +*.a +*~ +PLUGINS/ +lib/demo +lib/tst +epglv/mysqlepglv.so +epgd +epghttpd +PLUGINS/epgdata/libepgd-epgdata.so +http/3rdParty +scripts/_references.js +http/www/channellogos +http/images_unused +http/src/dev.sh +http/src/less-rhino-1.7.0.js +http/src/lessc-rhino-1.7.0.js +images_unused +translate-tabledef2dat +eptst +http/epgd.full.js +lib/pytst +/Make.config diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..f90922e --- /dev/null +++ b/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/HISTORY.h b/HISTORY.h new file mode 100644 index 0000000..ed490f8 --- /dev/null +++ b/HISTORY.h @@ -0,0 +1,1285 @@ +/* + * ----------------------------------- + * EPG Daemon - epgd Revision History + * ----------------------------------- + */ + +#define _VERSION "1.1.103" +#define VERSION_DATE "03.03.2017" +#define DB_API 4 + +#ifdef GIT_REV +# define VERSION _VERSION "-GIT" GIT_REV +#else +# define VERSION _VERSION +#endif + +/* + * ------------------------------------ + + +2017-03-03: version 1.1.103 (horchi) + - bugfix: Fixed os release detection for SuSe (fixed by 3po) + +2017-03-01: version 1.1.102 (horchi) + - Added: last merge to vdrs table (only for statistics/support reason) + +2017-02-27: version 1.1.101 (horchi) + - Added: Added support for systemd support in build environment + +2017-02-26: version 1.1.100 (horchi) + - bugfix: Fixed mail spam on invalid manuel timer + +2017-02-24: version 1.1.99 (ckone) + - change: Improved merge match duration due to some verry short events + +2017-02-24: version 1.1.98 (horchi) + - bugfix: Fixed problem with empty shorttext in timersdone + +2017-02-22: version 1.1.97 (horchi) + - changed: Modified Makefile to support more simultaneously make jobs + +2017-02-22: version 1.1.96 (horchi) + - added: 'After' template for systemd init + +2017-02-16: version 1.1.95 (horchi) + - added: Optional mail notification on create of 'auto-timer' + +2017-02-15: version 1.1.94 (horchi) + - bugfix: Fixed missing ! in some mails + +2017-02-14: version 1.1.93 (horchi) + - bugfix: Fixed timer delete on missing event + +2017-02-13: version 1.1.92 (horchi) + - bugfix: Fixed problem with autotimer update on simultaneous timer adjust + +2017-02-08: version 1.1.91 (horchi) + - changed: minor log level change + +2017-02-07: version 1.1.90 (rechner) + - fixed: sorting records for title + - fixed: multiple highlights on sorting-context-menu + - changed: newpath on moving improved + +2017-02-07: version 1.1.89 (horchi) + - changed: Timer 'start time change' messages only on changes greater 2 minutes + +2017-01-25: version 1.1.88 (horchi) + - bugfix: fixed auto adjust of timer start time + - bugfix: fixed handling of timer mails + +2017-01-24: version 1.1.87 (rechner) + - bugfix: fixed refresh of searchtimer-table after saving from dialog + +2017-01-20: version 1.1.86 (horchi) + - bugfix: fixed compile with python 3 + +2017-01-19: version 1.1.85 (rechner) + - added: defaultvalues for namingmode template + - added: placeholder for quicklinks in defaults + - fixed: click onsubmenu line + +2017-01-19: version 1.1.84 (horchi) + - bugfix: fixed minor problem with naming mode for sinlge timer create via web + +2017-01-19: version 1.1.83 (horchi) + - changed: changed length of template input box + +2017-01-19: version 1.1.82 (horchi) + - added: support of namingmode 'template' by epgd/epghttpd + +2017-01-19: version 1.1.81 (horchi) + - changed: Update of web help text for timer + +2017-01-18: version 1.1.80 (rechner) + - added: namingmode 6 = template in searchdialog added (missing in backend) + +2017-01-18: version 1.1.79 (horchi) + - bugfix: Fixed double escape of recording name + +2017-01-14: version 1.1.78 (horchi) + - changed: Compatibility to libmicrohttpd version <= 0x00095102 + +2017-01-13: version 1.1.77 (horchi) + - changed: Compatibility to libmicrohttpd version <= 0x00090000 + +2017-01-13: version 1.1.76 (horchi) + - added: Experimental TLS support + +2017-01-12: version 1.1.75 (horchi) + - bugfix: fixed config parser + +2017-01-12: version 1.1.74 (horchi) + - bugfix: fixed handling of null values in WEBIF communication + +2017-01-03: version 1.1.73 (rechner) + - bugfix: disabled state on user-rights again + +2017-01-02: version 1.1.72 (rechner) + - bugfix: disabled state on user-rights + +2017-01-02: version 1.1.71 (rechner) + - changed: layout from edit User + - bugfix: load users without cache + +2016-12-14: version 1.1.70 (horchi) + - bugfix: fixed sql syntax error in epgd-dropall (Thx to Michael Schaffner) + +2016-12-13: version 1.1.69 (horchi) + - bugfix: send TCC mails only once + +2016-12-12: version 1.1.68 (horchi) + - bugfix: fixed sql syntax error in epgd-dropall (Thx to Michael Schaffner) + +2016-12-12: version 1.1.67 (horchi) + - bugfix: fixed crash on epghttpd shutdown + +2016-12-05: version 1.1.66 (horchi) + - bugfix: mask ' signs at mal body + +2016-12-04: version 1.1.65 (rechner) + - bugfix: canceling von delete Timer no longer ignored + +2016-12-03: version 1.1.63 (rechner) + - added: recordigs could be selected and delete + +2016-12-02: version 1.1.62 (rechner) + - fixed: icons in WebIf + +2016-12-02: version 1.1.61 (horchi) + - change: moved TCC mails to message interface + +2016-12-02: version 1.1.60 (horchi) + - bugfix: fixed message config + +2016-12-01: version 1.1.59 (rechner) + - added: messages view in WebIf + +2016-12-01: version 1.1.58 (horchi) + - added: optional notification mails + - change: internal API redesign + +2016-12-01: version 1.1.57 (horchi) + - change: added pause on state change to prevent seldom 'deadlocks' on epg2vdr side + +2016-11-30: version 1.1.56 (horchi) + - change: merging of lib + +2016-11-30: version 1.1.55 (horchi) + - added: Delete / Modify of timers on event changes + +2016-11-28: version 1.1.54 (rechner) + - fixed: drag and drop for mobile in recording + - fixed: positioning of elements while drag and drop in recording + +2016-11-25: version 1.1.53 (horchi) + - change: Install systemd script only on change + +2016-11-24: version 1.1.52 (rechner) + - added: search in recordings + - change: drag and drop in recordings + - fixed: moving recording + +2016-11-24: version 1.1.51 (horchi) + - added: constabel test to lib/test tool + +2016-11-24: version 1.1.50 (horchi) + - bugfix: fixed sql syntax error + +2016-11-24: version 1.1.49 (horchi) + - added: recording by name service for webif requests + +2016-11-24: version 1.1.48 (horchi) + - fixed: Fix rename of recordings for webif service + +2016-11-21: version 1.1.47 (horchi) + - change: Added curl option for "CURLOPT_UNRESTRICTED_AUTH" + - fixed: URL in conflict mails + - change: Added more systemd watchdog notification + +2016-11-19: version 1.1.46 (rechner) + - fixed: Fix app for ipad and old browser (let was not supported) + +2016-11-19: version 1.1.45 (horchi) + - change: adjusted time format of timer conflict mails + +2016-11-18: version 1.1.44 (rechner) + - fixed: Fix app for ipad and old browser (let was not supported) + - change: optimze html-code for conflict mails + +2016-11-18: version 1.1.43 (horchi) + - change: new format of conflict mails + +2016-11-12: version 1.1.42 (rechner) + - fixed: SQL for mysql 5.7 changed (ckone) + - fixed: simple Aprostoph replace with special Aprostoph, because sending of Timerkonflikt-Mails failed + - fixed: search for recordigs + +2016-11-03: version 1.1.41 (horchi) + - added: started implementaion of message service for web + +2016-11-03: version 1.1.40 (horchi) + - added: support of redirect on file download + +2016-11-02: version 1.1.39 (horchi) + - bugfix: fixed parameter name (lastEpisodeFullRun) + +2016-11-01: version 1.1.38 (rechner) + - changed: https://ssl.constabel-it.de/eplists.constabel.net to https://www.eplists.de + +2016-11-01: version 1.1.37 (rechner) + - fixed: drag and drop not initialised + +2016-11-01: version 1.1.36 (rechner) + - added search for recordigs + - rechanged: match-density withot gradiant + - fixed: bug while changed between different resolutions + +2016-11-01: version 1.1.35 (horchi) + - bugfix: fixed epglv makefile + +2016-10-31: version 1.1.34 (rechner) + - changed: uses gradient for match-density and show % as title + +2016-10-31: version 1.1.32 (horchi) + - bugfix: Fixed timzone display for WEBIF + +2016-10-30: version 1.1.31 (horchi) + - change: skipping epgsearch timer at timer check + +2016-10-29: version 1.1.30 (horchi) + - change: added recording owner to event at web sercive protocol + +2016-10-27: version 1.1.29 (horchi) + - added: notify vdr on timer modification + +2016-10-26: version 1.1.28 (horchi) + - added: renaming recording on events data change (for pending timers) + +2016-10-26: version 1.1.27 (horchi) + - changed: renamed vdruuid to owner for web protocol + +2016-10-25: version 1.1.26 (rechner) + - added: show matching recording data of event detail + +2016-10-25: version 1.1.25 (horchi) + - bugfix: fixed minor error message + +2016-10-20: version 1.1.24 (horchi) + - bugfix: fixed (removed) string escape for sql bindings + +2016-10-20: version 1.1.23 (horchi) + - bugfix: minor fix of log message + +2016-10-20: version 1.1.22 (horchi) + - added: started implementaion of timer check on changed events (only log messages) + -> to be continues ;) + +2016-10-20: version 1.1.21 (horchi) + - bugfix: minor fix + +2016-10-20: version 1.1.20 (horchi) + - bugfix: fixed error handling of mysql udf epglv + +2016-10-19: version 1.1.19 (horchi) + - added: match density to recording data of event detail service + +2016-10-18: version 1.1.18 (horchi) + - added: recording data to event detail service + - change: improved epgd-dropall script + +2016-10-16: version 1.1.17 (horchi) + - change: improved db reconnect handling of searchtimer code + +2016-10-11: version 1.1.16 (rechner) + - fix: detailview on devices > 900 + - added: parameter for defaultsort in recordings + +2016-09-08: version 1.1.15 (rechner) + - fix: detailview on devices > 768 and < 1139 + +2016-08-30: version 1.1.14 (horchi) + - bugfix: fixed minor webif bug according safari browser (rechner) + +2016-08-29: version 1.1.13 (horchi) + - change: Update of epgd-tool by 3po + +2016-08-26: version 1.1.12 (horchi) + - added: support of long eventids for tvsp (merged dev into master) + +2016-07-25: version 1.1.11 (rechner) + - bugfix: if wrong channelsort from backend, channel will also shown right + +2016-07-21: version 1.1.10 (rechner) + - fixed: scrping must also using int64 + +2016-07-20: version 1.1.9 (rechner) + - fixed: imageid must also using int64 + +2016-07-19: version 1.1.8 (rechner) + - rechange: increased event id to unsigned int64 even for searchtimer + - change: increased event id to unsigned int64 even for lib/pytst + +2016-07-16: version 1.1.7 (rechner) + - change: increased event id to unsigned int64 even for searchtimer + +2016-07-15: version 1.1.6 (horchi) + - change: increased event id to unsigned int64 even for epghttps plugin + +2016-07-15: version 1.1.5 (horchi) + - bugfix: fixed 'optimized Makefiles' (by Alexander Grothe) + - change: minor code review + +2016-07-13: version 1.1.4 (horchi) + - change: increased event id to unsigned int64 for epgdata plugin + +2016-07-13: version 1.1.3 (horchi) + - change: started increase of event id to unsigned int64 + +2016-07-08: version 1.1.2 (horchi) + - change: optimized Makefiles (by Alexander Grothe) + +2016-07-06: version 1.1.1 (horchi) + - change: Update of epgd-tool by 3po + +2016-07-04: version 1.1.0 (horchi) + - change: Merged http branch into master + +2016-06-25: version 1.0.106 (rechner) + - fixed: avoid errormessage, if no channel has no data + +2016-06-19: version 1.0.104 (rechner) + - added: tv-switch channel icon to channels + - fixed: edit searchtimer from timerlist + +2016-06-12: version 1.0.103 (rechner) + - changed: logs an erroe, if defaultVDR is invalid or no vdr found + +2016-06-12: version 1.0.102 (rechner) + - fixed: failed open detailview + - added Make.config to ignore list + +2016-06-03: version 1.0.101 (horchi) + - change: Changed Makefile for epglv + +2016-06-02: version 1.0.100 (rechner) + - fix: storing of namingmode + +2016-06-01: version 1.0.99 (horchi) + - change: system notification thread more silent + +2016-06-01: version 1.0.98 (horchi) + - change: updated README + - change: improved init system integration + - register before tables are initialized + - implemented notrification timeout for alter tables (alter can take a long time) + +2016-06-01: version 1.0.97 (horchi) + - added: eventsview-uti.sql + +2016-06-01: version 1.0.96 (horchi) + - added: install of init scripts with 'make install' (for upstart and systemd) + the init system can set in Make.config + +2016-05-31: version 1.0.95 (horchi) + - change: update of views + +2016-05-31: version 1.0.94 (horchi) + - change: increased file topic to 1000 and the max image size to 512k + +2016-05-31: version 1.0.93 (horchi) + - change: log level für 'Check rights of' set to 2 + - change: adjusted path in systemd start files + +2016-05-31: version 1.0.92 (horchi) + - bugfix: set visible flag on initial create of channelmap + +2016-05-26: version 1.0.91 (rechner) + - fix: deleting of multiple timers + +2016-05-26: version 1.0.90 (rechner) + - fix: deleting of timers + +2016-05-25: version 1.0.89 (rechner) + - change: deleting and selecting from table rows are now only on visible rows + - added: shows count of deleting entries in confirm dialog + - fixed: 'visible' flag for channels only for flagvalue 1 + - fixed: wrong timerdialog on record in eventdetail + +2016-05-25: version 1.0.88 (horchi) + - bugfix: Fixed scrap for recordings - don't lookup events data for 'old' recordings + - change: Chenged order of recording scrap - fist honor the user scrap info + +2016-05-25: version 1.0.87 (horchi) + - bugfix: Fixed initial 'visible' flag for new sources of existing channel + +2016-05-24: version 1.0.86 (rechner) + - added: detail dialog for donetimer + - bugfix: some fixes + +2016-05-24: version 1.0.85 (horchi) + - change: minor change in thread context + +2016-05-24: version 1.0.84 (horchi) + - added: data/donetimer for webif request + +2016-05-23: version 1.0.83 (rechner) + - bugfix: could not open eventdetail after view settings + +2016-05-23: version 1.0.82 (horchi) + - change: modified repeaing timer check statement to handle '' values like null values + +2016-05-23: version 1.0.81 (horchi) + - change: let unset EPISODE* fields of timersdone 'null' + +2016-05-23: version 1.0.80 (horchi) + - change: adjusted log levels + +2016-05-21: version 1.0.79 (rechner) + - bugfix: css for thumb, if image is 4:30 + - changed: tip to Goldtip in searchdialog + - added: =! for quicktime, which should not be hihlighted in magazine view + +2016-05-21: version 1.0.78 (rechner) + - bugfix: now could not open after first call + - removed: parameter ratings + - bugfix: timerdone duration was wrong calculated + +2016-05-20: version 1.0.77 (horchi) + - change: update of epgdate xslt + +2016-05-20: version 1.0.76 (horchi) + - change: improved views for new rating info (ckone) + +2016-05-20: version 1.0.75 (horchi) + - change: fixed autotimer default name + +2016-05-20: version 1.0.74 (horchi) + - change: speed up web done-timers requests + +2016-05-20: version 1.0.73 (horchi) + - change: speed up web recording requests + +2016-05-20: version 1.0.72 (horchi) + - added: new column for textual rating and commentator + - change: removed unused info column + - change: updated merge procedure, views and xslt for new columns (ckone) + +2016-05-19: version 1.0.71 (rechner) + - bugfix: some fixes + - added: commentator and txtrating to eventdetail + - added: magazine - quicktimes colored + +2016-05-18: version 1.0.70 (rechner) + - added: tipp to data/events and shows in now and magazine + +2016-05-18: version 1.0.69 (horchi) + - change: improved stop of system notification thread + +2016-05-18: version 1.0.68 (horchi) + - added: new timer trigger field _starttime for internal usage + +2016-05-18: version 1.0.67 (horchi) + - added: auto wakeup VDR for not assumed timers within two days + +2016-05-18: version 1.0.66 (horchi) + - change: updated sql scripts + - change: updated merge procedure (ckone) + - change: table row fromat (at table create) now DYNAMIC + +2016-05-17: version 1.0.65 (rechner) + - added: tipp to data/event and shows in eventdetail + +2016-05-15: version 1.0.64 (rechner) + - removed: tipp from data/event, data/evetns, data/search + - added: parameter ratings + +2016-05-15: version 1.0.63 (rechner) + - added: numrating on data/event, data/evetns, data/search + - removed: tipp/tagestipp/toptipp from webview, uses numrating instead + +2016-05-15: version 1.0.62 (rechner) + - added: WOL on VDR menu item + - changed: topmenu has now submenus instead of tabs + +2016-05-15: version 1.0.61 (horchi) + - added: index for timers table + +2016-05-13: version 1.0.60 (horchi) + - added: wakeup vdr (WOL) for webif requests + +2016-05-11: version 1.0.59 (horchi) + - bugfix: Fixed event insert state handling for epgdata plugin + - change: Ported 'groub by' clause to mysql 5.7 + - change: minor changes + +2016-05-10: version 1.0.58 (horchi) + - added: optional config option 'seriesMail' for constabel login + +2016-05-10: version 1.0.57 (horchi) + - change: ported some SQL statements für mysql 5.7 + +2016-05-09: version 1.0.56 (horchi) + - fixed: added sql string-escape for python return + +2016-05-06: version 1.0.55 (rechner) + - fixed: magazine view for iphone + +2016-05-04: version 1.0.54 (horchi) + - change: update of eventsview-ck.sql + - change: increased field fileref to ASCII 100 + +2016-05-03: version 1.0.53 (rechner) + - bugfix: error on sort or delete record + +2016-05-03: version 1.0.52 (rechner) + - bugfix: doubled login call removed + - added: show count of recordings in List + +2016-05-03: version 1.0.51 (horchi) + - bugfix: fixed replay recording via webif + +2016-05-03: version 1.0.50 (horchi) + - added: curl option for 'gzip' + +2016-05-02: version 1.0.49 (horchi) + - change: removed 'groub by' clause of TCC due to compatibility to new mysql versions + +2016-04-29: version 1.0.48 (rechner) + - fixed: pages_now qucksesarch position + + 2016-04-28: version 1.0.47 (rechner) + - fixed: calendar skiped a day + +2016-04-27: version 1.0.46 (rechner) + - added: global error handling with log + +2016-04-27: version 1.0.45 (horchi) + - change: new files for fedora (thx to marco) + +2016-04-26: version 1.0.44 (rechner) + - fixed: calendar starts had ignored start of week + - added: EpgViewWeb in epgd.config configurable + +2016-04-25: version 1.0.43 (rechner) + - changed: calendar starts now with minEventDay + +2016-04-24: version 1.0.42 (rechner) + - added: now it is possible to override css via custom.css + - changed: added owner to data/replayrecording + +2016-04-24: version 1.0.41 (rechner) + - fixed: play record on VDR + +2016-04-24: version 1.0.40 (horchi) + - change: modified log messages for systemd integration (thx to seahawk1986) + +2016-04-23: version 1.0.39 (rechner) + - added: quicklinks added to now-View + - changed: eventdetail: if we have scrapper series info, constabel will be shown + +2016-04-23: version 1.0.38 (rechner) + - fixed: timerdialog window centered in magazine view + - fixed: encode & in title for canstable links + - fixed: typo in bugfix: removed timer with state '-' from web request + +2016-04-22: version 1.0.37 (horchi) + - bugfix: removed timer with state '-' from web request + +2016-04-22: version 1.0.36 (horchi) + - bugfix: fixed build of pytst + +2016-04-21: version 1.0.35 (rechner) + - fixed: error on save timer if list container not initialist + - added: if error in loader-func, loader also closed + +2016-04-20: version 1.0.34 (rechner) + - fixed: some typos (thanks to Lars) + +2016-04-20: version 1.0.33 (rechner) + - fixed: magazine: use difference of startimes for heigt calc instead of duration + +2016-04-20: version 1.0.32 (horchi) + - bugfix: fixed done check with null values + +2016-04-20: version 1.0.31 (horchi) + - change: episodename search now case insensitiv + - bugfix: fixed range search + +2016-04-20: version 1.0.30 (horchi) + - bugfix: fixed field format of AUTOTIMERNAME + +2016-04-20: version 1.0.29 (horchi) + - bugfix: fixed redundant recordings + +2016-04-19: version 1.0.28 (rechner) + - added: Version as parameter on epgd.js, epgd.css and common.js to prevent cached + - added: show thump on check count hits for save searchtimer + - added: help extended + +2016-04-19: version 1.0.27 (horchi) + - change: fix of makefile to new systemd version (thx to seahawk1986) + +2016-04-19: version 1.0.26 (horchi) + - bugfix: fixed field name + +2016-04-19: version 1.0.25 (horchi) + - change: ported makefile to new systemd version (thx to seahawk1986) + +2016-04-18: version 1.0.24 (rechner) + - fixed: data/search delete timer name on test and search + - changed: if page changed, while recordings loading, page will not changed back to recordings + - changed: searchdialog - delete and copy button added + +2016-04-18: version 1.0.23 (horchi) + - added: update of autotimer name (in timers and timersdone) on change + - added: timer-name suport for data/search + +2016-04-18: version 1.0.22 (horchi) + - added: type parameter to data/searchtimers query + - added: curl wrapper enhancement for request headers (thx to chriszero) + - added: autotimername to table timersdone + +2016-04-18: version 1.0.21 (horchi) + - bugfix: fixed fedora files + +2016-04-17: version 1.0.20 (rechner) + - added: if button drown is pressed in searchtimerlist, the searchresult will be shown like timer from searchtimer + +2016-04-17: version 1.0.19 (horchi) + - change: new files for fedora (thx to marco) + +2016-04-16: version 1.0.18 (rechner) + - added: fixed start/max critiria for data/search + - fixed: searchdialog not closed on save + - added: maxListEntries as Parameter for data/search + +2016-04-16: version 1.0.17 (horchi) + - added: fixed start/max critiria for data/search + +2016-04-15: version 1.0.16 (rechner) + - added: todos now shown in help/about + - added: copy button in Searchtimerdialog + - added: ask on searchtimerdialog, if result > 50 + - added: quicktime < current time in calendar -1, we changed also the day + - changed: timerdialogs: name moved to top + - fixed: on change from timerdialog to searchtimerdialog, search-in-title is checked + - fixed: repeat on eventdetail crashed + +2016-04-15: version 1.0.15 (horchi) + - added: start to data/search for paging + +2016-04-15: version 1.0.14 (horchi) + - added: autotimername to table timers + - added: limit for data/search + +2016-04-14: version 1.0.13 (rechner) + - fixed: searchtimerresultlist could only be execute once + - fixed: year in searchdialog gets also 2000- + - added: clear button on timepicker (search) + - changed: name from searchtimer is always visible + - added: searchtimerlist: name or expression will shown and has now icons + +2016-04-14: version 1.0.12 (horchi) + - change: increased parameter size to 500 character + +2016-04-14: version 1.0.11 (horchi) + - added: added missing js file + +2016-04-14: version 1.0.10 (horchi) + - added: allow name of searchtimer for 'quickTimes' + +2016-04-13: version 1.0.9 (rechner) + - added: app now launchable as WepApp in fullscreen + - changed: jquery update (2.2.3) + - changed: search is now inherited from searchtimer + - added: nexdays in searchdialog + +2016-04-13: version 1.0.8 (horchi) + - change: even more log messages + +2016-04-13: version 1.0.7 (horchi) + - change: minor log message changes + +2016-04-05: version 1.0.6 (rechner) + - added: filter for starttime in timer + - changed: sort of timersdone is now desc for starttime + +2016-04-04: version 1.0.5 (rechner) + - fixed: hit table was over dialog(zIndex) + +2016-03-28: version 1.0.4 (rechner) + - fixed: search: show loading, on new search + +2016-03-28: version 1.0.3 (rechner) + - added: multiple filter in tables + - fixed: sorting of tables + +2016-03-27: version 1.0.2 (rechner) + - fixed: daylight flag in localtime + - changed: editchannels input field now filterlines instead of selecting + - changed: in now view all Items have same height, mouseover on desc will expand it + +2016-03-26: version 1.0.1 (rechner) + - fixed: eventdetail headline was on wrong position in FF ESR + - added: History with versions info in web-help + - extend: help + +2016-03-26: version 1.0.0 (rechner) + - added: first Betarelease + +2016-03-26: version 0.7.12 (horchi) + - bugfix: fixed char compare of db API + +2016-03-25: version 0.7.11 (rechner) + - fixed: default-values for timer state and action changed to upercase + - added: magazine view scrolled on mouseover on border area + - changed: javascript is now minified + +2016-03-25: version 0.7.10 (rechner) + - fixed: default-values for timer state and action changed to upercase + - added: magazine view scrolled on mouseover on border area + +2016-03-24: version 0.7.9 (rechner) + - fixed: some fixes in webIf + - changed: fixed timer query für web requests, no default-values + - changed: click on now or magazine set time to now + - fixed: magzine view for iphone/ipad + +2016-03-24: version 0.7.8 (horchi) + - added: day range for autotimer + +2016-03-24: version 0.7.7 (horchi) + - bugfix: fixed handling of auto timer with vdr=auto + +2016-03-24: version 0.7.6 (horchi) + - change: fixed timer query für web requests + +2016-03-23: version 0.7.5 (rechner) + - changed: channel in timerdialog is now autocomple and contains all channels + - added: timertype in timerdialogs + - changed: mazineview layout changed, title on top, minheight of 20 px + +2016-03-23: version 0.7.4 (horchi) + - bugfix: fixed delete of timer attributes + +2016-03-23: version 0.7.3 (horchi) + - added: added field name to table serachtimers + +2016-03-23: version 0.7.2 (horchi) + - bugfix: fixed channel include/exclude of searchtimers + +2016-03-23: version 0.7.1 (horchi) + - change: fixed compile (missing header) on some environments + - change: Update of TODO list + - added: timer-type field to timer tables (for planned features) + +2016-03-22: version 0.7.0 (horchi/rechner) + - added: advanced searchtimer: episodename, season, seasonpart, year, category, genre, tipp, noepgmatch,chexclude + +2016-03-22: version 0.6.59 (horchi) + - changed: search timer statement ordered by starttime and the configured channel order + +2016-03-22: version 0.6.58 (horchi) + - changed: removed reason from timers table + +2016-03-21: version 0.6.57 (rechner) + - changed: show timer actionflag + +2016-03-21: version 0.6.56 (horchi) + - added: auto alter for default value + +2016-03-21: version 0.6.55 (rechner) + - changed: max-width for channellogos in magazine view + - fixed: filter in tables will be called, if table was updated + - added: logoShowName + +2016-03-21: version 0.6.54 (horchi) + - changed: added default value für timer state + +2016-03-19: version 0.6.53 (rechner) + - changed: channellogos now img-tags + +2016-03-18: version 0.6.52 (rechner) + - bugfix: fixed content type of SVG image + - added: support of sfg files in css + - added: Filter in donetimers for title + - changed: action-state in timer view + +2016-03-18: version 0.6.51 (horchi) + - added: added make update to Makefile + +2016-03-18: version 0.6.5 (horchi) + - bugfix: fixed content type of SVG image + +2016-03-17: version 0.6.49 (horchi) + - change: changed content type of SVG image + +2016-03-17: version 0.6.48 (horchi) + - bugfix: fixed path of SVG files + +2016-03-16: version 0.6.47 (horchi) + - added: extended filter of timer query (data/timers) (action, notaction and notstate) + +2016-03-16: version 0.6.46 (horchi) + - added: implemented max fail retries for autotimers with reuse of timer-row + +2016-03-15: version 0.6.45 (horchi) + - fixed: mising event id on manual timers + +2016-03-15: version 0.6.44 (horchi) + - fixed: init timezone lib + - fixed: fixed error message at failed image load + - fixed: fixed webif timer with 'vdr = auto' + - added: support of SVG logos + +2016-03-14: version 0.6.43 (rechner) + - fixed: calculating from timezone to all times + +2016-03-14: version 0.6.42 (horchi) + - bugfix: fixed 'escape user defined sql strings' + +2016-03-14: version 0.6.41 (horchi) + - added: httpDevice to epgd.conf, epghttpd listen on this device instead of all devices + +2016-03-14: version 0.6.40 (horchi) + - change: merge of lib code with plugin + +2016-03-14: version 0.6.39 (horchi) + - change: Escape user defined sql strings for queries + +2016-03-13: version 0.6.38 (rechner) + - fixed: currentTime in webif is now system time from epg daemon server + +2016-03-12: version 0.6.37 (rechner) + - added: parameter for schedules menu in webif + - added: records: headline for commonFolder + - changed: doTimerJobs -> response-object name is now timers + - changed: view of timersdone eual to timers + - fixed: sort of hits is now numeric + +2016-03-12: version 0.6.36 (horchi) + - change: update of epgsearchdone.pl + - added: README-import-epgsearch + - added: epgsearchdone.pl to make install + +2016-03-11: version 0.6.35 (horchi) + - added: added perl script to import epgsearchdone.data + +2016-03-03: version 0.6.34 (horchi) + - added: check expression for quickTime updated (webif) + +2016-03-02: version 0.6.33 (horchi) + - added: max-age of post requests now set to 0 + +2016-03-02: version 0.6.32 (horchi) + - added: @Now and @Next option to user times + +2016-02-29: version 0.6.31 (horchi) + - bugfix: fixed compile error + +2016-02-29: version 0.6.30 (horchi) + - added: config parameter for schedules menu + +2016-02-25: version 0.6.29 (horchi) + - changed: scraping now follow the category of the recoring strict + +2016-02-24: version 0.6.28 (horchi) + - changed: moved the python interface an the searchtimer api to lib/ + +2016-02-19: version 0.6.27 (rechner) + - changed: records: sort also in subfolders + - added: records: ESC canceled drag and drop and close menu + +2016-02-16: version 0.6.25 (rechner) + - change: query only pending an recording timer für timers?autotimer=x request + +2016-02-15: version 0.6.24 (rechner) + - added: show reason in timerlist + +2016-02-15: version 0.6.23 (horchi) + - bugfix: Fixed statement for already recorded check + +2016-02-15: version 0.6.22 (horchi) + - change: update searchtimer only on change + +2016-02-13: version 0.6.21 (horchi) + - change: prohibit searchtimer to create timer for already scheduled event + +2016-02-11: version 0.6.20 (rechner) + - change: help extend + +2016-02-11: version 0.6.19 (horchi) + - bugfix: Fixed searchtimer state + +2016-02-11: version 0.6.18 (horchi) + - bugfix: Removed DOS CRLF of source files + +2016-02-10: version 0.6.16 (rechner) + - change: data/save-timer and data/save-searchtimer: change start to starttime and stop to endtime + - change: expanded suchtimer dialog + +2016-02-10: version 0.6.15 (horchi) + - bugfix: Fixed variable overflow + +2016-02-10: version 0.6.14 (horchi) + - added: Detail EPG fields to searchtimers (not used so far) + +2016-02-09: version 0.6.13 (rechner) + - bugfix: delete searchtimer form dialog failed + - change: timerdialog: repeatFields "Episode" and "Episodenpart" deleted and season and seasonpart added + - added: records: show recordingday + +2016-02-09: version 0.6.12 (horchi) + - bugfix: Fixed error on timer create (uninitialized variable) + +2016-02-09: version 0.6.11 (horchi) + - bugfix: Fixed problem with done states an searchtimers + +2016-02-09: version 0.6.10 (horchi) + - change: Improved log message at timer create + - bugfix: Fixed problem with TCC mail count + +2016-02-08: version 0.6.9 (horchi) + - change: Fixed some compiler warnings + - change: improved check for 'repeating' events aut timer creation + +2016-02-07: version 0.6.8 (horchi) + - change: Send TCC mail only one per timer + - change: Try to fix compile problems by g++ 6 + +2016-02-05: version 0.6.7 (horchi) + - bugfix: call systemd watchdog trigger at even more situations :( .... + +2016-02-05: version 0.6.6 (horchi) + - bugfix: fixed sql syntax error + +2016-02-05: version 0.6.5 (horchi) + - added: implemented store-donetimers for webif request + +2016-02-05: version 0.6.4 (horchi) + - added: support for timer creation at 'any' vdr + - change: update of TODOs + - added: log duration of http requests + +2016-02-04: version 0.6.3 (horchi) + - change: finelized new timerjobs design + +2016-02-01: version 0.6.2 (horchi) + - change: redesign of timerjobs, remove table timerdistribution + +2016-02-01: version 0.6.1 (rechner) + bugfix: remove deleted item from view in recordings + change: if time could not be set in timpicker, because there are no events, automaticly a day will be added + +2016-02-01: version 0.6.0 (horchi) + - change: check constabel maximum only for full-update + +2016-02-01: version 0.5.34 (horchi) + - bugfix: Fixed parameter store + +2016-02-01: version 0.5.33 (horchi) + - bugfix: Now a maximum one constabel retries per 6 hours + +2016-01-29: version 0.5.32 (horchi) + - bugfix: Fixed delete of recording by webif + +2016-01-29: version 0.5.31 (horchi) + - change: TODO list update + +2016-01-29: version 0.5.30 (horchi) + - change: fixed field size + +2016-01-28: version 0.5.29 (rechner) + - change: all items in now-view have now the same height + - change: recordings: new algo for print title,name and shorttext + - bugfix: regex for quicktimes + +2016-01-26: version 0.5.28 (rechner) + - bugfix: magazine view fix, if less channels as visibile screen are available + - bugfix: saving quicktimes + - changed: show videofolder and available above records + +2016-01-27: version 0.5.27 (horchi) + - change: minor changes + +2016-01-26: version 0.5.26 (rechner) + - change: picktimers changed to quicktimers; no syntax label=time[~label=time...] +2016-01-26: version 0.5.25 (rechner) + - bugfix: magazine: maxcols are depending now from screen or mac channels + - bugfix: access deniend replaced with common error, if choose menu-item failed + - change: get parameters in dialog options are not cached anymore + - bugfix: no error popup at logoff + - added: show videofolder and available in records + +2016-01-20: version 0.5.24 (horchi) + - bugfix: fixed c&p bug in systemd notifications + +2016-01-18: version 0.5.23 (horchi) + - added: support script epgd-showtimerat + - added: notification events during epg merge procedure + - change: increased source field of table timerdistribution (to fit uuid) + +2016-01-18: version 0.5.22 (horchi) + - bugfix: implemented solution for 0.5.21 + +2016-01-18: version 0.5.21 (horchi) + - bugfix: refix of 0.5.20 ;) -> workaround is to store the channellist at least once via webif + +2016-01-17: version 0.5.20 (horchi) + - bugfix: Fixed double channel listing in WEBIF/'Programme' tab + +2016-01-15: version 0.5.19 (rechner) + - change: handling of 409 -> ids for failed parameter + +2016-01-15: version 0.5.18 (horchi) + - bugfix: don't try to send mail without at leadt one receiver + +2016-01-15: version 0.5.17 (horchi) + - added: return ids of failed parameters for data/store-parameters + - change: return all parameters, even the not yet configured for data/parameters + - added: added watchdog notification during episode lookup and download + +2016-01-15: version 0.5.16 (horchi) + - bugfix: fixed crash at store of parameter with missing value + +2016-01-14: version 0.5.15 (rechner) + - change: add type to parameter and use it in webif + - bugfix: parameter were cached after saving + +2016-01-14: version 0.5.14 (horchi) + - added: parameter type + +2016-01-14: version 0.5.13 (horchi) + - change: removed obsolete fields from table parameters + +2016-01-13: version 0.5.12 (rechner) + - change: show error message on state 409 + - change: save and delete timers: selected rows red, if this row failed + - bugfix: repeat-tab on eventsdetail was empty on call same eventdetail again + +2016-01-13: version 0.5.11 (horchi) + - bugfix: fixed typo in regexp for parameter validation + +2016-01-13: version 0.5.10 (horchi) + - bugfix: fixed loglevel handling for argument (-l) + - bugfix: fixed autoupdate on channelmap.conf changes + - change: minor code review and adjustment of some loglevels + +2016-01-13: version 0.5.9 (horchi) + - bugfix: fixed regular expressions for parameter validation + - bugfix: fixed return value on failed store of searchtimers + - added: system notification events during download + +2016-01-12: version 0.5.8 (rechner) + - change: extend search for repeats of eventdetail with shorttext + - bugfix: dateformat uses tr (de.js) + +2016-01-12: version 0.5.7 (horchi) + -bugfix: fixed define for systemd watchdog + +2016-01-12: version 0.5.6 (horchi) + - added: sending TCC mails for all registarted web users + +2016-01-12: version 0.5.5 (horchi) + - added: new search criteria for webif + - change: update of timer job interface for webif + +2016-01-12: version 0.5.4 (horchi) + - added: added missing parameter check by regular expression + - added: added watchdog notifications during scraping + +2016-01-11: version 0.5.3 (rechner) + - change: frontend-parameter cleaned in parameters.c + - bugfix: needLogin always changed to false on save-parameters + +2016-01-11: version 0.5.2 (horchi) + - change: Adapted systemd and pidfile options for epghttpd + +2016-01-11: version 0.5.1 (horchi) + - bugfix: fixed default for systemd in Make.config + +2016-01-11: version 0.5.0 (horchi) + - change: extended systemd interface (sd_watchdog_enabled) + - added: systemd notifications during epg update process + - added: support of pidfile (argument -i ) + +2016-01-08: version 0.4.2 (horchi) + - change: extended systemd interface + +2016-01-08: version 0.4.1 (horchi) + - change: changed config parameter handling + +2016-01-07: version 0.4.0 (horchi) + - change: Cleanup history for timer jobs now configurable + - added: Status interface for systemd -> activate/deactivate in Make.config + +2016-01-06: version 0.3.2 (horchi) + - change: Changed 'delete timer job' interface + +2016-01-05: version 0.3.1b (horchi) + - bugfix: Improved version check of revision control + +2016-01-05: version 0.3.1a (horchi) + - bugfix: Added version check to revision control + +2016-01-05: version 0.3.1 (horchi) + - added: Version control and git tagging helper functions to Makefile + - added: Start versioning of http branch + +2014-04-01: version 0.3.0a (horchi) + - added: started new development branch - dont' use - pre alpha! + - added: auto alter to DB API + +2014-04-15: version 0.2.0 (louis) + - added: scraper support + +2014-03-23: version 0.1.16 (horchi) + - bugfix: fixed type for userexit checksum + +2014-03-21: version 0.1.15 (horchi) + - added: added optional user defined procedure "userexit" called after data import + +2014-03-19: version 0.1.14 (horchi) + - bugfix: fixed image cleanup + +2014-03-19: version 0.1.13 (horchi) + - change: update images even if already imported + - added: uuid to eplists service login + +2014-03-17: version 0.1.12 (horchi) + - bugfix: major fix of 0.1.11! + +2014-03-17: version 0.1.11 + - change: increased episodes.partname, episodes.comppartname to 300 + - change: added fields producer, other and camera + - change: removed fields origtitle and team + +2014-01-03: version 0.1.10 + - change: adapted epgdata plugin to modified header + +2014-01-02: version 0.1.9 + - change: changed some fields to type Text due to row limit + - change: increased shortreview to varchar 500 + +2013-12-31: version 0.1.8 + - change: increased field guest to 1000 + +2013-12-06: version 0.1.7 + - bugfix: fixed mem bug on initial start (at view create) + +2013-12-05: version 0.1.6 + - bugfix: fixed mem bug on initial start (at procedure create) + +2013-12-04: version 0.1.5 + - bugfix: fixed minor mem leak + - change: changed coloum type of 'longdescription' from varchr to text + +2013-12-04: version 0.1.4 + - bugfix: fixed insert handling with multimerge + +2013-11-29: version 0.1.3 + - change: included procedures and views for multimerge + - change: added 90 minutes more for series fetch at eplists.constabel.net + +2013-11-20: version 0.1.2 + - change: changed merge flag in channelmap.conf yYnN not supportew anymore (preparation for feature ;)) + - change: updated bin-logging hint in README + - change: increased shorttext and compshorttext to 300 chars, topic and guest to 500 chars + therefore you have to alter your tables + - change: download timeout now configurable + - change: removed PIN from log message + - added: XML_PARSE_HUGE for libxml2 versions >= 20900 + +2013-10-28: version 0.1.1 + - change: fixed typos in README, added hint for epglv to README + - bugfix: fixed typo of channelmap parsing + - bugfix: Fixes at sql merge procedures by ckone + - change: Rerouted error messages wich prohibit start of epgd to stderr + - change: Improved epgd-tool (thanks to 3po) + +2013-10-23: version 0.1.0 + - change: first release with epg merge + - added: new options EpgView, CheckInitial and UpdateThreshold + - change new layout channelmap table + - added: -parameter to channelmap.conf (see channelmap.conf for instructions) + - added: handling of the DVBs x-components (for example the audio and video track descriptions) + +- Added possibilty to trigger EPG updates from your external EPG provider + - execute "killall -HUP epgd" on command line + + +2013-09-27: version 0.0.8b + - change: first alpha version with epg merge + - added: integrated sql procedures for epg merge (developed by ckone) + - added: automatic create of procedures and functions at initial start + - added: automatic create of analyze tables at initial start + - change: improved reuse of stored epgdata files after dropall + - change: improved cleanup of updated epgdata files + - added: new alternative view provided by 3PO + - change: improved drop script + +2013-09-23: version 0.0.8a + - change: started devel branch for epg merge + +2013-09-16: version 0.0.7 + - change: don't toggle updflg on series" + - change: improved speed on image load" + - bugfix: fixed bug on init with missing database (grabber plugin API changed!!) + +2013-09-05: version 0.0.6 + - added: init scripts and ebuild for gentoo - thanks to 3po + - added: show version (epgd -v) + - added: install of scripts with "make install" + - added: install of configuration (only if not already installed) + - change: renamed to epgd-ls-channelids.pl to epgd-ls-channelids + - change: updated init scripts + - change: updated epgd-tool (request root password only if needed) + - bugfix: fixed start with unknown parameter + - added: split busy state to "busy (events)" and "busy (images)" + +2013-09-03: version 0.0.5 + - change: updated log message + - change: updated db_helper and renamed to epgd-tool + - change: improved drop-all script (now interactive) and renamed to epgd-dropall + - change: added usage to getchannelid.pl and renamed to epgd-ls-channelids.pl + - change: Make.config now fit PREFIX und DESTDIR rules - thanks to gda + - added: plausibility for channelmap.conf (ignoring ambiguous channel config) + +2013-09-01: version 0.0.4 + - bugfix: fixed core on missing mysqld at start + +2013-09-01: version 0.0.3 + - change: removed mysql dependency from upstart skript + - change: improved error handling on download + - change: 'make' and 'make install' now build/install plugins + +2013-08-30: version 0.0.2 + - change: updated README + - added: DBAPI check on startup + - added: Store last update to vdrs table + - added: DEBUG switch to Make.config + - bugfix: minor bug in dh_helper.sh + - bugfix: fixed and renamend scripts/getchannelid.pl (config helper) + +2013-08-28: version 0.0.1 + - first official release + +2013-07-04: version 0.0.1-rc5 + - added: epgdata support + +2013-07-01: version 0.0.1-rc4 + - added: 'at' now supported as lang eplist file suffix + - added: extra coulumn 1-3 for optional eplist special fields + +2013-03-11: version 0.0.1-rc3 + - minor bugfixes + +2012-12-30: version 0.0.1-rc2 + - minor bugfixes + +2012-12-19: version 0.0.1-rc1 + - initiale version + * ------------------------------------ + */ diff --git a/Make.config b/Make.config new file mode 100644 index 0000000..1878f85 --- /dev/null +++ b/Make.config @@ -0,0 +1,87 @@ +# Make.config +# +# See the README file for copyright information and how to reach the author. +# +# + +# user defined stuff + +PREFIX = /usr/local +_BINDEST = $(DESTDIR)$(PREFIX)/bin +BINDEST = $(PREFIX)/bin +CACHEDIR = /var/cache/epgd +_PLGDEST = $(DESTDIR)$(PREFIX)/lib/epgd/plugins +PLGDEST = $(PREFIX)/lib/epgd/plugins +CONFDEST = $(DESTDIR)/etc/epgd +HTTPDEST = $(DESTDIR)/var/epgd/www +DEBUG = 1 + +SYSTEMDDEST = $(DESTDIR)/etc/systemd/system +UPSTARTDEST = $(DESTDIR)/etc/init + +# select your init system { none, upstart, systemd } + +INIT_SYSTEM = upstart + +# using systemd to start/stop: + +#SYSD_NOTIFY = 1 + +# ------------------ +# don't touch below + +CC = g++ +doCompile = $(CC) -c $(CFLAGS) $(DEFINES) +doLink = $(CC) $(LFLAGS) +doLib = ar -rs + +PLGSRCDIR = ./PLUGINS +TMPDIR = /tmp + +USELIBXML = 1 +USECURL = 1 +USEJPEG = 1 +USEPYTHON = 1 +USEEPGS = 1 +USEWOL = 1 + +USES = -DUSEUUID -DUSEMD5 -DUSELIBXML -DUSELIBARCHIVE -DUSEJSON -DUSEGUNZIP +DEFINES += -D_GNU_SOURCE -DBINDEST='"$(BINDEST)"' -DTARGET='"$(TARGET)"' -DLOG_PREFIX='""' -DPLGDIR='"$(PLGDEST)"' $(USES) + +ifdef SYSD_NOTIFY + SYSTEMD_VERSION_210 := $(shell expr `pkg-config --modversion libsystemd 2>/dev/null || echo 0` \>= 210) + SYSTEMD_VERSION_209 := $(shell expr `pkg-config --modversion libsystemd 2>/dev/null || pkg-config --modversion libsystemd-daemon 2>/dev/null || echo "0"` \>= 209) + + ifeq "$(SYSTEMD_VERSION_210)" "1" + SYSDLIB_210 = 1 + endif + + ifeq "$(SYSTEMD_VERSION_209)" "1" + SYSDLIB_209 = 1 + endif + +endif + +ifdef USELIBXML + DEFINES += $(shell xml2-config --cflags) $(shell xslt-config --cflags) $(shell python-config --includes) +endif + +ifdef SYSD_NOTIFY + ifdef SYSDLIB_209 + USES += -DSYSDWDIFO + endif + USES += -DUSESYSD +endif + +ifdef DEBUG + CFLAGS += -ggdb -fno-stack-protector -O0 +endif + +CFLAGS += -fPIC -Wextra -Wno-unused-parameter -Wreturn-type -Wall -Wno-parentheses -Wformat -pedantic \ + -Wunused-variable -Wunused-label \ + -Werror=format-security -Wparentheses \ + -Wunused-value -Wunused-function -Wno-long-long \ + -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 + +%.o: %.c + $(doCompile) -o $@ $< diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b7a7406 --- /dev/null +++ b/Makefile @@ -0,0 +1,268 @@ +# +# Makefile +# +# See the README file for copyright information and how to reach the author. +# + +include Make.config + +TARGET = epgd +HTTPTARGET = epghttpd +HISTFILE = "HISTORY.h" + +BASELIBS = -lrt -lz -larchive -ldl -lcrypto -luuid +BASELIBS += $(shell mysql_config --libs_r) $(shell python-config --libs) $(shell pkg-config --cflags --libs jansson) + +HLIB = -L./lib -lhorchi +DLIBS = $(HLIB) $(BASELIBS) -lcurl $(shell xml2-config --libs) $(shell xslt-config --libs) -lexslt +HTTPLIBS = $(HLIB) -lmicrohttpd $(BASELIBS) -lcurl $(shell xml2-config --libs) $(shell xslt-config --libs) -lexslt -ljpeg $(shell imlib2-config --libs) +CFLAGS += $(shell mysql_config --include) + +VERSION = $(shell grep 'define _VERSION ' $(HISTFILE) | awk '{ print $$3 }' | sed -e 's/[";]//g') +ARCHIVE = $(TARGET)-$(VERSION) + +LASTHIST = $(shell grep '^20[0-3][0-9]' $(HISTFILE) | head -1) +LASTCOMMENT = $(subst |,\n,$(shell sed -n '/$(LASTHIST)/,/^ *$$/p' $(HISTFILE) | tr '\n' '|')) +LASTTAG = $(shell git describe --tags --abbrev=0) +BRANCH = $(shell git rev-parse --abbrev-ref HEAD) +GIT_REV = $(shell git describe --always 2>/dev/null) + +HLIBDEP = ./lib/libhorchi.a + +export DESTDIR + +ifdef GIT_REV + DEFINES += -DGIT_REV='"$(GIT_REV)"' +endif + +ifdef SYSD_NOTIFY + ifdef SYSDLIB_210 + BASELIBS += $(shell pkg-config --libs libsystemd) + else + BASELIBS += $(shell pkg-config --libs libsystemd-daemon) + endif +endif + +# object files + +OBJS += main.o update.o plugin.o epgdconfig.o channelmap.o series.o svdrpclient.o levenshtein.o episode.o +OBJS += tvdbmanager.o moviedbmanager.o + +OBJS += tools/fuzzy.o tools/stringhelpers.o scraper/thetvdbscraper/thetvdbscraper.o +OBJS += scraper/thetvdbscraper/tvdbseries.o scraper/thetvdbscraper/tvdbmirrors.o +OBJS += scraper/thetvdbscraper/tvdbmedia.o scraper/thetvdbscraper/tvdbactor.o +OBJS += scraper/thetvdbscraper/tvdbepisode.o +OBJS += scraper/themoviedbscraper/themoviedbscraper.o scraper/themoviedbscraper/moviedbmovie.o +OBJS += scraper/themoviedbscraper/moviedbactor.o + +HTTPOBJS += epgdconfig.o webstore.o webdo.o webauth.o webtools.o httpd.o svdrpclient.o + +# rules: + +all: hlib $(TARGET) $(HTTPTARGET) plugins lv + +eptest: eptest.c episode.c + $(CC) $(CFLAGS) $(DEFINES) eptest.c episode.c svdrpclient.c -L./lib -lhorchi $(DLIBS) -o eptst + +hlib: + (cd lib && $(MAKE) lib) + +$(TARGET) : hlib $(OBJS) + $(CC) $(CFLAGS) -rdynamic $(OBJS) $(DLIBS) -o $@ + +$(HTTPTARGET) : hlib $(HTTPOBJS) + $(CC) $(CFLAGS) -rdynamic $(HTTPOBJS) $(HTTPLIBS) -o $@ + +lv: + (cd epglv && $(MAKE)) + +clean: clean-plugins + @-rm -f $(OBJS) $(HTTPOBJS) core* *~ */*~ *.so + @-rm -f scraper/themoviedbscraper/*~ scraper/themoviedbscraper/*~ scraper/thetvdbscraper/*~ + (cd epglv; $(MAKE) clean) + rm -f $(TARGET) $(ARCHIVE).tgz + rm -f $(HTTPTARGET) pytst + rm -f last.json eptst + (cd lib && $(MAKE) clean) + +dist: clean + @-rm -rf $(TMPDIR)/$(ARCHIVE) + @mkdir $(TMPDIR)/$(ARCHIVE) + @cp -a * $(TMPDIR)/$(ARCHIVE) + @tar czf $(ARCHIVE).tgz -C $(TMPDIR) $(ARCHIVE) + @-rm -rf $(TMPDIR)/$(ARCHIVE) + @echo Distribution package created as $(ARCHIVE).tgz + +install: install-epgd install-epglv install-epghttpd + make install-$(INIT_SYSTEM) + +install-epgd: hlib $(TARGET) $(HTTPTARGET) install-scripts install-config install-plugins + install -D $(TARGET) $(_BINDEST)/ + +install-epghttpd: install-http + install -D $(HTTPTARGET) $(_BINDEST)/ + +install-epglv: + (cd epglv; $(MAKE) install) + +install-none: + +install-upstart: + cat contrib/epgd.conf | sed s:"":"$(BINDEST)":g | sed s:"":"$(PLGDEST)":g | install -C -D /dev/stdin $(UPSTARTDEST)/epgd.conf + chmod a+r $(UPSTARTDEST)/epgd.conf + cat contrib/epghttpd.conf | sed s:"":"$(BINDEST)":g | install -C -D /dev/stdin $(UPSTARTDEST)/epghttpd.conf + chmod a+r $(UPSTARTDEST)/epghttpd.conf + +install-systemd: + cat contrib/epgd.service | sed s:"":"$(BINDEST)":g | sed s:"":"$(INIT_AFTER)":g | sed s:"":"$(PLGDEST)":g | install -C -D /dev/stdin $(SYSTEMDDEST)/epgd.service + chmod a+r $(SYSTEMDDEST)/epgd.service + cat contrib/epghttpd.service | sed s:"":"$(BINDEST)":g | install -C -D /dev/stdin $(SYSTEMDDEST)/epghttpd.service + chmod a+r $(SYSTEMDDEST)/epghttpd.service + ifeq ($(DESTDIR),) + systemctl daemon-reload + endif + +cppchk: + cppcheck --language=c++ --template="{file}:{line}:{severity}:{message}" --quiet --force *.c *.h \ + scraper/thetvdbscraper/*.c scraper/thetvdbscraper/*.h scraper/themoviedbscraper/*.c scraper/themoviedbscraper/*.h \ + tools/*.c tools/*.h + +#-------------------------------------------------------- +# dependencies +#-------------------------------------------------------- + +HEADER = lib/db.h lib/common.h lib/config.h epgd.h series.h svdrpclient.h lib/curl.h + +channelmap.o : channelmap.c $(HEADER) +episode.o : episode.c $(HEADER) levenshtein.h + +levenshtein.o : levenshtein.c $(HEADER) levenshtein.h +main.o : main.c $(HEADER) +series.o : series.c $(HEADER) series.h levenshtein.h +svdrpclient.o : svdrpclient.c $(HEADER) svdrpclient.h +update.o : update.c $(HEADER) +plugin.o : plugin.c $(HEADER) +httpd.o : httpd.c $(HEADER) httpd.h +webdo.o : webdo.c $(HEADER) httpd.h +webauth.o : webauth.c $(HEADER) httpd.h +webtools.o : webtools.c $(HEADER) httpd.h + +SCRHEADER = tools/stringhelpers.h lib/curl.h + +tvdbmanager.o : $(SCRHEADER) tvdbmanager.h tvdbmanager.c lib/epgservice.h lib/epgservice.c lib/db.h lib/db.c +moviedbmanager.o : $(SCRHEADER) moviedbmanager.h moviedbmanager.c lib/epgservice.h lib/epgservice.c lib/db.h lib/db.c +scraper/thetvdbscraper/thetvdbscraper.o : $(SCRHEADER) scraper/thetvdbscraper/thetvdbscraper.h scraper/thetvdbscraper/thetvdbscraper.c scraper/thetvdbscraper/tvdbseries.h scraper/thetvdbscraper/tvdbmirrors.h +scraper/thetvdbscraper/tvdbseries.o : $(SCRHEADER) scraper/thetvdbscraper/tvdbseries.h scraper/thetvdbscraper/tvdbseries.c scraper/thetvdbscraper/tvdbmirrors.h scraper/thetvdbscraper/tvdbmedia.h scraper/thetvdbscraper/tvdbactor.h scraper/thetvdbscraper/tvdbepisode.h +scraper/thetvdbscraper/tvdbmirrors.o : $(SCRHEADER) scraper/thetvdbscraper/tvdbmirrors.h scraper/thetvdbscraper/tvdbmirrors.c +scraper/thetvdbscraper/tvdbmedia.o : $(SCRHEADER) scraper/thetvdbscraper/tvdbmedia.h scraper/thetvdbscraper/tvdbmedia.c scraper/thetvdbscraper/tvdbmirrors.h +scraper/thetvdbscraper/tvdbactor.o : $(SCRHEADER) scraper/thetvdbscraper/tvdbactor.h scraper/thetvdbscraper/tvdbactor.c scraper/thetvdbscraper/tvdbmirrors.h +scraper/thetvdbscraper/tvdbepisodes.o : $(SCRHEADER) scraper/thetvdbscraper/tvdbepisode.h scraper/thetvdbscraper/tvdbepisode.c scraper/thetvdbscraper/tvdbmirrors.h +scraper/themoviedbscraper/themoviedbscraper.o : $(SCRHEADER) scraper/themoviedbscraper/themoviedbscraper.h scraper/themoviedbscraper/themoviedbscraper.c scraper/themoviedbscraper/moviedbmovie.h scraper/themoviedbscraper/moviedbactor.h +scraper/themoviedbscraper/moviedbmovie.o : $(SCRHEADER) scraper/themoviedbscraper/moviedbmovie.h scraper/themoviedbscraper/moviedbmovie.c scraper/themoviedbscraper/moviedbactor.h tools/fuzzy.h +scraper/themoviedbscraper/ moviedbactors.o : $(SCRHEADER) scraper/themoviedbscraper/moviedbactor.h scraper/themoviedbscraper/moviedbactor.c +tools/fuzzy.o : tools/fuzzy.h tools/fuzzy.c +tools/stringhelpers.o : tools/stringhelpers.h tools/stringhelpers.c + + +# ------------------------------------------------------ +# Plugins +# ------------------------------------------------------ + +plugins: + @find $(PLGSRCDIR) -maxdepth 1 -type d -name "[a-z0-9]*" -exec \ + $(MAKE) \-\-no-print-directory -C {} \; + +clean-plugins: + @find $(PLGSRCDIR) -maxdepth 1 -type d -name "[a-z0-9]*" -exec \ + $(MAKE) \-\-no-print-directory -C {} clean \; + +install-plugins: plugins + mkdir -p "$(_PLGDEST)" + for i in ${PLGSRCDIR}/*/Makefile; do\ + grep -q "PLUGIN.*=" "$$i" || continue;\ + i=`dirname $$i`;\ + (cd "$$i" && $(MAKE) install);\ + done; + +# ------------------------------------------------------ +# Install +# ------------------------------------------------------ + +install-scripts: + if ! test -d $(_BINDEST); then \ + mkdir -p "$(_BINDEST)" \ + chmod a+rx $(_BINDEST); \ + fi + install -D ./scripts/epgd-*[!~] $(_BINDEST)/ + install -D ./scripts/epgh-*[!~] $(_BINDEST)/ + install -D ./scripts/epgsearchdone.pl $(_BINDEST)/ + +install-http: + (cd "http/" && make install) + +install-config: + if ! test -d $(CONFDEST); then \ + mkdir -p $(CONFDEST); \ + chmod a+rx $(CONFDEST); \ + fi + install --mode=644 -D ./configs/getupdflg.sql $(CONFDEST) + install --mode=644 -D ./configs/getcrosslvr.sql $(CONFDEST) + install --mode=644 -D ./configs/getlvrmin.sql $(CONFDEST) + install --mode=644 -D ./configs/mergeepg.sql $(CONFDEST) + install --mode=644 -D ./configs/reverseepg.sql $(CONFDEST) + install --mode=644 -D ./configs/thetvdbview.sql $(CONFDEST) + install --mode=644 -D ./configs/epg.dat $(CONFDEST) + + for i in ./configs/eventsview*.sql; do\ + if ! test -f "$(CONFDEST)/`basename $$i`"; then\ + install --mode=644 -D "$$i" $(CONFDEST)/; \ + fi;\ + done; + if ! test -f $(CONFDEST)/epgd.conf; then \ + install --mode=644 -D ./configs/epgd.conf $(CONFDEST)/; \ + fi + if ! test -f $(CONFDEST)/recording.py; then \ + install --mode=644 -D ./configs/recording.py $(CONFDEST)/; \ + else \ + install --mode=644 -D ./configs/recording.py $(CONFDEST)/recording.py.dist; \ + fi + if ! test -f $(CONFDEST)/channelmap.conf; then \ + install --mode=644 -D ./configs/channelmap.conf $(CONFDEST)/; \ + fi + +# ------------------------------------------------------ +# Git / Versioning / Tagging +# ------------------------------------------------------ + +vcheck: + git fetch + if test "$(LASTTAG)" = "$(VERSION)"; then \ + echo "Warning: tag/version '$(VERSION)' already exists, update HISTORY first. Aborting!"; \ + exit 1; \ + fi + +push: vcheck + echo "tagging git with $(VERSION)" + git tag $(VERSION) + git push --tags + git push + +commit: vcheck + git commit -m "$(LASTCOMMENT)" -a + +git: commit push + +showv: + @echo "Git ($(BRANCH)):\\n Version: $(LASTTAG) (tag)" + @echo "Local:" + @echo " Version: $(VERSION)" + @echo " Change:" + @echo -n " $(LASTCOMMENT)" + +upd: update + +update: + git pull + @make clean install + restart epgd + restart epghttpd diff --git a/PLUGINS/epgdata/Makefile b/PLUGINS/epgdata/Makefile new file mode 100644 index 0000000..837c3c1 --- /dev/null +++ b/PLUGINS/epgdata/Makefile @@ -0,0 +1,52 @@ +# +# Makefile +# +# See the README file for copyright information and how to reach the author. +# +# + +EPGD_SRC ?= ../.. + +include $(EPGD_SRC)/Make.config + +PLUGIN = epgdata + +SOFILE = libepgd-epgdata.so +OBJS = epgdata.o + +CFLAGS += -I$(EPGD_SRC) + +all: $(SOFILE) + +$(SOFILE): $(OBJS) + $(CC) $(CFLAGS) -shared $(OBJS) $(LIBS) -o $@ + +install: $(SOFILE) install-config + install -D $(SOFILE) $(_PLGDEST)/ + +clean: + @-rm -f $(OBJS) core* *~ *.so + +install-config: + if ! test -d $(CONFDEST); then \ + mkdir -p $(CONFDEST); \ + chmod a+rx $(CONFDEST); \ + fi + if ! test -f $(CONFDEST)/channelmap.conf-epgdata-astra; then \ + install --mode=644 -D ./configs/channelmap.conf-epgdata-astra $(CONFDEST)/; \ + fi + for i in $(wildcard ./configs/epgdata*.xml) $(wildcard ./configs/*.xsl); do\ + if ! test -f "$(CONFDEST)/`basename $$i`"; then\ + install --mode=644 -D "$$i" $(CONFDEST)/; \ + fi;\ + done; + if ! grep -q "^epgdata" $(CONFDEST)/epgd.conf; then \ + cat ./configs/epgd.conf >> $(CONFDEST)/epgd.conf; \ + fi + + +#*************************************************************************** +# dependencies +#*************************************************************************** + +epgdata.o : epgdata.c epgdata.h diff --git a/PLUGINS/epgdata/configs/channelmap.conf-epgdata-astra b/PLUGINS/epgdata/configs/channelmap.conf-epgdata-astra new file mode 100644 index 0000000..7a3af70 --- /dev/null +++ b/PLUGINS/epgdata/configs/channelmap.conf-epgdata-astra @@ -0,0 +1,176 @@ +epgdata:71 = S19.2E-1-1019-10301 // Das Erste HD +epgdata:37 = S19.2E-1-1011-11110 // ZDF HD +epgdata:194 = S19.2E-1-1025-10331 // PHOENIX HD +epgdata:56 = S19.2E-1-1010-11150 // 3sat HD +epgdata:58 = S19.2E-1-1019-10302 // arte HD +epgdata:146 = S19.2E-1-1201-28396 // Einsfestival HD +epgdata:57 = S19.2E-1-1010-11160 // KiKA HD +epgdata:275 = S19.2E-1-1011-11140 // zdf.kultur HD +epgdata:276 = S19.2E-1-1010-11170 // ZDFinfo HD +epgdata:659 = S19.2E-1-1011-11130 // zdf_neo HD + +epgdata:71 = S19.2E-1-1101-28106 // Das Erste +epgdata:37 = S19.2E-1-1079-28006 // ZDF +epgdata:194 = S19.2E-1-1051-28725 // PHOENIX +epgdata:56 = S19.2E-1-1079-28007 // 3sat +epgdata:58 = S19.2E-1-1051-28724 // arte +epgdata:146 = S19.2E-1-1051-28722 // Einsfestival +epgdata:475 = S19.2E-1-1051-28723 // EinsPlus +epgdata:57 = S19.2E-1-1079-28008 // KiKA +epgdata:100 = S19.2E-1-1051-28721 // tagesschau24 +epgdata:275 = S19.2E-1-1079-28016 // zdf.kultur +epgdata:276 = S19.2E-1-1079-28011 // ZDFinfo +epgdata:659 = S19.2E-1-1079-28014 // zdf_neo + +epgdata:38 = S19.2E-1-1089-12003 // RTL Television +epgdata:41 = S19.2E-1-1089-12020 // RTL2 +epgdata:43 = S19.2E-1-1089-12040 // SUPER RTL +epgdata:763 = S19.2E-1-1089-12061 // RTLNITRO +epgdata:39 = S19.2E-1-1107-17500 // SAT.1 +epgdata:774 = S19.2E-1-1107-17504 // SAT.1 Gold +epgdata:40 = S19.2E-1-1107-17501 // ProSieben +epgdata:44 = S19.2E-1-1107-17502 // kabel eins +epgdata:507 = S19.2E-133-33-63 // DMAX +epgdata:694 = S19.2E-133-5-776 // SIXX +epgdata:42 = S19.2E-1-1089-12060 // VOX +epgdata:660 = S19.2E-1-1115-13110 // ServusTV Deutschland +epgdata:64 = S19.2E-133-33-9001 // SPORT1 +epgdata:65 = S19.2E-1-1091-31200 // Eurosport Deutschland +epgdata:66 = S19.2E-1-1089-12090 // n-tv +epgdata:175 = S19.2E-1-1107-17503 // N24 +epgdata:391 = S19.2E-1-1115-13102 // GoTV +// = S19.2E-133-7-65 // DELUXE MUSIC +// = S19.2E-1-1078-28676 // VIVA Germany +// = S19.2E-1-1021-4600 // a.tv + +epgdata:471 = S19.2E-133-1-42 // 13th Street +epgdata:123 = S19.2E-133-17-21 // Beate-Uhse.TV +epgdata:133 = S19.2E-133-17-24 // Classica +epgdata:138 = S19.2E-133-4-14 // Discovery Channel +epgdata:139 = S19.2E-133-17-34 // Disney Channel +epgdata:460 = S19.2E-133-17-26 // Disney Junior +epgdata:657 = S19.2E-133-17-28 // Disney XD +// = S19.2E-133-1-16 // Fox Serie +epgdata:152 = S19.2E-133-17-518 // Goldstar TV +epgdata:154 = S19.2E-133-17-22 // Heimatkanal +epgdata:160 = S19.2E-133-17-19 // Junior +epgdata:627 = S19.2E-133-1-168 // Motorvision TV +epgdata:626 = S19.2E-133-4-12 // NatGeo Wild +epgdata:453 = S19.2E-133-4-13 // National Geographic Channel +epgdata:527 = S19.2E-133-1-27 // RTL Crime +epgdata:529 = S19.2E-133-1-29 // RTL Passion +epgdata:701 = S19.2E-133-10-117 // Sky 3D +epgdata:615 = S19.2E-133-1-23 // Sky Krimi +epgdata:625 = S19.2E-133-4-52 // Spiegel Geschichte +epgdata:472 = S19.2E-133-17-36 // Syfy +epgdata:590 = S19.2E-133-1-50 // TNT Serie + +// = S19.2E-133-13-127 // 13th Street HD +// = S19.2E-133-10-125 // AXN HD +epgdata:490 = S19.2E-133-6-130 // Discovery HD +// = S19.2E-133-11-116 // Disney Channel HD +// = S19.2E-133-14-128 // E! Entertainm. HD +// = S19.2E-133-10-124 // Fox HD +epgdata:632 = S19.2E-133-11-113 // History HD +// = S19.2E-133-6-118 // Nat Geo Wild HD +// = S19.2E-133-13-112 // NatGeo HD +epgdata:762 = S19.2E-133-12-108 // Sky Sport News HD +// = S19.2E-133-12-126 // Syfy HD +// = S19.2E-133-11-123 // TNT Serie HD +// = S19.2E-133-14-101 // Universal HD +epgdata:10058 = S19.2E-133-10-106 // Sky Action HDD +epgdata:10059 = S19.2E-133-12-107 // Sky Hits HD + +epgdata:539 = S19.2E-1-1037-5253 // Animax +// = S19.2E-133-15-37 // AXN Action +epgdata:536 = S19.2E-133-15-57 // Biography Channel +epgdata:127 = S19.2E-133-15-56 // Bloomberg TV +epgdata:531 = S19.2E-133-15-39 // Cartoon Network (S) +// = S19.2E-1-1115-13105 // ESPN America (S) +epgdata:452 = S19.2E-133-15-58 // History +epgdata:492 = S19.2E-1-1107-17506 // kabel eins classics +epgdata:450 = S19.2E-133-15-33 // Kinowelt TV +// = S19.2E-133-15-38 // Romance TV +epgdata:528 = S19.2E-1-1089-12030 // RTL Living +epgdata:766 = S19.2E-1-1015-4701 // SAT.1 emotions +// = S19.2E-1-1107-17505 // ProSieben MAXX +epgdata:633 = S19.2E-133-15-35 // TNT Film (TCM) + +epgdata:631 = S19.2E-133-13-111 // Disney Cinemagic HD +// = S19.2E-133-12-115 // MGM HD +// = S19.2E-133-10-106 // Sky Action HD +epgdata:767 = S19.2E-133-13-110 // Sky Atlantic HD +epgdata:629 = S19.2E-133-6-131 // Sky Cinema HD +// = S19.2E-133-12-107 // Sky Hits HD + +epgdata:610 = S19.2E-133-2-10 // Sky Cinema +epgdata:611 = S19.2E-133-2-11 // Sky Cinema +1 +epgdata:612 = S19.2E-133-2-43 // Sky Cinema +24 +epgdata:630 = S19.2E-133-3-25 // Disney Cinemagic +epgdata:1196 = S19.2E-133-3-515 // MGM +epgdata:613 = S19.2E-133-2-9 // Sky Action +epgdata:617 = S19.2E-133-2-8 // Sky Comedy +epgdata:616 = S19.2E-133-2-20 // Sky Emotion +epgdata:618 = S19.2E-133-3-41 // Sky Hits +epgdata:614 = S19.2E-133-3-516 // Sky Nostalgie +// = S19.2E-133-3-17 // Sky Sport News + +epgdata:784 = S19.2E-133-14-119 // Sport1 US HD +epgdata:621 = S19.2E-133-6-129 // Sky Sport HD 1 +epgdata:697 = S19.2E-133-13-114 // Sky Sport HD 2 +// = S19.2E-133-6-268 // Sky Sport HD 3 +// = S19.2E-133-11-122 // Sport1+ HD +epgdata:619 = S19.2E-133-4-221 // Sky Sport 1 +epgdata:620 = S19.2E-133-4-222 // Sky Sport 2 +epgdata:564 = S19.2E-133-15-59 // sportdigital + +// = S19.2E-133-11-132 // Eurosport HD +// = S19.2E-133-14-109 // Eurosport 2 HD + +epgdata:54 = S19.2E-1-1117-13001 // ORF1 +epgdata:55 = S19.2E-1-1117-13002 // ORF2 +epgdata:757 = S19.2E-1-1115-13101 // ORF III +epgdata:759 = S19.2E-1-1003-13221 // ORF SPORT+ + +epgdata:115 = S19.2E-1-1117-13012 // ATV +epgdata:761 = S19.2E-1-1003-13223 // ATV2 +// = S19.2E-1-1082-20007 // PULS 4 Austria +epgdata:622 = S19.2E-133-1-30 // Sky Sport Austria +// = S19.2E-1-1115-13104 // LT1-OOE +// = S19.2E-1-1115-13111 // ServusTV Oesterreich + +// epgdata:10100 // Sat.1 Emotions HD +epgdata:104 = S19.2E-1-1093-28487 // BR alpha + +// epgdata:1183 = // Animal Planet +// epgdata:211 = // Rhein-Neckar-Fernsehen +// epgdata:266 = // VIVA +epgdata:277 = S19.2E-133-33-51 // Tele 5 +// epgdata:455 = // Fashion TV +// epgdata:465 = // MTV Dance +// epgdata:466 = // MTV Hits UK +// epgdata:468 = // AXN +// epgdata:469 = // Extreme Sports Channel +// epgdata:46 = // WDR +// epgdata:473 = // ESPN Classic +// epgdata:47 = // NDR +epgdata:486 = S19.2E-133-5-1793 // Das VIERTE +// epgdata:48 = // MDR +// epgdata:49 = // HR +// epgdata:504 = // Eurosport 2 +// epgdata:50 = // SWR +// epgdata:51 = // BR +// epgdata:52 = // RBB +// epgdata:537 = // Anixe HD +// epgdata:590 = // TNT Serie + +// epgdata:623 = // Sky Bundesliga +// epgdata:624 = // National Geographic Channel HD +// epgdata:628 = // Sky Select +// epgdata:698 = // SPORT1+ +// epgdata:743 = // Sky Sport HD Extra +// epgdata:756 = // Spiegel TV Wissen +// epgdata:758 = // E! Entertainment + + + diff --git a/PLUGINS/epgdata/configs/epgd.conf b/PLUGINS/epgdata/configs/epgd.conf new file mode 100644 index 0000000..e5c2073 --- /dev/null +++ b/PLUGINS/epgdata/configs/epgd.conf @@ -0,0 +1,10 @@ + +# --------------- +# epgdata plugin +# --------------- + +epgdata.url = http://www.epgdata.com +epgdata.pin = insert-your-pin-here + +# Download timeout in seconds (default 180) +#epgdata.timeout = 180 diff --git a/PLUGINS/epgdata/configs/epgdata-category.xml b/PLUGINS/epgdata/configs/epgdata-category.xml new file mode 100644 index 0000000..c047314 --- /dev/null +++ b/PLUGINS/epgdata/configs/epgdata-category.xml @@ -0,0 +1,143 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +]> + + + + 100 + Spielfilm + Spielfilm + + + 200 + Serie + Serie + + + 300 + Sport + Sport + + + 400 + Show + Show + + + 500 + Information + Information + + + 600 + Musik + Musik + + + 700 + Kinder + Kinder + + \ No newline at end of file diff --git a/PLUGINS/epgdata/configs/epgdata-genre.xml b/PLUGINS/epgdata/configs/epgdata-genre.xml new file mode 100644 index 0000000..ff63eaf --- /dev/null +++ b/PLUGINS/epgdata/configs/epgdata-genre.xml @@ -0,0 +1,507 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +]> + + + + 101 + Verschiedenes + + + 102 + Abenteuer + + + 103 + Action + + + 104 + Dokumentarfilm + + + 105 + Drama + + + 106 + Erotik + + + 108 + Fantasy + + + 109 + Heimat + + + 110 + Humor + + + 112 + Krimi + + + 113 + Kultur + + + 114 + Kurzfilm + + + 115 + Musik + + + 116 + Mystery + Horror + + + 117 + Romantik/Liebe + + + 119 + Science Fiction + + + 121 + Thriller + + + 122 + Western + + + 123 + Zeichentrick + + + 201 + Verschiedenes + + + 202 + Abenteuer + + + 203 + Action + + + 205 + Drama + + + 206 + Erotik + + + 207 + Familie + + + 208 + Fantasy + + + 210 + Humor + + + 211 + Krankenhaus + + + 212 + Krimi + + + 214 + Jugend + + + 216 + Mystery + Horror + + + 218 + Reality + + + 219 + Science Fiction + + + 220 + Soap + + + 221 + Thriller + + + 222 + Western + + + 223 + Zeichentrick + + + 301 + Verschiedenes + + + 331 + Boxen + + + 332 + Eishockey + + + 334 + Fußball + + + 335 + Olympia + + + 336 + Golf + + + 337 + Gymnastik + + + 338 + Handball + + + 339 + Motorsport + + + 340 + Radsport + + + 341 + Tennis + + + 342 + Wassersport + + + 343 + Wintersport + + + 344 + US-Sport + + + 345 + Leichtathletik + + + 346 + Volleyball + + + 347 + Extremsport + + + 348 + Reportagen + + + 401 + Verschiedenes + + + 406 + Erotik + + + 418 + Reality + + + 450 + Comedy + + + 451 + Familien-Show + + + 452 + Spielshows + + + 453 + Talkshows + + + 454 + Gerichtsshow + + + 455 + Homeshopping + + + 456 + Kochshow + + + 457 + Heimwerken + + + 501 + Verschiedenes + + + 560 + Geschichte + + + 561 + Magazin + + + 564 + Gesundheit + + + 565 + Motor + Verkehr + + + 566 + Nachrichten + + + 567 + Natur + + + 568 + Politik + + + 569 + Ratgeber + + + 570 + Reise + + + 571 + Wirtschaft + + + 572 + Wissen + + + 573 + Dokumentation + + + 601 + Verschiedenes + + + 680 + Jazz + + + 681 + Klassik + + + 682 + Musical + + + 683 + Rock + + + 684 + Volksmusik + + + 685 + Alternative + + + 686 + Pop + + + 687 + Clips + + + 688 + Show + + + 689 + Interview + + + 690 + Theater + + + 691 + Kino + + + 692 + Kultur + + + 701 + Verschiedenes + + + 790 + Filme + + + 791 + Nachrichten + + + 792 + Serien + + + 793 + Shows + + + 795 + Zeichentrick + + + 796 + Anime + + \ No newline at end of file diff --git a/PLUGINS/epgdata/configs/epgdata-iso-8859-1.xsl b/PLUGINS/epgdata/configs/epgdata-iso-8859-1.xsl new file mode 100644 index 0000000..24024ac --- /dev/null +++ b/PLUGINS/epgdata/configs/epgdata-iso-8859-1.xsl @@ -0,0 +1,8 @@ + + + + + + diff --git a/PLUGINS/epgdata/configs/epgdata-utf-8.xsl b/PLUGINS/epgdata/configs/epgdata-utf-8.xsl new file mode 100644 index 0000000..96a7b92 --- /dev/null +++ b/PLUGINS/epgdata/configs/epgdata-utf-8.xsl @@ -0,0 +1,8 @@ + + + + + + diff --git a/PLUGINS/epgdata/configs/epgdata.xsl b/PLUGINS/epgdata/configs/epgdata.xsl new file mode 100644 index 0000000..d5795ee --- /dev/null +++ b/PLUGINS/epgdata/configs/epgdata.xsl @@ -0,0 +1,208 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <xsl:value-of select="d19"/> + + + + + Serie + + + + + + + + + + + + + + + + TagesTipp + TopTipp + + + + + + + + + + + + + Sehr empfehlenswert + + + Empfehlenswert + + + Eher durchschnittlich + + + Eher uninteressant + + + + + + + + + + + + + DolbyDigital + Stereo + Zweikanal + + + + + + + + [PrimeTime] + [SchwarzWeiss] + [Untertitel] + [PayTV] + [Hörfilm] + [16:9] + + + + + + + + + + + jpg + + + + + + + + + + + + + + + + + / Allgemein * + / Allgemein ** + / Allgemein *** + / Allgemein **** + / Allgemein ***** + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +02:00 + +01:00 + + + +01:00 + + + + + + + diff --git a/PLUGINS/epgdata/epgdata.c b/PLUGINS/epgdata/epgdata.c new file mode 100644 index 0000000..3cf31ef --- /dev/null +++ b/PLUGINS/epgdata/epgdata.c @@ -0,0 +1,760 @@ +/* + * epgdata.c + * + * See the README file for copyright information + * + */ + +#include +#include + +#include "epgdata.h" + +//*************************************************************************** +// Epgdata +//*************************************************************************** + +Epgdata::Epgdata() + : Plugin() +{ + pxsltStylesheet = 0; + stmtByFileRef = 0; + stmtCleanDouble = 0; + stmtMarkOldEvents = 0; + selectByDate = 0; + selectId = 0; + + pin = 0; + timeout = 3 * tmeSecondsPerMinute; + baseurl = strdup("http://www.epgdata.com"); +} + +Epgdata::~Epgdata() +{ + if (pxsltStylesheet) + xsltFreeStylesheet(pxsltStylesheet); + + delete stmtByFileRef; + delete selectByDate; + delete stmtCleanDouble; + delete stmtMarkOldEvents; + + free(baseurl); + free(pin); +} + +int Epgdata::init(cEpgd* aObject, int aUtf8) +{ + Plugin::init(aObject, aUtf8); + + pxsltStylesheet = loadXSLT(getSource(), confDir, utf8); + + return done; +} + +int Epgdata::initDb() +{ + int status = success; + + // -------- + // by fileref (for pictures) + // select name from fileref + // where source = ? and fileref = ? + + stmtByFileRef = new cDbStatement(obj->fileDb); + + stmtByFileRef->build("select "); + stmtByFileRef->bind("NAME", cDBS::bndOut); + stmtByFileRef->build(" from %s where ", obj->fileDb->TableName()); + stmtByFileRef->bind("SOURCE", cDBS::bndIn | cDBS::bndSet); + stmtByFileRef->bind("FILEREF", cDBS::bndIn | cDBS::bndSet, " and "); + + status += stmtByFileRef->prepare(); + + // --------------- + // (for cleanup double) + // select name from fileref + // where source = ? order by name desc + + stmtCleanDouble = new cDbStatement(obj->fileDb); + + stmtCleanDouble->build("select "); + stmtCleanDouble->bind("NAME", cDBS::bndOut); + stmtCleanDouble->build(" from %s where ", obj->fileDb->TableName()); + stmtCleanDouble->bind("SOURCE", cDBS::bndIn | cDBS::bndSet); + stmtCleanDouble->build(" order by name desc"); + + status += stmtCleanDouble->prepare(); + + // --------- + // select channelid, merge, mergesp from channelmap + // where source = ? and extid = ? + + selectId = new cDbStatement(obj->mapDb); + + selectId->build("select "); + selectId->bind("CHANNELID", cDBS::bndOut); + selectId->bind("MERGESP", cDBS::bndOut, ", "); + selectId->bind("MERGE", cDBS::bndOut, ", "); + selectId->build(" from %s where ", obj->mapDb->TableName()); + selectId->bind("SOURCE", cDBS::bndIn | cDBS::bndSet); + selectId->bind("EXTERNALID", cDBS::bndIn | cDBS::bndSet, " and "); + + status += selectId->prepare(); + + // --------- + // select name, tag from filerf + // where source = 'epgdata' + // and name like ? + + valueName.setField(obj->fileDb->getField("NAME")); + valueNameLike.setField(obj->fileDb->getField("NAME")); + + selectByDate = new cDbStatement(obj->fileDb); + + selectByDate->build("select "); + selectByDate->bind(&valueName, cDBS::bndOut); + selectByDate->bind("FILEREF", cDBS::bndOut, ", "); + selectByDate->build(" from %s where source = '%s' and ", + obj->fileDb->TableName(), getSource()); + selectByDate->bindCmp(0, &valueNameLike, "like"); + + status += selectByDate->prepare(); + +// // -------- +// // update events set delflg = ?, updflg = ?, fileref = ?, updsp = ? +// // where fileref = ? +// // and source = ?; +// // and updflg in (....) + +// valueFileRef.setField(obj->eventsDb->getField("FileRef")); +// stmtSetDelByFileref = new cDbStatement(obj->eventsDb); + +// stmtSetDelByFileref->build("update %s set ", obj->eventsDb->TableName()); +// stmtSetDelByFileref->bind("DelFlg", cDbService::bndIn |cDbService:: bndSet); +// stmtSetDelByFileref->bind("UpdFlg", cDbService::bndIn |cDbService:: bndSet, ", "); +// stmtSetDelByFileref->bind("FileRef", cDbService::bndIn | cDbService::bndSet, ", "); +// stmtSetDelByFileref->bind("UpdSp", cDbService::bndIn | cDbService::bndSet, ", "); +// stmtSetDelByFileref->build( " where "); +// stmtSetDelByFileref->bind(&valueFileRef, cDbService::bndIn |cDbService:: bndSet); +// stmtSetDelByFileref->bind("Source", cDbService::bndIn | cDbService::bndSet, " and "); +// stmtSetDelByFileref->build(" and updflg in (%s)", Us::getDeletable()); + +// status += stmtSetDelByFileref->prepare(); + + // ---------- + // update events + // set updflg = case when updflg in (...) then 'D' else updflg end, + // delflg = 'Y', + // updsp = unix_timestamp() + // where source = '...' + // and (source, fileref) not in (select source,fileref from fileref) + + stmtMarkOldEvents = new cDbStatement(obj->eventsDb); + + stmtMarkOldEvents->build("update %s set ", obj->eventsDb->TableName()); + stmtMarkOldEvents->build("updflg = case when updflg in (%s) then 'D' else updflg end, ", cEventState::getDeletable()); + stmtMarkOldEvents->build("delflg = 'Y', updsp = unix_timestamp()"); + stmtMarkOldEvents->build(" where source = '%s'", getSource()); + stmtMarkOldEvents->build(" and (source, fileref) not in (select source,fileref from fileref)"); + + status += stmtMarkOldEvents->prepare(); + + // ---------- + // if no epgdata entry in fileref read files from FS to table + + int count = 0; + obj->fileDb->countWhere("source = 'epgdata'", count); + + if (!count) + { + char* path = 0; + DIR* dir; + dirent* dp; + + asprintf(&path, "%s/%s", EpgdConfig.cachePath, getSource()); + chkDir(path); + + if (!(dir = opendir(path))) + { + tell(0, "Error: Opening cache path '%s' failed, %s", path, strerror(errno)); + free(path); + return fail; + } + + while ((dp = readdir(dir))) + { + char* fileRef = 0; + char* file = 0; + char* tag = 0; + struct stat sb; + + if (!strstr(dp->d_name, "_de_qy.zip")) + continue; + + asprintf(&file, "%s/%s", path, dp->d_name); + stat(file, &sb); + free(file); + + asprintf(&tag, "%ld", sb.st_size); + asprintf(&fileRef, "%s-%s", dp->d_name, tag); + + // store file and let tag NULL to indicate that processing is needed + + obj->fileDb->clear(); + obj->fileDb->setValue("NAME", dp->d_name); + obj->fileDb->setValue("SOURCE", getSource()); + obj->fileDb->setValue("EXTERNALID", "0"); + obj->fileDb->setValue("FILEREF", fileRef); + obj->fileDb->store(); + + tell(1, "Added '%s' to table fileref", dp->d_name); + free(fileRef); + free(tag); + } + + free(path); + closedir(dir); + } + + return success; +} + +int Epgdata::exitDb() +{ + delete stmtByFileRef; stmtByFileRef = 0; + delete stmtCleanDouble; stmtCleanDouble = 0; + delete selectByDate; selectByDate = 0; + delete selectId; selectId = 0; + delete stmtMarkOldEvents; stmtMarkOldEvents = 0; + + return success; +} + +//*************************************************************************** +// At Config Item +//*************************************************************************** + +int Epgdata::atConfigItem(const char* Name, const char* Value) +{ + if (!strcasecmp(Name, "Url")) { free(baseurl); baseurl = strdup(Value); } + else if (!strcasecmp(Name, "Pin")) { free(pin); pin = strdup(Value); } + else if (!strcasecmp(Name, "Timeout")) { timeout = atoi(Value); } + + else return fail; + + return success; +} + +//*************************************************************************** +// Ready +//*************************************************************************** + +int Epgdata::ready() +{ + static int count = na; + + if (isEmpty(pin)) + return no; + + if (count == na) + { + char* where; + + asprintf(&where, "source = '%s'", getSource()); + + if (obj->mapDb->countWhere(where, count) != success) + count = na; + + free(where); + } + + return count > 0; +} + +//*************************************************************************** +// Process Day +//*************************************************************************** + +int Epgdata::processDay(int day, int fullupdate, Statistic* statistic) +{ + char* directory = 0; + char* fspath = 0; + char* path = 0; // name of the zip file including the path + int haveOneForThisDay = no; + MemoryStruct data; + int fileSize = 0; + char* fileRef = 0; + char* url = 0; + char* logurl = 0; + int load = yes; + char* like = 0; + int bSize = 0; + char entryName[200+TB]; + MemoryStruct uzdata; + // char* oldFileRef = 0; + + int status; + + // path to zip files, url, .. + + asprintf(&directory, "%s/%s", EpgdConfig.cachePath, getSource()); + chkDir(directory); + asprintf(&url, "%s/index.php?action=sendPackage&iOEM=VDR&pin=%s&dayOffset=%d&dataType=xml", baseurl, pin, day); + asprintf(&logurl, "%s/index.php?action=sendPackage&iOEM=VDR&pin=%s&dayOffset=%d&dataType=xml", baseurl, "insert-your-pin-here", day); + + // first get the http header + + data.clear(); + data.headerOnly = yes; + + status = obj->downloadFile(url, fileSize, &data); + + if (status != success || isEmpty(data.name)) + { + tell(1, "Download header for day (%d) at '%s' failed, aborting, got name '%s', status was %d", + day, logurl, data.name ? data.name : "", status); + status = fail; + goto Exit; + } + + tell(2, "Got info for day (%d), file '%s' with tag '%s'", day, data.name, data.tag); + + asprintf(&fileRef, "%s-%s", data.name, data.tag); + asprintf(&path, "%s/%s", directory, data.name); + + // lookup file + + obj->fileDb->clear(); + obj->fileDb->setValue("NAME", data.name); + obj->fileDb->setValue("SOURCE", getSource()); + + // 1:1 match ? + + obj->fileDb->find(); + + asprintf(&like, "%.8s_%%", data.name); + valueNameLike.setValue(like); + free(like); + + // check for update + + if (selectByDate->find()) + { + haveOneForThisDay = yes; + // oldFileRef = strdup(obj->fileDb->getStrValue("FileRef")); + } + + if (haveOneForThisDay && day >= EpgdConfig.upddays) + { + // don't check for update of existing files more than 'upddays' in the future + + tell(2, "Skipping update check of file '%s' for day %d", data.name, day); + + statistic->nonUpdates++; + status = success; + load = no; + } + else if (haveOneForThisDay && obj->fileDb->hasValue("FileRef", fileRef)) + { + tell(2, "Skipping download of day (%d) due to non-update", day); + statistic->nonUpdates++; + status = success; + load = no; + } + + if (!load && !obj->fileDb->getRow()->getValue("Tag")->isNull()) + goto Exit; + + // not exist, update or not processed -> work + + // first check if we have it already on fs + + asprintf(&fspath, "%s/%s", directory, valueName.getStrValue()); + + if (!load && fileExists(fspath)) + { + tell(1, "File '%s' exist, loading from filesystem", fspath); + + obj->loadFromFs(&data, valueName.getStrValue(), getSource()); + + free(fileRef); + free(path); + path = strdup(fspath); + asprintf(&fileRef, "%s-%s", valueName.getStrValue(), data.tag); + + obj->fileDb->clear(); + obj->fileDb->setValue("NAME", valueName.getStrValue()); + obj->fileDb->setValue("SOURCE", getSource()); + } + + free(fspath); + + if (load) + { + tell(0, "Download file: '%s' to '%s", logurl, data.name); + + data.clear(); + + if (obj->downloadFile(url, fileSize, &data, timeout) != success) + { + tell(0, "Download of day (%d) from '%s' failed", day, logurl); + status = fail; + goto Exit; + } + + statistic->bytes += data.size; + statistic->files++; + + // store zip to FS + + obj->storeToFs(&data, data.name, getSource()); + } + + if (data.isEmpty()) + goto Exit; + + // unzip ... + + uzdata.clear(); + + if (unzip(path, /*filter*/ ".xml", uzdata.memory, bSize, entryName) == success) + { + tell(0, "Processing file '%s' for day %d (%d/%d)", + fileRef, day, haveOneForThisDay, load); + + uzdata.size = bSize; + + // store ? + + if (EpgdConfig.storeXmlToFs) + obj->storeToFs(&uzdata, entryName, getSource()); + + // process file .. + + obj->connection->startTransaction(); + + if ((status = processFile(uzdata.memory, uzdata.size, fileRef)) != success) + statistic->rejected++; + + if (!obj->dbConnected()) + { + status = fail; + goto Exit; + } + +// we can use this code instead of "stmtMarkOldEvents" !! +// but we have to complete it like tvm plugin! +// if (haveOneForThisDay && load && strcmp(oldFileRef, fileRef) != 0) +// { +// // mark 'old' entrys in events table as deleted +// // and 'fake' fileref to new to avoid deletion at cleanup + +// tell(0, "Removing events of fileref '%s' for day %d", oldFileRef, day); + +// obj->eventsDb->clear(); +// obj->eventsDb->setValue("DelFlg", "Y"); +// obj->eventsDb->setValue("UpdFlg", "D"); +// obj->eventsDb->setValue("FileRef", fileRef); // fake to new fileref +// obj->eventsDb->setValue("UpdSp", time(0)); +// obj->eventsDb->setValue("Source", getSource()); +// valueFileRef.setValue(oldFileRef); // old fileref +// stmtSetDelByFileref->execute(); +// } + + // Confirm processing of file + + obj->fileDb->setValue("EXTERNALID", "0"); + obj->fileDb->setValue("TAG", data.tag); + obj->fileDb->setValue("FILEREF", fileRef); + obj->fileDb->store(); + + obj->connection->commit(); + } + + Exit: + + // free(oldFileRef); + obj->fileDb->reset(); + selectByDate->freeResult(); + + uzdata.clear(); + free(url); + free(logurl); + free(fileRef); + free(directory); + free(path); + + return status; +} + +//*************************************************************************** +// Process File +//*************************************************************************** + +int Epgdata::processFile(const char* data, int size, const char* fileRef) +{ + xmlDocPtr transformedDoc; + xmlNodePtr xmlRoot; + int count = 0; + + if ((transformedDoc = obj->transformXml(data, size, pxsltStylesheet, fileRef)) == 0) + { + tell(0, "XSLT transformation for '%s' failed, ignoring", fileRef); + return fail; + } + + if (!(xmlRoot = xmlDocGetRootElement(transformedDoc))) + { + tell(0, "Invalid xml document returned from xslt for '%s', ignoring", fileRef); + return fail; + } + + // DEBUG: xmlSaveFile("/tmp/test.xml", transformedDoc); + + for (xmlNodePtr node = xmlRoot->xmlChildrenNode; node && obj->dbConnected(); node = node->next) + { + char* prop = 0; + tEventId eventid; + char* extid = 0; + + // skip all unexpected elements + + if (node->type != XML_ELEMENT_NODE || strcmp((char*)node->name, "event") != 0) + continue; + + // get/check eventid + + if (!(prop = (char*)xmlGetProp(node, (xmlChar*)"id")) || !*prop || !(eventid = atoll(prop))) + { + xmlFree(prop); + tell(0, "Missing event id, ignoring!"); + continue; + } + + xmlFree(prop); + + // get/check provider id + + if (!(prop = (char*)xmlGetProp(node, (xmlChar*)"provid")) || !*prop || !atoi(prop)) + { + xmlFree(prop); + tell(0, "Missing provider id, ignoring!"); + continue; + } + + extid = strdup(prop); + xmlFree(prop); + + obj->mapDb->clear(); + obj->mapDb->setValue("EXTERNALID", extid); + obj->mapDb->setValue("SOURCE", getSource()); + free(extid); + + for (int f = selectId->find(); f; f = selectId->fetch()) + { + int insert; + const char* channelId = obj->mapDb->getStrValue("CHANNELID"); + + // create event .. + + obj->eventsDb->clear(); + obj->eventsDb->setBigintValue("EVENTID", eventid); + obj->eventsDb->setValue("CHANNELID", channelId); + + insert = !obj->eventsDb->find(); + + obj->eventsDb->setValue("SOURCE", getSource()); + obj->eventsDb->setValue("FILEREF", fileRef); + + // auto parse and set other fields + + obj->parseEvent(obj->eventsDb->getRow(), node); + + // ... + + time_t mergesp = obj->mapDb->getIntValue("MERGESP"); + long starttime = obj->eventsDb->getIntValue("STARTTIME"); + int merge = obj->mapDb->getIntValue("MERGE"); + + // store .. + + if (insert) + { + // handle insert + + obj->eventsDb->setValue("VERSION", 0xFF); + obj->eventsDb->setValue("TABLEID", 0L); + obj->eventsDb->setValue("USEID", 0L); + + if (starttime <= mergesp) + obj->eventsDb->setCharValue("UPDFLG", cEventState::usInactive); + else + obj->eventsDb->setCharValue("UPDFLG", merge > 1 ? cEventState::usMergeSpare : cEventState::usActive); + + obj->eventsDb->insert(); + } + else + { + if (obj->eventsDb->hasValue("DELFLG", "Y")) + obj->eventsDb->setValue("DELFLG", "N"); + + if (obj->eventsDb->hasValue("UPDFLG", "D")) + { + if (starttime <= mergesp) + obj->eventsDb->setCharValue("UPDFLG", cEventState::usInactive); + else + obj->eventsDb->setCharValue("UPDFLG", merge > 1 ? cEventState::usMergeSpare : cEventState::usActive); + } + + obj->eventsDb->update(); + } + + obj->eventsDb->reset(); + count++; + } + } + + selectId->freeResult(); + + xmlFreeDoc(transformedDoc); + + tell(2, "XML File '%s' processed, updated %d events", fileRef, count); + + return success; +} + +//*************************************************************************** +// Get Picture +//*************************************************************************** + +int Epgdata::getPicture(const char* imagename, const char* fileRef, MemoryStruct* data) +{ + int fileSize = 0; + char* path = 0; + char entryName[200+TB]; + + data->clear(); + + // lookup file information + + obj->fileDb->clear(); + obj->fileDb->setValue("FILEREF", fileRef); + obj->fileDb->setValue("SOURCE", getSource()); + + if (stmtByFileRef->find()) + asprintf(&path, "%s/epgdata/%s", EpgdConfig.cachePath, + obj->fileDb->getStrValue("Name")); + + stmtByFileRef->freeResult(); + + if (!path) + { + tell(0, "Error: No entry with fileref '%s' to lookup image '%s' found", + fileRef, imagename); + return 0; + } + + if (unzip(path, imagename, data->memory, fileSize, entryName) == success) + { + data->size = fileSize; + tell(2, "Unzip of image '%s' succeeded", imagename); + } + + free(path); + + return fileSize; +} + +int Epgdata::cleanupAfter() +{ + const char* ext = ".zip"; + struct dirent* dirent; + DIR* dir; + char* pdir; + int count = 0; + char* last = 0; + + // cleanup *.zip in FS cache ... + + // remove old versions for each day + + obj->fileDb->clear(); + obj->fileDb->setValue("SOURCE", getSource()); + + for (int f = stmtCleanDouble->find(); f; f = stmtCleanDouble->fetch()) + { + const char* name = obj->fileDb->getStrValue("NAME"); + + if (last && strncmp(name, last, 8) == 0) + { + char* where; + tell(1, "Remove old epgdata file '%s' from table", name); + asprintf(&where, "name = '%s'", name); + obj->fileDb->deleteWhere("%s", where); + free(where); + } + + free(last); + last = strdup(name); + } + + free(last); + stmtCleanDouble->freeResult(); + + // mark wasted events (delflg, ...) + + stmtMarkOldEvents->execute(); + + // cleanup filesystem, remove files which not referenced in table + + asprintf(&pdir, "%s/%s", EpgdConfig.cachePath, getSource()); + + if (!(dir = opendir(pdir))) + { + tell(1, "Can't open directory '%s', '%s'", pdir, strerror(errno)); + free(pdir); + + return done; + } + + tell(1, "Starting cleanup of epgdata zip's in '%s'", pdir); + + free(pdir); + + while ((dirent = readdir(dir))) + { + // check extension + + if (strncmp(dirent->d_name + strlen(dirent->d_name) - strlen(ext), ext, strlen(ext)) != 0) + continue; + + // lookup file + + obj->fileDb->clear(); + obj->fileDb->setValue("NAME", dirent->d_name); + obj->fileDb->setValue("SOURCE", getSource()); + + if (!obj->fileDb->find()) + { + asprintf(&pdir, "%s/%s/%s", EpgdConfig.cachePath, getSource(), dirent->d_name); + + if (!removeFile(pdir)) + count++; + + free(pdir); + } + + obj->fileDb->reset(); + } + + closedir(dir); + + tell(1, "Cleanup finished, removed (%d) epgdata files", count); + + return success; +} + +//*************************************************************************** + +extern "C" void* EPGPluginCreator() { return new Epgdata(); } diff --git a/PLUGINS/epgdata/epgdata.h b/PLUGINS/epgdata/epgdata.h new file mode 100644 index 0000000..0bb0d88 --- /dev/null +++ b/PLUGINS/epgdata/epgdata.h @@ -0,0 +1,52 @@ +/* + * epgdata.h + * + * See the README file for copyright information + * + */ + +#include "epgd.h" + +//*************************************************************************** +// Epgdata +//*************************************************************************** + +class Epgdata : public Plugin +{ + public: + + Epgdata(); + virtual ~Epgdata(); + + int init(cEpgd* aObject, int aUtf8); + int initDb(); + int exitDb(); + int atConfigItem(const char* Name, const char* Value); + + const char* getSource() { return "epgdata"; } + + int getPicture(const char* imagename, const char* fileRef, MemoryStruct* data); + int processDay(int day, int fullupdate, Statistic* statistic); + int cleanupAfter(); + int ready(); + + protected: + + int processFile(const char* data, int size, const char* fileRef); + + cDbValue valueNameLike; + cDbValue valueName; + cDbValue valueFileRef; + cDbStatement* stmtByFileRef; + cDbStatement* stmtCleanDouble; + cDbStatement* selectId; + cDbStatement* selectByDate; + cDbStatement* stmtMarkOldEvents; + xsltStylesheetPtr pxsltStylesheet; + + // config + + char* baseurl; + int timeout; + char* pin; +}; diff --git a/PLUGINS/epgdata/scripts/getepgdataids b/PLUGINS/epgdata/scripts/getepgdataids new file mode 100755 index 0000000..898a647 --- /dev/null +++ b/PLUGINS/epgdata/scripts/getepgdataids @@ -0,0 +1,37 @@ + +path="/tmp/epgdata/" +file=$path/"info.zip" + +mkdir -p $path + +cd $path +rm -f * + +wget "http://www.epgdata.com/index.php?action=sendInclude&iOEM=&pin=XYZ&dataType=xml" -q -O $file + +unzip $file > /dev/null 2>&1 +rm $file + +chanfile="channel_y.xml" + +cat $chanfile | while read line; do + + if [[ ${line} =~ "" ]]; then + + chan=${line#*>} + chan=${chan%<*} + + else + + if [[ ${line} =~ "" ]]; then + + id=${line#*>} + id=${id%<*} + + echo "epgdata:$id // $chan" + + fi + + fi + +done | sort diff --git a/PLUGINS/epgdata/scripts/getincludes b/PLUGINS/epgdata/scripts/getincludes new file mode 100755 index 0000000..120f1c1 --- /dev/null +++ b/PLUGINS/epgdata/scripts/getincludes @@ -0,0 +1,6 @@ + +rm -f include.zip +wget "http://www.epgdata.com/index.php?action=sendInclude&iOEM=&pin=&dataType=xml" -q -O include.zip +unzip include.zip +rm -f include.zip + diff --git a/README b/README new file mode 100644 index 0000000..fd0ef7a --- /dev/null +++ b/README @@ -0,0 +1,387 @@ +----------------------------------------------------------------------------------- +- epgd +- +- This daemon is used to download EPG data from the internet and manage it in a mysql database. +- +- Written by: C++/SQL - Jörg Wendel (vdr at jwendel dot de) +- SQL/Procedures - Christian Kaiser +- Documentation - Ingo Prochaska +- +- Homepage: http://projects.vdr-developer.org/projects/vdr-epg-daemon +- Source-code: http://projects.vdr-developer.org/git/vdr-epg-daemon.git +- +- This software is released under the GPL, version 2 (see COPYING). +- Additionally, compiling, linking, and/or using the OpenSSL toolkit in +- conjunction with this software is allowed. +----------------------------------------------------------------------------------- + +Contents: +--------- + +Contents +Description +EPG Merge +Get the source from git +Requirements +MySQL Setup +epgd Installation +epgd Configuration +Starting epgd and init-Scripts +Upgrade from older versions +MySQL Hints +Considerations + + +Description: +------------ + +epgd is part of the double team epgd+epg2vdr to effectively retrieve, store and import epg data to vdr. It is designed to handle large amount of data and pictures in a distributed environment with one epg-server and many possible vdr-clients - therefore it relies on mysql. + +Though it is possible to use epgd alone with mysql it only makes sense to use it as backend to the vdr-plugin epg2vdr. That being said you need to install, setup and configure mysql, epgd and epg2vdr in order to get a working environment. + + +EPG Merge: +---------- + + The DVB and external events will be merged for the next 72 hours, DVB EPG is the main event provider which will + be enhanced by the external EPG and series data from constabel.net. + If events can be merged, just starttime, duration and vps-flag of the DVB event will be used + from external provider. The epgd can mix events with up to 20 minutes difference of the start time + depending on title and duration. If DVB and external EPG can't be merged (due to late program changes or sg.), + the DVB event will be placed in your EPG to avoid wrong events. + Due to the EPG-merge the x-components delivered by DVB are also available. Notice that they can only be handled for + DVB and merged events, not for events which are only provided by the external source. + The merge behavior is configured in the channlemap.conf, 0 disables the merge for the corresponding channel, + 1 enables it and with merge 2 the provider ist hold in background and used as fall-back which is used in case + the merge 1 provider delivers poor data. + + +Get the source from git: +------------------------ + +get the source - probably done, when you reading this locally: +git clone git://projects.vdr-developer.org/vdr-epg-daemon.git + + +update the source: +cd /to/your/source/epgd +git pull + +throwing away local changes and update to latest source: +cd /to/your/source/epgd +git checkout -f master +git reset --hard +git pull + + +Requirements: +------------- + + - libarchive + - libcurl 7.10+ + - libxslt 1.1.24+ + - libxml2 + - libmysql >= 5.07 + - libz + - libssl-dev + - uuid uuid-dev + - libjansson4 libjansson-dev + - libmicrohttpd libmicrohttpd-dev (epghttpd) + - libimlib2 libimlib2-dev (epghttpd) + - libjpeg libjpeg-dev (epghttpd) + - python libpython libpython-dev python-dev + - mailutils (deinstall heirloom-mailx) !! + - libsystemd-daemon-dev (if you like to use the systemd status interface) + -> debian previous to 'sid' maybe libsystemd-dev? + + Example for Ubuntu (14.10): + + - libarchive12, libarchive-dev + - libz, libz-dev + - libssl-dev + - libcurl4-nss-dev (oder libcurl3-nss-dev) + - libxslt1.1 libxslt1-dev libxml2 libxml2-dev + - libmysqlclient-dev libmysqlclient18 + - libjpeg62-dev libjpeg62 + - uuid uuid-dev + - libjansson4 libjansson-dev + - libmicrohttpd libmicrohttpd-dev (epghttpd) + - libimlib2 libimlib2-dev (epghttpd) + - libjpeg libjpeg-dev (epghttpd) + - python libpython libpython-dev python-dev + - mailutils (deinstall heirloom-mailx) !! + - libsystemd-daemon-dev (if you like to use the systemd status interface) + +My-SQL Setup: +------------- + +You need a running mysql database. +Consult the manual of your linux-flavour how to install and configure mysql. +Remember to put your db-files in a large enough filesystem: with many channels, +many prefetched days and many pictures you will easily need 3 or more Gb of disk space. +When mysql is up and running you need to prepare the database and +access-rights for use with epgd: + +- login as root: +#> mysql -u root -p + CREATE DATABASE epg2vdr charset utf8; + CREATE USER 'epg2vdr'@'%' IDENTIFIED BY 'epg'; + GRANT ALL PRIVILEGES ON epg2vdr.* TO 'epg2vdr'@'%'; + GRANT ALL PRIVILEGES ON epg2vdr.* TO 'epg2vdr'@'localhost' IDENTIFIED BY 'epg'; + FLUSH PRIVILEGES; + +- make sure the database characterset (character_set_database) is set to latin1, + otherwise the index size will be exeeded, you can adjust the client and session + character sets as you like. + +- adjust the bind address in my.cnf: +adjust the line +bind-address = 127.0.0.1 +in youre my.cnf (mostly found here: /etc/mysql/my.cnf) to the address where +the mysql serve should listen on - Or comment out if it should listen on all interfaces. + +- switch of binary logging: +comment line starting with 'log_bin' in youre my.cnf + +Login as epg2vdr: +----------------- +#> mysql -u epg2vdr -pepg -Depg2vdr +- or remote +#> mysql -u epg2vdr -pepg -Depg2vdr -h + +If you have problems with setting up and granting access rights to your epg2vdr +read "MySQL Hints" near the end of this file. + +- show all users: + use mysql + SELECT * FROM user; + + +Possible Create Index Problems: +------------------------------- +If you get this error on epgd start while epgd is creating indexes and tables: + "Index column size too large. The maximum column size is 767 bytes" +Make sure the server charecter-set is set to latin1, file format is set to BARRACUDA and innodb_large_prefix ist active: + character-set-server = latin1 + innodb_large_prefix = ON + innodb_file_format = BARRACUDA +Remove all other collations from your mysqld config. +We use UTF8 only on client side! + + +epgd Installation: +------------------ + +epgd is source distributed only. So you have to build your binary and make some +adjustments to your system. So we try to help with some stuff in the contrib directory, +it's not a bad idea to learn something about your linux's init-system and init-scripts. + +- Unpack +- Modify Make.config (BINDEST, PLGDEST and INIT_SYSTEM) to meet your local systems requirements +- Call "make" +- Call "make plugins" +- Call "make install" +- Call "make install-plugins" +- Create directory /etc/epgd +- cp configs/* /etc/epgd +- merge(*) the config parts of the epgd plugins (./PLUGINS/*/configs) to /etc/epgd + -> merge /etc/epgd/channelmap.conf and /etc/epgd/epgd.conf + -> copy ./PLUGINS/*/configs/*.xsl to /etc/epgd +- modify config (/etc/epgd/channelmap.conf and /etc/epgd/epgd.conf) like your needs +- Create the database (see below) +- Install epglv - the lib installed by make install and the functions will installed + as described in epglv/README) +- Start epgd (see below) + +If you don't know how to merge you can start of with + +#> cat ./PLUGINS/*/configs/channelmap.conf >>/etc/epgd/channelmap.conf +#> cat ./PLUGINS/*/configs/epgd.conf >>/etc/epgd/epgd.conf + +This is only true if you use all plugins. If you use only one of them replace "*" with the plugin you use. + +Look carefully through your generated files! + + +epgd Update: +------------ + +If a table alter is required the epgd alter and create tables automatically after start (if the new, modified epg.dat + is installed in the config directory). Therefore always start the epgd before starting the epghttpd and the VDR after an update. + Please be patient, the alter can take some time depending on the size of the table! + +Starting epgd and init-Scripts: +------------------------------- + +There are many ways to start epgd. For a first try or debugging sessions you may want to start it simply by typing at the root command-prompt (paths have to be adjusted according to your changes to BINDEST and PLGDEST in Make.config): + +#> export LANG="de_DE.UTF-8" +#> ulimit -c unlimited #so you can torture the developers with back traces +#> /usr/local/bin/epgd -n -p /usr/local/lib/epgd/plugins + +epgd is configured in /etc/epgd/epgd.conf. But you can overwrite the following options on the command line: + + -n don't daemonize + -t log to stdout + -c use config in + -p load plugins from + -l set log level + +For production use you should start epgd after net- and mysql services via your init-system. Some start-scripts have been put to ./contrib hopefully serving your needs (or at least giving you an idea of how to proceed). + + +epgd Configuration: +------------------- + + DbHost = + ip/name of mysql server host (default localhost) + + DbPort = + port of the mysql server (default 3306) + + DbName = + name of the database (default epg2vdr) + + DbUser = + database user (default epg2vdr) + + DbPass = + database password (default epg) + + DaysInAdvance = + (default 8) + Download (insert) EPG information for the next # days + + DaysToUpdate = + (default 2) + Update # already insert days + + UpdateTime = 0 + Perform automatic update every # hours (default: 2 hours) + + XmlStoreToFs = + Store XML files to the filesystem, for debugging (default 0) + + GetEpgImages = + (default 0) + Download images with the EPG information + + NetDevice = + (default fist device) + network device of epgd (not used this time) + + HttpDevice + (default all devices) + epghttpd listen on this decive + + MaxImagesPerEvent + How many pictures per event should be downloaded + + EpgImageSize = + 0 = 174x130 + 1 = 329x245 + 2 = 525x400 + + CachePath = + path to cache of the xml files if XmlStoreToFs or SeriesStoreToFs enabled (default /var/cache/epgd) + + SeriesEnabled + get series from eplists.constabel.net (default 1) + + SeriesPort + (default 2006) + + SeriesStoreToFs + (default 0) + + SeriesUrl + (default eplists.constabel.net) + + ScrapEpg (default 1) + scrap EPG content 0/1 + + ScrapRecordings (default 1) + scrap recordings 0/1 + + EpgView (default eventsview.sql) + use this if you want to design your own view for detailed EPG views and live-plugin + eventsview.sql can be overwritten on updates, so use a different name + + EpgViewWeb (default eventsviewplain.sql) + use this if you want to design your own view for detailed EPG views in WebIF + eventsviewplain.sql can be overwritten on updates, so use a different name + + CheckInitial = 1 (default 1) + enable or disable the initial update of your external EPG provider after starting epgd + + UpdateThreshold = 500 (default 500) + call merging of DVB and external EPG after DVB changes and update clients + + UseProxy + Enable HTTP Proxy (default 0) + + HttpProxy + Name of the proxy + + UserName + Username of your proxy + + Password + Password of your proxy + + Loglevel # + Logging level 1-5 (Errors, Infos, Debug ...) (default 1) + +When choosing a loglevel consider carefully the impact on i/o-performance of your system. If you are using some kind of pattern driven logfile parsing software like logchecker you may want to use ./contrib/epgd.ignore + +HINTS / PITFALLS: +----------------- + +- the recordings hosted on a central storage (NAS, ...) and the vdr2epg toggle some recordings in the table round robin without any changes on it + this can occor if: + - the VDRs use different options for the filesystem (--vfat and/or --dirnames) + - the VDRs use different cahracter encoding and language settings + +--vfat bzw. --dirnames + +MYSQL HINTS: +----------- + - If you cannot figure out why you get Access denied, remove all entries from the user table + that have Host values with wildcards contained (entries that match '%' or '_' characters). + A very common error is to insert a new entry with Host='%' and User='some_user', + thinking that this allows you to specify localhost to connect from the same machine. + The reason that this does not work is that the default privileges include an + entry with Host='localhost' and User=''. Because that entry has a Host value 'localhost' + that is more specific than '%', it is used in preference to the new entry when connecting + from localhost! The correct procedure is to insert a second entry with Host='localhost' + and User='some_user', or to delete the entry with Host='localhost' and User=''. + After deleting the entry, remember to issue a "FLUSH PRIVILEGES" statement to reload the grant tables. + + + - *ATTENTION* if you have binary-logging (log_bin) enabled! + disable it OR add log-bin-trust-function-creators to your configuration: + > echo "log-bin-trust-function-creators = 1" >> /etc/mysql/my.cnf + > restart the database + + +Considerations: +--------------- + +By design epgd can handle multiple clients. If you are looking for a solution for your vdr-network plan your implementation +carefully. Which clients should be able to connect? Which epg-solution is in use on each client? Has any of the clients +patches or plugins running manipulating the epg? And now the most important hint: read the epg2vdr README before you continue. + +epgd can generate large amounts of data, as well db-data and logging-data - so don't be surprised. +Manipulating data (read, write, move around) does not only need appropriate disk space, +but also appropriate I/O-performance. + +If you run into problems and want to start from a clean base, stop epgd and drop all data +(take a look at the scripts in ./scripts) and restart epgd. + + +============ +HOWTOs +============ + +select starttimes from table timers: + select from_unixtime(day), starttime, from_unixtime(_starttime) as 'event starttime', from_unixtime(day + ((starttime % 100) * 60) + ((starttime div 100) * 60 * 60)) as 'timer starttime' from timers; diff --git a/README-import-epgsearch b/README-import-epgsearch new file mode 100644 index 0000000..cb95526 --- /dev/null +++ b/README-import-epgsearch @@ -0,0 +1,62 @@ +---------------------------------------------------------------------------- + Übernehmen der 'erledigten Aufnahmen' von epgsearch aus epgsearchdone.data +---------------------------------------------------------------------------- + +1.) epgsearchdone.data einlesen: + +epgsearchdone.pl epgsearchdone.data loaddone + + +2.) die Datensätze gegen die Episodentabelle abgleichen: + +update + timersdone t, + (select distinct compname,comppartname,compshortname,lang,season,part from episodes) e +set + t.episodecompname = e.compname, + t.episodecomppartname = e.comppartname, + t.episodecompshortname = e.compshortname, + t.episodelang = e.lang, + t.episodeseason = e.season, + t.episodepart = e.part +where + t.comptitle=e.compname and + t.compshorttext=e.comppartname and + t.episodecompname is null and + t.source = 'epgsearch' and + t.state = 'R'; + + +3) optional ein paar Leichen löschen, also aufgenommene Events ohne brauchbaren Titel oder Untertitel (sofern man nur Serien übernehmen möchte): + +delete from + timersdone +where + source = 'epgsearch' and + state = 'R' and + ( + comptitle = compshorttext or + ifnull(comptitle,'') = '' or + ifnull(compshorttext,'') = '' + ); + + +4) Testen der Treffer mit: + +select + count(*),case when episodecompname is not Null then 'match' else 'no match' end status +from + timersdone group by case when episodecompname is not Null then 'yes' else 'no' end; + + +5) bei Bedarf Backup der tabelle erstellen: + +epgsearchdone.pl epgddone.dump writedump + + +6) Zurückspielen des Backup: + +epgsearchdone.pl epgddone.dump loaddump + + Wenn die Tabelle nicht leer ist, vorher truncaten, sonst hagelt es Primärschlüsselverletzungen: + truncate table timersdone; diff --git a/TODO b/TODO new file mode 100644 index 0000000..9560a0d --- /dev/null +++ b/TODO @@ -0,0 +1,187 @@ +----------------------------------- + Legende +----------------------------------- + ++ pending +- in Arbeit += erledigt oder nichts zu tun + +Erste Spalte 'Backend', Zweite Spalte 'Frontend' + +----------------------------------- + TODOs +----------------------------------- + ++= bei Nachrichten messages Tabelle optional, konfigurierbar zusätzlich Email Notifications versenden ++= Timer Job Check im epg2vdr geht nicht wenn epgd busy ++= Suchtimer Typ 'Umschalten' fertig stellen ++= Schutz vor 'SQL-Injection' ++= Format Erkennung (HD,SD) für Autotimer entspr. der konfigurierten Reihenfolge priorisieren ++= im Programm OSD Menü nach dones suchen ++= am OSD Sendung als „bereits aufgezeichnet“ markieren ++= am OSD aus Event einen Suchtimer erstellen lassen ++= auf events Tabelle scrap stamp mit constable stamp vergleichen und durch setzen von scrnew neu scrapen lassen ++= 'nach'-scrapen der Aufnahmen verbessern (auf neue Daten der recordinglist stützen) view von Christian + +=+ Anzeige des verbleibenden Platzes für Aufnahmen in HH:MM +=+ Timerliste nach VDR's gruppieren +=+ Kanallisten verwalten und bei Timern usw. als Auswahl anbieten +=+ Zeit/Pixelverhältnis in Magazinansicht einstellbar machen +=+ Suchtimer löschen als eigenen Dialog anzeigen und alle zugeordneten Timer anzeigen, damit die auch in einem + Rutsch mitgelöscht werden können. +=+ am Suchtimer im WEB die erledigten Timer aus timersdone anzeigen (ist schon über 'testen' erledigt?) + dabie die Option zum einzeln oder komplett löschen lassen anbieten +=+ Channel/Aufnahme im Browser abspielen (ggf. auch streamen) +=+ Magazineansicht: rechte Scrollbar sichtbar machen. +=+ Hilfe Seiten fürs Web + +++ WEBIF Seite zum bearbeiten def Aufnahmen (Genre, Category, Serien-Titel, User-ScrapIDs) + Bearbeitung in in Gruppen also mit einem Click für alle ausgewählten, für ganze Folgen einer Serie oder Staffel +++ logoSuffix: mehrere komma getrennt erfassen und im Backend dann in dieser Reihenfolge suchen (als Standard SVG,PNG???) +++ Button zum aktualisieren der bestehenden Timer nach Anpassung der recordings.py +++ im WebIf Sendung als „bereits aufgezeichnet“ markieren +++ channlemap im web bearbeiten (Auswahl pro User ermöglichen) +++ data/status zur Anzeige von Version und Status des epgd im webif +++ Beim löschen eines Timers fragen ob die passenden Einträge aus der timersdone mit gelöscht werden sollen +++ Suchtimer: Checkbox für "Neu" bzw. "Erstausstrahlung" +++ Titel (Namen des Aufzeichnung) im Timer-Dialog bearbeitbar machen + -> http://www.vdr-portal.de/board1-news/board2-vdr-news/p1269286-announce-easteregg-epgd-epghttpd-1-0-0-beta1-jetzt-mit-web-serientimer-unterst%C3%BCtzung/#post1269286 + +-------------------------------------------------------- +Baucht dass wirklich jemand - von wem war der Request? +-------------------------------------------------------- + ++= Suchtimer am OSD anlegen und bearbeiten -> ist das wirklich nötig? +++ hits bei Suchtimern aufteilen nach total und aktiven Timern +++ Suchtimer auf einzelne VDR begrenzen, dies soll Suchtimer mit retundanten Aufnahmen (eine je VDR) ermöglichen, + dazu muss je VDR ein separater Suchtimer angelegt werden. + - Flag 'LOCAL' am Suchtimer und VDRUUID in die TIMERSDONE aufnehmen +++ Wie erkennen wir sofortaufnahmen und timeshifting? Anderen Status geben und dann im Web nicht anzeigen + oder sollen wir dise gar nicht erst in die DB schreiben? + -> wo/warum würden diese in der Anzeige stören + +----------------------------------- + Fertig: +----------------------------------- + +== Nachrichten Tabelle die im WEB angezeigt wird +== bei entfernten (gelöschten) events + -> bei manuellen Timern per email warnen (aktuell per message ans WEBIF) + -> bei Auto-Timer canceln damit er neu angelegt wird und optional Mail Nachricht +== timer automatisch verschieben (nachziehen) +== falsch konfiguriertes 'http:://' bzw. 'https:://' präfix automatisch aus seriesUrl löschen +== epg2vdr und WEB um Favoriten Suche erweitern + -> Favoriten im WEB konfigurierbar (Zeitraum bis, Kategorie, TagesTipp, TopTipp) +== WOL für VDRs bei anstehenden Timern x Tage vor dem Event +== im WebIf Magazine Ansicht farblich hinterlegte Balken über die gesammte Bildschirmbreite legen, die den quicklinks-zeiten entsprechen +== im WEBIF bei schmalen Displays (Handy) ggf. rechte Zeitspalte im Magazin ausblenden +== Datepicker: wenn die aktuelle Zeit um Mitternacht ist, bei den quicklinks ggf. den Tag auch mit verändern +== In der Autotimer-Liste im WEB Knopf für "Suche" anbieten (ohne den Dialog öffnen zu müssen) +== Entweder im Frontend Nextdays (im Backend bereits implementiert) implementieren +== Timer/Suchtimer Typen einbauen (Aufnahme/Suche/Umschalten) +== Im Suichtimer-Dialog 'Folgentitel' ind 'Serie' oder 'Serientitel' umbenennen +== Default Netzwerk Interface sollte nach Plain Start ohne Config nicht + auf 'lo' stehen wenn es noch ein anderes Device gibt + +== Suchtimer Optionen: + unter "Erweiterte EPG Daten" gruppiert (zum aufklappen) kommt: + - Episode (wird in EPISODENAME gesucht oder wenn dort leer in TITLE) + -> suchtimerfeld wird "EPISODENAME" + - Staffel und Staffelfolge sind wir dran -> Dirk nenne am besten das Feld im Web auch Staffelfolge?! + -> suchtimerfelder sind "SEASON" und "SEASONPART" + - Kategorie (Komma getrennte Liste) z.B. "Spielfilm,Serie" + -> suchtimerfeld: "CATEGORY" + - Genre " 'Krimi','Action' " (GENRE) -> wie Kategorie + - Jahr (Format analog Staffel z.B. "-2004" oder "2010-2012") + -> suchtimerfeld: "YEAR" + - Tipp + -> suchtimerfeld: "TIPP" + - eine Checkbox für passt auch wenn die Erweiterten Daten bei einem Event nicht vorhanden sind + -> suchtimerfeld: "NOEPGMATCH" + +== Kanal-Ausschussliste für Suchtimer +== HD Erkennung für Autotimer anhand des Feldes 'FORMAT' der channelmap +== Suche für 'vorhandene Timer' im WEB einbauen +== Sortierung der Events für die Suchtimer-Matches um den Kanal erweitert, + entspr. der im WEB konfigurierten Sortierung der Kanäle +== data/timers Anfrage-Filter um action und notaction und notstate erweitern +== Sortierung der Suchtimer nach HITS ist nicht numerisch +== Sortierung für Aufnahmeliste im WEB +== manuelle timer Anfragen durch das webif in die Vergangenheit im httpd ablehnen +== force des epg seitens des epg2vdr wenn event beim Timer anlegen nicht gefunden werden kann +== Endlose Versuche bei nicht gefundenem Autotimer Event verhindern +== check autotimer update (only perform on change) +== "Aufnahme läuft" Frage beim Timer löschen am OSD funktioniert noch nicht +== im Programm Menü beim toggeln von den Zeiten auf Schedule die aktuelle Position (Sendung) merken +== field owner der Aufnahmen in der tabelle recordinglist aktualisieren wenn im + vdr die 'NAS' Option (useCommonRecFolder) an- bzw ausschaltet wird + -> gelöst durch löschen und neu einlesen der Aufnahmen 'diese' VDR +== Im Programm Menü mit '2' in Aufnahmen suchen +== Wiederholungen anhand der episode Daten (EPISODECOMPSHORTNAME) vermeiden, automatisch sofern + vorhanden statt title + Christain: Du nimmst einfach immer das höherwertigste: + Für den Titel: + "COMPTITLE", => ist das schlechteste + "EPISODECOMPNAME" => ist schon besser + "EPISODECOMPSHORTNAME" => ist das ultimative + Und für die Folge: + "COMPSHORTTEXT", + "EPISODECOMPPARTNAME" => ist das bessere + Also brauchst du drei Knöpfe, nämlich noch einen dritten für die Beschreibung + -> im Web die Knöpfe für Episode und Episodenpart entfernen +== Anzeige des Aufnahmedatums in der Aufnahmeliste im WEB +== episodenfelder in timersdone NULL belassen wenn nicht verfügbar +== Staffel und Folge in timersdone speichern +== gelöschte timer verbleiben in der timersdone in state re'Q'uestet + -> fixed +== Aktualisieren der recordinglist bei löschen eiern Aufnahme prüfen (klappt der trigger im epg2vdr?) + -> ja funktioniert! VDR hat hierfür keine Trigger daher wird es im 5 Minuten Zyklus geprüft :( +== autotimerid in timersdone ablegen +== Kannalnamen zur Anzeige im WEB auch in recordinglist ablegen, Hintergrund, alte Aufnahmen + können auf nicht mehr existierende Kanäle verweisen +== auto-timer soll das nächst-mögliche Event nehmen + -> ist/war bereits so +== Konfig am epg2vdr ob VDR im Web sein soll (also Timer und Aufnahmen im Web veröffentlichen möchte), + Neues Feld in vdrs Tabelle 'shareinweb' + Wenn nicht 'shareinweb' auch keine Auto-Timer etc. pp. (vdr nicht im WEBIF zu sehen. + Lösung, für dies shareinweb = no VDRS gilt: + -> ihre timer stehen nicht in der timers Tabelle + -> sie lesen und pflegen weder timerdistribution noch timersdone + -> sie werden bei data/vdrs nicht mehr ausgeliefert + -> ihre Aufnahmen werden bei data/recordins nicht ausgeliefert + -> sie erhalten keine svdrp Trigger vom epghttpd (alias WEB) + -> sie legen weiterhin (wegen scraper) ihre Aufnahmen in recordingslist ab! +== Obsolete Kanäle automatisch via epg2vdr deaktivieren (vdr Feature und bei m Timer anlegen erkennen) + -> das VDR feature hängt lediglich OBSOLETE an den Kanalnamen und ist erst am 2.3.1 verfügbar + Lösung: + == Tabelle channelmap um Fels 'unknownatvdr' erweitert (default null) + == feld wird auf 1 gesetzt wenn der Kanal im handler als OBSOLETE erkannt wird + == dabei wird auch der Neune um OBSOLETE erweiterete Kanalname übernommen + == unknown wird ebenso gesetzt wenn ein VDR beim übernehmen eines Timers feststellt + dass er den Kanal nicht kennt, dann muss der User das im WEB erkennen können + und seine Konfiguration entspr. manuell nacharbeiten (channlelmap.conf, channels.conf's) + == die 'unknownatvdr' Kanäle werden beim Zuweisen der Timer zum VDR nicht mehr berücksichtigt + -> Fehlermeldung : "AUTOTIMER: Skipping hit, channelid '%s' is unknown at least on one VDR!" +== cleanup der tabelle timerdistribution - >löschen alter erfolgreich verteilter + Aufträge (assumed = 'Y') +== generisch die Parameter des epgd im WEB anzeigen, parameter Tabelle um valexp(regulärer Ausdruck) erweitert + Bei valexp = [01] wird eine checkbox angezeigt, sonst ein textfeld mit validierung beim Speichern +== Aufnahme-Dauer in Tabelle in Sekunden (statt Minuten) +== erledigte Timer (timersdone) im web anzeigen +== Sicherheitsabfrage beim löschen von Autotimern und Timern? +== Optische Aufbereitung der Seite 'Timer->Aufträge' + und seite ggf. umbenennen in eine Kurzform für "Anstehende und fehlerhafte Aufträge" + mir fällt nix ein ;) +== Konfig Option am epg2vdr ob vdr im NAS Verbund - wird in vdrs Tabelle ('usecommonrecfolder') gespeichert und + ersetzt Parameter globalRecDir bei Dirk + -> dazu auch Schlüssel der recordinglist auf vdruuid erweitern, + Feld heißt 'owner': leer, wenn vdr im NAS Verbund oder uuid des VDR wenn eigenes Aufnahmeverzeichnis verwendet wird + Feld 'vdruuid' bleibt wie gehabt und zeigt an welcher VDR den Datensatz hinzugefügt hat +== TCC Mails an alle User entspr. derer Konfiguration versenden +== Parameter vor dem speichern anhand der regexp prüfen +== nach Wiederholungen suchen im WEB (alles bei dem Title 1:1 übereinstimmt) -> reicht nicht, + titel ist oft der Serienname, shorttext müsste mit übergeben werden können + => /data/search -> casesensitiv: 1, searchmode: 1, + expression , searchfields: 1, + expression1 <shorttext>, searchfields1: 2 +== Aufnahmen selektierbar machen und dann zum Löschen anbieten diff --git a/alter/alter.sql b/alter/alter.sql new file mode 100755 index 0000000..b306ef5 --- /dev/null +++ b/alter/alter.sql @@ -0,0 +1,9 @@ +#!/bin/bash + +mysql -u epg2vdr -pepg -Depg2vdr -e 'ALTER TABLE events ADD imagecount int(4) DEFAULT Null after extepnum;' +mysql -u epg2vdr -pepg -Depg2vdr -e 'ALTER TABLE events CHANGE shorttext shorttext varchar(300) DEFAULT NULL;' +mysql -u epg2vdr -pepg -Depg2vdr -e 'ALTER TABLE events CHANGE compshorttext compshorttext varchar(300) DEFAULT NULL;' +mysql -u epg2vdr -pepg -Depg2vdr -e 'ALTER TABLE events CHANGE topic topic varchar(500) DEFAULT NULL;' +mysql -u epg2vdr -pepg -Depg2vdr -e 'ALTER TABLE events CHANGE guest guest varchar(500) DEFAULT NULL;' +mysql -u epg2vdr -pepg -Depg2vdr -e "update vdrs set dbapi = 4 where uuid = 'epgd';" + diff --git a/channelmap.c b/channelmap.c new file mode 100644 index 0000000..9629227 --- /dev/null +++ b/channelmap.c @@ -0,0 +1,305 @@ +/* + * channelmap.c + * + * See the README file for copyright information + * + */ + +#include <fstream> +#include <string.h> + +#include "lib/common.h" + +#include "epgd.h" + +//*************************************************************************** +// Load Channelmap +//*************************************************************************** + +int cEpgd::loadChannelmap() +{ + ifstream cmfile; + string s; + size_t p; + int line = 0; + int count = 0; + int status = success; + char* path; + + enum ConfIndex + { + ciSource, + ciExtid, + ciMerge, + ciVps, + + ciCount + }; + + asprintf(&path, "%s/channelmap.conf", confDir); + cmfile.open(path); + + if (cmfile.fail()) + { + tell(0, "Error reading '%s' %s!", path, strerror(errno)); + free(path); + + return fail; + } + + tell(0, "Loading '%s'", path); + + connection->startTransaction(); + + mapDb->clear(); + cDbStatement updateFlag(mapDb); + updateFlag.build("update %s set updflg = 'D'", mapDb->TableName()); + updateFlag.prepare(); + updateFlag.execute(); + + while (!cmfile.eof()) + { + char* left = 0; + char* right = 0; + char* extid = 0; + char* source = 0; + char* pc; + int index; + int vps = no; + int merge = 1; + + getline(cmfile, s); + line++; + + removeChars(s, " \f\n\r\t\v"); + + // remove comments + + p = s.find_first_of("//"); + + if (p != string::npos) + s.erase(p); + + if (s.empty()) + continue; + + // split line at '=' + + p = s.find_first_of("="); + + if ((p == string::npos) || !s.substr(p+1).length()) + { + tell(0, "Error parsing '%s' at line %d!", path, line); + status = fail; + break; + } + + left = strdup(s.substr(0, p).c_str()); + right = strdup(s.substr(p+1).c_str()); + + for (index = 0, pc = strtok(left, ":"); pc; pc = strtok(0, ":"), index++) + { + switch (index) + { + case ciSource: source = strdup(pc); break; + case ciExtid: extid = strdup(pc); break; + case ciMerge: merge = atoi(pc); break; + case ciVps: vps = strchr("1yY", *pc) != 0; break; + } + } + + free(left); + + if (!right || !source || !extid) + { + tell(0, "Error: Syntax error in '%s' at line %d!", path, line); + + free(right); + free(source); + free(extid); + status = fail; + break; + } + + // read channels separated by commas + + for (index = 0, pc = strtok(right, ","); pc; pc = strtok(0, ","), index++) + { + updateMapRow(extid, source, pc, merge, vps); + count++; + } + + free(right); + free(source); + free(extid); + } + + connection->commit(); + cmfile.close(); + free(path); + + tell(0, "%d channel mappings read.", count); + + return status; +} + +//*************************************************************************** +// Update Map Row +//*************************************************************************** + +int cEpgd::updateMapRow(char* extid, const char* source, const char* chan, + int merge, int vps) +{ + int insert = no; + int changed = 0; + + // updflg: + // I - insert + // U - updated + // S - stay unchanged + // D - no more used -> delete + + // force id of vdr source to 0 + + if (!isZero(extid) && strcmp(source, "vdr") == 0) + { + tell(1, "Force extid of for channel '%s' to 0, due to source 'vdr'", chan); + free(extid); + extid = strdup("0"); + merge = 0; + } + else if (strcmp(source, "vdr") == 0) + { + merge = 0; + } + else if (isZero(extid) && strcmp(source, "vdr") != 0) + { + tell(1, "Ignoring config with empty extid for channel '%s', '%s'", + chan, source); + return fail; + } + + // + + mapDb->clear(); + mapDb->setValue("EXTERNALID", extid); + mapDb->setValue("CHANNELID", chan); + mapDb->setValue("SOURCE", source); + + // defaults + + mapDb->setValue("ORDER", 0); + mapDb->setValue("VISIBLE", 3); + + // lookup + + insert = !mapDb->find(); + + if (insert) + { + // select by channelid ... + // - to fill order an visible + + if (!selectMapOrdOf->find()) + { + if (selectMaxMapOrd->find()) + mapDb->setValue("ORDER", mapDb->getIntValue("ORDER") + 1); + } + + // visible and order was set by selectMapOrdOf + + selectMapOrdOf->freeResult(); + selectMaxMapOrd->freeResult(); + } + + mapDb->setValue("VPS", vps); + + if (!mapDb->hasValue("MERGE", (long)merge)) + { + changed++; + mapDb->setValue("MERGE", merge); + } + + if (changed || insert) + { + tell(1, "Channel '%s' %s, source '%s', extid %s, merge %d", + chan, insert ? "inserted" : "updated", + source, + extid, + merge); + + mapDb->setValue("MERGESP", 0L); // reset mergesp! + mapDb->setValue("UPDFLG", insert ? "I" : "U"); + + // force initial check + + if (!EpgdConfig.checkInitial) + { + tell(1, "At least one channelmap change detected, force initial check!"); + EpgdConfig.checkInitial = yes; + } + } + else + { + mapDb->setValue("UPDFLG", "S"); + } + + mapDb->store(); + mapDb->reset(); + + return done; +} + +//*************************************************************************** +// Apply Channelmap Changes to Events +//*************************************************************************** + +int cEpgd::applyChannelmapChanges() +{ + connection->startTransaction(); + + mapDb->clear(); + + for (int f = selectAllMap->find(); f; f = selectAllMap->fetch()) + { + char flg = mapDb->getStrValue("UpdFlg")[0]; + + // remove all fileref entrys for deleted 'D', updated 'U' or inserted 'I' + // channelmap rows + + if (flg == 'U' || flg == 'D' || flg == 'I') + { + tell(1, "Removing fileref and event entrys for channel '%s' " + "(extid %s) of '%s' due to channelmap change (%c)", + mapDb->getStrValue("CHANNELID"), + mapDb->getStrValue("EXTERNALID"), + mapDb->getStrValue("SOURCE"), + flg); + + if (!isZero(mapDb->getStrValue("EXTERNALID"))) + { + // delete coresponding fileref entrys + + fileDb->deleteWhere("extid = '%s' and source = '%s'", + mapDb->getStrValue("EXTERNALID"), + mapDb->getStrValue("SOURCE")); + } + + // delete events + + eventsDb->deleteWhere("channelid = '%s' and source = '%s'", + mapDb->getStrValue("CHANNELID"), + mapDb->getStrValue("SOURCE")); + } + } + + selectAllMap->freeResult(); + + // now delete wasted map entries + + mapDb->deleteWhere("updflg = 'D'"); + + connection->commit(); + + return done; +} diff --git a/configs/channelmap.conf b/configs/channelmap.conf new file mode 100644 index 0000000..beed1fa --- /dev/null +++ b/configs/channelmap.conf @@ -0,0 +1,49 @@ +// +// ChannelMap for EPG Daemon +// -------------------------- +// +// Format: +// <source>:<extid>[:<merge>[:<vps>]] = <cid1>[,<cid2>[,<cid3>]] +// +// +// <source> 'vdr' or the source name provided by a plugin +// <extid> 000 for vdr or the channle id used by the external EPG provider +// <merge> Merge DVB and externel EPG for this channel +// { 0, 1, 2 } (default 1, the default for source 'vdr' is 0) +// <vps> { y, Y, n, N, 0, 1 } (default 0) +// <cid> VDR ChannelID (Src-NID-TID-SID) + +// +// channels not listed here will not touched by the plugin +// if 'blacklist' in plugin options set to 'yes' the plugin will block all +// event data of the DVB stream since the channel is not listed here + +// +// get this channels from DVB stream + +vdr:000:0:0 = S19.2E-1-1066-28656 // VH1 +vdr:000:0:0 = S19.2E-133-12-105 // Sky Sport HD Extra +vdr:000:0:0 = S19.2E-133-2-262 // Sky Bundesliga 1 +vdr:000:0:0 = S19.2E-133-3-272 // Spieldaten +vdr:000:0:0 = S19.2E-133-3-282 // Sky Bundesliga 3 +vdr:000:0:0 = S19.2E-133-3-292 // Sky Bundesliga 4 +vdr:000:0:0 = S19.2E-133-3-302 // Sky Bundesliga 5 +vdr:000:0:0 = S19.2E-133-17-312 // FRA - AUE +vdr:000:0:0 = S19.2E-133-17-322 // 2. Liga Konf. +vdr:000:0:0 = S19.2E-133-17-332 // MSV - AACH +vdr:000:0:0 = S19.2E-133-1-342 // Sky Bundesliga 9 +vdr:000:0:0 = S19.2E-133-1-352 // Sky Bundesliga 10 +vdr:000:0:0 = S19.2E-133-2-252 // Sky Bundesliga 11 +vdr:000:0:0 = S19.2E-133-2-253 // LIVE Wimbledon 3 +vdr:000:0:0 = S19.2E-133-17-333 // Sky Racer +vdr:000:0:0 = S19.2E-133-17-323 // Sky Pitlane +vdr:000:0:0 = S19.2E-133-17-313 // Sky Sport 6 +vdr:000:0:0 = S19.2E-0-111719-303 // Sky Sport 7 +vdr:000:0:0 = S19.2E-0-111719-293 // Sky Sport 8 +vdr:000:0:0 = S19.2E-0-111719-283 // Sky Sport 9 +vdr:000:0:0 = S19.2E-0-111797-263 // Sky Sport 10 +vdr:000:0:0 = S19.2E-0-111719-273 // Sky Sport 11 +vdr:000:0:0 = S19.2E-133-1-363 // Sky Sport 12 +vdr:000:0:0 = S19.2E-133-1-373 // Sky Sport 13 +vdr:000:0:0 = S19.2E-53-1097-2042 // Hustler TV +vdr:000:0:0 = S19.2E-53-1097-2045 // Dorcel TV diff --git a/configs/epg.dat b/configs/epg.dat new file mode 100644 index 0000000..6e07ea3 --- /dev/null +++ b/configs/epg.dat @@ -0,0 +1,981 @@ +// -------------------------------------------------------------------------- +// +// Table Dictionary for EPG Daemon and related Plugins +// +// -------------------------------------------------------------------------- +// See the README file for copyright information and how to reach the author +// -------------------------------------------------------------------------- + +// ---------------------------------------------------------------- +// Table Events +// ---------------------------------------------------------------- + +Table events +{ + EVENTID "" eventid UBigInt 0 Primary, + CHANNELID "" channelid Ascii 50 Primary, + + MASTERID "" masterid UInt 0 Autoinc, + USEID "" useid UInt 0 Data, + + SOURCE "" source Ascii 10 Meta, + FILEREF "" fileref Ascii 100 Meta, + INSSP "" inssp Int 10 Meta, + UPDSP "" updsp Int 10 Meta, + UPDFLG "" updflg Ascii 1 Meta, + DELFLG "" delflg Ascii 1 Meta, + + TABLEID "" tableid Int 2 Data, + VERSION "" version Int 3 Data, + TITLE "" title Ascii 200 Data, + COMPTITLE "" comptitle Ascii 200 Data, + SHORTTEXT "" shorttext Ascii 300 Data, + COMPSHORTTEXT "" compshorttext Ascii 300 Data, + LONGDESCRIPTION "" longdescription MText 25000 Data, + COMPLONGDESCRIPTION "" complongdescription MText 25000 Data filter epgd|httpd|epg2vdr, + STARTTIME "" starttime Int 10 Data, + DURATION "" duration Int 5 Data, + PARENTALRATING "" parentalrating Int 2 Data, + VPS "" vps Int 10 Data, + CONTENTS "Genre code like table 28 of ETSI EN 300 468" contents ASCII 100 Data filter epgd|httpd|epg2vdr, + SHORTDESCRIPTION "" shortdescription MText 3000 Data, + ACTOR "" actor MText 5000 Data, + AUDIO "" audio Ascii 50 Data, + CATEGORY "" category Ascii 50 Data, + COUNTRY "" country Ascii 50 Data, + DIRECTOR "" director Text 1000 Data, + COMMENTATOR "" commentator Ascii 200 Data, + FLAGS "" flags Ascii 100 Data, + GENRE "" genre Ascii 100 Data, + MUSIC "" music Ascii 250 Data, + PRODUCER "" producer Text 1000 Data, + SCREENPLAY "" screenplay Ascii 500 Data, + SHORTREVIEW "" shortreview Ascii 500 Data, + TIPP "" tipp Ascii 250 Data, + TOPIC "" topic Ascii 1000 Data, + YEAR "" year Ascii 10 Data, + RATING "" rating Ascii 250 Data, + NUMRATING "" numrating Int 2 Data filter epgd|httpd|epg2vdr, + TXTRATING "" txtrating Ascii 100 Data, + MOVIEID "" movieid Ascii 20 Data, + MODERATOR "" moderator Ascii 250 Data, + OTHER "" other Text 2000 Data, + GUEST "" guest Text 1000 Data, + CAMERA "" camera Text 1000 Data, + EXTEPNUM "" extepnum Int 4 Data, + IMAGECOUNT "" imagecount Int 2 Data, + + EPISODECOMPNAME "" episodecompname Ascii 100 Data filter epgd|httpd|epg2vdr, + EPISODECOMPSHORTNAME "" episodecompshortname Ascii 100 Data filter epgd|httpd|epg2vdr, + EPISODECOMPPARTNAME "" episodecomppartname Ascii 200 Data filter epgd|httpd|epg2vdr, + EPISODELANG "" episodelang Ascii 10 Data filter epgd|httpd|epg2vdr, + + SCRSERIESID "" scrseriesid Int 0 Data, + SCRSERIESEPISODE "" scrseriesepisode Int 0 Data, + SCRMOVIEID "" scrmovieid Int 0 Data, + SCRSP "" scrsp Int 0 Data, +} + +// ---------------------------------------------------------------- +// Indices for Events +// ---------------------------------------------------------------- + +Index events +{ + comptitle "" COMPTITLE, + source "" SOURCE, + filerefsource "" FILEREF SOURCE, + channelid "" CHANNELID, + useid "" USEID, + useidchannelid "" USEID CHANNELID, + updflgupdsp "" UPDFLG UPDSP, + sourcechannelid "" SOURCE CHANNELID, + scrsp "" SCRSP, + sourceupdsp "" SOURCE UPDSP, + scrseriesid "" SCRSERIESID, + channelidstarttime "" CHANNELID STARTTIME, +} + +// ---------------------------------------------------------------- +// Table Components +// ---------------------------------------------------------------- + +Table components +{ + EVENTID "" eventid UBigInt 0 Primary, + CHANNELID "" channelid Ascii 50 Primary, + STREAM "" stream Int 3 Primary, + TYPE "" type Int 3 Primary, + LANG "" lang Ascii 8 Primary, + DESCRIPTION "" description Ascii 100 Primary, + INSSP "" inssp Int 0 Meta, + UPDSP "" updsp Int 0 Meta, +} + +// ---------------------------------------------------------------- +// Table FileRef +// ---------------------------------------------------------------- + +Table fileref +{ + NAME "" name Ascii 100 Primary, + SOURCE "" source Ascii 10 Primary, + INSSP "" inssp Int 0 Meta, + UPDSP "" updsp Int 0 Meta, + EXTERNALID "" extid Ascii 10 Data, + FILEREF "" fileref Ascii 100 Data, + TAG "" tag Ascii 100 Data, +} + +// ---------------------------------------------------------------- +// Indices for FileRefs +// ---------------------------------------------------------------- + +Index filerefs +{ + SourceFileref "" SOURCE FILEREF, + Fileref "" FILEREF, +} + +// ---------------------------------------------------------------- +// Table ImageRefs +// ---------------------------------------------------------------- + +Table imagerefs +{ + EVENTID "" eventid UBigInt 0 Primary, + LFN "" lfn Int 0 Primary, + INSSP "" inssp Int 0 Meta, + UPDSP "" updsp Int 0 Meta, + SOURCE "" source Ascii 10 Meta, + FILEREF "" fileref Ascii 100 Data, + IMGNAME "" imagename Ascii 100 Data, +} + +// ---------------------------------------------------------------- +// Indices for ImageRefs +// ---------------------------------------------------------------- + +Index imagerefs +{ + lfn "" LFN, + name "" IMGNAME, +} + +// ---------------------------------------------------------------- +// Table Images +// ---------------------------------------------------------------- + +Table images +{ + IMGNAME "" imagename Ascii 100 Primary, + INSSP "" inssp Int 0 Meta, + UPDSP "" updsp Int 0 Meta, + IMAGE "" image Mlob 512000 Data, +} + +// ---------------------------------------------------------------- +// Table Episodes +// ---------------------------------------------------------------- + +Table episodes +{ + COMPNAME "" compname Ascii 100 Primary, + COMPPARTNAME "" comppartname Ascii 200 Primary, + LANG "" lang Ascii 10 Primary, + + INSSP "" inssp Int 0 Meta, + UPDSP "" updsp Int 0 Meta, + + LINK "" link Int 0 Data, + SHORTNAME "" shortname Ascii 100 Data, + COMPSHORTNAME "" compshortname Ascii 100 Data, + EPISODENAME "" episodename Ascii 100 Data, + PARTNAME "" partname Ascii 300 Data, + SEASON "" season Int 0 Data, + PART "" part Int 0 Data, + PARTS "" parts Int 0 Data, + NUMBER "" number Int 0 Data, + EXTRACOL1 "" extracol1 Ascii 250 Data, + EXTRACOL2 "" extracol2 Ascii 250 Data, + EXTRACOL3 "" extracol3 Ascii 250 Data, + COMMENT "" comment Ascii 250 Data, +} + +// ---------------------------------------------------------------- +// Indices for Episodes +// ---------------------------------------------------------------- + +Index episodes +{ + updsp "" UPDSP, +} + +// ---------------------------------------------------------------- +// Table ChannelMap +// ---------------------------------------------------------------- + +Table channelmap +{ + EXTERNALID "" extid Ascii 10 Primary, + CHANNELID "" channelid Ascii 50 Primary, + SOURCE "" source Ascii 20 Primary, + + ORDER "" ord Int 0 Data, + VISIBLE "" visible Int 0 Data, + CHANNELNAME "" channelname Ascii 100 Data, + VPS "" vps Int 0 Data, + FORMAT "" format Ascii 50 Data, + UNKNOWNATVDR "" unknownatvdr UInt 1 Data, + MERGE "" merge Int 0 Data, + MERGESP "" mergesp Int 0 Data, + INSSP "" inssp Int 0 Meta, + UPDSP "" updsp Int 0 Meta, + UPDFLG "" updflg Ascii 1 Meta, +} + +// ---------------------------------------------------------------- +// Indices for ChannelMap +// ---------------------------------------------------------------- + +Index channelmap +{ + sourceExtid "" SOURCE EXTERNALID, + source "" SOURCE, + updflg "" UPDFLG, + sourcechannelid "" SOURCE CHANNELID, + mergesp "" MERGESP, + channelid "" CHANNELID, +} + +// ---------------------------------------------------------------- +// Table Vdrs +// ---------------------------------------------------------------- + +Table vdrs +{ + UUID "" uuid Ascii 40 Primary, + + INSSP "" inssp Int 0 Meta, + UPDSP "" updsp Int 0 Meta, + + NAME "" name Ascii 100 Data, + VERSION "" version Ascii 100 Data, + DBAPI "" dbapi UInt 0 Data, + LASTUPDATE "" lastupd Int 0 Data, + NEXTUPDATE "" nextupd Int 0 Data, + LASTMERGE "" lastmerge Int 0 Data, + STATE "" state Ascii 20 Data, + MASTER "" master Ascii 1 Data, + IP "" ip Ascii 20 Data, + MAC "" mac Ascii 18 Data, + PID "" pid UInt 0 Data filter epgd|httpd|epg2vdr, + SVDRP "" svdrp UInt 0 Data filter epgd|httpd|epg2vdr, + TUNERCOUNT "" tunercount UInt 0 Data filter epgd|httpd|epg2vdr, + + SHAREINWEB "" shareinweb UInt 1 Data, + USECOMMONRECFOLDER "" usecommonrecfolder UInt 1 Data, + + VIDEODIR "" videodir Ascii 300 Data, + VIDEOTOTAL "" videototal UInt 0 Data, + VIDEOFREE "" videofree UInt 0 Data, +} + +// ---------------------------------------------------------------- +// Indices for Vdrs +// ---------------------------------------------------------------- + +Index vdrs +{ + state "" STATE, +} + +// ---------------------------------------------------------------- +// Table Users +// ---------------------------------------------------------------- + +Table users +{ + USER "" user Ascii 40 Primary, + + INSSP "" inssp Int 0 Meta, + UPDSP "" updsp Int 0 Meta, + + PASSWD "" passwd Ascii 100 Data, + ACTIVE "" active Int 1 Data, + RIGHTS "" rights UInt 0 Data, +} + +// ---------------------------------------------------------------- +// Table Parameters +// ---------------------------------------------------------------- + +Table parameters +{ + OWNER "" owner Ascii 40 Primary, + NAME "" name Ascii 40 Primary, + INSSP "" inssp Int 0 Meta, + UPDSP "" updsp Int 0 Meta, + VALUE "" value Ascii 500 Data, +} + +// ---------------------------------------------------------------- +// Table Analyse +// ---------------------------------------------------------------- + +Table analyse +{ + CHANNELID "" channelid Ascii 50 Primary, + VDRMASTERID "" vdr_masterid UInt 0 Data, + VDREVENTID "" vdr_eventid UBigInt 0 Primary, + VDRSTARTTIME "" vdr_starttime Int 10 Data, + VDRDURATION "" vdr_duration Int 5 Data, + VDRTITLE "" vdr_title Ascii 200 Data, + VDRSHORTTEXT "" vdr_shorttext Ascii 300 Data, + EXTMASTERID "" ext_masterid UInt 0 Data, + EXTEVENTID "" ext_eventid UBigInt 0 Data, + EXTSTARTTIME "" ext_starttime Int 10 Data, + EXTDURATION "" ext_duration Int 5 Data, + EXTTITLE "" ext_title Ascii 200 Data, + EXTSHORTTEXT "" ext_shorttext Ascii 300 Data, + EXTEPISODE "" ext_episode Ascii 1 Data, + EXTMERGE "" ext_merge Int 11 Data, + EXIIMAGES "" ext_images Ascii 1 Data, + LVMIN "" lvmin Int 3 Data, + RANK "" rank Int 5 Data, +} + +// ---------------------------------------------------------------- +// Indices for Analyse +// ---------------------------------------------------------------- + +Index analyse +{ + vdr_masterid "" VDRMASTERID, +} + +// ---------------------------------------------------------------- +// Table Snapshot +// ---------------------------------------------------------------- + +Table snapshot +{ + CHANNELID "" channelid Ascii 50 Data, + SOURCE "" source Ascii 10 Data, + VDRMASTERID "" masterid UInt 0 Data, + EVENTID "" eventid UBigInt 0 Data, + USEID "" useid UInt 0 Data, + STARTTIME "" starttime Int 10 Data, + DURATION "" duration Int 5 Data, + TITLE "" title Ascii 200 Data, + COMPTITLE "" comptitle Ascii 200 Data, + SHORTTEXT "" shorttext Ascii 300 Data, + COMPSHORTTEXT "" compshorttext Ascii 300 Data, + UPDSP "" updsp Int 10 Data, + EPISODE "" episode Ascii 1 Data, + MERGE "" merge Int 0 Data, + IMAGES "" images Ascii 1 Data, +} + +// ---------------------------------------------------------------- +// Indices for Snapshot +// ---------------------------------------------------------------- + +Index snapshot +{ + channelid "" CHANNELID, + starttimeSource "" STARTTIME SOURCE, +} + +// ---------------------------------------------------------------- +// Table UseEvents +// ---------------------------------------------------------------- + +Table useevents +{ + CNTSOURCE "" cnt_source Ascii 10 Primary, + CHANNELID "" cnt_channelid Ascii 50 Primary, + CNTEVENTID "" cnt_eventid UBigInt 0 Primary|Meta, + + MASTERID "" cnt_masterid UInt 0 Data|Meta, + USEID "" cnt_useid UInt 0 Data, + + SUBSOURCE "" sub_source Ascii 10 Data|Meta, + SUBEVENTID "" sub_eventid UBigInt 0 Data|Meta, + UPDSP "" all_updsp Int 0 Data, + UPDFLG "" cnt_updflg Ascii 1 Data|Meta, + DELFLG "" cnt_delflg Ascii 1 Data, + FILEREF "" cnt_fileref Ascii 100 Data, + TABLEID "" cnt_tableid Int 2 Data, + VERSION "" cnt_version Int 3 Data, + TITLE "" sub_title Ascii 200 Data, + SHORTTEXT "" sub_shorttext Ascii 300 Data, + COMPTITLE "" sub_comptitle Ascii 200 Data, + COMPSHORTTEXT "" sub_compshorttext Ascii 300 Data, + GENRE "" sub_genre Ascii 100 Data, + COUNTRY "" sub_country Ascii 50 Data, + YEAR "" sub_year Ascii 10 Data, + STARTTIME "" cnt_starttime Int 10 Data, + DURATION "" cnt_duration Int 5 Data, + PARENTALRATING "" cnt_parentalrating Int 2 Data, + VPS "" cnt_vps Int 10 Data, + CONTENTS "Genre code like table 28 of ETSI EN 300 468" cnt_contents ASCII 100 Data, + CATEGORY "" sub_category Ascii 50 Data, + SHORTDESCRIPTION "" sub_shortdescription MText 3000 Data, + SHORTREVIEW "" sub_shortreview Ascii 500 Data, + TIPP "" sub_tipp Ascii 250 Data, + RATING "" sub_rating Ascii 250 Data, + NUMRATING "" sub_numrating Int 2 Data, + TXTRATING "" sub_txtrating Ascii 100 Data, + TOPIC "" sub_topic Ascii 1000 Data, + LONGDESCRIPTION "" sub_longdescription MText 25000 Data, + COMPLONGDESCRIPTION "" sub_complongdescription MText 25000 Data, + CNTLONGDESCRIPTION "" cnt_longdescription MText 25000 Data, + MODERATOR "" sub_moderator Ascii 250 Data, + GUEST "" sub_guest Text 1000 Data, + ACTOR "" sub_actor MText 5000 Data, + PRODUCER "" sub_producer Text 1000 Data, + OTHER "" sub_other Text 2000 Data, + DIRECTOR "" sub_director Text 1000 Data, + COMMENTATOR "" sub_commentator Ascii 200 Data, + SCREENPLAY "" sub_screenplay Ascii 500 Data, + CAMERA "" sub_camera Text 1000 Data, + MUSIC "" sub_music Ascii 250 Data, + AUDIO "" sub_audio Ascii 50 Data, + FLAGS "" sub_flags Ascii 100 Data, + IMAGECOUNT "" sub_imagecount Int 2 Data, + + SCRSERIESID "" sub_scrseriesid Int 0 Data, + SCRSERIESEPISODE "" sub_scrseriesepisode Int 0 Data, + SCRMOVIEID "" sub_scrmovieid Int 0 Data, + SCRSP "" sub_scrsp Int 0 Data|Meta, + + EPISODECOMPNAME "" sub_episodecompname Ascii 100 Data, + EPISODECOMPSHORTNAME "" sub_episodecompshortname Ascii 100 Data, + EPISODECOMPPARTNAME "" sub_episodecomppartname Ascii 200 Data, + + EPISODENAME "" epi_episodename Ascii 100 Data, + EPISODESHORTNAME "" epi_shortname Ascii 100 Data, + EPISODEPARTNAME "" epi_partname Ascii 300 Data, + EPISODELANG "" epi_lang Ascii 10 Data, + EPISODEEXTRACOL1 "" epi_extracol1 Ascii 250 Data, + EPISODEEXTRACOL2 "" epi_extracol2 Ascii 250 Data, + EPISODEEXTRACOL3 "" epi_extracol3 Ascii 250 Data, + EPISODESEASON "" epi_season Int 0 Data, + EPISODEPART "" epi_part Int 0 Data, + EPISODEPARTS "" epi_parts Int 0 Data, + EPISODENUMBER "" epi_number Int 0 Data, +} + +// ---------------------------------------------------------------- +// Indices for UseEvents +// ---------------------------------------------------------------- + +Index useevents +{ + channelidstarttime "" CHANNELID STARTTIME, + useid "" USEID, + channelidupdflgupdsp "" CHANNELID UPDFLG UPDSP, + channelid "" CHANNELID, + updflgstarttimeduration "" UPDSP STARTTIME DURATION, +} + +// ---------------------------------------------------------------- +// Table Recording List +// ---------------------------------------------------------------- + +Table recordinglist +{ + MD5PATH "" md5path Ascii 40 Primary, + STARTTIME "" starttime UInt 0 Primary, + OWNER "uuid of vdr" owner Ascii 40 Primary, + + INSSP "" inssp Int 10 Meta, + UPDSP "" updsp Int 10 Meta, + LASTIFOUPD "" lastifoupd Int 10 Meta, + + VDRUUID "" vdruuid Ascii 40 Data, + PATH "" path Ascii 1000 Data, + NAME "" name Ascii 1000 Data, + FOLDER "" folder Ascii 1000 Data, + TITLE "" title Ascii 200 Data, + SHORTTEXT "" shorttext Ascii 300 Data, + LONGDESCRIPTION "" longdescription MText 25000 Data, + DURATION "" duration UInt 0 Data, + FSK "" fsk UInt 1 Data, + + EVENTID "useid" eventid UInt 0 Data, + CHANNELID "" channelid Ascii 50 Data, + CHANNELNAME "just a copy" channelname Ascii 100 Data, + + STATE "" state Ascii 1 Data, + INUSE "" inuse UInt 1 Data, + JOB "" job Ascii 1 Data, + + // enriched by 'external' data of events + + ACTOR "" actor MText 5000 Data, + AUDIO "" audio Ascii 50 Data, + CATEGORY "" category Ascii 50 Data, + COUNTRY "" country Ascii 50 Data, + DIRECTOR "" director Text 1000 Data, + FLAGS "" flags Ascii 100 Data, + GENRE "" genre Ascii 100 Data, + MUSIC "" music Ascii 250 Data, + PRODUCER "" producer Text 1000 Data, + SCREENPLAY "" screenplay Ascii 500 Data, + SHORTREVIEW "" shortreview Ascii 500 Data, + TIPP "" tipp Ascii 250 Data, + TOPIC "" topic Ascii 1000 Data, + YEAR "" year Ascii 10 Data, + RATING "" rating Ascii 250 Data, + NUMRATING "" numrating Int 2 Data, + TXTRATING "" txtrating Ascii 100 Data, + MODERATOR "" moderator Ascii 250 Data, + OTHER "" other Text 2000 Data, + GUEST "" guest Text 1000 Data, + CAMERA "" camera Text 1000 Data, + + // episode reference + + EPISODECOMPNAME "" episodecompname Ascii 100 Data filter epgd|httpd|epg2vdr, + EPISODECOMPSHORTNAME "" episodecompshortname Ascii 100 Data filter epgd|httpd|epg2vdr, + EPISODECOMPPARTNAME "" episodecomppartname Ascii 200 Data filter epgd|httpd|epg2vdr, + EPISODELANG "" episodelang Ascii 10 Data filter epgd|httpd|epg2vdr, + + // scraper fields + // IDs found while scraping (reference to scraper tables), managed by epgd + + SCRSERIESID "" scrseriesid UInt 0 Data, + SCRSERIESEPISODE "" scrseriesepisode UInt 0 Data, + SCRMOVIEID "" scrmovieid UInt 0 Data, + + // this fields are written by the scraper plugin, + // the id fields hold the user hint for scraping + + SCRINFOMOVIEID "" scrinfomovieid UInt 0 Data, + SCRINFOSERIESID "" scrinfoseriesid UInt 0 Data, + SCRINFOEPISODEID "" scrinfoepisodeid UInt 0 Data, + + SCRNEW "" scrnew UInt 0 Data, + SCRSP "" scrsp Int 0 Data, +} + +// ---------------------------------------------------------------- +// Table RecordingDirs +// ---------------------------------------------------------------- + +Table recordingdirs +{ + VDRUUID "" vdruuid Ascii 40 Primary, + DIRECTORY "" directory Ascii 255 Primary, + + INSSP "" inssp Int 0 Meta, + UPDSP "" updsp Int 0 Meta, +} + +// ---------------------------------------------------------------- +// Table Timers +// ---------------------------------------------------------------- + +Table timers +{ + ID "" id UInt 0 Primary|Autoinc, + VDRUUID "" vdruuid Ascii 40 Primary, + + INSSP "" inssp Int 0 Meta, + UPDSP "" updsp Int 0 Meta, + + EVENTID "useid" eventid UInt 0 Data, + CHANNELID "" channelid Ascii 50 Data, + _STARTTIME "pre filled start timer for trigger" _starttime Int 10 Data, + + SOURCE "like osd, webif, epgd" source Ascii 40 Data, + TYPE "'R'ecord, 'V'iew (umschalt)" type Ascii 1 Data, + STATE "'D'eleted, 'R'unning, 'F'inished" state Ascii 1 Data default u, + INFO "error reason if state is failed" info Ascii 255 Data, + ACTION "" action Ascii 1 Data default a, + TCCMAILCNT "" tccmailcnt UInt 0 Data, + WRNCOUNT "" wrncount UInt 0 Data, + RETRYS "" retrys UInt 0 Data, + + NAMINGMODE "" namingmode Int 0 Data, + TEMPLATE "" template Ascii 100 Data, + ACTIVE "" active UInt 0 Data, + DAY "" day Int 10 Data, + WEEKDAYS "" weekdays Int 10 Data, + STARTTIME "" starttime Int 10 Data, + ENDTIME "" endtime Int 10 Data, + FILE "" file Ascii 512 Data, + DIRECTORY "" directory Ascii 512 Data, + + PRIORITY "" priority Int 0 Data, + LIFETIME "" lifetime Int 0 Data, + VPS "" vps Int 0 Data, + CHILDLOCK "" childlock Int 0 Data, + AUX "" aux Ascii 1000 Data, + + AUTOTIMERNAME "Bezeichung des Suchtimers" autotimername Ascii 100 Data, + AUTOTIMERID "id of autotimer" autotimerid UInt 0 Data, + AUTOTIMERINSSP "" autotimerinssp Int 0 Data, + + // just to update the done state by the plugin !! + + DONEID "id of done entry" doneid UInt 0 Data, + EXPRESSION "" expression Ascii 200 Data, +} + +// ---------------------------------------------------------------- +// Indices for Timers +// ---------------------------------------------------------------- + +Index timers +{ + eventidchannelidvdruuid "" EVENTID CHANNELID VDRUUID, + vdruuidstate "" VDRUUID STATE +} + +// ---------------------------------------------------------------- +// Table +// ---------------------------------------------------------------- + +Table searchtimers +{ + ID "" id UInt 0 Primary|Autoinc, + + INSSP "" inssp Int 0 Meta, + UPDSP "" updsp Int 0 Meta, + + CHANNELIDS "comma separated list of channleids or empty" channelids Ascii 500 Data, + CHEXCLUDE "" chexclude UInt 0 Data, + CHFORMAT "HD,SD" chformat Ascii 50 Data, + + NAME "Bezeichung des Suchtimers" name Ascii 100 Data, + EXPRESSION "" expression Ascii 200 Data, + EXPRESSION1 "" expression1 Ascii 200 Data, + SEARCHMODE "1 exact, 2 regexp, 3 like, 4 enthalten, .." searchmode UInt 0 Data, + SEARCHFIELDS "Bitmaske: 1 title, 2 shorttext, 4 - desc, .." searchfields UInt 0 Data, + SEARCHFIELDS1 "Bitmaske: 0 off, 1 title, 2 shorttext, 4 - desc, .." searchfields1 UInt 0 Data, + + CASESENSITIV "0,1" casesensitiv UInt 0 Data, + + REPEATFIELDS "Bitmaske: 1 title, 2 shorttext, 4 - desc, .." repeatfields UInt 0 Data, + + // optional EPG Detail options + + EPISODENAME "" episodename Ascii 100 Data, + SEASON "e.g. '1-7'" season Ascii 10 Data, + SEASONPART "e.g. '20-'" seasonpart Ascii 10 Data, + CATEGORY "e.g. 'Spielfilm','Serie'" category Ascii 150 Data, + GENRE "e.g. 'Krimi','Action'" genre Ascii 150 Data, + YEAR "e.g. '2010-2015'" year Ascii 10 Data, + TIPP "" tipp Ascii 250 Data, + NOEPGMATCH "" noepgmatch Int 0 Data, + + // steering + + TYPE "'R'ecord, 'V'iew, 'S'earch" type Ascii 1 Data, + STATE "D - Deleted" state Ascii 1 Data, + NAMINGMODE "" namingmode Int 0 Data, + TEMPLATE "" template Ascii 100 Data, + + ACTIVE "0,1" active UInt 0 Data, + SOURCE "webif ,osd, ..." source Ascii 40 Data, + HITS "stastic counter, just for info" hits UInt 0 Data, + MODSP "last user modification time" modsp Int 0 Data, + LASTRUN "last execution of search timer" lastrun Int 0 Data, + VDRUUID "empty or uuid of vdr" vdruuid Ascii 40 Data, + + // timer details + + WEEKDAYS "bitmask like timers, 0 foy all" weekdays Int 0 Data, + NEXTDAYS "" nextdays UInt 0 Data, + STARTTIME "null for unlimited search" starttime Int 0 Data, + ENDTIME "null for unlimited search" endtime Int 0 Data, + DIRECTORY "" directory Ascii 512 Data, + PRIORITY "" priority Int 0 Data, + LIFETIME "" lifetime Int 0 Data, + VPS "" vps Int 0 Data, + CHILDLOCK "" childlock Int 0 Data, +} + +// ---------------------------------------------------------------- +// Table TimersDone +// ---------------------------------------------------------------- + +Table timersdone +{ + ID "" id UInt 0 Primary|Autoinc, + + INSSP "" inssp Int 0 Meta, + UPDSP "" updsp Int 0 Meta, + + SOURCE "" source Ascii 40 Data, + STATE "Q requested, C created, R recorded, F Failed" state Ascii 1 Data, + + TIMERID "not filled completely in all cases yet" timerid UInt 0 Data, + AUTOTIMERID "" autotimerid UInt 0 Data, + AUTOTIMERNAME "Bezeichung des Suchtimers" autotimername Ascii 100 Data, + + // to compare + + TITLE "" title Ascii 200 Data, + COMPTITLE "" comptitle Ascii 200 Data, + SHORTTEXT "" shorttext Ascii 300 Data, + COMPSHORTTEXT "" compshorttext Ascii 300 Data, + LONGDESCRIPTION "" longdescription MText 25000 Data, + COMPLONGDESCRIPTION "" complongdescription MText 25000 Data, + + EPISODECOMPNAME "" episodecompname Ascii 100 Data filter epgd|httpd|epg2vdr, + EPISODECOMPSHORTNAME "" episodecompshortname Ascii 100 Data filter epgd|httpd|epg2vdr, + EPISODECOMPPARTNAME "" episodecomppartname Ascii 200 Data filter epgd|httpd|epg2vdr, + EPISODELANG "" episodelang Ascii 10 Data filter epgd|httpd|epg2vdr, + EPISODESEASON "" episodeseason Int 0 Data, + EPISODEPART "" episodepart Int 0 Data, + + // just for info + + CHANNELID "" channelid Ascii 50 Data, + CHANNELNAME "" channelname Ascii 100 Data; + EXPRESSION "expression of autotimer" expression Ascii 200 Data, + STARTTIME "" starttime Int 10 Data, + DURATION "" duration Int 5 Data, + AUX "" aux Ascii 512 Data, +} + +// ---------------------------------------------------------------- +// Indices for TimersDone +// ---------------------------------------------------------------- + +Index TimersDone +{ + checkdoubles "" COMPTITLE, COMPSHORTTEXT +} + +// ---------------------------------------------------------------- +// Table Messages / Notifications +// ---------------------------------------------------------------- + +Table messages +{ + ID "" id UInt 0 Primary|Autoinc, + + INSSP "" inssp Int 0 Meta, + UPDSP "" updsp Int 0 Meta, + + TYPE "Warning, Info, Error, Fatal" type Ascii 1 Data, + TITLE "" title Ascii 200 Data, + STATE "Read, New, Deleted" state Ascii 1 Data, + TEXT "" text MText 20000 Data, +} + +// ---------------------------------------------------------------- +// SCRAPER stuff +// ---------------------------------------------------------------- +// ---------------------------------------------------------------- +// Table Series +// ---------------------------------------------------------------- + +Table series +{ + SERIESID "" series_id UInt 0 Primary, + SERIESNAME "" series_name Ascii 200 Data, + SERIESLASTSCRAPED "" series_last_scraped UInt 0 Data, + SERIESLASTUPDATED "" series_last_updated UInt 0 Data, + SERIESOVERVIEW "" series_overview Text 10000 Data, + SERIESFIRSTAIRED "" series_firstaired Ascii 50 Data, + SERIESNETWORK "" series_network Ascii 100 Data, + SERIESIMDBID "" series_imdb_id Ascii 20 Data, + SERIESGENRE "" series_genre Ascii 100 Data, + SERIESRATING "" series_rating Float 31 Data, + SERIESSTATUS "" series_status Ascii 50 Data, +} + +// ---------------------------------------------------------------- +// Indices for Series +// ---------------------------------------------------------------- + +Index series +{ + seriesname "" SERIESNAME, +} + +// ---------------------------------------------------------------- +// Table SeriesEpisode +// ---------------------------------------------------------------- + +Table series_episode +{ + EPISODEID "" episode_id UInt 0 Primary, + EPISODENUMBER "" episode_number UInt 0 Data, + SEASONNUMBER "" season_number UInt 0 Data, + EPISODENAME "" episode_name Ascii 300 Data, + EPISODEOVERVIEW "" episode_overview Text 10000 Data, + EPISODEFIRSTAIRED "" episode_firstaired Ascii 20 Data, + EPISODEGUESTSTARS "" episode_gueststars Ascii 1000 Data, + EPISODERATING "" episode_rating Float 31 Data, + EPISODELASTUPDATED "" episode_last_updated UInt 0 Data, + SERIESID "" series_id UInt 0 Data, +} + +// ---------------------------------------------------------------- +// Indices for SeriesEpisode +// ---------------------------------------------------------------- + +Index series_episode +{ + series_id "" SERIESID, +} + +// ---------------------------------------------------------------- +// Table SeriesMedia +// ---------------------------------------------------------------- + +Table series_media +{ + SERIESID "" series_id UInt 0 Primary, + SEASONNUMBER "" season_number UInt 0 Primary, + EPISODEID "" episode_id UInt 0 Primary, + ACTORID "" actor_id UInt 0 Primary, + MEDIATYPE "" media_type UInt 0 Primary, + + INSSP "" inssp Int 0 Meta filter epgd|httpd|epg2vdr, + UPDSP "" updsp Int 0 Meta filter epgd|httpd|epg2vdr, + + MEDIAURL "" media_url Ascii 100 Data, + MEDIAWIDTH "" media_width UInt 0 Data, + MEDIAHEIGHT "" media_height UInt 0 Data, + MEDIARATING "" media_rating Float 31 Data, + MEDIACONTENT "" media_content Mlob 1000000 Data, +} + +// ---------------------------------------------------------------- +// Indices for SeriesMedia +// ---------------------------------------------------------------- + +Index series_media +{ + series_id "" SERIESID, + season_number "" SEASONNUMBER, + episode_id "" EPISODEID, + actor_id "" ACTORID, +} + +// ---------------------------------------------------------------- +// Table SeriesActor +// ---------------------------------------------------------------- + +Table series_actor +{ + ACTORID "" actor_id UInt 0 Primary, + ACTORNAME "" actor_name Ascii 100 Data, + ACTORROLE "" actor_role Ascii 500 Data, + SORTORDER "" actor_sortorder UInt 0 Data, +} + +// ---------------------------------------------------------------- +// Indices for SeriesActor +// ---------------------------------------------------------------- + +Index series_actor +{ +} + +// ---------------------------------------------------------------- +// Table Movie +// ---------------------------------------------------------------- + +Table movie +{ + MOVIEID "" movie_id UInt 0 Primary, + TITLE "" movie_title Ascii 300 Data, + ORIGINALTITLE "" movie_original_title Ascii 300 Data, + TAGLINE "" movie_tagline Ascii 1000 Data, + OVERVIEW "" movie_overview Text 5000 Data, + ISADULT "" movie_adult UInt 0 Data, + COLLECTIONID "" movie_collection_id UInt 0 Data, + COLLECTIONNAME "" movie_collection_name Ascii 300 Data, + BUDGET "" movie_budget UInt 0 Data, + REVENUE "" movie_revenue UInt 0 Data, + GENRES "" movie_genres Ascii 500 Data, + HOMEPAGE "" movie_homepage Ascii 300 Data, + RELEAASEDATE "" movie_release_date Ascii 20 Data, + RUNTIME "" movie_runtime UInt 0 Data, + POPULARITY "" movie_popularity Float 31 Data, + VOTEAVERAGE "" movie_vote_average Float 31 Data, +} + +// ---------------------------------------------------------------- +// Indices for Movies +// ---------------------------------------------------------------- + +Index movie +{ + movie_id "" MOVIEID, + movietitle "" TITLE, +} + +// ---------------------------------------------------------------- +// Table MovieActor +// ---------------------------------------------------------------- + +Table movie_actor +{ + ACTORID "" actor_id UInt 0 Primary, + ACTORNAME "" actor_name Ascii 300 Data, +} + +// ---------------------------------------------------------------- +// Indices for MovieActor +// ---------------------------------------------------------------- + +Index movie_actor +{ + actor_id "" ACTORID, +} + +// ---------------------------------------------------------------- +// Table MovieActors +// ---------------------------------------------------------------- + +Table movie_actors +{ + MOVIEID "" movie_id UInt 0 Primary, + ACTORID "" actor_id UInt 0 Primary, + ROLE "" actor_role Ascii 300 Data, +} + +// ---------------------------------------------------------------- +// Indices for MovieActors +// ---------------------------------------------------------------- + +Index movie_actors +{ + movie_id "" MOVIEID, + actor_id "" ACTORID, +} + +// ---------------------------------------------------------------- +// Table MovieMedia +// ---------------------------------------------------------------- + +Table movie_media +{ + MOVIEID "" movie_id UInt 0 Primary, + ACTORID "" actor_id UInt 0 Primary, + MEDIATYPE "" media_type UInt 0 Primary, + MEDIAURL "" media_url Ascii 100 Data, + MEDIAWIDTH "" media_width UInt 0 Data, + MEDIAHEIGHT "" media_height UInt 0 Data, + MEDIACONTENT "" media_content Mlob 1000000 Data, +} + +// ---------------------------------------------------------------- +// Indices for MovieMedia +// ---------------------------------------------------------------- + +Index movie_media +{ + movie_id "" MOVIEID, + actor_id "" ACTORID, +} diff --git a/configs/epgd.conf b/configs/epgd.conf new file mode 100644 index 0000000..fbcb03d --- /dev/null +++ b/configs/epgd.conf @@ -0,0 +1,49 @@ +# ------------------------------------ +# Configuration of EPG Daemon +# ------------------------------------ + +# EpgImageSize +# 0 = 174x130 +# 1 = 329x245 +# 2 = 525x400 + +DbHost = localhost +DbPort = 3306 +DbName = epg2vdr +DbUser = epg2vdr +DbPass = epg + +EpgView = eventsview.sql +EpgViewWeb = eventsviewplain.sql +TheTvDBView = thetvdbview.sql + +CheckInitial = 1 +DaysInAdvance = 8 +DaysToUpdate = 4 +UpdateTime = 12 +UpdateThreshold = 500 + +XmlStoreToFs = 0 + +GetEPGImages = 1 +EpgImageSize = 2 +MaxImagesPerEvent = 1 + +SeriesEnabled = 1 +SeriesPort = 2006 +SeriesStoreToFs = 0 +SeriesUrl = eplists.constabel.net + +ScrapEpg = 1 +ScrapRecordings = 1 + +# NetDevice = eth0 + +# CachePath = /var/cache/epgd/ +# HttpPort = 9999 + +# HttpProxy = 127.0.0.1:8000 +# UserName = +# Password = + +LogLevel = 1 diff --git a/configs/eventsview-3po.sql b/configs/eventsview-3po.sql new file mode 100644 index 0000000..3f9d167 --- /dev/null +++ b/configs/eventsview-3po.sql @@ -0,0 +1,75 @@ +CREATE VIEW eventsview as select cnt_useid useid, cnt_eventid eventid, cnt_channelid channelid, cnt_source source, all_updsp updsp, cnt_updflg updflg, cnt_delflg delflg, cnt_fileref fileref, cnt_tableid tableid, cnt_version version, sub_title title, +case when sub_shorttext is null then + concat( + case when length(ifnull(sub_genre,'')) > 0 then sub_genre else '' end, + case when length(ifnull(sub_genre,'')) > 0 and length(ifnull(sub_country,'')) + length(ifnull(sub_year,'')) > 0 then ' (' else '' end, + case when length(ifnull(sub_country,'')) > 0 then sub_country else '' end, + case when length(ifnull(sub_country,'')) > 0 and length(ifnull(sub_year,'')) > 0 then ' ' else '' end, + case when length(ifnull(sub_year,'')) > 0 then sub_year else '' end, + case when length(ifnull(sub_genre,'')) > 0 and length(ifnull(sub_country,'')) + length(ifnull(sub_year,'')) > 0 then ')' else '' end + ) +else + concat( + sub_shorttext, + case when length(ifnull(sub_genre,'')) + length(ifnull(sub_country,'')) + length(ifnull(sub_year,'')) > 0 then ' (' else '' end, + case when length(ifnull(sub_genre,'')) > 0 then sub_genre else '' end, + case when length(ifnull(sub_country,'')) or length(ifnull(sub_year,'')) > 0 then ', ' else '' end, + case when length(ifnull(sub_country,'')) > 0 then sub_country else '' end, + case when length(ifnull(sub_country,'')) > 0 and length(ifnull(sub_year,'')) > 0 then ' ' else '' end, + case when length(ifnull(sub_year,'')) > 0 then sub_year else '' end, + case when length(ifnull(sub_genre,'')) + length(ifnull(sub_country,'')) + length(ifnull(sub_year,'')) > 0 then ')' else '' end + ) +end shorttext, +cnt_starttime starttime, cnt_duration duration, cnt_parentalrating parentalrating, cnt_vps vps, cnt_contents contents, replace( +concat( + TRIM(LEADING '|' FROM + concat( + case when sub_genre is Null then '' else concat('|','Genre: ',sub_genre) end, + case when sub_category is Null then '' else concat('|','Kategorie: ',sub_category) end, + case when sub_country is Null then '' else concat('|','Land: ',sub_country) end, + case when sub_year is Null then '' else concat('|','Jahr: ',substring(sub_year,1,4)) end, + case when sub_flags is Null then '' else concat('|',sub_flags) end, + case when sub_flags is Null or sub_audio is Null then '' else ' ' end, + case when sub_audio is Null then '' else concat('[', replace(sub_audio, ' ', '] ['), ']') end, + case when sub_flags is Null and sub_audio is Null then '|' else '' end, + case when sub_flags is Null or sub_audio is Null then '' else ' ' end, + case when cnt_parentalrating is Null then '' else concat('[FSK ',cnt_parentalrating,']') end, + case when cnt_source <> sub_source then concat(' [EPG: ',upper(replace(cnt_source,'vdr','dvb')),'/',upper(sub_source),']') else concat(' [EPG: ',upper(replace(cnt_source,'vdr','dvb')),']') end + ) + ), + case when sub_source <> 'epgdata' and sub_tipp = 'TagesTipp' then '||Tagestipp' else '' end, + concat( + case when sub_txtrating is Null and sub_shortreview is null then '' else '||Bewertung: ' end, + case when sub_txtrating is null then '' else sub_txtrating end, + case when sub_txtrating is Null or sub_shortreview is null then '' else ', ' end, + case when sub_shortreview is Null then '' else sub_shortreview end, + case when sub_topic is Null then '' else concat('||','Thema: ',sub_topic) end, + case when sub_longdescription is Null then '' else concat('||',sub_longdescription) end, + case when sub_moderator is Null then '' else concat('||','Moderator: ',sub_moderator) end, + case when sub_commentator is Null then '' else concat('||','Kommentar: ',sub_commentator) end, + case when sub_producer is Null then '' else concat('|','Produzent: ',sub_producer) end, + case when sub_guest is Null then '' else concat('|','Gäste: ',sub_guest) end, + case when sub_other is Null then '' else concat('|','Sonstige: ',sub_other) end, + case when sub_actor is Null then '' else concat('|',replace(sub_actor,'), ', ')|')) end, + case when sub_director is Null and sub_screenplay is Null and sub_camera is Null and sub_music is Null then '' else '|' end, + case when sub_director is Null then '' else concat('|','Regie: ',sub_director) end, + case when sub_screenplay is Null then '' else concat('|','Drehbuch: ',sub_screenplay) end, + case when sub_camera is Null then '' else concat('|','Kamera: ',sub_camera) end, + case when sub_music is Null then '' else concat('|','Musik: ',sub_music) end, + case when sub_rating is Null then '' else concat('|',replace(replace(sub_rating,' / ', '|'),' ',': ')) end, + case when epi_episodename is Null then '' else concat('||','Serie: ',epi_episodename) end, + case when epi_shortname is Null then '' else concat('|','Kurzname: ',epi_shortname) end, + case when epi_partname is Null then '' else concat('|','Episode: ',epi_partname) end, + case when epi_extracol1 is Null then '' else concat('|',epi_extracol1) end, + case when epi_extracol2 is Null then '' else concat('|',epi_extracol2) end, + case when epi_extracol3 is Null then '' else concat('|',epi_extracol3) end, + case when epi_season is Null then '' else concat('|','Staffel: ',cast(epi_season as char)) end, + case when epi_part is Null then '' else concat('|','Staffelfolge: ',cast(epi_part as char)) end, + case when epi_parts is Null then '' else concat('|','Staffelfolgen: ',cast(epi_parts as char)) end, + case when epi_number is Null then '' else concat('|','Folge: ',cast(epi_number as char)) end + ) +) +,'|', ' +') as description +from + useevents; diff --git a/configs/eventsview-ck.sql b/configs/eventsview-ck.sql new file mode 100644 index 0000000..62e54e8 --- /dev/null +++ b/configs/eventsview-ck.sql @@ -0,0 +1,67 @@ +CREATE VIEW eventsview as select cnt_useid useid, cnt_eventid eventid, cnt_channelid channelid, cnt_source source, all_updsp updsp, cnt_updflg updflg, cnt_delflg delflg, cnt_fileref fileref, cnt_tableid tableid, cnt_version version, sub_title title, +case when sub_shorttext is null then + concat( + case when length(ifnull(sub_genre,'')) > 0 then sub_genre else '' end, + case when length(ifnull(sub_genre,'')) > 0 and length(ifnull(sub_country,'')) + length(ifnull(sub_year,'')) > 0 then ' (' else '' end, + case when length(ifnull(sub_country,'')) > 0 then sub_country else '' end, + case when length(ifnull(sub_country,'')) > 0 and length(ifnull(sub_year,'')) > 0 then ' ' else '' end, + case when length(ifnull(sub_year,'')) > 0 then sub_year else '' end, + case when length(ifnull(sub_genre,'')) > 0 and length(ifnull(sub_country,'')) + length(ifnull(sub_year,'')) > 0 then ')' else '' end + ) +else + sub_shorttext +end shorttext, +cnt_starttime starttime, cnt_duration duration, cnt_parentalrating parentalrating, cnt_vps vps, cnt_contents contents, replace( +concat( + TRIM(LEADING '|' FROM + concat( + case when sub_genre is Null then '' else concat('|','Genre: ',sub_genre) end, + case when sub_category is Null then '' else concat('|','Kategorie: ',sub_category) end, + case when sub_country is Null then '' else concat('|','Land: ',sub_country) end, + case when sub_year is Null then '' else concat('|','Jahr: ',substring(sub_year,1,4)) end + ) + ), + concat( + case when sub_shortdescription is Null then '' else concat('||',sub_shortdescription) end, + case when sub_txtrating is Null and sub_shortreview is null then '' else '||' end, + case when sub_txtrating is null then '' else sub_txtrating end, + case when sub_txtrating is Null or sub_shortreview is null then '' else ', ' end, + case when sub_shortreview is Null then '' else sub_shortreview end, + case when sub_tipp is Null and sub_rating is Null then '' else '||' end, + case when sub_tipp is Null then '' else concat('|[',sub_tipp,']') end, + case when sub_rating is Null then '' else concat('|',sub_rating) end, + case when sub_topic is Null then '' else concat('||','Thema: ',sub_topic) end, + case when sub_longdescription is Null then '' else concat('||',sub_longdescription) end, + case when sub_moderator is Null then '' else concat('||','Moderator: ',sub_moderator) end, + case when sub_commentator is Null then '' else concat('||','Kommentar: ',sub_commentator) end, + case when sub_guest is Null then '' else concat('|','Gäste: ',sub_guest) end, + case when cnt_parentalrating is Null or cnt_parentalrating = 0 then '' else concat('||','Altersempfehlung: ab ',cnt_parentalrating) end, + case when sub_actor is Null and sub_producer is Null and sub_other is Null then '' else '|' end, + case when sub_actor is Null then '' else concat('|','Darsteller: ',sub_actor) end, + case when sub_producer is Null then '' else concat('|','Produzent: ',sub_producer) end, + case when sub_other is Null then '' else concat('|','Sonstige: ',sub_other) end, + case when sub_director is Null and sub_screenplay is Null and sub_camera is Null and sub_music is Null and sub_audio is Null and sub_flags is Null then '' else '|' end, + case when sub_director is Null then '' else concat('|','Regie: ',sub_director) end, + case when sub_screenplay is Null then '' else concat('|','Drehbuch: ',sub_screenplay) end, + case when sub_camera is Null then '' else concat('|','Kamera: ',sub_camera) end, + case when sub_music is Null then '' else concat('|','Musik: ',sub_music) end, + case when sub_audio is Null then '' else concat('|','Audio: ',sub_audio) end, + case when sub_flags is Null then '' else concat('|','Flags: ',sub_flags) end, + case when epi_episodename is Null then '' else concat('||','Serie: ',epi_episodename) end, + case when epi_shortname is Null then '' else concat('|','Kurzname: ',epi_shortname) end, + case when epi_partname is Null then '' else concat('|','Episode: ',epi_partname) end, + case when epi_extracol1 is Null then '' else concat('|',epi_extracol1) end, + case when epi_extracol2 is Null then '' else concat('|',epi_extracol2) end, + case when epi_extracol3 is Null then '' else concat('|',epi_extracol3) end, + case when epi_season is Null then '' else concat('|','Staffel: ',cast(epi_season as char)) end, + case when epi_part is Null then '' else concat('|','Staffelfolge: ',cast(epi_part as char)) end, + case when epi_parts is Null then '' else concat('|','Staffelfolgen: ',cast(epi_parts as char)) end, + case when epi_number is Null then '' else concat('|','Folge: ',cast(epi_number as char)) end, + case when cnt_source = sub_source or (sub_category in('Serie','Spielfilm') and length(cnt_longdescription) / length(sub_longdescription) <= 5) or cnt_longdescription is Null then '' else concat('||','DVB EPG:|',cnt_longdescription) end, + case when cnt_source <> sub_source then concat('||','Quelle: ',upper(replace(cnt_source,'vdr','dvb')),'/',upper(sub_source)) else concat('||','Quelle: ',upper(replace(cnt_source,'vdr','dvb'))) end + ) +) +,'|', ' +') as description +from + useevents; diff --git a/configs/eventsview-horchi.sql b/configs/eventsview-horchi.sql new file mode 100644 index 0000000..3e9debf --- /dev/null +++ b/configs/eventsview-horchi.sql @@ -0,0 +1,67 @@ +CREATE VIEW eventsview as select cnt_useid useid, cnt_eventid eventid, cnt_channelid channelid, cnt_source source, all_updsp updsp, cnt_updflg updflg, cnt_delflg delflg, cnt_fileref fileref, cnt_tableid tableid, cnt_version version, sub_title title, +case when sub_shorttext is null then + concat( + case when length(ifnull(sub_genre,'')) > 0 then sub_genre else '' end, + case when length(ifnull(sub_genre,'')) > 0 and length(ifnull(sub_country,'')) + length(ifnull(sub_year,'')) > 0 then ' (' else '' end, + case when length(ifnull(sub_country,'')) > 0 then sub_country else '' end, + case when length(ifnull(sub_country,'')) > 0 and length(ifnull(sub_year,'')) > 0 then ' ' else '' end, + case when length(ifnull(sub_year,'')) > 0 then sub_year else '' end, + case when length(ifnull(sub_genre,'')) > 0 and length(ifnull(sub_country,'')) + length(ifnull(sub_year,'')) > 0 then ')' else '' end + ) +else + sub_shorttext +end shorttext, +cnt_starttime starttime, cnt_duration duration, cnt_parentalrating parentalrating, cnt_vps vps, cnt_contents contents, replace( +concat( + TRIM(LEADING '|' FROM + concat( + case when sub_genre is Null then '' else concat('|','Genre: ',sub_genre) end, + case when sub_category is Null then '' else concat('|','Kategorie: ',sub_category) end, + case when sub_country is Null then '' else concat('|','Land: ',sub_country) end, + case when sub_year is Null then '' else concat('|','Jahr: ',substring(sub_year,1,4)) end, + case when epi_episodename is Null then '' else concat('|Serie: ',epi_episodename,' - Staffel: ',epi_season,' / Folge: ',epi_part) end, + case when sub_flags is Null then '' else concat('|',sub_flags) end, + case when sub_flags is Null or sub_audio is Null then '' else ' ' end, + case when sub_audio is Null then '' else concat('[', replace(sub_audio, ' ', '] ['), ']') end, + case when sub_flags is Null and sub_audio is Null then '|' else '' end, + case when sub_flags is Null or sub_audio is Null then '' else ' ' end, + case when cnt_parentalrating is Null then '' else concat('[FSK ',cnt_parentalrating,']') end, + case when cnt_source <> sub_source then concat(' [EPG: ',upper(replace(cnt_source,'vdr','dvb')),'/',upper(sub_source),']') else concat(' [EPG: ',upper(replace(cnt_source,'vdr','dvb')),']') end + ) + ), + case when sub_tipp is Null then '' else concat('||',sub_tipp) end, + concat( + case when sub_txtrating is Null and sub_shortreview is null then '' else '||Bewertung: ' end, + case when sub_txtrating is null then '' else sub_txtrating end, + case when sub_txtrating is Null or sub_shortreview is null then '' else ', ' end, + case when sub_shortreview is Null then '' else sub_shortreview end, + case when sub_topic is Null then '' else concat('||','Thema: ',sub_topic) end, + case when sub_longdescription is Null then '' else concat('||',sub_longdescription) end, + case when sub_moderator is Null then '' else concat('||','Moderator: ',sub_moderator) end, + case when sub_commentator is Null then '' else concat('||','Kommentar: ',sub_commentator) end, + case when sub_producer is Null then '' else concat('|','Produzent: ',sub_producer) end, + case when sub_guest is Null then '' else concat('|','Gäste: ',sub_guest) end, + case when sub_other is Null then '' else concat('|','Sonstige: ',sub_other) end, + case when sub_actor is Null then '' else concat('|',replace(sub_actor,'), ', ')|')) end, + case when sub_director is Null and sub_screenplay is Null and sub_camera is Null and sub_music is Null then '' else '|' end, + case when sub_director is Null then '' else concat('|','Regie: ',sub_director) end, + case when sub_screenplay is Null then '' else concat('|','Drehbuch: ',sub_screenplay) end, + case when sub_camera is Null then '' else concat('|','Kamera: ',sub_camera) end, + case when sub_music is Null then '' else concat('|','Musik: ',sub_music) end, + case when sub_rating is Null then '' else concat('|',replace(replace(sub_rating,' / ', '|'),' ',': ')) end, + case when epi_episodename is Null then '' else concat('||','Serie: ',epi_episodename) end, + case when epi_shortname is Null then '' else concat('|','Kurzname: ',epi_shortname) end, + case when epi_partname is Null then '' else concat('|','Episode: ',epi_partname) end, + case when epi_extracol1 is Null then '' else concat('|',epi_extracol1) end, + case when epi_extracol2 is Null then '' else concat('|',epi_extracol2) end, + case when epi_extracol3 is Null then '' else concat('|',epi_extracol3) end, + case when epi_season is Null then '' else concat('|','Staffel: ',cast(epi_season as char)) end, + case when epi_part is Null then '' else concat('|','Staffelfolge: ',cast(epi_part as char)) end, + case when epi_parts is Null then '' else concat('|','Staffelfolgen: ',cast(epi_parts as char)) end, + case when epi_number is Null then '' else concat('|','Folge: ',cast(epi_number as char)) end + ) +) +,'|', ' +') as description +from + useevents; diff --git a/configs/eventsview-uti.sql b/configs/eventsview-uti.sql new file mode 100644 index 0000000..2984707 --- /dev/null +++ b/configs/eventsview-uti.sql @@ -0,0 +1,68 @@ +CREATE VIEW eventsview as select cnt_useid useid, cnt_eventid eventid, cnt_channelid channelid, cnt_source source, all_updsp updsp, cnt_updflg updflg, cnt_delflg delflg, cnt_fileref fileref, cnt_tableid tableid, cnt_version version, sub_title title, +case when sub_shorttext is null then + concat( + case when length(ifnull(sub_genre,'')) > 0 then sub_genre else '' end, + case when length(ifnull(sub_genre,'')) > 0 and length(ifnull(sub_country,'')) + length(ifnull(sub_year,'')) > 0 then ' (' else '' end, + case when length(ifnull(sub_country,'')) > 0 then sub_country else '' end, + case when length(ifnull(sub_country,'')) > 0 and length(ifnull(sub_year,'')) > 0 then ' ' else '' end, + case when length(ifnull(sub_year,'')) > 0 then sub_year else '' end, + case when length(ifnull(sub_genre,'')) > 0 and length(ifnull(sub_country,'')) + length(ifnull(sub_year,'')) > 0 then ')' else '' end + ) +else + sub_shorttext +end shorttext, +cnt_starttime starttime, cnt_duration duration, cnt_parentalrating parentalrating, cnt_vps vps, cnt_contents contents, replace( +concat( + TRIM(LEADING '|' FROM + concat( + case when sub_genre is Null then '' else concat('|','Genre: ',sub_genre) end, + case when sub_category is Null then '' else concat('|','Kategorie: ',sub_category) end, + case when sub_country is Null then '' else concat('|','Land: ',sub_country) end, + case when sub_year is Null then '' else concat('|','Jahr: ',substring(sub_year,1,4)) end, + case when sub_flags is Null then '' else concat('|',sub_flags) end, + case when sub_flags is Null or sub_audio is Null then '' else ' ' end, + case when sub_audio is Null then '' else concat('[', replace(sub_audio, ' ', '] ['), ']') end, + case when sub_flags is Null and sub_audio is Null then '|' else '' end, + case when sub_flags is Null or sub_audio is Null then '' else ' ' end, + case when cnt_parentalrating is Null then '' else concat('[FSK ',cnt_parentalrating,']') end + ) + ), + case when sub_shortdescription is Null then '' else concat('||',sub_shortdescription) end, + case when sub_source <> 'epgdata' and sub_tipp = '[TagesTipp]' then '||Tagestipp' else '' end, + concat( + case when sub_txtrating is Null and sub_shortreview is null then '' else '||Bewertung: ' end, + case when sub_txtrating is null then '' else sub_txtrating end, + case when sub_txtrating is Null or sub_shortreview is null then '' else ', ' end, + case when sub_shortreview is Null then '' else sub_shortreview end, + case when sub_topic is Null then '' else concat('||','Thema: ',sub_topic) end, + case when sub_longdescription is Null then '' else concat('||',sub_longdescription) end, + case when sub_moderator is Null then '' else concat('||','Moderator: ',sub_moderator) end, + case when sub_commentator is Null then '' else concat('||','Kommentar: ',sub_commentator) end, + case when sub_producer is Null then '' else concat('|','Produzent: ',sub_producer) end, + case when sub_guest is Null then '' else concat('|','Gäste: ',sub_guest) end, + case when sub_other is Null then '' else concat('|','Sonstige: ',sub_other) end, + case when sub_actor is Null then '' else concat('|',replace(sub_actor,'), ', ')|')) end, + case when sub_director is Null and sub_screenplay is Null and sub_camera is Null and sub_music is Null then '' else '|' end, + case when sub_director is Null then '' else concat('|','Regie: ',sub_director) end, + case when sub_screenplay is Null then '' else concat('|','Drehbuch: ',sub_screenplay) end, + case when sub_camera is Null then '' else concat('|','Kamera: ',sub_camera) end, + case when sub_music is Null then '' else concat('|','Musik: ',sub_music) end, + case when sub_rating is Null then '' else concat('|',replace(replace(sub_rating,' / ', '|'),' ',': ')) end, + case when epi_episodename is Null then '' else concat('||','Serie: ',epi_episodename) end, + case when epi_shortname is Null then '' else concat('|','Kurzname: ',epi_shortname) end, + case when epi_partname is Null then '' else concat('|','Episode: ',epi_partname) end, + case when epi_extracol1 is Null then '' else concat('|',epi_extracol1) end, + case when epi_extracol2 is Null then '' else concat('|',epi_extracol2) end, + case when epi_extracol3 is Null then '' else concat('|',epi_extracol3) end, + case when epi_season is Null then '' else concat('|','Staffel: ',cast(epi_season as char)) end, + case when epi_part is Null then '' else concat('|','Staffelfolge: ',cast(epi_part as char)) end, + case when epi_part is Null then '' else concat('|','Staffelfolgen: ',cast(epi_parts as char)) end, + case when epi_number is Null then '' else concat('|','Folge: ',cast(epi_number as char)) end, + case when cnt_source = sub_source or (sub_category in('Serie','Spielfilm') and length(cnt_longdescription) / length(sub_longdescription) <= 5) or cnt_longdescription is Null then '' else concat('||','DVB EPG:|',cnt_longdescription) end, + case when cnt_source <> sub_source then concat('||','Quelle: ',upper(replace(cnt_source,'vdr','dvb')),'/',upper(sub_source)) else concat('||','Quelle: ',upper(replace(cnt_source,'vdr','dvb'))) end + ) +) +,'|', ' +') as description +from + useevents; diff --git a/configs/eventsview.sql b/configs/eventsview.sql new file mode 100644 index 0000000..6cee8af --- /dev/null +++ b/configs/eventsview.sql @@ -0,0 +1,66 @@ +CREATE VIEW eventsview as select cnt_useid useid, cnt_eventid eventid, cnt_channelid channelid, cnt_source source, all_updsp updsp, cnt_updflg updflg, cnt_delflg delflg, cnt_fileref fileref, cnt_tableid tableid, cnt_version version, sub_title title, +case when sub_shorttext is null then + concat( + case when length(ifnull(sub_genre,'')) > 0 then sub_genre else '' end, + case when length(ifnull(sub_genre,'')) > 0 and length(ifnull(sub_country,'')) + length(ifnull(sub_year,'')) > 0 then ' (' else '' end, + case when length(ifnull(sub_country,'')) > 0 then sub_country else '' end, + case when length(ifnull(sub_country,'')) > 0 and length(ifnull(sub_year,'')) > 0 then ' ' else '' end, + case when length(ifnull(sub_year,'')) > 0 then sub_year else '' end, + case when length(ifnull(sub_genre,'')) > 0 and length(ifnull(sub_country,'')) + length(ifnull(sub_year,'')) > 0 then ')' else '' end + ) +else + sub_shorttext +end shorttext, +cnt_starttime starttime, cnt_duration duration, cnt_parentalrating parentalrating, cnt_vps vps, cnt_contents contents, replace( +concat( + TRIM(LEADING '|' FROM + concat( + case when sub_genre is Null then '' else concat('|','Genre: ',sub_genre) end, + case when sub_category is Null then '' else concat('|','Kategorie: ',sub_category) end, + case when sub_country is Null then '' else concat('|','Land: ',sub_country) end, + case when sub_year is Null then '' else concat('|','Jahr: ',substring(sub_year,1,4)) end + ) + ), + concat( + case when sub_shortdescription is Null then '' else concat('||',sub_shortdescription) end, + case when sub_txtrating is Null and sub_shortreview is null then '' else '||' end, + case when sub_txtrating is null then '' else sub_txtrating end, + case when sub_txtrating is Null or sub_shortreview is null then '' else ', ' end, + case when sub_shortreview is Null then '' else sub_shortreview end, + case when sub_tipp is Null and sub_rating is Null then '' else '||' end, + case when sub_tipp is Null then '' else concat('|',sub_tipp) end, + case when sub_rating is Null then '' else concat('|',sub_rating) end, + case when sub_topic is Null then '' else concat('||','Thema: ',sub_topic) end, + case when sub_longdescription is Null then '' else concat('||',sub_longdescription) end, + case when sub_moderator is Null then '' else concat('||','Moderator: ',sub_moderator) end, + case when sub_commentator is Null then '' else concat('||','Kommentar: ',sub_commentator) end, + case when sub_guest is Null then '' else concat('|','Gäste: ',sub_guest) end, + case when cnt_parentalrating is Null or cnt_parentalrating = 0 then '' else concat('||','Altersempfehlung: ab ',cnt_parentalrating) end, + case when sub_actor is Null and sub_producer is Null and sub_other is Null then '' else '|' end, + case when sub_actor is Null then '' else concat('|','Darsteller: ',sub_actor) end, + case when sub_producer is Null then '' else concat('|','Produzent: ',sub_producer) end, + case when sub_other is Null then '' else concat('|','Sonstige: ',sub_other) end, + case when sub_director is Null and sub_screenplay is Null and sub_camera is Null and sub_music is Null and sub_audio is Null and sub_flags is Null then '' else '|' end, + case when sub_director is Null then '' else concat('|','Regie: ',sub_director) end, + case when sub_screenplay is Null then '' else concat('|','Drehbuch: ',sub_screenplay) end, + case when sub_camera is Null then '' else concat('|','Kamera: ',sub_camera) end, + case when sub_music is Null then '' else concat('|','Musik: ',sub_music) end, + case when sub_audio is Null then '' else concat('|','Audio: ',sub_audio) end, + case when sub_flags is Null then '' else concat('|','Flags: ',sub_flags) end, + case when epi_episodename is Null then '' else concat('||','Serie: ',epi_episodename) end, + case when epi_shortname is Null then '' else concat('|','Kurzname: ',epi_shortname) end, + case when epi_partname is Null then '' else concat('|','Episode: ',epi_partname) end, + case when epi_extracol1 is Null then '' else concat('|',epi_extracol1) end, + case when epi_extracol2 is Null then '' else concat('|',epi_extracol2) end, + case when epi_extracol3 is Null then '' else concat('|',epi_extracol3) end, + case when epi_season is Null then '' else concat('|','Staffel: ',cast(epi_season as char)) end, + case when epi_part is Null then '' else concat('|','Staffelfolge: ',cast(epi_part as char)) end, + case when epi_parts is Null then '' else concat('|','Staffelfolgen: ',cast(epi_parts as char)) end, + case when epi_number is Null then '' else concat('|','Folge: ',cast(epi_number as char)) end, + case when cnt_source <> sub_source then concat('||','Quelle: ',upper(replace(cnt_source,'vdr','dvb')),'/',upper(sub_source)) else concat('||','Quelle: ',upper(replace(cnt_source,'vdr','dvb'))) end + ) +) +,'|', ' +') as description +from + useevents; diff --git a/configs/eventsviewplain-3po.sql b/configs/eventsviewplain-3po.sql new file mode 100644 index 0000000..1b2c511 --- /dev/null +++ b/configs/eventsviewplain-3po.sql @@ -0,0 +1,99 @@ +CREATE VIEW eventsviewplain +as +select + cnt_useid, + cnt_eventid, + cnt_channelid, + sub_eventid as imageid, + cnt_source, + all_updsp, + cnt_updflg as updflg, + cnt_delflg, + cnt_fileref, + cnt_tableid, + cnt_version, + sub_title, + sub_comptitle, + case + when ifnull(sub_compshorttext,'') = '' or sub_comptitle=sub_compshorttext or ( substring(sub_compshorttext,1,1)='S' and substring(sub_compshorttext,2,1) REGEXP ('[0-9]') ) then '' + else sub_compshorttext + end sub_compshorttext, + sub_complongdescription, + case + when ifnull(sub_shorttext,'') = '' or sub_comptitle=sub_compshorttext or ( substring(sub_shorttext,1,1)='S' and substring(sub_shorttext,2,1) REGEXP ('[0-9]') ) then '' + else sub_shorttext + end sub_shorttext, + cnt_starttime, + cnt_duration, + cnt_parentalrating, + cnt_vps, + cnt_contents, + sub_imagecount, + sub_genre, + sub_category, + sub_country, + sub_year, + sub_shortdescription, + concat( + case + when cnt_source = 'epgdata' then + case when sub_rating like '%Allgemein *****%' then concat('|','Bewertung: Sehr empfehlenswert') + when sub_rating like '%Allgemein ****%' then concat('|','Bewertung: Empfehlenswert') + when sub_rating like '%Allgemein ***%' then concat('|','Bewertung: Eher durchschnittlich') + when sub_rating like '%Allgemein **%' then concat('|','Bewertung: Eher nicht empfehlenswert') + when sub_rating like '%Allgemein *%' then concat('|','Bewertung: Eher uninteressant') + else '' + end + else + case when sub_numrating = 5 then 'Bewertung: Einer der besten Filme aller Zeiten' + when sub_numrating = 4 then 'Bewertung: Sehr empfehlenswert' + when sub_numrating = 3 then 'Bewertung: Empfehlenswert' + when sub_numrating = 2 then 'Bewertung: Eher durchschnittlich' + when sub_numrating = 1 then 'Bewertung: Eher uninteressant' + else '' + end + end, + case when ((cnt_source = 'epgdata' and sub_rating is null) or sub_numrating is Null) or sub_shortreview is null then '' else ', ' end, + case when sub_shortreview is Null then '' else sub_shortreview end +) as sub_shortreview, + sub_tipp, + sub_rating, + sub_numrating, + sub_txtrating, + sub_topic, + sub_longdescription, + case when cnt_source != sub_source and sub_category not in('Serie','Spielfilm') then cnt_longdescription end cnt_longdescription, + sub_moderator, + sub_guest, + sub_actor, + sub_producer, + sub_other, + sub_director, + sub_commentator, + sub_screenplay, + sub_camera, + sub_music, + sub_audio, + sub_flags, + sub_episodecompname, + sub_episodecompshortname, + sub_episodecomppartname, + sub_scrseriesid, + sub_scrseriesepisode, + sub_scrmovieid, + epi_episodename, + epi_shortname, + epi_partname, + epi_lang, + epi_extracol1, + epi_extracol2, + epi_extracol3, + epi_season, + epi_part, + epi_parts, + epi_number, + case when cnt_source <> sub_source then concat(upper(replace(cnt_source,'vdr','dvb')),'/',upper(sub_source)) else upper(replace(cnt_source,'vdr','dvb')) end merge +from + useevents +where + cnt_updflg in('A','L','P'); diff --git a/configs/eventsviewplain.sql b/configs/eventsviewplain.sql new file mode 100644 index 0000000..51b9a71 --- /dev/null +++ b/configs/eventsviewplain.sql @@ -0,0 +1,78 @@ +CREATE VIEW eventsviewplain +as +select + cnt_useid, + cnt_eventid, + cnt_channelid, + sub_eventid as imageid, + cnt_source, + all_updsp, + cnt_updflg as updflg, + cnt_delflg, + cnt_fileref, + cnt_tableid, + cnt_version, + sub_title, + sub_comptitle, + case + when ifnull(sub_compshorttext,'') = '' or sub_comptitle=sub_compshorttext or ( substring(sub_compshorttext,1,1)='S' and substring(sub_compshorttext,2,1) REGEXP ('[0-9]') ) then '' + else sub_compshorttext + end sub_compshorttext, + sub_complongdescription, + case + when ifnull(sub_shorttext,'') = '' or sub_comptitle=sub_compshorttext or ( substring(sub_shorttext,1,1)='S' and substring(sub_shorttext,2,1) REGEXP ('[0-9]') ) then '' + else sub_shorttext + end sub_shorttext, + cnt_starttime, + cnt_duration, + cnt_parentalrating, + cnt_vps, + cnt_contents, + sub_imagecount, + sub_genre, + sub_category, + sub_country, + sub_year, + sub_shortdescription, + sub_shortreview, + sub_tipp, + sub_rating, + sub_numrating, + sub_txtrating, + sub_topic, + sub_longdescription, + case when cnt_source != sub_source and sub_category not in('Serie','Spielfilm') then cnt_longdescription end cnt_longdescription, + sub_moderator, + sub_guest, + sub_actor, + sub_producer, + sub_other, + sub_director, + sub_commentator, + sub_screenplay, + sub_camera, + sub_music, + sub_audio, + sub_flags, + sub_episodecompname, + sub_episodecompshortname, + sub_episodecomppartname, + sub_scrseriesid, + sub_scrseriesepisode, + sub_scrmovieid, + epi_episodename, + epi_shortname, + epi_partname, + epi_lang, + epi_extracol1, + epi_extracol2, + epi_extracol3, + epi_season, + epi_part, + epi_parts, + epi_number, + case when cnt_source <> sub_source then concat(upper(replace(cnt_source,'vdr','dvb')),'/',upper(sub_source)) else upper(replace(cnt_source,'vdr','dvb')) end merge +from + useevents +where + cnt_updflg in('A','L','P'); diff --git a/configs/getcrosslvr.sql b/configs/getcrosslvr.sql new file mode 100644 index 0000000..bc6f943 --- /dev/null +++ b/configs/getcrosslvr.sql @@ -0,0 +1,34 @@ +CREATE FUNCTION getcrosslvr ( comp1 varchar(300), comp2 varchar(300) ) +RETURNS int +NOT DETERMINISTIC +BEGIN +DECLARE ratio DECIMAL(7,2); +DECLARE shorter varchar(300); +DECLARE longer varchar(300); +DECLARE complenght int; +DECLARE crosslv int; +DECLARE crosslvt int; +IF char_length(comp1) = 0 then + set ratio = 999; + set shorter = comp1; set longer = comp2; set complenght = char_length(comp2); +ELSEIF char_length(comp2) = 0 then + set ratio = 999; + set shorter = comp2; set longer = comp1; set complenght = char_length(comp1); +ELSEIF char_length(comp1) >= char_length(comp2) then + set ratio = round(char_length(comp1) / char_length(comp2),2); + set shorter = comp2; set longer = comp1; set complenght = char_length(comp1); +else set ratio = round(char_length(comp2) / char_length(comp1),2); + set shorter = comp1; set longer = comp2; set complenght = char_length(comp2); +END IF; +IF comp1 is null or comp2 is null then set crosslv = 99; +ELSEIF comp1 = comp2 then set crosslv = 0; +ELSEIF comp1 is Null or comp2 is Null or char_length(comp1) = 0 or char_length(comp2) = 0 then set crosslv = 99; +ELSEIF complenght >= 10 and ratio >= 3.2 then set crosslv = 99; +ELSEIF ratio < 1.5 then set crosslv = epglvr(shorter,longer); +ELSE set crosslvt = epglvr(shorter,substr(longer,1,complenght/2)); + IF crosslvt < 60 then set crosslv = crosslvt; + ELSE set crosslv = epglvr(substr(longer from complenght/2+1),shorter); + END IF; +END IF; +RETURN crosslv; +END diff --git a/configs/getlvrmin.sql b/configs/getlvrmin.sql new file mode 100644 index 0000000..d075dfd --- /dev/null +++ b/configs/getlvrmin.sql @@ -0,0 +1,51 @@ +CREATE FUNCTION getlvrmin ( vdr_starttime int(10), ext_starttime int(10), vdr_duration int(5), ext_duration int(5), lv1 int(3), lv2 int(3), lv3 int(3), lv4 int(3) ) +RETURNS int +NOT DETERMINISTIC +BEGIN +DECLARE delta_st int; +DECLARE delta_du int; +DECLARE lv_time int default 0; +DECLARE lv_min int; +DECLARE lv_dur int; +DECLARE lv_sum int; + +IF vdr_duration = ext_duration then set delta_du = 100; +ELSEIF vdr_duration > ext_duration then set delta_du = round(vdr_duration/ext_duration*100,0); +ELSE set delta_du = round(ext_duration/vdr_duration*100,0); +END IF; + +IF delta_du > 184 then set lv_dur = 50; +ELSEIF delta_du > 168 then set lv_dur = 40; +ELSEIF delta_du > 152 then set lv_dur = 30; +ELSEIF delta_du > 136 then set lv_dur = 20; +ELSEIF delta_du > 120 then set lv_dur = 10; +ELSE set lv_dur = 0; +END IF; + +IF vdr_starttime = ext_starttime then set delta_st = 100; +ELSEIF vdr_starttime > ext_starttime then set delta_st = vdr_starttime-ext_starttime; +ELSE set delta_st = ext_starttime-vdr_starttime; +END IF; + +IF delta_st <= 600 then + IF delta_st > 540 then set lv_time = 50; + ELSEIF delta_st > 480 then set lv_time = 40; + ELSEIF delta_st > 420 then set lv_time = 30; + ELSEIF delta_st > 360 then set lv_time = 20; + ELSEIF delta_st > 300 then set lv_time = 10; + ELSE set lv_time = 0; + END IF; + + set lv_min = LEAST(lv1,lv2,lv3,lv4); + + set lv_sum = lv_time + lv_dur + lv_min; + +ELSEIF lv_dur + lv1 + lv4 <= 60 then set lv_sum = 60; +ELSEIF lv1 <= 30 and vdr_starttime = ext_starttime then set lv_sum = 60; +ELSEIF lv1 <= 30 and vdr_duration/abs(vdr_starttime-ext_starttime) >= 2.5 then set lv_sum = 60; +ELSE set lv_sum = 99; +END IF; + +RETURN lv_sum; + +END diff --git a/configs/getupdflg.sql b/configs/getupdflg.sql new file mode 100644 index 0000000..dd63734 --- /dev/null +++ b/configs/getupdflg.sql @@ -0,0 +1,33 @@ +CREATE FUNCTION getupdflg ( master_id INT(11) ) +RETURNS CHAR +NOT DETERMINISTIC +BEGIN +DECLARE upd_flg CHAR; + SET upd_flg = ( + select case + when ev.source != 'vdr' and ev.starttime <= cm.mergesp and ev.masterid != ev.useid then 'C' + when ev.source != 'vdr' and ev.starttime <= cm.mergesp and jo.masterid is not Null then 'T' + when ev.delflg = 'Y' then 'D' + when ev.source != 'vdr' and ev.starttime <= cm.mergesp and jo.masterid is Null then 'R' + when ev.source != 'vdr' and ev.starttime > cm.mergesp then 'A' + when ev.source = 'vdr' and cm.mergesp is Null then 'P' + when ev.source = 'vdr' and ev.starttime > cm.mergesp then 'I' + when ev.source = 'vdr' and ev.starttime <= cm.mergesp and ev.masterid = ev.useid then 'A' + when ev.source = 'vdr' and ev.starttime <= cm.mergesp and ev.masterid != ev.useid then 'L' + end +from + events ev +left join + events jo +on + ev.masterid = jo.useid and jo.useid != 0 and jo.updflg = 'L' +left join + (select distinct mergesp,channelid from channelmap where channelmap.source != 'vdr') cm +on + ev.channelid = cm.channelid +where + ev.masterid = master_id + limit 1 +); +RETURN upd_flg; +END diff --git a/configs/mergeepg.sql b/configs/mergeepg.sql new file mode 100644 index 0000000..bde021a --- /dev/null +++ b/configs/mergeepg.sql @@ -0,0 +1,401 @@ +CREATE PROCEDURE mergeepg () +BEGIN +/* +* declare variables +*/ +DECLARE startrun INT; +DECLARE lastrun INT; +/* +* configure merge +*/ +set @epi ='a'; +set @img ='b'; +set @sht =''; +/* +* fix useid = 0 +*/ +update events set useid = masterid where useid = 0; +/* +* cleanup deleted Links +*/ +update + events e +set + e.useid = e.masterid, + e.updsp = unix_timestamp() +where + e.source = 'vdr' and + e.updflg in ('D','R') and + e.useid != e.masterid and + e.starttime + e.duration >= unix_timestamp(); +/* +* cleanup broken Links +*/ +update + events t + inner join +( + select + v.masterid, + e.starttime, + e.comptitle, + e.compshorttext, + e.updflg + from + events v + left join + events e + on e.masterid = v.useid and v.masterid != e.masterid and e.updflg in ('T','C') and e.delflg is Null + where + v.updflg in('L') and + v.starttime + v.duration >= unix_timestamp() +) s +on t.masterid=s.masterid +set + t.useid = t.masterid, + t.updflg = case when t.delflg = 'Y' then 'D' else 'A' end, + t.updsp = unix_timestamp() +where + s.updflg is Null or + abs(s.starttime - t.starttime) > 21600 or + (abs(s.starttime - t.starttime) > 3600 and + getlvrmin(0,0,0,0, + getcrosslvr(s.comptitle,t.comptitle), + getcrosslvr(s.comptitle,t.compshorttext), + getcrosslvr(s.compshorttext,t.comptitle), + getcrosslvr(s.compshorttext,t.compshorttext)) >= 60); +/* +* cleanup broken Targets +*/ +update + events t + inner join +( + select + e.masterid, + v.updflg + from + events e + left join + events v + on e.masterid = v.useid and v.masterid != e.masterid and v.updflg = 'L' + where + e.updflg in('C','T') and + e.starttime + e.duration >= unix_timestamp() +) s +on t.masterid=s.masterid +set + t.useid = t.masterid, + t.updflg = case when t.delflg = 'Y' then 'D' else 'R' end, + t.updsp = unix_timestamp() +where + s.updflg is Null; +/* +* reset tables +*/ +truncate snapshot; +truncate analyse; +/* +* prepare snapshot +*/ +insert into snapshot +select + distinct ev.channelid, ev.source, masterid, ev.eventid, useid, starttime, duration, title, comptitle, shorttext, compshorttext, ev.updsp, + case when episodecompname is Null then Null else 'X' end episodecompname, + case when ev.source = 'vdr' then Null else cm.merge end merge, + case when ev.imagecount >0 then 'X' else Null end images +from + events ev + inner join channelmap cm on ( ev.channelid = cm.channelid ) +where + ( ev.source = cm.source or ev.source = 'vdr' ) + AND + ev.updflg in ('I','A','R','S') + AND + ev.starttime between unix_timestamp() - ev.duration and unix_timestamp() + 259200 + AND + cm.merge in(1,2); +/* +* do the magic +*/ +set @pk1 =''; +set @rn1 =10000; +set @lvmin =''; +insert ignore into analyse +SELECT channelid, vdr_masterid, vdr_eventid, vdr_starttime, vdr_duration, vdr_title, vdr_shorttext, ext_masterid, ext_eventid, ext_starttime, ext_duration, ext_title, ext_shorttext, ext_episodecompname, ext_merge, ext_images, lvmin, + epi+img+sht + ranklv as rank +FROM +( + SELECT channelid, vdr_masterid, vdr_eventid, vdr_starttime, vdr_duration, vdr_title, vdr_shorttext, ext_masterid, ext_eventid, ext_starttime, ext_duration, ext_title, ext_shorttext, ext_episodecompname, ext_merge, ext_images, lvmin, + case when ext_episodecompname is not Null then 0 else (case @epi when 'a' then 1000 when 'b' then 100 when 'c' then 10 else 0 end) end epi, + case when ext_images is not Null then 0 else (case @img when 'a' then 1000 when 'b' then 100 when 'c' then 10 else 0 end) end img, + case when ext_shorttext is not Null then 0 else (case @sht when 'a' then 1000 when 'b' then 100 when 'c' then 10 else 0 end) end sht, + @rn1 := if(@pk1=concat(channelid,vdr_eventid,ext_source), if(@lv=lvmin, @rn1, @rn1+10000),10000+ext_merge) as ranklv, + @pk1 := concat(channelid,vdr_eventid,ext_source), + @lv := lvmin + FROM + ( + select + vdr.channelid, + vdr.masterid vdr_masterid, vdr.eventid vdr_eventid, vdr.starttime vdr_starttime, vdr.duration vdr_duration, vdr.title vdr_title, vdr.shorttext vdr_shorttext, + ext.masterid ext_masterid, ext.eventid ext_eventid, ext.starttime ext_starttime, ext.duration ext_duration, ext.title ext_title, ext.shorttext ext_shorttext, + ext.source ext_source,ext.episode ext_episodecompname, ext.merge ext_merge, ext.images ext_images, + getlvrmin(vdr.starttime,ext.starttime,vdr.duration,ext.duration, + getcrosslvr(vdr.comptitle,ext.comptitle), + getcrosslvr(vdr.comptitle,ext.compshorttext), + getcrosslvr(vdr.compshorttext,ext.comptitle), + getcrosslvr(vdr.compshorttext,ext.compshorttext) + ) lvmin + from + snapshot vdr + inner join + snapshot ext + on vdr.channelid = ext.channelid and + vdr.starttime - ext.starttime between -1200 and +1200 and + (vdr.duration+1) / (ext.duration+1) * 100 between 50 and 200 + where + vdr.source = 'vdr' + AND + vdr.source <> ext.source + ORDER BY channelid,vdr_eventid,ext_merge desc,lvmin + ) A + where lvmin <= 60 +) B +order by channelid,vdr_eventid,rank; +/* +* update mergesp +*/ +update + channelmap cm, + (select channelid,max(vdr_starttime) merge_sp from analyse group by channelid) an +set + cm.mergesp = an.merge_sp +where + an.channelid = cm.channelid and + an.merge_sp > cm.mergesp; +/* +* update useid on vdr events +*/ +update + events ev, + analyse an +set + ev.useid = an.ext_masterid +where + ev.masterid = vdr_masterid and + ev.channelid = an.channelid; +/* +* update useid on ext events +*/ +update + events ext, + events vdr +set + ext.useid = case when ext.updflg in('I','R') then vdr.masterid else ext.useid end, + ext.updflg = case when ext.updflg in('I','R') then 'C' else 'T' end, + ext.updsp = case when ext.updflg in('I','R') then unix_timestamp() else ext.updsp end +where + ext.masterid = vdr.useid and + ext.channelid = vdr.channelid and + ext.updflg in('I','A','R','S') and + ext.source <> vdr.source and + vdr.source = 'vdr'; +/* +* update all other relevant updflg and updsp +*/ +update + events ev, + (select distinct channelid,mergesp from channelmap where source != 'vdr') cm +set + ev.updflg = case when ev.source = 'vdr' and ev.masterid != ev.useid then 'L' + when ev.source = 'vdr' and ev.masterid = ev.useid then 'A' + when ev.source != 'vdr' and ev.updflg = 'S' then 'I' + when ev.source != 'vdr' then 'R' + end, + ev.updsp = case when source = 'vdr' and ev.masterid = ev.useid and ev.updflg = 'A' then ev.updsp + else unix_timestamp() + end +where + ev.channelid = cm.channelid and + ev.starttime < cm.mergesp + ev.duration/10 and + ( ev.source = 'vdr' and ev.updflg in ('I','A') or + ev.source != 'vdr' and ev.updflg in ('A','S') ); +/* +* reinitialize prior removed dvb events +*/ +update + events ev, + (select distinct channelid,mergesp from channelmap where source != 'vdr') cm +set + ev.updflg = 'A', + ev.useid = ev.masterid, + ev.updsp = unix_timestamp() +where + ev.channelid = cm.channelid and + ev.starttime < cm.mergesp + ev.duration/10 and + ev.source = 'vdr' and + ev.updflg in ('R'); +/* +* get startrun / lastrun +*/ +SET startrun = (select unix_timestamp()); +SET lastrun = (select value from parameters where owner = 'epgd' and name = 'mergeStart'); +/* +* truncate useevents if needed +*/ +IF lastrun = 0 then truncate table useevents; +END IF; +/* +* update useevents +*/ +insert into + useevents( cnt_source, cnt_channelid, cnt_eventid, cnt_masterid, cnt_useid, sub_source, sub_eventid, all_updsp, cnt_updflg, cnt_delflg, cnt_fileref, cnt_tableid, cnt_version, sub_title, sub_shorttext, sub_comptitle, sub_compshorttext, sub_genre, sub_country, sub_year, cnt_starttime, cnt_duration, cnt_parentalrating, cnt_vps, cnt_contents, sub_category, sub_shortdescription, sub_shortreview, sub_tipp, sub_rating, sub_numrating, sub_txtrating, sub_topic, sub_longdescription, sub_complongdescription, cnt_longdescription, sub_moderator, sub_guest, sub_actor, sub_producer, sub_other, sub_director, sub_commentator, sub_screenplay, sub_camera, sub_music, sub_audio, sub_flags, sub_imagecount, sub_scrseriesid, sub_scrseriesepisode, sub_scrmovieid, sub_scrsp, sub_episodecompname, sub_episodecompshortname, sub_episodecomppartname, epi_episodename, epi_shortname, epi_partname, epi_lang, epi_extracol1, epi_extracol2, epi_extracol3, epi_season, epi_part, epi_parts, epi_number ) +select + cnt.source, + cnt.channelid, + cnt.eventid, + cnt.masterid, + cnt.useid, + sub.source, + sub.eventid, + GREATEST(cnt.updsp,sub.updsp,IFNULL(epi.updsp,0)), + cnt.updflg, + cnt.delflg, + cnt.fileref, + cnt.tableid, + cnt.version, + sub.title, + sub.shorttext, + sub.comptitle, + sub.compshorttext, + sub.genre, + sub.country, + sub.year, + cnt.starttime, + cnt.duration, + cnt.parentalrating, + cnt.vps, + cnt.contents, + sub.category, + sub.shortdescription, + sub.shortreview, + sub.tipp, + sub.rating, + sub.numrating, + sub.txtrating, + sub.topic, + sub.longdescription, + sub.complongdescription, + cnt.longdescription, + sub.moderator, + sub.guest, + sub.actor, + sub.producer, + sub.other, + sub.director, + sub.commentator, + sub.screenplay, + sub.camera, + sub.music, + sub.audio, + sub.flags, + sub.imagecount, + sub.scrseriesid, + sub.scrseriesepisode, + sub.scrmovieid, + sub.scrsp, + sub.episodecompname, + sub.episodecompshortname, + sub.episodecomppartname, + epi.episodename, + epi.shortname, + epi.partname, + epi.lang, + epi.extracol1, + epi.extracol2, + epi.extracol3, + epi.season, + epi.part, + epi.parts, + epi.number +from + events cnt + inner join events sub on (case when cnt.useid = 0 then cnt.masterid else cnt.useid end = sub.masterid) + left outer join episodes epi on (sub.episodecompname = epi.compname and sub.episodecomppartname = epi.comppartname and sub.episodelang = epi.lang) +where + cnt.updflg in('A','L','P','C','R','D','X') and + GREATEST(cnt.updsp,sub.updsp,IFNULL(epi.updsp,0)) >= lastrun - 5 +ON DUPLICATE KEY UPDATE + cnt_masterid = cnt.masterid, + cnt_useid = cnt.useid, + sub_source = sub.source, + sub_eventid = sub.eventid, + all_updsp = GREATEST(cnt.updsp,sub.updsp,IFNULL(epi.updsp,0)), + cnt_updflg = cnt.updflg, + cnt_delflg = cnt.delflg, + cnt_fileref = cnt.fileref, + cnt_tableid = cnt.tableid, + cnt_version = cnt.version, + sub_title = sub.title, + sub_shorttext = sub.shorttext, + sub_comptitle = sub.comptitle, + sub_compshorttext = sub.compshorttext, + sub_genre = sub.genre, + sub_country = sub.country, + sub_year = sub.year, + cnt_starttime = cnt.starttime, + cnt_duration = cnt.duration, + cnt_parentalrating = cnt.parentalrating, + cnt_vps = cnt.vps, + cnt_contents = cnt.contents, + sub_category = sub.category, + sub_shortdescription = sub.shortdescription, + sub_shortreview = sub.shortreview, + sub_tipp = sub.tipp, + sub_rating = sub.rating, + sub_numrating = sub.numrating, + sub_txtrating = sub.txtrating, + sub_topic = sub.topic, + sub_longdescription = sub.longdescription, + sub_complongdescription = sub.complongdescription, + cnt_longdescription = cnt.longdescription, + sub_moderator = sub.moderator, + sub_guest = sub.guest, + sub_actor = sub.actor, + sub_producer = sub.producer, + sub_other = sub.other, + sub_director = sub.director, + sub_commentator = sub.commentator, + sub_screenplay = sub.screenplay, + sub_camera = sub.camera, + sub_music = sub.music, + sub_audio = sub.audio, + sub_flags = sub.flags, + sub_imagecount = sub.imagecount, + sub_scrseriesid = sub.scrseriesid, + sub_scrseriesepisode = sub.scrseriesepisode, + sub_scrmovieid = sub.scrmovieid, + sub_scrsp = sub.scrsp, + sub_episodecompname = sub.episodecompname, + sub_episodecompshortname = sub.episodecompshortname, + sub_episodecomppartname = sub.episodecomppartname, + epi_episodename = epi.episodename, + epi_shortname = epi.shortname, + epi_partname = epi.partname, + epi_lang = epi.lang, + epi_extracol1 = epi.extracol1, + epi_extracol2 = epi.extracol2, + epi_extracol3 = epi.extracol3, + epi_season = epi.season, + epi_part = epi.part, + epi_parts = epi.parts, + epi_number = epi.number; +/* +* remove hidden events +*/ +delete from useevents where (cnt_source,cnt_channelid,cnt_eventid) in( select source,channelid,eventid from events where updflg in ('T','S','I') ); +/* +* update lastrun +*/ +update parameters set updsp = unix_timestamp(), value = startrun where owner = 'epgd' and name = 'mergeStart'; +END diff --git a/configs/recording.py b/configs/recording.py new file mode 100644 index 0000000..fedebb3 --- /dev/null +++ b/configs/recording.py @@ -0,0 +1,155 @@ +# ------------------------------------------------------------------------------------------# ---------------------------------------------------- +# - after importing 'event' the event object is available +# with the following methods: +# +# title +# shorttext +# starttime +# year +# category +# episodname +# shortname +# partname +# season +# part +# number +# extracol1 +# extracol2 +# extracol3 +# +# namingmode -> timers naming mode { 1,2,3,4,5 } - see epgservice.h +# tmplExpression +# +# - implement at least the function 'name()' witch have to return the name of the recording +# if the result was empty VDRs typical recording name will be used +# ------------------------------------------------------------------------------------------ + +import event + +def name(): + + import locale + locale.setlocale(locale.LC_ALL, 'de_DE.UTF-8') + import time + + if event.namingmode() == 1: # Auto + + if event.episodname(): + if event.shortname(): + title = event.shortname() + else: + title = event.episodname() + + part = "%02i" % int(event.part()) + number = "%03i" % int(event.number()) + + if event.title() == 'Tatort': + if event.extracol1(): + ermittler = event.extracol1()[11:] + else: + ermittler = '' + + if event.extracol2(): + ort = event.extracol2()[5:] + else: + ort = '' + + season = str(int(event.season())+1969) + return "Tatort~" + ort + "~" + ermittler + "~" + season + "x" + part + " - " + number + ". " + event.shorttext() + + else: + if event.title() == 'Polizeiruf 110': + season = str(int(event.season())+1971) + else: + season = "%02i" % int(event.season()) + + return title + "~" + season + "x" + part + " - " + number + ". " + event.shorttext() + + elif event.category() == 'Serie': + if event.shorttext() and event.title() != event.shorttext(): + return event.title() + "~" + event.shorttext() + else: + return event.title() + "~" + time.strftime("%a %d.%m.%Y %H:%M", time.localtime(event.starttime())) + else: + return event.title() + + + elif event.namingmode() == 2: # Constable + + if event.episodname(): + if event.shortname(): + title = event.shortname() + else: + title = event.episodname() + + part = "%02i" % int(event.part()) + number = "%03i" % int(event.number()) + + if event.title() == 'Tatort': + if event.extracol1: + ermittler = event.extracol1()[11:] + else: + ermittler = '' + + if event.extracol2(): + ort = event.extracol2()[5:] + else: + ort = '' + + season = str(int(event.season())+1969) + return "Tatort~" + ort + "~" + ermittler + "~" + season + "x" + part + " - " + number + ". " + event.shorttext() + + else: + if event.title() == 'Polizeiruf 110': + season = str(int(event.season())+1971) + else: + season = "%02i" % int(event.season()) + + return title + "~" + season + "x" + part + " - " + number + ". " + event.shorttext() + + elif event.shorttext() and event.title() != event.shorttext(): + return event.title() + "~?x? - ?. " + event.shorttext() + else: + return event.title() + "~" + time.strftime("%a %d.%m.%Y %H:%M", time.localtime(event.starttime())) + + elif event.namingmode() == 3: # Serie + if event.shorttext() and event.title() != event.shorttext(): + return event.title() + "~" + event.shorttext() + else: + return event.title() + + elif event.namingmode() == 4: # Kategorisiert + if event.category(): + return event.category() + "~" + event.title() + else: + return event.title() + + elif event.namingmode() == 5: # User (has to be defined/configured by User + return event.title() + + elif event.namingmode() == 6: + if event.tmplExpression() == "": + return event.title() + + recording = event.tmplExpression() + recording = recording.replace("%title%", event.title()) + recording = recording.replace("%shorttext%", event.shorttext()) + recording = recording.replace("%starttime%", time.strftime("%a %d.%m.%Y %H:%M", time.localtime(event.starttime()))) + recording = recording.replace("%year%", event.year()) + recording = recording.replace("%category%", event.category()) + recording = recording.replace("%episodname%", event.episodname()) + recording = recording.replace("%shortname%", event.shortname()) + recording = recording.replace("%partname%", event.partname()) + recording = recording.replace("%season%", "%02i" % int(event.season())) + recording = recording.replace("%part%", "%02i" % int(event.part())) + recording = recording.replace("%number%", "%02i" % int(event.number())) + recording = recording.replace("%extracol1%", event.extracol1()) + recording = recording.replace("%extracol2%", event.extracol2()) + recording = recording.replace("%extracol3%", event.extracol3()) + + recording = recording.replace("/", "~") + + return recording + + else: + return event.title() diff --git a/configs/reverseepg.sql b/configs/reverseepg.sql new file mode 100644 index 0000000..01653ff --- /dev/null +++ b/configs/reverseepg.sql @@ -0,0 +1,42 @@ +CREATE PROCEDURE reverseepg () +BEGIN +/* +* channelmap zurücksetzen +*/ +update channelmap set mergesp = 0; +/* +* events zurücksetzen Teil 1 +*/ +update + events ev, + (select distinct channelid from channelmap where source <> 'vdr' ) cm +set + useid = masterid, + updflg = + case + when ev.delflg = 'Y' then 'D' + else 'I' + end +where + ev.source = 'vdr' and + ev.channelid = cm.channelid; +/* +* events zurücksetzen Teil 2 +*/ +update + events ev, + (select distinct mergesp,merge,channelid,source from channelmap) cm +set + useid = masterid, + updflg = + case + when ev.delflg = 'Y' then 'D' + when ev.source = 'vdr' then 'P' + when ev.source != 'vdr' and merge > 1 then 'S' + else 'A' + end +where + ev.source = cm.source and + ev.channelid = cm.channelid; +END + diff --git a/configs/thetvdbview.sql b/configs/thetvdbview.sql new file mode 100644 index 0000000..d6b06af --- /dev/null +++ b/configs/thetvdbview.sql @@ -0,0 +1,33 @@ +CREATE VIEW thetvdbview as +select + ev.eventid, + case when ep.compname = 'TATORT' then concat('Tatort',replace(substring(ep.extracol1,11),' und ',' & ')) else ev.title end title, + ev.scrsp, + case when ep.compname = 'TATORT' then Null else ep.season end season, + case when ep.compname = 'TATORT' then Null else ep.part end part, + case when ep.compname = 'TATORT' then Null else ep.number end number, + ep.partname shorttext +from + events ev, episodes ep +where + ev.episodecompname = ep.compname and + ev.episodecomppartname = ep.comppartname and + ev.episodelang = ep.lang and + ev.scrsp is null and + updflg in('A','T','C','P') +union +select + eventid, + title, + scrsp, + case when substring(shorttext,1,1)='S' and substring(shorttext,2,1) REGEXP ('[0-9]') then TRIM(LEADING '0' from replace(SUBSTRING_INDEX(shorttext, 'E', 1),'S','')) end season, + case when substring(shorttext,1,1)='S' and substring(shorttext,2,1) REGEXP ('[0-9]') then TRIM(LEADING '0' from SUBSTRING_INDEX(shorttext, 'E', -1)) end part, + null number, + case when substring(shorttext,1,1)='S' and substring(shorttext,2,1) REGEXP ('[0-9]') then Null else shorttext end shorttext +from + events +where + episodecompname is Null + and scrsp is null + and updflg in('A','T','C','P') + and category = 'Serie'; diff --git a/contrib/40-epgd.conf b/contrib/40-epgd.conf new file mode 100644 index 0000000..1179acf --- /dev/null +++ b/contrib/40-epgd.conf @@ -0,0 +1,2 @@ +local2.* -/var/log/epgd.log +local2.* ~ diff --git a/contrib/README.fedora b/contrib/README.fedora new file mode 100644 index 0000000..5b62123 --- /dev/null +++ b/contrib/README.fedora @@ -0,0 +1,122 @@ +Installation instructions for Fedora 23 and above +------------------------------------------------- + +Installation of mysql database +------------------------------ + +[root@fc23 tmp]# dnf -y install mariadb mariadb-libs mariadb-server + +- enable mysql service + +[root@fc23 tmp]# systemctl enable mariadb.service + +- start mysql service + +[root@fc23 tmp]# systemctl start mariadb.service + +- check mysql status + +[root@fc23 tmp]# systemctl status mariadb.service +? mariadb.service - MariaDB 10.1 database server + Loaded: loaded (/usr/lib/systemd/system/mariadb.service; enabled; vendor preset: disabled) + Active: active (running) since Mi 2016-04-06 08:35:23 CEST; 3s ago + Process: 55587 ExecStartPost=/usr/libexec/mysql-check-upgrade (code=exited, status=0/SUCCESS) + Process: 55403 ExecStartPre=/usr/libexec/mysql-prepare-db-dir %n (code=exited, status=0/SUCCESS) + Process: 55375 ExecStartPre=/usr/libexec/mysql-check-socket (code=exited, status=0/SUCCESS) + Main PID: 55557 (mysqld) + Status: "Taking your SQL requests now..." + Tasks: 25 (limit: 512) + CGroup: /system.slice/mariadb.service + +-55557 /usr/libexec/mysqld --basedir=/usr + +Apr 06 08:35:09 fc24 mysql-prepare-db-dir[55403]: 2016-04-06 8:35:09 139857994893504 [Note] /usr/libexec/mysqld (mysqld 10.1.12-MariaDB) start +Apr 06 08:35:18 fc24 mysql-prepare-db-dir[55403]: 2016-04-06 8:35:18 139836914665664 [Note] /usr/libexec/mysqld (mysqld 10.1.12-MariaDB) start +Apr 06 08:35:20 fc24 mysql-prepare-db-dir[55403]: 2016-04-06 8:35:20 139732787038400 [Note] /usr/libexec/mysqld (mysqld 10.1.12-MariaDB) start +Apr 06 08:35:23 fc24 mysql-prepare-db-dir[55403]: PLEASE REMEMBER TO SET A PASSWORD FOR THE MariaDB root USER ! +Apr 06 08:35:23 fc24 mysql-prepare-db-dir[55403]: To do so, start the server, then issue the following commands: +Apr 06 08:35:23 fc24 mysql-prepare-db-dir[55403]: '/usr/bin/mysqladmin' -u root password 'new-password' +Apr 06 08:35:23 fc24 mysql-prepare-db-dir[55403]: '/usr/bin/mysqladmin' -u root -h fc24 password 'new-password' +Apr 06 08:35:23 fc24 mysql-prepare-db-dir[55403]: Alternatively you can run: +Apr 06 08:35:23 fc24 mysqld[55557]: 2016-04-06 8:35:23 140367759493312 [Note] /usr/libexec/mysqld (mysqld 10.1.12-MariaDB) starting as process +Apr 06 08:35:23 fc24 systemd[1]: Started MariaDB 10.1 database server. + +- install the necessary vdr plugins for a working epg environment + +[root@fc23 tmp]# dnf install vdr-scraper2vdr vdr-epg2vdr vdr-epg-daemon + +- create mysql root password for epgd-tool and save it in the root folder + +[root@fc23 tmp]# mysqladmin -u root -p password "password" +[root@fc23 tmp]# mkdir -p ~/.ssh +[root@fc23 tmp]# echo 'export PASSWORD="password"' > ~/.ssh/mysqlpasswd + +- create new mysql database and user with the helper script epgd-tool + +[root@fc23 tmp]# epgd-tool -fix-cnf +[root@fc23 tmp]# epgd-tool -new-db +[root@fc23 tmp]# epgd-tool -new-u + +- customize the channelmap.conf + +modify the config files (/etc/epgd/channelmap.conf and /etc/epgd/epgd.conf) like your needs or take a prepared one from +http://www.vdr-portal.de/index.php?page=Attachment&attachmentID=35919&h=2f0cb1b9698645550cd789acf335c3bb99cc7051&s=2d0ac4c6400452abd71b1e36cd9c51f5b4811f7f + +- enable the epgd service + +[root@fc23 tmp]# systemctl enable epgd.service + +- start the epgd service + +[root@fc23 tmp]# systemctl start epgd.service + +- check the epgd status + +[root@fc23 tmp]# systemctl status epgd.service +epgd.service - Database driven EPG Data collector + Loaded: loaded (/usr/lib/systemd/system/epgd.service; enabled) + Active: active (running) since Do 2016-04-01 14:51:08 CEST; 7s ago + Process: 18714 ExecStart=/usr/bin/epgd -c /etc/epgd (code=exited, status=0/SUCCESS) + Main PID: 18719 (epgd) + CGroup: /system.slice/epgd.service + └─18719 /usr/bin/epgd -c /etc/epgd +Apr 01 14:51:07 fc23 epgd[18714]: Loading '/etc/epgd/channelmap.conf' +Apr 01 14:51:07 fc23 epgd[18714]: 26 channel mappings read. +Apr 01 14:51:07 fc23 epgd[18714]: Creating directory '/var/cache/epgd/epgdata' +Apr 01 14:51:07 fc23 epgd[18714]: No external events on database, force initial check! +Apr 01 14:51:07 fc23 epgd[18714]: using scrapping language de +Apr 01 14:51:07 fc23 epgd[18714]: tvdb scraper connected +Apr 01 14:51:08 fc23 epgd[18714]: moviedb scraper connected +Apr 01 14:51:08 fc23 epgd[18719]: Scheduled next update in 10 second(s) +Apr 01 14:51:08 fc23 epgd[18719]: State now 'standby' +Apr 01 14:51:08 fc23 systemd[1]: Started Database driven EPG Data collector. + +- enable the epghttpd service + +[root@fc23 tmp]# systemctl enable epghttpd.service + +- start the epghttpd service + +[root@fc23 tmp]# systemctl start epghttpd.service + +- check the epghttpd status + +[root@fc23 tmp]# systemctl status epghttpd.service +● epghttpd.service - EPG HTTP Daemon that provides a web interface + Loaded: loaded (/usr/lib/systemd/system/epghttpd.service; enabled; vendor preset: disabled) + Active: active (running) since Di 2016-04-26 19:55:49 CEST; 1h 33min ago + Main PID: 3252 (epghttpd) + CGroup: /system.slice/epghttpd.service + └─3252 /usr/bin/epghttpd -c /etc/epgd + +Apr 26 19:55:49 fc23 epghttpd[3252]: Initialize python script '/etc/epgd/recording.py' +Apr 26 19:55:49 fc23 epghttpd[3252]: Dictionary '/etc/epgd/epg.dat' loaded +Apr 26 19:55:49 fc23 epghttpd[3252]: Info: Calling mysql_library_init() +Apr 26 19:55:49 fc23 epghttpd[3252]: Connecting to database at 'localhost:3306' +Apr 26 19:55:49 fc23 epghttpd[3252]: Calling mysql_init(3252) +Apr 26 19:55:49 fc23 epghttpd[3252]: SQL client character now 'utf8' +Apr 26 19:55:49 fc23 epghttpd[3252]: Calling mysql_init(3252) +Apr 26 19:55:49 fc23 epghttpd[3252]: Listener at port 9999 established, waiting for connections +Apr 26 19:55:49 fc23 epghttpd[3252]: Info: Systemd support not enabled, epgd won't be sending notifications! +Apr 26 21:29:05 fc23 systemd[1]: Started EPG HTTP Daemon that provides a web interface. + +For more information, please read the document /usr/share/doc/vdr-epg-daemon/README. diff --git a/contrib/README.openrc b/contrib/README.openrc new file mode 100644 index 0000000..cdc6b3d --- /dev/null +++ b/contrib/README.openrc @@ -0,0 +1,9 @@ +To use the openrc init-scripts (i.e. on gentoo linux): + +cp ./contrib/epgd.init.d.openrc /etc/init.d/epgd +chmod 0744 /etc/init.d/epgd + +cp ./contrib/epgd.conf.d.openrc /etc/conf.d/epgd +chmod 0644 /etc/conf.d/epgd + +Edit /etc/conf.d/epgd to your preferences. epgd config is in /etc/epgd/epgd.conf (see README in source-root) diff --git a/contrib/epgd.SuSE b/contrib/epgd.SuSE new file mode 100644 index 0000000..6947963 --- /dev/null +++ b/contrib/epgd.SuSE @@ -0,0 +1,115 @@ +#! /bin/bash +# +# Author: +# +# /etc/init.d/epg +# +### BEGIN INIT INFO +# Provides: epgd +# Required-Start: $syslog mysql +# Required-Stop: +# Default-Start: 2 3 5 +# Default-Stop: 0 1 2 6 +# Short-Description: EPG Daemon +# Description: EPG Daemon - collects EPG Data from VDR's +# and other ressources +### END INIT INFO + +# Check for missing binaries (stale symlinks should not happen) +EPGD_BIN=/usr/local/bin/epgd +test -x $EPGD_BIN || exit 5 + +# Check for existence of needed config directory +EPGD_CONFDIR=/etc/epgd +test -d $EPGD_CONFDIR || exit 6 + +# Check for existence of needed config file and read it +EPGD_CONFIG=${EPGD_CONFDIR}/epgd.conf +test -r $EPGD_CONFIG || exit 6 + +# Check for existence of needed plugin directory +EPGD_PLGDIR=/usr/local/lib/epgd/plugins +test -d $EPGD_PLGDIR || exit 6 + +# Source LSB init functions +# providing start_daemon, killproc, pidofproc, +# log_success_msg, log_failure_msg and log_warning_msg. +# This is currently not used by UnitedLinux based distributions and +# not needed for init scripts for UnitedLinux only. If it is used, +# the functions from rc.status should not be sourced or used. +#. /lib/lsb/init-functions + +# Shell functions sourced from /etc/rc.status: +# rc_check check and set local and overall rc status +# rc_status check and set local and overall rc status +# rc_status -v ditto but be verbose in local rc status +# rc_status -v -r ditto and clear the local rc status + +# rc_status -s display "skipped" and exit with status 3 +# rc_status -u display "unused" and exit with status 3 +# rc_failed set local and overall rc status to failed +# rc_failed <num> set local and overall rc status to <num> +# rc_reset clear local rc status (overall remains) +# rc_exit exit appropriate to overall rc status +# rc_active checks whether a service is activated by symlinks +# rc_splash arg sets the boot splash screen to arg (if active) +. /etc/rc.status + +# Reset status of this service +rc_reset + +# Return values acc. to LSB for all commands but status: +# 0 - success +# 1 - generic or unspecified error +# 2 - invalid or excess argument(s) +# 3 - unimplemented feature (e.g. "reload") +# 4 - user had insufficient privileges +# 5 - program is not installed +# 6 - program is not configured +# 7 - program is not running +# 8--199 - reserved (8--99 LSB, 100--149 distrib, 150--199 appl) +# +# Note that starting an already running service, stopping +# or restarting a not-running service as well as the restart +# with force-reload (in case signaling is not supported) are +# considered a success. + +start_epgd() { + echo -n "Starting EPG-Daemon" + startproc ${EPGD_BIN} -n -c ${EPGD_CONFDIR} -p ${EPGD_PLGDIR} + sleep 2 && checkproc $EPGD_BIN + # Remember status and be verbose + rc_status -v +} + +stop_epgd() +{ + echo -n "Stopping EPG-Daemon" + ## Stop daemon with killproc(8) and if this fails + ## killproc sets the return value according to LSB. + + /sbin/killproc -TERM ${EPGD_BIN} + + # Remember status and be verbose + rc_status -v +} + +case "$1" in + start) + start_epgd + ;; + stop) + stop_epgd + ;; + restart) + stop_epgd + sleep2 + start_epgd + ;; + *) + N=/etc/init.d/$NAME + echo "Usage: $N {start|stop|restart|force-reload}" >&2 + exit 1 + ;; +esac +rc_exit diff --git a/contrib/epgd.conf b/contrib/epgd.conf new file mode 100644 index 0000000..c1f6b07 --- /dev/null +++ b/contrib/epgd.conf @@ -0,0 +1,19 @@ +# epgd - EPG Daemon +# +# The EPG daemon provides EPG data from various providers +# +# upstart script + +description "EPG Daemon" +author "Jörg Wendel <vdr at jwendel dot de>" + +start on (started local-filesystems and net-device-up IFACE!=lo) +stop on runlevel [!2345] + +script + +export LANG="de_DE.UTF-8" + +exec <BINDEST>/epgd -n -p <PLGDEST> + +end script diff --git a/contrib/epgd.conf.d.openrc b/contrib/epgd.conf.d.openrc new file mode 100644 index 0000000..e720b94 --- /dev/null +++ b/contrib/epgd.conf.d.openrc @@ -0,0 +1,3 @@ +LOGFILE="/var/log/epgd.log" +PIDFILE="/var/run/epgd.pid" +CLI_OPTIONS="-n -p /usr/local/lib/epgd/plugins" diff --git a/contrib/epgd.debian b/contrib/epgd.debian new file mode 100644 index 0000000..0b4256d --- /dev/null +++ b/contrib/epgd.debian @@ -0,0 +1,68 @@ +#! /bin/bash +# +# Author: +# +# /etc/init.d/epg +# +### BEGIN INIT INFO +# Provides: epgd +# Required-Start: $syslog mysql +# Required-Stop: +# Default-Start: 2 3 5 +# Default-Stop: 0 1 2 6 +# Short-Description: EPG Daemon +# Description: EPG Daemon - collects EPG Data from VDR's +# and other ressources +### END INIT INFO + +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin +NAME=EPGD +DESC="EPG Daemon" + +# Check for missing binaries (stale symlinks should not happen) +EPGD_BIN=/usr/local/bin/epgd +test -x $EPGD_BIN || exit 5 + +# Check for existence of needed config directory +EPGD_CONFDIR=/etc/epgd +test -d $EPGD_CONFDIR || exit 6 + +# Check for existence of needed config file and read it +EPGD_CONFIG=${EPGD_CONFDIR}/epgd.conf +test -r $EPGD_CONFIG || exit 6 + +# Check for existence of needed plugin directory +EPGD_PLGDIR=/usr/local/lib/epgd/plugins +test -d $EPGD_PLGDIR || exit 6 + +start_epgd() { + echo -n "Starting $DESC: " + start-stop-daemon --start --verbose --background --oknodo --exec ${EPGD_BIN} -- -n -c ${EPGD_CONFDIR} -p ${EPGD_PLGDIR} + echo "$NAME." +} + +stop_epgd() +{ + echo -n "Stoppig $DESC: " + start-stop-daemon --stop --signal KILL --verbose --oknodo --exec ${EPGD_BIN} + echo "$NAME." +} + +case "$1" in + start) + start_epgd + ;; + stop) + stop_epgd + ;; + restart) + stop_epgd + sleep 2 + start_epgd + ;; + *) + N=/etc/init.d/$NAME + echo "Usage: $N {start|stop|restart|force-reload}" >&2 + exit 1 + ;; +esac diff --git a/contrib/epgd.ignore b/contrib/epgd.ignore new file mode 100644 index 0000000..dbd7b83 --- /dev/null +++ b/contrib/epgd.ignore @@ -0,0 +1,48 @@ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: .*channel mappings read. +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: Cleanup of events finished +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: Cleanup of events finished +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: Delete events +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: Delete fileref.*source.*and starttime.*duration +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: Download header for day +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: Downloaded file.*with.*Bytes +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: Downloaded image +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: EPG Update finished, loaded.*files.*non-updates skipped, 0 rejected due to format error. +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: EPG Update started +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: Got \'Setting encoding to utf8\' +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: Got info for day.*file.*with tag +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: Got.*Setting encoding to utf8 +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: Image cleanup finished +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: Info: Stylesheet +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: Loaded.*images.*, checked +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: Loading +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: Lookup done for.*series, matched.*parts by compare and.*parts by lv in.*seconds +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: Processing file.*for day +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: Read.*option from /etc/epgd/epgd.conf +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: Received.*episode files +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: Requesting episode changes of last.*minutes +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: SQL client character now +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: SVDRPCL: connected to eplists.constabel.net +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: Scheduled next update in +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: Set locale to +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: Shutdown triggered with signal 15 +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: Skipping download of day.*due to non-update +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: Skipping update check of file.*for day +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: Start download of new images +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: Starting cleanup of events +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: Starting cleanup of image +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: Starting episode download +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: Starting episode lookup +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: Statement.*insert|select +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: Statement.*update|delete +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: Still updating images, now.*checked and.*loaded +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: There are.*images for event +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: Updating day today.*now +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: Updating day today.*now +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: Updating.*day today.*now +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: View.*eventsview.*already exist +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: XML File.*processed, updated.*events +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: action ended +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: detected UTF-8 +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: no images for event +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: shutdown +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ epgd: try loading image from diff --git a/contrib/epgd.init.d b/contrib/epgd.init.d new file mode 100755 index 0000000..3494fe1 --- /dev/null +++ b/contrib/epgd.init.d @@ -0,0 +1,86 @@ +#! /bin/bash +# +# Author: OleS +# +# /etc/init.d/epgd +# +### BEGIN INIT INFO +# Provides: epgd +# Required-Start: $syslog mysql +# Required-Stop: +# Default-Start: 2 3 5 +# Default-Stop: 0 1 2 6 +# Short-Description: EPG Daemon +# Description: EPG Daemon - collects EPG Data from VDR's +# and other ressources +### END INIT INFO + +export LANG="de_DE.UTF-8" +export LC_ALL="de_DE.UTF-8" +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin +NAME=epgd +DESC="EPG Daemon" + +# Check for missing binaries (stale symlinks should not happen) +EPGD_BIN=/usr/local/bin/epgd +test -x $EPGD_BIN || exit 5 + +# Check for existence of needed config directory +EPGD_CONFDIR=/etc/epgd +test -d $EPGD_CONFDIR || exit 6 + +# Check for existence of needed config file and read it +EPGD_CONFIG=${EPGD_CONFDIR}/epgd.conf +test -r $EPGD_CONFIG || exit 6 + +# Check for existance of needed plugin directory +EPGD_PLGDIR=/usr/local/lib/epgd/plugins +test -d $EPGD_PLGDIR || exit 6 + +. /lib/lsb/init-functions + +start_epgd() { + log_daemon_msg "Starting $DESC" "$NAME" || true + if start-stop-daemon --start --quiet --background --oknodo --exec ${EPGD_BIN} -- -n -c ${EPGD_CONFDIR} -p ${EPGD_PLGDIR}; then + log_end_msg 0 || true + else + log_end_msg 1 || true + fi +} + +stop_epgd() +{ + log_daemon_msg "Stopping $DESC" "$NAME" || true + if start-stop-daemon --stop --signal KILL --verbose --oknodo --exec ${EPGD_BIN} 2>&1> /dev/null; then + log_end_msg 0 || true + else + log_end_msg 1 || true + fi +} + +status_epgd() +{ + status_of_proc /usr/local/bin/epgd $NAME && exit 0 || exit $? +} + +case "$1" in + start) + start_epgd + ;; + stop) + stop_epgd + ;; + restart) + stop_epgd + sleep 2 + start_epgd + ;; + status) + status_epgd + ;; + *) + N=/etc/init.d/$NAME + echo "Usage: $N {start|stop|restart|status}" >&2 + exit 1 + ;; +esac diff --git a/contrib/epgd.init.d.openrc b/contrib/epgd.init.d.openrc new file mode 100755 index 0000000..d45c511 --- /dev/null +++ b/contrib/epgd.init.d.openrc @@ -0,0 +1,30 @@ +#!/sbin/runscript +# Copyright 1999-2012 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: $ + +depend() { + need net + need mysql +} + +start() { + export LOGFILE + export LANG="de_DE.UTF-8" + export PIDFILE + export CLI_OPTIONS + export COMMAND="/usr/local/bin/epgd" + ebegin "Starting epgd" + start-stop-daemon --start --pidfile ${PIDFILE} -i -u root:root \ + --progress --background --make-pidfile -1 ${LOGFILE} \ + -2 ${LOGFILE} --exec ${COMMAND} --verbose -- ${CLI_OPTIONS} + eend $? +} + +stop() { + ebegin "Stoping epgd" + start-stop-daemon --stop --pidfile ${PIDFILE} --progress \ + --retry 30 --exec ${COMMAND} --verbose + + eend $? +} diff --git a/contrib/epgd.service b/contrib/epgd.service new file mode 100644 index 0000000..d7af532 --- /dev/null +++ b/contrib/epgd.service @@ -0,0 +1,13 @@ +[Unit] + +Description = Database driven EPG Data collector +After = <AFTER> + +[Service] + +Type = forking +ExecStart = <BINDEST>/epgd -c /etc/epgd -p <PLGDEST> + +[Install] + +WantedBy = multi-user.target diff --git a/contrib/epghttpd.conf b/contrib/epghttpd.conf new file mode 100644 index 0000000..90d1a24 --- /dev/null +++ b/contrib/epghttpd.conf @@ -0,0 +1,17 @@ +# EPG web/http Deamon +# +# upstart script + + +description "EPG/Web-Server" + +start on (started epgd) +stop on runlevel [!2345] + +script + +export LANG="de_DE.UTF-8" + +exec <BINDEST>/epghttpd -n + +end script diff --git a/contrib/epghttpd.init.d b/contrib/epghttpd.init.d new file mode 100755 index 0000000..310bd01 --- /dev/null +++ b/contrib/epghttpd.init.d @@ -0,0 +1,73 @@ +#! /bin/bash +# +# Author: OleS +# +# /etc/init.d/epghttpd +# +### BEGIN INIT INFO +# Provides: epghttpd +# Required-Start: $syslog epgd +# Required-Stop: +# Default-Start: 2 3 5 +# Default-Stop: 0 1 2 6 +# Short-Description: EPG HTTP Daemon +# Description: EPG HTTP Daemon - provides a web interface similar to vdr live +### END INIT INFO + +export LANG="de_DE.UTF-8" +export LC_ALL="de_DE.UTF-8" +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin +NAME=epghttpd +DESC="EPG HTTP Daemon" + +# Check for missing binaries (stale symlinks should not happen) +EPGHTTPD_BIN=/usr/local/bin/epghttpd +test -x $EPGHTTPD_BIN || exit 5 + +. /lib/lsb/init-functions + +start_epghttpd() { + log_daemon_msg "Starting $DESC" "$NAME" || true + if start-stop-daemon --start --quiet --background --oknodo --exec ${EPGHTTPD_BIN} -- -n; then + log_end_msg 0 || true + else + log_end_msg 1 || true + fi +} + +stop_epghttpd() +{ + log_daemon_msg "Stopping $DESC" "$NAME" || true + if start-stop-daemon --stop --signal KILL --verbose --oknodo --exec ${EPGHTTPD_BIN} 2>&1> /dev/null; then + log_end_msg 0 || true + else + log_end_msg 1 || true + fi +} + +status_epghttpd() +{ + status_of_proc /usr/local/bin/epghttpd $NAME && exit 0 || exit $? +} + +case "$1" in + start) + start_epghttpd + ;; + stop) + stop_epghttpd + ;; + restart) + stop_epghttpd + sleep 2 + start_epghttpd + ;; + status) + status_epghttpd + ;; + *) + N=/etc/init.d/$NAME + echo "Usage: $N {start|stop|restart|status}" >&2 + exit 1 + ;; +esac diff --git a/contrib/epghttpd.service b/contrib/epghttpd.service new file mode 100644 index 0000000..fd8d7f4 --- /dev/null +++ b/contrib/epghttpd.service @@ -0,0 +1,13 @@ +[Unit] + +Description = EPG HTTP Daemon that provides a web interface +After = epgd.service + +[Service] + +Type = forking +ExecStart = <BINDEST>/epghttpd -c /etc/epgd + +[Install] + +WantedBy = multi-user.target diff --git a/contrib/gentoo/README.txt b/contrib/gentoo/README.txt new file mode 100644 index 0000000..0bdf32c --- /dev/null +++ b/contrib/gentoo/README.txt @@ -0,0 +1,108 @@ +Installation des EPG Deamon und des epg2vdr Plugins auf Gen2VDR (ab Version 4) +by 3PO + +ebuild herunterladen: + + +cd /tmp +git clone git://projects.vdr-developer.org/vdr-epg-daemon.git + +Dann der "/etc/portage/make.conf" folgenden Eintrag hinzuf?gen: + +EPGD_LOCAL_PATCHES_DIR="/usr/local/portage/patches/epgd" + + + +Das ebuild entpacken und EPGd installieren: + +cd /tmp/vdr-epg-daemon/contrib/gentoo +tar -xvf epgd-ebuild.tgz -C / +echo "=media-tv/epgd-9999 **" >> /etc/portage/package.keywords/media +emerge -av epgd + + + +Sollen weitere Plugins verwendet werden, dann geht das z.B. so: + +mkdir -p /usr/local/portage/patches/epgd +cd /usr/local/portage/patches/epgd +wget http://dreipo.cc/tvm/tvm.diff +emerge -av epgd + + + + +Die MySQL Datenbank wird wie folgt erstellt: + +MySQL starten und dem Autostart hinzuf?gen: + +stt mysql +rc-update add mysql default + + + +Falls noch nicht geschehen, das root Passwort f?r MySQL vergeben: + +mysqladmin -u root -p password "WUNSCHPASSWORT" + + + +Man kann es dann, der Einfachheit halber, im root Verzeichnis speichern: + +mkdir -p /root/.ssh +echo 'export PASSWORD="WUNSCHPASSWORT"' > /root/.ssh/mysqlpasswd + + + +Datenbank erstellen lassen: + +epgd-tool -new + + + +EPGd starten und dem Autostart hinzuf?gen: + +rc-update add epgd default + + + +Damit ist der Serverteil erledigt, jetzt muss noch das epg2vdr Plugin installiert werden: + +cd /usr/local/src/VDR/PLUGINS/src +git clone git://projects.vdr-developer.org/vdr-plugin-epg2vdr.git epg2vdr-git +ln -svfn epg2vdr-git epg2vdr +cd epg2vdr +make all +make install +/_config/bin/instvdr.sh + + + + +Jetzt noch mit: + +g2v-setup + +epg2vdr aktivieren. + + +FERTIG! ;) + + + +Updates: + +EPGd: + +emerge -av epgd +stp epgd && stt epgd + + + + +epg2vdr Plugin: + +cd /usr/local/src/VDR/PLUGINS/src/epg2vdr +git pull +make clean all install +/_config/bin/instvdr.sh diff --git a/contrib/gentoo/epgd-ebuild.tgz b/contrib/gentoo/epgd-ebuild.tgz new file mode 100644 index 0000000..f95853c Binary files /dev/null and b/contrib/gentoo/epgd-ebuild.tgz differ diff --git a/epgd.h b/epgd.h new file mode 100644 index 0000000..46a0eaa --- /dev/null +++ b/epgd.h @@ -0,0 +1,277 @@ +/* + * epgd.h + * + * See the README file for copyright information and how to reach the author. + * + */ + +#ifndef __EPGD_H +#define __EPGD_H + +#include <libxslt/transform.h> +#include <libxslt/xsltutils.h> +#include <libexslt/exslt.h> + +#include <unistd.h> + +#include <vector> + +#include "lib/common.h" +#include "lib/db.h" +#include "lib/epgservice.h" +#include "lib/configuration.h" +#include "lib/searchtimer.h" + +#include "epgdconfig.h" + +#include "series.h" +#include "levenshtein.h" + +#include "tvdbmanager.h" +#include "moviedbmanager.h" + +#include "HISTORY.h" + +#define confDirDefault "/etc/epgd" + +extern const char* confDir; + +//*************************************************************************** +// Statistic +//*************************************************************************** + +struct Statistic +{ + int bytes; + int files; + int rejected; + int nonUpdates; +}; + +class cEpgd; + +//*************************************************************************** +// Plugin +//*************************************************************************** + +class Plugin +{ + public: + + Plugin() { obj = 0; utf8 = yes; } + virtual ~Plugin() {} + + virtual int init(cEpgd* aObject, int aUtf8) + { + obj = aObject; + utf8 = aUtf8; + return success; + } + + virtual int exit() { return done; } + virtual int initDb() { return done; } + virtual int exitDb() { return done; } + + virtual int atConfigItem(const char* Name, const char* Value) = 0; + virtual const char* getSource() = 0; + virtual int hasSource(const char* source) { return strcmp(getSource(), source) == 0; } + + virtual int getPicture(const char* imagename, const char* fileRef, MemoryStruct* data) = 0; + virtual int processDay(int day, int fullupdate, Statistic* stat) = 0; + + virtual int cleanupBefore() { return done; } + virtual int cleanupAfter() { return done; } + + virtual int ready() = 0; + + protected: + + cEpgd* obj; + int utf8; +}; + +//*************************************************************************** +// Plugin Loader +//*************************************************************************** + +class PluginLoader +{ + public: + + PluginLoader(const char* name, Plugin* p = 0); + virtual ~PluginLoader(); + + int load(); + Plugin* getPlugin() { return plugin; } + + private: + + char* fileName; + void* handle; + Plugin* plugin; +}; + +//*************************************************************************** +// EPG Deamon +//*************************************************************************** + +class cEpgd : public cFrame, public cSystemNotification +{ + public: + + cEpgd(); + virtual ~cEpgd(); + + // interface + + int init(); + int initUuid(); + void loop(); + void scheduleAutoUpdate(int wait = 0); + int atConfigItem(const char* Name, const char* Value); + int parseEvent(cDbRow* event, xmlNode* node); + + int dbConnected(int force = no) + { return connection && connection->isConnected() && (!force || connection->check() == success); } + + // static stuff + + static void downF(int signal) { tell(0, "Shutdown triggered with signal %d", signal); shutdown = yes; } + static void triggerF(int aSignal); + static int doShutDown() { return shutdown; } + + int wakeupVdr(const char* uuid); + int triggerVdrs(const char* trg, const char* options = ""); + int __attribute__ ((format(printf, 5, 6))) message(int level, char type, const char* title, const char* format, ...); + int sendTccMail(string& mailBody); + int sendTccTestMail(); + + xmlDocPtr transformXml(const char* buffer, int size, xsltStylesheetPtr stylesheet, const char* fileRef); + int storeToFs(MemoryStruct* data, const char* filename, const char* subPath); + int loadFromFs(MemoryStruct* data, const char* filename, const char* subPath); + int downloadFile(const char* url, int& size, MemoryStruct* data, int timeout = 30, const char* userAgent = "libcurl-agent/1.0"); + + // public for plugins access + + cDbConnection* connection; + + cDbTable* eventsDb; + cDbTable* useeventsDb; + cDbTable* compDb; + cDbTable* fileDb; + cDbTable* imageDb; + cDbTable* imageRefDb; + cDbTable* episodeDb; + cDbTable* mapDb; + cDbTable* vdrDb; + cDbTable* parameterDb; + cDbTable* recordingListDb; + cDbTable* timerDb; + cDbTable* messageDb; + + cDbStatement* selectAllMap; + cDbStatement* selectByCompTitle; + cDbStatement* selectMaxUpdSp; + cDbStatement* selectDistCompname; + cDbStatement* selectByCompName; + cDbStatement* selectByCompNames; + cDbStatement* updateEpisodeAtEvents; + cDbStatement* updateScrReference; + cDbStatement* selectMaxMapOrd; + cDbStatement* selectMapOrdOf; + cDbStatement* countDvbChanges; + cDbStatement* selectNewRecordings; + cDbStatement* countNewRecordings; + cDbStatement* selectRecordingEvent; + cDbStatement* selectRecOtherClient; + cDbStatement* selectActiveVdrs; + cDbStatement* selectWebUsers; + cDbStatement* cleanupTimerActions; + cDbStatement* selectNotAssumedTimers; + + cDbValue changeCount; + cDbValue newRecCount; + + cDbProcedure* procMergeEpg; + cDbProcedure* procUser; + + private: + + // functions + + int initDb(); + int exitDb(); + int checkProcedure(const char* name, cDBS::ProcType type, cDbProcedure* fp = 0); + int checkView(const char* name, const char* file); + int registerMe(); + + int loadPlugins(); + int initPlugins(); + int initPluginDb(); + int exitPluginDb(); + + void setState(cEpgdState::State state, time_t lastUpdate = 0, int silent = no); + + int loadChannelmap(); + int updateMapRow(char* extid, const char* source, const char* chan, int merge, int vps); + int applyChannelmapChanges(); + int checkConnection(); + + // work + + int update(); + int cleanupEvents(); + int cleanupPictures(); + int getPictures(); + int storeImageRefs(tEventId evtId, const char* source, const char* images, + const char* ext, const char* fileref); + int scrapNewEvents(); + int cleanupSeriesAndMovies(); + void scrapNewRecordings(int count); + + int updateSearchTimers(int force = yes, const char* reason = ""); + + // plugin interface + + int cleanupBefore(); + int cleanupAfter(); + int getPicture(const char* source, const char* imagename, + const char* fileRef, MemoryStruct* data); + int processDay(int day, int fullupdate, Statistic* stat); + + // series + + int evaluateEpisodes(); + int downloadEpisodes(); + + // scraper stuff + + int initScrapers(); + void exitScrapers(); + bool checkEventsForRecording(int eventId, string channelId, int &seriesId, int &episodeId, int &movieId); + bool checkRecOtherClients(string uuid, string recPath, int recStart); + + // data + + int withutf8; + + time_t nextUpdateAt; + time_t lastUpdateAt; + time_t lastMergeAt; + + int fullupdate; + int fullreload; + + static int shutdown; + static int epgTrigger; + static int searchTimerTrigger; + + std::vector<PluginLoader*> plugins; + + cTVDBManager* tvdbManager; + cMovieDBManager* movieDbManager; + cSearchTimer* search; +}; + +//*************************************************************************** +#endif //__EPGD_H diff --git a/epgdconfig.c b/epgdconfig.c new file mode 100644 index 0000000..84fdc7a --- /dev/null +++ b/epgdconfig.c @@ -0,0 +1,57 @@ +/* + * config.c: + * + * See the README file for copyright information and how to reach the author. + * + */ + +#include "lib/epgservice.h" + +#include "epgdconfig.h" + +cEpgdConfig EpgdConfig; + +//*************************************************************************** +// cEpgdConfig +//*************************************************************************** + +cEpgdConfig::cEpgdConfig() + : cEpgConfig() +{ + checkInitial = yes; + updatetime = 6; // hours + days = 8; + upddays = 2; + storeXmlToFs = no; + + maximagesperevent = 1; + epgImageSize = 2; + + seriesEnabled = yes; + sstrcpy(seriesUrl, "www.eplists.de", sizeof(seriesUrl)); + *seriesMail = 0; + seriesPort = 2006; + storeSeriesToFs = no; + + sstrcpy(cachePath, "/var/cache/epgd", sizeof(cachePath)); + sstrcpy(httpPath, "/var/epgd/www", sizeof(httpPath)); + sstrcpy(pluginPath, PLGDIR, sizeof(pluginPath)); + sstrcpy(epgView, "eventsview.sql", sizeof(epgView)); + sstrcpy(epgViewWeb, "eventsviewplain.sql", sizeof(epgViewWeb)); + sstrcpy(theTvDBView, "thetvdbview.sql", sizeof(theTvDBView)); + updateThreshold = 200; + maintanance = no; + + httpPort = 9999; + *httpDevice = 0; + httpUseTls = no; + *httpUser = 0; + *httpPass = 0; + + *proxy = 0; // the proxy + *proxyuser = 0; // proxy user + *proxypwd = 0; // proxy password + + scrapEpg = yes; + scrapRecordings = yes; +} diff --git a/epgdconfig.h b/epgdconfig.h new file mode 100644 index 0000000..0335ce7 --- /dev/null +++ b/epgdconfig.h @@ -0,0 +1,63 @@ +/* + * epgdconfig.h: + * + * See the README file for copyright information and how to reach the author. + * + */ + +#ifndef __EPGD_CONFIG_H +#define __EPGD_CONFIG_H + +#include "lib/config.h" + +//*************************************************************************** +// Config +//*************************************************************************** + +struct cEpgdConfig : public cEpgConfig +{ + public: + + cEpgdConfig(); + + int checkInitial; + int updatetime; + int days; + int upddays; + int storeXmlToFs; + + int maximagesperevent; + int epgImageSize; + + int seriesEnabled; + char seriesUrl[500+TB]; + char seriesMail[500+TB]; + int seriesPort; + int storeSeriesToFs; + + char cachePath[256+TB]; + char httpPath[256+TB]; + char pluginPath[256+TB]; + char epgView[100+TB]; + char epgViewWeb[100+TB]; + char theTvDBView[100+TB]; + int updateThreshold; + int maintanance; + int httpPort; + char httpDevice[20+TB]; + int httpUseTls; + char httpUser[100+TB]; + char httpPass[100+TB]; + char proxy[256+TB]; + char proxyuser[100+TB]; + char proxypwd[100+TB]; + + int scrapEpg; + int scrapRecordings; +}; + +extern cEpgdConfig EpgdConfig; + +//*************************************************************************** + +#endif // __EPGD_CONFIG_H diff --git a/epglv/COPYING b/epglv/COPYING new file mode 100644 index 0000000..f90922e --- /dev/null +++ b/epglv/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/epglv/Makefile b/epglv/Makefile new file mode 100644 index 0000000..917fb23 --- /dev/null +++ b/epglv/Makefile @@ -0,0 +1,60 @@ +# +# Makefile +# +# See the README file for copyright information and how to reach the author. +# + +include ../Make.config + +ARCH := $(shell getconf LONG_BIT) + +ifneq (,$(findstring "arm", $(shell uname -m))) + CPP_FLAGS_32 := -m32 + CPP_FLAGS_64 := -m64 +endif + +CPP_FLAGS := $(CPP_FLAGS_$(ARCH)) -Wall \ + -fPIC \ + -I/usr/local/include/mysql \ + -L/usr/lib/mysql \ + -L/usr/local/lib/mysql \ + -I/usr/include/mysql \ + $(shell mysql_config --libs) \ + -DMYSQL_DYNAMIC_PLUGIN \ + -DDEBUG_MYSQL=0 + +CC := gcc + +MYSQL_PLGDIR := $(shell mysql_config --plugindir) +TARGET = mysqlepglv.so +OBJS = src/epglvbase.o src/epglv.o + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CC) $(CPP_FLAGS) -pipe -O3 -shared -o $(TARGET) $(OBJS) + +install: $(TARGET) + strip $(TARGET) + if ! test -f $(DESTDIR)/$(MYSQL_PLGDIR)/$(TARGET); then \ + install -D --mode=644 -t $(DESTDIR)/$(MYSQL_PLGDIR) $(TARGET); \ + fi + +forceinstall: $(TARGET) + strip $(TARGET) + install -D --mode=644 -t $(DESTDIR)/$(MYSQL_PLGDIR) $(TARGET); \ + $(_BINDEST)/epgd-import-epglv + +clean: + -rm -f $(TARGET) src/*.o src/*~ *~ + +%.o: %.c +src/%.o: src/%.c + $(CC) -c $(CPP_FLAGS) -pipe -O3 -shared $< -o $@ + +#-------------------------------------------------------- +# dependencies +#-------------------------------------------------------- + +src/epglvbase.o : src/epglvbase.c src/epglv.h +src/epglv.o : src/epglv.c src/epglv.h diff --git a/epglv/README b/epglv/README new file mode 100644 index 0000000..089f42e --- /dev/null +++ b/epglv/README @@ -0,0 +1,57 @@ +EPG2VDR Levenshtein Distance for MySQL +Supports UTF-8 insensitive calculation throught iconv. + +Copyright (C) 2013 Jörg Wendel + +Redistribute as you wish, but leave this information intact. + +The build process is integrated in epgd's makefile, to build epglv +separately follow this steps: + +Compiling: +---------- + + Run + make + make install + +Installing UDFs in MySQL: +------------------------- + + Loading UDFs in MySQL, at the mysql prompt call: + + DROP FUNCTION IF EXISTS epglv; + DROP FUNCTION IF EXISTS epglvr; + CREATE FUNCTION epglv RETURNS INT SONAME 'mysqlepglv.so'; + CREATE FUNCTION epglvr RETURNS INT SONAME 'mysqlepglv.so'; + + Check te installtion by: + + mysql> SELECT * FROM mysql.func; + +-----------+-----+-------------------+----------+ + | name | ret | dl | type | + +-----------+-----+-------------------+----------+ + | epglv | 2 | mysqlepglv.so | function | + +-----------+-----+-------------------+----------+ + +Attention: +---------- + + Before changing the lib in MySQLs plugin dir DROP the function if it already exist. + Otherwise you can get mysql in a undefined state and a mysql reinstall may necessary! + +Using epglv: +------------ + + mysql> select epglv(); + ERROR: EPGLV() requires two arguments (string, string) + + First string is compared against second string. + + mysql> select epglv('€uro', 'Euro'); + +----------------------------+ + | epglv('€uro', 'Euro') | + +----------------------------+ + | 1 | + +----------------------------+ + diff --git a/epglv/src/epglv.c b/epglv/src/epglv.c new file mode 100644 index 0000000..80be809 --- /dev/null +++ b/epglv/src/epglv.c @@ -0,0 +1,57 @@ +/* + +EPG2VDR Levenshtein Distance UDF for MySQL +Supports UTF-8 throught iconv. + +Copyright (C) 2013 Jörg Wendel + +*/ + +#include "epglv.h" + +//*************************************************************************** +// EPGLV() +//*************************************************************************** + +my_bool epglv_init(UDF_INIT* init, UDF_ARGS* args, char* message) +{ + return base_epglv_init(init, args, message); +} + +void epglv_deinit(UDF_INIT* init) +{ + base_epglv_deinit(init); +} + +long long epglv(UDF_INIT* init, UDF_ARGS* args, char* is_null, char* error) +{ + long long len1 = 0, len2 = 0; + long long diff = base_epglv(init, args, is_null, error, &len1, &len2); + + return diff; +} + +//*************************************************************************** +// EPGLVR() +//*************************************************************************** + +my_bool epglvr_init(UDF_INIT* init, UDF_ARGS* args, char* message) +{ + return base_epglv_init(init, args, message); +} + +void epglvr_deinit(UDF_INIT* init) +{ + base_epglv_deinit(init); +} + +long long epglvr(UDF_INIT* init, UDF_ARGS* args, char* is_null, char* error) +{ + long long len1 = 0, len2 = 0; + + long long diff = base_epglv(init, args, is_null, error, &len1, &len2); + + long long len = len1 < len2 ? len2 : len1; + + return (double)diff / ((double)len / 100.0); +} diff --git a/epglv/src/epglv.h b/epglv/src/epglv.h new file mode 100644 index 0000000..39554b8 --- /dev/null +++ b/epglv/src/epglv.h @@ -0,0 +1,52 @@ +/* + +EPG2VDR Levenshtein Distance UDF for MySQL +Supports UTF-8 throught iconv. + +Copyright (C) 2013 Jörg Wendel + +*/ + +#ifndef __EPGLV_H +#define __EPGLV_H + +#ifdef STANDARD +# include <string.h> +#else +# include <my_global.h> +# include <my_sys.h> +#endif + +#include <mysql.h> +#include <m_ctype.h> +#include <m_string.h> + +#include <locale.h> +#include <stdio.h> +#include <string.h> +#include <wchar.h> +#include <stdlib.h> +#include <stdarg.h> +#include <iconv.h> +#include <errno.h> +#include <stdint.h> +#include <assert.h> + +#define LENGTH_MAX 1000 + +#define debug_print(fmt, ...) \ + do { if (DEBUG_MYSQL) fprintf(stderr, "%s():%d> " fmt "\n", \ + __func__, __LINE__, __VA_ARGS__); fflush(stderr); } while (0) + +#define print(fmt, ...) \ + do { fprintf(stderr, "%s():%d> " fmt "\n", \ + __func__, __LINE__, __VA_ARGS__); fflush(stderr); } while (0) + +#define MIN(a,b) (((a)<(b))?(a):(b)) + +#endif // __EPGLV_H + +my_bool base_epglv_init(UDF_INIT* init, UDF_ARGS* args, char* message); +void base_epglv_deinit(UDF_INIT* init); +long long base_epglv(UDF_INIT* init, UDF_ARGS* args, char* is_null, + char* error, long long* l1, long long* l2); diff --git a/epglv/src/epglvbase.c b/epglv/src/epglvbase.c new file mode 100644 index 0000000..845edcb --- /dev/null +++ b/epglv/src/epglvbase.c @@ -0,0 +1,295 @@ +/* + +EPG2VDR Levenshtein Distance UDF for MySQL +Supports UTF-8 i throught iconv. + +Copyright (C) 2013 Jörg Wendel + +*/ + +#include "epglv.h" + +//*************************************************************************** +// Declarations +//*************************************************************************** + +struct workspace_t // structure to allocate memory in init and use it in core functions +{ + char* str1; // internal buffer to store 1st string + char* str2; // internal buffer to store 2nd string + int* row0; // round buffer for levenshtein_core function + int* row1; // round buffer for levenshtein_core function + int* row2; // round buffer for levenshtein_core function + mbstate_t* mbstate; // buffer for mbsnrtowcs + iconv_t ic; // buffer for iconv + char iconv_init; // flag indicating if iconv has been inited before +}; + +//*************************************************************************** +// Function Declarations +//*************************************************************************** + +int epglv_core(struct workspace_t *ws, + const char *str1, int len1, + const char *str2, int len2, + int w, int s, int a, int d, int limit); + +char* epglv_utf8toiso(const char *str_src, long long *len_src, + struct workspace_t * ws, char *str_dst, int limit); + +//*************************************************************************** +// The Work +//*************************************************************************** +//*************************************************************************** +// init - check parameters and allocate memory for MySql +//*************************************************************************** + +my_bool base_epglv_init(UDF_INIT* init, UDF_ARGS* args, char* message) +{ + struct workspace_t *ws; + + // make sure both arguments are ok + + if (args->arg_count != 2 || args->arg_type[0] != STRING_RESULT || args->arg_type[1] != STRING_RESULT) + { + strncpy(message, "EPGLV() requires arguments (string, string)", 80); + return 1; + } + + init->maybe_null = 0; // EPGLV() will not be returning null + + // attempt to allocate memory in which to calculate distance + + ws = (struct workspace_t*)malloc(sizeof(struct workspace_t)); + ws->mbstate = (mbstate_t*)malloc(sizeof(mbstate_t)); + ws->str1 = (char*)malloc(sizeof(char)*(LENGTH_MAX+2)); // max allocated for UTF-8 complex string + ws->str2 = (char*)malloc(sizeof(char)*(LENGTH_MAX+2)); + ws->row0 = (int*)malloc(sizeof(int)*(LENGTH_MAX+2)); + ws->row1 = (int*)malloc(sizeof(int)*(LENGTH_MAX+2)); + ws->row2 = (int*)malloc(sizeof(int)*(LENGTH_MAX+2)); + ws->iconv_init = 0; + + if (!ws || !ws->mbstate || !ws->str1 || !ws->str2 || !ws->row0 || !ws->row1 || !ws->row2) + { + free(ws->row2); free(ws->row1); free(ws->row0); + free(ws->str2); free(ws->str1); + free(ws->mbstate); free(ws); + strncpy(message, "EPGLV() failed to allocate memory", 80); + return 1; + } + + if (!setlocale(LC_CTYPE, "de_DE.UTF-8")) + { + free(ws->row2); free(ws->row1); free(ws->row0); + free(ws->str2); free(ws->str1); + free(ws->mbstate); free(ws); + strncpy(message, "EPGLV() failed to change locale", 80); + return 1; + } + + init->ptr = (char *) ws; + debug_print("%s", "init successful"); + + return 0; +} + +//*************************************************************************** +// deallocate memory, clean and close +//*************************************************************************** + +void base_epglv_deinit(UDF_INIT* init) +{ + if (init->ptr) + { + struct workspace_t* ws = (struct workspace_t*)init->ptr; + + if (ws->iconv_init) + iconv_close(ws->ic); + + free(ws->row2); + free(ws->row1); + free(ws->row0); + free(ws->str2); + free(ws->str1); + free(ws->mbstate); + free(ws); + } + + debug_print("%s", "bye"); +} + +//*************************************************************************** +// check parameters and allocate memory for MySql +//*************************************************************************** + +long long base_epglv(UDF_INIT* init, UDF_ARGS* args, char* is_null, char* error, + long long* len1, long long* len2) +{ + const char* str1 = args->args[0]; + const char* str2 = args->args[1]; + + char* iso_str1 = 0; + char* iso_str2 = 0; + struct workspace_t* ws = (struct workspace_t*)init->ptr; // get a pointer to memory previously allocated + + *error = 0; + *len1 = (!str1) ? 0 : args->lengths[0]; + *len2 = (!str2) ? 0 : args->lengths[1]; + long long max = *len1 > *len2 ? *len1 : *len2; + + if (max >= LENGTH_MAX) + { + print("size(%lld) was bigger than %d, aborting", max, LENGTH_MAX); + return -1; + } + + if (!*len1 && !*len2) + return 0; + + if (!*len1 || !*len2) + return max; + + if ((iso_str1 = epglv_utf8toiso(str1, len1, ws, ws->str1, max)) == 0) + return -1; + + if ((iso_str2 = epglv_utf8toiso(str2, len2, ws, ws->str2, max)) == 0) + return -1; + + return epglv_core( + ws, + iso_str1, *len1, + iso_str2, *len2, + /* swap */ 1, + /* substitution */ 1, + /* insertion */ 1, + /* deletion */ 1, + /* limit */ max); +} + +//*************************************************************************** +// core function +//*************************************************************************** + +int epglv_core(struct workspace_t* ws, + const char* str1, int len1, + const char* str2, int len2, + int w, int s, int a, int d, int limit) +{ + int* row0 = ws->row0; + int* row1 = ws->row1; + int* row2 = ws->row2; + int i, j; + + for (j = 0; j <= len2; j++) + row1[j] = j * a; + + for (i = 0; i < len1; i++) + { + int* dummy; + + row2[0] = (i + 1) * d; + + for (j = 0; j < len2; j++) + { + // substitution + + row2[j + 1] = row1[j] + s * (str1[i] != str2[j]); + + // swap + + if (i > 0 && j > 0 && + str1[i - 1] == str2[j] && + str1[i] == str2[j - 1] && + row2[j + 1] > row0[j - 1] + w) + { + row2[j + 1] = row0[j - 1] + w; + } + + // deletion + + if (row2[j + 1] > row1[j + 1] + d) + row2[j + 1] = row1[j + 1] + d; + + // insertion + + if (row2[j + 1] > row2[j] + a) + row2[j + 1] = row2[j] + a; + } + + dummy = row0; + row0 = row1; + row1 = row2; + row2 = dummy; + } + + debug_print("returning(%d)", row1[len2]); + + return row1[len2]; +} + +//************************************************************************** +// translates an UTF8 string to ISO with some error return codes +//************************************************************************** + +char* epglv_utf8toiso(const char* str_src, long long* len_src, + struct workspace_t* ws, char* str_dst, int limit) +{ + mbstate_t* mbstate = ws->mbstate; + size_t len_mbsnrtowcs, len_ret = LENGTH_MAX, len_min = LENGTH_MAX; + char* ret = str_dst; + char* in_s = (char*)str_src; + + memset((void*)mbstate, '\0', sizeof(mbstate_t)); + + if ((len_mbsnrtowcs = mbsnrtowcs(0, &str_src, *len_src, 0, mbstate)) == -1) + { + print("mbsnrtowcs failed, str_src(%s): '%m'", str_src); + strncpy(str_dst, str_src, len_min); + str_dst[len_min] = 0; str_dst[len_min + 1] = 0; + *len_src = len_min; + return str_dst; + } + + len_min = MIN(len_mbsnrtowcs, limit); + + if (len_mbsnrtowcs == *len_src) + { + strncpy(str_dst, str_src, len_min); + str_dst[len_min] = 0; str_dst[len_min + 1] = 0; + *len_src = len_min; + return str_dst; + } + + if (!ws->iconv_init) + { + if ((ws->ic = iconv_open("ISO8859-15", "UTF-8")) == (iconv_t)-1) + { + print("%s", "failed to initialize iconv '%m'"); + return 0; + } + + ws->iconv_init = 1; + } + + if (iconv(ws->ic, &in_s, (size_t*)len_src, &ret, &len_ret) == -1) + { + if (errno != E2BIG) + { + print("in_s '%s' at '%s'; len_src (%lld) len_ret (%zu) '%m'", str_src, in_s, *len_src, len_ret); + strncpy(str_dst, str_src, len_min); + str_dst[len_min] = 0; str_dst[len_min + 1] = 0; + *len_src = len_min; + return str_dst; + } + + print("inside E2BIG len_mbsnrtowcs(%zu) len_src(%lld)", len_mbsnrtowcs, *len_src); + len_mbsnrtowcs = len_min; + } + + *len_src = len_min; // adjust converted length + str_dst[len_min] = 0; str_dst[len_min + 1] = 0; + + iconv(ws->ic, 0, 0, 0, 0); + + return str_dst; +} diff --git a/epgtest.cc b/epgtest.cc new file mode 100644 index 0000000..9fc6666 --- /dev/null +++ b/epgtest.cc @@ -0,0 +1,847 @@ + + +#include <stdio.h> +#include <unistd.h> + +#include "epg2vdr.h" +#include "update.h" + +int loglevel = 4; +cDbConnection* connection = 0; + +int fileExists(const char* path) +{ + return access(path, F_OK) == 0; +} + +cEvent::cEvent(tEventID EventID) +{ + schedule = NULL; + eventID = EventID; + tableID = 0xFF; + version = 0xFF; + title = NULL; + shortText = NULL; + description = NULL; + components = NULL; + memset(contents, 0, sizeof(contents)); + parentalRating = 0; + startTime = 0; + duration = 0; + vps = 0; +} + +cEvent::~cEvent() +{ +} + +int cEvent::Compare(const cListObject &ListObject) const +{ + return 0; +} + +void cEvent::SetTitle(const char* t) +{ + title = strcpyrealloc(title, t); +} + +void cEvent::SetShortText(const char *ShortText) +{ + shortText = strcpyrealloc(shortText, ShortText); +} + +void cEvent::SetDescription(const char *Description) +{ + description = strcpyrealloc(description, Description); +} + +void cEvent::SetStartTime(time_t StartTime) +{ +} + +void cEvent::SetDuration(int Duration) +{ +} + +// --- tChannelID ------------------------------------------------------------ + +const tChannelID tChannelID::InvalidID; + +tChannelID tChannelID::FromString(const char *s) +{ +// char *sourcebuf = NULL; +// int nid; +// int tid; +// int sid; +// int rid = 0; +// int fields = sscanf(s, "%a[^-]-%d-%d-%d-%d", &sourcebuf, &nid, &tid, &sid, &rid); +// if (fields == 4 || fields == 5) { +// int source = cSource::FromString(sourcebuf); +// free(sourcebuf); +// if (source >= 0) +// return tChannelID(source, nid, tid, sid, rid); +// } + return tChannelID::InvalidID; +} + +// cString tChannelID::ToString(void) const +// { +// char buffer[256]; +// snprintf(buffer, sizeof(buffer), rid ? "%s-%d-%d-%d-%d" : "%s-%d-%d-%d", *cSource::ToString(source), nid, tid, sid, rid); +// return buffer; +// } + +tChannelID &tChannelID::ClrPolarization(void) +{ + while (tid > 100000) + tid -= 100000; + return *this; +} + + +//*************************************************************************** +// Parse XML Event +//*************************************************************************** + +int parseEvent(cDbRow* event, xmlNode* node) +{ + const char* name; + char* content; + + for (xmlNodePtr n = node->xmlChildrenNode; n; n = n->next) + { + if (n->type != XML_ELEMENT_NODE) + continue; + + name = (const char*)n->name; + content = (char*)xmlNodeGetContent(n); + + printf("\t%s = '%s'\n", name, content); + + if (cDbService::FieldDef* f = cEventFields::toField(name)) + { + if (f->format == cDbService::ffAscii) + event->setValue(f->index, content); + else + event->setValue(f->index, atoi(content)); + } + else + printf("Ignoring unexpected element <%s>\n", name); + + xmlFree(content); + } + + return success; +} + +//*************************************************************************** +// +//*************************************************************************** + +MemoryStruct data; + +//*************************************************************************** +// Download Episodes and store to filesystem +//*************************************************************************** + +int downloadEpisodes(Table* episodeDb) +{ + // #CKO + + // cSvdrpClient cl("eplists.constabel.net", 2006 /*port*/); + cSvdrpClient cl("bauerl", 2006 /*port*/); + + string fileName; + string linkName; + int isLink = 0; + cEpisodeFiles files; + int code; + int abort = 0; + char command[50]; + int withutf8 = yes; + + if (cl.open() != 0) + { + printf("Open connection to '%s' failed, aborting transfer!\n", "eplists.constabel.net"); + return fail; + } + + printf("Starting episode download ...\n"); + + // select characterset + + printf("request charset ...\n"); + + if (!cl.send(withutf8 ? "CHARSET utf-8\n": "CHARSET iso-8859-1\n")) + { + tell(0, "Send '%s' failed, aborting transfer!", command); + cl.close(); + + return fail; + } + + // check for characterset confirmation + + cList<cLine> csconf; + + if (cl.receive(&csconf) != 225) + { + tell(0, "SVDRPCL: did not receive charset confirmation. Closing..."); + cl.abort(); + + return fail; + } + + if (csconf.First() && csconf.First()->Text()) + tell(0, "Got '%s'", csconf.First()->Text()); + + // identify myself + + + sprintf(command, "HELLO %s v%s (%s)\n", "epgd", VERSION, VERSION_DATE); + printf("send %s", command); + cl.send(command); + cl.receive(); + + // GET + + // sprintf(command, "GET all\n"); // #CKO + sprintf(command, "TGET newer than 4 days\n"); // #CKO + + printf("send %s", command); + + if (!cl.send(command)) + { + printf("Send '%s' failed, aborting transfer!\n", command); + cl.close(); + + return fail; + } + + cList<cLine>* result = new cList<cLine>; + + while (!abort && (code = cl.receive(result)) != codeCommunicationEnd) + { + switch (code) + { + case codeFileInfo: + { + if (result->Count() < 2) + { + if (loglevel > 1) + printf("Protocol violation, aborting!\n"); + + abort = 1; + } + else + { + linkName = ""; + fileName = result->Next(result->First())->Text(); + isLink = fileName != "not a link"; + + if (!isLink) + fileName = result->First()->Text(); + else + linkName = result->First()->Text(); + } + + break; + } + case codeFileContent: + { + if (isLink) + { + files.Add(new cEpisodeFile(fileName, linkName)); + } + else + { + for (cLine* l = result->First(); l; l = result->Next(l)) + { + if (strcmp(l->Text(), "End of data") == 0) + { + result->Del(l); + break; + } + } + + if (result->Count()) + { + // create episode file and adopt the result + + files.Add(new cEpisodeFile(fileName, "", result)); + + // create new result object since cEpisodeFile adopted the current + + result = new cList<cLine>; + } + } + + break; + } + + case codeTransferEnd: + { + abort = 1; + break; + } + } + + result->Clear(); + } + + printf("Received %d episode files\n", files.Count()); + files.storeToFile("./epl/"); + files.storeToTable(episodeDb); + + delete result; + cl.close(); + + return 0; +} + +//*************************************************************************** +// Update Map Table +//*************************************************************************** + +int updateChannelMap(cChannelMap* chanmap, const char* dbpath) +{ + Table* mapDb; + int count = 0; + + mapDb = new Table(connection, "channelmap", cChannelMapFields::fields); + + if (mapDb->open() != success) + { + tell(0, "Could not access sqlite database %s for table %s", dbpath, + mapDb->TableName()); + + return fail; + } + + mapDb->truncate(); + + tell(0, "Update map"); + + for (cChanMap::iterator iter = chanmap->chanmap.begin(); iter != chanmap->chanmap.end(); iter++) + { + const char* extid = iter->first; + + tell(0, "Update map for extid %s", extid); + + for (int index = 0; index < chanmap->GetChanCount(extid); index++) + { + mapDb->clear(); + mapDb->setValue(cChannelMapFields::fiExtId, extid); + mapDb->setValue(cChannelMapFields::fiChannelId, chanmap->GetChanStr(extid, index)); + mapDb->setValue(cChannelMapFields::fiSource, chanmap->isNull(extid) ? "epgdata" : "vdr"); + mapDb->store(); + tell(0, "insert '%s' to extid %s in map", chanmap->GetChanStr(extid, index), extid); + count++; + } + } + + tell(0, "Update channel map done with %d entries", count); + + delete mapDb; + + return success; +} + +//*************************************************************************** +// Main +//*************************************************************************** + +int main(int argc, char** argv) +{ + int res; + + if (argc < 1) + { + printf("Usage: %s \n", argv[0]); + return 1; + } + + Table::setConfPath("./configs/epg2vdr"); + cDbConnection::setHost("bauerl"); // #CKO + cDbConnection::setEncoding("utf8"); + + connection = new cDbConnection(); + + // ------------------------------------------------ + // Image Table Test + + + Table* imageDb = new Table(connection, "images", cImageFields::fields, cImageFields::views); + + if (imageDb->open() != success) + { + printf("Opening database 'images' failed\n"); + delete imageDb; + return 1; + } + +// imageDb->clear(); +// imageDb->setValue(cImageFields::fiEventId, 1212); +// imageDb->setValue(cImageFields::fiLfn, 0); +// imageDb->setValue(cImageFields::fiName, "1212.jpg"); +// imageDb->store(); + + imageDb->clear(); + imageDb->setValue(cImageFields::fiLfn, 1); // limit to config + + for (int res = imageDb->find(cImageFields::viAllLessLfn); res; res = imageDb->fetch(cImageFields::viAllLessLfn)) + { + int eventid = imageDb->getIntValue(cImageFields::fiEventId); + const char* image = imageDb->getStrValue(cImageFields::fiName); + int lfn = imageDb->getIntValue(cImageFields::fiLfn); + + char* destfile; + asprintf(&destfile, "./%s", image); + + // get image if missing + + if (!fileExists(destfile) && !imageDb->isNull(cImageFields::fiImage)) + { + printf("Store image '%s' with %ld bytes\n", + destfile, imageDb->getStrValueSize(cImageFields::fiImage)); + + if (FILE* fh1 = fopen(destfile, "w")) + { + fwrite(imageDb->getStrValue(cImageFields::fiImage), 1, + imageDb->getStrValueSize(cImageFields::fiImage), fh1); + fclose(fh1); + } + else + { + printf("can't write image to '%s', error was '%m'\n", destfile); + } + } + + free(destfile); + } + + imageDb->resetFetch(cImageFields::viAllLessLfn); + imageDb->clear(); + imageDb->setValue(cImageFields::fiLfn, 1); // limit to config + +// delete imageDb; +// return 0; + + for (int res = imageDb->find(cImageFields::viAllLessLfn); res; res = imageDb->fetch(cImageFields::viAllLessLfn)) + { + int eventid = imageDb->getIntValue(cImageFields::fiEventId); + const char* image = imageDb->getStrValue(cImageFields::fiName); + int lfn = imageDb->getIntValue(cImageFields::fiLfn); + + // if (lfn != 0) tell(0, "Got lfn %d from table, max is %d", lfn, EPG2VDRConfig.maximagesperevent); + + char* destfile; + asprintf(&destfile, "./%s", image); + + printf("Check for '%s'\n", destfile); + + // import the images from the FS into the table + + if (fileExists(destfile)) + { + printf("Found '%s' import to database\n", destfile); + + if (FILE* fh1 = fopen(destfile, "r")) + { + int size = 200000; + char* buf = (char*)calloc(size, sizeof(char)); + + size = fread(buf, 1, size, fh1); + + if (size > 0 || size < 200000) + { + printf("Copy image '%s' with %d bytes to table\n", destfile, size); + imageDb->setValue(cImageFields::fiImage, buf, size); + imageDb->store(); + } + + free(buf); + fclose(fh1); + } + else + { + tell(1, "Can't open image '%s', error was '%m'", destfile); + } + } + + free(destfile); + } + + imageDb->resetFetch(cImageFields::viAllLessLfn); + delete imageDb; + + return 0; + + // ------------------------------------------------ + // Constabel Test + + Table* episodesDb = new Table(connection, "episodes", cEpisodeFields::fields, cEpisodeFields::views); + + if (episodesDb->open() != success) + { + printf("Opening database 'episodes' failed\n"); + delete episodesDb; + return 1; + } + + // test insert ... + + episodesDb->clear(); + episodesDb->setValue(cEpisodeFields::fiCompName, "TESTSERIE1"); + episodesDb->setValue(cEpisodeFields::fiCompPartName, "TESTSERIE"); + episodesDb->setValue(cEpisodeFields::fiEpisodeName, "PART1"); + episodesDb->setValue(cEpisodeFields::fiPartName, "part1"); + episodesDb->setValue(cEpisodeFields::fiLang, "de"); + + episodesDb->store(); + + episodesDb->clear(); + episodesDb->setValue(cEpisodeFields::fiCompName, "TESTSERIE1"); + episodesDb->setValue(cEpisodeFields::fiCompPartName, "TESTSERIE"); + episodesDb->setValue(cEpisodeFields::fiLang, "de"); + + if (episodesDb->find()) + { + printf("Got: %s\n", episodesDb->getStrValue(cEpisodeFields::fiEpisodeName)); + printf("Got: %s\n", episodesDb->getStrValue(cEpisodeFields::fiPartName)); + } + + downloadEpisodes(episodesDb); + // evaluateEpisodes(episodesDb, evtDb); + + delete episodesDb; + + // ------------------------------------------------ + // Test Episodes Table ... + + printf("\n----------------------------------\n"); + + Table* epiDb = new Table(connection, "episodes", cEpisodeFields::fields, cEpisodeFields::views); + + if (epiDb->open() != success) + { + printf("Opening database 'episodes' failed\n"); + delete epiDb; + return 1; + } + + int days = na; + + epiDb->clear(); + epiDb->setValue(cEpisodeFields::fiCompName, "TESTSERIE"); + epiDb->setValue(cEpisodeFields::fiCompPartName, "TESTSERIE"); + epiDb->setValue(cEpisodeFields::fiEpisodeName, "test serie"); + epiDb->setValue(cEpisodeFields::fiPartName, "part1"); + epiDb->setValue(cEpisodeFields::fiLang, "de"); + epiDb->store(); + + epiDb->clear(); + + if (epiDb->find(cEpisodeFields::viMaxUpdSp)) + { + printf("found - max updsp is (%ld)\n", epiDb->getIntValue(cEpisodeFields::fiMaxUpdSp)); + + if (epiDb->getIntValue(cEpisodeFields::fiMaxUpdSp)) + days = (time(0) - epiDb->getIntValue(cEpisodeFields::fiMaxUpdSp)) / 60 / 60 / 24; + } + + epiDb->resetFetch(cEpisodeFields::viMaxUpdSp); + + printf("episodes have to get %d days\n", days); + + delete epiDb; + + // ------------------------------------------------ + // Test EPG Table ... + + printf("\n----------------------------------\n"); + + Table* db = new Table(connection, "events", cEventFields::fields, cEventFields::views); + + if (db->open() != success) + { + printf("Opening database 'events' failed\n"); + delete db; + return 1; + } + + db->setValue(cEventFields::fiEventId, 4711); + db->setValue(cEventFields::fiSource, "epgdata"); + db->setValue(cEventFields::fiTitle, "Test Title"); + db->setValue(cEventFields::fiCompTitle, "TESTTITLE"); + db->setValue(cEventFields::fiChannelId, "11"); + db->setValue(cEventFields::fiCategory, "cat 11"); + db->store(); + + db->clear(); + db->setValue(cEventFields::fiEventId, 4712); + db->setValue(cEventFields::fiSource, "epgdata"); + db->setValue(cEventFields::fiShortText, "blablabla"); + db->setValue(cEventFields::fiTitle, "Test Title 12"); + db->setValue(cEventFields::fiCompTitle, "TESTTITLE"); + db->setValue(cEventFields::fiChannelId, "11"); + db->setValue(cEventFields::fiFileRef, "test-1234"); + db->setValue(cEventFields::fiCategory, "cat 12"); + db->setValue(cEventFields::fiLongDescription, + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); + db->store(); + + db->clear(); + db->setValue(cEventFields::fiEventId, 4713); + db->setValue(cEventFields::fiSource, "epgdata"); + db->setValue(cEventFields::fiTitle, "Test Title what the fuck ..."); + db->setValue(cEventFields::fiChannelId, "11"); + db->setValue(cEventFields::fiFileRef, "test-11111"); + db->setValue(cEventFields::fiCategory, "cat 13"); + db->setValue(cEventFields::fiCompTitle, "TESTTITLEWHATTHEFUCK"); + db->store(); + + // fetch via view + + printf("lookup events for channel 11 via lview\n"); + + db->clear(); + db->setValue(cEventFields::fiChannelId, "11"); + db->setValue(cEventFields::fiSource, "epgdata"); + + for (res = db->find(cEventFields::viByChannel); res; res = db->fetch(cEventFields::viByChannel)) + { + if (!db->find()) + printf("FATAL!\n"); + + int id = db->getIntValue(cEventFields::fiEventId); + + printf(" -> found event '%s'(%d) [%s] '%s'\n", + db->getStrValue(cEventFields::fiTitle), + id, + db->getStrValue(cEventFields::fiCompTitle), + db->getStrValue(cEventFields::fiCategory)); + + if (!db->find(cEventFields::viVdr)) // perform select to load view fields + { + printf("Fatal can't lookup event %d\n", id); + continue; + } + + db->resetFetch(cEventFields::viVdr); + } + + db->resetFetch(cEventFields::viByChannel); + + int count; + db->countWhere("source = 'epgdata'", count); + printf("source 'epgdata' -> %d\n", count); + + db->countWhere("source = 'vdr'", count); + printf("source 'vdr' -> %d\n", count); + + db->countWhere("", count); + printf("all events -> %d\n", count); + + delete db; + + return 0; + + printf("\n"); + + // --------------------------------- + + printf("lookup events by comptitle 'TESTTITLE' lview\n"); + + db->setValue(cEventFields::fiCompTitle, "TESTTITLE"); + + for (int res = db->find(cEventFields::viByCompTitle); res; + res = db->fetch(cEventFields::viByCompTitle)) + { + if (!db->find()) + printf("FATAL!\n"); + + printf(" -> found (%ld) '%s' by comptitle [%s]\n", + db->getIntValue(cEventFields::fiEventId), + db->getStrValue(cEventFields::fiTitle), + db->getStrValue(cEventFields::fiCompTitle)); + } + + db->resetFetch(cEventFields::viByCompTitle); + + printf("\n"); + + printf("lookup event by db-view\n"); + + db->clear(); + db->setValue(cEventFields::fiEventId, 4712); + db->setValue(cEventFields::fiChannelId, "11"); + + if (db->find(cEventFields::viVdr)) + { + if (!db->find()) + printf("FATAL!\n"); + + int id = db->getIntValue(cEventFields::fiEventId); + printf(" -> found event '%s'(%d) [%s] '%s'\n", + db->getStrValue(cEventFields::fiTitle), + id, + db->getStrValue(cEventFields::fiCompTitle), + db->getStrValue(cEventFields::fiShortText) + ); + printf(" -> [%s]\n", + db->getStrValue(cEventFields::fiDescription)); + } + + db->resetFetch(cEventFields::viVdr); + + delete db; + + return 0; + + printf("----------------------------------\n"); + + // delete db; + + // ------------------------------------------------ + // Test Image Table ... + + printf("\n----------------------------------\n"); + + Table* imgDb = new Table(connection, "images", cImageFields::fields, cImageFields::views); + + if (imgDb->open() != success) + { + printf("Opening database 'images' failed\n"); + delete imgDb; + return 1; + } + + imgDb->setValue(cImageFields::fiEventId, 4711); + imgDb->setValue(cImageFields::fiLfn, 0); + imgDb->setValue(cImageFields::fiName, "ok 1"); + + imgDb->store(); + + imgDb->setValue(cImageFields::fiEventId, 4711); + imgDb->setValue(cImageFields::fiLfn, 1); + imgDb->setValue(cImageFields::fiName, "fail"); + + imgDb->store(); + + imgDb->setValue(cImageFields::fiEventId, 4713); + imgDb->setValue(cImageFields::fiLfn, 0); + imgDb->setValue(cImageFields::fiName, "ok 2"); + + imgDb->store(); + + // fetch via view + + imgDb->clear(); + imgDb->setValue(cImageFields::fiLfn, 1); + + for (res = imgDb->find(cImageFields::viAllLessLfn); res; res = imgDb->fetch(cImageFields::viAllLessLfn)) + { + int id = imgDb->getIntValue(cImageFields::fiEventId); + printf(" -> found image (%d) via view, name is '%s', lfn is (%ld)\n", + id, imgDb->getStrValue(cImageFields::fiName), + imgDb->getIntValue(cImageFields::fiLfn)); + } + + imgDb->resetFetch(cImageFields::viAllLessLfn); + + printf("----------------------------------\n"); + delete imgDb; + + // ------------------------------------------------ + + return 0; + + // ------------------------------------------------ + // Test File Table ... + + Table* fileDb = new Table(connection, "fileref", cFileRef::fields); + + fileDb->open(); + + fileDb->setValue(cEventFields::fiName, "test"); + + if (fileDb->find()) + printf("found with tag %s\n", fileDb->getStrValue(cFileRef::fiTag)); + else + printf("NOT found\n"); + + fileDb->setValue(cFileRef::fiTag, "1234"); + fileDb->setValue(cFileRef::fiFileRef, "test-1234"); + fileDb->store(); + + delete fileDb; + + // ------------------------------------------------ + + return 0; + + // ------------------------------------------------ + // Test XML parsing + + xmlDocPtr xml = 0; + + xml = xmlParseFile("test.xml"); + + if (!xml) + { + printf("Failed to parse test.xml\n"); + return 1; + } + + xmlNodePtr xmlRoot = xmlDocGetRootElement(xml); + + for (xmlNodePtr node = xmlRoot->xmlChildrenNode; node; node = node->next) + { + cDbRow* evt = 0; + char* prop = 0; + tEventID id; + + // skip all unexpected elements + + if (node->type != XML_ELEMENT_NODE || strcmp((char*)node->name, "event") != 0) + continue; + + // get/check id + + if (!(prop = (char*)xmlGetProp(node, (xmlChar*)"id")) || !*prop || !(id = atoi(prop))) + { + xmlFree(prop); + printf("Missing event id, ignoring!\n"); + continue; + } + + xmlFree(prop); + + // create event + + evt = new cDbRow(cEventFields::fields); + + evt->setValue(cEventFields::fiEventId, id); + evt->setValue(cEventFields::fiSource, "epgdata"); + + printf("event %ld\n", evt->getIntValue(cEventFields::fiEventId)); + + if (parseEvent(evt, node) != success) + delete evt; + } + + xmlFreeDoc(xml); + + return 0; +} diff --git a/episode.c b/episode.c new file mode 100644 index 0000000..af07bd2 --- /dev/null +++ b/episode.c @@ -0,0 +1,298 @@ +/* + * update.c + * + * See the README file for copyright information + * + */ + +#include <unistd.h> +#include <locale.h> +#include <zlib.h> + +#include "epgd.h" + +//*************************************************************************** +// Get Special +//*************************************************************************** + +int getSpecial(const char* line, const char* item, char* content, int max, int* count = 0) +{ + const char* p; + + unsigned int off = strlen(item) + 1; + + if ((p = strstr(line, item)) && strlen(line) > off) + { + snprintf(content, max, "%s", p+off); + + if (count) + (*count)++; + + return success; + } + + return fail; +} + +//*************************************************************************** +// Store To Table +//*************************************************************************** + +int cEpisodeFile::storeToTable(cDbTable* episodeDb, const cList<cLine>* linkLines) +{ + const int maxSeasons = 100; + + string::size_type pos; + string compName; + string lang = "de"; + string ename = name; + + char shortName[100] = ""; + char col1Name[100] = ""; + char col2Name[100] = ""; + char col3Name[100] = ""; + int exColCount = 0; + + const cList<cLine>* theLines = linkLines ? linkLines : lines; + + if (!theLines) + return done; + + if (isLink()) + ename = link; + + // detect language special + + if ((pos = ename.rfind('.')) != string::npos) + { + lang = ename.substr(pos+1); + + if (lang == "de" || lang == "en" || lang == "de-en" || lang == "en-de" || lang == "at") + ename.erase(pos); + else + lang = "de"; + } + + // build compressed name for episode lookup + + compName = ename; + prepareCompressed(compName); + + if (!compName.length()) + return done; + + // delete old entry of this episode + + episodeDb->deleteWhere("compname = '%s' and lang = '%s'", compName.c_str(), lang.c_str()); + + // parse ... + + unsigned short seasons[maxSeasons+1]; + int seasonNr = na; + int insideSeasonList = no; + char* line = 0; + + memset(seasons, 0, sizeof(seasons)); + + for (cLine* l = theLines->First(); l; l = theLines->Next(l)) + { + free(line); + line = strdup(l->Text()); + + if (l->Length() < 4) + continue; + + if (line[0] == '#') + { + getSpecial(line, "# SHORT", shortName, 100); + getSpecial(line, "# EXTRACOL1", col1Name, 100, &exColCount); + getSpecial(line, "# EXTRACOL2", col2Name, 100, &exColCount); + getSpecial(line, "# EXTRACOL3", col3Name, 100, &exColCount); + + // parse season list: + // # SEASONLIST + // # 1 1 10 + // # 2 11 20 + // # 3 21 30 + // # /SEASONLIST + + if (strstr(line, "SEASONLIST")) + { + if (strstr(line, "/SEASONLIST")) + insideSeasonList = no; + else + insideSeasonList = yes; + + continue; + } + + // is season info? + + if (insideSeasonList) + { + int s, v, t; + + if (!isdigit(line[2])) + { + tell(0, "Warning: (%s) Ignoring unexpected season line [%s]" + " missing number at position 3", name.c_str(), line); + continue; + } + + if (sscanf(line, "# %d\t%d\t%d", &s, &v, &t) == 3) + { + if (seasonNr == na) + seasonNr = s; + + if (s != seasonNr) + tell(0, "Info: (%s) Season line [%s] not in sequence, " + "expected season %d", name.c_str(), line, seasonNr); + + if (seasonNr > maxSeasons) + { + tell(0, "Warning: (%s) Ignoring unexpected season line " + "[%s] only %d seasons expected", name.c_str(), line, maxSeasons); + } + + // store part count of the season + + seasons[seasonNr] = t-(v-1); + seasonNr++; + } + } + + continue; + } + + if (!isdigit(line[0]) || !isdigit(line[1]) || line[2] != '\t') + continue; + + // found episode line ... + + string partNameComp; + char partName[200] = ""; + char comment[200] = ""; + char ex1[250] = ""; + char ex2[250] = ""; + char ex3[250] = ""; + char ex[250] = ""; + + int se; + int ep; + int no; + + // get lines like: + // "01<tab>1<tab>1<tab>Schatten der Vergangenheit<tab>[extcol1<tab>[extcol2<tab>[extcol3]]][<tab>#comment]<tab>" + + switch (exColCount) + { + case 0: + { + if (sscanf(line, "%d\t%d\t%d\t%[^\t\n]\t%[^\t\n]", + &se, &ep, &no, partName, comment) < 4) + { + tell(0, "Warning: (%s) Got invalid episode line [%s], " + "at lease 4 columns expected", name.c_str(), line); + continue; + } + + break; + } + case 1: + { + if (sscanf(line, "%d\t%d\t%d\t%[^\t\n]\t%[^\t\n]\t%[^\t\n]", + &se, &ep, &no, partName, ex1, comment) < 5) + { + tell(0, "Warning: (%s) Got invalid episode line [%s], " + "at lease 5 columns expected", name.c_str(), line); + continue; + } + + break; + } + case 2: + { + if (sscanf(line, "%d\t%d\t%d\t%[^\t\n]\t%[^\t\n]\t%[^\t\n]\t%[^\t\n]", + &se, &ep, &no, partName, ex1, ex2, comment) < 6) + { + tell(0, "Warning: (%s) Got invalid episode line [%s], " + "at lease 6 columns expected", name.c_str(), line); + continue; + } + + break; + } + case 3: + { + if (sscanf(line, "%d\t%d\t%d\t%[^\t\n]\t%[^\t\n]\t%[^\t\n]\t%[^\t\n]\t%[^\t\n]", + &se, &ep, &no, partName, ex1, ex2, ex3, comment) < 7) + { + tell(0, "Warning: (%s) Got invalid episode line [%s], " + "at lease 7 columns expected", name.c_str(), line); + continue; + } + + break; + } + } + + partNameComp = partName; + prepareCompressed(partNameComp); + + if (!partNameComp.length() || strcmp(partName, "n.n.") == 0) + continue; + + episodeDb->clear(); + + episodeDb->setValue("COMPNAME", compName.c_str()); + episodeDb->setValue("COMPPARTNAME", partNameComp.c_str()); + episodeDb->setValue("LANG", lang.c_str()); + + episodeDb->setValue("EPISODENAME", ename.c_str()); + episodeDb->setValue("LINK", isLink()); + episodeDb->setValue("PARTNAME", partName); + episodeDb->setValue("SEASON", se); + episodeDb->setValue("PART", ep); + episodeDb->setValue("PARTS", se < maxSeasons ? seasons[se] : 0); + episodeDb->setValue("NUMBER", no); + + if (!isEmpty(shortName)) + { + string comp; + comp = shortName; + prepareCompressed(comp); + + episodeDb->setValue("SHORTNAME", shortName); + episodeDb->setValue("COMPSHORTNAME", comp.c_str()); + } + + if (!isEmpty(comment)) + episodeDb->setValue("COMMENT", comment); + + if (!isEmpty(ex1) && !isEmpty(col1Name)) + { + snprintf(ex, 250, "%s: %s", col1Name, ex1); + episodeDb->setValue("EXTRACOL1", ex); + } + + if (!isEmpty(ex2) && !isEmpty(col2Name)) + { + snprintf(ex, 250, "%s: %s", col2Name, ex2); + episodeDb->setValue("EXTRACOL2", ex); + } + + if (!isEmpty(ex3) && !isEmpty(col3Name)) + { + snprintf(ex, 250, "%s: %s", col3Name, ex3); + episodeDb->setValue("EXTRACOL3", ex); + } + + if (episodeDb->store() != success) + tell(0, "Error: (%s) Can't store part '%s'/%d of " + "serie '%s' in database", name.c_str(), partName, ep, ename.c_str()); + } + + free(line); + + return 0; +} diff --git a/eptest.c b/eptest.c new file mode 100644 index 0000000..484270a --- /dev/null +++ b/eptest.c @@ -0,0 +1,126 @@ + +#include <stdio.h> +#include <errno.h> +#include <signal.h> + +#include "lib/config.h" +#include "lib/common.h" +#include "series.h" + +cDbTable* episodeDb = 0; +cDbConnection* connection = 0; +const char* logPrefix = ""; + +//*************************************************************************** +// Init / Exit +//*************************************************************************** + +void initConnection() +{ + cDbConnection::init(); + + cDbConnection::setEncoding("utf8"); + cDbConnection::setHost("localhost"); + + cDbConnection::setPort(3306); + cDbConnection::setName("epg2vdr"); + cDbConnection::setUser("epg2vdr"); + cDbConnection::setPass("epg"); + cDbConnection::setConfPath("/etc/epgd/"); + + connection = new cDbConnection(); +} + +void exitConnection() +{ + cDbConnection::exit(); + + if (connection) + delete connection; +} + +int init() +{ + episodeDb = new cDbTable(connection, "episodes"); + if (episodeDb->open() != success) return fail; + + return success; +} + +int exit() +{ + delete episodeDb; + return done; +} + +//*************************************************************************** +// Main +//*************************************************************************** + +int main(int argc, char** argv) +{ + const int max = 1000; + + FILE* fp; + char line[max]; + char* filename = argv[1]; + + cEpgConfig::logstdout = yes; + cEpgConfig::loglevel = 0; + + // at first allpy locale !! + + setlocale(LC_CTYPE, ""); + + // read dictionary + + if (dbDict.in("/etc/epgd/epg.dat") != success) + { + fprintf(stderr, "Error: Invalid dictionary configuration, aborting!"); + return 1; + } + + initConnection(); + + if (init() != success) + { + tell(0, "init of database failed"); + return 1; + } + + if ((fp = fopen(filename, "r")) == 0) + { + fprintf(stderr, "Error: Can't open '%s', %s\n", filename, strerror(errno)); + exit (0); + } + + cList<cLine>* result = new cList<cLine>; + + while (fgets(line, max, fp)) + { + // fputs(line, stdout); + line[strlen(line)-1] = 0; + result->Add(new cLine(line)); + } + + fclose(fp); + + char* f = filename; + + if (strrchr(filename, '/')) + f = strrchr(filename, '/') + 1; + + if (char* p = strstr(f, ".episodes")) + *p = 0; + + cEpisodeFile file(f, "", result) ; + + // insert / update series into database ... + + episodeDb->getConnection()->startTransaction(); + file.storeToTable(episodeDb); + episodeDb->getConnection()->commit(); + delete result; + + return 0; +} diff --git a/http/3rdParty/boilerplate5/css/main_post.min.css b/http/3rdParty/boilerplate5/css/main_post.min.css new file mode 100644 index 0000000..19f8328 --- /dev/null +++ b/http/3rdParty/boilerplate5/css/main_post.min.css @@ -0,0 +1 @@ +.hidden{display:none !important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.clearfix:before,.clearfix:after{content:" ";display:table}.clearfix:after{clear:both}.clearfix{*zoom:1}@media print{*,*:before,*:after{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="#"]:after,a[href^="javascript:"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}} \ No newline at end of file diff --git a/http/3rdParty/boilerplate5/css/main_pre.min.css b/http/3rdParty/boilerplate5/css/main_pre.min.css new file mode 100644 index 0000000..a7baa33 --- /dev/null +++ b/http/3rdParty/boilerplate5/css/main_pre.min.css @@ -0,0 +1 @@ +/*! HTML5 Boilerplate v5.0 | MIT License | http://h5bp.com/ */html{color:#222;font-size:1em;line-height:1.4}::-moz-selection{background:#b3d4fc;text-shadow:none}::selection{background:#b3d4fc;text-shadow:none}hr{display:block;height:1px;border:0;border-top:1px solid #ccc;margin:1em 0;padding:0}audio,canvas,iframe,img,svg,video{vertical-align:middle}fieldset{border:0;margin:0;padding:0}textarea{resize:vertical}.browserupgrade{margin:.2em 0;background:#ccc;color:#000;padding:.2em 0} \ No newline at end of file diff --git a/http/3rdParty/boilerplate5/css/normalize.min.css b/http/3rdParty/boilerplate5/css/normalize.min.css new file mode 100644 index 0000000..f6e0b65 --- /dev/null +++ b/http/3rdParty/boilerplate5/css/normalize.min.css @@ -0,0 +1 @@ +/*! normalize.css v3.0.2 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0} \ No newline at end of file diff --git a/http/3rdParty/fontello/LICENSE.txt b/http/3rdParty/fontello/LICENSE.txt new file mode 100644 index 0000000..6a22557 --- /dev/null +++ b/http/3rdParty/fontello/LICENSE.txt @@ -0,0 +1,75 @@ +Font license info + + +## Fontelico + + Copyright (C) 2012 by Fontello project + + Author: Crowdsourced, for Fontello project + License: SIL (http://scripts.sil.org/OFL) + Homepage: http://fontello.com + + +## Font Awesome + + Copyright (C) 2016 by Dave Gandy + + Author: Dave Gandy + License: SIL () + Homepage: http://fortawesome.github.com/Font-Awesome/ + + +## Entypo + + Copyright (C) 2012 by Daniel Bruce + + Author: Daniel Bruce + License: SIL (http://scripts.sil.org/OFL) + Homepage: http://www.entypo.com + + +## Typicons + + (c) Stephen Hutchings 2012 + + Author: Stephen Hutchings + License: SIL (http://scripts.sil.org/OFL) + Homepage: http://typicons.com/ + + +## Modern Pictograms + + Copyright (c) 2012 by John Caserta. All rights reserved. + + Author: John Caserta + License: SIL (http://scripts.sil.org/OFL) + Homepage: http://thedesignoffice.org/project/modern-pictograms/ + + +## Zocial + + Copyright (C) 2012 by Sam Collins + + Author: Sam Collins + License: MIT (http://opensource.org/licenses/mit-license.php) + Homepage: http://zocial.smcllns.com/ + + +## Elusive + + Copyright (C) 2013 by Aristeides Stathopoulos + + Author: Aristeides Stathopoulos + License: SIL (http://scripts.sil.org/OFL) + Homepage: http://aristeides.com/ + + +## Linecons + + Copyright (C) 2013 by Designmodo + + Author: Designmodo for Smashing Magazine + License: CC BY () + Homepage: http://designmodo.com/linecons-free/ + + diff --git a/http/3rdParty/fontello/README.txt b/http/3rdParty/fontello/README.txt new file mode 100644 index 0000000..beaab33 --- /dev/null +++ b/http/3rdParty/fontello/README.txt @@ -0,0 +1,75 @@ +This webfont is generated by http://fontello.com open source project. + + +================================================================================ +Please, note, that you should obey original font licenses, used to make this +webfont pack. Details available in LICENSE.txt file. + +- Usually, it's enough to publish content of LICENSE.txt file somewhere on your + site in "About" section. + +- If your project is open-source, usually, it will be ok to make LICENSE.txt + file publicly available in your repository. + +- Fonts, used in Fontello, don't require a clickable link on your site. + But any kind of additional authors crediting is welcome. +================================================================================ + + +Comments on archive content +--------------------------- + +- /font/* - fonts in different formats + +- /css/* - different kinds of css, for all situations. Should be ok with + twitter bootstrap. Also, you can skip <i> style and assign icon classes + directly to text elements, if you don't mind about IE7. + +- demo.html - demo file, to show your webfont content + +- LICENSE.txt - license info about source fonts, used to build your one. + +- config.json - keeps your settings. You can import it back into fontello + anytime, to continue your work + + +Why so many CSS files ? +----------------------- + +Because we like to fit all your needs :) + +- basic file, <your_font_name>.css - is usually enough, it contains @font-face + and character code definitions + +- *-ie7.css - if you need IE7 support, but still don't wish to put char codes + directly into html + +- *-codes.css and *-ie7-codes.css - if you like to use your own @font-face + rules, but still wish to benefit from css generation. That can be very + convenient for automated asset build systems. When you need to update font - + no need to manually edit files, just override old version with archive + content. See fontello source code for examples. + +- *-embedded.css - basic css file, but with embedded WOFF font, to avoid + CORS issues in Firefox and IE9+, when fonts are hosted on the separate domain. + We strongly recommend to resolve this issue by `Access-Control-Allow-Origin` + server headers. But if you ok with dirty hack - this file is for you. Note, + that data url moved to separate @font-face to avoid problems with <IE9, when + string is too long. + +- animate.css - use it to get ideas about spinner rotation animation. + + +Attention for server setup +-------------------------- + +You MUST setup server to reply with proper `mime-types` for font files - +otherwise some browsers will fail to show fonts. + +Usually, `apache` already has necessary settings, but `nginx` and other +webservers should be tuned. Here is list of mime types for our file extensions: + +- `application/vnd.ms-fontobject` - eot +- `application/x-font-woff` - woff +- `application/x-font-ttf` - ttf +- `image/svg+xml` - svg diff --git a/http/3rdParty/fontello/config.json b/http/3rdParty/fontello/config.json new file mode 100644 index 0000000..ea91e9f --- /dev/null +++ b/http/3rdParty/fontello/config.json @@ -0,0 +1,350 @@ +{ + "name": "epgd", + "css_prefix_text": "i-", + "css_use_suffix": false, + "hinting": true, + "units_per_em": 1000, + "ascent": 850, + "glyphs": [ + { + "uid": "9bc2902722abb366a213a052ade360bc", + "css": "progress", + "code": 59392, + "src": "fontelico" + }, + { + "uid": "0f99ab40ab0b4d64a74f2d0deeb03e42", + "css": "record", + "code": 59393, + "src": "fontawesome" + }, + { + "uid": "5211af474d3a9848f67f945e2ccaf143", + "css": "cancel", + "code": 59394, + "src": "fontawesome" + }, + { + "uid": "ce3cf091d6ebd004dd0b52d24074e6e3", + "css": "help", + "code": 59395, + "src": "fontawesome" + }, + { + "uid": "17ebadd1e3f274ff0205601eef7b9cc4", + "css": "help-circled", + "code": 59396, + "src": "fontawesome" + }, + { + "uid": "e82cedfa1d5f15b00c5a81c9bd731ea2", + "css": "info-circled", + "code": 59397, + "src": "fontawesome" + }, + { + "uid": "3d4ea8a78dc34efe891f3a0f3d961274", + "css": "info", + "code": 59398, + "src": "fontawesome" + }, + { + "uid": "e15f0d620a7897e2035c18c80142f6d9", + "css": "link-ext", + "code": 59399, + "src": "fontawesome" + }, + { + "uid": "f48ae54adfb27d8ada53d0fd9e34ee10", + "css": "trash", + "code": 59400, + "src": "fontawesome" + }, + { + "uid": "b091a8bd0fdade174951f17d936f51e4", + "css": "folder-closed", + "code": 59401, + "src": "fontawesome" + }, + { + "uid": "6533bdc16ab201eb3f3b27ce989cab33", + "css": "folder-opened", + "code": 59402, + "src": "fontawesome" + }, + { + "uid": "559647a6f430b3aeadbecd67194451dd", + "css": "menu", + "code": 59403, + "src": "fontawesome" + }, + { + "uid": "3a00327e61b997b58518bd43ed83c3df", + "css": "login", + "code": 59404, + "src": "fontawesome" + }, + { + "uid": "0d20938846444af8deb1920dc85a29fb", + "css": "logout", + "code": 59405, + "src": "fontawesome" + }, + { + "uid": "2d6150442079cbda7df64522dc24f482", + "css": "down-dir", + "code": 59406, + "src": "fontawesome" + }, + { + "uid": "80cd1022bd9ea151d554bec1fa05f2de", + "css": "up-dir", + "code": 59407, + "src": "fontawesome" + }, + { + "uid": "9dc654095085167524602c9acc0c5570", + "css": "left-dir", + "code": 59408, + "src": "fontawesome" + }, + { + "uid": "fb1c799ffe5bf8fb7f8bcb647c8fe9e6", + "css": "right-dir", + "code": 59409, + "src": "fontawesome" + }, + { + "uid": "a73c5deb486c8d66249811642e5d719a", + "css": "refresh", + "code": 59410, + "src": "fontawesome" + }, + { + "uid": "dd6c6b221a1088ff8a9b9cd32d0b3dd5", + "css": "check", + "code": 59411, + "src": "fontawesome" + }, + { + "uid": "4b900d04e8ab8c82f080c1cfbac5772c", + "css": "check-empty", + "code": 59412, + "src": "fontawesome" + }, + { + "uid": "f4445feb55521283572ee88bc304f928", + "css": "save", + "code": 59413, + "src": "fontawesome" + }, + { + "uid": "94103e1b3f1e8cf514178ec5912b4469", + "css": "sort-down", + "code": 59414, + "src": "fontawesome" + }, + { + "uid": "65b3ce930627cabfb6ac81ac60ec5ae4", + "css": "sort-up", + "code": 59415, + "src": "fontawesome" + }, + { + "uid": "3ed68ae14e9cde775121954242a412b2", + "css": "sort-name-up", + "code": 59416, + "src": "fontawesome" + }, + { + "uid": "6586267200a42008a9fc0a1bf7ac06c7", + "css": "sort-name-down", + "code": 59417, + "src": "fontawesome" + }, + { + "uid": "c9b928dc82d7d77033644fcf59dca3b3", + "css": "flashlight", + "code": 59418, + "src": "entypo" + }, + { + "uid": "7f6916533c0842b6cec699fd773693d3", + "css": "wait", + "code": 59419, + "src": "entypo" + }, + { + "uid": "cb13afd4722a849d48056540bb74c47e", + "css": "play", + "code": 59420, + "src": "entypo" + }, + { + "uid": "48f2e18872fe74d4579a4c8a1527fc1e", + "css": "stop", + "code": 59421, + "src": "entypo" + }, + { + "uid": "d8d378d0ce413f231dfa37592e39c227", + "css": "pause", + "code": 59422, + "src": "entypo" + }, + { + "uid": "0afbb00323696f49e9c47f4d9fe6390b", + "css": "to-end", + "code": 59423, + "src": "entypo" + }, + { + "uid": "ceefe7653a4f6edaacce9e7f196cec5a", + "css": "to-start", + "code": 59424, + "src": "entypo" + }, + { + "uid": "18f7c393e3532e40edd45607c9d99988", + "css": "forward", + "code": 59425, + "src": "entypo" + }, + { + "uid": "85806fd8ab907f45d34f976354a0df23", + "css": "rewind", + "code": 59426, + "src": "entypo" + }, + { + "uid": "40c9502d45c736a0a6ec45e6fbc28656", + "css": "ok", + "code": 59427, + "src": "typicons" + }, + { + "uid": "8f28d948aa6379b1a69d2a090e7531d4", + "css": "warning", + "code": 59428, + "src": "typicons" + }, + { + "uid": "0ohst63cgq1mf1syayvfl8mphms8dbes", + "css": "clock", + "code": 59429, + "src": "modernpics" + }, + { + "uid": "58b5f27abdf85c2b2b8db2770d61162d", + "css": "buffer", + "code": 59430, + "src": "zocial" + }, + { + "uid": "9e0404ba55575a540164db9a5ad511df", + "css": "doc-new", + "code": 59431, + "src": "elusive" + }, + { + "uid": "9725db89b610135dc76cd8a21afffa83", + "css": "search", + "code": 59432, + "src": "linecons" + }, + { + "uid": "2aeb4987b469d22fcb8b471b6d2cdfff", + "css": "edit", + "code": 59433, + "src": "linecons" + }, + { + "uid": "7697f1734d53461137f05faab3f79cf0", + "css": "tv", + "code": 59434, + "src": "linecons" + }, + { + "uid": "2f518b428fe0bc6fd682e666bd169427", + "css": "thumb-rate-up", + "code": 59435, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M1204.3 901.1C1199 982.2 1190.2 1028.8 1173.1 1065.4 1146.9 1121.9 1069.7 1209.8 1022.1 1237.5 992.2 1254.9 919.2 1272.6 874.3 1273.3 830.7 1274 820.4 1269 798.6 1236.7 772.6 1198.6 743 1173.2 699.2 1151.7 640.6 1122.9 627.2 1104.7 626.8 1052.8 626.4 1011 614.8 990.2 575.5 961.2 524.3 923.3 497 888.5 488.9 851 482.2 801.6 522.2 750.1 505.6 701.6 475.8 675.9 449.8 657.2 424.7 626.2 391.9 561.6 415.2 467.4 473.5 429.7 507.8 413 561.3 400.4 621.8 394.7 683.8 389 710.3 380 765.8 345.8 835.6 308.2 877.1 285.9 971.3 285L976.9 161.1C896 83.4 882.8 22 911-84.4 938.8-166.1 932.8-228.9 1017.6-269 1061-287 1094.3-290.3 1129.6-280.1 1189.4-262.7 1228.5-233.3 1249.7-189.9 1289.1-109 1295.2 65.2 1263.7 216.5 1244.9 279.5 1255.3 337.7 1283.5 395.6 1324 496.6 1306.2 518.9 1340.8 548.4 1246.6 696.2 1218.4 723.4 1204.2 901.3ZM1239 394.2C1208.3 336.7 1212.3 269.2 1227.8 208 1251.9 83.8 1267-78.3 1208.9-193 1185.3-227.3 1129.6-255 1084.2-255 976.3-252.1 973.6-171.2 948.4-89.1 928.9-45.5 927.2 7.7 947.3 51.4 985.9 125.8 1064.6 160.3 1126.2 211.2 1088.6 217 1053.8 200.2 1019.5 187.6L1023.9 297.8C1139.3 351.3 1147.6 455.2 1104.7 562.1 1143.9 591.1 1179.1 645.4 1178.6 723.3 1199.8 663.1 1249.7 614.9 1271.3 555.3 1284.7 495.4 1266.8 445.2 1239.1 394.2ZM971.9 874.5C930 885.7 889.4 889.8 898 881.9 900.3 879.7 928.9 866 961.4 851.5 1115.1 804.5 1197.7 610.1 1006.5 572.2 915 571 809.3 667.2 721.9 614.4 775.8 624.6 822.7 601.7 870.5 578.9 930.9 548.9 961.4 540.7 1014.1 540.5 1085.4 536.1 1083.7 457.8 1070 404.3 994.3 269.5 850.3 337 747.2 387.3 690.4 415.7 661.7 423.7 580.6 433.6 487 439.7 448.8 479.4 446.8 577.2 444.5 639.2 543.7 649.4 545.4 703.2 543.4 746.4 530.7 788.3 527.4 831.3 527.2 870.8 551.3 901.2 606.7 931.6 649.9 955.3 655 964.4 658.9 1024.6 660.5 1049.7 663.7 1073.2 665.9 1076.9 734.7 1125 776.1 1136.5 830.8 1210.1 914.7 1240.6 1094 1183.4 1075.5 1068.5 1000.3 1076.2 931.9 1080.6 875.2 1036.7 898.6 1031 922.5 1031.6 946.3 1032.9 1149.4 1086.1 1217.8 789.8 972 874.6Z", + "width": 1727 + }, + "search": [ + "thumb-rate-up" + ] + }, + { + "uid": "971842913945f59c7f3cf11e75e1e4f1", + "css": "flash-outline", + "code": 59436, + "src": "typicons" + }, + { + "uid": "3ab229dd9bccaaaf6c71096da4b72c04", + "css": "error", + "code": 59437, + "src": "elusive" + }, + { + "uid": "97b8d7283a173b3bba043e9738a5fbdc", + "css": "thumb-rate-up", + "code": 59393, + "src": "custom_icons", + "selected": false, + "svg": { + "path": "M971.9 874.5L972 874.6C1217.8 789.8 1149.4 1086.1 946.3 1032.9 922.5 1031.6 898.6 1031 875.2 1036.7 931.9 1080.6 1000.3 1076.2 1075.5 1068.5 1094 1183.4 914.7 1240.6 830.8 1210.1 776.1 1136.5 734.7 1125 665.9 1076.9 663.7 1073.2 660.5 1049.7 658.9 1024.6 655 964.4 649.9 955.3 606.7 931.6 551.3 901.2 527.2 870.8 527.4 831.3 530.7 788.3 543.4 746.4 545.4 703.2 543.7 649.4 444.5 639.2 446.8 577.2 448.8 479.4 487 439.7 580.6 433.6 661.7 423.7 690.4 415.7 747.2 387.3 850.3 337 994.3 269.5 1070 404.3 1083.7 457.8 1085.4 536.1 1014.1 540.5 961.4 540.7 930.9 548.9 870.5 578.9 822.7 601.7 775.8 624.6 721.9 614.4 809.3 667.2 915 571 1006.5 572.2 1197.7 610.1 1115.1 804.5 961.4 851.5 928.9 866 900.3 879.7 898 881.9 889.4 889.8 930 885.7 971.9 874.5ZM1239 394.2L1239.1 394.2C1266.8 445.2 1284.7 495.4 1271.3 555.3 1249.7 614.9 1199.8 663.1 1178.6 723.3 1179.1 645.4 1143.9 591.1 1104.7 562.1 1147.6 455.2 1139.3 351.3 1023.9 297.8L1019.5 187.6C1053.8 200.2 1088.6 217 1126.2 211.2 1064.6 160.3 985.9 125.8 947.3 51.4 927.2 7.7 928.9-45.5 948.4-89.1 973.6-171.2 976.3-252.1 1084.2-255 1129.6-255 1185.3-227.3 1208.9-193 1267-78.3 1251.9 83.8 1227.8 208 1212.3 269.2 1208.3 336.7 1239 394.2ZM1204.3 901.1L1204.2 901.3C1218.4 723.4 1246.6 696.2 1340.8 548.4 1306.2 518.9 1324 496.6 1283.5 395.6 1255.3 337.7 1244.9 279.5 1263.7 216.5 1295.2 65.2 1289.1-109 1249.7-189.9 1228.5-233.3 1189.4-262.7 1129.6-280.1 1094.3-290.3 1061-287 1017.6-269 932.8-228.9 938.8-166.1 911-84.4 882.8 22 896 83.4 976.9 161.1L971.3 285C877.1 285.9 835.6 308.2 765.8 345.8 710.3 380 683.8 389 621.8 394.7 561.3 400.4 507.8 413 473.5 429.7 415.2 467.4 391.9 561.6 424.7 626.2 449.8 657.2 475.8 675.9 505.6 701.6 522.2 750.1 482.2 801.6 488.9 851 497 888.5 524.3 923.3 575.5 961.2 614.8 990.2 626.4 1011 626.8 1052.8 627.2 1104.7 640.6 1122.9 699.2 1151.7 743 1173.2 772.6 1198.6 798.6 1236.7 820.4 1269 830.7 1274 874.3 1273.3 919.2 1272.6 992.2 1254.9 1022.1 1237.5 1069.7 1209.8 1146.9 1121.9 1173.1 1065.4 1190.2 1028.8 1199 982.2 1204.3 901.1Z", + "width": 1727 + }, + "search": [ + "thumb-rate-up" + ] + }, + { + "uid": "ec35e3afe47c84e7b9dfd728517b7c74", + "css": "thumb-rate-up", + "code": 59394, + "src": "custom_icons", + "selected": false, + "svg": { + "path": "M824.4 1236.6C1196.5 1253.3 1155 965.4 1196.3 738.4 1241.4 692.9 1296.6 633.6 1302.4 545.9 1284.3 449.8 1270.7 379.8 1230.8 258.6 1295.2-179.7 1226.4-292 1033.9-261.6 967-233.1 842.9-0.1 992 141.5L994.3 290.8C900.6 296.3 839.4 311.8 690.1 393.3 571.1 404.4 432.4 441.7 427.2 543.3 422.5 612.5 470.7 645.4 511.3 684.4 512.7 745.5 513.2 804.7 507.5 864.7 529.7 929.8 646.7 966 647.6 1078.2 684.3 1136.6 765.2 1183.9 824.4 1236.6Z", + "width": 1727 + }, + "search": [ + "thumb-rate-up" + ] + }, + { + "uid": "1a92f9fdade31855ab6e47ba357b0095", + "css": "thumb-rate-up", + "code": 59395, + "src": "custom_icons", + "selected": false, + "svg": { + "path": "M824.4 1236.6C1196.5 1253.3 1155 965.4 1196.3 738.4 1241.4 692.9 1296.6 633.6 1302.4 545.9 1284.3 449.8 1270.7 379.8 1230.8 258.6 1295.2-179.7 1226.4-292 1033.9-261.6 967-233.1 842.9-0.1 992 141.5L994.3 290.8C900.6 296.3 839.4 311.8 690.1 393.3 571.1 404.4 432.4 441.7 427.2 543.3 422.5 612.5 470.7 645.4 511.3 684.4 512.7 745.5 513.2 804.7 507.5 864.7 529.7 929.8 646.7 966 647.6 1078.2 684.3 1136.6 765.2 1183.9 824.4 1236.6ZM1204.3 901.1C1199 982.2 1190.2 1028.8 1173.1 1065.4 1146.9 1121.9 1069.7 1209.8 1022.1 1237.5 992.2 1254.9 919.2 1272.6 874.3 1273.3 830.7 1274 820.4 1269 798.6 1236.7 772.6 1198.6 743 1173.2 699.2 1151.7 640.6 1122.9 627.2 1104.7 626.8 1052.8 626.4 1011 614.8 990.2 575.5 961.2 524.3 923.3 497 888.5 488.9 851 482.2 801.6 522.2 750.1 505.6 701.6 475.8 675.9 449.8 657.2 424.7 626.2 391.9 561.6 415.2 467.4 473.5 429.7 507.8 413 561.3 400.4 621.8 394.7 683.8 389 710.3 380 765.8 345.8 835.6 308.2 877.1 285.9 971.3 285L976.9 161.1C896 83.4 882.8 22 911-84.4 938.8-166.1 932.8-228.9 1017.6-269 1061-287 1094.3-290.3 1129.6-280.1 1189.4-262.7 1228.5-233.3 1249.7-189.9 1289.1-109 1295.2 65.2 1263.7 216.5 1244.9 279.5 1255.3 337.7 1283.5 395.6 1324 496.6 1306.2 518.9 1340.8 548.4 1246.6 696.2 1218.4 723.4 1204.2 901.3ZM1239 394.2C1208.3 336.7 1212.3 269.2 1227.8 208 1251.9 83.8 1267-78.3 1208.9-193 1185.3-227.3 1129.6-255 1084.2-255 976.3-252.1 973.6-171.2 948.4-89.1 928.9-45.5 927.2 7.7 947.3 51.4 985.9 125.8 1064.6 160.3 1126.2 211.2 1088.6 217 1053.8 200.2 1019.5 187.6L1023.9 297.8C1139.3 351.3 1147.6 455.2 1104.7 562.1 1143.9 591.1 1179.1 645.4 1178.6 723.3 1199.8 663.1 1249.7 614.9 1271.3 555.3 1284.7 495.4 1266.8 445.2 1239.1 394.2ZM971.9 874.5C930 885.7 889.4 889.8 898 881.9 900.3 879.7 928.9 866 961.4 851.5 1115.1 804.5 1197.7 610.1 1006.5 572.2 915 571 809.3 667.2 721.9 614.4 775.8 624.6 822.7 601.7 870.5 578.9 930.9 548.9 961.4 540.7 1014.1 540.5 1085.4 536.1 1083.7 457.8 1070 404.3 994.3 269.5 850.3 337 747.2 387.3 690.4 415.7 661.7 423.7 580.6 433.6 487 439.7 448.8 479.4 446.8 577.2 444.5 639.2 543.7 649.4 545.4 703.2 543.4 746.4 530.7 788.3 527.4 831.3 527.2 870.8 551.3 901.2 606.7 931.6 649.9 955.3 655 964.4 658.9 1024.6 660.5 1049.7 663.7 1073.2 665.9 1076.9 734.7 1125 776.1 1136.5 830.8 1210.1 914.7 1240.6 1094 1183.4 1075.5 1068.5 1000.3 1076.2 931.9 1080.6 875.2 1036.7 898.6 1031 922.5 1031.6 946.3 1032.9 1149.4 1086.1 1217.8 789.8 972 874.6Z", + "width": 1727 + }, + "search": [ + "thumb-rate-up" + ] + }, + { + "uid": "373d597841b9e4db4979e00ad49d58a1", + "css": "thumb-rate-up", + "code": 59396, + "src": "custom_icons", + "selected": false, + "svg": { + "path": "M824.4 1236.6C1196.5 1253.3 1155 965.4 1196.3 738.4 1241.4 692.9 1296.6 633.6 1302.4 545.9 1284.3 449.8 1270.7 379.8 1230.8 258.6 1295.2-179.7 1226.4-292 1033.9-261.6 967-233.1 842.9-0.1 992 141.5L994.3 290.8C900.6 296.3 839.4 311.8 690.1 393.3 571.1 404.4 432.4 441.7 427.2 543.3 422.5 612.5 470.7 645.4 511.3 684.4 512.7 745.5 513.2 804.7 507.5 864.7 529.7 929.8 646.7 966 647.6 1078.2 684.3 1136.6 765.2 1183.9 824.4 1236.6ZM1204.3 901.1C1199 982.2 1190.2 1028.8 1173.1 1065.4 1146.9 1121.9 1069.7 1209.8 1022.1 1237.5 992.2 1254.9 919.2 1272.6 874.3 1273.3 830.7 1274 820.4 1269 798.6 1236.7 772.6 1198.6 743 1173.2 699.2 1151.7 640.6 1122.9 627.2 1104.7 626.8 1052.8 626.4 1011 614.8 990.2 575.5 961.2 524.3 923.3 497 888.5 488.9 851 482.2 801.6 522.2 750.1 505.6 701.6 475.8 675.9 449.8 657.2 424.7 626.2 391.9 561.6 415.2 467.4 473.5 429.7 507.8 413 561.3 400.4 621.8 394.7 683.8 389 710.3 380 765.8 345.8 835.6 308.2 877.1 285.9 971.3 285L976.9 161.1C896 83.4 882.8 22 911-84.4 938.8-166.1 932.8-228.9 1017.6-269 1061-287 1094.3-290.3 1129.6-280.1 1189.4-262.7 1228.5-233.3 1249.7-189.9 1289.1-109 1295.2 65.2 1263.7 216.5 1244.9 279.5 1255.3 337.7 1283.5 395.6 1324 496.6 1306.2 518.9 1340.8 548.4 1246.6 696.2 1218.4 723.4 1204.2 901.3ZM1239 394.2C1208.3 336.7 1212.3 269.2 1227.8 208 1251.9 83.8 1267-78.3 1208.9-193 1185.3-227.3 1129.6-255 1084.2-255 976.3-252.1 973.6-171.2 948.4-89.1 928.9-45.5 927.2 7.7 947.3 51.4 985.9 125.8 1064.6 160.3 1126.2 211.2 1088.6 217 1053.8 200.2 1019.5 187.6L1023.9 297.8C1139.3 351.3 1147.6 455.2 1104.7 562.1 1143.9 591.1 1179.1 645.4 1178.6 723.3 1199.8 663.1 1249.7 614.9 1271.3 555.3 1284.7 495.4 1266.8 445.2 1239.1 394.2ZM971.9 874.5C930 885.7 889.4 889.8 898 881.9 900.3 879.7 928.9 866 961.4 851.5 1115.1 804.5 1197.7 610.1 1006.5 572.2 915 571 809.3 667.2 721.9 614.4 775.8 624.6 822.7 601.7 870.5 578.9 930.9 548.9 961.4 540.7 1014.1 540.5 1085.4 536.1 1083.7 457.8 1070 404.3 994.3 269.5 850.3 337 747.2 387.3 690.4 415.7 661.7 423.7 580.6 433.6 487 439.7 448.8 479.4 446.8 577.2 444.5 639.2 543.7 649.4 545.4 703.2 543.4 746.4 530.7 788.3 527.4 831.3 527.2 870.8 551.3 901.2 606.7 931.6 649.9 955.3 655 964.4 658.9 1024.6 660.5 1049.7 663.7 1073.2 665.9 1076.9 734.7 1125 776.1 1136.5 830.8 1210.1 914.7 1240.6 1094 1183.4 1075.5 1068.5 1000.3 1076.2 931.9 1080.6 875.2 1036.7 898.6 1031 922.5 1031.6 946.3 1032.9 1149.4 1086.1 1217.8 789.8 972 874.6Z", + "width": 1727 + }, + "search": [ + "thumb-rate-up" + ] + } + ] +} \ No newline at end of file diff --git a/http/3rdParty/fontello/css/animation.css b/http/3rdParty/fontello/css/animation.css new file mode 100644 index 0000000..ac5a956 --- /dev/null +++ b/http/3rdParty/fontello/css/animation.css @@ -0,0 +1,85 @@ +/* + Animation example, for spinners +*/ +.animate-spin { + -moz-animation: spin 2s infinite linear; + -o-animation: spin 2s infinite linear; + -webkit-animation: spin 2s infinite linear; + animation: spin 2s infinite linear; + display: inline-block; +} +@-moz-keyframes spin { + 0% { + -moz-transform: rotate(0deg); + -o-transform: rotate(0deg); + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + + 100% { + -moz-transform: rotate(359deg); + -o-transform: rotate(359deg); + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} +@-webkit-keyframes spin { + 0% { + -moz-transform: rotate(0deg); + -o-transform: rotate(0deg); + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + + 100% { + -moz-transform: rotate(359deg); + -o-transform: rotate(359deg); + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} +@-o-keyframes spin { + 0% { + -moz-transform: rotate(0deg); + -o-transform: rotate(0deg); + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + + 100% { + -moz-transform: rotate(359deg); + -o-transform: rotate(359deg); + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} +@-ms-keyframes spin { + 0% { + -moz-transform: rotate(0deg); + -o-transform: rotate(0deg); + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + + 100% { + -moz-transform: rotate(359deg); + -o-transform: rotate(359deg); + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} +@keyframes spin { + 0% { + -moz-transform: rotate(0deg); + -o-transform: rotate(0deg); + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + + 100% { + -moz-transform: rotate(359deg); + -o-transform: rotate(359deg); + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} diff --git a/http/3rdParty/fontello/css/epgd-codes.css b/http/3rdParty/fontello/css/epgd-codes.css new file mode 100644 index 0000000..98daddc --- /dev/null +++ b/http/3rdParty/fontello/css/epgd-codes.css @@ -0,0 +1,47 @@ + +.i-progress:before { content: '\e800'; } /* '' */ +.i-record:before { content: '\e801'; } /* '' */ +.i-cancel:before { content: '\e802'; } /* '' */ +.i-help:before { content: '\e803'; } /* '' */ +.i-help-circled:before { content: '\e804'; } /* '' */ +.i-info-circled:before { content: '\e805'; } /* '' */ +.i-info:before { content: '\e806'; } /* '' */ +.i-link-ext:before { content: '\e807'; } /* '' */ +.i-trash:before { content: '\e808'; } /* '' */ +.i-folder-closed:before { content: '\e809'; } /* '' */ +.i-folder-opened:before { content: '\e80a'; } /* '' */ +.i-menu:before { content: '\e80b'; } /* '' */ +.i-login:before { content: '\e80c'; } /* '' */ +.i-logout:before { content: '\e80d'; } /* '' */ +.i-down-dir:before { content: '\e80e'; } /* '' */ +.i-up-dir:before { content: '\e80f'; } /* '' */ +.i-left-dir:before { content: '\e810'; } /* '' */ +.i-right-dir:before { content: '\e811'; } /* '' */ +.i-refresh:before { content: '\e812'; } /* '' */ +.i-check:before { content: '\e813'; } /* '' */ +.i-check-empty:before { content: '\e814'; } /* '' */ +.i-save:before { content: '\e815'; } /* '' */ +.i-sort-down:before { content: '\e816'; } /* '' */ +.i-sort-up:before { content: '\e817'; } /* '' */ +.i-sort-name-up:before { content: '\e818'; } /* '' */ +.i-sort-name-down:before { content: '\e819'; } /* '' */ +.i-flashlight:before { content: '\e81a'; } /* '' */ +.i-wait:before { content: '\e81b'; } /* '' */ +.i-play:before { content: '\e81c'; } /* '' */ +.i-stop:before { content: '\e81d'; } /* '' */ +.i-pause:before { content: '\e81e'; } /* '' */ +.i-to-end:before { content: '\e81f'; } /* '' */ +.i-to-start:before { content: '\e820'; } /* '' */ +.i-forward:before { content: '\e821'; } /* '' */ +.i-rewind:before { content: '\e822'; } /* '' */ +.i-ok:before { content: '\e823'; } /* '' */ +.i-warning:before { content: '\e824'; } /* '' */ +.i-clock:before { content: '\e825'; } /* '' */ +.i-buffer:before { content: '\e826'; } /* '' */ +.i-doc-new:before { content: '\e827'; } /* '' */ +.i-search:before { content: '\e828'; } /* '' */ +.i-edit:before { content: '\e829'; } /* '' */ +.i-tv:before { content: '\e82a'; } /* '' */ +.i-thumb-rate-up:before { content: '\e82b'; } /* '' */ +.i-flash-outline:before { content: '\e82c'; } /* '' */ +.i-error:before { content: '\e82d'; } /* '' */ \ No newline at end of file diff --git a/http/3rdParty/fontello/css/epgd-embedded.css b/http/3rdParty/fontello/css/epgd-embedded.css new file mode 100644 index 0000000..592255d --- /dev/null +++ b/http/3rdParty/fontello/css/epgd-embedded.css @@ -0,0 +1,100 @@ +@font-face { + font-family: 'epgd'; + src: url('../font/epgd.eot?45443790'); + src: url('../font/epgd.eot?45443790#iefix') format('embedded-opentype'), + url('../font/epgd.svg?45443790#epgd') format('svg'); + font-weight: normal; + font-style: normal; +} +@font-face { + font-family: 'epgd'; + src: url('data:application/octet-stream;base64,d09GRgABAAAAACj0AA8AAAAAQbQAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABHU1VCAAABWAAAADsAAABUIIwleU9TLzIAAAGUAAAAQwAAAFY/MkoJY21hcAAAAdgAAAEbAAAD5ljZ8FtjdnQgAAAC9AAAABMAAAAgCRX84GZwZ20AAAMIAAAFkAAAC3CKkZBZZ2FzcAAACJgAAAAIAAAACAAAABBnbHlmAAAIoAAAG7kAACnQ27ixt2hlYWQAACRcAAAAMgAAADYNC5xTaGhlYQAAJJAAAAAgAAAAJAh1Bj1obXR4AAAksAAAAHQAAAC8lTj/vGxvY2EAACUkAAAAYAAAAGDfHOpabWF4cAAAJYQAAAAgAAAAIAGBDJ9uYW1lAAAlpAAAAXgAAAKdc1jeP3Bvc3QAACccAAABWgAAAfu5TV0AcHJlcAAAKHgAAAB6AAAAhuVBK7x4nGNgZGBg4GIwYLBjYMpJLMlj4HNx8wlhkGJgYYAAkDwymzEnMz2RgQPGA8qxgGkOIGaDiAIAKVkFSAB4nGNgZNZlnMDAysDAVMW0h4GBoQdCMz5gMGRkAooysDIzYAUBaa4pDA4vGF7oMgf9z2KIYiliXAEUZgTJAQDTLAu7AHic7dNZUsJAFIXhPxBxQsV5nnAeyLOLc0E+ua6zCzy3OcswVV9XpSsEivs3sAaM7dN66H7pqOvHu13bH7PV9nu+2zN97WuxXHqlVt/3bR352d5vnLDOBpv+3DZTdthljxn7HHDIEceccMoZ51xwyRXX3HDLHffMeeCRJ5554ZU33vnw9y8Y/PIJ/9e0ltFX7ob6/1faRMJTQFGTVdSMFDV1haeFwnND4Qmi8CxRVA0KzxdF/TqFZ47C00fhDlC4CBRuA4UrQeFeULgcFG4IhWtC4a5QuDAUbg2Fq0Ph/lC4RBRuEoXrROFOUbhYFG4XhStG4Z5RuGwUbhyFa0fh7lH4BKDwWUDhU4HC5wNFnWCFz4xP6ArDH+xSbWcAeJxjYEADEhDIUvQvAoQBE0QD+QB4nK1WaXfTRhQdeUmchCwlCy1qYcTEabBGJmzBgAlBsmMgXZytlaCLFDvpvvGJ3+Bf82Tac+g3flrvGy8kkLTncJqTo3fnzdXM22USWpLYC+uRlJsvxdTWJo3sPAnphk3LUXwoO3shZYrJ3wVREK2W2rcdh0REIlC1rrBEEPseWZpkfOhRRsu2pFdNyi096S5b40G9Vd9+GjrKsTuhpGYzdGg9siVVGFWiSKY9UtKmZaj6K0krvL/CzFfNUMKITiJpvBnG0EjeG2e0ymg1tuMoimyy3ChSJJrhQRR5lNUS5+SKCQzKB82Q8sqnEeXD/Iis2KOcVrBLttP8vi95p3c5P7Ffb1G25EAfyI7s4Ox0JV+EW1th3LST7ShUEXbXd0Js2exU/2aP8ppGA7crMr3QjGCpfIUQKz+hzP4hWS2cT/mSR6NaspETQetlTuxLPoHW44gpcc0YWdDd0QkR1P2SMwz2mD4e/PHeKZYLEwJ4HMt6RyWcCBMpYXM0SdowcmAlZYsqqfWumDjldVrEW8J+7drRl85o41B3YjxbDx1bOVHJ8WhSp5lMndpJzaMpDaKUdCZ4zK8DKD+iSV5tYzWJlUfTOGbGhEQiAi3cS1NBLDuxpCkEzaMZvbkbprl2LVqkyQP13KP39OZWuLnTU9oO9LNGf1anYjrYC9PpaeQv8Wna5SJF6frpGX5M4kHWAjKRLTbDlIMHb/0O0svXlhyF1wbY7u3zK6h91kTwpAH7G9AeT9UpCUyFmFWIVkBirWtZlsnVrBapyNR3Q5pWvqzTBIpyHBfHvoxx/V8zM5aYEr7fidOzIy49c+1LCNMcfJt1PZrXqcVyAXFmeU6nWZbv6zTH8gOd5lme1+kIS1unoyw/1GmB5Uc6HWN5QQuadN/BkIsw5AIOkDCEpQNDWF6CISwVDGG5CENYFmEIyyUYwvJjGMJyGYawvKxl1dRTSePamVgGbEJgYo4eucxF5WoquVRCu2hUakOeEm6VVBTPqn9loF488oY5sBZIl8iaXzHOlY9G5fjWFS1vGjtXwLHqbx+O9jnxUtaLhT8F/9XWVCW9Ys3Dk6vwG4aebCeqNql4dE2Xz1U9uv5fVFRYC/QbSIVYKMqybHBnIoSPOp2GaqCVQ8xszDy063XLmp/D/TcxQhZQ/fg3FBoL3INOWUlZ7eCs1dfbstw7g3I4EyxJMTfz+lb4IiOz0n6RWcqej3wecAWMSmXYagOtFbzZJzEPmd4kzwRxW1E2SNrYzgSJDRzzgHnznQQmYeqqDeRO4YYN+AVhbsF5J1yieqMsh+5F7PMopPxbp+JE9qhojMCz2Rthr+9Cym9xDCQ0+aV+DFQVoakYNRXQNFJuqAZfxtm6bULGDvQjKnbDsqziw8cW95WSbRmEfKSI1aOjn9Zeok6q3H5mFJfvnb4FwSA1MX9733RxkMq7WskyR20DU7calVPXmkPjVYfq5lH1vePsEzlrmm66Jx56X9Oq28HFXCyw9m0O0lImF9T1YYUNosvFpVDqZTRJ77gHGBYY0O9Qio3/q/rYfJ4rVYXRcSTfTtS30edgDPwP2H9H9QPQ92Pocg0uz/eaE59u9OFsma6iF+un6Dcwa625WboG3NB0A+IhR62OuMoNfKcGcXqkuRzpIeBj3RXiAcAmgMXgE921jOZTAKP5jDk+wOfMYdBkDoMt5jDYZs4awA5zGOwyh8Eecxh8wZx1gC+ZwyBkDoOIOQyeMCcAeMocBl8xh8HXzGHwDXPuA3zLHAYxcxgkzGGwr+nWMMwtXtBdoLZBVaADU09Y3MPiUFNlyP6OF4b9vUHM/sEgpv6o6faQ+hMvDPVng5j6i0FM/VXTnSH1N14Y6u8GMfUPg5j6TL8Yy2UGv4x8lwoHlF1sPufvifcP28VAuQABAAH//wAPeJytegl0HMd1bb3qvWemp2e6p2cwABqz9mAZDMBZQRIEhgBBgEOQhkCaAihwCNEkLQmiKCmSqMhytDhRKCcRk9hhZEdOKEVOzk+8aLfi7/99EusoznGiLTLj6Hz7W7aTr28nkU8i59g8RCOverBpcZycBEt1dXf163qvXt13X1UTWPnhyl3cD7gJspUE6/48kAlCyEkDhEhfVpREJ+f91qqjUK1VbSqJ7Ddqsd9qbQRyZbxdAKlSbV2LWnibu3Li6OE/P9zcdSSbjsffr6tK+1hB1iRlIt5mRccb1x57fryyFRI9B2b+6sStZ25dWBxIUzpU05WJdFLM5nYduetDH777A4YqhKTCSHtAaSw2r2qON8zwxL4dD87MTl9d35FKQY9h7N5z4+z8lX8wYWGnCRCy8hPuDfoV0kUy9WSbTAkHk4Ry9DThCHeatThNAE5GKpUML8T6IGRKYjo1ABFTTCdTTiVUrpaSRasTatVSMWpxb1iSFFRfb465Z8abzXG4f6z5uhqUJIs+sHwhqnDq6wve9bOsXHhdpepaP96kr9L7SIbY9fZUmy7xhMIkB5TQ04C3T5odpsl6kDWDIGIHJFY45VHIsaJa7MIeYGHh7ahFXw1O63n90UexmNbZUd84DwYffTR4o8Uqn/508N0NgwXWgFBmG7oVbRMk28nS09hJgMm9jwVn5uoO4TnK8SewjxyFJSIQjhe4RaYHHMRmZI7pNN1ez7Ua0lM/o+V8XcmZfbaTEYV4XxaNK6VTzg4oV6OlomWYGidpsOkqulHZyaWYY7HBKHjWtyncr8n3KZqm3Kf4H9djTjwStfFE9jd6kx3lVCZmdkuqJF0lU37+j/oPTxV+CxuC9wz4YcIupxJhNTAYUHWwlHhh1tATxRToWlHhd4u6/PHUtkOEcCvLK49zRzkf2qVGdpGp+kQPCJwCFAidJDw6D8+dIpxAOWGJSITyEl1EvQkIBPUWRU9vcY6IIE5H7D7Dcpy0LHT0ZStlpw9SYieY1nYoVo1yAdKoIw5qqYgaFy1mAQ2ikdb9Ms6wES5qapAqULxtA7ylykuy6hXnRha2nJ1UAg1eVAQ7O9RrtaeHwbsVC3eotun/m5uff+OrN4h3fOmtL/7C7NpjKty15WDhTMBX4yWn3Q5H4v7gWNbEG+GUTxfjHd2ztz53yy3PfZ8Vm2xhkwJ6yZ767u4EFQVNpBRiQHnCTRKZCKIsLBKRABVhEWcXoJXQFrwk8QcJz0tzROKl6Qgawgk56bQidK4aI7TZIpH0hm24d9hK2GQFul2Vqqr8BNOoUmHlJUmd3LAMnNis+DxesNkdrDzplSpcnl+9oH57k7L4480JOLmq72h9uAsEMR6mlJPxHqCyIhE4EZXlPIdf5MFzdDyseXrFSTtJqyQJ7S0/RxDJVdCjS5X0Wq1oRUNYcJscHnW04ISpu98NmmBp6bR3uIhlOmhNWdo5zcIiaB6f9G6w8mLrYGnuly1665JXXcJm63pwb3CzJEdGyXR9Tzd6ZAg9uFagPE2CwPOTzD9P40AJlBdOoVZU4JZQAcoDZeoR7iDhOKYUR6a3tWcr1ayn1GZkrHnI6J2LUsi0oslidU0bI4RDNgDQgrEagzEPSblwc9wdbGGnpKqSeyZbhmoGXsqWVTkjqxetDt8x9+OCztdxKl1/zGdp0InKTT/hPfPSWBO8duWsO+g9yfwAXmOGo358UBTr6J7swY6WLUS0xeNc2JvPXWQAvXicfJAcr1995QQV5Z5kW0gB5rqTaAKsiEBO8ZQSSSTSEtGIImvKYjBAZb+K3i2LTSL5fNJBIkm+OeKTfNMnjl/dvGr+wOz7pvdM7hw1M6bDftI6OjlGExG92LMVs0n0Z5wboWTItAHNNAJQwjCaFiUhwtqEWkbPhdb9BQGDeVIXYAG2ZxKvOLdRfUCVWlVJnXL9skzhJSrL7v2X2nnhcZGHH6hyddWM3jT6TE7JW09Ee5XcZ3HSfMH9MrsIO1n5U+rucRpaftNvqqpJT+wUAIQD+MblNwu7xgrU8DpxJNIBtnlEXfXJh3EcoiRP8vUewiNk8uBhJ2XYSTmOHiQ42eYIBpXpdAV/Sl7AQJxYnUgOzhgxgr6GRqoaoQ1fZPbrBOZg83bUPRO1wY4+aSUSFv1DKzHZKC3PlxqN0pOlBpwpNW6D+60EJKwMlnZ0+Q1sB7/nnmEtaIyV4QabAis/4XuwvyGcRROkUZ/M4CwHhgG8JPKLiP0clbhFWUF3QQdi6C8IHvoLc0QAYdoIj9V3bB+qDPYn7TYrnDNy1S2qYPVBmc0YjPMRk6mB4T2brLxTRRxgAYO9Bu/SMBphEGJx37GXH7bKgUd9Nj0aLQYfVZc/Ap9NWO6X15Q/1zZDv9/26dhsdvnhNe0HylOwZJd9Muw1YqGvBRQzrn/Nf/zwJnu4mc/bzuF04mu2s2GP0uF4e4jNJ88u3GH63Op8qtXL3cALHkBifBSQEQj8OkC+kwg4FfwtrbOANXRMtuAwt3oeXT1Pbz6fN/XLb3owx4WCFvw7Z5tQ0gJ9SsPbQa8EbZIB6SR7YAMn51GXGKmTmfo+PyBITiZxmHcTDukHJyKzQaCkcAoHVwSM+ETgUcdTOPoicl/mvbxwkAgCP4cVfjqf7c0ZVtpkER9MCfEPJ+w69GNhRcGqrU78Ws7BGA9Igqq5kDfwZaeKeLl60aK/5XNf9tnmJU+fS6btgwHfc83xJyTsKOuqLD+RrSJXekpUMSKvXhlvQlPzuS+pZvDhVhB5WLOogheedm8fb6qyTxEDksxQ9yw+zVOZX73SXLfJEvLCHNpkrD5qolTm9RgpxI1IwSN/5skpFjFEL2Lwb4sYVrot25vNeWHQtJgbs1C35saRqHcpl16NGx6522QsjwOuGQtO0DW9UHNEpjXFGfo/JVLkIiIzU4d1iQ3uJQwgaKUCDQuawkOLi6/rXHbc2/FB1Bny722jVb6OhhiGf8QAEK2bLWrMytMsFaqYlE3iVaK+GteQlVzydfgusXj1FvraX2hYxz8vCsHKCsrbDn+B8kJ1bV1SpMgkZT3HL0CL5qMkM+j6WTi7pNrqJfWPmefavksqvmCtb/BBeicJvEffoobXN/Sv1fSh6hGLhOI93hGjc65fs3yrXV3XFXbSD2Pf1C8wGSZL9VrqsREbAewU7FQ9XfAxlXlXS89WJ1s+8zh3FWJlhkySI/XD41kqKgM4Y6IIAjIAh3xDkUVZEU9JeBUdiZ5CosGJlJEOdCWMukgkRUHGGYUnm11p94STzVazTsXMqCyomhHNm1CSuMGdEExtqBUxIa21ImmkNcEQWx3mZPjrzbfKCIuXUUylLG5v5nufuOLB4SmmlnaJjf6+7uO1xr05Mcb7kUdqpt66OnvjXrwYFfyncdpl/v4TV3ySPRTDpADOf3Fk65TPexxNsy/TC40RdSjgh2dXr+xrnYv8asu1+XUBbdVPxsj++t7twItZjIQInhJ6toTJlIgsTUSM4Rk5W9pEzsT3IGdmNJKrbK2UPMR5OzvDQICjmM4572Bo6BYsmzVgw0u6oOV95iaC9lLaVjipHUlIwL/KthhPEzIIjLzvHndrIKP9UNN2aBntY3AtnowEYO/j6zxN4w2xQwBunar9miykUTUQ3G2a9kOvfYA9GEAJq3YxVnlaX70bIQWYb2AMQWxjMYTOYVCh05TY7ZahSiRIg4Jg9sEm5VBxJxp6O0WlN23qfPnODfXGFulX1jvHbs6v32kiLyHIUJhfz2OfOJIkW5AFXFHf39ebTvEyD5MBHDiQ6W6iSsDLKgY9mXCizHmpEBLJpoDEQFHILDsSZY4oRJmu7xiqRJ1SyNgeCuk+9OdospIUSthtludK60EvHWL4x5BFWkuGWGKInK8qrLPBVoMu9P2L8Fn3ALw15Rc+JXTIGMP/t2XD1FQiAi9jTL+IiRH6bqs8jownjJ6B1EiIVoMP6ZZ08SK8Jcelh0Q/MC5kvbFc9Y5ge1kWCzequnzJo1P/ZCVi2qeC1bV1ja8jTkbfEycds4Vu6zhZezdO/ktQZTCJ+Sps4CT9f++Jk61M46fiJEKuh09M3OrYXcf9HuZAKkmREbIfttSDUYSWch55vwOgcJN7HzNm5uqNEHiLQRLiknQCYUkVqbpkgKoo6gdQUsBPAk0zrGu8Pwg+2e9rMqiSWC6goJiDOMYwj+RXgX3tex8zUeLenypRVJWl/6TI+vRmaR5u/hfEzc/Xu0dH0+nR/aP7903vbeyZmtw9sWt8bGc9PZIe2YFe2Waa6YytRxjWlnDcKmkcQGk93CG+rkVxlsUKkWTFQJitpBFhI+lKMsIhGEcYDFcMPC/l0lKJHY2SQT9xrJutHCDFd18Tn8A87UlZDix5WTtL3F9xv/iCJIiyqN47Djte4DFgCL5fufXh3vjZeO+F3N1X3U1vuCOuUJ+qisu7RekJQXhSiXCE+egyURv3FiHnQwpO63cX3W/wOC2BjsGPhodnZoaH4Sb3HHmXXxTJPhiv+3ePRDmNq0IgRFed4goS1MJa8IQJ4VAo/AHiC9CAzzM+CVCypOOQaEFOa2J2EPCFAkdRMksZm4ZflREWQJxt1UQ4pAiYWEJj1TdmNwnWwqGl/w7J9QMtoeFT/41SmaeUSul0aV9p3/Selo9UyuliurhlcKDQnw+FQhuekt3wFOGnesrbvYFb85yUmFv3HeY6pcrPcBTKb3IJX8tpgOdW3cYvyr9TarmJIt31Li/5je3bZ2a2b4eb3QfoRz5SgpwqCOxVzGf+NojVcbYG+JOV89zHuEFikg7Sg7zISbRZhsL19wELqUhdQSzQGjCCUbXAquYcjYJNqwVetIHLjRQ67tMXiu414f1T8TA8KJr62dhZ9xcSzYQ22I2hwZ4eFP3dw1MFWe2mfzZyNnafborYPNaYxubFBf1sx6Dbm1jIaHJ3AeJ2tyoXGsPdfnlwejUHu44Oog+3k25yjK3LVYpoLEbm5/ZRInKYiPEiL2D6gtmqSBhI3IBwymFShok2z3uJNktZKD99YDbensl1xiXMysDUkGwCW9Xx2NUIlAvAWBYOosCW+UvFGiqbThnlEYq6V2piKhc1uzjLwaRHo0EqOmJF7IQRWikXIygqWikPUC+40cHFY8cWP/ONz7DD5179nGuHeXnhzl+c0+zF627/dbnD39a5QI+/dZw/3G+EQn7bj0An+4NBmjos37KrPHaHuNAXDgh+iac35K9pDi+cLNyW2r8/dVvh5MJw85r8bYn9+xOiJovlompW3UbYzmixjgW7WK0WE4f7jEiEDqrhsKYGdZ2m4HBijHcGU7adGnT4MXuhx9Bk02+tc+K36G8SHxGfVAXAcbdYfuJxiij8vaa5B2OpVAxux9Dj/qtu2pTapr6RO8zRjxI/idUjFNb2GIBIPPGDj2OUpRgJmRjMvP0FqjUa7sh0ppt+tO72jo3BxUyHxxOxCNMvIZSHSLqeQC7IMVkcJkAnVQWIFlBCakjgiQyyuCaUiUyuVeDZw0+5lw8/Rb9UX35+bIxuq68d1+TP0XtRR/PtPQ34Q7rfDJheT1FvYVXv7Lrch9AA562ODgv+T+M83KbG1e9p4Th8MR7Wure5hW3b4JVtZPM7/PgOFtHXXmHYLKIb5Vq2iuiACVDWyZVb4j+nwfVmR4fpflz73PnzmGx4st3dKPt76r9u88SvyeZuxDyIrSjJT1shVaD9b+uvtKnOHcMu/6pl29YsVh40EwkT+90h/1jTO+A7Hbr2480nb5PvJ22efIVH+aHNXc5uPtHgNibV/agGz2twjVd/UGP9Z2Jdm71D1t52trYG8Tdclv4dMYhDttarGXV1lwroaWTAHLkRWTDnEWBuDuk0cNMRE4jpRJxgQJaIAQYbfaG10MqokeFlOeiuSBqRHVrVGlSdnIOsPefAqbH+lwqF/C/mRy+Yjd65hbx7uc99JZIA/aVw2Q+8TwsZ3b7vXgj29L9cuKeQz2P+5+QfvMLtm4GHEz36y4Zswdej3bLqD7vXXAh6MXXluyvneZtzPFvZiJjT9T0pRo+91TKCuYwMVEJS7O0LEAF4YXGTVoQppQWAdOfszo72SDjQprXJAs4Wv8J8MIW6eCt+OXByxShYHv9FrYxy0UwZGHByTgWxyqJ0S8L9y0TvGL1pZz7l/lVy4LpRTHc++OHlcx9aqkNlJHf27G+Kk3vEwlie/q/a8kptZqZGoXbt0vLKtf/zT5YoLC3fMnEW7tSCTz4Z1BIFWmT6IZ9c+SrXT3+EXtxDtmLetpccJEfISXTm28nH6r8ewVnPSYRji4KyIMmLCghEFQV10QCfCX7e58esIAp8gC0cBogWDmiLOK3DwVB4ERMenQb1RYsttNCDFkt35jDpgel8r4WSz9z2czffcOq6a08cv3px4aq5Kw/Mvm9/Y8/uiZ31HcPVcnFL79b81kRXpMfq8anEBDPmYQHbeTVZ4pti27VllhkbRVay/VnH21szWRuD7bA5I9RbSdYwW0OoZ+AffVdFelcl964KnL/h6EJ1aKi6cPSbzYVqrVZdaJ4+1Jjq7evrnWp8Zq3ywl0R/zmNj6e1e6+3ojT66WA4qJnaH2p4MLQ9rbMx/Mfa51uHR9g9M7C3daA/Gqq0XsHe1fzm0YXK0HJ/3nvHJHvHpPeyPPiDDwVTMao90J5phy5VY8KGWodHlCB70e/imaFpo62zva3Dn7QOa7GW+2uMtRUc719j650/D5Q7WKWE78JJyrbAOIr0HHP20+jb/Mau8i/fd+r67dvyfaYgRPoqI7RWxHCIJsfpubZ9Dpi8UbymUUkD/GPUCbFkgBZoiD1gdVG2r84a4ym2L9kcayxoHNtmx4I1yxaZICu6KgqFtP6cdDZXwLnh6x3yG3ZGGvi6kcrTfVvtXscK2HowzMVVkQO1d1jt+6O81KHEkdK5PxbjpWpnSvH1bsOnzLa73t9rZCJtuxZ8vSlDT/QicmsSPlRXXFdyzLx2sSBOj4xwvJof9sGCPViXb92f48d6UbSSKiu/eqRgakqbboVWyOj2QwI/F7TComzRyDFe7kjHAxFDwJRM8VFZlng1YFmCedDgwrxPoh/ifFYsYCkQCZqmIPu0bTlTUP1aoluIaTwnx5H1+RTNivF3cpbsF09EuERHQuSxfcwUH9EcrpoxaNxSeCUQNvmxfNQnM7lnOuLdKr+Gv9dxT+P4Yrwmx+pHge1kszHFUWbLvhIFaYklX5LIaBTlCG3KICK7VnhRaRJeEPhZwvPCIdVPBV5oBAKYkcUCsagVMY1wSEc38hM/0uVQWBPa+iKhWjKUDiUj7D9XKVVKEaTESH+/RKVD7rk/gEc+8vKFF1+8cJ4rPuM+CvxDy8fnXnzkRfa3kb+8wR0gYeSmWbKF7K1PxWMcx8saAFtFQiNKMn8K2woi8TZmMROUGO4Cx/ZbOGSKbP2ILadwdNpIZow200hH2b5spIyktlKu8pYuSqkcWwKsmcz/2HobmFamqjsZESGhVjTTKTFqppLA970G21577VPNWfdycqFeSxRCl/uTl0NAnwH+mWfcy88cuXde1/ffAImeAWw+2/zkt+hr7vPfgD58oF6wUlS/nOzHB/7hnmfpUyA+RZ+95/DdkLj+fcioJE/ff8LxsUkfYu8o2UOuwCgyXz905aEr9kzsEAVxF8aTaVRu30CWbdCzzU0J2SpbreYlgV9aTXaYCdjuPTJgBrRkHWePHjkw22lYZr5fRg4cKVfL1R1gYNiseJ992CCBJzAlpj17lIo4IXMOzrAazuhRFl0LgIhas6LgSBz76gXYVzJYi9Qq1QEPjSOMODPqLFHaUCMw8eDwoetmGtpONxPrcn+i8qrK99dH46ao/xw/0D+c4PLjJ+EWX49WLd09KPEf6O+H3NzQHU47hv8ePWpnPx/i/3mH/afXzeyWy/28sHV0Zrinh5dlGRXzdVmwi35y+0zjz+puV1TezWGK02908IltA/30jPYoPb7bFgfOVraYKdV3moYhZ9XcH5htVhL6umKdunuwpyf2Izq8+Ncze45Ytf6xxtaRHi/Wr6zcz/1/ruTt/oyScfIrdX0ARCEHvNQe01iKgTm0iqnugGfn45scUZHZjJGRCctsNNBf2QcCMIeclofp9nqBsZ4b/8MPzNe18bGwU62UnWq2xFaH19b8pBDbXYqwKdjiCmVMNJPe4LFlQrbbkkui/xqra2iRUGs3CqdmstrN5XNDUO12v/qVqB5cfkELQ/Qr7ldzQ3U9yOXxTA9efhUPI+EAfSwQDgeWZwLhLvrY8sxxelOuCkPO8jk8ZNvEOLsbF9uyQ46mAza/yTu4fnhaw0TE3eudwtOtOOPOCTv4m8lVGGX+gRytL9xaRWt8GGncPQcoJ/w+prgvPP9LhJf417/JNqhbFJHg/dMEJwEGH07ieOnU+kc4ksSWiJFu7Pm77zz7hT/+H49c+J1PHj9WKcdkjEeCF28kjTLfzRVohZXAPuxivzmr9ZnXCNRGuNalUm3jNgYj9GicF5gRssBjRdH7Nd5wamEUktag9VUY+5ql9RFY67OxEqtL+B9phT+koxowaeDNjRTrkIgVa/Vaa8Z4crxbLWERJtlkr1/7wqz17Rlrzp5GbIpa+Dw+yj/FawFjMRNd2NmumwNJ2/ZDpDPXyxbYZQmoALbu03yYDXbG91011NtnJrpS/WJPFkATfbKk6sZIpX2+q1OOxgsBWcGM2r89oKhBvyIlujtLu8N7Ul29ml8RZR8XhGAoafUOhAPtmi/YjkAX1tMJ01LMlKmwjfNvJrZI/Pahg/5ArH1XLBl+n5los2OZnthg/7buQb8SSA8PjvdM9Y3smBwBCKqxuKyDJFOnN2pgys5z2kDSaG/rOtzdZ7WJU5mao5v+6NaB3r5gtre0Y7q971QkYEEg1tmtB9sS7QnH6qx06BGlM6pFdGjTkOl07Z8IB8KyEY8qQVG+MzfZ69SMXEpvC5vtoty2c8cbN115JNnZE1b86pGIHk47/RX428aNIH00noFwKGjpnY6a3JtIdZp2Iohgy4nKDU5j55UxJ19rS1QTbb29KbchCyIfD88UBtM5TRFsUUGFJL8UtXTgCpnSiKZGAmkrLAk790RCfj0s6+FoT79hD0b9hq4l+iXVNkPRpF8xzK5Ut8QLNk7+oBGaHPMFvPWZ99P/y13jfd9hs2/7YgFR4DmWY8DkRiYrSxFDsmXby2S3sB2brFG0ouwjOg/UEc5HmdtjKgFvuj8Pwr1wn3v53r5hUI8806fl3Du6eoaGI0efzuvdcF8XXXHP/bb753DzeXhkpM+yvn1t2zVZ94HOZul717adzMHNnS2+eC33fYzPLG+PkCLCIPG2RxG/RGA7Os13xp9wOBwJRwwD6YKEDCFUxkCF9JLU1gNuJRkBBx6Cbt79trvgfueXXoXCq6+6r7x6NTWh+SI41P2W23S/RcF58fxF+goMvkIv/vi558i/AYqGo0sAAAB4nGNgZGBgAGIjEe5H8fw2Xxm4mV8ARRiupOkEwej/j/9FsNqyFAG5HAxMIFEALCgLNQAAeJxjYGRgYA76n8XAwLb//+P/T1htGYAiKEAfAKHSBrx4nGN+wcDA/OL/B2YQLcjAwGQNpCP//wVhxlSQHESceQEDA4s+SA6KF0DUMln//w9SB1YLFQerj0TIg8VAuO3/TyYDoNovQPEIIBaC0kDMXADF/EB7mP4/ZtYFsi8D8VaoGyDu/M+2H6j+5v+fID4AdXQoYwAAAAAAZgCqAPQBgAIGAn4C4gNoBCwEhAUQBXYGAAaCBqoG0Ab4BxoHsAg8CIYJFgk+CWQKcAuCC9IMggygDMQM9A0mDVQNhA24DhoOig+IEHgQ0BFIEhASvBRSFKAU6AABAAAALwDtAAoAAAAAAAIAMABAAHMAAACkC3AAAAAAeJx1j19LAkEUxc+opSX0UNRbMC9FEqx/ICF7EQzt2cCeVx13V9adZXYUfO079NCX66vU2XWUCNphZn733HvP3AVwji8I7L4H7h0LVBjtuIQqHh2XqfcdV7ieHR+hjhfHx9RfHZ/iHm+O67jAOx1E5YTREh+OBWr4dlzCmag6LqMmLh1XyNeOj3AlbhwfU39yfIqJGDiu41Z8DnS6NVEQWnk3aMhOq92V063UlKLEj6W/tqE2mezLhU6simPtzfRKpcF8rIJ17Jsc8z1RJot0ItteKw9HKlHGt2qeu2WboGPtQi6MXsmh85Gp0Us1s15obdprNn/7YwCNFFsYRAgQwkLijmqDdwcttNElTVkhWbmripDAR0zFx5odYZHJGPe5F4wSqooVMdnDjOeKccreOcakgH0xu81B3d8TUu4VFS6S73ucYp8dkZKiwi9emB9my7BhRYeq5QT5FKZ4VWL4Zx5Jrzy3pDKj7hV/ban20OT6Z/4fO0p1nnicbZBbUxQxEIXnLHPbZRcVFO8igihqhL8Ukp6d1GaTVCfD4L83MxbFi/3Qp7+qrtOXYlH8i1Xx/7jBAgcoUaFGgxZLrHCINTY4wjM8xwsc4wQv8QqneI03eIt3eI8P+IhPOMNnnOMLLnCJr7jCN3zHNX7gJ35B4DducFu0gf2WKcaaSXnWtZJOkS17smE9JaEMK0t6bVznH6GcoLXG7QQ9pCqxjP2m81YTC2V9JP1IPpDL/XtyQ2X91rg6Zz+kVvvRCW24HsIkraUuTcWSzbafq4apy5v1lepJ7Q7nLGgf0p8yyntaRs+5L9s0czWE9axO7inD0RNMPavO5h3t5F2O0qQyWJl9kg9VkEOkOnlBTrdZYpKcms7zKPM/mEbj9MLvmozOuG2VD1S7+m7oOuJGeyUcjXUkyaovSZu0SPeb1A/7O8EyTats5tkiX50/RhUxey6Kv4VLi/oAAHicY/DewXAiKGIjI2Nf5AbGnRwMHAzJBRsZWJ02MTAyaIEYm7mYGDkgLD4GMIvNaRfTAaA0J5DN7rSLwQHCZmZw2ajC2BEYscGhI2Ijc4rLRjUQbxdHAwMji0NHckgESEkkEGzmYWLk0drB+L91A0vvRiYGFwAMdiP0AAA=') format('woff'), + url('data:application/octet-stream;base64,AAEAAAAPAIAAAwBwR1NVQiCMJXkAAAD8AAAAVE9TLzI/MkoJAAABUAAAAFZjbWFwWNnwWwAAAagAAAPmY3Z0IAkV/OAAADWcAAAAIGZwZ22KkZBZAAA1vAAAC3BnYXNwAAAAEAAANZQAAAAIZ2x5Ztu4sbcAAAWQAAAp0GhlYWQNC5xTAAAvYAAAADZoaGVhCHUGPQAAL5gAAAAkaG10eJU4/7wAAC+8AAAAvGxvY2HfHOpaAAAweAAAAGBtYXhwAYEMnwAAMNgAAAAgbmFtZXNY3j8AADD4AAACnXBvc3S5TV0AAAAzmAAAAftwcmVw5UErvAAAQSwAAACGAAEAAAAKADAAPgACbGF0bgAOREZMVAAaAAQAAAAAAAAAAQAAAAQAAAAAAAAAAQAAAAFsaWdhAAgAAAABAAAAAQAEAAQAAAABAAgAAQAGAAAAAQAAAAEDLQGQAAUAAAJ6ArwAAACMAnoCvAAAAeAAMQECAAACAAUDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFBmRWQAQOgA6C0DUv9qAFoEcgGoAAAAAQAAAAAAAAAAAAUAAAADAAAALAAAAAQAAAGuAAEAAAAAAKgAAwABAAAALAADAAoAAAGuAAQAfAAAAAQABAABAADoLf//AADoAP//AAAAAQAEAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwADQAOAA8AEAARABIAEwAUABUAFgAXABgAGQAaABsAHAAdAB4AHwAgACEAIgAjACQAJQAmACcAKAApACoAKwAsAC0ALgAAAQYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAACOAAAAAAAAAAuAADoAAAA6AAAAAABAADoAQAA6AEAAAACAADoAgAA6AIAAAADAADoAwAA6AMAAAAEAADoBAAA6AQAAAAFAADoBQAA6AUAAAAGAADoBgAA6AYAAAAHAADoBwAA6AcAAAAIAADoCAAA6AgAAAAJAADoCQAA6AkAAAAKAADoCgAA6AoAAAALAADoCwAA6AsAAAAMAADoDAAA6AwAAAANAADoDQAA6A0AAAAOAADoDgAA6A4AAAAPAADoDwAA6A8AAAAQAADoEAAA6BAAAAARAADoEQAA6BEAAAASAADoEgAA6BIAAAATAADoEwAA6BMAAAAUAADoFAAA6BQAAAAVAADoFQAA6BUAAAAWAADoFgAA6BYAAAAXAADoFwAA6BcAAAAYAADoGAAA6BgAAAAZAADoGQAA6BkAAAAaAADoGgAA6BoAAAAbAADoGwAA6BsAAAAcAADoHAAA6BwAAAAdAADoHQAA6B0AAAAeAADoHgAA6B4AAAAfAADoHwAA6B8AAAAgAADoIAAA6CAAAAAhAADoIQAA6CEAAAAiAADoIgAA6CIAAAAjAADoIwAA6CMAAAAkAADoJAAA6CQAAAAlAADoJQAA6CUAAAAmAADoJgAA6CYAAAAnAADoJwAA6CcAAAAoAADoKAAA6CgAAAApAADoKQAA6CkAAAAqAADoKgAA6CoAAAArAADoKwAA6CsAAAAsAADoLAAA6CwAAAAtAADoLQAA6C0AAAAuAAAAAf/w/38D6wNFADkAD0AMLAEARQAAAGYTAQUVKyUGBwYmJyYnJicmNzY/ATY3Nh4CBwYHBgcGFxYXFhcWNjc+ASc0JyYnLgEHNTYXFhcWFxYXFgYHBgNXRV9ax1peRF0lIxoaVRAKCRtCLggOBwlFGhkWF0NKaWLGQzU5ASApU1DNZXV3dVxgLyMCAjg3EAlFIyEGJSdEXX97fYBjEwoFEQcuPhsNCUpgXlteQ0oUEkVNPZhQUkxhQD0iIgEpExNGSXBSWVemRRYAAAAAAQAA//kD6ALDAB8AJEAhGQgCAAMBRwACAwJvAAMAA28AAAEAbwABAWYVNTUkBAUYKwERFAcGIyIvARUUBiMhIiY1ETQ2MyEyFh0BNzYzMhcWA+gWBwcPCuFeQv53Q15eQwGJQl7hCg8HBxYCjv2gFwkDCuFcQ15eQwGIQ15eQ1zhCgIKAAAAAAEAAP/vAtQChgAkAB5AGyIZEAcEAAIBRwMBAgACbwEBAABmFBwUFAQFGCslFA8BBiIvAQcGIi8BJjQ/AScmND8BNjIfATc2Mh8BFhQPARcWAtQPTBAsEKSkECwQTBAQpKQQEEwQLBCkpBAsEEwPD6SkD3AWEEwPD6WlDw9MECwQpKQQLBBMEBCkpBAQTA8uD6SkDwACAAD/+QI5AsMADwA7AGu1AAEAAQFHS7APUFhAJgAEAwIDBGUAAgEDAgFrAAUAAwQFA2AAAQAAAVQAAQEAWAAAAQBMG0AnAAQDAgMEAm0AAgEDAgFrAAUAAwQFA2AAAQAAAVQAAQEAWAAAAQBMWUAJJxQrHiYkBgUaKyUVFAYHIyImPQE0NhczMhYTFA4DBw4BFRQGByMiJj0BNDY3PgE0JiciBwYHBiMiLwEuATc2MzIeAgGJDgiGCQ4OCYYJDLEQGCYaFRceDgmGCAxKKiEcNCIkGBQoBwoHB1sIAgRZqi1aSC6VhgkMAQ4IhgkOAQwBRR40IiASCg0wDQoQARYJGi5SExAgMiIBEA4yCQRGBhAIlCI6VgAAA//9/7EDXwMLAA8ANwBEAEhARSkBBQMJAQIBAAJHAAQCAwIEA20AAwUCAwVrAAcAAgQHAmAABQAAAQUAYAABBgYBVAABAQZYAAYBBkwVHisTFiYmIwgFHCslNTQmKwEiBh0BFBY7ATI2EzQuASMiBwYfARYzMjc+ATIWFRQGBw4BFxUUFjsBMjY0Nj8BPgMXFA4BIi4CPgEyHgEB9AoIawgKCghrCAqPPlwxiEcJDUoEBgkFHiU4KhYbIzwBCghrCAoYEhwKHhQM13LG6MhuBnq89Lp+UmsICgoIawgKCgF/MVQudw0LNwQHJhseEhUaDA9CJRQICgoSIgsQBhocKFJ1xHR0xOrEdHTEAAP//f+xA18DCwAeAC4AOwBJQEYoIAIGBQ4GAgIBGAECBAADRwAIAAUGCAVgAAYAAQIGAWAAAgMBAAQCAGAABAcHBFQABAQHWAAHBAdMFRYmJiYRJiMjCQUdKyU1NCYrARE0JisBIgYdARQWOwEVIyIGHQEUFjsBMjYDNTQmKwEiBh0BFBY7ATI2BRQOASIuAj4BMh4BAjsKBzYKCLIICgoINTUICgoI+gcKRwoIawgKCghrCAoBZXLG6MhuBnq89Lp+UlkICgEeCAoKCFkICrMKCFkICgoB/FkICgoIWQgKCuB1xHR0xOrEdHTEAAAAAAIAAP/5AWYDCwAeAC4AP0A8HwEFBhoSAgIDCAACAAEDRwAGAAUDBgVgAAMAAgEDAmAEAQEAAAFUBAEBAQBYAAABAEw1JiMmIRYzBwUbKyUVFAYHISImJzU0NjczNSMiJic1NDY3MzIWFxEzMhYDFRQGByMiJj0BNDY7ATIWAWUUEP7jDxQBFg4jIw8UARYO1g8UASMPFkgWDo8OFhYOjw8UZEcPFAEWDkcPFAHWFg5HDxQBFg7+vxYCdWsPFAEWDmsOFhYAAAAAAgAA//kD6ANSACcAPwBMQEkoAQEGEQECATcuAgQCIQEFBARHAAYBBm8ABAIFAgQFbQAFAwIFA2sAAQACBAECYAADAAADVAADAwBYAAADAEw6GyU1NiUzBwUbKwEVFAYjISImNRE0NjchMhYdARQGIyEiBgcRFBYXITI2PQE0NjsBMhYTERQOAS8BAQYiLwEmNDcBJyY0NjMhMhYDEl5D/jBDXl5DAYkHCgoH/nclNAE2JAHQJTQKCCQICtYWHAti/pQFEARABgYBbGILFg4BHQ8UAUyyQ15eQwHQQl4BCggkCAo0Jf4wJTQBNiSyCAoKAdr+4w8UAgxi/pQGBkAFDgYBbGILHBYWAAAAAAYAAP+xAxIDCwAPAB8ALwA7AEMAZwBkQGFXRQIGCCkhGREJAQYAAQJHBQMCAQYABgEAbQQCAgAHBgAHawAOAAkIDglgDw0CCAwKAgYBCAZeAAcLCwdUAAcHC1gACwcLTGVkYV5bWVNST0xJR0E/FCQUJiYmJiYjEAUdKwERFAYrASImNRE0NjsBMhYXERQGKwEiJjURNDY7ATIWFxEUBisBIiY1ETQ2OwEyFhMRIREUHgEzITI+AQEzJyYnIwYHBRUUBisBERQGIyEiJicRIyImPQE0NjsBNz4BNzMyFh8BMzIWAR4KCCQICgoIJAgKjwoIJAgKCggkCAqOCgckCAoKCCQHCkj+DAgIAgHQAggI/on6GwQFsQYEAesKCDY0Jf4wJTQBNQgKCgisJwksFrIXKgknrQgKAbf+vwgKCggBQQgKCgj+vwgKCggBQQgKCgj+vwgKCggBQQgKCv5kAhH97wwUCgoUAmVBBQEBBVMkCAr97y5EQi4CEwoIJAgKXRUcAR4UXQoAAgAA//kDoQMLABcALAAsQCkABAABBQQBYAAFAAACBQBgAAIDAwJUAAICA1gAAwIDTCM1NTU1MwYFGislETQmByEiJic1NCYHIyIGFREUFjMhMjYTERQGIyEiJjURNDY7ATIWHQEhMhYDWR4X/ncXHgEeF7MWICAWAqcWIEdKM/1ZM0pKM7MzSgF3M0p2AYkWIAEgFiQWIAEeF/3oFiAgAZ/+dzNKSjMCGDNKSjMSSgADAAD/+QQpAwsAEQAnAEUASkBHJAEBAAFHAAYABAcGBGAABwADAgcDYAgJAgIAAAECAGAAAQUFAVQAAQEFWAAFAQVMExJCQD07ODUwLSEeGRYSJxMnNjEKBRYrATQjISIGDwEGFRQzITI2PwE2JSE1NCYHISImJzU0JgcjIgYVETc+AQUUDwEOASMhIiY1ETQ2OwEyFh0BITIWFxUzMhYXFgPiHv2hFjQNpAseAl8XMg+kCv2DAa0gFv6/Fx4BHhezFiCPGVAC6hmlGFIl/aEzSkozszNKAS80SAFrHjQLCAFLExgRyw0JFBoQywxkWhYgASAWJBYgAR4X/iSvHiZaIyDLHiZKMwIYM0pKMxJKM1oaGxEAAAAAAwAA//kDWgLEAA8AHwAvADdANCgBBAUIAAIAAQJHAAUABAMFBGAAAwACAQMCYAABAAABVAABAQBYAAABAEwmNSY1JjMGBRorJRUUBgchIiYnNTQ2NyEyFgMVFAYnISImJzU0NhchMhYDFRQGIyEiJic1NDYXITIWA1kUEPzvDxQBFg4DEQ8WARQQ/O8PFAEWDgMRDxYBFBD87w8UARYOAxEPFmRHDxQBFg5HDxQBFgEQSA4WARQPSA4WARQBDkcOFhYORw8WARQAAAAAAgAA//kDWQLEABgAQABQQE0MAQECAUchAQABRgADBwYHAwZtAAIGAQYCAW0AAQUGAQVrAAAFBAUABG0ABwAGAgcGYAAFAAQFVAAFBQRYAAQFBEwsJSonExYjFAgFHCsBFAcBBiImPQEjIiYnNTQ2NzM1NDYWFwEWNxEUBisBIiY3JyY/AT4BFzMyNicRNCYHIyI0JjYvASY/AT4BFzMyFgKVC/7RCx4U+g8UARYO+hQeCwEvC8ReQ7IHDAEBAQECAQgIsiU2ATQmtAYKAgIBAQECAQgIskNeAV4OC/7QChQPoRYO1g8UAaEOFgIJ/tAKtf54Q14KCAsJBg0HCAE2JAGIJTYBBAIIBAsJBg0HCAFeAAAAAgAA//kDawLDACcAQABCQD8UAQIBAUcABgIFAgYFbQAFAwIFA2sABAMAAwQAbQABAAIGAQJgAAMEAANUAAMDAFgAAAMATBYjGSUqJScHBRsrJRQWDwEOAQcjIiY1ETQ2OwEyFhUXFg8BDgEnIyIGBxEUFhczMh4CARQHAQYiJj0BIyImPQE0NjczNTQ2FhcBFgFlAgECAQgIskNeXkOyCAoBAQECAQgIsiU0ATYktAYCBgICBgv+0QscFvoOFhYO+hYcCwEvCy4CEgUOCQQBXkMBiENeCggLCQYNBwgBNCb+eCU0AQQCCAEsDgv+0AoUD6EWDtYPFAGhDhYCCf7QCgAAAAABAAAAAAI8Ae0ADgAXQBQAAQABAUcAAQABbwAAAGY1FAIFFisBFA8BBiIvASY0NjMhMhYCOwr6CxwL+gsWDgH0DhYByQ4L+gsL+gscFhYAAAH//wAAAjsByQAOABFADgABAAFvAAAAZhUyAgUWKyUUBichIi4BPwE2Mh8BFgI7FA/+DA8UAgz6Ch4K+gqrDhYBFB4L+goK+gsAAAABAAAAAAFnAnwADQAXQBQAAQABAUcAAQABbwAAAGYXEwIFFisBERQGIi8BJjQ/ATYyFgFlFCAJ+goK+gscGAJY/gwOFgv6CxwL+gsWAAAAAAEAAAAAAUECfQAOAAq3AAAAZhQBBRUrARQPAQYiJjURND4BHwEWAUEK+gscFhYcC/oKAV4OC/oLFg4B9A8UAgz6CgAAAgAA/7EDWwMLACQARwBdQFpDJQIGCS8BBQYXAQMCCAEBAwRHAAkIBggJBm0HAQUGAgYFAm0EAQIDBgIDawABAwADAQBtAAgABgUIBmAAAwEAA1QAAwMAWAAAAwBMRkUmJSU2JSY1FCQKBR0rARQVDgEjIiYnBwYiJj0BNDY7ATIWBg8BHgE3MjY3Njc2OwEyFhMVFAYrASImNj8BJiMiBgcGBwYrASImNzU+ATMyFhc3NjIWA0sk5JlRmDxICxwWFg76DhYCCU0oZDdKgicGGAQMawgKDhQQ+g4WAglNUnBLgicGFwUMbwcMASTmmVGaPEgLHBgBBQMBlro+OUgLFg76DhYWHAtNJCoBSj4KOA0MAbj6DhYWHAtNTUo+CjgNDAYElro+OUgLFgAAAgAA//kDoAMLAC0AQgBOQEs7AQQGJQEFBAJHAAcBAgEHAm0ABgIEAgYEbQAEBQIEBWsABQMCBQNrAAEAAgYBAmAAAwAAA1QAAwMAWAAAAwBMFBcVJzU5NTMIBRwrARUUBiMhIiY1ETQ2NyEyFx4BDwEGIycmIyEiBgcRFBYXITI2PQE0PwE2MzIXFhMBBiIvASY0PwE2Mh8BATYyHwEWFAMSXkP+MENeXkMB0CMeCQMHGwYHBQ0M/jAlNAE2JAHQJTQFJAYHAwQLgf45DSQO8A4OPQ4kDpMBaQ0kDj4NAUuxQ15eQwHQQl4BDgQTBhwFAQM0Jf4wJTQBNiSNCAUjBgIEAQX+Og4O8A0kDj4NDZMBaQ0NPQ4kAAIAAP/5AxMDCwAPAB8AK0AoAAMEAQABAwBgAAECAgFUAAEBAlgAAgECTAIAHhsWEwoHAA8CDwUFFCsBISIGBxEUFhchMjY1ETQmFxEUBiMhIiY1ETQ2NyEyFgJx/jAlNAE2JAHQJTQ0fF5D/jBDXl5DAdBCYALDNCX+MCU0ATYkAdAlNFn+MENeXkMB0EJeAWAAAAAEAAD/sQNZAwsAAwAhADEARQBRQE4rKiMiBAgEAUcNAQQGAQgCRgAKBwEECAoEYAAIAAMGCANgAAYAAQAGAV4FAgIACQkAUgUCAgAACVgACQAJTEA9ODUXJjMREzsRERALBR0rFyE1IQUzETQmLwEuAQcVFAYjISImJzUjETM1NDYzITIWBwM1NCYrASIGFxUUFjczMjYFERQGIyEiJicRNDYzITIWHwEeAdYBrf5TAfRIDAWdBRwIHhf+vhYeAUhIIBUB0RYgAdYKCGsHDAEKCGsHDAFkHhf9EhceASAWAgUXNg+cEBYH1tYB9AgaB5wGDAHoFiAgFuj9NugWICAWAR6yCAoKCLIHDAEKCv36FiAgFgLuFiAYDp0PNgAAAAABAAD/1QI8ARcADgAXQBQAAQABAUcAAQABbwAAAGYmFAIFFislFA8BBiIvASY0NjchMhYCOwr6CxwL+gsWDgH0DhbzDwr6Cwv6Ch4UARYAAAH//wAAAjsC5wAOABFADgABAAFvAAAAZhUyAgUWKwEUBiMhIi4BPwE2Mh8BFgI7FA/+DA8UAgz6Ch4K+goByQ4WFhwL+gsL+goAAAAEAAD/agOfA1IACgAiAD4ATgExQA8XAQADNCwCBggmAQEJA0dLsBNQWEBKEQEDAANvAAcGAgYHZQQBAgoGAgprEwEKCQkKYwAAAA0MAA1eFBIQDgQMDwELCAwLXgAIAAYHCAZeAAkBAQlUAAkJAVkFAQEJAU0bS7AUUFhASxEBAwADbwAHBgIGB2UEAQIKBgIKaxMBCgkGCglrAAAADQwADV4UEhAOBAwPAQsIDAteAAgABgcIBl4ACQEBCVQACQkBWQUBAQkBTRtATBEBAwADbwAHBgIGBwJtBAECCgYCCmsTAQoJBgoJawAAAA0MAA1eFBIQDgQMDwELCAwLXgAIAAYHCAZeAAkBAQlUAAkJAVkFAQEJAU1ZWUAoPz8jIz9OP05NTEtKSUhHRkVEQ0JBQCM+Iz49OxERGRQUIyQeEBUFHSsBMy8BJjUjDwEGBwEUDwEGIi8BJjY7ARE0NjsBMhYVETMyFgUVITUTNj8BNSMGKwEVIzUhFQMGDwEVNzY7ATUTFSM1MycjBzMVIzUzEzMTApliKAYCAgECAgP+2gayBQ4GswgIDWsKCGsICmsICgHS/rrOBwUGCAYKgkMBPc4ECAYIBQuLdaEqGogaKqAngFuAAm56GgkCCwoKBv1GBgeyBQWzCRUDAAgKCgj9AApKgjIBJwsFBQECQIAy/tgECgcBAQJCAfU8PFBQPDwBcf6PAAAAAAQAAP9qA58DUgAKACIAMgBNAUNADEY+FwMOAzYBDRECR0uwE1BYQFEADw4SDg9lFAESERESYwALDQINCwJtBAECAA0CAGsQAQMADg8DDl4AEQANCxENXwAAAAcGAAdeEwwKCAQGAQEGUhMMCggEBgYBVgkFAgEGAUobS7AUUFhAUgAPDhIOD2UUARIRDhIRawALDQINCwJtBAECAA0CAGsQAQMADg8DDl4AEQANCxENXwAAAAcGAAdeEwwKCAQGAQEGUhMMCggEBgYBVgkFAgEGAUobQFMADw4SDg8SbRQBEhEOEhFrAAsNAg0LAm0EAQIADQIAaxABAwAODwMOXgARAA0LEQ1fAAAABwYAB14TDAoIBAYBAQZSEwwKCAQGBgFWCQUCAQYBSllZQCgzMyMjM00zTUxJRURDQkFANTQjMiMyMTAvLi0sERERFBQjJB4QFQUdKyUzLwEmNSMPAQYHBRQPAQYiLwEmNjsBETQ2OwEyFhURMzIWBRUjNTMnIwczFSM1MxMzEwMVITUTNj8BNSIGJwYrARUjNSEVAw8BFTczNQKZYigGAgIBAgID/toGsgUOBrMICA1rCghrCAprCAoCBKEqGogaKqAngFuAC/66zgcFBgEEAwYKgkMBPc4MBgibM3oaCQILCgkHfwYHsgUFswkVAwAICgoI/QAKkTs7UFA7OwFy/o4Cg4MzAScKBQUCAgECQIAy/tkPBQICQwAAA//5/5YDkwMwABQAHAApAAq3JiAZFhMJAy0rAR4BDwEOAScBBi4CNwEmNj8BNhYBFjYnJg4CAR4CNi4EBh4BAyc+LhyGEFwy/mgSTkgaEgGYBhQQiBiI/n4gXiAOMCgGAV4eTDAGDCg8SC4ICigCwj6IGIYQFAb+aBIYSkwSAZgyXBCIHDD+KiBcJA4IKC4BGh4oCgguSjwoDAgwTAAAAAMAAP9qAjADUgAbACgAYgBJQEY1MgICAzYBBAJYTQIABgNHAAUEBgQFBm0ABgAEBgBrAAAAbgABAAMCAQNgAAIEBAJUAAICBFgABAIETFNSGhskJx0aBwUaKwEUDgEUHgEdARQGIiY9ATQ+ATQuAT0BNDYyFhUFBwYXFjMyNzYnJiMiEzQ+Aj8BNjU3BiInFxQfAxYmFiMUDgIPAgYmBjUGHQE+AjU0MhUUHgEXNTQvAiYvAS4BAjBgYmJgrNisYGJiYK7Urv4eEgQIXHyEWA4eYGp4kAgcDBkdXAJk9GQEWi0TEREMHgwCCgYIDA8PAiJaCHRENEJ6BlwrEg0FDAcEAm4saF48XGYudiJOTiJ2LmZcPF5oLHYgTk4gBg4IBjQyChQ2/koSHiQOGBxcHjI2NjIgWisTFRUCMAoSEg4KDxAQAiIBWiBCBCYwIh4eIjAmBEIeXCkTDggUDBYAAAABAAAAAAH0ApIACwAGswoFAS0rARYUBwEGJjURNDYXAeYODv5UGCIiGAF4Ch4K/vYQFB4CAh4UEAAAAAABAAAAAAJYAooADAAYQBUCAQABAG8AAQFmAQAHBAAMAQsDBRQrATIVERQjISI1ETQ2MwIOSkr+PkwkKAKKQP4qQkIB1iQcAAACAAAAAAISArwACAARACNAIAUCBAMAAQBvAwEBAWYKCQEADg0JEQoRBQQACAEIBgUUKwEyFREUIjURNCEyFREUIjURNAG4WrT+/Fq0ArxA/cZCQgI6QED9xkJCAjpAAAACAAAAAAJYAoIACwAUABhAFQIBAAEAbwABAWYNDBEQDBQNFAMFFCsBFhQHBQYmNRE0NhclMhURFCI1ETQBnA4O/pYWHBwWAdxKlgF2ChoK5A4SGgG6GhIOKDr+Ljo6AdI6AAAAAgAAAAACWAKCAAwAFAARQA4AAAEAbwABAWYTHgIFFisTNDclNhYVERQGJyUmJzQyFREUIjWuDgFsFBwcFP6UDq6WlgFeDgrkDhIa/kYaEg7kCvY6Ov4uOjoAAAACAAAAAANwAnwACwAXAAi1FhEKBQItKwEWFAcFBiY1ETQ2FwcWFAcFBiY1ETQ2FwNiDg7+jBYeHhZSDg7+mBQgIBQBdgocCPgOEBwB4hwQDvgKHAj4DhAcAeIcEA4AAAACAAAAAANwAnwADAAZAAi1FhEJBAItKxE0NyU2FhURFAYnJSYlNDclNhYVERQGJyUmDgF2FCAgFP6KDgHGDgFoFCAgFP6YDgFeDgr4DhAc/h4cEA74CA4OCvgOEBz+HhwQDvgIAAAAAAIAAP/XAyUC5QATACYAOUA2JAoCAAMBRwACAQJvBAEAAwBwAAEDAwFUAAEBA1gFAQMBA0wVFAEAFCYVJg8NCAcAEwETBgUUKwUiLwEmNDc2Mh8BEz4BMzIWBwEGASIGFh8BFjY3ATYmJyYGBwMnJgFtQi3QLi4shCw/oBRKKlhcLP78K/7SFSABENASNAwBBAsOERMoC+OgDykt0S6BLiwsPgEfJiyYUf4rUAGhICkQ0RMIFgHVFygICgwS/migDwAAAAAE/+P/lgQeAyYADAAZAB4AKQBMQEkiAQQGAUcABgAEAAYEbQgBAgcBAAYCAGAABAAFAQQFYAABAwMBVAABAQNYAAMBA0wODQEAKCceHRwbFRINGQ4ZCAUADAEMCQUUKwEiBwEGFjMhMjYnASYnMhcBFgYjISImNwE2EzQyFCITFA8BJyY1ND4BFgICMSD+zCAqQgJxQSwi/s0hL2o/ATQ/Z339j3trQAE1PieIiJIGR0kGLkIsAr03/f83UFA3AgE3aWv9/2m7uWsCAWv9dEWIAXwOD7OzDw4gLgIyAAAAAAoAAP/IAy0C9QAUACkAOQBCAEsAVABdAGYAbwB4AJNAkBUBAAADBwADYAAHAAgFBwhgCQEFAAoGBQpgEwELFAEMBAsMYAAGFwEEDQYEYAANAA4SDQ5gABEAEg8REmAADwAQAg8QYBYBAgEBAlQWAQICAVgAAQIBTCwqFhUBAHd2c3JubWppZWRhYFxbWFdTUk9OSklGRUFAPTw2NDIxKjksOSAfFSkWKQsKABQBFBgFFCsBMhcWFxYUBwYHBiInJicmNDc2NzYTMjc2NzY0JyYnJiIHBgcGFBcWFxYTIyIvASY+Ah8BMzIWDgEDNDYyFhQGIiYXNDYyFhQGIiYXNDYyFhQGIiYHNDYyFhQGIiYHNDYyFhQGIiYnNDYyFhQGIiYnNDYyFhQGIiYBlm5fXDY4ODZcX91eXDY3NzZcXm9WSkgqKysqSEqsSkgqKysqSErOfxUMjw4EGiMOgmwWFwIXpQ8SDw4UDqcOEg8OEw5JDxIPDhQOQg4UDg8SD68OFA4PEg+iDhIPDhQNSw4SDw4UDQL1ODVcX91eXDY4ODZcXt1fXDU4/S0sKkhKrEpHKisrKkdKrEpIKiwBDA+cDyIYAg6OGyQbAR8KDg4UDg84Cg4OFA4PogkPDxIPDp4KDg4TDg4/CQ8PEg8OSwkPDxIPDrkJDw8SDw4AAAADAAD/agPTA1IANQBmAI0AN0A0eQECA1Q2AgAEHwACAQADRwADAgNvAAIEAm8ABAAEbwAAAQBvAAEBZoeGbWw7OiwrFAUFFSs1PgI3Mh4BFxYXFj4BMzc2PwE2NzYeAR8BHgIXFhcOAgcOAQcOAQ8BBiInJSYvAi4CET4CNzIWHwIWFxY2PwE2Nz4CNzYeATMeAxcOAgcFDgMnJicuAycmET4CNyUyHgEfARYXHgIXFhcOAg8BBg8BBg8BBiYjJScuAScmCyo4DBMeJAcv1RMiLAJNOR4qJhYNHhAPEgMaCgYDAQoqPAorqiwHHAkaERQU/vgGGjM2HSIJCyo6DBMeFBl/VSoTJBUZRFwLKiITECAqAgUWDgcBCipACf7+ByYULA7WLgZMPj4DBAosPAsBXB4wQAh1TicEQioGAwEJIjQJjF0uFA4JGRAWEf8APztWBQRYDxYSBggWAhViBAgcIxoNFRMFAgYICQsCCAgHBAoNFhYFFFQTAxIECwcCewMLFhgNFgkBFQ8UFAUICw46JxQFCgwOICgFGA4EAwgaAwYKCwkOFhgEfAMWCAwGZRUDIBwgBgQBFQ8YFAaiDiYDNiQTAhoWCQQJDRIUBEIsFwsIBAsHAnccGigKBAAAAAACAAD/agO1A1IADAAYAGJAXwEBAwIBRwADAgECAwFtAAEHAgEHawAHBgIHBmsAAAACAwACXggBBg0LAgkEBgleAAQFBQRSAAQEBVYKDAIFBAVKDQ0AAA0YDRgXFhUUExIREA8OAAwADBERERESDgUZKxURNyERIxEhFSMRIRUnNTM1MxUzFSMVIzW8AgdW/o+mAaKD0aDPz6CWAzK2/qQBBJz9ZFjPos/Pos/PAAAAAAQAAP9qA+gDUwASABwAJQAxAEtASBoYAwMECA4BAQQCRwAIBwQHCARtAAAABQYABWAABgAHCAYHYAAEAAEDBAFgAAMCAgNUAAMDAlgAAgMCTBMhJBMZFBMjFwkFHSsVNDcBJjU0NgQWEAYHIicBBiImNxQWNj8BJicHBgEUFiQ2ECYkBhc0NjcyFCMiBhcUIiEBBCvaATra2p1eUv78IVxANyAuEfwtIfwRAQK2AQS2tv78tl2CWRAQTm4BICkvIQEEUl6a3gLa/sbYASv+/CFALhYiAhD8IS38EQHsgbgCtAEGtAK4gVqAASBsTxAAAAcAAP9qA+4DUgAeACsAOQA/AEkAUQBgAFlAVldWUUlFPQYFBkQBBAVMAQMETS8lAAQCAwRHAAYHBQcGBW0ABQQHBQRrAAAABwYAB2AABAADAgQDYAACAQECVAACAgFYAAECAUxfXVNSHRMWFCwtCAUaKxU0NjQ2PQETNjcBNTc2MzIXHgEHAQYHBQcGIgYjIiY3FBYzMj8BNicmDwEGNx4BFz8BNiYnLgEHBgc3FhcBJgcDFhcWFwEmJyYnAxYXFTc1Ni8BMhcWFxU3NicmJyYjIgcCAkoKFQFFmDxWalBKDkH+JBgf/vkKBAoKBC1APxoUBhBzBC8tPCADLENmAXQLKQ42M4AwBwRjLS0BJ1g4eiYbFRQBKRAXHiWvEQTyPR7BalBGCDQtBAU5P1A8KSkECAgIAgIBCx8WAUQCmjtQSsJA/h8XCEYDAQJALRMcBCA6Ly0Cdw6kAmRGHgYviDUxFCIKC28CEgEnFjf+6xQZFiEBKx8YHRD+VCkpGPUCPGDTUEldFjctQko5PikAAAAE////iQPpAzMAHwAvAD8AQwCLQBAvAQYFJwEEBxsYDgMCAQNHS7AKUFhALwACAQECZAAAAAUGAAVgAAYACQgGCV4ACAAHBAgHYAAEAQEEVAAEBAFYAwEBBAFMG0AuAAIBAnAAAAAFBgAFYAAGAAkIBgleAAgABwQIB2AABAEBBFQABAQBWAMBAQQBTFlADkNCEiY2NTQmNiUzCgUdKzURNDY3ITIWBxEUBgchFRcWFRQGIyEiJjc0PwE1ISImNxQWFyEyNicRNCYnISIGFxMRNDYzITIWFREUBgchIiY3IREhNigDLCc4ATYo/sjDFxAP/c4OEgEXw/7IJzhAEA8DLA4SARAP/NQOEgE+Eg0CsA0SEg39UA0SHwKw/VBkAnEnNgE4Jv2PJzYBJRkGGg0SEg0aBhklOCYOEAESDQJxDhABEg3+DAG1DhISDv5LDhABEg0BtQAAAAMAAP5YBT0EcgBbAI0A7ABfQFx1NgIBAn0BBgGBUwIDBaMBBAPOxoUABAcE4d0CAAcGRwACAQJvAAEGAW8ABgUGbwAEAwcDBAdtAAUAAwQFA2AABwcAWAAAAA0ASeXiuLerqaKgm5pkYjU0GAgFFSsFDgEHDgEHDgImJy4BJy4CNS4BJy4BJyY3Njc2NzYnFicmJyYnJj4BNz4DNzY3Njc2MzcuAScmNzY3Njc2Nz4CFxYXHgEHBhcWHwEWFxYXBwYHDgQTJjcSJy4BIw4BBwYHBgcGBw4BFxYXFhcWFwYmJyYnJjMXFhcWBxYXFhU2PwE2NzYnJgEOATc2Nz4BNzYnJiciBw4BBwYnJicWNzY3PgE3Njc2JyYnJgcGBw4BBw4BBwYXFhcWFxYVBgcGBxQWFx4BFxYXFhcWFxYXFhcWNjc2NzYnBicmJzY3MhcWNz4BJicmBLQEDg0TYCQXXEEbEBQvIR4eDAEVHScqBgIEAggHAQIFAR4QCw4LEAIiHRpNWzgqKxQgHyItBiklAQEOBgsIBwoQEz41G1kfHQgXGi4NCAkEBQYMOw0JCg8MCQcgKB0zRhJJIh8qDgwJBggLAw8BDxEhFiovEg0bDgsPGwEEUhIQIyAUFgkUIhQJCgoI/t0gMQcEOzhUDA0YG0QYIRJPFCAZHhgkKRgwLTooMAwJDSM8MEMpSCs+PUc+AQEPChgaCBABBwgCJioXEwQEAgQDDi8hExsZH1ooKxYZBkgkNyYQFAwXOS8qKw8lKjM9TBsrbRUNFgENGB0oEA8ZIBsgJhYdNRwQFQkdFw4VEAEZDgoODh9ORRINEggTGhcJDwYIfCdHKiY3EyciEBkSFBsGCBlBPehxV10hHSkSCQwKXRUQEiMmLTUB2UpwAQeKGiQBEhEPFhAdJgohSyAiHRQeIA8CAwQDBgluJkpBVxgmLDcZIDYgGSoqIv5KCAUGBBoSUC4wIycOCQUeBgkBAQ8HDAcXFhABAy4kMz4OChUNIxYSBwVBSRURDBASCBASFyktEx4wFwwTEA4gLQcKHhQRFyEMCRMUHyIoBwQFHgQBAQ8TEUdCCw0AA//5/1UC3wNoAAAABgAeACRAIRgNBgUEAwIHAQABRwIBAAEAbwABAWYIBxUTBx4IHgMFFCsBMQEFAwElEzIWFxQPARceAQcBBiMiJj8BJy4BNwE2Ae/+eQEFggGG/vyCKzwBCl22Kw4n/nofKTg8FV+1LBAoAYYfAv/+j5f+xwFylgGiPisWFuBpGWgl/o4dXjPkaRlmJwFyHQAAAwAA/2kD6gNTAAgAEQAVADJALwAAAAMEAANgAAQGAQUCBAVeAAIBAQJUAAICAVgAAQIBTBISEhUSFRMTFBMSBwUZKxE0AAQAAgAEADcUFiQ2ECYkBhc1IRUBJgGcASgE/uD+XP7ihdQBLtTU/tLUYQIUAV7PASYC/t7+Xv7eAgEmz5bWAtIBMNIC1vjExAAAAQAAAAEAADIUC+JfDzz1AAsD6AAAAADUZixSAAAAANRmLFL/4/5YBT0EcgAAAAgAAgAAAAAAAAABAAADUv9qAAAGv//j/+QFPQABAAAAAAAAAAAAAAAAAAAALwPoAAAD6P/wA+gAAAMRAAACOwAAA1n//QNZ//0BZQAAA+gAAAMRAAADoAAABC8AAANZAAADWQAAA6AAAAI7AAACO///AWUAAAFlAAADWQAAA6AAAAMRAAADWQAAAjsAAAI7//8DoAAAA6AAAAOG//kCMAAAAfQAAAJYAAACEgAAAlgAAAJYAAADcAAAA3AAAAMPAAAEAv/jAy0AAAPTAAADtQAAA+gAAAPoAAAD6P//Br8AAALZ//kD6AAAAAAAAABmAKoA9AGAAgYCfgLiA2gELASEBRAFdgYABoIGqgbQBvgHGgewCDwIhgkWCT4JZApwC4IL0gyCDKAMxAz0DSYNVA2EDbgOGg6KD4gQeBDQEUgSEBK8FFIUoBToAAEAAAAvAO0ACgAAAAAAAgAwAEAAcwAAAKQLcAAAAAAAAAASAN4AAQAAAAAAAAA1AAAAAQAAAAAAAQAEADUAAQAAAAAAAgAHADkAAQAAAAAAAwAEAEAAAQAAAAAABAAEAEQAAQAAAAAABQALAEgAAQAAAAAABgAEAFMAAQAAAAAACgArAFcAAQAAAAAACwATAIIAAwABBAkAAABqAJUAAwABBAkAAQAIAP8AAwABBAkAAgAOAQcAAwABBAkAAwAIARUAAwABBAkABAAIAR0AAwABBAkABQAWASUAAwABBAkABgAIATsAAwABBAkACgBWAUMAAwABBAkACwAmAZlDb3B5cmlnaHQgKEMpIDIwMTYgYnkgb3JpZ2luYWwgYXV0aG9ycyBAIGZvbnRlbGxvLmNvbWVwZ2RSZWd1bGFyZXBnZGVwZ2RWZXJzaW9uIDEuMGVwZ2RHZW5lcmF0ZWQgYnkgc3ZnMnR0ZiBmcm9tIEZvbnRlbGxvIHByb2plY3QuaHR0cDovL2ZvbnRlbGxvLmNvbQBDAG8AcAB5AHIAaQBnAGgAdAAgACgAQwApACAAMgAwADEANgAgAGIAeQAgAG8AcgBpAGcAaQBuAGEAbAAgAGEAdQB0AGgAbwByAHMAIABAACAAZgBvAG4AdABlAGwAbABvAC4AYwBvAG0AZQBwAGcAZABSAGUAZwB1AGwAYQByAGUAcABnAGQAZQBwAGcAZABWAGUAcgBzAGkAbwBuACAAMQAuADAAZQBwAGcAZABHAGUAbgBlAHIAYQB0AGUAZAAgAGIAeQAgAHMAdgBnADIAdAB0AGYAIABmAHIAbwBtACAARgBvAG4AdABlAGwAbABvACAAcAByAG8AagBlAGMAdAAuAGgAdAB0AHAAOgAvAC8AZgBvAG4AdABlAGwAbABvAC4AYwBvAG0AAAAAAgAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvAQIBAwEEAQUBBgEHAQgBCQEKAQsBDAENAQ4BDwEQAREBEgETARQBFQEWARcBGAEZARoBGwEcAR0BHgEfASABIQEiASMBJAElASYBJwEoASkBKgErASwBLQEuAS8BMAAIcHJvZ3Jlc3MGcmVjb3JkBmNhbmNlbARoZWxwDGhlbHAtY2lyY2xlZAxpbmZvLWNpcmNsZWQEaW5mbwhsaW5rLWV4dAV0cmFzaA1mb2xkZXItY2xvc2VkDWZvbGRlci1vcGVuZWQEbWVudQVsb2dpbgZsb2dvdXQIZG93bi1kaXIGdXAtZGlyCGxlZnQtZGlyCXJpZ2h0LWRpcgdyZWZyZXNoBWNoZWNrC2NoZWNrLWVtcHR5BHNhdmUJc29ydC1kb3duB3NvcnQtdXAMc29ydC1uYW1lLXVwDnNvcnQtbmFtZS1kb3duCmZsYXNobGlnaHQEd2FpdARwbGF5BHN0b3AFcGF1c2UGdG8tZW5kCHRvLXN0YXJ0B2ZvcndhcmQGcmV3aW5kAm9rB3dhcm5pbmcFY2xvY2sGYnVmZmVyB2RvYy1uZXcGc2VhcmNoBGVkaXQCdHYNdGh1bWItcmF0ZS11cA1mbGFzaC1vdXRsaW5lBWVycm9yAAAAAAEAAf//AA8AAAAAAAAAAAAAAAAAAAAAABgAGAAYABgEcv5YBHL+WLAALCCwAFVYRVkgIEu4AA5RS7AGU1pYsDQbsChZYGYgilVYsAIlYbkIAAgAY2MjYhshIbAAWbAAQyNEsgABAENgQi2wASywIGBmLbACLCBkILDAULAEJlqyKAEKQ0VjRVJbWCEjIRuKWCCwUFBYIbBAWRsgsDhQWCGwOFlZILEBCkNFY0VhZLAoUFghsQEKQ0VjRSCwMFBYIbAwWRsgsMBQWCBmIIqKYSCwClBYYBsgsCBQWCGwCmAbILA2UFghsDZgG2BZWVkbsAErWVkjsABQWGVZWS2wAywgRSCwBCVhZCCwBUNQWLAFI0KwBiNCGyEhWbABYC2wBCwjISMhIGSxBWJCILAGI0KxAQpDRWOxAQpDsAFgRWOwAyohILAGQyCKIIqwASuxMAUlsAQmUVhgUBthUllYI1khILBAU1iwASsbIbBAWSOwAFBYZVktsAUssAdDK7IAAgBDYEItsAYssAcjQiMgsAAjQmGwAmJmsAFjsAFgsAUqLbAHLCAgRSCwC0NjuAQAYiCwAFBYsEBgWWawAWNgRLABYC2wCCyyBwsAQ0VCKiGyAAEAQ2BCLbAJLLAAQyNEsgABAENgQi2wCiwgIEUgsAErI7AAQ7AEJWAgRYojYSBkILAgUFghsAAbsDBQWLAgG7BAWVkjsABQWGVZsAMlI2FERLABYC2wCywgIEUgsAErI7AAQ7AEJWAgRYojYSBksCRQWLAAG7BAWSOwAFBYZVmwAyUjYUREsAFgLbAMLCCwACNCsgsKA0VYIRsjIVkqIS2wDSyxAgJFsGRhRC2wDiywAWAgILAMQ0qwAFBYILAMI0JZsA1DSrAAUlggsA0jQlktsA8sILAQYmawAWMguAQAY4ojYbAOQ2AgimAgsA4jQiMtsBAsS1RYsQRkRFkksA1lI3gtsBEsS1FYS1NYsQRkRFkbIVkksBNlI3gtsBIssQAPQ1VYsQ8PQ7ABYUKwDytZsABDsAIlQrEMAiVCsQ0CJUKwARYjILADJVBYsQEAQ2CwBCVCioogiiNhsA4qISOwAWEgiiNhsA4qIRuxAQBDYLACJUKwAiVhsA4qIVmwDENHsA1DR2CwAmIgsABQWLBAYFlmsAFjILALQ2O4BABiILAAUFiwQGBZZrABY2CxAAATI0SwAUOwAD6yAQEBQ2BCLbATLACxAAJFVFiwDyNCIEWwCyNCsAojsAFgQiBgsAFhtRAQAQAOAEJCimCxEgYrsHIrGyJZLbAULLEAEystsBUssQETKy2wFiyxAhMrLbAXLLEDEystsBgssQQTKy2wGSyxBRMrLbAaLLEGEystsBsssQcTKy2wHCyxCBMrLbAdLLEJEystsB4sALANK7EAAkVUWLAPI0IgRbALI0KwCiOwAWBCIGCwAWG1EBABAA4AQkKKYLESBiuwcisbIlktsB8ssQAeKy2wICyxAR4rLbAhLLECHistsCIssQMeKy2wIyyxBB4rLbAkLLEFHistsCUssQYeKy2wJiyxBx4rLbAnLLEIHistsCgssQkeKy2wKSwgPLABYC2wKiwgYLAQYCBDI7ABYEOwAiVhsAFgsCkqIS2wKyywKiuwKiotsCwsICBHICCwC0NjuAQAYiCwAFBYsEBgWWawAWNgI2E4IyCKVVggRyAgsAtDY7gEAGIgsABQWLBAYFlmsAFjYCNhOBshWS2wLSwAsQACRVRYsAEWsCwqsAEVMBsiWS2wLiwAsA0rsQACRVRYsAEWsCwqsAEVMBsiWS2wLywgNbABYC2wMCwAsAFFY7gEAGIgsABQWLBAYFlmsAFjsAErsAtDY7gEAGIgsABQWLBAYFlmsAFjsAErsAAWtAAAAAAARD4jOLEvARUqLbAxLCA8IEcgsAtDY7gEAGIgsABQWLBAYFlmsAFjYLAAQ2E4LbAyLC4XPC2wMywgPCBHILALQ2O4BABiILAAUFiwQGBZZrABY2CwAENhsAFDYzgtsDQssQIAFiUgLiBHsAAjQrACJUmKikcjRyNhIFhiGyFZsAEjQrIzAQEVFCotsDUssAAWsAQlsAQlRyNHI2GwCUMrZYouIyAgPIo4LbA2LLAAFrAEJbAEJSAuRyNHI2EgsAQjQrAJQysgsGBQWCCwQFFYswIgAyAbswImAxpZQkIjILAIQyCKI0cjRyNhI0ZgsARDsAJiILAAUFiwQGBZZrABY2AgsAErIIqKYSCwAkNgZCOwA0NhZFBYsAJDYRuwA0NgWbADJbACYiCwAFBYsEBgWWawAWNhIyAgsAQmI0ZhOBsjsAhDRrACJbAIQ0cjRyNhYCCwBEOwAmIgsABQWLBAYFlmsAFjYCMgsAErI7AEQ2CwASuwBSVhsAUlsAJiILAAUFiwQGBZZrABY7AEJmEgsAQlYGQjsAMlYGRQWCEbIyFZIyAgsAQmI0ZhOFktsDcssAAWICAgsAUmIC5HI0cjYSM8OC2wOCywABYgsAgjQiAgIEYjR7ABKyNhOC2wOSywABawAyWwAiVHI0cjYbAAVFguIDwjIRuwAiWwAiVHI0cjYSCwBSWwBCVHI0cjYbAGJbAFJUmwAiVhuQgACABjYyMgWGIbIVljuAQAYiCwAFBYsEBgWWawAWNgIy4jICA8ijgjIVktsDossAAWILAIQyAuRyNHI2EgYLAgYGawAmIgsABQWLBAYFlmsAFjIyAgPIo4LbA7LCMgLkawAiVGUlggPFkusSsBFCstsDwsIyAuRrACJUZQWCA8WS6xKwEUKy2wPSwjIC5GsAIlRlJYIDxZIyAuRrACJUZQWCA8WS6xKwEUKy2wPiywNSsjIC5GsAIlRlJYIDxZLrErARQrLbA/LLA2K4ogIDywBCNCijgjIC5GsAIlRlJYIDxZLrErARQrsARDLrArKy2wQCywABawBCWwBCYgLkcjRyNhsAlDKyMgPCAuIzixKwEUKy2wQSyxCAQlQrAAFrAEJbAEJSAuRyNHI2EgsAQjQrAJQysgsGBQWCCwQFFYswIgAyAbswImAxpZQkIjIEewBEOwAmIgsABQWLBAYFlmsAFjYCCwASsgiophILACQ2BkI7ADQ2FkUFiwAkNhG7ADQ2BZsAMlsAJiILAAUFiwQGBZZrABY2GwAiVGYTgjIDwjOBshICBGI0ewASsjYTghWbErARQrLbBCLLA1Ky6xKwEUKy2wQyywNishIyAgPLAEI0IjOLErARQrsARDLrArKy2wRCywABUgR7AAI0KyAAEBFRQTLrAxKi2wRSywABUgR7AAI0KyAAEBFRQTLrAxKi2wRiyxAAEUE7AyKi2wRyywNCotsEgssAAWRSMgLiBGiiNhOLErARQrLbBJLLAII0KwSCstsEossgAAQSstsEsssgABQSstsEwssgEAQSstsE0ssgEBQSstsE4ssgAAQistsE8ssgABQistsFAssgEAQistsFEssgEBQistsFIssgAAPistsFMssgABPistsFQssgEAPistsFUssgEBPistsFYssgAAQCstsFcssgABQCstsFgssgEAQCstsFkssgEBQCstsFossgAAQystsFsssgABQystsFwssgEAQystsF0ssgEBQystsF4ssgAAPystsF8ssgABPystsGAssgEAPystsGEssgEBPystsGIssDcrLrErARQrLbBjLLA3K7A7Ky2wZCywNyuwPCstsGUssAAWsDcrsD0rLbBmLLA4Ky6xKwEUKy2wZyywOCuwOystsGgssDgrsDwrLbBpLLA4K7A9Ky2waiywOSsusSsBFCstsGsssDkrsDsrLbBsLLA5K7A8Ky2wbSywOSuwPSstsG4ssDorLrErARQrLbBvLLA6K7A7Ky2wcCywOiuwPCstsHEssDorsD0rLbByLLMJBAIDRVghGyMhWUIrsAhlsAMkUHiwARUwLQBLuADIUlixAQGOWbABuQgACABjcLEABUKyAAEAKrEABUKzCgIBCCqxAAVCsw4AAQgqsQAGQroCwAABAAkqsQAHQroAQAABAAkqsQMARLEkAYhRWLBAiFixA2REsSYBiFFYugiAAAEEQIhjVFixAwBEWVlZWbMMAgEMKrgB/4WwBI2xAgBEAAA=') format('truetype'); +} +/* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */ +/* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */ +/* +@media screen and (-webkit-min-device-pixel-ratio:0) { + @font-face { + font-family: 'epgd'; + src: url('../font/epgd.svg?45443790#epgd') format('svg'); + } +} +*/ + + [class^="i-"]:before, [class*=" i-"]:before { + font-family: "epgd"; + font-style: normal; + font-weight: normal; + speak: none; + + display: inline-block; + text-decoration: inherit; + width: 1em; + margin-right: .2em; + text-align: center; + /* opacity: .8; */ + + /* For safety - reset parent styles, that can break glyph codes*/ + font-variant: normal; + text-transform: none; + + /* fix buttons height, for twitter bootstrap */ + line-height: 1em; + + /* Animation center compensation - margins should be symmetric */ + /* remove if not needed */ + margin-left: .2em; + + /* you can be more comfortable with increased icons size */ + /* font-size: 120%; */ + + /* Uncomment for 3D effect */ + /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */ +} +.i-progress:before { content: '\e800'; } /* '' */ +.i-record:before { content: '\e801'; } /* '' */ +.i-cancel:before { content: '\e802'; } /* '' */ +.i-help:before { content: '\e803'; } /* '' */ +.i-help-circled:before { content: '\e804'; } /* '' */ +.i-info-circled:before { content: '\e805'; } /* '' */ +.i-info:before { content: '\e806'; } /* '' */ +.i-link-ext:before { content: '\e807'; } /* '' */ +.i-trash:before { content: '\e808'; } /* '' */ +.i-folder-closed:before { content: '\e809'; } /* '' */ +.i-folder-opened:before { content: '\e80a'; } /* '' */ +.i-menu:before { content: '\e80b'; } /* '' */ +.i-login:before { content: '\e80c'; } /* '' */ +.i-logout:before { content: '\e80d'; } /* '' */ +.i-down-dir:before { content: '\e80e'; } /* '' */ +.i-up-dir:before { content: '\e80f'; } /* '' */ +.i-left-dir:before { content: '\e810'; } /* '' */ +.i-right-dir:before { content: '\e811'; } /* '' */ +.i-refresh:before { content: '\e812'; } /* '' */ +.i-check:before { content: '\e813'; } /* '' */ +.i-check-empty:before { content: '\e814'; } /* '' */ +.i-save:before { content: '\e815'; } /* '' */ +.i-sort-down:before { content: '\e816'; } /* '' */ +.i-sort-up:before { content: '\e817'; } /* '' */ +.i-sort-name-up:before { content: '\e818'; } /* '' */ +.i-sort-name-down:before { content: '\e819'; } /* '' */ +.i-flashlight:before { content: '\e81a'; } /* '' */ +.i-wait:before { content: '\e81b'; } /* '' */ +.i-play:before { content: '\e81c'; } /* '' */ +.i-stop:before { content: '\e81d'; } /* '' */ +.i-pause:before { content: '\e81e'; } /* '' */ +.i-to-end:before { content: '\e81f'; } /* '' */ +.i-to-start:before { content: '\e820'; } /* '' */ +.i-forward:before { content: '\e821'; } /* '' */ +.i-rewind:before { content: '\e822'; } /* '' */ +.i-ok:before { content: '\e823'; } /* '' */ +.i-warning:before { content: '\e824'; } /* '' */ +.i-clock:before { content: '\e825'; } /* '' */ +.i-buffer:before { content: '\e826'; } /* '' */ +.i-doc-new:before { content: '\e827'; } /* '' */ +.i-search:before { content: '\e828'; } /* '' */ +.i-edit:before { content: '\e829'; } /* '' */ +.i-tv:before { content: '\e82a'; } /* '' */ +.i-thumb-rate-up:before { content: '\e82b'; } /* '' */ +.i-flash-outline:before { content: '\e82c'; } /* '' */ +.i-error:before { content: '\e82d'; } /* '' */ \ No newline at end of file diff --git a/http/3rdParty/fontello/css/epgd-ie7-codes.css b/http/3rdParty/fontello/css/epgd-ie7-codes.css new file mode 100644 index 0000000..c1b51dc --- /dev/null +++ b/http/3rdParty/fontello/css/epgd-ie7-codes.css @@ -0,0 +1,47 @@ + +.i-progress { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-record { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-cancel { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-help { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-help-circled { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-info-circled { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-info { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-link-ext { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-trash { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-folder-closed { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-folder-opened { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-menu { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-login { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-logout { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-down-dir { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-up-dir { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-left-dir { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-right-dir { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-refresh { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-check { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-check-empty { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-save { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-sort-down { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-sort-up { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-sort-name-up { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-sort-name-down { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-flashlight { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-wait { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-play { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-stop { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-pause { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-to-end { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-to-start { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-forward { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-rewind { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-ok { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-warning { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-clock { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-buffer { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-doc-new { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-search { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-edit { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-tv { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-thumb-rate-up { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-flash-outline { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-error { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } \ No newline at end of file diff --git a/http/3rdParty/fontello/css/epgd-ie7.css b/http/3rdParty/fontello/css/epgd-ie7.css new file mode 100644 index 0000000..e9a25ae --- /dev/null +++ b/http/3rdParty/fontello/css/epgd-ie7.css @@ -0,0 +1,58 @@ +[class^="i-"], [class*=" i-"] { + font-family: 'epgd'; + font-style: normal; + font-weight: normal; + + /* fix buttons height */ + line-height: 1em; + + /* you can be more comfortable with increased icons size */ + /* font-size: 120%; */ +} + +.i-progress { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-record { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-cancel { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-help { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-help-circled { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-info-circled { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-info { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-link-ext { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-trash { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-folder-closed { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-folder-opened { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-menu { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-login { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-logout { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-down-dir { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-up-dir { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-left-dir { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-right-dir { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-refresh { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-check { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-check-empty { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-save { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-sort-down { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-sort-up { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-sort-name-up { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-sort-name-down { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-flashlight { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-wait { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-play { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-stop { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-pause { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-to-end { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-to-start { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-forward { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-rewind { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-ok { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-warning { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-clock { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-buffer { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-doc-new { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-search { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-edit { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-tv { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-thumb-rate-up { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-flash-outline { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.i-error { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } \ No newline at end of file diff --git a/http/3rdParty/fontello/css/epgd.css b/http/3rdParty/fontello/css/epgd.css new file mode 100644 index 0000000..3396c72 --- /dev/null +++ b/http/3rdParty/fontello/css/epgd.css @@ -0,0 +1,103 @@ +@font-face { + font-family: 'epgd'; + src: url('../font/epgd.eot?78346169'); + src: url('../font/epgd.eot?78346169#iefix') format('embedded-opentype'), + url('../font/epgd.woff2?78346169') format('woff2'), + url('../font/epgd.woff?78346169') format('woff'), + url('../font/epgd.ttf?78346169') format('truetype'), + url('../font/epgd.svg?78346169#epgd') format('svg'); + font-weight: normal; + font-style: normal; +} +/* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */ +/* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */ +/* +@media screen and (-webkit-min-device-pixel-ratio:0) { + @font-face { + font-family: 'epgd'; + src: url('../font/epgd.svg?78346169#epgd') format('svg'); + } +} +*/ + + [class^="i-"]:before, [class*=" i-"]:before { + font-family: "epgd"; + font-style: normal; + font-weight: normal; + speak: none; + + display: inline-block; + text-decoration: inherit; + width: 1em; + margin-right: .2em; + text-align: center; + /* opacity: .8; */ + + /* For safety - reset parent styles, that can break glyph codes*/ + font-variant: normal; + text-transform: none; + + /* fix buttons height, for twitter bootstrap */ + line-height: 1em; + + /* Animation center compensation - margins should be symmetric */ + /* remove if not needed */ + margin-left: .2em; + + /* you can be more comfortable with increased icons size */ + /* font-size: 120%; */ + + /* Font smoothing. That was taken from TWBS */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + + /* Uncomment for 3D effect */ + /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */ +} + +.i-progress:before { content: '\e800'; } /* '' */ +.i-record:before { content: '\e801'; } /* '' */ +.i-cancel:before { content: '\e802'; } /* '' */ +.i-help:before { content: '\e803'; } /* '' */ +.i-help-circled:before { content: '\e804'; } /* '' */ +.i-info-circled:before { content: '\e805'; } /* '' */ +.i-info:before { content: '\e806'; } /* '' */ +.i-link-ext:before { content: '\e807'; } /* '' */ +.i-trash:before { content: '\e808'; } /* '' */ +.i-folder-closed:before { content: '\e809'; } /* '' */ +.i-folder-opened:before { content: '\e80a'; } /* '' */ +.i-menu:before { content: '\e80b'; } /* '' */ +.i-login:before { content: '\e80c'; } /* '' */ +.i-logout:before { content: '\e80d'; } /* '' */ +.i-down-dir:before { content: '\e80e'; } /* '' */ +.i-up-dir:before { content: '\e80f'; } /* '' */ +.i-left-dir:before { content: '\e810'; } /* '' */ +.i-right-dir:before { content: '\e811'; } /* '' */ +.i-refresh:before { content: '\e812'; } /* '' */ +.i-check:before { content: '\e813'; } /* '' */ +.i-check-empty:before { content: '\e814'; } /* '' */ +.i-save:before { content: '\e815'; } /* '' */ +.i-sort-down:before { content: '\e816'; } /* '' */ +.i-sort-up:before { content: '\e817'; } /* '' */ +.i-sort-name-up:before { content: '\e818'; } /* '' */ +.i-sort-name-down:before { content: '\e819'; } /* '' */ +.i-flashlight:before { content: '\e81a'; } /* '' */ +.i-wait:before { content: '\e81b'; } /* '' */ +.i-play:before { content: '\e81c'; } /* '' */ +.i-stop:before { content: '\e81d'; } /* '' */ +.i-pause:before { content: '\e81e'; } /* '' */ +.i-to-end:before { content: '\e81f'; } /* '' */ +.i-to-start:before { content: '\e820'; } /* '' */ +.i-forward:before { content: '\e821'; } /* '' */ +.i-rewind:before { content: '\e822'; } /* '' */ +.i-ok:before { content: '\e823'; } /* '' */ +.i-warning:before { content: '\e824'; } /* '' */ +.i-clock:before { content: '\e825'; } /* '' */ +.i-buffer:before { content: '\e826'; } /* '' */ +.i-doc-new:before { content: '\e827'; } /* '' */ +.i-search:before { content: '\e828'; } /* '' */ +.i-edit:before { content: '\e829'; } /* '' */ +.i-tv:before { content: '\e82a'; } /* '' */ +.i-thumb-rate-up:before { content: '\e82b'; } /* '' */ +.i-flash-outline:before { content: '\e82c'; } /* '' */ +.i-error:before { content: '\e82d'; } /* '' */ \ No newline at end of file diff --git a/http/3rdParty/fontello/demo.html b/http/3rdParty/fontello/demo.html new file mode 100644 index 0000000..6e86ed0 --- /dev/null +++ b/http/3rdParty/fontello/demo.html @@ -0,0 +1,376 @@ +<!DOCTYPE html> +<html> + <head><!--[if lt IE 9]><script language="javascript" type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script><![endif]--> + <meta charset="UTF-8"><style>/* + * Bootstrap v2.2.1 + * + * Copyright 2012 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */ +.clearfix { + *zoom: 1; +} +.clearfix:before, +.clearfix:after { + display: table; + content: ""; + line-height: 0; +} +.clearfix:after { + clear: both; +} +html { + font-size: 100%; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} +a:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +a:hover, +a:active { + outline: 0; +} +button, +input, +select, +textarea { + margin: 0; + font-size: 100%; + vertical-align: middle; +} +button, +input { + *overflow: visible; + line-height: normal; +} +button::-moz-focus-inner, +input::-moz-focus-inner { + padding: 0; + border: 0; +} +body { + margin: 0; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 20px; + color: #333; + background-color: #fff; +} +a { + color: #08c; + text-decoration: none; +} +a:hover { + color: #005580; + text-decoration: underline; +} +.row { + margin-left: -20px; + *zoom: 1; +} +.row:before, +.row:after { + display: table; + content: ""; + line-height: 0; +} +.row:after { + clear: both; +} +[class*="span"] { + float: left; + min-height: 1px; + margin-left: 20px; +} +.container, +.navbar-static-top .container, +.navbar-fixed-top .container, +.navbar-fixed-bottom .container { + width: 940px; +} +.span12 { + width: 940px; +} +.span11 { + width: 860px; +} +.span10 { + width: 780px; +} +.span9 { + width: 700px; +} +.span8 { + width: 620px; +} +.span7 { + width: 540px; +} +.span6 { + width: 460px; +} +.span5 { + width: 380px; +} +.span4 { + width: 300px; +} +.span3 { + width: 220px; +} +.span2 { + width: 140px; +} +.span1 { + width: 60px; +} +[class*="span"].pull-right, +.row-fluid [class*="span"].pull-right { + float: right; +} +.container { + margin-right: auto; + margin-left: auto; + *zoom: 1; +} +.container:before, +.container:after { + display: table; + content: ""; + line-height: 0; +} +.container:after { + clear: both; +} +p { + margin: 0 0 10px; +} +.lead { + margin-bottom: 20px; + font-size: 21px; + font-weight: 200; + line-height: 30px; +} +small { + font-size: 85%; +} +h1 { + margin: 10px 0; + font-family: inherit; + font-weight: bold; + line-height: 20px; + color: inherit; + text-rendering: optimizelegibility; +} +h1 small { + font-weight: normal; + line-height: 1; + color: #999; +} +h1 { + line-height: 40px; +} +h1 { + font-size: 38.5px; +} +h1 small { + font-size: 24.5px; +} +body { + margin-top: 90px; +} +.header { + position: fixed; + top: 0; + left: 50%; + margin-left: -480px; + background-color: #fff; + border-bottom: 1px solid #ddd; + padding-top: 10px; + z-index: 10; +} +.footer { + color: #ddd; + font-size: 12px; + text-align: center; + margin-top: 20px; +} +.footer a { + color: #ccc; + text-decoration: underline; +} +.the-icons { + font-size: 14px; + line-height: 24px; +} +.switch { + position: absolute; + right: 0; + bottom: 10px; + color: #666; +} +.switch input { + margin-right: 0.3em; +} +.codesOn .i-name { + display: none; +} +.codesOn .i-code { + display: inline; +} +.i-code { + display: none; +} +@font-face { + font-family: 'epgd'; + src: url('./font/epgd.eot?36693829'); + src: url('./font/epgd.eot?36693829#iefix') format('embedded-opentype'), + url('./font/epgd.woff?36693829') format('woff'), + url('./font/epgd.ttf?36693829') format('truetype'), + url('./font/epgd.svg?36693829#epgd') format('svg'); + font-weight: normal; + font-style: normal; + } + + + .demo-icon + { + font-family: "epgd"; + font-style: normal; + font-weight: normal; + speak: none; + + display: inline-block; + text-decoration: inherit; + width: 1em; + margin-right: .2em; + text-align: center; + /* opacity: .8; */ + + /* For safety - reset parent styles, that can break glyph codes*/ + font-variant: normal; + text-transform: none; + + /* fix buttons height, for twitter bootstrap */ + line-height: 1em; + + /* Animation center compensation - margins should be symmetric */ + /* remove if not needed */ + margin-left: .2em; + + /* You can be more comfortable with increased icons size */ + /* font-size: 120%; */ + + /* Font smoothing. That was taken from TWBS */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + + /* Uncomment for 3D effect */ + /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */ + } + </style> + <link rel="stylesheet" href="css/animation.css"><!--[if IE 7]><link rel="stylesheet" href="css/epgd-ie7.css"><![endif]--> + <script> + function toggleCodes(on) { + var obj = document.getElementById('icons'); + + if (on) { + obj.className += ' codesOn'; + } else { + obj.className = obj.className.replace(' codesOn', ''); + } + } + + </script> + </head> + <body> + <div class="container header"> + <h1> + epgd + <small>font demo</small> + </h1> + <label class="switch"> + <input type="checkbox" onclick="toggleCodes(this.checked)">show codes + </label> + </div> + <div id="icons" class="container"> + <div class="row"> + <div title="Code: 0xe800" class="the-icons span3"><i class="demo-icon i-progress animate-spin"></i> <span class="i-name">i-progress</span><span class="i-code">0xe800</span></div> + <div title="Code: 0xe801" class="the-icons span3"><i class="demo-icon i-record"></i> <span class="i-name">i-record</span><span class="i-code">0xe801</span></div> + <div title="Code: 0xe802" class="the-icons span3"><i class="demo-icon i-cancel"></i> <span class="i-name">i-cancel</span><span class="i-code">0xe802</span></div> + <div title="Code: 0xe803" class="the-icons span3"><i class="demo-icon i-help"></i> <span class="i-name">i-help</span><span class="i-code">0xe803</span></div> + </div> + <div class="row"> + <div title="Code: 0xe804" class="the-icons span3"><i class="demo-icon i-help-circled"></i> <span class="i-name">i-help-circled</span><span class="i-code">0xe804</span></div> + <div title="Code: 0xe805" class="the-icons span3"><i class="demo-icon i-info-circled"></i> <span class="i-name">i-info-circled</span><span class="i-code">0xe805</span></div> + <div title="Code: 0xe806" class="the-icons span3"><i class="demo-icon i-info"></i> <span class="i-name">i-info</span><span class="i-code">0xe806</span></div> + <div title="Code: 0xe807" class="the-icons span3"><i class="demo-icon i-link-ext"></i> <span class="i-name">i-link-ext</span><span class="i-code">0xe807</span></div> + </div> + <div class="row"> + <div title="Code: 0xe808" class="the-icons span3"><i class="demo-icon i-trash"></i> <span class="i-name">i-trash</span><span class="i-code">0xe808</span></div> + <div title="Code: 0xe809" class="the-icons span3"><i class="demo-icon i-folder-closed"></i> <span class="i-name">i-folder-closed</span><span class="i-code">0xe809</span></div> + <div title="Code: 0xe80a" class="the-icons span3"><i class="demo-icon i-folder-opened"></i> <span class="i-name">i-folder-opened</span><span class="i-code">0xe80a</span></div> + <div title="Code: 0xe80b" class="the-icons span3"><i class="demo-icon i-menu"></i> <span class="i-name">i-menu</span><span class="i-code">0xe80b</span></div> + </div> + <div class="row"> + <div title="Code: 0xe80c" class="the-icons span3"><i class="demo-icon i-login"></i> <span class="i-name">i-login</span><span class="i-code">0xe80c</span></div> + <div title="Code: 0xe80d" class="the-icons span3"><i class="demo-icon i-logout"></i> <span class="i-name">i-logout</span><span class="i-code">0xe80d</span></div> + <div title="Code: 0xe80e" class="the-icons span3"><i class="demo-icon i-down-dir"></i> <span class="i-name">i-down-dir</span><span class="i-code">0xe80e</span></div> + <div title="Code: 0xe80f" class="the-icons span3"><i class="demo-icon i-up-dir"></i> <span class="i-name">i-up-dir</span><span class="i-code">0xe80f</span></div> + </div> + <div class="row"> + <div title="Code: 0xe810" class="the-icons span3"><i class="demo-icon i-left-dir"></i> <span class="i-name">i-left-dir</span><span class="i-code">0xe810</span></div> + <div title="Code: 0xe811" class="the-icons span3"><i class="demo-icon i-right-dir"></i> <span class="i-name">i-right-dir</span><span class="i-code">0xe811</span></div> + <div title="Code: 0xe812" class="the-icons span3"><i class="demo-icon i-refresh"></i> <span class="i-name">i-refresh</span><span class="i-code">0xe812</span></div> + <div title="Code: 0xe813" class="the-icons span3"><i class="demo-icon i-check"></i> <span class="i-name">i-check</span><span class="i-code">0xe813</span></div> + </div> + <div class="row"> + <div title="Code: 0xe814" class="the-icons span3"><i class="demo-icon i-check-empty"></i> <span class="i-name">i-check-empty</span><span class="i-code">0xe814</span></div> + <div title="Code: 0xe815" class="the-icons span3"><i class="demo-icon i-save"></i> <span class="i-name">i-save</span><span class="i-code">0xe815</span></div> + <div title="Code: 0xe816" class="the-icons span3"><i class="demo-icon i-sort-down"></i> <span class="i-name">i-sort-down</span><span class="i-code">0xe816</span></div> + <div title="Code: 0xe817" class="the-icons span3"><i class="demo-icon i-sort-up"></i> <span class="i-name">i-sort-up</span><span class="i-code">0xe817</span></div> + </div> + <div class="row"> + <div title="Code: 0xe818" class="the-icons span3"><i class="demo-icon i-sort-name-up"></i> <span class="i-name">i-sort-name-up</span><span class="i-code">0xe818</span></div> + <div title="Code: 0xe819" class="the-icons span3"><i class="demo-icon i-sort-name-down"></i> <span class="i-name">i-sort-name-down</span><span class="i-code">0xe819</span></div> + <div title="Code: 0xe81a" class="the-icons span3"><i class="demo-icon i-flashlight"></i> <span class="i-name">i-flashlight</span><span class="i-code">0xe81a</span></div> + <div title="Code: 0xe81b" class="the-icons span3"><i class="demo-icon i-wait"></i> <span class="i-name">i-wait</span><span class="i-code">0xe81b</span></div> + </div> + <div class="row"> + <div title="Code: 0xe81c" class="the-icons span3"><i class="demo-icon i-play"></i> <span class="i-name">i-play</span><span class="i-code">0xe81c</span></div> + <div title="Code: 0xe81d" class="the-icons span3"><i class="demo-icon i-stop"></i> <span class="i-name">i-stop</span><span class="i-code">0xe81d</span></div> + <div title="Code: 0xe81e" class="the-icons span3"><i class="demo-icon i-pause"></i> <span class="i-name">i-pause</span><span class="i-code">0xe81e</span></div> + <div title="Code: 0xe81f" class="the-icons span3"><i class="demo-icon i-to-end"></i> <span class="i-name">i-to-end</span><span class="i-code">0xe81f</span></div> + </div> + <div class="row"> + <div title="Code: 0xe820" class="the-icons span3"><i class="demo-icon i-to-start"></i> <span class="i-name">i-to-start</span><span class="i-code">0xe820</span></div> + <div title="Code: 0xe821" class="the-icons span3"><i class="demo-icon i-forward"></i> <span class="i-name">i-forward</span><span class="i-code">0xe821</span></div> + <div title="Code: 0xe822" class="the-icons span3"><i class="demo-icon i-rewind"></i> <span class="i-name">i-rewind</span><span class="i-code">0xe822</span></div> + <div title="Code: 0xe823" class="the-icons span3"><i class="demo-icon i-ok"></i> <span class="i-name">i-ok</span><span class="i-code">0xe823</span></div> + </div> + <div class="row"> + <div title="Code: 0xe824" class="the-icons span3"><i class="demo-icon i-warning"></i> <span class="i-name">i-warning</span><span class="i-code">0xe824</span></div> + <div title="Code: 0xe825" class="the-icons span3"><i class="demo-icon i-clock"></i> <span class="i-name">i-clock</span><span class="i-code">0xe825</span></div> + <div title="Code: 0xe826" class="the-icons span3"><i class="demo-icon i-buffer"></i> <span class="i-name">i-buffer</span><span class="i-code">0xe826</span></div> + <div title="Code: 0xe827" class="the-icons span3"><i class="demo-icon i-doc-new"></i> <span class="i-name">i-doc-new</span><span class="i-code">0xe827</span></div> + </div> + <div class="row"> + <div title="Code: 0xe828" class="the-icons span3"><i class="demo-icon i-search"></i> <span class="i-name">i-search</span><span class="i-code">0xe828</span></div> + <div title="Code: 0xe829" class="the-icons span3"><i class="demo-icon i-edit"></i> <span class="i-name">i-edit</span><span class="i-code">0xe829</span></div> + <div title="Code: 0xe82a" class="the-icons span3"><i class="demo-icon i-tv"></i> <span class="i-name">i-tv</span><span class="i-code">0xe82a</span></div> + <div title="Code: 0xe82b" class="the-icons span3"><i class="demo-icon i-thumb-rate-up"></i> <span class="i-name">i-thumb-rate-up</span><span class="i-code">0xe82b</span></div> + </div> + <div class="row"> + <div title="Code: 0xe82c" class="the-icons span3"><i class="demo-icon i-flash-outline"></i> <span class="i-name">i-flash-outline</span><span class="i-code">0xe82c</span></div> + <div title="Code: 0xe82d" class="the-icons span3"><i class="demo-icon i-error"></i> <span class="i-name">i-error</span><span class="i-code">0xe82d</span></div> + </div> + </div> + <div class="container footer">Generated by <a href="http://fontello.com">fontello.com</a></div> + </body> +</html> \ No newline at end of file diff --git a/http/3rdParty/fontello/font/epgd.eot b/http/3rdParty/fontello/font/epgd.eot new file mode 100644 index 0000000..afecad6 Binary files /dev/null and b/http/3rdParty/fontello/font/epgd.eot differ diff --git a/http/3rdParty/fontello/font/epgd.svg b/http/3rdParty/fontello/font/epgd.svg new file mode 100644 index 0000000..e59f432 --- /dev/null +++ b/http/3rdParty/fontello/font/epgd.svg @@ -0,0 +1,102 @@ +<?xml version="1.0" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg xmlns="http://www.w3.org/2000/svg"> +<metadata>Copyright (C) 2016 by original authors @ fontello.com</metadata> +<defs> +<font id="epgd" horiz-adv-x="1000" > +<font-face font-family="epgd" font-weight="400" font-stretch="normal" units-per-em="1000" ascent="850" descent="-150" /> +<missing-glyph horiz-adv-x="1000" /> +<glyph glyph-name="progress" unicode="" d="M855 9c-189-190-520-172-705 13-190 190-200 494-28 695 11 13 21 26 35 34 36 23 85 18 117-13 30-31 35-76 16-112-5-9-9-15-16-22-140-151-145-379-8-516 153-153 407-121 542 34 106 122 142 297 77 451-83 198-305 291-510 222l0 1c236 82 492-24 588-252 71-167 37-355-72-493-11-15-23-29-36-42z" horiz-adv-x="1000" /> + +<glyph glyph-name="record" unicode="" d="M1000 654v-608q0-23-22-32-7-3-14-3-15 0-25 10l-225 225v-92q0-67-47-114t-113-47h-393q-67 0-114 47t-47 114v392q0 67 47 114t114 47h393q66 0 113-47t47-114v-92l225 225q10 10 25 10 7 0 14-2 22-10 22-33z" horiz-adv-x="1000" /> + +<glyph glyph-name="cancel" unicode="" d="M724 112q0-22-15-38l-76-76q-16-15-38-15t-38 15l-164 165-164-165q-16-15-38-15t-38 15l-76 76q-16 16-16 38t16 38l164 164-164 164q-16 16-16 38t16 38l76 76q16 16 38 16t38-16l164-164 164 164q16 16 38 16t38-16l76-76q15-15 15-38t-15-38l-164-164 164-164q15-15 15-38z" horiz-adv-x="785.7" /> + +<glyph glyph-name="help" unicode="" d="M393 149v-134q0-9-7-15t-15-7h-134q-9 0-16 7t-7 15v134q0 9 7 16t16 6h134q9 0 15-6t7-16z m176 335q0-30-8-56t-20-43-31-33-32-25-34-19q-23-13-38-37t-15-37q0-10-7-18t-16-9h-134q-8 0-14 11t-6 20v26q0 46 37 87t79 60q33 16 47 32t14 42q0 24-26 41t-60 18q-36 0-60-16-20-14-60-64-7-9-17-9-7 0-14 4l-91 70q-8 6-9 14t3 16q89 148 259 148 45 0 90-17t81-46 59-72 23-88z" horiz-adv-x="571.4" /> + +<glyph glyph-name="help-circled" unicode="" d="M500 82v107q0 8-5 13t-13 5h-107q-8 0-13-5t-5-13v-107q0-8 5-13t13-5h107q8 0 13 5t5 13z m143 375q0 49-31 91t-77 65-95 23q-136 0-207-119-9-13 4-24l74-55q4-4 10-4 9 0 14 7 30 38 48 51 19 14 48 14 27 0 48-15t21-33q0-21-11-34t-38-25q-35-15-65-48t-29-70v-20q0-8 5-13t13-5h107q8 0 13 5t5 13q0 10 12 27t30 28q18 10 28 16t25 19 25 27 16 34 7 45z m214-107q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" /> + +<glyph glyph-name="info-circled" unicode="" d="M571 82v89q0 8-5 13t-12 5h-54v286q0 8-5 13t-13 5h-178q-8 0-13-5t-5-13v-89q0-8 5-13t13-5h53v-179h-53q-8 0-13-5t-5-13v-89q0-8 5-13t13-5h250q7 0 12 5t5 13z m-71 500v89q0 8-5 13t-13 5h-107q-8 0-13-5t-5-13v-89q0-8 5-13t13-5h107q8 0 13 5t5 13z m357-232q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" /> + +<glyph glyph-name="info" unicode="" d="M357 100v-71q0-15-10-25t-26-11h-285q-15 0-25 11t-11 25v71q0 15 11 25t25 11h35v214h-35q-15 0-25 11t-11 25v71q0 15 11 25t25 11h214q15 0 25-11t11-25v-321h35q15 0 26-11t10-25z m-71 643v-107q0-15-11-25t-25-11h-143q-14 0-25 11t-11 25v107q0 14 11 25t25 11h143q15 0 25-11t11-25z" horiz-adv-x="357.1" /> + +<glyph glyph-name="link-ext" unicode="" d="M786 332v-178q0-67-47-114t-114-47h-464q-67 0-114 47t-47 114v464q0 66 47 113t114 48h393q7 0 12-5t5-13v-36q0-8-5-13t-12-5h-393q-37 0-63-26t-27-63v-464q0-37 27-63t63-27h464q37 0 63 27t26 63v178q0 8 5 13t13 5h36q8 0 13-5t5-13z m214 482v-285q0-15-11-25t-25-11-25 11l-98 98-364-364q-5-6-13-6t-12 6l-64 64q-6 5-6 12t6 13l364 364-98 98q-11 11-11 25t11 25 25 11h285q15 0 25-11t11-25z" horiz-adv-x="1000" /> + +<glyph glyph-name="trash" unicode="" d="M286 439v-321q0-8-5-13t-13-5h-36q-8 0-13 5t-5 13v321q0 8 5 13t13 5h36q8 0 13-5t5-13z m143 0v-321q0-8-5-13t-13-5h-36q-8 0-13 5t-5 13v321q0 8 5 13t13 5h36q8 0 13-5t5-13z m142 0v-321q0-8-5-13t-12-5h-36q-8 0-13 5t-5 13v321q0 8 5 13t13 5h36q7 0 12-5t5-13z m72-404v529h-500v-529q0-12 4-22t8-15 6-5h464q2 0 6 5t8 15 4 22z m-375 601h250l-27 65q-4 5-9 6h-177q-6-1-10-6z m518-18v-36q0-8-5-13t-13-5h-54v-529q0-46-26-80t-63-34h-464q-37 0-63 33t-27 79v531h-53q-8 0-13 5t-5 13v36q0 8 5 13t13 5h172l39 93q9 21 31 35t44 15h178q23 0 44-15t30-35l39-93h173q8 0 13-5t5-13z" horiz-adv-x="785.7" /> + +<glyph glyph-name="folder-closed" unicode="" d="M857 118v393q0 22-15 38t-38 15h-393q-23 0-38 16t-16 38v36q0 22-15 38t-38 15h-179q-22 0-38-15t-16-38v-536q0-22 16-38t38-16h679q22 0 38 16t15 38z m72 393v-393q0-51-37-88t-88-37h-679q-51 0-88 37t-37 88v536q0 51 37 88t88 37h179q51 0 88-37t37-88v-18h375q51 0 88-37t37-88z" horiz-adv-x="928.6" /> + +<glyph glyph-name="folder-opened" unicode="" d="M994 331q0 19-30 19h-607q-22 0-48-12t-39-29l-164-203q-11-13-11-22 0-20 30-20h607q23 0 48 13t40 29l164 203q10 12 10 22z m-637 90h429v90q0 22-16 38t-38 15h-321q-23 0-38 16t-16 38v36q0 22-15 38t-38 15h-179q-22 0-38-15t-16-38v-476l143 175q25 30 65 49t78 19z m708-90q0-35-25-67l-165-203q-24-30-65-49t-78-19h-607q-51 0-88 37t-37 88v536q0 51 37 88t88 37h179q51 0 88-37t37-88v-18h303q52 0 88-37t37-88v-90h107q30 0 56-13t37-40q8-17 8-37z" horiz-adv-x="1071.4" /> + +<glyph glyph-name="menu" unicode="" d="M857 100v-71q0-15-10-25t-26-11h-785q-15 0-25 11t-11 25v71q0 15 11 25t25 11h785q15 0 26-11t10-25z m0 286v-72q0-14-10-25t-26-10h-785q-15 0-25 10t-11 25v72q0 14 11 25t25 10h785q15 0 26-10t10-25z m0 285v-71q0-14-10-25t-26-11h-785q-15 0-25 11t-11 25v71q0 15 11 26t25 10h785q15 0 26-10t10-26z" horiz-adv-x="857.1" /> + +<glyph glyph-name="login" unicode="" d="M661 350q0-14-11-25l-303-304q-11-10-26-10t-25 10-10 25v161h-250q-15 0-25 11t-11 25v214q0 15 11 25t25 11h250v161q0 14 10 25t25 10 26-10l303-304q11-10 11-25z m196 196v-392q0-67-47-114t-114-47h-178q-7 0-13 5t-5 13q0 2-1 11t0 15 2 13 5 11 12 3h178q37 0 64 27t26 63v392q0 37-26 64t-64 26h-174t-6 0-6 2-5 3-4 5-1 8q0 2-1 11t0 15 2 13 5 11 12 3h178q67 0 114-47t47-114z" horiz-adv-x="857.1" /> + +<glyph glyph-name="logout" unicode="" d="M357 46q0-2 1-11t0-14-2-14-5-11-12-3h-178q-67 0-114 47t-47 114v392q0 67 47 114t114 47h178q8 0 13-5t5-13q0-2 1-11t0-15-2-13-5-11-12-3h-178q-37 0-63-26t-27-64v-392q0-37 27-63t63-27h174t6 0 7-2 4-3 4-5 1-8z m518 304q0-14-11-25l-303-304q-11-10-25-10t-25 10-11 25v161h-250q-14 0-25 11t-11 25v214q0 15 11 25t25 11h250v161q0 14 11 25t25 10 25-10l303-304q11-10 11-25z" horiz-adv-x="928.6" /> + +<glyph glyph-name="down-dir" unicode="" d="M571 457q0-14-10-25l-250-250q-11-11-25-11t-25 11l-250 250q-11 11-11 25t11 25 25 11h500q14 0 25-11t10-25z" horiz-adv-x="571.4" /> + +<glyph glyph-name="up-dir" unicode="" d="M571 171q0-14-10-25t-25-10h-500q-15 0-25 10t-11 25 11 26l250 250q10 10 25 10t25-10l250-250q10-11 10-26z" horiz-adv-x="571.4" /> + +<glyph glyph-name="left-dir" unicode="" d="M357 600v-500q0-14-10-25t-26-11-25 11l-250 250q-10 11-10 25t10 25l250 250q11 11 25 11t26-11 10-25z" horiz-adv-x="357.1" /> + +<glyph glyph-name="right-dir" unicode="" d="M321 350q0-14-10-25l-250-250q-11-11-25-11t-25 11-11 25v500q0 15 11 25t25 11 25-11l250-250q10-10 10-25z" horiz-adv-x="357.1" /> + +<glyph glyph-name="refresh" unicode="" d="M843 261q0-3 0-4-36-150-150-243t-267-93q-81 0-157 31t-136 88l-72-72q-11-11-25-11t-25 11-11 25v250q0 14 11 25t25 11h250q14 0 25-11t10-25-10-25l-77-77q40-36 90-57t105-20q74 0 139 37t104 99q6 10 30 66 4 13 16 13h107q8 0 13-6t5-12z m14 446v-250q0-14-10-25t-26-11h-250q-14 0-25 11t-10 25 10 25l77 77q-82 77-194 77-75 0-140-37t-104-99q-6-10-29-66-5-13-17-13h-111q-7 0-13 6t-5 12v4q36 150 151 243t268 93q81 0 158-31t137-88l72 72q11 11 25 11t26-11 10-25z" horiz-adv-x="857.1" /> + +<glyph glyph-name="check" unicode="" d="M786 331v-177q0-67-47-114t-114-47h-464q-67 0-114 47t-47 114v464q0 66 47 113t114 48h464q35 0 65-14 9-4 10-13 2-10-5-16l-27-28q-6-5-13-5-1 0-5 1-13 3-25 3h-464q-37 0-63-26t-27-63v-464q0-37 27-63t63-27h464q37 0 63 27t26 63v141q0 8 5 13l36 35q6 6 13 6 3 0 7-2 11-4 11-16z m129 273l-455-454q-13-14-31-14t-32 14l-240 240q-14 13-14 31t14 32l61 62q14 13 32 13t32-13l147-147 361 361q13 13 31 13t32-13l62-61q13-14 13-32t-13-32z" horiz-adv-x="928.6" /> + +<glyph glyph-name="check-empty" unicode="" d="M625 707h-464q-37 0-63-26t-27-63v-464q0-37 27-63t63-27h464q37 0 63 27t26 63v464q0 37-26 63t-63 26z m161-89v-464q0-67-47-114t-114-47h-464q-67 0-114 47t-47 114v464q0 66 47 113t114 48h464q66 0 114-48t47-113z" horiz-adv-x="785.7" /> + +<glyph glyph-name="save" unicode="" d="M214-7h429v214h-429v-214z m500 0h72v500q0 8-6 21t-11 20l-157 156q-5 6-19 12t-22 5v-232q0-22-15-38t-38-16h-322q-22 0-37 16t-16 38v232h-72v-714h72v232q0 22 16 38t37 16h465q22 0 38-16t15-38v-232z m-214 518v178q0 8-5 13t-13 5h-107q-7 0-13-5t-5-13v-178q0-7 5-13t13-5h107q7 0 13 5t5 13z m357-18v-518q0-22-15-38t-38-16h-750q-23 0-38 16t-16 38v750q0 22 16 38t38 16h517q23 0 50-12t42-26l156-157q16-15 27-42t11-49z" horiz-adv-x="857.1" /> + +<glyph glyph-name="sort-down" unicode="" d="M571 243q0-15-10-25l-250-250q-11-11-25-11t-25 11l-250 250q-11 10-11 25t11 25 25 11h500q14 0 25-11t10-25z" horiz-adv-x="571.4" /> + +<glyph glyph-name="sort-up" unicode="" d="M571 457q0-14-10-25t-25-11h-500q-15 0-25 11t-11 25 11 25l250 250q10 11 25 11t25-11l250-250q10-10 10-25z" horiz-adv-x="571.4" /> + +<glyph glyph-name="sort-name-up" unicode="" d="M665 622h98l-40 122-6 26q-2 9-2 11h-2l-1-11q0 0-2-10t-5-16z m-254-576q0-6-6-13l-178-178q-5-5-13-5-6 0-12 5l-179 179q-8 9-4 19 4 11 17 11h107v768q0 8 5 13t13 5h107q8 0 13-5t5-13v-768h107q8 0 13-5t5-13z m466-66v-130h-326v50l206 295q7 11 12 16l6 5v1q-1 0-3 0t-5 0q-6-2-16-2h-130v-64h-67v128h317v-50l-206-296q-4-4-12-14l-6-7v-1l8 1q5 2 16 2h139v66h67z m50 501v-60h-161v60h42l-26 80h-136l-26-80h42v-60h-160v60h39l128 369h91l128-369h39z" horiz-adv-x="928.6" /> + +<glyph glyph-name="sort-name-down" unicode="" d="M665 51h98l-40 122-6 26q-2 9-2 11h-2l-1-11q0-1-2-10t-5-16z m-254-5q0-6-6-13l-178-178q-5-5-13-5-6 0-12 5l-179 179q-8 9-4 19 4 11 17 11h107v768q0 8 5 13t13 5h107q8 0 13-5t5-13v-768h107q8 0 13-5t5-13z m516-137v-59h-161v59h42l-26 80h-136l-26-80h42v-59h-160v59h39l128 370h91l128-370h39z m-50 643v-131h-326v51l206 295q7 10 12 15l6 5v2q-1 0-3-1t-5 0q-6-2-16-2h-130v-64h-67v128h317v-50l-206-295q-4-5-12-15l-6-5v-2l8 2q5 0 16 0h139v67h67z" horiz-adv-x="928.6" /> + +<glyph glyph-name="flashlight" unicode="" d="M807 706q62-62 85-130t-5-92l-134-134q-16-16-62-26t-96-4l-408-408q-18-18-57-6t-75 50q-36 36-49 74t5 56l408 408q-6 50 4 96t26 62l136 136q24 28 92 4t130-86z m-448-408q32-32 80 14 46 46 14 82-14 14-38 10t-44-24-23-43 11-39z m336 298q30-30 68-50t62-25 28-1q2 4-4 27t-26 60-50 67-66 50-59 26-27 2 1-28 25-62 48-66z" horiz-adv-x="902" /> + +<glyph glyph-name="wait" unicode="" d="M560 622q0-44-48-96t-97-99-49-77 49-76 97-97 48-97l0-118q0-34-86-73t-194-39-194 39-86 73l0 118q0 46 48 97t97 97 49 76-49 77-97 99-48 96l0 118q0 32 87 71t193 39 193-39 87-71l0-118z m-482 112l-18-14q-4-8 4-14 92-52 216-52 132 0 220 50 14 10-16 30-96 54-202 54-120 0-204-54z m228-384q0 18 4 33t18 33 20 25 31 31 29 28q92 92 92 122l2 50q-100-54-222-54t-222 54l4-50q0-32 90-122 6-6 22-21t23-22l19-19t17-21 11-20 9-23 3-24q0-10-1-19t-6-18-8-16-11-17l-12-15t-15-16-16-15-18-16-17-16q-90-90-90-122l0-66q8 4 66 23t92 43 34 58q0 30 26 30t26-30q0-34 33-58t94-43 67-23l0 66q0 30-92 122-4 4-21 20t-22 21-18 19-18 22-12 20-9 23-2 23z" horiz-adv-x="560" /> + +<glyph glyph-name="play" unicode="" d="M486 376q14-10 14-26 0-14-14-24l-428-266q-24-16-41-6t-17 40l0 514q0 30 17 40t41-6z" horiz-adv-x="500" /> + +<glyph glyph-name="stop" unicode="" d="M526 650q74 0 74-64l0-470q0-66-74-66l-450 0q-76 0-76 66l0 470q0 36 18 50t58 14l450 0z" horiz-adv-x="600" /> + +<glyph glyph-name="pause" unicode="" d="M440 700q90 0 90-64l0-570q0-66-90-66t-90 66l0 570q0 64 90 64z m-350 0q90 0 90-64l0-570q0-66-90-66t-90 66l0 570q0 64 90 64z" horiz-adv-x="530" /> + +<glyph glyph-name="to-end" unicode="" d="M412 374q14-10 14-24 0-12-14-22l-362-228q-22-14-36-5t-14 35l0 442q0 26 14 35t36-5z m114 268q74 0 74-58l0-466q0-58-74-58-76 0-76 58l0 466q0 58 76 58z" horiz-adv-x="600" /> + +<glyph glyph-name="to-start" unicode="" d="M174 350q0 14 14 24l364 228q20 14 34 5t14-35l0-442q0-26-14-35t-34 5l-364 228q-14 10-14 22z m-174 234q0 58 76 58 74 0 74-58l0-466q0-58-74-58-76 0-76 58l0 466z" horiz-adv-x="600" /> + +<glyph glyph-name="forward" unicode="" d="M866 374q14-10 14-24t-14-22l-372-248q-22-14-37-6t-15 36l0 482q0 28 15 36t37-6z m-454 0q14-10 14-24t-14-22l-360-248q-20-14-36-6t-16 36l0 482q0 28 16 36t36-6z" horiz-adv-x="880" /> + +<glyph glyph-name="rewind" unicode="" d="M0 350q0 14 14 24l374 248q20 14 36 6t16-36l0-482q0-28-16-36t-36 6l-374 248q-14 8-14 22z m454 0q0 14 14 24l360 248q20 14 36 6t16-36l0-482q0-28-16-36t-36 6l-360 248q-14 8-14 22z" horiz-adv-x="880" /> + +<glyph glyph-name="ok" unicode="" d="M365-41q-66 0-111 45l-208 209q-46 46-46 110 0 65 46 111 44 44 110 44t110-44l63-62 160 287q20 38 57 60t79 22q88 0 134-76t2-157l-260-469q-43-80-136-80z m-209 417q-21 0-37-16t-15-37q0-20 16-36l208-209q18-19 44-15t38 26l260 469q11 23 4 43t-24 28q-19 10-39 4t-31-24l-227-408-160 160q-15 15-37 15z" horiz-adv-x="783" /> + +<glyph glyph-name="warning" unicode="" d="M514 701q-49 0-81-55l-308-513q-32-55-11-95t87-40l625 0q65 0 87 40t-12 95l-307 513q-33 55-80 55z m0 105q106 0 169-107l308-513q63-105 12-199-52-93-177-93l-625 0q-123 0-177 93-53 92 11 199l309 513q62 107 170 107z m-69-652q0 69 69 69 67 0 67-69 0-67-67-67-69 0-69 67z m146 313q0-14-6-29l-71-179q-44 108-73 179-6 15-6 29 0 32 23 55t56 24 55-24 22-55z" horiz-adv-x="1026" /> + +<glyph glyph-name="clock" unicode="" d="M406 757c224 0 407-182 407-407 0-223-183-406-407-406-225 0-406 183-406 406 0 225 181 407 406 407z m0-723c175 0 317 143 317 318s-142 316-317 316-317-141-317-316 142-318 317-318z m120 268l-127 0c-14 0-25 5-33 15l-143 156c-39 41 25 101 65 61l130-142 108 0c62 0 55-90 0-90z m-145 287c0 13 12 24 24 24s24-11 24-24-11-24-24-24-24 12-24 24z m167-65c0 13 11 24 23 24s24-11 24-24-11-24-24-24-23 12-23 24z m73-171c0 12 12 24 24 24s24-12 24-24-11-24-24-24-24 11-24 24z m-66-168c0 13 11 24 24 24s24-11 24-24-12-23-24-23-24 11-24 23z m-175-72c0 12 11 24 24 24s24-12 24-24-12-24-24-24-24 11-24 24z m-162 65c0 12 11 24 23 24s24-12 24-24-11-24-24-24-23 11-23 24z m-75 175c0 12 11 24 23 24s24-12 24-24-11-24-24-24-23 11-23 24z" horiz-adv-x="813" /> + +<glyph glyph-name="buffer" unicode="" d="M0 88q11 15 32 26t49 20 40 15q19 0 34-4t33-15 25-13q47-21 260-119 19-4 36 0t39 18 24 14q20 9 77 35t87 39q4 2 42 21t60 24q13 2 28-1t23-7 23-13 18-11 16-6 18-8 11-11q3-4 4-14-10-13-31-24t-51-22-40-16q-43-20-128-62t-129-61q-7-3-21-12t-23-13-26-11-27-7-30 2l-264 123q-6 3-32 14t-51 22-54 24-46 24-22 16q-4 4-4 13z m0 268q11 15 32 25t50 20 41 15q19 0 34-4t35-15 25-14q42-19 127-58t127-59q19-5 37 0t39 17 25 14q68 32 160 72 11 5 32 17t38 19 36 11q16 3 32-1t37-17 23-13q5-3 16-6t18-8 11-11q3-5 4-14-10-14-31-25t-53-23-41-16q-48-23-135-65t-123-59q-7-3-26-14t-29-15-32-10-36 0q-214 101-260 122-6 3-44 19t-69 30-62 30-34 22q-4 4-4 14z m0 267q10 15 32 27t52 22 41 16l348 162q30 0 54-7t56-26 40-22q39-18 117-54t117-55q4-2 37-15t54-24 27-20q3-4 4-13-9-13-26-22t-43-19-35-14q-47-22-140-66t-139-67q-6-3-20-11t-23-12-25-11-27-6-28 1q-245 114-256 119-4 2-63 28t-102 46-48 30q-4 4-4 13z" horiz-adv-x="979" /> + +<glyph glyph-name="doc-new" unicode="" d="M0-150l0 818 188 182 519 0 0-348-86 0 0 260-369 0 0-156-166 0 0-668 418 0 0-88-504 0z m373 207l0 162 209 0 0 207 160 0 0-207 207 0 0-162-207 0 0-207-160 0 0 207-209 0z" horiz-adv-x="949" /> + +<glyph glyph-name="search" unicode="" d="M0-41q0 47 33 80l260 260q-43 82-43 176 0 154 109 265t266 110 266-110 109-266-109-265-266-109q-94 0-176 43l-260-260q-33-33-80-33-45 0-77 32t-32 77z m55 1q0-22 16-39t39-16 40 17l252 252q-45 33-78 78l-252-252q-17-17-17-40z m258 515q0-129 91-221t221-91 221 91 91 221-91 221-221 91-221-91-91-221z m93 0q0 90 65 154t154 65q16 0 16-16t-16-16q-78 0-133-54t-54-133q0-16-16-16t-16 16z" horiz-adv-x="1000" /> + +<glyph glyph-name="edit" unicode="" d="M0-41q0 4 1 8t1 8 1 8 1 6l0 2 74 267q10 31 31 53l325 324 0 2 2 2 150 152q60 59 146 59 106 0 186-80 74-74 81-171t-58-161l-476-481q-24-23-55-31l-263-70-3-1q-3-1-7-2t-9-1-10-1-9-1q-45 0-77 32t-32 77z m63 0q0-19 13-33t33-14q6 0 22 4l115 32q4 58-43 105-45 45-105 43l-32-119q-3-14-3-18z m44 168q67-2 118-52t52-120l116 30 11 6q41 47 34 115t-61 121q-51 49-115 59t-112-24q-7-10-11-21z m131 225q45-2 90-20l295 295q-88 22-144-33z m119-35q38-20 65-45 21-22 41-55l297 299q-16 31-39 55-30 29-67 45z m122-129q17-41 21-82l0-24 242 245 0 2q61 60 31 156z m101 508q106 0 186-80 70-73 78-166l0-22 52 55q45 45 41 111-5 74-62 131-63 62-143 62-60 0-101-41z" horiz-adv-x="1000" /> + +<glyph glyph-name="tv" unicode="" d="M0 100l0 625q0 39 27 66t67 28l812 0q39 0 67-28t27-66l0-625q0-39-27-66t-67-28l-312 0 0-37 195-25q23-6 23-32 0-13-8-22t-23-9l-562 0q-14 0-23 9t-8 22q0 26 23 32l195 25 0 37-312 0q-39 0-67 28t-27 66z m63 0q0-14 8-22t23-9l812 0q14 0 23 9t8 22l0 625q0 14-8 22t-23 9l-812 0q-14 0-23-9t-8-22l0-625z m62 125l0 437q0 14 9 23t22 9l688 0q13 0 22-9t9-23l0-437q0-14-9-22t-22-9l-688 0q-13 0-22 9t-9 22z m31 0l688 0 0 437-688 0 0-437z" horiz-adv-x="1000" /> + +<glyph glyph-name="thumb-rate-up" unicode="" d="M1204-51c-5-81-14-128-31-164-26-57-103-145-151-173-30-17-103-35-148-35-43-1-54 4-75 36-26 38-56 64-100 85-58 29-72 47-72 99-1 42-12 63-51 92-52 38-79 72-87 110-7 49 33 101 17 149-30 26-56 45-81 76-33 64-10 159 49 196 34 17 87 30 148 35 62 6 88 15 144 49 70 38 111 60 205 61l6 124c-81 78-94 139-66 245 28 82 22 145 107 185 43 18 76 21 112 11 59-17 99-47 120-90 39-81 45-255 14-406-19-63-9-122 20-180 40-101 22-123 57-152-94-148-123-175-137-353z m35 507c-31 57-27 125-11 186 24 124 39 286-19 401-24 34-79 62-125 62-108-3-110-84-136-166-19-43-21-97-1-140 39-75 118-109 179-160-37-6-72 11-106 23l4-110c115-53 124-157 81-264 39-29 74-83 74-161 21 60 71 108 92 168 14 60-4 110-32 161z m-267-481c-42-11-83-15-74-7 2 2 31 16 63 30 154 48 237 242 46 280-92 1-198-95-285-42 54-11 101 12 149 35 60 30 90 38 143 39 71 4 70 82 56 136-76 135-220 67-323 17-57-29-85-37-166-47-94-6-132-45-134-143-2-62 97-72 98-126-2-43-14-85-18-128 0-40 24-70 80-101 43-23 48-32 52-93 2-25 5-48 7-52 69-48 110-60 165-133 84-31 263 27 245 141-76-7-144-12-201 32 24 6 48 5 71 4 203-53 272 243 26 158z" horiz-adv-x="1727" /> + +<glyph glyph-name="flash-outline" unicode="" d="M495 767z m0 0l-391-369 261-151-130-313 390 370-260 150z m0 105q43 0 73-31t31-74q0-22-10-44l-93-224 182-105q43-25 50-77t-32-89l-390-370q-31-29-72-29-56 0-86 47t-9 98l95 228-181 105q-44 25-52 76t32 90l390 370q31 29 72 29z" horiz-adv-x="729" /> + +<glyph glyph-name="error" unicode="" d="M0 350q0 207 147 354t353 146 354-146 146-354-146-354-354-146-353 146-147 354z m137 0q0-150 106-257t257-106 257 106 106 257-106 257-257 106-257-106-106-257z m97-98l0 196 532 0 0-196-532 0z" horiz-adv-x="1000" /> +</font> +</defs> +</svg> \ No newline at end of file diff --git a/http/3rdParty/fontello/font/epgd.ttf b/http/3rdParty/fontello/font/epgd.ttf new file mode 100644 index 0000000..afcefa7 Binary files /dev/null and b/http/3rdParty/fontello/font/epgd.ttf differ diff --git a/http/3rdParty/fontello/font/epgd.woff b/http/3rdParty/fontello/font/epgd.woff new file mode 100644 index 0000000..bab45aa Binary files /dev/null and b/http/3rdParty/fontello/font/epgd.woff differ diff --git a/http/3rdParty/jQuery-Timepicker-Addon-master/dist/jquery-ui-timepicker-addon.min.css b/http/3rdParty/jQuery-Timepicker-Addon-master/dist/jquery-ui-timepicker-addon.min.css new file mode 100644 index 0000000..079d885 --- /dev/null +++ b/http/3rdParty/jQuery-Timepicker-Addon-master/dist/jquery-ui-timepicker-addon.min.css @@ -0,0 +1,5 @@ +/*! jQuery Timepicker Addon - v1.5.0 - 2014-09-01 +* http://trentrichardson.com/examples/timepicker +* Copyright (c) 2014 Trent Richardson; Licensed MIT */ + +.ui-timepicker-div .ui-widget-header{margin-bottom:8px}.ui-timepicker-div dl{text-align:left}.ui-timepicker-div dl dt{float:left;clear:left;padding:0 0 0 5px}.ui-timepicker-div dl dd{margin:0 10px 10px 40%}.ui-timepicker-div td{font-size:90%}.ui-tpicker-grid-label{background:0 0;border:0;margin:0;padding:0}.ui-timepicker-rtl{direction:rtl}.ui-timepicker-rtl dl{text-align:right;padding:0 5px 0 0}.ui-timepicker-rtl dl dt{float:right;clear:right}.ui-timepicker-rtl dl dd{margin:0 40% 10px 10px} \ No newline at end of file diff --git a/http/3rdParty/jQuery-Timepicker-Addon-master/dist/jquery-ui-timepicker-addon.min.js b/http/3rdParty/jQuery-Timepicker-Addon-master/dist/jquery-ui-timepicker-addon.min.js new file mode 100644 index 0000000..b7f8786 --- /dev/null +++ b/http/3rdParty/jQuery-Timepicker-Addon-master/dist/jquery-ui-timepicker-addon.min.js @@ -0,0 +1,5 @@ +/*! jQuery Timepicker Addon - v1.5.0 - 2014-09-01 +* http://trentrichardson.com/examples/timepicker +* Copyright (c) 2014 Trent Richardson; Licensed MIT */ +(function($){if($.ui.timepicker=$.ui.timepicker||{},!$.ui.timepicker.version){$.extend($.ui,{timepicker:{version:"1.5.0"}});var Timepicker=function(){this.regional=[],this.regional[""]={currentText:"Now",closeText:"Done",amNames:["AM","A"],pmNames:["PM","P"],timeFormat:"HH:mm",timeSuffix:"",timeOnlyTitle:"Choose Time",timeText:"Time",hourText:"Hour",minuteText:"Minute",secondText:"Second",millisecText:"Millisecond",microsecText:"Microsecond",timezoneText:"Time Zone",isRTL:!1},this._defaults={showButtonPanel:!0,timeOnly:!1,timeOnlyShowDate:!1,showHour:null,showMinute:null,showSecond:null,showMillisec:null,showMicrosec:null,showTimezone:null,showTime:!0,stepHour:1,stepMinute:1,stepSecond:1,stepMillisec:1,stepMicrosec:1,hour:0,minute:0,second:0,millisec:0,microsec:0,timezone:null,hourMin:0,minuteMin:0,secondMin:0,millisecMin:0,microsecMin:0,hourMax:23,minuteMax:59,secondMax:59,millisecMax:999,microsecMax:999,minDateTime:null,maxDateTime:null,maxTime:null,minTime:null,onSelect:null,hourGrid:0,minuteGrid:0,secondGrid:0,millisecGrid:0,microsecGrid:0,alwaysSetTime:!0,separator:" ",altFieldTimeOnly:!0,altTimeFormat:null,altSeparator:null,altTimeSuffix:null,altRedirectFocus:!0,pickerTimeFormat:null,pickerTimeSuffix:null,showTimepicker:!0,timezoneList:null,addSliderAccess:!1,sliderAccessArgs:null,controlType:"slider",defaultValue:null,parse:"strict"},$.extend(this._defaults,this.regional[""])};$.extend(Timepicker.prototype,{$input:null,$altInput:null,$timeObj:null,inst:null,hour_slider:null,minute_slider:null,second_slider:null,millisec_slider:null,microsec_slider:null,timezone_select:null,maxTime:null,minTime:null,hour:0,minute:0,second:0,millisec:0,microsec:0,timezone:null,hourMinOriginal:null,minuteMinOriginal:null,secondMinOriginal:null,millisecMinOriginal:null,microsecMinOriginal:null,hourMaxOriginal:null,minuteMaxOriginal:null,secondMaxOriginal:null,millisecMaxOriginal:null,microsecMaxOriginal:null,ampm:"",formattedDate:"",formattedTime:"",formattedDateTime:"",timezoneList:null,units:["hour","minute","second","millisec","microsec"],support:{},control:null,setDefaults:function(e){return extendRemove(this._defaults,e||{}),this},_newInst:function($input,opts){var tp_inst=new Timepicker,inlineSettings={},fns={},overrides,i;for(var attrName in this._defaults)if(this._defaults.hasOwnProperty(attrName)){var attrValue=$input.attr("time:"+attrName);if(attrValue)try{inlineSettings[attrName]=eval(attrValue)}catch(err){inlineSettings[attrName]=attrValue}}overrides={beforeShow:function(e,t){return $.isFunction(tp_inst._defaults.evnts.beforeShow)?tp_inst._defaults.evnts.beforeShow.call($input[0],e,t,tp_inst):void 0},onChangeMonthYear:function(e,t,i){tp_inst._updateDateTime(i),$.isFunction(tp_inst._defaults.evnts.onChangeMonthYear)&&tp_inst._defaults.evnts.onChangeMonthYear.call($input[0],e,t,i,tp_inst)},onClose:function(e,t){tp_inst.timeDefined===!0&&""!==$input.val()&&tp_inst._updateDateTime(t),$.isFunction(tp_inst._defaults.evnts.onClose)&&tp_inst._defaults.evnts.onClose.call($input[0],e,t,tp_inst)}};for(i in overrides)overrides.hasOwnProperty(i)&&(fns[i]=opts[i]||null);tp_inst._defaults=$.extend({},this._defaults,inlineSettings,opts,overrides,{evnts:fns,timepicker:tp_inst}),tp_inst.amNames=$.map(tp_inst._defaults.amNames,function(e){return e.toUpperCase()}),tp_inst.pmNames=$.map(tp_inst._defaults.pmNames,function(e){return e.toUpperCase()}),tp_inst.support=detectSupport(tp_inst._defaults.timeFormat+(tp_inst._defaults.pickerTimeFormat?tp_inst._defaults.pickerTimeFormat:"")+(tp_inst._defaults.altTimeFormat?tp_inst._defaults.altTimeFormat:"")),"string"==typeof tp_inst._defaults.controlType?("slider"===tp_inst._defaults.controlType&&$.ui.slider===void 0&&(tp_inst._defaults.controlType="select"),tp_inst.control=tp_inst._controls[tp_inst._defaults.controlType]):tp_inst.control=tp_inst._defaults.controlType;var timezoneList=[-720,-660,-600,-570,-540,-480,-420,-360,-300,-270,-240,-210,-180,-120,-60,0,60,120,180,210,240,270,300,330,345,360,390,420,480,525,540,570,600,630,660,690,720,765,780,840];null!==tp_inst._defaults.timezoneList&&(timezoneList=tp_inst._defaults.timezoneList);var tzl=timezoneList.length,tzi=0,tzv=null;if(tzl>0&&"object"!=typeof timezoneList[0])for(;tzl>tzi;tzi++)tzv=timezoneList[tzi],timezoneList[tzi]={value:tzv,label:$.timepicker.timezoneOffsetString(tzv,tp_inst.support.iso8601)};return tp_inst._defaults.timezoneList=timezoneList,tp_inst.timezone=null!==tp_inst._defaults.timezone?$.timepicker.timezoneOffsetNumber(tp_inst._defaults.timezone):-1*(new Date).getTimezoneOffset(),tp_inst.hour=tp_inst._defaults.hour<tp_inst._defaults.hourMin?tp_inst._defaults.hourMin:tp_inst._defaults.hour>tp_inst._defaults.hourMax?tp_inst._defaults.hourMax:tp_inst._defaults.hour,tp_inst.minute=tp_inst._defaults.minute<tp_inst._defaults.minuteMin?tp_inst._defaults.minuteMin:tp_inst._defaults.minute>tp_inst._defaults.minuteMax?tp_inst._defaults.minuteMax:tp_inst._defaults.minute,tp_inst.second=tp_inst._defaults.second<tp_inst._defaults.secondMin?tp_inst._defaults.secondMin:tp_inst._defaults.second>tp_inst._defaults.secondMax?tp_inst._defaults.secondMax:tp_inst._defaults.second,tp_inst.millisec=tp_inst._defaults.millisec<tp_inst._defaults.millisecMin?tp_inst._defaults.millisecMin:tp_inst._defaults.millisec>tp_inst._defaults.millisecMax?tp_inst._defaults.millisecMax:tp_inst._defaults.millisec,tp_inst.microsec=tp_inst._defaults.microsec<tp_inst._defaults.microsecMin?tp_inst._defaults.microsecMin:tp_inst._defaults.microsec>tp_inst._defaults.microsecMax?tp_inst._defaults.microsecMax:tp_inst._defaults.microsec,tp_inst.ampm="",tp_inst.$input=$input,tp_inst._defaults.altField&&(tp_inst.$altInput=$(tp_inst._defaults.altField),tp_inst._defaults.altRedirectFocus===!0&&tp_inst.$altInput.css({cursor:"pointer"}).focus(function(){$input.trigger("focus")})),(0===tp_inst._defaults.minDate||0===tp_inst._defaults.minDateTime)&&(tp_inst._defaults.minDate=new Date),(0===tp_inst._defaults.maxDate||0===tp_inst._defaults.maxDateTime)&&(tp_inst._defaults.maxDate=new Date),void 0!==tp_inst._defaults.minDate&&tp_inst._defaults.minDate instanceof Date&&(tp_inst._defaults.minDateTime=new Date(tp_inst._defaults.minDate.getTime())),void 0!==tp_inst._defaults.minDateTime&&tp_inst._defaults.minDateTime instanceof Date&&(tp_inst._defaults.minDate=new Date(tp_inst._defaults.minDateTime.getTime())),void 0!==tp_inst._defaults.maxDate&&tp_inst._defaults.maxDate instanceof Date&&(tp_inst._defaults.maxDateTime=new Date(tp_inst._defaults.maxDate.getTime())),void 0!==tp_inst._defaults.maxDateTime&&tp_inst._defaults.maxDateTime instanceof Date&&(tp_inst._defaults.maxDate=new Date(tp_inst._defaults.maxDateTime.getTime())),tp_inst.$input.bind("focus",function(){tp_inst._onFocus()}),tp_inst},_addTimePicker:function(e){var t=this.$altInput&&this._defaults.altFieldTimeOnly?this.$input.val()+" "+this.$altInput.val():this.$input.val();this.timeDefined=this._parseTime(t),this._limitMinMaxDateTime(e,!1),this._injectTimePicker()},_parseTime:function(e,t){if(this.inst||(this.inst=$.datepicker._getInst(this.$input[0])),t||!this._defaults.timeOnly){var i=$.datepicker._get(this.inst,"dateFormat");try{var s=parseDateTimeInternal(i,this._defaults.timeFormat,e,$.datepicker._getFormatConfig(this.inst),this._defaults);if(!s.timeObj)return!1;$.extend(this,s.timeObj)}catch(a){return $.timepicker.log("Error parsing the date/time string: "+a+"\ndate/time string = "+e+"\ntimeFormat = "+this._defaults.timeFormat+"\ndateFormat = "+i),!1}return!0}var n=$.datepicker.parseTime(this._defaults.timeFormat,e,this._defaults);return n?($.extend(this,n),!0):!1},_injectTimePicker:function(){var e=this.inst.dpDiv,t=this.inst.settings,i=this,s="",a="",n=null,r={},l={},o=null,c=0,u=0;if(0===e.find("div.ui-timepicker-div").length&&t.showTimepicker){var m=' style="display:none;"',d='<div class="ui-timepicker-div'+(t.isRTL?" ui-timepicker-rtl":"")+'"><dl>'+'<dt class="ui_tpicker_time_label"'+(t.showTime?"":m)+">"+t.timeText+"</dt>"+'<dd class="ui_tpicker_time"'+(t.showTime?"":m)+"></dd>";for(c=0,u=this.units.length;u>c;c++){if(s=this.units[c],a=s.substr(0,1).toUpperCase()+s.substr(1),n=null!==t["show"+a]?t["show"+a]:this.support[s],r[s]=parseInt(t[s+"Max"]-(t[s+"Max"]-t[s+"Min"])%t["step"+a],10),l[s]=0,d+='<dt class="ui_tpicker_'+s+'_label"'+(n?"":m)+">"+t[s+"Text"]+"</dt>"+'<dd class="ui_tpicker_'+s+'"><div class="ui_tpicker_'+s+'_slider"'+(n?"":m)+"></div>",n&&t[s+"Grid"]>0){if(d+='<div style="padding-left: 1px"><table class="ui-tpicker-grid-label"><tr>',"hour"===s)for(var h=t[s+"Min"];r[s]>=h;h+=parseInt(t[s+"Grid"],10)){l[s]++;var p=$.datepicker.formatTime(this.support.ampm?"hht":"HH",{hour:h},t);d+='<td data-for="'+s+'">'+p+"</td>"}else for(var _=t[s+"Min"];r[s]>=_;_+=parseInt(t[s+"Grid"],10))l[s]++,d+='<td data-for="'+s+'">'+(10>_?"0":"")+_+"</td>";d+="</tr></table></div>"}d+="</dd>"}var f=null!==t.showTimezone?t.showTimezone:this.support.timezone;d+='<dt class="ui_tpicker_timezone_label"'+(f?"":m)+">"+t.timezoneText+"</dt>",d+='<dd class="ui_tpicker_timezone" '+(f?"":m)+"></dd>",d+="</dl></div>";var g=$(d);for(t.timeOnly===!0&&(g.prepend('<div class="ui-widget-header ui-helper-clearfix ui-corner-all"><div class="ui-datepicker-title">'+t.timeOnlyTitle+"</div>"+"</div>"),e.find(".ui-datepicker-header, .ui-datepicker-calendar").hide()),c=0,u=i.units.length;u>c;c++)s=i.units[c],a=s.substr(0,1).toUpperCase()+s.substr(1),n=null!==t["show"+a]?t["show"+a]:this.support[s],i[s+"_slider"]=i.control.create(i,g.find(".ui_tpicker_"+s+"_slider"),s,i[s],t[s+"Min"],r[s],t["step"+a]),n&&t[s+"Grid"]>0&&(o=100*l[s]*t[s+"Grid"]/(r[s]-t[s+"Min"]),g.find(".ui_tpicker_"+s+" table").css({width:o+"%",marginLeft:t.isRTL?"0":o/(-2*l[s])+"%",marginRight:t.isRTL?o/(-2*l[s])+"%":"0",borderCollapse:"collapse"}).find("td").click(function(){var e=$(this),t=e.html(),a=parseInt(t.replace(/[^0-9]/g),10),n=t.replace(/[^apm]/gi),r=e.data("for");"hour"===r&&(-1!==n.indexOf("p")&&12>a?a+=12:-1!==n.indexOf("a")&&12===a&&(a=0)),i.control.value(i,i[r+"_slider"],s,a),i._onTimeChange(),i._onSelectHandler()}).css({cursor:"pointer",width:100/l[s]+"%",textAlign:"center",overflow:"hidden"}));if(this.timezone_select=g.find(".ui_tpicker_timezone").append("<select></select>").find("select"),$.fn.append.apply(this.timezone_select,$.map(t.timezoneList,function(e){return $("<option />").val("object"==typeof e?e.value:e).text("object"==typeof e?e.label:e)})),this.timezone!==void 0&&null!==this.timezone&&""!==this.timezone){var M=-1*new Date(this.inst.selectedYear,this.inst.selectedMonth,this.inst.selectedDay,12).getTimezoneOffset();M===this.timezone?selectLocalTimezone(i):this.timezone_select.val(this.timezone)}else this.hour!==void 0&&null!==this.hour&&""!==this.hour?this.timezone_select.val(t.timezone):selectLocalTimezone(i);this.timezone_select.change(function(){i._onTimeChange(),i._onSelectHandler()});var v=e.find(".ui-datepicker-buttonpane");if(v.length?v.before(g):e.append(g),this.$timeObj=g.find(".ui_tpicker_time"),null!==this.inst){var k=this.timeDefined;this._onTimeChange(),this.timeDefined=k}if(this._defaults.addSliderAccess){var T=this._defaults.sliderAccessArgs,D=this._defaults.isRTL;T.isRTL=D,setTimeout(function(){if(0===g.find(".ui-slider-access").length){g.find(".ui-slider:visible").sliderAccess(T);var e=g.find(".ui-slider-access:eq(0)").outerWidth(!0);e&&g.find("table:visible").each(function(){var t=$(this),i=t.outerWidth(),s=(""+t.css(D?"marginRight":"marginLeft")).replace("%",""),a=i-e,n=s*a/i+"%",r={width:a,marginRight:0,marginLeft:0};r[D?"marginRight":"marginLeft"]=n,t.css(r)})}},10)}i._limitMinMaxDateTime(this.inst,!0)}},_limitMinMaxDateTime:function(e,t){var i=this._defaults,s=new Date(e.selectedYear,e.selectedMonth,e.selectedDay);if(this._defaults.showTimepicker){if(null!==$.datepicker._get(e,"minDateTime")&&void 0!==$.datepicker._get(e,"minDateTime")&&s){var a=$.datepicker._get(e,"minDateTime"),n=new Date(a.getFullYear(),a.getMonth(),a.getDate(),0,0,0,0);(null===this.hourMinOriginal||null===this.minuteMinOriginal||null===this.secondMinOriginal||null===this.millisecMinOriginal||null===this.microsecMinOriginal)&&(this.hourMinOriginal=i.hourMin,this.minuteMinOriginal=i.minuteMin,this.secondMinOriginal=i.secondMin,this.millisecMinOriginal=i.millisecMin,this.microsecMinOriginal=i.microsecMin),e.settings.timeOnly||n.getTime()===s.getTime()?(this._defaults.hourMin=a.getHours(),this.hour<=this._defaults.hourMin?(this.hour=this._defaults.hourMin,this._defaults.minuteMin=a.getMinutes(),this.minute<=this._defaults.minuteMin?(this.minute=this._defaults.minuteMin,this._defaults.secondMin=a.getSeconds(),this.second<=this._defaults.secondMin?(this.second=this._defaults.secondMin,this._defaults.millisecMin=a.getMilliseconds(),this.millisec<=this._defaults.millisecMin?(this.millisec=this._defaults.millisecMin,this._defaults.microsecMin=a.getMicroseconds()):(this.microsec<this._defaults.microsecMin&&(this.microsec=this._defaults.microsecMin),this._defaults.microsecMin=this.microsecMinOriginal)):(this._defaults.millisecMin=this.millisecMinOriginal,this._defaults.microsecMin=this.microsecMinOriginal)):(this._defaults.secondMin=this.secondMinOriginal,this._defaults.millisecMin=this.millisecMinOriginal,this._defaults.microsecMin=this.microsecMinOriginal)):(this._defaults.minuteMin=this.minuteMinOriginal,this._defaults.secondMin=this.secondMinOriginal,this._defaults.millisecMin=this.millisecMinOriginal,this._defaults.microsecMin=this.microsecMinOriginal)):(this._defaults.hourMin=this.hourMinOriginal,this._defaults.minuteMin=this.minuteMinOriginal,this._defaults.secondMin=this.secondMinOriginal,this._defaults.millisecMin=this.millisecMinOriginal,this._defaults.microsecMin=this.microsecMinOriginal)}if(null!==$.datepicker._get(e,"maxDateTime")&&void 0!==$.datepicker._get(e,"maxDateTime")&&s){var r=$.datepicker._get(e,"maxDateTime"),l=new Date(r.getFullYear(),r.getMonth(),r.getDate(),0,0,0,0);(null===this.hourMaxOriginal||null===this.minuteMaxOriginal||null===this.secondMaxOriginal||null===this.millisecMaxOriginal)&&(this.hourMaxOriginal=i.hourMax,this.minuteMaxOriginal=i.minuteMax,this.secondMaxOriginal=i.secondMax,this.millisecMaxOriginal=i.millisecMax,this.microsecMaxOriginal=i.microsecMax),e.settings.timeOnly||l.getTime()===s.getTime()?(this._defaults.hourMax=r.getHours(),this.hour>=this._defaults.hourMax?(this.hour=this._defaults.hourMax,this._defaults.minuteMax=r.getMinutes(),this.minute>=this._defaults.minuteMax?(this.minute=this._defaults.minuteMax,this._defaults.secondMax=r.getSeconds(),this.second>=this._defaults.secondMax?(this.second=this._defaults.secondMax,this._defaults.millisecMax=r.getMilliseconds(),this.millisec>=this._defaults.millisecMax?(this.millisec=this._defaults.millisecMax,this._defaults.microsecMax=r.getMicroseconds()):(this.microsec>this._defaults.microsecMax&&(this.microsec=this._defaults.microsecMax),this._defaults.microsecMax=this.microsecMaxOriginal)):(this._defaults.millisecMax=this.millisecMaxOriginal,this._defaults.microsecMax=this.microsecMaxOriginal)):(this._defaults.secondMax=this.secondMaxOriginal,this._defaults.millisecMax=this.millisecMaxOriginal,this._defaults.microsecMax=this.microsecMaxOriginal)):(this._defaults.minuteMax=this.minuteMaxOriginal,this._defaults.secondMax=this.secondMaxOriginal,this._defaults.millisecMax=this.millisecMaxOriginal,this._defaults.microsecMax=this.microsecMaxOriginal)):(this._defaults.hourMax=this.hourMaxOriginal,this._defaults.minuteMax=this.minuteMaxOriginal,this._defaults.secondMax=this.secondMaxOriginal,this._defaults.millisecMax=this.millisecMaxOriginal,this._defaults.microsecMax=this.microsecMaxOriginal)}if(null!==e.settings.minTime){var o=new Date("01/01/1970 "+e.settings.minTime);this.hour<o.getHours()?(this.hour=this._defaults.hourMin=o.getHours(),this.minute=this._defaults.minuteMin=o.getMinutes()):this.hour===o.getHours()&&this.minute<o.getMinutes()?this.minute=this._defaults.minuteMin=o.getMinutes():this._defaults.hourMin<o.getHours()?(this._defaults.hourMin=o.getHours(),this._defaults.minuteMin=o.getMinutes()):this._defaults.minuteMin=this._defaults.hourMin===o.getHours()===this.hour&&this._defaults.minuteMin<o.getMinutes()?o.getMinutes():0}if(null!==e.settings.maxTime){var c=new Date("01/01/1970 "+e.settings.maxTime);this.hour>c.getHours()?(this.hour=this._defaults.hourMax=c.getHours(),this.minute=this._defaults.minuteMax=c.getMinutes()):this.hour===c.getHours()&&this.minute>c.getMinutes()?this.minute=this._defaults.minuteMax=c.getMinutes():this._defaults.hourMax>c.getHours()?(this._defaults.hourMax=c.getHours(),this._defaults.minuteMax=c.getMinutes()):this._defaults.minuteMax=this._defaults.hourMax===c.getHours()===this.hour&&this._defaults.minuteMax>c.getMinutes()?c.getMinutes():59}if(void 0!==t&&t===!0){var u=parseInt(this._defaults.hourMax-(this._defaults.hourMax-this._defaults.hourMin)%this._defaults.stepHour,10),m=parseInt(this._defaults.minuteMax-(this._defaults.minuteMax-this._defaults.minuteMin)%this._defaults.stepMinute,10),d=parseInt(this._defaults.secondMax-(this._defaults.secondMax-this._defaults.secondMin)%this._defaults.stepSecond,10),h=parseInt(this._defaults.millisecMax-(this._defaults.millisecMax-this._defaults.millisecMin)%this._defaults.stepMillisec,10),p=parseInt(this._defaults.microsecMax-(this._defaults.microsecMax-this._defaults.microsecMin)%this._defaults.stepMicrosec,10);this.hour_slider&&(this.control.options(this,this.hour_slider,"hour",{min:this._defaults.hourMin,max:u,step:this._defaults.stepHour}),this.control.value(this,this.hour_slider,"hour",this.hour-this.hour%this._defaults.stepHour)),this.minute_slider&&(this.control.options(this,this.minute_slider,"minute",{min:this._defaults.minuteMin,max:m,step:this._defaults.stepMinute}),this.control.value(this,this.minute_slider,"minute",this.minute-this.minute%this._defaults.stepMinute)),this.second_slider&&(this.control.options(this,this.second_slider,"second",{min:this._defaults.secondMin,max:d,step:this._defaults.stepSecond}),this.control.value(this,this.second_slider,"second",this.second-this.second%this._defaults.stepSecond)),this.millisec_slider&&(this.control.options(this,this.millisec_slider,"millisec",{min:this._defaults.millisecMin,max:h,step:this._defaults.stepMillisec}),this.control.value(this,this.millisec_slider,"millisec",this.millisec-this.millisec%this._defaults.stepMillisec)),this.microsec_slider&&(this.control.options(this,this.microsec_slider,"microsec",{min:this._defaults.microsecMin,max:p,step:this._defaults.stepMicrosec}),this.control.value(this,this.microsec_slider,"microsec",this.microsec-this.microsec%this._defaults.stepMicrosec))}}},_onTimeChange:function(){if(this._defaults.showTimepicker){var e=this.hour_slider?this.control.value(this,this.hour_slider,"hour"):!1,t=this.minute_slider?this.control.value(this,this.minute_slider,"minute"):!1,i=this.second_slider?this.control.value(this,this.second_slider,"second"):!1,s=this.millisec_slider?this.control.value(this,this.millisec_slider,"millisec"):!1,a=this.microsec_slider?this.control.value(this,this.microsec_slider,"microsec"):!1,n=this.timezone_select?this.timezone_select.val():!1,r=this._defaults,l=r.pickerTimeFormat||r.timeFormat,o=r.pickerTimeSuffix||r.timeSuffix;"object"==typeof e&&(e=!1),"object"==typeof t&&(t=!1),"object"==typeof i&&(i=!1),"object"==typeof s&&(s=!1),"object"==typeof a&&(a=!1),"object"==typeof n&&(n=!1),e!==!1&&(e=parseInt(e,10)),t!==!1&&(t=parseInt(t,10)),i!==!1&&(i=parseInt(i,10)),s!==!1&&(s=parseInt(s,10)),a!==!1&&(a=parseInt(a,10)),n!==!1&&(n=""+n);var c=r[12>e?"amNames":"pmNames"][0],u=e!==parseInt(this.hour,10)||t!==parseInt(this.minute,10)||i!==parseInt(this.second,10)||s!==parseInt(this.millisec,10)||a!==parseInt(this.microsec,10)||this.ampm.length>0&&12>e!=(-1!==$.inArray(this.ampm.toUpperCase(),this.amNames))||null!==this.timezone&&n!==""+this.timezone;u&&(e!==!1&&(this.hour=e),t!==!1&&(this.minute=t),i!==!1&&(this.second=i),s!==!1&&(this.millisec=s),a!==!1&&(this.microsec=a),n!==!1&&(this.timezone=n),this.inst||(this.inst=$.datepicker._getInst(this.$input[0])),this._limitMinMaxDateTime(this.inst,!0)),this.support.ampm&&(this.ampm=c),this.formattedTime=$.datepicker.formatTime(r.timeFormat,this,r),this.$timeObj&&(l===r.timeFormat?this.$timeObj.text(this.formattedTime+o):this.$timeObj.text($.datepicker.formatTime(l,this,r)+o)),this.timeDefined=!0,u&&this._updateDateTime()}},_onSelectHandler:function(){var e=this._defaults.onSelect||this.inst.settings.onSelect,t=this.$input?this.$input[0]:null;e&&t&&e.apply(t,[this.formattedDateTime,this])},_updateDateTime:function(e){e=this.inst||e;var t=e.currentYear>0?new Date(e.currentYear,e.currentMonth,e.currentDay):new Date(e.selectedYear,e.selectedMonth,e.selectedDay),i=$.datepicker._daylightSavingAdjust(t),s=$.datepicker._get(e,"dateFormat"),a=$.datepicker._getFormatConfig(e),n=null!==i&&this.timeDefined;this.formattedDate=$.datepicker.formatDate(s,null===i?new Date:i,a);var r=this.formattedDate;if(""===e.lastVal&&(e.currentYear=e.selectedYear,e.currentMonth=e.selectedMonth,e.currentDay=e.selectedDay),this._defaults.timeOnly===!0&&this._defaults.timeOnlyShowDate===!1?r=this.formattedTime:(this._defaults.timeOnly!==!0&&(this._defaults.alwaysSetTime||n)||this._defaults.timeOnly===!0&&this._defaults.timeOnlyShowDate===!0)&&(r+=this._defaults.separator+this.formattedTime+this._defaults.timeSuffix),this.formattedDateTime=r,this._defaults.showTimepicker)if(this.$altInput&&this._defaults.timeOnly===!1&&this._defaults.altFieldTimeOnly===!0)this.$altInput.val(this.formattedTime),this.$input.val(this.formattedDate);else if(this.$altInput){this.$input.val(r);var l="",o=null!==this._defaults.altSeparator?this._defaults.altSeparator:this._defaults.separator,c=null!==this._defaults.altTimeSuffix?this._defaults.altTimeSuffix:this._defaults.timeSuffix;this._defaults.timeOnly||(l=this._defaults.altFormat?$.datepicker.formatDate(this._defaults.altFormat,null===i?new Date:i,a):this.formattedDate,l&&(l+=o)),l+=null!==this._defaults.altTimeFormat?$.datepicker.formatTime(this._defaults.altTimeFormat,this,this._defaults)+c:this.formattedTime+c,this.$altInput.val(l)}else this.$input.val(r);else this.$input.val(this.formattedDate);this.$input.trigger("change")},_onFocus:function(){if(!this.$input.val()&&this._defaults.defaultValue){this.$input.val(this._defaults.defaultValue);var e=$.datepicker._getInst(this.$input.get(0)),t=$.datepicker._get(e,"timepicker");if(t&&t._defaults.timeOnly&&e.input.val()!==e.lastVal)try{$.datepicker._updateDatepicker(e)}catch(i){$.timepicker.log(i)}}},_controls:{slider:{create:function(e,t,i,s,a,n,r){var l=e._defaults.isRTL;return t.prop("slide",null).slider({orientation:"horizontal",value:l?-1*s:s,min:l?-1*n:a,max:l?-1*a:n,step:r,slide:function(t,s){e.control.value(e,$(this),i,l?-1*s.value:s.value),e._onTimeChange()},stop:function(){e._onSelectHandler()}})},options:function(e,t,i,s,a){if(e._defaults.isRTL){if("string"==typeof s)return"min"===s||"max"===s?void 0!==a?t.slider(s,-1*a):Math.abs(t.slider(s)):t.slider(s);var n=s.min,r=s.max;return s.min=s.max=null,void 0!==n&&(s.max=-1*n),void 0!==r&&(s.min=-1*r),t.slider(s)}return"string"==typeof s&&void 0!==a?t.slider(s,a):t.slider(s)},value:function(e,t,i,s){return e._defaults.isRTL?void 0!==s?t.slider("value",-1*s):Math.abs(t.slider("value")):void 0!==s?t.slider("value",s):t.slider("value")}},select:{create:function(e,t,i,s,a,n,r){for(var l='<select class="ui-timepicker-select ui-state-default ui-corner-all" data-unit="'+i+'" data-min="'+a+'" data-max="'+n+'" data-step="'+r+'">',o=e._defaults.pickerTimeFormat||e._defaults.timeFormat,c=a;n>=c;c+=r)l+='<option value="'+c+'"'+(c===s?" selected":"")+">",l+="hour"===i?$.datepicker.formatTime($.trim(o.replace(/[^ht ]/gi,"")),{hour:c},e._defaults):"millisec"===i||"microsec"===i||c>=10?c:"0"+(""+c),l+="</option>";return l+="</select>",t.children("select").remove(),$(l).appendTo(t).change(function(){e._onTimeChange(),e._onSelectHandler()}),t},options:function(e,t,i,s,a){var n={},r=t.children("select");if("string"==typeof s){if(void 0===a)return r.data(s);n[s]=a}else n=s;return e.control.create(e,t,r.data("unit"),r.val(),n.min||r.data("min"),n.max||r.data("max"),n.step||r.data("step"))},value:function(e,t,i,s){var a=t.children("select");return void 0!==s?a.val(s):a.val()}}}}),$.fn.extend({timepicker:function(e){e=e||{};var t=Array.prototype.slice.call(arguments);return"object"==typeof e&&(t[0]=$.extend(e,{timeOnly:!0})),$(this).each(function(){$.fn.datetimepicker.apply($(this),t)})},datetimepicker:function(e){e=e||{};var t=arguments;return"string"==typeof e?"getDate"===e||"option"===e&&2===t.length&&"string"==typeof t[1]?$.fn.datepicker.apply($(this[0]),t):this.each(function(){var e=$(this);e.datepicker.apply(e,t)}):this.each(function(){var t=$(this);t.datepicker($.timepicker._newInst(t,e)._defaults)})}}),$.datepicker.parseDateTime=function(e,t,i,s,a){var n=parseDateTimeInternal(e,t,i,s,a);if(n.timeObj){var r=n.timeObj;n.date.setHours(r.hour,r.minute,r.second,r.millisec),n.date.setMicroseconds(r.microsec)}return n.date},$.datepicker.parseTime=function(e,t,i){var s=extendRemove(extendRemove({},$.timepicker._defaults),i||{});-1!==e.replace(/\'.*?\'/g,"").indexOf("Z");var a=function(e,t,i){var s,a=function(e,t){var i=[];return e&&$.merge(i,e),t&&$.merge(i,t),i=$.map(i,function(e){return e.replace(/[.*+?|()\[\]{}\\]/g,"\\$&")}),"("+i.join("|")+")?"},n=function(e){var t=e.toLowerCase().match(/(h{1,2}|m{1,2}|s{1,2}|l{1}|c{1}|t{1,2}|z|'.*?')/g),i={h:-1,m:-1,s:-1,l:-1,c:-1,t:-1,z:-1};if(t)for(var s=0;t.length>s;s++)-1===i[(""+t[s]).charAt(0)]&&(i[(""+t[s]).charAt(0)]=s+1);return i},r="^"+(""+e).replace(/([hH]{1,2}|mm?|ss?|[tT]{1,2}|[zZ]|[lc]|'.*?')/g,function(e){var t=e.length;switch(e.charAt(0).toLowerCase()){case"h":return 1===t?"(\\d?\\d)":"(\\d{"+t+"})";case"m":return 1===t?"(\\d?\\d)":"(\\d{"+t+"})";case"s":return 1===t?"(\\d?\\d)":"(\\d{"+t+"})";case"l":return"(\\d?\\d?\\d)";case"c":return"(\\d?\\d?\\d)";case"z":return"(z|[-+]\\d\\d:?\\d\\d|\\S+)?";case"t":return a(i.amNames,i.pmNames);default:return"("+e.replace(/\'/g,"").replace(/(\.|\$|\^|\\|\/|\(|\)|\[|\]|\?|\+|\*)/g,function(e){return"\\"+e})+")?"}}).replace(/\s/g,"\\s?")+i.timeSuffix+"$",l=n(e),o="";s=t.match(RegExp(r,"i"));var c={hour:0,minute:0,second:0,millisec:0,microsec:0};return s?(-1!==l.t&&(void 0===s[l.t]||0===s[l.t].length?(o="",c.ampm=""):(o=-1!==$.inArray(s[l.t].toUpperCase(),i.amNames)?"AM":"PM",c.ampm=i["AM"===o?"amNames":"pmNames"][0])),-1!==l.h&&(c.hour="AM"===o&&"12"===s[l.h]?0:"PM"===o&&"12"!==s[l.h]?parseInt(s[l.h],10)+12:Number(s[l.h])),-1!==l.m&&(c.minute=Number(s[l.m])),-1!==l.s&&(c.second=Number(s[l.s])),-1!==l.l&&(c.millisec=Number(s[l.l])),-1!==l.c&&(c.microsec=Number(s[l.c])),-1!==l.z&&void 0!==s[l.z]&&(c.timezone=$.timepicker.timezoneOffsetNumber(s[l.z])),c):!1},n=function(e,t,i){try{var s=new Date("2012-01-01 "+t);if(isNaN(s.getTime())&&(s=new Date("2012-01-01T"+t),isNaN(s.getTime())&&(s=new Date("01/01/2012 "+t),isNaN(s.getTime()))))throw"Unable to parse time with native Date: "+t;return{hour:s.getHours(),minute:s.getMinutes(),second:s.getSeconds(),millisec:s.getMilliseconds(),microsec:s.getMicroseconds(),timezone:-1*s.getTimezoneOffset()}}catch(n){try{return a(e,t,i)}catch(r){$.timepicker.log("Unable to parse \ntimeString: "+t+"\ntimeFormat: "+e)}}return!1};return"function"==typeof s.parse?s.parse(e,t,s):"loose"===s.parse?n(e,t,s):a(e,t,s)},$.datepicker.formatTime=function(e,t,i){i=i||{},i=$.extend({},$.timepicker._defaults,i),t=$.extend({hour:0,minute:0,second:0,millisec:0,microsec:0,timezone:null},t);var s=e,a=i.amNames[0],n=parseInt(t.hour,10);return n>11&&(a=i.pmNames[0]),s=s.replace(/(?:HH?|hh?|mm?|ss?|[tT]{1,2}|[zZ]|[lc]|'.*?')/g,function(e){switch(e){case"HH":return("0"+n).slice(-2);case"H":return n;case"hh":return("0"+convert24to12(n)).slice(-2);case"h":return convert24to12(n);case"mm":return("0"+t.minute).slice(-2);case"m":return t.minute;case"ss":return("0"+t.second).slice(-2);case"s":return t.second;case"l":return("00"+t.millisec).slice(-3);case"c":return("00"+t.microsec).slice(-3);case"z":return $.timepicker.timezoneOffsetString(null===t.timezone?i.timezone:t.timezone,!1);case"Z":return $.timepicker.timezoneOffsetString(null===t.timezone?i.timezone:t.timezone,!0);case"T":return a.charAt(0).toUpperCase();case"TT":return a.toUpperCase();case"t":return a.charAt(0).toLowerCase();case"tt":return a.toLowerCase();default:return e.replace(/'/g,"")}})},$.datepicker._base_selectDate=$.datepicker._selectDate,$.datepicker._selectDate=function(e,t){var i,s=this._getInst($(e)[0]),a=this._get(s,"timepicker");a&&s.settings.showTimepicker?(a._limitMinMaxDateTime(s,!0),i=s.inline,s.inline=s.stay_open=!0,this._base_selectDate(e,t),s.inline=i,s.stay_open=!1,this._notifyChange(s),this._updateDatepicker(s)):this._base_selectDate(e,t)},$.datepicker._base_updateDatepicker=$.datepicker._updateDatepicker,$.datepicker._updateDatepicker=function(e){var t=e.input[0];if(!($.datepicker._curInst&&$.datepicker._curInst!==e&&$.datepicker._datepickerShowing&&$.datepicker._lastInput!==t||"boolean"==typeof e.stay_open&&e.stay_open!==!1)){this._base_updateDatepicker(e);var i=this._get(e,"timepicker");i&&i._addTimePicker(e)}},$.datepicker._base_doKeyPress=$.datepicker._doKeyPress,$.datepicker._doKeyPress=function(e){var t=$.datepicker._getInst(e.target),i=$.datepicker._get(t,"timepicker");if(i&&$.datepicker._get(t,"constrainInput")){var s=i.support.ampm,a=null!==i._defaults.showTimezone?i._defaults.showTimezone:i.support.timezone,n=$.datepicker._possibleChars($.datepicker._get(t,"dateFormat")),r=(""+i._defaults.timeFormat).replace(/[hms]/g,"").replace(/TT/g,s?"APM":"").replace(/Tt/g,s?"AaPpMm":"").replace(/tT/g,s?"AaPpMm":"").replace(/T/g,s?"AP":"").replace(/tt/g,s?"apm":"").replace(/t/g,s?"ap":"")+" "+i._defaults.separator+i._defaults.timeSuffix+(a?i._defaults.timezoneList.join(""):"")+i._defaults.amNames.join("")+i._defaults.pmNames.join("")+n,l=String.fromCharCode(void 0===e.charCode?e.keyCode:e.charCode);return e.ctrlKey||" ">l||!n||r.indexOf(l)>-1}return $.datepicker._base_doKeyPress(e)},$.datepicker._base_updateAlternate=$.datepicker._updateAlternate,$.datepicker._updateAlternate=function(e){var t=this._get(e,"timepicker");if(t){var i=t._defaults.altField;if(i){var s=(t._defaults.altFormat||t._defaults.dateFormat,this._getDate(e)),a=$.datepicker._getFormatConfig(e),n="",r=t._defaults.altSeparator?t._defaults.altSeparator:t._defaults.separator,l=t._defaults.altTimeSuffix?t._defaults.altTimeSuffix:t._defaults.timeSuffix,o=null!==t._defaults.altTimeFormat?t._defaults.altTimeFormat:t._defaults.timeFormat;n+=$.datepicker.formatTime(o,t,t._defaults)+l,t._defaults.timeOnly||t._defaults.altFieldTimeOnly||null===s||(n=t._defaults.altFormat?$.datepicker.formatDate(t._defaults.altFormat,s,a)+r+n:t.formattedDate+r+n),$(i).val(e.input.val()?n:"")}}else $.datepicker._base_updateAlternate(e)},$.datepicker._base_doKeyUp=$.datepicker._doKeyUp,$.datepicker._doKeyUp=function(e){var t=$.datepicker._getInst(e.target),i=$.datepicker._get(t,"timepicker");if(i&&i._defaults.timeOnly&&t.input.val()!==t.lastVal)try{$.datepicker._updateDatepicker(t)}catch(s){$.timepicker.log(s)}return $.datepicker._base_doKeyUp(e)},$.datepicker._base_gotoToday=$.datepicker._gotoToday,$.datepicker._gotoToday=function(e){var t=this._getInst($(e)[0]);t.dpDiv,this._base_gotoToday(e);var i=this._get(t,"timepicker");selectLocalTimezone(i);var s=new Date;this._setTime(t,s),this._setDate(t,s)},$.datepicker._disableTimepickerDatepicker=function(e){var t=this._getInst(e);if(t){var i=this._get(t,"timepicker");$(e).datepicker("getDate"),i&&(t.settings.showTimepicker=!1,i._defaults.showTimepicker=!1,i._updateDateTime(t))}},$.datepicker._enableTimepickerDatepicker=function(e){var t=this._getInst(e);if(t){var i=this._get(t,"timepicker");$(e).datepicker("getDate"),i&&(t.settings.showTimepicker=!0,i._defaults.showTimepicker=!0,i._addTimePicker(t),i._updateDateTime(t))}},$.datepicker._setTime=function(e,t){var i=this._get(e,"timepicker");if(i){var s=i._defaults; +i.hour=t?t.getHours():s.hour,i.minute=t?t.getMinutes():s.minute,i.second=t?t.getSeconds():s.second,i.millisec=t?t.getMilliseconds():s.millisec,i.microsec=t?t.getMicroseconds():s.microsec,i._limitMinMaxDateTime(e,!0),i._onTimeChange(),i._updateDateTime(e)}},$.datepicker._setTimeDatepicker=function(e,t,i){var s=this._getInst(e);if(s){var a=this._get(s,"timepicker");if(a){this._setDateFromField(s);var n;t&&("string"==typeof t?(a._parseTime(t,i),n=new Date,n.setHours(a.hour,a.minute,a.second,a.millisec),n.setMicroseconds(a.microsec)):(n=new Date(t.getTime()),n.setMicroseconds(t.getMicroseconds())),"Invalid Date"==""+n&&(n=void 0),this._setTime(s,n))}}},$.datepicker._base_setDateDatepicker=$.datepicker._setDateDatepicker,$.datepicker._setDateDatepicker=function(e,t){var i=this._getInst(e),s=t;if(i){"string"==typeof t&&(s=new Date(t),s.getTime()||(this._base_setDateDatepicker.apply(this,arguments),s=$(e).datepicker("getDate")));var a,n=this._get(i,"timepicker");s instanceof Date?(a=new Date(s.getTime()),a.setMicroseconds(s.getMicroseconds())):a=s,n&&a&&(n.support.timezone||null!==n._defaults.timezone||(n.timezone=-1*a.getTimezoneOffset()),s=$.timepicker.timezoneAdjust(s,n.timezone),a=$.timepicker.timezoneAdjust(a,n.timezone)),this._updateDatepicker(i),this._base_setDateDatepicker.apply(this,arguments),this._setTimeDatepicker(e,a,!0)}},$.datepicker._base_getDateDatepicker=$.datepicker._getDateDatepicker,$.datepicker._getDateDatepicker=function(e,t){var i=this._getInst(e);if(i){var s=this._get(i,"timepicker");if(s){void 0===i.lastVal&&this._setDateFromField(i,t);var a=this._getDate(i);return a&&s._parseTime($(e).val(),s.timeOnly)&&(a.setHours(s.hour,s.minute,s.second,s.millisec),a.setMicroseconds(s.microsec),null!=s.timezone&&(s.support.timezone||null!==s._defaults.timezone||(s.timezone=-1*a.getTimezoneOffset()),a=$.timepicker.timezoneAdjust(a,s.timezone))),a}return this._base_getDateDatepicker(e,t)}},$.datepicker._base_parseDate=$.datepicker.parseDate,$.datepicker.parseDate=function(e,t,i){var s;try{s=this._base_parseDate(e,t,i)}catch(a){if(!(a.indexOf(":")>=0))throw a;s=this._base_parseDate(e,t.substring(0,t.length-(a.length-a.indexOf(":")-2)),i),$.timepicker.log("Error parsing the date string: "+a+"\ndate string = "+t+"\ndate format = "+e)}return s},$.datepicker._base_formatDate=$.datepicker._formatDate,$.datepicker._formatDate=function(e){var t=this._get(e,"timepicker");return t?(t._updateDateTime(e),t.$input.val()):this._base_formatDate(e)},$.datepicker._base_optionDatepicker=$.datepicker._optionDatepicker,$.datepicker._optionDatepicker=function(e,t,i){var s,a=this._getInst(e);if(!a)return null;var n=this._get(a,"timepicker");if(n){var r,l,o,c,u=null,m=null,d=null,h=n._defaults.evnts,p={};if("string"==typeof t){if("minDate"===t||"minDateTime"===t)u=i;else if("maxDate"===t||"maxDateTime"===t)m=i;else if("onSelect"===t)d=i;else if(h.hasOwnProperty(t)){if(i===void 0)return h[t];p[t]=i,s={}}}else if("object"==typeof t){t.minDate?u=t.minDate:t.minDateTime?u=t.minDateTime:t.maxDate?m=t.maxDate:t.maxDateTime&&(m=t.maxDateTime);for(r in h)h.hasOwnProperty(r)&&t[r]&&(p[r]=t[r])}for(r in p)p.hasOwnProperty(r)&&(h[r]=p[r],s||(s=$.extend({},t)),delete s[r]);if(s&&isEmptyObject(s))return;if(u?(u=0===u?new Date:new Date(u),n._defaults.minDate=u,n._defaults.minDateTime=u):m?(m=0===m?new Date:new Date(m),n._defaults.maxDate=m,n._defaults.maxDateTime=m):d&&(n._defaults.onSelect=d),u||m)return c=$(e),o=c.datetimepicker("getDate"),l=this._base_optionDatepicker.call($.datepicker,e,s||t,i),c.datetimepicker("setDate",o),l}return void 0===i?this._base_optionDatepicker.call($.datepicker,e,t):this._base_optionDatepicker.call($.datepicker,e,s||t,i)};var isEmptyObject=function(e){var t;for(t in e)if(e.hasOwnProperty(t))return!1;return!0},extendRemove=function(e,t){$.extend(e,t);for(var i in t)(null===t[i]||void 0===t[i])&&(e[i]=t[i]);return e},detectSupport=function(e){var t=e.replace(/'.*?'/g,"").toLowerCase(),i=function(e,t){return-1!==e.indexOf(t)?!0:!1};return{hour:i(t,"h"),minute:i(t,"m"),second:i(t,"s"),millisec:i(t,"l"),microsec:i(t,"c"),timezone:i(t,"z"),ampm:i(t,"t")&&i(e,"h"),iso8601:i(e,"Z")}},convert24to12=function(e){return e%=12,0===e&&(e=12),e+""},computeEffectiveSetting=function(e,t){return e&&e[t]?e[t]:$.timepicker._defaults[t]},splitDateTime=function(e,t){var i=computeEffectiveSetting(t,"separator"),s=computeEffectiveSetting(t,"timeFormat"),a=s.split(i),n=a.length,r=e.split(i),l=r.length;return l>1?{dateString:r.splice(0,l-n).join(i),timeString:r.splice(0,n).join(i)}:{dateString:e,timeString:""}},parseDateTimeInternal=function(e,t,i,s,a){var n,r,l;if(r=splitDateTime(i,a),n=$.datepicker._base_parseDate(e,r.dateString,s),""===r.timeString)return{date:n};if(l=$.datepicker.parseTime(t,r.timeString,a),!l)throw"Wrong time format";return{date:n,timeObj:l}},selectLocalTimezone=function(e,t){if(e&&e.timezone_select){var i=t||new Date;e.timezone_select.val(-i.getTimezoneOffset())}};$.timepicker=new Timepicker,$.timepicker.timezoneOffsetString=function(e,t){if(isNaN(e)||e>840||-720>e)return e;var i=e,s=i%60,a=(i-s)/60,n=t?":":"",r=(i>=0?"+":"-")+("0"+Math.abs(a)).slice(-2)+n+("0"+Math.abs(s)).slice(-2);return"+00:00"===r?"Z":r},$.timepicker.timezoneOffsetNumber=function(e){var t=(""+e).replace(":","");return"Z"===t.toUpperCase()?0:/^(\-|\+)\d{4}$/.test(t)?("-"===t.substr(0,1)?-1:1)*(60*parseInt(t.substr(1,2),10)+parseInt(t.substr(3,2),10)):e},$.timepicker.timezoneAdjust=function(e,t){var i=$.timepicker.timezoneOffsetNumber(t);return isNaN(i)||e.setMinutes(e.getMinutes()+-e.getTimezoneOffset()-i),e},$.timepicker.timeRange=function(e,t,i){return $.timepicker.handleRange("timepicker",e,t,i)},$.timepicker.datetimeRange=function(e,t,i){$.timepicker.handleRange("datetimepicker",e,t,i)},$.timepicker.dateRange=function(e,t,i){$.timepicker.handleRange("datepicker",e,t,i)},$.timepicker.handleRange=function(e,t,i,s){function a(a,n){var r=t[e]("getDate"),l=i[e]("getDate"),o=a[e]("getDate");if(null!==r){var c=new Date(r.getTime()),u=new Date(r.getTime());c.setMilliseconds(c.getMilliseconds()+s.minInterval),u.setMilliseconds(u.getMilliseconds()+s.maxInterval),s.minInterval>0&&c>l?i[e]("setDate",c):s.maxInterval>0&&l>u?i[e]("setDate",u):r>l&&n[e]("setDate",o)}}function n(t,i,a){if(t.val()){var n=t[e].call(t,"getDate");null!==n&&s.minInterval>0&&("minDate"===a&&n.setMilliseconds(n.getMilliseconds()+s.minInterval),"maxDate"===a&&n.setMilliseconds(n.getMilliseconds()-s.minInterval)),n.getTime&&i[e].call(i,"option",a,n)}}s=$.extend({},{minInterval:0,maxInterval:0,start:{},end:{}},s);var r=!1;return"timepicker"===e&&(r=!0,e="datetimepicker"),$.fn[e].call(t,$.extend({timeOnly:r,onClose:function(){a($(this),i)},onSelect:function(){n($(this),i,"minDate")}},s,s.start)),$.fn[e].call(i,$.extend({timeOnly:r,onClose:function(){a($(this),t)},onSelect:function(){n($(this),t,"maxDate")}},s,s.end)),a(t,i),n(t,i,"minDate"),n(i,t,"maxDate"),$([t.get(0),i.get(0)])},$.timepicker.log=function(){window.console&&window.console.log.apply(window.console,Array.prototype.slice.call(arguments))},$.timepicker._util={_extendRemove:extendRemove,_isEmptyObject:isEmptyObject,_convert24to12:convert24to12,_detectSupport:detectSupport,_selectLocalTimezone:selectLocalTimezone,_computeEffectiveSetting:computeEffectiveSetting,_splitDateTime:splitDateTime,_parseDateTimeInternal:parseDateTimeInternal},Date.prototype.getMicroseconds||(Date.prototype.microseconds=0,Date.prototype.getMicroseconds=function(){return this.microseconds},Date.prototype.setMicroseconds=function(e){return this.setMilliseconds(this.getMilliseconds()+Math.floor(e/1e3)),this.microseconds=e%1e3,this}),$.timepicker.version="1.5.0"}})(jQuery); \ No newline at end of file diff --git a/http/3rdParty/jquery-2.1.4.min.js b/http/3rdParty/jquery-2.1.4.min.js new file mode 100644 index 0000000..49990d6 --- /dev/null +++ b/http/3rdParty/jquery-2.1.4.min.js @@ -0,0 +1,4 @@ +/*! jQuery v2.1.4 | (c) 2005, 2015 jQuery Foundation, Inc. | jquery.org/license */ +!function(a,b){"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){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l=a.document,m="2.1.4",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},n.extend=n.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||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){return!n.isArray(a)&&a-parseFloat(a)+1>=0},isPlainObject:function(a){return"object"!==n.type(a)||a.nodeType||n.isWindow(a)?!1:a.constructor&&!j.call(a.constructor.prototype,"isPrototypeOf")?!1:!0},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?h[i.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=l.createElement("script"),b.text=a,l.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:g.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;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;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(e=d.call(arguments,2),f=function(){return a.apply(b||this,e.concat(d.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:k}),n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b="length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=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=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,aa=/[+~]/,ba=/'|\\/g,ca=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),da=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ea=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fa){H={apply:E.length?function(a,b){G.apply(a,I.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,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(ba,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+ra(o[l]);w=aa.test(a)&&pa(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$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("div");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=a.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);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 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 pa(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:!1},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=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",ea,!1):e.attachEvent&&e.attachEvent("onunload",ea)),p=!f(g),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="<a id='"+u+"'></a><select id='"+u+"-\f]' msallowcapture=''><option selected=''></option></select>",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.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===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(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,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?la(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):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(U,"='$1']"),!(!c.matchesSelector||!p||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&&D.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.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:X,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(ca,da),a[3]=(a[3]||a[4]||a[5]||"").replace(ca,da),"~="===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 X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.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(ca,da).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("(^|"+L+")"+a+"("+L+"|$)"))&&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(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},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;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/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=J(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(R,"$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(ca,da),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return W.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(ca,da).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:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!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 Z.test(a.nodeName)},input:function(a){return Y.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:oa(function(){return[0]}),last:oa(function(a,b){return[b-1]}),eq:oa(function(a,b,c){return[0>c?c+b:c]}),even:oa(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:oa(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:oa(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:oa(function(a,b,c){for(var d=0>c?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 qa(){}qa.prototype=d.filters=d.pseudos,d.setFilters=new qa,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=S.exec(h)))&&(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=T.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(R," ")}),h=h.slice(c.length));for(g in d.filter)!(e=X[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 ra(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function sa(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function ta(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 ua(a,b,c){for(var d=0,e=b.length;e>d;d++)ga(a,b[d],c);return c}function va(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wa(a,b,c,d,e,f){return d&&!d[u]&&(d=wa(d)),e&&!e[u]&&(e=wa(e,f)),ia(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ua(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:va(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=va(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?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=va(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sa(function(a){return a===b},h,!0),l=sa(function(a){return J(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}];f>i;i++)if(c=d.relative[a[i].type])m=[sa(ta(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wa(i>1&&ta(m),i>1&&ra(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xa(a.slice(i,e)),f>e&&xa(a=a.slice(e)),f>e&&ra(a))}m.push(c)}return ta(m)}function ya(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=va(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&ga.uniqueSort(i)}return k&&(w=v,j=t),r};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=xa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,ya(e,d)),f.selector=a}return f},i=ga.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ca,da),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ca,da),aa.test(j[0].type)&&pa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&ra(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,aa.test(a)&&pa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ja(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){return c?void 0: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){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return g.call(b,a)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=n.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:l,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}return d=l.getElementById(c[2]),d&&d.parentNode&&(this.length=1,this[0]=d),this.context=l,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};A.prototype=n.fn,y=n(l);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?"string"==typeof a?g.call(n(a),this[0]):g.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,"parentNode")},parentsUntil:function(a,b,c){return n.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return n.dir(a,"nextSibling")},prevAll:function(a){return n.dir(a,"previousSibling")},nextUntil:function(a,b,c){return n.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return n.dir(a,"previousSibling",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(C[a]||n.unique(e),B.test(a)&&e.reverse()),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return n.each(a.match(E)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(b=a.memory&&l,c=!0,g=e||0,e=0,f=h.length,d=!0;h&&f>g;g++)if(h[g].apply(l[0],l[1])===!1&&a.stopOnFalse){b=!1;break}d=!1,h&&(i?i.length&&j(i.shift()):b?h=[]:k.disable())},k={add:function(){if(h){var c=h.length;!function g(b){n.each(b,function(b,c){var d=n.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&g(c)})}(arguments),d?f=h.length:b&&(e=c,j(b))}return this},remove:function(){return h&&n.each(arguments,function(a,b){var c;while((c=n.inArray(b,h,c))>-1)h.splice(c,1),d&&(f>=c&&f--,g>=c&&g--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],f=0,this},disable:function(){return h=i=b=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,b||k.disable(),this},locked:function(){return!i},fireWith:function(a,b){return!h||c&&!i||(b=b||[],b=[a,b.slice?b.slice():b],d?i.push(b):j(b)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!c}};return k},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&n.isFunction(a.promise)?e:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(H.resolveWith(l,[n]),n.fn.triggerHandler&&(n(l).triggerHandler("ready"),n(l).off("ready"))))}});function I(){l.removeEventListener("DOMContentLoaded",I,!1),a.removeEventListener("load",I,!1),n.ready()}n.ready.promise=function(b){return H||(H=n.Deferred(),"complete"===l.readyState?setTimeout(n.ready):(l.addEventListener("DOMContentLoaded",I,!1),a.addEventListener("load",I,!1))),H.promise(b)},n.ready.promise();var J=n.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)n.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;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};n.acceptData=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function K(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=n.expando+K.uid++}K.uid=1,K.accepts=n.acceptData,K.prototype={key:function(a){if(!K.accepts(a))return 0;var b={},c=a[this.expando];if(!c){c=K.uid++;try{b[this.expando]={value:c},Object.defineProperties(a,b)}catch(d){b[this.expando]=c,n.extend(a,b)}}return this.cache[c]||(this.cache[c]={}),c},set:function(a,b,c){var d,e=this.key(a),f=this.cache[e];if("string"==typeof b)f[b]=c;else if(n.isEmptyObject(f))n.extend(this.cache[e],b);else for(d in b)f[d]=b[d];return f},get:function(a,b){var c=this.cache[this.key(a)];return void 0===b?c:c[b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=this.key(a),g=this.cache[f];if(void 0===b)this.cache[f]={};else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in g?d=[b,e]:(d=e,d=d in g?[d]:d.match(E)||[])),c=d.length;while(c--)delete g[d[c]]}},hasData:function(a){return!n.isEmptyObject(this.cache[a[this.expando]]||{})},discard:function(a){a[this.expando]&&delete this.cache[a[this.expando]]}};var L=new K,M=new K,N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(O,"-$1").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}M.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return M.hasData(a)||L.hasData(a)},data:function(a,b,c){ +return M.access(a,b,c)},removeData:function(a,b){M.remove(a,b)},_data:function(a,b,c){return L.access(a,b,c)},_removeData:function(a,b){L.remove(a,b)}}),n.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=M.get(f),1===f.nodeType&&!L.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));L.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){M.set(this,a)}):J(this,function(b){var c,d=n.camelCase(a);if(f&&void 0===b){if(c=M.get(f,a),void 0!==c)return c;if(c=M.get(f,d),void 0!==c)return c;if(c=P(f,d,void 0),void 0!==c)return c}else this.each(function(){var c=M.get(this,d);M.set(this,d,b),-1!==a.indexOf("-")&&void 0!==c&&M.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){M.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=L.get(a,b),c&&(!d||n.isArray(c)?d=L.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.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 L.get(a,c)||L.access(a,c,{empty:n.Callbacks("once memory").add(function(){L.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?n.queue(this[0],a):void 0===b?this:this.each(function(){var c=n.queue(this,a,b);n._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&n.dequeue(this,a)})},dequeue:function(a){return this.each(function(){n.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=n.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=L.get(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var Q=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,R=["Top","Right","Bottom","Left"],S=function(a,b){return a=b||a,"none"===n.css(a,"display")||!n.contains(a.ownerDocument,a)},T=/^(?:checkbox|radio)$/i;!function(){var a=l.createDocumentFragment(),b=a.appendChild(l.createElement("div")),c=l.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="<textarea>x</textarea>",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U="undefined";k.focusinBubbles="onfocusin"in a;var V=/^key/,W=/^(?:mouse|pointer|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return l.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof n!==U&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(E)||[""],j=b.length;while(j--)h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g,!1)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&(delete r.handle,L.remove(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,m,o,p=[d||l],q=j.call(b,"type")?b.type:b,r=j.call(b,"namespace")?b.namespace.split("."):[];if(g=h=d=d||l,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+n.event.triggered)&&(q.indexOf(".")>=0&&(r=q.split("."),q=r.shift(),r.sort()),k=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=r.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},e||!o.trigger||o.trigger.apply(d,c)!==!1)){if(!e&&!o.noBubble&&!n.isWindow(d)){for(i=o.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||l)&&p.push(h.defaultView||h.parentWindow||a)}f=0;while((g=p[f++])&&!b.isPropagationStopped())b.type=f>1?i:o.bindType||q,m=(L.get(g,"events")||{})[b.type]&&L.get(g,"handle"),m&&m.apply(g,c),m=k&&g[k],m&&m.apply&&n.acceptData(g)&&(b.result=m.apply(g,c),b.result===!1&&b.preventDefault());return b.type=q,e||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!n.acceptData(d)||k&&n.isFunction(d[q])&&!n.isWindow(d)&&(h=d[k],h&&(d[k]=null),n.event.triggered=q,d[q](),n.event.triggered=void 0,h&&(d[k]=h)),b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(L.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(g.namespace))&&(a.handleObj=g,a.data=g.data,e=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(a.result=e)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!==this;i=i.parentNode||this)if(i.disabled!==!0||"click"!==a.type){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>=0:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,d,e,f=b.button;return null==a.pageX&&null!=b.clientX&&(c=a.target.ownerDocument||l,d=c.documentElement,e=c.body,a.pageX=b.clientX+(d&&d.scrollLeft||e&&e.scrollLeft||0)-(d&&d.clientLeft||e&&e.clientLeft||0),a.pageY=b.clientY+(d&&d.scrollTop||e&&e.scrollTop||0)-(d&&d.clientTop||e&&e.clientTop||0)),a.which||void 0===f||(a.which=1&f?1:2&f?3:4&f?2:0),a}},fix:function(a){if(a[n.expando])return a;var b,c,d,e=a.type,f=a,g=this.fixHooks[e];g||(this.fixHooks[e]=g=W.test(e)?this.mouseHooks:V.test(e)?this.keyHooks:{}),d=g.props?this.props.concat(g.props):this.props,a=new n.Event(f),b=d.length;while(b--)c=d[b],a[c]=f[c];return a.target||(a.target=l),3===a.target.nodeType&&(a.target=a.target.parentNode),g.filter?g.filter(a,f):a},special:{load:{noBubble:!0},focus:{trigger:function(){return this!==_()&&this.focus?(this.focus(),!1):void 0},delegateType:"focusin"},blur:{trigger:function(){return this===_()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return"checkbox"===this.type&&this.click&&n.nodeName(this,"input")?(this.click(),!1):void 0},_default:function(a){return n.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}},simulate:function(a,b,c,d){var e=n.extend(new n.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?n.event.trigger(e,null,b):n.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},n.removeEvent=function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)},n.Event=function(a,b){return this instanceof n.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?Z:$):this.type=a,b&&n.extend(this,b),this.timeStamp=a&&a.timeStamp||n.now(),void(this[n.expando]=!0)):new n.Event(a,b)},n.Event.prototype={isDefaultPrevented:$,isPropagationStopped:$,isImmediatePropagationStopped:$,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=Z,a&&a.preventDefault&&a.preventDefault()},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=Z,a&&a.stopPropagation&&a.stopPropagation()},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=Z,a&&a.stopImmediatePropagation&&a.stopImmediatePropagation(),this.stopPropagation()}},n.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){n.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return(!e||e!==d&&!n.contains(d,e))&&(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),k.focusinBubbles||n.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){n.event.simulate(b,a.target,n.event.fix(a),!0)};n.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=L.access(d,b);e||d.addEventListener(a,c,!0),L.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=L.access(d,b)-1;e?L.access(d,b,e):(d.removeEventListener(a,c,!0),L.remove(d,b))}}}),n.fn.extend({on:function(a,b,c,d,e){var f,g;if("object"==typeof a){"string"!=typeof b&&(c=c||b,b=void 0);for(g in a)this.on(g,b,c,a[g],e);return this}if(null==c&&null==d?(d=b,c=b=void 0):null==d&&("string"==typeof b?(d=c,c=void 0):(d=c,c=b,b=void 0)),d===!1)d=$;else if(!d)return this;return 1===e&&(f=d,d=function(a){return n().off(a),f.apply(this,arguments)},d.guid=f.guid||(f.guid=n.guid++)),this.each(function(){n.event.add(this,a,d,c,b)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,n(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=$),this.each(function(){n.event.remove(this,a,c,b)})},trigger:function(a,b){return this.each(function(){n.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?n.event.trigger(a,b,c,!0):void 0}});var aa=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,ba=/<([\w:]+)/,ca=/<|&#?\w+;/,da=/<(?:script|style|link)/i,ea=/checked\s*(?:[^=]|=\s*.checked.)/i,fa=/^$|\/(?:java|ecma)script/i,ga=/^true\/(.*)/,ha=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,ia={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};ia.optgroup=ia.option,ia.tbody=ia.tfoot=ia.colgroup=ia.caption=ia.thead,ia.th=ia.td;function ja(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function ka(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function la(a){var b=ga.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function ma(a,b){for(var c=0,d=a.length;d>c;c++)L.set(a[c],"globalEval",!b||L.get(b[c],"globalEval"))}function na(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(L.hasData(a)&&(f=L.access(a),g=L.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}M.hasData(a)&&(h=M.access(a),i=n.extend({},h),M.set(b,i))}}function oa(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||"*"):a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function pa(a,b){var c=b.nodeName.toLowerCase();"input"===c&&T.test(a.type)?b.checked=a.checked:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}n.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=oa(h),f=oa(a),d=0,e=f.length;e>d;d++)pa(f[d],g[d]);if(b)if(c)for(f=f||oa(a),g=g||oa(h),d=0,e=f.length;e>d;d++)na(f[d],g[d]);else na(a,h);return g=oa(h,"script"),g.length>0&&ma(g,!i&&oa(a,"script")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,o=a.length;o>m;m++)if(e=a[m],e||0===e)if("object"===n.type(e))n.merge(l,e.nodeType?[e]:e);else if(ca.test(e)){f=f||k.appendChild(b.createElement("div")),g=(ba.exec(e)||["",""])[1].toLowerCase(),h=ia[g]||ia._default,f.innerHTML=h[1]+e.replace(aa,"<$1></$2>")+h[2],j=h[0];while(j--)f=f.lastChild;n.merge(l,f.childNodes),f=k.firstChild,f.textContent=""}else l.push(b.createTextNode(e));k.textContent="",m=0;while(e=l[m++])if((!d||-1===n.inArray(e,d))&&(i=n.contains(e.ownerDocument,e),f=oa(k.appendChild(e),"script"),i&&ma(f),c)){j=0;while(e=f[j++])fa.test(e.type||"")&&c.push(e)}return k},cleanData:function(a){for(var b,c,d,e,f=n.event.special,g=0;void 0!==(c=a[g]);g++){if(n.acceptData(c)&&(e=c[L.expando],e&&(b=L.cache[e]))){if(b.events)for(d in b.events)f[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);L.cache[e]&&delete L.cache[e]}delete M.cache[c[M.expando]]}}}),n.fn.extend({text:function(a){return J(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=a)})},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=ja(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=ja(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(oa(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&ma(oa(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(oa(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return J(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!da.test(a)&&!ia[(ba.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(aa,"<$1></$2>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(oa(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(oa(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,m=this,o=l-1,p=a[0],q=n.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&ea.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(c=n.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(f=n.map(oa(c,"script"),ka),g=f.length;l>j;j++)h=c,j!==o&&(h=n.clone(h,!0,!0),g&&n.merge(f,oa(h,"script"))),b.call(this[j],h,j);if(g)for(i=f[f.length-1].ownerDocument,n.map(f,la),j=0;g>j;j++)h=f[j],fa.test(h.type||"")&&!L.access(h,"globalEval")&&n.contains(i,h)&&(h.src?n._evalUrl&&n._evalUrl(h.src):n.globalEval(h.textContent.replace(ha,"")))}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),g=e.length-1,h=0;g>=h;h++)c=h===g?this:this.clone(!0),n(e[h])[b](c),f.apply(d,c.get());return this.pushStack(d)}});var qa,ra={};function sa(b,c){var d,e=n(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:n.css(e[0],"display");return e.detach(),f}function ta(a){var b=l,c=ra[a];return c||(c=sa(a,b),"none"!==c&&c||(qa=(qa||n("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=qa[0].contentDocument,b.write(),b.close(),c=sa(a,b),qa.detach()),ra[a]=c),c}var ua=/^margin/,va=new RegExp("^("+Q+")(?!px)[a-z%]+$","i"),wa=function(b){return b.ownerDocument.defaultView.opener?b.ownerDocument.defaultView.getComputedStyle(b,null):a.getComputedStyle(b,null)};function xa(a,b,c){var d,e,f,g,h=a.style;return c=c||wa(a),c&&(g=c.getPropertyValue(b)||c[b]),c&&(""!==g||n.contains(a.ownerDocument,a)||(g=n.style(a,b)),va.test(g)&&ua.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 ya(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}!function(){var b,c,d=l.documentElement,e=l.createElement("div"),f=l.createElement("div");if(f.style){f.style.backgroundClip="content-box",f.cloneNode(!0).style.backgroundClip="",k.clearCloneStyle="content-box"===f.style.backgroundClip,e.style.cssText="border:0;width:0;height:0;top:0;left:-9999px;margin-top:1px;position:absolute",e.appendChild(f);function g(){f.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;margin-top:1%;top:1%;border:1px;padding:1px;width:4px;position:absolute",f.innerHTML="",d.appendChild(e);var g=a.getComputedStyle(f,null);b="1%"!==g.top,c="4px"===g.width,d.removeChild(e)}a.getComputedStyle&&n.extend(k,{pixelPosition:function(){return g(),b},boxSizingReliable:function(){return null==c&&g(),c},reliableMarginRight:function(){var b,c=f.appendChild(l.createElement("div"));return c.style.cssText=f.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",c.style.marginRight=c.style.width="0",f.style.width="1px",d.appendChild(e),b=!parseFloat(a.getComputedStyle(c,null).marginRight),d.removeChild(e),f.removeChild(c),b}})}}(),n.swap=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};var za=/^(none|table(?!-c[ea]).+)/,Aa=new RegExp("^("+Q+")(.*)$","i"),Ba=new RegExp("^([+-])=("+Q+")","i"),Ca={position:"absolute",visibility:"hidden",display:"block"},Da={letterSpacing:"0",fontWeight:"400"},Ea=["Webkit","O","Moz","ms"];function Fa(a,b){if(b in a)return b;var c=b[0].toUpperCase()+b.slice(1),d=b,e=Ea.length;while(e--)if(b=Ea[e]+c,b in a)return b;return d}function Ga(a,b,c){var d=Aa.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function Ha(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=n.css(a,c+R[f],!0,e)),d?("content"===c&&(g-=n.css(a,"padding"+R[f],!0,e)),"margin"!==c&&(g-=n.css(a,"border"+R[f]+"Width",!0,e))):(g+=n.css(a,"padding"+R[f],!0,e),"padding"!==c&&(g+=n.css(a,"border"+R[f]+"Width",!0,e)));return g}function Ia(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=wa(a),g="border-box"===n.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=xa(a,b,f),(0>e||null==e)&&(e=a.style[b]),va.test(e))return e;d=g&&(k.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+Ha(a,b,c||(g?"border":"content"),d,f)+"px"}function Ja(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=L.get(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&S(d)&&(f[g]=L.access(d,"olddisplay",ta(d.nodeName)))):(e=S(d),"none"===c&&e||L.set(d,"olddisplay",e?c:n.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}n.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=xa(a,"opacity");return""===c?"1":c}}}},cssNumber:{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=n.camelCase(b),i=a.style;return b=n.cssProps[h]||(n.cssProps[h]=Fa(i,h)),g=n.cssHooks[b]||n.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=Ba.exec(c))&&(c=(e[1]+1)*e[2]+parseFloat(n.css(a,b)),f="number"),null!=c&&c===c&&("number"!==f||n.cssNumber[h]||(c+="px"),k.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=n.camelCase(b);return b=n.cssProps[h]||(n.cssProps[h]=Fa(a.style,h)),g=n.cssHooks[b]||n.cssHooks[h],g&&"get"in g&&(e=g.get(a,!0,c)),void 0===e&&(e=xa(a,b,d)),"normal"===e&&b in Da&&(e=Da[b]),""===c||c?(f=parseFloat(e),c===!0||n.isNumeric(f)?f||0:e):e}}),n.each(["height","width"],function(a,b){n.cssHooks[b]={get:function(a,c,d){return c?za.test(n.css(a,"display"))&&0===a.offsetWidth?n.swap(a,Ca,function(){return Ia(a,b,d)}):Ia(a,b,d):void 0},set:function(a,c,d){var e=d&&wa(a);return Ga(a,c,d?Ha(a,b,d,"border-box"===n.css(a,"boxSizing",!1,e),e):0)}}}),n.cssHooks.marginRight=ya(k.reliableMarginRight,function(a,b){return b?n.swap(a,{display:"inline-block"},xa,[a,"marginRight"]):void 0}),n.each({margin:"",padding:"",border:"Width"},function(a,b){n.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+R[d]+b]=f[d]||f[d-2]||f[0];return e}},ua.test(a)||(n.cssHooks[a+b].set=Ga)}),n.fn.extend({css:function(a,b){return J(this,function(a,b,c){var d,e,f={},g=0;if(n.isArray(b)){for(d=wa(a),e=b.length;e>g;g++)f[b[g]]=n.css(a,b[g],!1,d);return f}return void 0!==c?n.style(a,b,c):n.css(a,b)},a,b,arguments.length>1)},show:function(){return Ja(this,!0)},hide:function(){return Ja(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){S(this)?n(this).show():n(this).hide()})}});function Ka(a,b,c,d,e){return new Ka.prototype.init(a,b,c,d,e)}n.Tween=Ka,Ka.prototype={constructor:Ka,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(n.cssNumber[c]?"":"px")},cur:function(){var a=Ka.propHooks[this.prop];return a&&a.get?a.get(this):Ka.propHooks._default.get(this)},run:function(a){var b,c=Ka.propHooks[this.prop];return this.options.duration?this.pos=b=n.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):Ka.propHooks._default.set(this),this}},Ka.prototype.init.prototype=Ka.prototype,Ka.propHooks={_default:{get:function(a){var b;return null==a.elem[a.prop]||a.elem.style&&null!=a.elem.style[a.prop]?(b=n.css(a.elem,a.prop,""),b&&"auto"!==b?b:0):a.elem[a.prop]},set:function(a){n.fx.step[a.prop]?n.fx.step[a.prop](a):a.elem.style&&(null!=a.elem.style[n.cssProps[a.prop]]||n.cssHooks[a.prop])?n.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},Ka.propHooks.scrollTop=Ka.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},n.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},n.fx=Ka.prototype.init,n.fx.step={};var La,Ma,Na=/^(?:toggle|show|hide)$/,Oa=new RegExp("^(?:([+-])=|)("+Q+")([a-z%]*)$","i"),Pa=/queueHooks$/,Qa=[Va],Ra={"*":[function(a,b){var c=this.createTween(a,b),d=c.cur(),e=Oa.exec(b),f=e&&e[3]||(n.cssNumber[a]?"":"px"),g=(n.cssNumber[a]||"px"!==f&&+d)&&Oa.exec(n.css(c.elem,a)),h=1,i=20;if(g&&g[3]!==f){f=f||g[3],e=e||[],g=+d||1;do h=h||".5",g/=h,n.style(c.elem,a,g+f);while(h!==(h=c.cur()/d)&&1!==h&&--i)}return e&&(g=c.start=+g||+d||0,c.unit=f,c.end=e[1]?g+(e[1]+1)*e[2]:+e[2]),c}]};function Sa(){return setTimeout(function(){La=void 0}),La=n.now()}function Ta(a,b){var c,d=0,e={height:a};for(b=b?1:0;4>d;d+=2-b)c=R[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function Ua(a,b,c){for(var d,e=(Ra[b]||[]).concat(Ra["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function Va(a,b,c){var d,e,f,g,h,i,j,k,l=this,m={},o=a.style,p=a.nodeType&&S(a),q=L.get(a,"fxshow");c.queue||(h=n._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,l.always(function(){l.always(function(){h.unqueued--,n.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[o.overflow,o.overflowX,o.overflowY],j=n.css(a,"display"),k="none"===j?L.get(a,"olddisplay")||ta(a.nodeName):j,"inline"===k&&"none"===n.css(a,"float")&&(o.display="inline-block")),c.overflow&&(o.overflow="hidden",l.always(function(){o.overflow=c.overflow[0],o.overflowX=c.overflow[1],o.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],Na.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(p?"hide":"show")){if("show"!==e||!q||void 0===q[d])continue;p=!0}m[d]=q&&q[d]||n.style(a,d)}else j=void 0;if(n.isEmptyObject(m))"inline"===("none"===j?ta(a.nodeName):j)&&(o.display=j);else{q?"hidden"in q&&(p=q.hidden):q=L.access(a,"fxshow",{}),f&&(q.hidden=!p),p?n(a).show():l.done(function(){n(a).hide()}),l.done(function(){var b;L.remove(a,"fxshow");for(b in m)n.style(a,b,m[b])});for(d in m)g=Ua(p?q[d]:0,d,l),d in q||(q[d]=g.start,p&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function Wa(a,b){var c,d,e,f,g;for(c in a)if(d=n.camelCase(c),e=b[d],f=a[c],n.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=n.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 Xa(a,b,c){var d,e,f=0,g=Qa.length,h=n.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=La||Sa(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:n.extend({},b),opts:n.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:La||Sa(),duration:c.duration,tweens:[],createTween:function(b,c){var d=n.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;d>c;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;for(Wa(k,j.opts.specialEasing);g>f;f++)if(d=Qa[f].call(j,a,k,j.opts))return d;return n.map(k,Ua,j),n.isFunction(j.opts.start)&&j.opts.start.call(a,j),n.fx.timer(n.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)}n.Animation=n.extend(Xa,{tweener:function(a,b){n.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");for(var c,d=0,e=a.length;e>d;d++)c=a[d],Ra[c]=Ra[c]||[],Ra[c].unshift(b)},prefilter:function(a,b){b?Qa.unshift(a):Qa.push(a)}}),n.speed=function(a,b,c){var d=a&&"object"==typeof a?n.extend({},a):{complete:c||!c&&b||n.isFunction(a)&&a,duration:a,easing:c&&b||b&&!n.isFunction(b)&&b};return d.duration=n.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in n.fx.speeds?n.fx.speeds[d.duration]:n.fx.speeds._default,(null==d.queue||d.queue===!0)&&(d.queue="fx"),d.old=d.complete,d.complete=function(){n.isFunction(d.old)&&d.old.call(this),d.queue&&n.dequeue(this,d.queue)},d},n.fn.extend({fadeTo:function(a,b,c,d){return this.filter(S).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=n.isEmptyObject(a),f=n.speed(b,c,d),g=function(){var b=Xa(this,n.extend({},a),f);(e||L.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=n.timers,g=L.get(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&Pa.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)&&n.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=L.get(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=n.timers,g=d?d.length:0;for(c.finish=!0,n.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;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),n.each(["toggle","show","hide"],function(a,b){var c=n.fn[b];n.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(Ta(b,!0),a,d,e)}}),n.each({slideDown:Ta("show"),slideUp:Ta("hide"),slideToggle:Ta("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){n.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),n.timers=[],n.fx.tick=function(){var a,b=0,c=n.timers;for(La=n.now();b<c.length;b++)a=c[b],a()||c[b]!==a||c.splice(b--,1);c.length||n.fx.stop(),La=void 0},n.fx.timer=function(a){n.timers.push(a),a()?n.fx.start():n.timers.pop()},n.fx.interval=13,n.fx.start=function(){Ma||(Ma=setInterval(n.fx.tick,n.fx.interval))},n.fx.stop=function(){clearInterval(Ma),Ma=null},n.fx.speeds={slow:600,fast:200,_default:400},n.fn.delay=function(a,b){return a=n.fx?n.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},function(){var a=l.createElement("input"),b=l.createElement("select"),c=b.appendChild(l.createElement("option"));a.type="checkbox",k.checkOn=""!==a.value,k.optSelected=c.selected,b.disabled=!0,k.optDisabled=!c.disabled,a=l.createElement("input"),a.value="t",a.type="radio",k.radioValue="t"===a.value}();var Ya,Za,$a=n.expr.attrHandle;n.fn.extend({attr:function(a,b){return J(this,n.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){n.removeAttr(this,a)})}}),n.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(a&&3!==f&&8!==f&&2!==f)return typeof a.getAttribute===U?n.prop(a,b,c):(1===f&&n.isXMLDoc(a)||(b=b.toLowerCase(),d=n.attrHooks[b]||(n.expr.match.bool.test(b)?Za:Ya)), +void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=n.find.attr(a,b),null==e?void 0:e):null!==c?d&&"set"in d&&void 0!==(e=d.set(a,c,b))?e:(a.setAttribute(b,c+""),c):void n.removeAttr(a,b))},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(E);if(f&&1===a.nodeType)while(c=f[e++])d=n.propFix[c]||c,n.expr.match.bool.test(c)&&(a[d]=!1),a.removeAttribute(c)},attrHooks:{type:{set:function(a,b){if(!k.radioValue&&"radio"===b&&n.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}}}),Za={set:function(a,b,c){return b===!1?n.removeAttr(a,c):a.setAttribute(c,c),c}},n.each(n.expr.match.bool.source.match(/\w+/g),function(a,b){var c=$a[b]||n.find.attr;$a[b]=function(a,b,d){var e,f;return d||(f=$a[b],$a[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,$a[b]=f),e}});var _a=/^(?:input|select|textarea|button)$/i;n.fn.extend({prop:function(a,b){return J(this,n.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[n.propFix[a]||a]})}}),n.extend({propFix:{"for":"htmlFor","class":"className"},prop:function(a,b,c){var d,e,f,g=a.nodeType;if(a&&3!==g&&8!==g&&2!==g)return f=1!==g||!n.isXMLDoc(a),f&&(b=n.propFix[b]||b,e=n.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){return a.hasAttribute("tabindex")||_a.test(a.nodeName)||a.href?a.tabIndex:-1}}}}),k.optSelected||(n.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null}}),n.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){n.propFix[this.toLowerCase()]=this});var ab=/[\t\r\n\f]/g;n.fn.extend({addClass:function(a){var b,c,d,e,f,g,h="string"==typeof a&&a,i=0,j=this.length;if(n.isFunction(a))return this.each(function(b){n(this).addClass(a.call(this,b,this.className))});if(h)for(b=(a||"").match(E)||[];j>i;i++)if(c=this[i],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(ab," "):" ")){f=0;while(e=b[f++])d.indexOf(" "+e+" ")<0&&(d+=e+" ");g=n.trim(d),c.className!==g&&(c.className=g)}return this},removeClass:function(a){var b,c,d,e,f,g,h=0===arguments.length||"string"==typeof a&&a,i=0,j=this.length;if(n.isFunction(a))return this.each(function(b){n(this).removeClass(a.call(this,b,this.className))});if(h)for(b=(a||"").match(E)||[];j>i;i++)if(c=this[i],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(ab," "):"")){f=0;while(e=b[f++])while(d.indexOf(" "+e+" ")>=0)d=d.replace(" "+e+" "," ");g=a?n.trim(d):"",c.className!==g&&(c.className=g)}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):this.each(n.isFunction(a)?function(c){n(this).toggleClass(a.call(this,c,this.className,b),b)}:function(){if("string"===c){var b,d=0,e=n(this),f=a.match(E)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else(c===U||"boolean"===c)&&(this.className&&L.set(this,"__className__",this.className),this.className=this.className||a===!1?"":L.get(this,"__className__")||"")})},hasClass:function(a){for(var b=" "+a+" ",c=0,d=this.length;d>c;c++)if(1===this[c].nodeType&&(" "+this[c].className+" ").replace(ab," ").indexOf(b)>=0)return!0;return!1}});var bb=/\r/g;n.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=n.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,n(this).val()):a,null==e?e="":"number"==typeof e?e+="":n.isArray(e)&&(e=n.map(e,function(a){return null==a?"":a+""})),b=n.valHooks[this.type]||n.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=n.valHooks[e.type]||n.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(bb,""):null==c?"":c)}}}),n.extend({valHooks:{option:{get:function(a){var b=n.find.attr(a,"value");return null!=b?b:n.trim(n.text(a))}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],!(!c.selected&&i!==e||(k.optDisabled?c.disabled:null!==c.getAttribute("disabled"))||c.parentNode.disabled&&n.nodeName(c.parentNode,"optgroup"))){if(b=n(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=n.makeArray(b),g=e.length;while(g--)d=e[g],(d.selected=n.inArray(d.value,f)>=0)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),n.each(["radio","checkbox"],function(){n.valHooks[this]={set:function(a,b){return n.isArray(b)?a.checked=n.inArray(n(a).val(),b)>=0:void 0}},k.checkOn||(n.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})}),n.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){n.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),n.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)},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)}});var cb=n.now(),db=/\?/;n.parseJSON=function(a){return JSON.parse(a+"")},n.parseXML=function(a){var b,c;if(!a||"string"!=typeof a)return null;try{c=new DOMParser,b=c.parseFromString(a,"text/xml")}catch(d){b=void 0}return(!b||b.getElementsByTagName("parsererror").length)&&n.error("Invalid XML: "+a),b};var eb=/#.*$/,fb=/([?&])_=[^&]*/,gb=/^(.*?):[ \t]*([^\r\n]*)$/gm,hb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,ib=/^(?:GET|HEAD)$/,jb=/^\/\//,kb=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,lb={},mb={},nb="*/".concat("*"),ob=a.location.href,pb=kb.exec(ob.toLowerCase())||[];function qb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(E)||[];if(n.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 rb(a,b,c,d){var e={},f=a===mb;function g(h){var i;return e[h]=!0,n.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 sb(a,b){var c,d,e=n.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&n.extend(!0,a,d),a}function tb(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}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function ub(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}}n.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:ob,type:"GET",isLocal:hb.test(pb[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":nb,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":n.parseJSON,"text xml":n.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?sb(sb(a,n.ajaxSettings),b):sb(n.ajaxSettings,a)},ajaxPrefilter:qb(lb),ajaxTransport:qb(mb),ajax:function(a,b){"object"==typeof a&&(b=a,a=void 0),b=b||{};var c,d,e,f,g,h,i,j,k=n.ajaxSetup({},b),l=k.context||k,m=k.context&&(l.nodeType||l.jquery)?n(l):n.event,o=n.Deferred(),p=n.Callbacks("once memory"),q=k.statusCode||{},r={},s={},t=0,u="canceled",v={readyState:0,getResponseHeader:function(a){var b;if(2===t){if(!f){f={};while(b=gb.exec(e))f[b[1].toLowerCase()]=b[2]}b=f[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===t?e:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return t||(a=s[c]=s[c]||a,r[a]=b),this},overrideMimeType:function(a){return t||(k.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>t)for(b in a)q[b]=[q[b],a[b]];else v.always(a[v.status]);return this},abort:function(a){var b=a||u;return c&&c.abort(b),x(0,b),this}};if(o.promise(v).complete=p.add,v.success=v.done,v.error=v.fail,k.url=((a||k.url||ob)+"").replace(eb,"").replace(jb,pb[1]+"//"),k.type=b.method||b.type||k.method||k.type,k.dataTypes=n.trim(k.dataType||"*").toLowerCase().match(E)||[""],null==k.crossDomain&&(h=kb.exec(k.url.toLowerCase()),k.crossDomain=!(!h||h[1]===pb[1]&&h[2]===pb[2]&&(h[3]||("http:"===h[1]?"80":"443"))===(pb[3]||("http:"===pb[1]?"80":"443")))),k.data&&k.processData&&"string"!=typeof k.data&&(k.data=n.param(k.data,k.traditional)),rb(lb,k,b,v),2===t)return v;i=n.event&&k.global,i&&0===n.active++&&n.event.trigger("ajaxStart"),k.type=k.type.toUpperCase(),k.hasContent=!ib.test(k.type),d=k.url,k.hasContent||(k.data&&(d=k.url+=(db.test(d)?"&":"?")+k.data,delete k.data),k.cache===!1&&(k.url=fb.test(d)?d.replace(fb,"$1_="+cb++):d+(db.test(d)?"&":"?")+"_="+cb++)),k.ifModified&&(n.lastModified[d]&&v.setRequestHeader("If-Modified-Since",n.lastModified[d]),n.etag[d]&&v.setRequestHeader("If-None-Match",n.etag[d])),(k.data&&k.hasContent&&k.contentType!==!1||b.contentType)&&v.setRequestHeader("Content-Type",k.contentType),v.setRequestHeader("Accept",k.dataTypes[0]&&k.accepts[k.dataTypes[0]]?k.accepts[k.dataTypes[0]]+("*"!==k.dataTypes[0]?", "+nb+"; q=0.01":""):k.accepts["*"]);for(j in k.headers)v.setRequestHeader(j,k.headers[j]);if(k.beforeSend&&(k.beforeSend.call(l,v,k)===!1||2===t))return v.abort();u="abort";for(j in{success:1,error:1,complete:1})v[j](k[j]);if(c=rb(mb,k,b,v)){v.readyState=1,i&&m.trigger("ajaxSend",[v,k]),k.async&&k.timeout>0&&(g=setTimeout(function(){v.abort("timeout")},k.timeout));try{t=1,c.send(r,x)}catch(w){if(!(2>t))throw w;x(-1,w)}}else x(-1,"No Transport");function x(a,b,f,h){var j,r,s,u,w,x=b;2!==t&&(t=2,g&&clearTimeout(g),c=void 0,e=h||"",v.readyState=a>0?4:0,j=a>=200&&300>a||304===a,f&&(u=tb(k,v,f)),u=ub(k,u,v,j),j?(k.ifModified&&(w=v.getResponseHeader("Last-Modified"),w&&(n.lastModified[d]=w),w=v.getResponseHeader("etag"),w&&(n.etag[d]=w)),204===a||"HEAD"===k.type?x="nocontent":304===a?x="notmodified":(x=u.state,r=u.data,s=u.error,j=!s)):(s=x,(a||!x)&&(x="error",0>a&&(a=0))),v.status=a,v.statusText=(b||x)+"",j?o.resolveWith(l,[r,x,v]):o.rejectWith(l,[v,x,s]),v.statusCode(q),q=void 0,i&&m.trigger(j?"ajaxSuccess":"ajaxError",[v,k,j?r:s]),p.fireWith(l,[v,x]),i&&(m.trigger("ajaxComplete",[v,k]),--n.active||n.event.trigger("ajaxStop")))}return v},getJSON:function(a,b,c){return n.get(a,b,c,"json")},getScript:function(a,b){return n.get(a,void 0,b,"script")}}),n.each(["get","post"],function(a,b){n[b]=function(a,c,d,e){return n.isFunction(c)&&(e=e||d,d=c,c=void 0),n.ajax({url:a,type:b,dataType:e,data:c,success:d})}}),n._evalUrl=function(a){return n.ajax({url:a,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},n.fn.extend({wrapAll:function(a){var b;return n.isFunction(a)?this.each(function(b){n(this).wrapAll(a.call(this,b))}):(this[0]&&(b=n(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 this.each(n.isFunction(a)?function(b){n(this).wrapInner(a.call(this,b))}:function(){var b=n(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=n.isFunction(a);return this.each(function(c){n(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){n.nodeName(this,"body")||n(this).replaceWith(this.childNodes)}).end()}}),n.expr.filters.hidden=function(a){return a.offsetWidth<=0&&a.offsetHeight<=0},n.expr.filters.visible=function(a){return!n.expr.filters.hidden(a)};var vb=/%20/g,wb=/\[\]$/,xb=/\r?\n/g,yb=/^(?:submit|button|image|reset|file)$/i,zb=/^(?:input|select|textarea|keygen)/i;function Ab(a,b,c,d){var e;if(n.isArray(b))n.each(b,function(b,e){c||wb.test(a)?d(a,e):Ab(a+"["+("object"==typeof e?b:"")+"]",e,c,d)});else if(c||"object"!==n.type(b))d(a,b);else for(e in b)Ab(a+"["+e+"]",b[e],c,d)}n.param=function(a,b){var c,d=[],e=function(a,b){b=n.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=n.ajaxSettings&&n.ajaxSettings.traditional),n.isArray(a)||a.jquery&&!n.isPlainObject(a))n.each(a,function(){e(this.name,this.value)});else for(c in a)Ab(c,a[c],b,e);return d.join("&").replace(vb,"+")},n.fn.extend({serialize:function(){return n.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=n.prop(this,"elements");return a?n.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!n(this).is(":disabled")&&zb.test(this.nodeName)&&!yb.test(a)&&(this.checked||!T.test(a))}).map(function(a,b){var c=n(this).val();return null==c?null:n.isArray(c)?n.map(c,function(a){return{name:b.name,value:a.replace(xb,"\r\n")}}):{name:b.name,value:c.replace(xb,"\r\n")}}).get()}}),n.ajaxSettings.xhr=function(){try{return new XMLHttpRequest}catch(a){}};var Bb=0,Cb={},Db={0:200,1223:204},Eb=n.ajaxSettings.xhr();a.attachEvent&&a.attachEvent("onunload",function(){for(var a in Cb)Cb[a]()}),k.cors=!!Eb&&"withCredentials"in Eb,k.ajax=Eb=!!Eb,n.ajaxTransport(function(a){var b;return k.cors||Eb&&!a.crossDomain?{send:function(c,d){var e,f=a.xhr(),g=++Bb;if(f.open(a.type,a.url,a.async,a.username,a.password),a.xhrFields)for(e in a.xhrFields)f[e]=a.xhrFields[e];a.mimeType&&f.overrideMimeType&&f.overrideMimeType(a.mimeType),a.crossDomain||c["X-Requested-With"]||(c["X-Requested-With"]="XMLHttpRequest");for(e in c)f.setRequestHeader(e,c[e]);b=function(a){return function(){b&&(delete Cb[g],b=f.onload=f.onerror=null,"abort"===a?f.abort():"error"===a?d(f.status,f.statusText):d(Db[f.status]||f.status,f.statusText,"string"==typeof f.responseText?{text:f.responseText}:void 0,f.getAllResponseHeaders()))}},f.onload=b(),f.onerror=b("error"),b=Cb[g]=b("abort");try{f.send(a.hasContent&&a.data||null)}catch(h){if(b)throw h}},abort:function(){b&&b()}}:void 0}),n.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(a){return n.globalEval(a),a}}}),n.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),n.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(d,e){b=n("<script>").prop({async:!0,charset:a.scriptCharset,src:a.url}).on("load error",c=function(a){b.remove(),c=null,a&&e("error"===a.type?404:200,a.type)}),l.head.appendChild(b[0])},abort:function(){c&&c()}}}});var Fb=[],Gb=/(=)\?(?=&|$)|\?\?/;n.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=Fb.pop()||n.expando+"_"+cb++;return this[a]=!0,a}}),n.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(Gb.test(b.url)?"url":"string"==typeof b.data&&!(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&Gb.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=n.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(Gb,"$1"+e):b.jsonp!==!1&&(b.url+=(db.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||n.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,Fb.push(e)),g&&n.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),n.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||l;var d=v.exec(a),e=!c&&[];return d?[b.createElement(d[1])]:(d=n.buildFragment([a],b,e),e&&e.length&&n(e).remove(),n.merge([],d.childNodes))};var Hb=n.fn.load;n.fn.load=function(a,b,c){if("string"!=typeof a&&Hb)return Hb.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>=0&&(d=n.trim(a.slice(h)),a=a.slice(0,h)),n.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(e="POST"),g.length>0&&n.ajax({url:a,type:e,dataType:"html",data:b}).done(function(a){f=arguments,g.html(d?n("<div>").append(n.parseHTML(a)).find(d):a)}).complete(c&&function(a,b){g.each(c,f||[a.responseText,b,a])}),this},n.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){n.fn[b]=function(a){return this.on(b,a)}}),n.expr.filters.animated=function(a){return n.grep(n.timers,function(b){return a===b.elem}).length};var Ib=a.document.documentElement;function Jb(a){return n.isWindow(a)?a:9===a.nodeType&&a.defaultView}n.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=n.css(a,"position"),l=n(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=n.css(a,"top"),i=n.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),n.isFunction(b)&&(b=b.call(a,c,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)}},n.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){n.offset.setOffset(this,a,b)});var b,c,d=this[0],e={top:0,left:0},f=d&&d.ownerDocument;if(f)return b=f.documentElement,n.contains(b,d)?(typeof d.getBoundingClientRect!==U&&(e=d.getBoundingClientRect()),c=Jb(f),{top:e.top+c.pageYOffset-b.clientTop,left:e.left+c.pageXOffset-b.clientLeft}):e},position:function(){if(this[0]){var a,b,c=this[0],d={top:0,left:0};return"fixed"===n.css(c,"position")?b=c.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),n.nodeName(a[0],"html")||(d=a.offset()),d.top+=n.css(a[0],"borderTopWidth",!0),d.left+=n.css(a[0],"borderLeftWidth",!0)),{top:b.top-d.top-n.css(c,"marginTop",!0),left:b.left-d.left-n.css(c,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||Ib;while(a&&!n.nodeName(a,"html")&&"static"===n.css(a,"position"))a=a.offsetParent;return a||Ib})}}),n.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(b,c){var d="pageYOffset"===c;n.fn[b]=function(e){return J(this,function(b,e,f){var g=Jb(b);return void 0===f?g?g[c]:b[e]:void(g?g.scrollTo(d?a.pageXOffset:f,d?f:a.pageYOffset):b[e]=f)},b,e,arguments.length,null)}}),n.each(["top","left"],function(a,b){n.cssHooks[b]=ya(k.pixelPosition,function(a,c){return c?(c=xa(a,b),va.test(c)?n(a).position()[b]+"px":c):void 0})}),n.each({Height:"height",Width:"width"},function(a,b){n.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){n.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return J(this,function(b,c,d){var e;return n.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?n.css(b,c,g):n.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),n.fn.size=function(){return this.length},n.fn.andSelf=n.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return n});var Kb=a.jQuery,Lb=a.$;return n.noConflict=function(b){return a.$===n&&(a.$=Lb),b&&a.jQuery===n&&(a.jQuery=Kb),n},typeof b===U&&(a.jQuery=a.$=n),n}); diff --git a/http/3rdParty/jquery-2.2.3.min.js b/http/3rdParty/jquery-2.2.3.min.js new file mode 100644 index 0000000..b8c4187 --- /dev/null +++ b/http/3rdParty/jquery-2.2.3.min.js @@ -0,0 +1,4 @@ +/*! jQuery v2.2.3 | (c) jQuery Foundation | jquery.org/license */ +!function(a,b){"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){var c=[],d=a.document,e=c.slice,f=c.concat,g=c.push,h=c.indexOf,i={},j=i.toString,k=i.hasOwnProperty,l={},m="2.2.3",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return e.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:e.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a){return n.each(this,a)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(e.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:g,sort:c.sort,splice:c.splice},n.extend=n.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||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){var b=a&&a.toString();return!n.isArray(a)&&b-parseFloat(b)+1>=0},isPlainObject:function(a){var b;if("object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;if(a.constructor&&!k.call(a,"constructor")&&!k.call(a.constructor.prototype||{},"isPrototypeOf"))return!1;for(b in a);return void 0===b||k.call(a,b)},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?i[j.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=d.createElement("script"),b.text=a,d.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b){var c,d=0;if(s(a)){for(c=a.length;c>d;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(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):g.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:h.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;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;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,g=0,h=[];if(s(a))for(d=a.length;d>g;g++)e=b(a[g],g,c),null!=e&&h.push(e);else for(g in a)e=b(a[g],g,c),null!=e&&h.push(e);return f.apply([],h)},guid:1,proxy:function(a,b){var c,d,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(d=e.call(arguments,2),f=function(){return a.apply(b||this,d.concat(e.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:l}),"function"==typeof Symbol&&(n.fn[Symbol.iterator]=c[Symbol.iterator]),n.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){i["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=!!a&&"length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=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=ga(),z=ga(),A=ga(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+M+"))|)"+L+"*\\]",O=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+N+")*)|.*)\\)|)",P=new RegExp(L+"+","g"),Q=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),R=new RegExp("^"+L+"*,"+L+"*"),S=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),T=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),U=new RegExp(O),V=new RegExp("^"+M+"$"),W={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M+"|[*])"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},X=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Z=/^[^{]+\{\s*\[native \w/,$=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,_=/[+~]/,aa=/'|\\/g,ba=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),ca=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},da=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(ea){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fa(a,b,d,e){var f,h,j,k,l,o,r,s,w=b&&b.ownerDocument,x=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==x&&9!==x&&11!==x)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==x&&(o=$.exec(a)))if(f=o[1]){if(9===x){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(w&&(j=w.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(o[2])return H.apply(d,b.getElementsByTagName(a)),d;if((f=o[3])&&c.getElementsByClassName&&b.getElementsByClassName)return H.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==x)w=b,s=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(aa,"\\$&"):b.setAttribute("id",k=u),r=g(a),h=r.length,l=V.test(k)?"#"+k:"[id='"+k+"']";while(h--)r[h]=l+" "+qa(r[h]);s=r.join(","),w=_.test(a)&&oa(b.parentNode)||b}if(s)try{return H.apply(d,w.querySelectorAll(s)),d}catch(y){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(Q,"$1"),b,d,e)}function ga(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ha(a){return a[u]=!0,a}function ia(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ja(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function ka(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function la(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function na(a){return ha(function(b){return b=+b,ha(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 oa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=fa.support={},f=fa.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fa.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),(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ia(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ia(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Z.test(n.getElementsByClassName),c.getById=ia(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return"undefined"!=typeof b.getElementsByClassName&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=Z.test(n.querySelectorAll))&&(ia(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("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ia(function(a){var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Z.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ia(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",O)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Z.test(o.compareDocumentPosition),t=b||Z.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?J(k,a)-J(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?J(k,a)-J(k,b):0;if(e===f)return ka(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?ka(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},fa.matches=function(a,b){return fa(a,null,null,b)},fa.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(T,"='$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 fa(b,n,null,[a]).length>0},fa.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fa.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.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},fa.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fa.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=fa.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=fa.selectors={cacheLength:50,createPseudo:ha,match:W,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(ba,ca),a[3]=(a[3]||a[4]||a[5]||"").replace(ba,ca),"~="===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]||fa.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]&&fa.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return W.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&U.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(ba,ca).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("(^|"+L+")"+a+"("+L+"|$)"))&&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=fa.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(P," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},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()]||fa.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ha(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ha(function(a){var b=[],c=[],d=h(a.replace(Q,"$1"));return d[u]?ha(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:ha(function(a){return function(b){return fa(a,b).length>0}}),contains:ha(function(a){return a=a.replace(ba,ca),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ha(function(a){return V.test(a||"")||fa.error("unsupported lang: "+a),a=a.replace(ba,ca).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:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!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 Y.test(a.nodeName)},input:function(a){return X.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:na(function(){return[0]}),last:na(function(a,b){return[b-1]}),eq:na(function(a,b,c){return[0>c?c+b:c]}),even:na(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:na(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:na(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:na(function(a,b,c){for(var d=0>c?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]=la(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=ma(b);function pa(){}pa.prototype=d.filters=d.pseudos,d.setFilters=new pa,g=fa.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=R.exec(h))||(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=S.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(Q," ")}),h=h.slice(c.length));for(g in d.filter)!(e=W[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?fa.error(a):z(a,i).slice(0)};function qa(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function ra(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j,k=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(j=b[u]||(b[u]={}),i=j[b.uniqueID]||(j[b.uniqueID]={}),(h=i[d])&&h[0]===w&&h[1]===f)return k[2]=h[2];if(i[d]=k,k[2]=a(b,c,g))return!0}}}function sa(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 ta(a,b,c){for(var d=0,e=b.length;e>d;d++)fa(a,b[d],c);return c}function ua(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(c&&!c(f,d,e)||(g.push(f),j&&b.push(h)));return g}function va(a,b,c,d,e,f){return d&&!d[u]&&(d=va(d)),e&&!e[u]&&(e=va(e,f)),ha(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ta(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ua(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ua(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?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ua(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function wa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ra(function(a){return a===b},h,!0),l=ra(function(a){return J(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}];f>i;i++)if(c=d.relative[a[i].type])m=[ra(sa(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return va(i>1&&sa(m),i>1&&qa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(Q,"$1"),c,e>i&&wa(a.slice(i,e)),f>e&&wa(a=a.slice(e)),f>e&&qa(a))}m.push(c)}return sa(m)}function xa(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]=F.call(i));u=ua(u)}H.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&fa.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ha(f):f}return h=fa.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xa(e,d)),f.selector=a}return f},i=fa.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ba,ca),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=W.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ba,ca),_.test(j[0].type)&&oa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qa(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,!b||_.test(a)&&oa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ia(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ia(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||ja("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ia(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ja("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ia(function(a){return null==a.getAttribute("disabled")})||ja(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fa}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.uniqueSort=n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},v=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},w=n.expr.match.needsContext,x=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,y=/^.[^:#\[\.,]*$/;function z(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(y.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return h.call(b,a)>-1!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(z(this,a||[],!1))},not:function(a){return this.pushStack(z(this,a||[],!0))},is:function(a){return!!z(this,"string"==typeof a&&w.test(a)?n(a):a||[],!1).length}});var A,B=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=n.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||A,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:B.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 n?b[0]:b,n.merge(this,n.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),x.test(e[1])&&n.isPlainObject(b))for(e in b)n.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&f.parentNode&&(this.length=1,this[0]=f),this.context=d,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?void 0!==c.ready?c.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};C.prototype=n.fn,A=n(d);var D=/^(?:parents|prev(?:Until|All))/,E={children:!0,contents:!0,next:!0,prev:!0};n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=w.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?h.call(n(a),this[0]):h.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.uniqueSort(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function F(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return u(a,"parentNode")},parentsUntil:function(a,b,c){return u(a,"parentNode",c)},next:function(a){return F(a,"nextSibling")},prev:function(a){return F(a,"previousSibling")},nextAll:function(a){return u(a,"nextSibling")},prevAll:function(a){return u(a,"previousSibling")},nextUntil:function(a,b,c){return u(a,"nextSibling",c)},prevUntil:function(a,b,c){return u(a,"previousSibling",c)},siblings:function(a){return v((a.parentNode||{}).firstChild,a)},children:function(a){return v(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(E[a]||n.uniqueSort(e),D.test(a)&&e.reverse()),this.pushStack(e)}});var G=/\S+/g;function H(a){var b={};return n.each(a.match(G)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?H(a):n.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){n.each(b,function(b,c){n.isFunction(c)?a.unique&&j.has(c)||f.push(c):c&&c.length&&"string"!==n.type(c)&&d(c)})}(arguments),c&&!b&&i()),this},remove:function(){return n.each(arguments,function(a,b){var c;while((c=n.inArray(b,f,c))>-1)f.splice(c,1),h>=c&&h--}),this},has:function(a){return a?n.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||(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},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().progress(c.notify).done(c.resolve).fail(c.reject):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=e.call(arguments),d=c.length,f=1!==d||a&&n.isFunction(a.promise)?d:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?e.call(arguments):d,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(d>1)for(i=new Array(d),j=new Array(d),k=new Array(d);d>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().progress(h(b,j,i)).done(h(b,k,c)).fail(g.reject):--f;return f||g.resolveWith(k,c),g.promise()}});var I;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(I.resolveWith(d,[n]),n.fn.triggerHandler&&(n(d).triggerHandler("ready"),n(d).off("ready"))))}});function J(){d.removeEventListener("DOMContentLoaded",J),a.removeEventListener("load",J),n.ready()}n.ready.promise=function(b){return I||(I=n.Deferred(),"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(n.ready):(d.addEventListener("DOMContentLoaded",J),a.addEventListener("load",J))),I.promise(b)},n.ready.promise();var K=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)K(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;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},L=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function M(){this.expando=n.expando+M.uid++}M.uid=1,M.prototype={register:function(a,b){var c=b||{};return a.nodeType?a[this.expando]=c:Object.defineProperty(a,this.expando,{value:c,writable:!0,configurable:!0}),a[this.expando]},cache:function(a){if(!L(a))return{};var b=a[this.expando];return b||(b={},L(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[b]=c;else for(d in b)e[d]=b[d];return e},get:function(a,b){return void 0===b?this.cache(a):a[this.expando]&&a[this.expando][b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=a[this.expando];if(void 0!==f){if(void 0===b)this.register(a);else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in f?d=[b,e]:(d=e,d=d in f?[d]:d.match(G)||[])),c=d.length;while(c--)delete f[d[c]]}(void 0===b||n.isEmptyObject(f))&&(a.nodeType?a[this.expando]=void 0:delete a[this.expando])}},hasData:function(a){var b=a[this.expando];return void 0!==b&&!n.isEmptyObject(b)}};var N=new M,O=new M,P=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,Q=/[A-Z]/g;function R(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(Q,"-$&").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:P.test(c)?n.parseJSON(c):c; +}catch(e){}O.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return O.hasData(a)||N.hasData(a)},data:function(a,b,c){return O.access(a,b,c)},removeData:function(a,b){O.remove(a,b)},_data:function(a,b,c){return N.access(a,b,c)},_removeData:function(a,b){N.remove(a,b)}}),n.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=O.get(f),1===f.nodeType&&!N.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),R(f,d,e[d])));N.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){O.set(this,a)}):K(this,function(b){var c,d;if(f&&void 0===b){if(c=O.get(f,a)||O.get(f,a.replace(Q,"-$&").toLowerCase()),void 0!==c)return c;if(d=n.camelCase(a),c=O.get(f,d),void 0!==c)return c;if(c=R(f,d,void 0),void 0!==c)return c}else d=n.camelCase(a),this.each(function(){var c=O.get(this,d);O.set(this,d,b),a.indexOf("-")>-1&&void 0!==c&&O.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){O.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=N.get(a,b),c&&(!d||n.isArray(c)?d=N.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.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 N.get(a,c)||N.access(a,c,{empty:n.Callbacks("once memory").add(function(){N.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?n.queue(this[0],a):void 0===b?this:this.each(function(){var c=n.queue(this,a,b);n._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&n.dequeue(this,a)})},dequeue:function(a){return this.each(function(){n.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=n.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=N.get(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var S=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,T=new RegExp("^(?:([+-])=|)("+S+")([a-z%]*)$","i"),U=["Top","Right","Bottom","Left"],V=function(a,b){return a=b||a,"none"===n.css(a,"display")||!n.contains(a.ownerDocument,a)};function W(a,b,c,d){var e,f=1,g=20,h=d?function(){return d.cur()}:function(){return n.css(a,b,"")},i=h(),j=c&&c[3]||(n.cssNumber[b]?"":"px"),k=(n.cssNumber[b]||"px"!==j&&+i)&&T.exec(n.css(a,b));if(k&&k[3]!==j){j=j||k[3],c=c||[],k=+i||1;do f=f||".5",k/=f,n.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 X=/^(?:checkbox|radio)$/i,Y=/<([\w:-]+)/,Z=/^$|\/(?:java|ecma)script/i,$={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,"",""]};$.optgroup=$.option,$.tbody=$.tfoot=$.colgroup=$.caption=$.thead,$.th=$.td;function _(a,b){var c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function aa(a,b){for(var c=0,d=a.length;d>c;c++)N.set(a[c],"globalEval",!b||N.get(b[c],"globalEval"))}var ba=/<|&#?\w+;/;function ca(a,b,c,d,e){for(var f,g,h,i,j,k,l=b.createDocumentFragment(),m=[],o=0,p=a.length;p>o;o++)if(f=a[o],f||0===f)if("object"===n.type(f))n.merge(m,f.nodeType?[f]:f);else if(ba.test(f)){g=g||l.appendChild(b.createElement("div")),h=(Y.exec(f)||["",""])[1].toLowerCase(),i=$[h]||$._default,g.innerHTML=i[1]+n.htmlPrefilter(f)+i[2],k=i[0];while(k--)g=g.lastChild;n.merge(m,g.childNodes),g=l.firstChild,g.textContent=""}else m.push(b.createTextNode(f));l.textContent="",o=0;while(f=m[o++])if(d&&n.inArray(f,d)>-1)e&&e.push(f);else if(j=n.contains(f.ownerDocument,f),g=_(l.appendChild(f),"script"),j&&aa(g),c){k=0;while(f=g[k++])Z.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),l.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="<textarea>x</textarea>",l.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var da=/^key/,ea=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,fa=/^([^.]*)(?:\.(.+)|)/;function ga(){return!0}function ha(){return!1}function ia(){try{return d.activeElement}catch(a){}}function ja(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)ja(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=ha;else if(!e)return a;return 1===f&&(g=e,e=function(a){return n().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=n.guid++)),a.each(function(){n.event.add(this,b,e,d,c)})}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=N.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return"undefined"!=typeof n&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(G)||[""],j=b.length;while(j--)h=fa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=N.hasData(a)&&N.get(a);if(r&&(i=r.events)){b=(b||"").match(G)||[""],j=b.length;while(j--)if(h=fa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&N.remove(a,"handle events")}},dispatch:function(a){a=n.event.fix(a);var b,c,d,f,g,h=[],i=e.call(arguments),j=(N.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())a.rnamespace&&!a.rnamespace.test(g.namespace)||(a.handleObj=g,a.data=g.data,d=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==d&&(a.result=d)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&("click"!==a.type||isNaN(a.button)||a.button<1))for(;i!==this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>-1:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},props:"altKey bubbles cancelable ctrlKey currentTarget detail eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,e,f,g=b.button;return null==a.pageX&&null!=b.clientX&&(c=a.target.ownerDocument||d,e=c.documentElement,f=c.body,a.pageX=b.clientX+(e&&e.scrollLeft||f&&f.scrollLeft||0)-(e&&e.clientLeft||f&&f.clientLeft||0),a.pageY=b.clientY+(e&&e.scrollTop||f&&f.scrollTop||0)-(e&&e.clientTop||f&&f.clientTop||0)),a.which||void 0===g||(a.which=1&g?1:2&g?3:4&g?2:0),a}},fix:function(a){if(a[n.expando])return a;var b,c,e,f=a.type,g=a,h=this.fixHooks[f];h||(this.fixHooks[f]=h=ea.test(f)?this.mouseHooks:da.test(f)?this.keyHooks:{}),e=h.props?this.props.concat(h.props):this.props,a=new n.Event(g),b=e.length;while(b--)c=e[b],a[c]=g[c];return a.target||(a.target=d),3===a.target.nodeType&&(a.target=a.target.parentNode),h.filter?h.filter(a,g):a},special:{load:{noBubble:!0},focus:{trigger:function(){return this!==ia()&&this.focus?(this.focus(),!1):void 0},delegateType:"focusin"},blur:{trigger:function(){return this===ia()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return"checkbox"===this.type&&this.click&&n.nodeName(this,"input")?(this.click(),!1):void 0},_default:function(a){return n.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}}},n.removeEvent=function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c)},n.Event=function(a,b){return this instanceof n.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?ga:ha):this.type=a,b&&n.extend(this,b),this.timeStamp=a&&a.timeStamp||n.now(),void(this[n.expando]=!0)):new n.Event(a,b)},n.Event.prototype={constructor:n.Event,isDefaultPrevented:ha,isPropagationStopped:ha,isImmediatePropagationStopped:ha,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=ga,a&&a.preventDefault()},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=ga,a&&a.stopPropagation()},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=ga,a&&a.stopImmediatePropagation(),this.stopPropagation()}},n.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){n.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return e&&(e===d||n.contains(d,e))||(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),n.fn.extend({on:function(a,b,c,d){return ja(this,a,b,c,d)},one:function(a,b,c,d){return ja(this,a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,n(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=ha),this.each(function(){n.event.remove(this,a,c,b)})}});var ka=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,la=/<script|<style|<link/i,ma=/checked\s*(?:[^=]|=\s*.checked.)/i,na=/^true\/(.*)/,oa=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;function pa(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function qa(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function ra(a){var b=na.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function sa(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(N.hasData(a)&&(f=N.access(a),g=N.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}O.hasData(a)&&(h=O.access(a),i=n.extend({},h),O.set(b,i))}}function ta(a,b){var c=b.nodeName.toLowerCase();"input"===c&&X.test(a.type)?b.checked=a.checked:"input"!==c&&"textarea"!==c||(b.defaultValue=a.defaultValue)}function ua(a,b,c,d){b=f.apply([],b);var e,g,h,i,j,k,m=0,o=a.length,p=o-1,q=b[0],r=n.isFunction(q);if(r||o>1&&"string"==typeof q&&!l.checkClone&&ma.test(q))return a.each(function(e){var f=a.eq(e);r&&(b[0]=q.call(this,e,f.html())),ua(f,b,c,d)});if(o&&(e=ca(b,a[0].ownerDocument,!1,a,d),g=e.firstChild,1===e.childNodes.length&&(e=g),g||d)){for(h=n.map(_(e,"script"),qa),i=h.length;o>m;m++)j=e,m!==p&&(j=n.clone(j,!0,!0),i&&n.merge(h,_(j,"script"))),c.call(a[m],j,m);if(i)for(k=h[h.length-1].ownerDocument,n.map(h,ra),m=0;i>m;m++)j=h[m],Z.test(j.type||"")&&!N.access(j,"globalEval")&&n.contains(k,j)&&(j.src?n._evalUrl&&n._evalUrl(j.src):n.globalEval(j.textContent.replace(oa,"")))}return a}function va(a,b,c){for(var d,e=b?n.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||n.cleanData(_(d)),d.parentNode&&(c&&n.contains(d.ownerDocument,d)&&aa(_(d,"script")),d.parentNode.removeChild(d));return a}n.extend({htmlPrefilter:function(a){return a.replace(ka,"<$1></$2>")},clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=_(h),f=_(a),d=0,e=f.length;e>d;d++)ta(f[d],g[d]);if(b)if(c)for(f=f||_(a),g=g||_(h),d=0,e=f.length;e>d;d++)sa(f[d],g[d]);else sa(a,h);return g=_(h,"script"),g.length>0&&aa(g,!i&&_(a,"script")),h},cleanData:function(a){for(var b,c,d,e=n.event.special,f=0;void 0!==(c=a[f]);f++)if(L(c)){if(b=c[N.expando]){if(b.events)for(d in b.events)e[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);c[N.expando]=void 0}c[O.expando]&&(c[O.expando]=void 0)}}}),n.fn.extend({domManip:ua,detach:function(a){return va(this,a,!0)},remove:function(a){return va(this,a)},text:function(a){return K(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return ua(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=pa(this,a);b.appendChild(a)}})},prepend:function(){return ua(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=pa(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return ua(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return ua(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&&(n.cleanData(_(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return K(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&&!la.test(a)&&!$[(Y.exec(a)||["",""])[1].toLowerCase()]){a=n.htmlPrefilter(a);try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(_(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return ua(this,arguments,function(b){var c=this.parentNode;n.inArray(this,a)<0&&(n.cleanData(_(this)),c&&c.replaceChild(b,this))},a)}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),f=e.length-1,h=0;f>=h;h++)c=h===f?this:this.clone(!0),n(e[h])[b](c),g.apply(d,c.get());return this.pushStack(d)}});var wa,xa={HTML:"block",BODY:"block"};function ya(a,b){var c=n(b.createElement(a)).appendTo(b.body),d=n.css(c[0],"display");return c.detach(),d}function za(a){var b=d,c=xa[a];return c||(c=ya(a,b),"none"!==c&&c||(wa=(wa||n("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=wa[0].contentDocument,b.write(),b.close(),c=ya(a,b),wa.detach()),xa[a]=c),c}var Aa=/^margin/,Ba=new RegExp("^("+S+")(?!px)[a-z%]+$","i"),Ca=function(b){var c=b.ownerDocument.defaultView;return c&&c.opener||(c=a),c.getComputedStyle(b)},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},Ea=d.documentElement;!function(){var b,c,e,f,g=d.createElement("div"),h=d.createElement("div");if(h.style){h.style.backgroundClip="content-box",h.cloneNode(!0).style.backgroundClip="",l.clearCloneStyle="content-box"===h.style.backgroundClip,g.style.cssText="border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute",g.appendChild(h);function i(){h.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;position:relative;display:block;margin:auto;border:1px;padding:1px;top:1%;width:50%",h.innerHTML="",Ea.appendChild(g);var d=a.getComputedStyle(h);b="1%"!==d.top,f="2px"===d.marginLeft,c="4px"===d.width,h.style.marginRight="50%",e="4px"===d.marginRight,Ea.removeChild(g)}n.extend(l,{pixelPosition:function(){return i(),b},boxSizingReliable:function(){return null==c&&i(),c},pixelMarginRight:function(){return null==c&&i(),e},reliableMarginLeft:function(){return null==c&&i(),f},reliableMarginRight:function(){var b,c=h.appendChild(d.createElement("div"));return c.style.cssText=h.style.cssText="-webkit-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",c.style.marginRight=c.style.width="0",h.style.width="1px",Ea.appendChild(g),b=!parseFloat(a.getComputedStyle(c).marginRight),Ea.removeChild(g),h.removeChild(c),b}})}}();function Fa(a,b,c){var d,e,f,g,h=a.style;return c=c||Ca(a),g=c?c.getPropertyValue(b)||c[b]:void 0,""!==g&&void 0!==g||n.contains(a.ownerDocument,a)||(g=n.style(a,b)),c&&!l.pixelMarginRight()&&Ba.test(g)&&Aa.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 Ga(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}var Ha=/^(none|table(?!-c[ea]).+)/,Ia={position:"absolute",visibility:"hidden",display:"block"},Ja={letterSpacing:"0",fontWeight:"400"},Ka=["Webkit","O","Moz","ms"],La=d.createElement("div").style;function Ma(a){if(a in La)return a;var b=a[0].toUpperCase()+a.slice(1),c=Ka.length;while(c--)if(a=Ka[c]+b,a in La)return a}function Na(a,b,c){var d=T.exec(b);return d?Math.max(0,d[2]-(c||0))+(d[3]||"px"):b}function Oa(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=n.css(a,c+U[f],!0,e)),d?("content"===c&&(g-=n.css(a,"padding"+U[f],!0,e)),"margin"!==c&&(g-=n.css(a,"border"+U[f]+"Width",!0,e))):(g+=n.css(a,"padding"+U[f],!0,e),"padding"!==c&&(g+=n.css(a,"border"+U[f]+"Width",!0,e)));return g}function Pa(b,c,e){var f=!0,g="width"===c?b.offsetWidth:b.offsetHeight,h=Ca(b),i="border-box"===n.css(b,"boxSizing",!1,h);if(d.msFullscreenElement&&a.top!==a&&b.getClientRects().length&&(g=Math.round(100*b.getBoundingClientRect()[c])),0>=g||null==g){if(g=Fa(b,c,h),(0>g||null==g)&&(g=b.style[c]),Ba.test(g))return g;f=i&&(l.boxSizingReliable()||g===b.style[c]),g=parseFloat(g)||0}return g+Oa(b,c,e||(i?"border":"content"),f,h)+"px"}function Qa(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=N.get(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&V(d)&&(f[g]=N.access(d,"olddisplay",za(d.nodeName)))):(e=V(d),"none"===c&&e||N.set(d,"olddisplay",e?c:n.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}n.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Fa(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=n.camelCase(b),i=a.style;return b=n.cssProps[h]||(n.cssProps[h]=Ma(h)||h),g=n.cssHooks[b]||n.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=T.exec(c))&&e[1]&&(c=W(a,b,e),f="number"),null!=c&&c===c&&("number"===f&&(c+=e&&e[3]||(n.cssNumber[h]?"":"px")),l.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=n.camelCase(b);return b=n.cssProps[h]||(n.cssProps[h]=Ma(h)||h),g=n.cssHooks[b]||n.cssHooks[h],g&&"get"in g&&(e=g.get(a,!0,c)),void 0===e&&(e=Fa(a,b,d)),"normal"===e&&b in Ja&&(e=Ja[b]),""===c||c?(f=parseFloat(e),c===!0||isFinite(f)?f||0:e):e}}),n.each(["height","width"],function(a,b){n.cssHooks[b]={get:function(a,c,d){return c?Ha.test(n.css(a,"display"))&&0===a.offsetWidth?Da(a,Ia,function(){return Pa(a,b,d)}):Pa(a,b,d):void 0},set:function(a,c,d){var e,f=d&&Ca(a),g=d&&Oa(a,b,d,"border-box"===n.css(a,"boxSizing",!1,f),f);return g&&(e=T.exec(c))&&"px"!==(e[3]||"px")&&(a.style[b]=c,c=n.css(a,b)),Na(a,c,g)}}}),n.cssHooks.marginLeft=Ga(l.reliableMarginLeft,function(a,b){return b?(parseFloat(Fa(a,"marginLeft"))||a.getBoundingClientRect().left-Da(a,{marginLeft:0},function(){return a.getBoundingClientRect().left}))+"px":void 0}),n.cssHooks.marginRight=Ga(l.reliableMarginRight,function(a,b){return b?Da(a,{display:"inline-block"},Fa,[a,"marginRight"]):void 0}),n.each({margin:"",padding:"",border:"Width"},function(a,b){n.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+U[d]+b]=f[d]||f[d-2]||f[0];return e}},Aa.test(a)||(n.cssHooks[a+b].set=Na)}),n.fn.extend({css:function(a,b){return K(this,function(a,b,c){var d,e,f={},g=0;if(n.isArray(b)){for(d=Ca(a),e=b.length;e>g;g++)f[b[g]]=n.css(a,b[g],!1,d);return f}return void 0!==c?n.style(a,b,c):n.css(a,b)},a,b,arguments.length>1)},show:function(){return Qa(this,!0)},hide:function(){return Qa(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){V(this)?n(this).show():n(this).hide()})}});function Ra(a,b,c,d,e){return new Ra.prototype.init(a,b,c,d,e)}n.Tween=Ra,Ra.prototype={constructor:Ra,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||n.easing._default,this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(n.cssNumber[c]?"":"px")},cur:function(){var a=Ra.propHooks[this.prop];return a&&a.get?a.get(this):Ra.propHooks._default.get(this)},run:function(a){var b,c=Ra.propHooks[this.prop];return this.options.duration?this.pos=b=n.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):Ra.propHooks._default.set(this),this}},Ra.prototype.init.prototype=Ra.prototype,Ra.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=n.css(a.elem,a.prop,""),b&&"auto"!==b?b:0)},set:function(a){n.fx.step[a.prop]?n.fx.step[a.prop](a):1!==a.elem.nodeType||null==a.elem.style[n.cssProps[a.prop]]&&!n.cssHooks[a.prop]?a.elem[a.prop]=a.now:n.style(a.elem,a.prop,a.now+a.unit)}}},Ra.propHooks.scrollTop=Ra.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},n.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2},_default:"swing"},n.fx=Ra.prototype.init,n.fx.step={};var Sa,Ta,Ua=/^(?:toggle|show|hide)$/,Va=/queueHooks$/;function Wa(){return a.setTimeout(function(){Sa=void 0}),Sa=n.now()}function Xa(a,b){var c,d=0,e={height:a};for(b=b?1:0;4>d;d+=2-b)c=U[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function Ya(a,b,c){for(var d,e=(_a.tweeners[b]||[]).concat(_a.tweeners["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function Za(a,b,c){var d,e,f,g,h,i,j,k,l=this,m={},o=a.style,p=a.nodeType&&V(a),q=N.get(a,"fxshow");c.queue||(h=n._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,l.always(function(){l.always(function(){h.unqueued--,n.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[o.overflow,o.overflowX,o.overflowY],j=n.css(a,"display"),k="none"===j?N.get(a,"olddisplay")||za(a.nodeName):j,"inline"===k&&"none"===n.css(a,"float")&&(o.display="inline-block")),c.overflow&&(o.overflow="hidden",l.always(function(){o.overflow=c.overflow[0],o.overflowX=c.overflow[1],o.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],Ua.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(p?"hide":"show")){if("show"!==e||!q||void 0===q[d])continue;p=!0}m[d]=q&&q[d]||n.style(a,d)}else j=void 0;if(n.isEmptyObject(m))"inline"===("none"===j?za(a.nodeName):j)&&(o.display=j);else{q?"hidden"in q&&(p=q.hidden):q=N.access(a,"fxshow",{}),f&&(q.hidden=!p),p?n(a).show():l.done(function(){n(a).hide()}),l.done(function(){var b;N.remove(a,"fxshow");for(b in m)n.style(a,b,m[b])});for(d in m)g=Ya(p?q[d]:0,d,l),d in q||(q[d]=g.start,p&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function $a(a,b){var c,d,e,f,g;for(c in a)if(d=n.camelCase(c),e=b[d],f=a[c],n.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=n.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 _a(a,b,c){var d,e,f=0,g=_a.prefilters.length,h=n.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=Sa||Wa(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:n.extend({},b),opts:n.extend(!0,{specialEasing:{},easing:n.easing._default},c),originalProperties:b,originalOptions:c,startTime:Sa||Wa(),duration:c.duration,tweens:[],createTween:function(b,c){var d=n.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;d>c;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($a(k,j.opts.specialEasing);g>f;f++)if(d=_a.prefilters[f].call(j,a,k,j.opts))return n.isFunction(d.stop)&&(n._queueHooks(j.elem,j.opts.queue).stop=n.proxy(d.stop,d)),d;return n.map(k,Ya,j),n.isFunction(j.opts.start)&&j.opts.start.call(a,j),n.fx.timer(n.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)}n.Animation=n.extend(_a,{tweeners:{"*":[function(a,b){var c=this.createTween(a,b);return W(c.elem,a,T.exec(b),c),c}]},tweener:function(a,b){n.isFunction(a)?(b=a,a=["*"]):a=a.match(G);for(var c,d=0,e=a.length;e>d;d++)c=a[d],_a.tweeners[c]=_a.tweeners[c]||[],_a.tweeners[c].unshift(b)},prefilters:[Za],prefilter:function(a,b){b?_a.prefilters.unshift(a):_a.prefilters.push(a)}}),n.speed=function(a,b,c){var d=a&&"object"==typeof a?n.extend({},a):{complete:c||!c&&b||n.isFunction(a)&&a,duration:a,easing:c&&b||b&&!n.isFunction(b)&&b};return d.duration=n.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in n.fx.speeds?n.fx.speeds[d.duration]:n.fx.speeds._default,null!=d.queue&&d.queue!==!0||(d.queue="fx"),d.old=d.complete,d.complete=function(){n.isFunction(d.old)&&d.old.call(this),d.queue&&n.dequeue(this,d.queue)},d},n.fn.extend({fadeTo:function(a,b,c,d){return this.filter(V).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=n.isEmptyObject(a),f=n.speed(b,c,d),g=function(){var b=_a(this,n.extend({},a),f);(e||N.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=n.timers,g=N.get(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&Va.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||n.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=N.get(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=n.timers,g=d?d.length:0;for(c.finish=!0,n.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;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),n.each(["toggle","show","hide"],function(a,b){var c=n.fn[b];n.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(Xa(b,!0),a,d,e)}}),n.each({slideDown:Xa("show"),slideUp:Xa("hide"),slideToggle:Xa("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){n.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),n.timers=[],n.fx.tick=function(){var a,b=0,c=n.timers;for(Sa=n.now();b<c.length;b++)a=c[b],a()||c[b]!==a||c.splice(b--,1);c.length||n.fx.stop(),Sa=void 0},n.fx.timer=function(a){n.timers.push(a),a()?n.fx.start():n.timers.pop()},n.fx.interval=13,n.fx.start=function(){Ta||(Ta=a.setInterval(n.fx.tick,n.fx.interval))},n.fx.stop=function(){a.clearInterval(Ta),Ta=null},n.fx.speeds={slow:600,fast:200,_default:400},n.fn.delay=function(b,c){return b=n.fx?n.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",l.checkOn=""!==a.value,l.optSelected=c.selected,b.disabled=!0,l.optDisabled=!c.disabled,a=d.createElement("input"),a.value="t",a.type="radio",l.radioValue="t"===a.value}();var ab,bb=n.expr.attrHandle;n.fn.extend({attr:function(a,b){return K(this,n.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){n.removeAttr(this,a)})}}),n.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return"undefined"==typeof a.getAttribute?n.prop(a,b,c):(1===f&&n.isXMLDoc(a)||(b=b.toLowerCase(),e=n.attrHooks[b]||(n.expr.match.bool.test(b)?ab:void 0)),void 0!==c?null===c?void n.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=n.find.attr(a,b),null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!l.radioValue&&"radio"===b&&n.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(G);if(f&&1===a.nodeType)while(c=f[e++])d=n.propFix[c]||c,n.expr.match.bool.test(c)&&(a[d]=!1),a.removeAttribute(c)}}),ab={set:function(a,b,c){return b===!1?n.removeAttr(a,c):a.setAttribute(c,c),c}},n.each(n.expr.match.bool.source.match(/\w+/g),function(a,b){var c=bb[b]||n.find.attr;bb[b]=function(a,b,d){var e,f;return d||(f=bb[b],bb[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,bb[b]=f),e}});var cb=/^(?:input|select|textarea|button)$/i,db=/^(?:a|area)$/i;n.fn.extend({prop:function(a,b){return K(this,n.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[n.propFix[a]||a]})}}),n.extend({prop:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return 1===f&&n.isXMLDoc(a)||(b=n.propFix[b]||b, +e=n.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=n.find.attr(a,"tabindex");return b?parseInt(b,10):cb.test(a.nodeName)||db.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),l.optSelected||(n.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)}}),n.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){n.propFix[this.toLowerCase()]=this});var eb=/[\t\r\n\f]/g;function fb(a){return a.getAttribute&&a.getAttribute("class")||""}n.fn.extend({addClass:function(a){var b,c,d,e,f,g,h,i=0;if(n.isFunction(a))return this.each(function(b){n(this).addClass(a.call(this,b,fb(this)))});if("string"==typeof a&&a){b=a.match(G)||[];while(c=this[i++])if(e=fb(c),d=1===c.nodeType&&(" "+e+" ").replace(eb," ")){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=n.trim(d),e!==h&&c.setAttribute("class",h)}}return this},removeClass:function(a){var b,c,d,e,f,g,h,i=0;if(n.isFunction(a))return this.each(function(b){n(this).removeClass(a.call(this,b,fb(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(G)||[];while(c=this[i++])if(e=fb(c),d=1===c.nodeType&&(" "+e+" ").replace(eb," ")){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=n.trim(d),e!==h&&c.setAttribute("class",h)}}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):n.isFunction(a)?this.each(function(c){n(this).toggleClass(a.call(this,c,fb(this),b),b)}):this.each(function(){var b,d,e,f;if("string"===c){d=0,e=n(this),f=a.match(G)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else void 0!==a&&"boolean"!==c||(b=fb(this),b&&N.set(this,"__className__",b),this.setAttribute&&this.setAttribute("class",b||a===!1?"":N.get(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+fb(c)+" ").replace(eb," ").indexOf(b)>-1)return!0;return!1}});var gb=/\r/g,hb=/[\x20\t\r\n\f]+/g;n.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=n.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,n(this).val()):a,null==e?e="":"number"==typeof e?e+="":n.isArray(e)&&(e=n.map(e,function(a){return null==a?"":a+""})),b=n.valHooks[this.type]||n.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=n.valHooks[e.type]||n.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(gb,""):null==c?"":c)}}}),n.extend({valHooks:{option:{get:function(a){var b=n.find.attr(a,"value");return null!=b?b:n.trim(n.text(a)).replace(hb," ")}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],(c.selected||i===e)&&(l.optDisabled?!c.disabled:null===c.getAttribute("disabled"))&&(!c.parentNode.disabled||!n.nodeName(c.parentNode,"optgroup"))){if(b=n(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=n.makeArray(b),g=e.length;while(g--)d=e[g],(d.selected=n.inArray(n.valHooks.option.get(d),f)>-1)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),n.each(["radio","checkbox"],function(){n.valHooks[this]={set:function(a,b){return n.isArray(b)?a.checked=n.inArray(n(a).val(),b)>-1:void 0}},l.checkOn||(n.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var ib=/^(?:focusinfocus|focusoutblur)$/;n.extend(n.event,{trigger:function(b,c,e,f){var g,h,i,j,l,m,o,p=[e||d],q=k.call(b,"type")?b.type:b,r=k.call(b,"namespace")?b.namespace.split("."):[];if(h=i=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!ib.test(q+n.event.triggered)&&(q.indexOf(".")>-1&&(r=q.split("."),q=r.shift(),r.sort()),l=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=r.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},f||!o.trigger||o.trigger.apply(e,c)!==!1)){if(!f&&!o.noBubble&&!n.isWindow(e)){for(j=o.delegateType||q,ib.test(j+q)||(h=h.parentNode);h;h=h.parentNode)p.push(h),i=h;i===(e.ownerDocument||d)&&p.push(i.defaultView||i.parentWindow||a)}g=0;while((h=p[g++])&&!b.isPropagationStopped())b.type=g>1?j:o.bindType||q,m=(N.get(h,"events")||{})[b.type]&&N.get(h,"handle"),m&&m.apply(h,c),m=l&&h[l],m&&m.apply&&L(h)&&(b.result=m.apply(h,c),b.result===!1&&b.preventDefault());return b.type=q,f||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!L(e)||l&&n.isFunction(e[q])&&!n.isWindow(e)&&(i=e[l],i&&(e[l]=null),n.event.triggered=q,e[q](),n.event.triggered=void 0,i&&(e[l]=i)),b.result}},simulate:function(a,b,c){var d=n.extend(new n.Event,c,{type:a,isSimulated:!0});n.event.trigger(d,null,b),d.isDefaultPrevented()&&c.preventDefault()}}),n.fn.extend({trigger:function(a,b){return this.each(function(){n.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?n.event.trigger(a,b,c,!0):void 0}}),n.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){n.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),n.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),l.focusin="onfocusin"in a,l.focusin||n.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){n.event.simulate(b,a.target,n.event.fix(a))};n.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=N.access(d,b);e||d.addEventListener(a,c,!0),N.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=N.access(d,b)-1;e?N.access(d,b,e):(d.removeEventListener(a,c,!0),N.remove(d,b))}}});var jb=a.location,kb=n.now(),lb=/\?/;n.parseJSON=function(a){return JSON.parse(a+"")},n.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||n.error("Invalid XML: "+b),c};var mb=/#.*$/,nb=/([?&])_=[^&]*/,ob=/^(.*?):[ \t]*([^\r\n]*)$/gm,pb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,qb=/^(?:GET|HEAD)$/,rb=/^\/\//,sb={},tb={},ub="*/".concat("*"),vb=d.createElement("a");vb.href=jb.href;function wb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(G)||[];if(n.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 xb(a,b,c,d){var e={},f=a===tb;function g(h){var i;return e[h]=!0,n.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 yb(a,b){var c,d,e=n.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&n.extend(!0,a,d),a}function zb(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}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function Ab(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}}n.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:jb.href,type:"GET",isLocal:pb.test(jb.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":ub,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":n.parseJSON,"text xml":n.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?yb(yb(a,n.ajaxSettings),b):yb(n.ajaxSettings,a)},ajaxPrefilter:wb(sb),ajaxTransport:wb(tb),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.ajaxSetup({},c),o=m.context||m,p=m.context&&(o.nodeType||o.jquery)?n(o):n.event,q=n.Deferred(),r=n.Callbacks("once memory"),s=m.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,getResponseHeader:function(a){var b;if(2===v){if(!h){h={};while(b=ob.exec(g))h[b[1].toLowerCase()]=b[2]}b=h[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===v?g:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return v||(a=u[c]=u[c]||a,t[a]=b),this},overrideMimeType:function(a){return v||(m.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>v)for(b in a)s[b]=[s[b],a[b]];else x.always(a[x.status]);return this},abort:function(a){var b=a||w;return e&&e.abort(b),z(0,b),this}};if(q.promise(x).complete=r.add,x.success=x.done,x.error=x.fail,m.url=((b||m.url||jb.href)+"").replace(mb,"").replace(rb,jb.protocol+"//"),m.type=c.method||c.type||m.method||m.type,m.dataTypes=n.trim(m.dataType||"*").toLowerCase().match(G)||[""],null==m.crossDomain){j=d.createElement("a");try{j.href=m.url,j.href=j.href,m.crossDomain=vb.protocol+"//"+vb.host!=j.protocol+"//"+j.host}catch(y){m.crossDomain=!0}}if(m.data&&m.processData&&"string"!=typeof m.data&&(m.data=n.param(m.data,m.traditional)),xb(sb,m,c,x),2===v)return x;k=n.event&&m.global,k&&0===n.active++&&n.event.trigger("ajaxStart"),m.type=m.type.toUpperCase(),m.hasContent=!qb.test(m.type),f=m.url,m.hasContent||(m.data&&(f=m.url+=(lb.test(f)?"&":"?")+m.data,delete m.data),m.cache===!1&&(m.url=nb.test(f)?f.replace(nb,"$1_="+kb++):f+(lb.test(f)?"&":"?")+"_="+kb++)),m.ifModified&&(n.lastModified[f]&&x.setRequestHeader("If-Modified-Since",n.lastModified[f]),n.etag[f]&&x.setRequestHeader("If-None-Match",n.etag[f])),(m.data&&m.hasContent&&m.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",m.contentType),x.setRequestHeader("Accept",m.dataTypes[0]&&m.accepts[m.dataTypes[0]]?m.accepts[m.dataTypes[0]]+("*"!==m.dataTypes[0]?", "+ub+"; q=0.01":""):m.accepts["*"]);for(l in m.headers)x.setRequestHeader(l,m.headers[l]);if(m.beforeSend&&(m.beforeSend.call(o,x,m)===!1||2===v))return x.abort();w="abort";for(l in{success:1,error:1,complete:1})x[l](m[l]);if(e=xb(tb,m,c,x)){if(x.readyState=1,k&&p.trigger("ajaxSend",[x,m]),2===v)return x;m.async&&m.timeout>0&&(i=a.setTimeout(function(){x.abort("timeout")},m.timeout));try{v=1,e.send(t,z)}catch(y){if(!(2>v))throw y;z(-1,y)}}else z(-1,"No Transport");function z(b,c,d,h){var j,l,t,u,w,y=c;2!==v&&(v=2,i&&a.clearTimeout(i),e=void 0,g=h||"",x.readyState=b>0?4:0,j=b>=200&&300>b||304===b,d&&(u=zb(m,x,d)),u=Ab(m,u,x,j),j?(m.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(n.lastModified[f]=w),w=x.getResponseHeader("etag"),w&&(n.etag[f]=w)),204===b||"HEAD"===m.type?y="nocontent":304===b?y="notmodified":(y=u.state,l=u.data,t=u.error,j=!t)):(t=y,!b&&y||(y="error",0>b&&(b=0))),x.status=b,x.statusText=(c||y)+"",j?q.resolveWith(o,[l,y,x]):q.rejectWith(o,[x,y,t]),x.statusCode(s),s=void 0,k&&p.trigger(j?"ajaxSuccess":"ajaxError",[x,m,j?l:t]),r.fireWith(o,[x,y]),k&&(p.trigger("ajaxComplete",[x,m]),--n.active||n.event.trigger("ajaxStop")))}return x},getJSON:function(a,b,c){return n.get(a,b,c,"json")},getScript:function(a,b){return n.get(a,void 0,b,"script")}}),n.each(["get","post"],function(a,b){n[b]=function(a,c,d,e){return n.isFunction(c)&&(e=e||d,d=c,c=void 0),n.ajax(n.extend({url:a,type:b,dataType:e,data:c,success:d},n.isPlainObject(a)&&a))}}),n._evalUrl=function(a){return n.ajax({url:a,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},n.fn.extend({wrapAll:function(a){var b;return n.isFunction(a)?this.each(function(b){n(this).wrapAll(a.call(this,b))}):(this[0]&&(b=n(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 n.isFunction(a)?this.each(function(b){n(this).wrapInner(a.call(this,b))}):this.each(function(){var b=n(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=n.isFunction(a);return this.each(function(c){n(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){n.nodeName(this,"body")||n(this).replaceWith(this.childNodes)}).end()}}),n.expr.filters.hidden=function(a){return!n.expr.filters.visible(a)},n.expr.filters.visible=function(a){return a.offsetWidth>0||a.offsetHeight>0||a.getClientRects().length>0};var Bb=/%20/g,Cb=/\[\]$/,Db=/\r?\n/g,Eb=/^(?:submit|button|image|reset|file)$/i,Fb=/^(?:input|select|textarea|keygen)/i;function Gb(a,b,c,d){var e;if(n.isArray(b))n.each(b,function(b,e){c||Cb.test(a)?d(a,e):Gb(a+"["+("object"==typeof e&&null!=e?b:"")+"]",e,c,d)});else if(c||"object"!==n.type(b))d(a,b);else for(e in b)Gb(a+"["+e+"]",b[e],c,d)}n.param=function(a,b){var c,d=[],e=function(a,b){b=n.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=n.ajaxSettings&&n.ajaxSettings.traditional),n.isArray(a)||a.jquery&&!n.isPlainObject(a))n.each(a,function(){e(this.name,this.value)});else for(c in a)Gb(c,a[c],b,e);return d.join("&").replace(Bb,"+")},n.fn.extend({serialize:function(){return n.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=n.prop(this,"elements");return a?n.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!n(this).is(":disabled")&&Fb.test(this.nodeName)&&!Eb.test(a)&&(this.checked||!X.test(a))}).map(function(a,b){var c=n(this).val();return null==c?null:n.isArray(c)?n.map(c,function(a){return{name:b.name,value:a.replace(Db,"\r\n")}}):{name:b.name,value:c.replace(Db,"\r\n")}}).get()}}),n.ajaxSettings.xhr=function(){try{return new a.XMLHttpRequest}catch(b){}};var Hb={0:200,1223:204},Ib=n.ajaxSettings.xhr();l.cors=!!Ib&&"withCredentials"in Ib,l.ajax=Ib=!!Ib,n.ajaxTransport(function(b){var c,d;return l.cors||Ib&&!b.crossDomain?{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(Hb[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()}}:void 0}),n.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 n.globalEval(a),a}}}),n.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),n.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(e,f){b=n("<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 Jb=[],Kb=/(=)\?(?=&|$)|\?\?/;n.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=Jb.pop()||n.expando+"_"+kb++;return this[a]=!0,a}}),n.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(Kb.test(b.url)?"url":"string"==typeof b.data&&0===(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&Kb.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=n.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(Kb,"$1"+e):b.jsonp!==!1&&(b.url+=(lb.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||n.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?n(a).removeProp(e):a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,Jb.push(e)),g&&n.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),n.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||d;var e=x.exec(a),f=!c&&[];return e?[b.createElement(e[1])]:(e=ca([a],b,f),f&&f.length&&n(f).remove(),n.merge([],e.childNodes))};var Lb=n.fn.load;n.fn.load=function(a,b,c){if("string"!=typeof a&&Lb)return Lb.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>-1&&(d=n.trim(a.slice(h)),a=a.slice(0,h)),n.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(e="POST"),g.length>0&&n.ajax({url:a,type:e||"GET",dataType:"html",data:b}).done(function(a){f=arguments,g.html(d?n("<div>").append(n.parseHTML(a)).find(d):a)}).always(c&&function(a,b){g.each(function(){c.apply(this,f||[a.responseText,b,a])})}),this},n.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){n.fn[b]=function(a){return this.on(b,a)}}),n.expr.filters.animated=function(a){return n.grep(n.timers,function(b){return a===b.elem}).length};function Mb(a){return n.isWindow(a)?a:9===a.nodeType&&a.defaultView}n.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=n.css(a,"position"),l=n(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=n.css(a,"top"),i=n.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),n.isFunction(b)&&(b=b.call(a,c,n.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)}},n.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){n.offset.setOffset(this,a,b)});var b,c,d=this[0],e={top:0,left:0},f=d&&d.ownerDocument;if(f)return b=f.documentElement,n.contains(b,d)?(e=d.getBoundingClientRect(),c=Mb(f),{top:e.top+c.pageYOffset-b.clientTop,left:e.left+c.pageXOffset-b.clientLeft}):e},position:function(){if(this[0]){var a,b,c=this[0],d={top:0,left:0};return"fixed"===n.css(c,"position")?b=c.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),n.nodeName(a[0],"html")||(d=a.offset()),d.top+=n.css(a[0],"borderTopWidth",!0),d.left+=n.css(a[0],"borderLeftWidth",!0)),{top:b.top-d.top-n.css(c,"marginTop",!0),left:b.left-d.left-n.css(c,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent;while(a&&"static"===n.css(a,"position"))a=a.offsetParent;return a||Ea})}}),n.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c="pageYOffset"===b;n.fn[a]=function(d){return K(this,function(a,d,e){var f=Mb(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)}}),n.each(["top","left"],function(a,b){n.cssHooks[b]=Ga(l.pixelPosition,function(a,c){return c?(c=Fa(a,b),Ba.test(c)?n(a).position()[b]+"px":c):void 0})}),n.each({Height:"height",Width:"width"},function(a,b){n.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){n.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return K(this,function(b,c,d){var e;return n.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?n.css(b,c,g):n.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),n.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)},size:function(){return this.length}}),n.fn.andSelf=n.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return n});var Nb=a.jQuery,Ob=a.$;return n.noConflict=function(b){return a.$===n&&(a.$=Ob),b&&a.jQuery===n&&(a.jQuery=Nb),n},b||(a.jQuery=a.$=n),n}); diff --git a/http/3rdParty/jquery-scrollstop-master/LICENSE.md b/http/3rdParty/jquery-scrollstop-master/LICENSE.md new file mode 100644 index 0000000..3bddfec --- /dev/null +++ b/http/3rdParty/jquery-scrollstop-master/LICENSE.md @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to <http://unlicense.org/> diff --git a/http/3rdParty/jquery-scrollstop-master/README.md b/http/3rdParty/jquery-scrollstop-master/README.md new file mode 100644 index 0000000..0a0f2b8 --- /dev/null +++ b/http/3rdParty/jquery-scrollstop-master/README.md @@ -0,0 +1,66 @@ +jquery-scrollstop +================= + +This plugin fires two events on `window` when scrolling starts and stops: +`scrollstart` and `scrollstop`. + +## Example + +The example shows a small box in the upper left that says "SCROLLING" and +colors the body different colors when scrolling: http://ssorallen.com/jquery-scrollstop/ + +## Usage + +`scrollstart` fires after the first scroll event and won't fire again until +after a `scrollstop` event is fired. + +`scrollstop` fires after no `scroll` events have fired for 250 milliseconds. + +```js +$(window) + .on("scrollstart", function() { + // Paint the world yellow when scrolling starts. + $(document.body).css({background: "yellow"}); + }) + .on("scrollstop", function() { + // Paint it all green when scrolling stops. + $(document.body).css({background: "green"}); + }) +``` + +### Configuration + +#### latency + +`latency` is the minimum time between the last scroll event and when the +`scrollstop` event fires. Set `$.event.special.scrollstop.latency` to the +desired number of milliseconds (default: 250). + +```js +// Configure time between final scroll event and +// `scrollstop` event to 650ms (default is 250ms). +$.event.special.scrollstop.latency = 650; +``` + +##### latency per element + +Latency can be configured per-element by passing options when the event listener +is bound. If multiple event listeners are bound to the same element, only the +data from the first event listener will set the configuration. + +```js +// Configure latency to 650ms for #scrolling-div +$("#scrolling-div").on("scrollstop", {latency: 650}, function() { ... }); +``` + +### jQuery Version Support + +The plugin is tested in jQuery 1.2.3+ and jQuery 2.0.3+. + +### Attribution + +James Padolsey's jQuery scrollstop plugin that fires an event when scrolling +stops for minimum amount of time. + +Originally code copied from +http://james.padolsey.com/javascript/special-scroll-events-for-jquery/ diff --git a/http/3rdParty/jquery-scrollstop-master/index.html b/http/3rdParty/jquery-scrollstop-master/index.html new file mode 100644 index 0000000..6c2c06f --- /dev/null +++ b/http/3rdParty/jquery-scrollstop-master/index.html @@ -0,0 +1,159 @@ +<!DOCTYPE html> +<!-- Originally written by James Padolsey at + http://james.padolsey.com/demos/scrollevents/ --> +<html lang="en"> + <head> + <title>ScrollStop & ScrollStart special events for JQuery + + + +
+

SCROLL THIS PAGE (JavaScript required to see demo in action!)

+

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus

+

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus

+

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus

+

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus

+

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus

+

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus

+

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus

+

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus

+

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus

+

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus

+

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus

+

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus

+

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus

+

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus

+

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus

+
+
+
+

SCROLL THIS DIV (2000ms latency)

+

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus

+

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus

+

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus

+

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus

+

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus

+

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus

+

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus

+
+
+

SCROLL THIS DIV (500ms latency)

+

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus

+

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus

+

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus

+

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus

+

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus

+

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus

+

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus

+
+
+ + + + + + diff --git a/http/3rdParty/jquery-scrollstop-master/jquery.scrollstop.js b/http/3rdParty/jquery-scrollstop-master/jquery.scrollstop.js new file mode 100644 index 0000000..68048b5 --- /dev/null +++ b/http/3rdParty/jquery-scrollstop-master/jquery.scrollstop.js @@ -0,0 +1,78 @@ +/*! + * jQuery Scrollstop Plugin v1.1.0 + * https://github.com/ssorallen/jquery-scrollstop + */ +(function($) { + // $.event.dispatch was undocumented and was deprecated in jQuery 1.7[1]. It + // was replaced by $.event.handle in jQuery 1.9. + // + // Use the first of the available functions to support jQuery <1.8. + // + // [1] https://github.com/jquery/jquery-migrate/blob/master/src/event.js#L25 + var dispatch = $.event.dispatch || $.event.handle; + + var special = $.event.special, + uid1 = 'D' + (+new Date()), + uid2 = 'D' + (+new Date() + 1); + + special.scrollstart = { + setup: function(data) { + var _data = $.extend({ + latency: special.scrollstop.latency + }, data); + + var timer, + handler = function(evt) { + var _self = this, + _args = arguments; + + if (timer) { + clearTimeout(timer); + } else { + evt.type = 'scrollstart'; + dispatch.apply(_self, _args); + } + + timer = setTimeout(function() { + timer = null; + }, _data.latency); + }; + + $(this).bind('scroll', handler).data(uid1, handler); + }, + teardown: function() { + $(this).unbind('scroll', $(this).data(uid1)); + } + }; + + special.scrollstop = { + latency: 250, + setup: function(data) { + var _data = $.extend({ + latency: special.scrollstop.latency + }, data); + + var timer, + handler = function(evt) { + var _self = this, + _args = arguments; + + if (timer) { + clearTimeout(timer); + } + + timer = setTimeout(function() { + timer = null; + evt.type = 'scrollstop'; + dispatch.apply(_self, _args); + }, _data.latency); + }; + + $(this).bind('scroll', handler).data(uid2, handler); + }, + teardown: function() { + $(this).unbind('scroll', $(this).data(uid2)); + } + }; + +})(jQuery); diff --git a/http/3rdParty/jquery-scrollstop-master/jquery.scrollstop.min.js b/http/3rdParty/jquery-scrollstop-master/jquery.scrollstop.min.js new file mode 100644 index 0000000..cbb9fe5 --- /dev/null +++ b/http/3rdParty/jquery-scrollstop-master/jquery.scrollstop.min.js @@ -0,0 +1,5 @@ +/*! + * jQuery Scrollstop Plugin v1.1.0 + * https://github.com/ssorallen/jquery-scrollstop + */ +(function(e){var b=e.event.dispatch||e.event.handle;var a=e.event.special,d="D"+(+new Date()),c="D"+(+new Date()+1);a.scrollstart={setup:function(h){var g=e.extend({latency:a.scrollstop.latency},h);var i,f=function(l){var j=this,k=arguments;if(i){clearTimeout(i)}else{l.type="scrollstart";b.apply(j,k)}i=setTimeout(function(){i=null},g.latency)};e(this).bind("scroll",f).data(d,f)},teardown:function(){e(this).unbind("scroll",e(this).data(d))}};a.scrollstop={latency:250,setup:function(h){var g=e.extend({latency:a.scrollstop.latency},h);var i,f=function(l){var j=this,k=arguments;if(i){clearTimeout(i)}i=setTimeout(function(){i=null;l.type="scrollstop";b.apply(j,k)},g.latency)};e(this).bind("scroll",f).data(c,f)},teardown:function(){e(this).unbind("scroll",e(this).data(c))}}})(jQuery); \ No newline at end of file diff --git a/http/3rdParty/jquery-scrollstop-master/scrollstop.jquery.json b/http/3rdParty/jquery-scrollstop-master/scrollstop.jquery.json new file mode 100644 index 0000000..218f541 --- /dev/null +++ b/http/3rdParty/jquery-scrollstop-master/scrollstop.jquery.json @@ -0,0 +1,19 @@ +{ + "name": "scrollstop", + "version": "1.1.0", + + "author": { + "name": "James Padolsey", + "url": "http://james.padolsey.com/javascript/special-scroll-events-for-jquery/" + }, + "dependencies": { + "jquery": ">=1.2.3" + }, + "description": "jQuery plugin that adds custom scroll start and scroll stop events.", + "homepage": "https://github.com/ssorallen/jquery-scrollstop", + "maintainer": { + "name": "Ross Allen", + "url": "https://github.com/ssorallen/" + }, + "title": "jQuery Scrollstop" +} diff --git a/http/3rdParty/jquery-ui-1.11.4.custom/external/jquery/jquery.js b/http/3rdParty/jquery-ui-1.11.4.custom/external/jquery/jquery.js new file mode 100644 index 0000000..c5c64825 --- /dev/null +++ b/http/3rdParty/jquery-ui-1.11.4.custom/external/jquery/jquery.js @@ -0,0 +1,9789 @@ +/*! + * jQuery JavaScript Library v1.10.2 + * http://jquery.com/ + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * + * Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2013-07-03T13:48Z + */ +(function( window, undefined ) { + +// Can't do this because several apps including ASP.NET trace +// the stack via arguments.caller.callee and Firefox dies if +// you try to trace through "use strict" call chains. (#13335) +// Support: Firefox 18+ +//"use strict"; +var + // The deferred used on DOM ready + readyList, + + // A central reference to the root jQuery(document) + rootjQuery, + + // Support: IE<10 + // For `typeof xmlNode.method` instead of `xmlNode.method !== undefined` + core_strundefined = typeof undefined, + + // Use the correct document accordingly with window argument (sandbox) + location = window.location, + document = window.document, + docElem = document.documentElement, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // [[Class]] -> type pairs + class2type = {}, + + // List of deleted data cache ids, so we can reuse them + core_deletedIds = [], + + core_version = "1.10.2", + + // Save a reference to some core methods + core_concat = core_deletedIds.concat, + core_push = core_deletedIds.push, + core_slice = core_deletedIds.slice, + core_indexOf = core_deletedIds.indexOf, + core_toString = class2type.toString, + core_hasOwn = class2type.hasOwnProperty, + core_trim = core_version.trim, + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context, rootjQuery ); + }, + + // Used for matching numbers + core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source, + + // Used for splitting on whitespace + core_rnotwhite = /\S+/g, + + // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE) + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g, + rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g, + + // Matches dashed string for camelizing + rmsPrefix = /^-ms-/, + rdashAlpha = /-([\da-z])/gi, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }, + + // The ready event handler + completed = function( event ) { + + // readyState === "complete" is good enough for us to call the dom ready in oldIE + if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) { + detach(); + jQuery.ready(); + } + }, + // Clean-up method for dom ready events + detach = function() { + if ( document.addEventListener ) { + document.removeEventListener( "DOMContentLoaded", completed, false ); + window.removeEventListener( "load", completed, false ); + + } else { + document.detachEvent( "onreadystatechange", completed ); + window.detachEvent( "onload", completed ); + } + }; + +jQuery.fn = jQuery.prototype = { + // The current version of jQuery being used + jquery: core_version, + + constructor: jQuery, + init: function( selector, context, rootjQuery ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + + // scripts is true for back-compat + jQuery.merge( this, jQuery.parseHTML( + match[1], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + // Properties of context are called as methods if possible + if ( jQuery.isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || rootjQuery ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if ( selector.selector !== undefined ) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return core_slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + ret.context = this.context; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Add the callback + jQuery.ready.promise().done( fn ); + + return this; + }, + + slice: function() { + return this.pushStack( core_slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: core_push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + var src, copyIsArray, copy, name, options, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + // Unique for each copy of jQuery on the page + // Non-digits removed to match rinlinejQuery + expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" ), + + noConflict: function( deep ) { + if ( window.$ === jQuery ) { + window.$ = _$; + } + + if ( deep && window.jQuery === jQuery ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger("ready").off("ready"); + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + isWindow: function( obj ) { + /* jshint eqeqeq: false */ + return obj != null && obj == obj.window; + }, + + isNumeric: function( obj ) { + return !isNaN( parseFloat(obj) ) && isFinite( obj ); + }, + + type: function( obj ) { + if ( obj == null ) { + return String( obj ); + } + return typeof obj === "object" || typeof obj === "function" ? + class2type[ core_toString.call(obj) ] || "object" : + typeof obj; + }, + + isPlainObject: function( obj ) { + var key; + + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + try { + // Not own constructor property must be Object + if ( obj.constructor && + !core_hasOwn.call(obj, "constructor") && + !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + } catch ( e ) { + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } + + // Support: IE<9 + // Handle iteration over inherited properties before own properties. + if ( jQuery.support.ownLast ) { + for ( key in obj ) { + return core_hasOwn.call( obj, key ); + } + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + for ( key in obj ) {} + + return key === undefined || core_hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + var name; + for ( name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw new Error( msg ); + }, + + // data: string of html + // context (optional): If specified, the fragment will be created in this context, defaults to document + // keepScripts (optional): If true, will include scripts passed in the html string + parseHTML: function( data, context, keepScripts ) { + if ( !data || typeof data !== "string" ) { + return null; + } + if ( typeof context === "boolean" ) { + keepScripts = context; + context = false; + } + context = context || document; + + var parsed = rsingleTag.exec( data ), + scripts = !keepScripts && []; + + // Single tag + if ( parsed ) { + return [ context.createElement( parsed[1] ) ]; + } + + parsed = jQuery.buildFragment( [ data ], context, scripts ); + if ( scripts ) { + jQuery( scripts ).remove(); + } + return jQuery.merge( [], parsed.childNodes ); + }, + + parseJSON: function( data ) { + // Attempt to parse using the native JSON parser first + if ( window.JSON && window.JSON.parse ) { + return window.JSON.parse( data ); + } + + if ( data === null ) { + return data; + } + + if ( typeof data === "string" ) { + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + if ( data ) { + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test( data.replace( rvalidescape, "@" ) + .replace( rvalidtokens, "]" ) + .replace( rvalidbraces, "")) ) { + + return ( new Function( "return " + data ) )(); + } + } + } + + jQuery.error( "Invalid JSON: " + data ); + }, + + // Cross-browser xml parsing + parseXML: function( data ) { + var xml, tmp; + if ( !data || typeof data !== "string" ) { + return null; + } + try { + if ( window.DOMParser ) { // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + } catch( e ) { + xml = undefined; + } + if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; + }, + + noop: function() {}, + + // Evaluates a script in a global context + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && jQuery.trim( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + } )( data ); + } + }, + + // Convert dashed to camelCase; used by the css and data modules + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + }, + + // args is for internal usage only + each: function( obj, callback, args ) { + var value, + i = 0, + length = obj.length, + isArray = isArraylike( obj ); + + if ( args ) { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } + } + + return obj; + }, + + // Use native String.trim function wherever possible + trim: core_trim && !core_trim.call("\uFEFF\xA0") ? + function( text ) { + return text == null ? + "" : + core_trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArraylike( Object(arr) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + core_push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + var len; + + if ( arr ) { + if ( core_indexOf ) { + return core_indexOf.call( arr, elem, i ); + } + + len = arr.length; + i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; + + for ( ; i < len; i++ ) { + // Skip accessing in sparse arrays + if ( i in arr && arr[ i ] === elem ) { + return i; + } + } + } + + return -1; + }, + + merge: function( first, second ) { + var l = second.length, + i = first.length, + j = 0; + + if ( typeof l === "number" ) { + for ( ; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var retVal, + ret = [], + i = 0, + length = elems.length; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, + i = 0, + length = elems.length, + isArray = isArraylike( elems ), + ret = []; + + // Go through the array, translating each of the items to their + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + } + + // Flatten any nested arrays + return core_concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + var args, proxy, tmp; + + if ( typeof context === "string" ) { + tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + args = core_slice.call( arguments, 2 ); + proxy = function() { + return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || jQuery.guid++; + + return proxy; + }, + + // Multifunctional method to get and set values of a collection + // The value/s can optionally be executed if it's a function + access: function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + length = elems.length, + bulk = key == null; + + // Sets many values + if ( jQuery.type( key ) === "object" ) { + chainable = true; + for ( i in key ) { + jQuery.access( elems, fn, i, key[i], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !jQuery.isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < length; i++ ) { + fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) ); + } + } + } + + return chainable ? + elems : + + // Gets + bulk ? + fn.call( elems ) : + length ? fn( elems[0], key ) : emptyGet; + }, + + now: function() { + return ( new Date() ).getTime(); + }, + + // A method for quickly swapping in/out CSS properties to get correct calculations. + // Note: this method belongs to the css module but it's needed here for the support module. + // If support gets modularized, this method should be moved back to the css module. + swap: function( elem, options, callback, args ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.apply( elem, args || [] ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; + } +}); + +jQuery.ready.promise = function( obj ) { + if ( !readyList ) { + + readyList = jQuery.Deferred(); + + // Catch cases where $(document).ready() is called after the browser event has already occurred. + // we once tried to use readyState "interactive" here, but it caused issues like the one + // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + setTimeout( jQuery.ready ); + + // Standards-based browsers support DOMContentLoaded + } else if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed, false ); + + // If IE event model is used + } else { + // Ensure firing before onload, maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", completed ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", completed ); + + // If IE and not a frame + // continually check to see if the document is ready + var top = false; + + try { + top = window.frameElement == null && document.documentElement; + } catch(e) {} + + if ( top && top.doScroll ) { + (function doScrollCheck() { + if ( !jQuery.isReady ) { + + try { + // Use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + top.doScroll("left"); + } catch(e) { + return setTimeout( doScrollCheck, 50 ); + } + + // detach all dom ready events + detach(); + + // and execute any waiting functions + jQuery.ready(); + } + })(); + } + } + } + return readyList.promise( obj ); +}; + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +function isArraylike( obj ) { + var length = obj.length, + type = jQuery.type( obj ); + + if ( jQuery.isWindow( obj ) ) { + return false; + } + + if ( obj.nodeType === 1 && length ) { + return true; + } + + return type === "array" || type !== "function" && + ( length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj ); +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); +/*! + * Sizzle CSS Selector Engine v1.10.2 + * http://sizzlejs.com/ + * + * Copyright 2013 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2013-07-03 + */ +(function( window, undefined ) { + +var i, + support, + cachedruns, + Expr, + getText, + isXML, + compile, + outermostContext, + sortInput, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + -(new Date()), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + hasDuplicate = false, + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + return 0; + }, + + // General-purpose constants + strundefined = typeof undefined, + MAX_NEGATIVE = 1 << 31, + + // Instance methods + hasOwn = ({}).hasOwnProperty, + arr = [], + pop = arr.pop, + push_native = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf if we can't use a native one + indexOf = arr.indexOf || function( elem ) { + var i = 0, + len = this.length; + for ( ; i < len; i++ ) { + if ( this[i] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + // http://www.w3.org/TR/css3-syntax/#characters + characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", + + // Loosely modeled on CSS identifier characters + // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors + // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = characterEncoding.replace( "w", "w#" ), + + // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace + + "*(?:([*^$|!~]?=)" + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]", + + // Prefer arguments quoted, + // then not containing pseudos/brackets, + // then attribute selectors/non-parenthetical expressions, + // then anything else + // These preferences are here to reduce the number of selectors + // needing tokenize in the PSEUDO preFilter + pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + + rsibling = new RegExp( whitespace + "*[+~]" ), + rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*)" + whitespace + "*\\]", "g" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + characterEncoding + ")" ), + "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), + "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rescape = /'|\\/g, + + // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), + funescape = function( _, escaped, escapedWhitespace ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + // Support: Firefox + // Workaround erroneous numeric interpretation of +"0x" + return high !== high || escapedWhitespace ? + escaped : + // BMP codepoint + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }; + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + (arr = slice.call( preferredDoc.childNodes )), + preferredDoc.childNodes + ); + // Support: Android<4.0 + // Detect silently failing push.apply + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + push_native.apply( target, slice.call(els) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + // Can't trust NodeList.length + while ( (target[j++] = els[i++]) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var match, elem, m, nodeType, + // QSA vars + i, groups, old, nid, newContext, newSelector; + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + + context = context || document; + results = results || []; + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) { + return []; + } + + if ( documentIsHTML && !seed ) { + + // Shortcuts + if ( (match = rquickExpr.exec( selector )) ) { + // Speed-up: Sizzle("#ID") + if ( (m = match[1]) ) { + if ( nodeType === 9 ) { + elem = context.getElementById( m ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE, Opera, and Webkit return items + // by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + } else { + // Context is not a document + if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && + contains( context, elem ) && elem.id === m ) { + results.push( elem ); + return results; + } + } + + // Speed-up: Sizzle("TAG") + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Speed-up: Sizzle(".CLASS") + } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) { + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // QSA path + if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + nid = old = expando; + newContext = context; + newSelector = nodeType === 9 && selector; + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + groups = tokenize( selector ); + + if ( (old = context.getAttribute("id")) ) { + nid = old.replace( rescape, "\\$&" ); + } else { + context.setAttribute( "id", nid ); + } + nid = "[id='" + nid + "'] "; + + i = groups.length; + while ( i-- ) { + groups[i] = nid + toSelector( groups[i] ); + } + newContext = rsibling.test( selector ) && context.parentNode || context; + newSelector = groups.join(","); + } + + if ( newSelector ) { + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch(qsaError) { + } finally { + if ( !old ) { + context.removeAttribute("id"); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {Function(string, Object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key += " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key ] = value); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created div and expects a boolean result + */ +function assert( fn ) { + var div = document.createElement("div"); + + try { + return !!fn( div ); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if ( div.parentNode ) { + div.parentNode.removeChild( div ); + } + // release memory in IE + div = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split("|"), + i = attrs.length; + + while ( i-- ) { + Expr.attrHandle[ arr[i] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + ( ~b.sourceIndex || MAX_NEGATIVE ) - + ( ~a.sourceIndex || MAX_NEGATIVE ); + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); +} + +/** + * Detect xml + * @param {Element|Object} elem An element or a document + */ +isXML = Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var doc = node ? node.ownerDocument || node : preferredDoc, + parent = doc.defaultView; + + // If no document and documentElement is available, return + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Set our document + document = doc; + docElem = doc.documentElement; + + // Support tests + documentIsHTML = !isXML( doc ); + + // Support: IE>8 + // If iframe document is assigned to "document" variable and if iframe has been reloaded, + // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936 + // IE6-8 do not support the defaultView property so parent will be undefined + if ( parent && parent.attachEvent && parent !== parent.top ) { + parent.attachEvent( "onbeforeunload", function() { + setDocument(); + }); + } + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans) + support.attributes = assert(function( div ) { + div.className = "i"; + return !div.getAttribute("className"); + }); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert(function( div ) { + div.appendChild( doc.createComment("") ); + return !div.getElementsByTagName("*").length; + }); + + // Check if getElementsByClassName can be trusted + support.getElementsByClassName = assert(function( div ) { + div.innerHTML = "
"; + + // Support: Safari<4 + // Catch class over-caching + div.firstChild.className = "i"; + // Support: Opera<10 + // Catch gEBCN failure to find non-leading classes + return div.getElementsByClassName("i").length === 2; + }); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert(function( div ) { + docElem.appendChild( div ).id = expando; + return !doc.getElementsByName || !doc.getElementsByName( expando ).length; + }); + + // ID find and filter + if ( support.getById ) { + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== strundefined && documentIsHTML ) { + var m = context.getElementById( id ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + }; + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute("id") === attrId; + }; + }; + } else { + // Support: IE6/7 + // getElementById is not reliable as a find shortcut + delete Expr.find["ID"]; + + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; + } + + // Tag + Expr.find["TAG"] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== strundefined ) { + return context.getElementsByTagName( tag ); + } + } : + function( tag, context ) { + var elem, + tmp = [], + i = 0, + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( (elem = results[i++]) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See http://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( div ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // http://bugs.jquery.com/ticket/12359 + div.innerHTML = ""; + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !div.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + }); + + assert(function( div ) { + + // Support: Opera 10-12/IE8 + // ^= $= *= and empty values + // Should not select anything + // Support: Windows 8 Native Apps + // The type attribute is restricted during .innerHTML assignment + var input = doc.createElement("input"); + input.setAttribute( "type", "hidden" ); + div.appendChild( input ).setAttribute( "t", "" ); + + if ( div.querySelectorAll("[t^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":enabled").length ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Opera 10-11 does not throw on post-comma invalid pseudos + div.querySelectorAll("*,:x"); + rbuggyQSA.push(",.*:"); + }); + } + + if ( (support.matchesSelector = rnative.test( (matches = docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector) )) ) { + + assert(function( div ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( div, "div" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( div, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + }); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); + + /* Contains + ---------------------------------------------------------------------- */ + + // Element contains another + // Purposefully does not implement inclusive descendent + // As in, an element does not contain itself + contains = rnative.test( docElem.contains ) || docElem.compareDocumentPosition ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + )); + } : + function( a, b ) { + if ( b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = docElem.compareDocumentPosition ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b ); + + if ( compare ) { + // Disconnected nodes + if ( compare & 1 || + (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { + + // Choose the first element that is related to our preferred document + if ( a === doc || contains(preferredDoc, a) ) { + return -1; + } + if ( b === doc || contains(preferredDoc, b) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } + + // Not directly comparable, sort on existence of method + return a.compareDocumentPosition ? -1 : 1; + } : + function( a, b ) { + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + + // Parentless nodes are either documents or disconnected + } else if ( !aup || !bup ) { + return a === doc ? -1 : + b === doc ? 1 : + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( (cur = cur.parentNode) ) { + ap.unshift( cur ); + } + cur = b; + while ( (cur = cur.parentNode) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[i] === bp[i] ) { + i++; + } + + return i ? + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[i], bp[i] ) : + + // Otherwise nodes in our document sort first + ap[i] === preferredDoc ? -1 : + bp[i] === preferredDoc ? 1 : + 0; + }; + + return doc; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + if ( support.matchesSelector && documentIsHTML && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch(e) {} + } + + return Sizzle( expr, document, null, [elem] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + // Set document vars if needed + if ( ( context.ownerDocument || context ) !== document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val === undefined ? + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + (val = elem.getAttributeNode(name)) && val.specified ? + val.value : + null : + val; +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( (elem = results[i++]) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + // If no nodeType, this is expected to be an array + for ( ; (node = elem[i]); i++ ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (see #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1].slice( 0, 3 ) === "nth" ) { + // nth-* requires argument + if ( !match[3] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); + match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + + // other types prohibit arguments + } else if ( match[3] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[5] && match[2]; + + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[3] && match[4] !== undefined ) { + match[2] = match[4]; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + match[0] = match[0].slice( 0, excess ); + match[2] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { return true; } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" ); + }); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, what, argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, context, xml ) { + var cache, outerCache, node, diff, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( (node = node[ dir ]) ) { + if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { + return false; + } + } + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + // Seek `elem` from a previously-cached index + outerCache = parent[ expando ] || (parent[ expando ] = {}); + cache = outerCache[ type ] || []; + nodeIndex = cache[0] === dirruns && cache[1]; + diff = cache[0] === dirruns && cache[2]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( (node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + (diff = nodeIndex = 0) || start.pop()) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + outerCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + // Use previously-cached element index if available + } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) { + diff = cache[1]; + + // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...) + } else { + // Use the same loop as above to seek `elem` from the start + while ( (node = ++nodeIndex && node && node[ dir ] || + (diff = nodeIndex = 0) || start.pop()) ) { + + if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) { + // Cache the index of each encountered element + if ( useCache ) { + (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf.call( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + // Potentially complex pseudos + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + // lang value must be a valid identifier + if ( !ridentifier.test(lang || "") ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( (elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + return false; + }; + }), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + + // Boolean properties + "enabled": function( elem ) { + return elem.disabled === false; + }, + + "disabled": function( elem ) { + return elem.disabled === true; + }, + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)), + // not comment, processing instructions, or others + // Thanks to Diego Perini for the nodeName shortcut + // Greater than "@" means alpha characters (specifically not starting with "#" or "?") + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeName > "@" || elem.nodeType === 3 || elem.nodeType === 4 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === elem.type ); + }, + + // Position-in-collection + "first": createPositionalPseudo(function() { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } +}; + +Expr.pseudos["nth"] = Expr.pseudos["eq"]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +function tokenize( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + // Don't consume trailing commas as valid + soFar = soFar.slice( match[0].length ) || soFar; + } + groups.push( tokens = [] ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + matched = match.shift(); + tokens.push({ + value: matched, + // Cast descendant combinators to space + type: match[0].replace( rtrim, " " ) + }); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + (match = preFilters[ type ]( match ))) ) { + matched = match.shift(); + tokens.push({ + value: matched, + type: type, + matches: match + }); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +} + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[i].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + checkNonElements = base && dir === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var data, cache, outerCache, + dirkey = dirruns + " " + doneName; + + // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching + if ( xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || (elem[ expando ] = {}); + if ( (cache = outerCache[ dir ]) && cache[0] === dirkey ) { + if ( (data = cache[1]) === true || data === cachedruns ) { + return data === true; + } + } else { + cache = outerCache[ dir ] = [ dirkey ]; + cache[1] = matcher( elem, context, xml ) || cachedruns; + if ( cache[1] === true ) { + return true; + } + } + } + } + } + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( (elem = temp[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + // Restore matcherIn since elem is not yet a final match + temp.push( (matcherIn[i] = elem) ); + } + } + postFinder( null, (matcherOut = []), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) && + (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) { + + seed[temp] = !(results[temp] = elem); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf.call( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + } else { + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + // A counter to specify which element is currently being matched + var matcherCachedRuns = 0, + bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, expandContext ) { + var elem, j, matcher, + setMatched = [], + matchedCount = 0, + i = "0", + unmatched = seed && [], + outermost = expandContext != null, + contextBackup = outermostContext, + // We must always have either seed elements or context + elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ), + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1); + + if ( outermost ) { + outermostContext = context !== document && context; + cachedruns = matcherCachedRuns; + } + + // Add elements passing elementMatchers directly to results + // Keep `i` a string if there are no elements so `matchedCount` will be "00" below + for ( ; (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + while ( (matcher = elementMatchers[j++]) ) { + if ( matcher( elem, context, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + cachedruns = ++matcherCachedRuns; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // Apply set filters to unmatched elements + matchedCount += i; + if ( bySet && i !== matchedCount ) { + j = 0; + while ( (matcher = setMatchers[j++]) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !group ) { + group = tokenize( selector ); + } + i = group.length; + while ( i-- ) { + cached = matcherFromTokens( group[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + } + return cached; +}; + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results ); + } + return results; +} + +function select( selector, context, results, seed ) { + var i, tokens, token, type, find, + match = tokenize( selector ); + + if ( !seed ) { + // Try to minimize operations if there is only one group + if ( match.length === 1 ) { + + // Take a shortcut and set the context if the root selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + support.getById && context.nodeType === 9 && documentIsHTML && + Expr.relative[ tokens[1].type ] ) { + + context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; + if ( !context ) { + return results; + } + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( runescape, funescape ), + rsibling.test( tokens[0].type ) && context.parentNode || context + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + } + + // Compile and execute a filtering function + // Provide `match` to avoid retokenization if we modified the selector above + compile( selector, match )( + seed, + context, + !documentIsHTML, + results, + rsibling.test( selector ) + ); + return results; +} + +// One-time assignments + +// Sort stability +support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; + +// Support: Chrome<14 +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert(function( div1 ) { + // Should return 1, but returns 4 (following) + return div1.compareDocumentPosition( document.createElement("div") ) & 1; +}); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert(function( div ) { + div.innerHTML = ""; + return div.firstChild.getAttribute("href") === "#" ; +}) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + }); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert(function( div ) { + div.innerHTML = ""; + div.firstChild.setAttribute( "value", "" ); + return div.firstChild.getAttribute( "value" ) === ""; +}) ) { + addHandle( "value", function( elem, name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + }); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert(function( div ) { + return div.getAttribute("disabled") == null; +}) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return (val = elem.getAttributeNode( name )) && val.specified ? + val.value : + elem[ name ] === true ? name.toLowerCase() : null; + } + }); +} + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.pseudos; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + +})( window ); +// String to Object options format cache +var optionsCache = {}; + +// Convert String-formatted options into Object-formatted ones and store in cache +function createOptions( options ) { + var object = optionsCache[ options ] = {}; + jQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) { + object[ flag ] = true; + }); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + ( optionsCache[ options ] || createOptions( options ) ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + // Last fire value (for non-forgettable lists) + memory, + // Flag to know if list was already fired + fired, + // End of the loop when firing + firingLength, + // Index of currently firing callback (modified by remove if needed) + firingIndex, + // First callback to fire (used internally by add and fireWith) + firingStart, + // Actual callback list + list = [], + // Stack of fire calls for repeatable lists + stack = !options.once && [], + // Fire callbacks + fire = function( data ) { + memory = options.memory && data; + fired = true; + firingIndex = firingStart || 0; + firingStart = 0; + firingLength = list.length; + firing = true; + for ( ; list && firingIndex < firingLength; firingIndex++ ) { + if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { + memory = false; // To prevent further calls using add + break; + } + } + firing = false; + if ( list ) { + if ( stack ) { + if ( stack.length ) { + fire( stack.shift() ); + } + } else if ( memory ) { + list = []; + } else { + self.disable(); + } + } + }, + // Actual Callbacks object + self = { + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + // First, we save the current length + var start = list.length; + (function add( args ) { + jQuery.each( args, function( _, arg ) { + var type = jQuery.type( arg ); + if ( type === "function" ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && type !== "string" ) { + // Inspect recursively + add( arg ); + } + }); + })( arguments ); + // Do we need to add the callbacks to the + // current firing batch? + if ( firing ) { + firingLength = list.length; + // With memory, if we're not firing then + // we should call right away + } else if ( memory ) { + firingStart = start; + fire( memory ); + } + } + return this; + }, + // Remove a callback from the list + remove: function() { + if ( list ) { + jQuery.each( arguments, function( _, arg ) { + var index; + while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + // Handle firing indexes + if ( firing ) { + if ( index <= firingLength ) { + firingLength--; + } + if ( index <= firingIndex ) { + firingIndex--; + } + } + } + }); + } + return this; + }, + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length ); + }, + // Remove all callbacks from the list + empty: function() { + list = []; + firingLength = 0; + return this; + }, + // Have the list do nothing anymore + disable: function() { + list = stack = memory = undefined; + return this; + }, + // Is it disabled? + disabled: function() { + return !list; + }, + // Lock the list in its current state + lock: function() { + stack = undefined; + if ( !memory ) { + self.disable(); + } + return this; + }, + // Is it locked? + locked: function() { + return !stack; + }, + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( list && ( !fired || stack ) ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + if ( firing ) { + stack.push( args ); + } else { + fire( args ); + } + } + return this; + }, + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; +jQuery.extend({ + + Deferred: function( func ) { + var tuples = [ + // action, add listener, listener list, final state + [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], + [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], + [ "notify", "progress", jQuery.Callbacks("memory") ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + then: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + return jQuery.Deferred(function( newDefer ) { + jQuery.each( tuples, function( i, tuple ) { + var action = tuple[ 0 ], + fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; + // deferred[ done | fail | progress ] for forwarding actions to newDefer + deferred[ tuple[1] ](function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise() + .done( newDefer.resolve ) + .fail( newDefer.reject ) + .progress( newDefer.notify ); + } else { + newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); + } + }); + }); + fns = null; + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Keep pipe for back-compat + promise.pipe = promise.then; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 3 ]; + + // promise[ done | fail | progress ] = list.add + promise[ tuple[1] ] = list.add; + + // Handle state + if ( stateString ) { + list.add(function() { + // state = [ resolved | rejected ] + state = stateString; + + // [ reject_list | resolve_list ].disable; progress_list.lock + }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); + } + + // deferred[ resolve | reject | notify ] + deferred[ tuple[0] ] = function() { + deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments ); + return this; + }; + deferred[ tuple[0] + "With" ] = list.fireWith; + }); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( subordinate /* , ..., subordinateN */ ) { + var i = 0, + resolveValues = core_slice.call( arguments ), + length = resolveValues.length, + + // the count of uncompleted subordinates + remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, + + // the master Deferred. If resolveValues consist of only a single Deferred, just use that. + deferred = remaining === 1 ? subordinate : jQuery.Deferred(), + + // Update function for both resolve and progress values + updateFunc = function( i, contexts, values ) { + return function( value ) { + contexts[ i ] = this; + values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value; + if( values === progressValues ) { + deferred.notifyWith( contexts, values ); + } else if ( !( --remaining ) ) { + deferred.resolveWith( contexts, values ); + } + }; + }, + + progressValues, progressContexts, resolveContexts; + + // add listeners to Deferred subordinates; treat others as resolved + if ( length > 1 ) { + progressValues = new Array( length ); + progressContexts = new Array( length ); + resolveContexts = new Array( length ); + for ( ; i < length; i++ ) { + if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { + resolveValues[ i ].promise() + .done( updateFunc( i, resolveContexts, resolveValues ) ) + .fail( deferred.reject ) + .progress( updateFunc( i, progressContexts, progressValues ) ); + } else { + --remaining; + } + } + } + + // if we're not waiting on anything, resolve the master + if ( !remaining ) { + deferred.resolveWith( resolveContexts, resolveValues ); + } + + return deferred.promise(); + } +}); +jQuery.support = (function( support ) { + + var all, a, input, select, fragment, opt, eventName, isSupported, i, + div = document.createElement("div"); + + // Setup + div.setAttribute( "className", "t" ); + div.innerHTML = "
a"; + + // Finish early in limited (non-browser) environments + all = div.getElementsByTagName("*") || []; + a = div.getElementsByTagName("a")[ 0 ]; + if ( !a || !a.style || !all.length ) { + return support; + } + + // First batch of tests + select = document.createElement("select"); + opt = select.appendChild( document.createElement("option") ); + input = div.getElementsByTagName("input")[ 0 ]; + + a.style.cssText = "top:1px;float:left;opacity:.5"; + + // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) + support.getSetAttribute = div.className !== "t"; + + // IE strips leading whitespace when .innerHTML is used + support.leadingWhitespace = div.firstChild.nodeType === 3; + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + support.tbody = !div.getElementsByTagName("tbody").length; + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + support.htmlSerialize = !!div.getElementsByTagName("link").length; + + // Get the style information from getAttribute + // (IE uses .cssText instead) + support.style = /top/.test( a.getAttribute("style") ); + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + support.hrefNormalized = a.getAttribute("href") === "/a"; + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + support.opacity = /^0.5/.test( a.style.opacity ); + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + support.cssFloat = !!a.style.cssFloat; + + // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere) + support.checkOn = !!input.value; + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + support.optSelected = opt.selected; + + // Tests for enctype support on a form (#6743) + support.enctype = !!document.createElement("form").enctype; + + // Makes sure cloning an html5 element does not cause problems + // Where outerHTML is undefined, this still works + support.html5Clone = document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav>"; + + // Will be defined later + support.inlineBlockNeedsLayout = false; + support.shrinkWrapBlocks = false; + support.pixelPosition = false; + support.deleteExpando = true; + support.noCloneEvent = true; + support.reliableMarginRight = true; + support.boxSizingReliable = true; + + // Make sure checked status is properly cloned + input.checked = true; + support.noCloneChecked = input.cloneNode( true ).checked; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as disabled) + select.disabled = true; + support.optDisabled = !opt.disabled; + + // Support: IE<9 + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + + // Check if we can trust getAttribute("value") + input = document.createElement("input"); + input.setAttribute( "value", "" ); + support.input = input.getAttribute( "value" ) === ""; + + // Check if an input maintains its value after becoming a radio + input.value = "t"; + input.setAttribute( "type", "radio" ); + support.radioValue = input.value === "t"; + + // #11217 - WebKit loses check when the name is after the checked attribute + input.setAttribute( "checked", "t" ); + input.setAttribute( "name", "t" ); + + fragment = document.createDocumentFragment(); + fragment.appendChild( input ); + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + support.appendChecked = input.checked; + + // WebKit doesn't clone checked state correctly in fragments + support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE<9 + // Opera does not clone events (and typeof div.attachEvent === undefined). + // IE9-10 clones events bound via attachEvent, but they don't trigger with .click() + if ( div.attachEvent ) { + div.attachEvent( "onclick", function() { + support.noCloneEvent = false; + }); + + div.cloneNode( true ).click(); + } + + // Support: IE<9 (lack submit/change bubble), Firefox 17+ (lack focusin event) + // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP) + for ( i in { submit: true, change: true, focusin: true }) { + div.setAttribute( eventName = "on" + i, "t" ); + + support[ i + "Bubbles" ] = eventName in window || div.attributes[ eventName ].expando === false; + } + + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + // Support: IE<9 + // Iteration over object's inherited properties before its own. + for ( i in jQuery( support ) ) { + break; + } + support.ownLast = i !== "0"; + + // Run tests that need a body at doc ready + jQuery(function() { + var container, marginDiv, tds, + divReset = "padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;", + body = document.getElementsByTagName("body")[0]; + + if ( !body ) { + // Return for frameset docs that don't have a body + return; + } + + container = document.createElement("div"); + container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px"; + + body.appendChild( container ).appendChild( div ); + + // Support: IE8 + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + div.innerHTML = "
t
"; + tds = div.getElementsByTagName("td"); + tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none"; + isSupported = ( tds[ 0 ].offsetHeight === 0 ); + + tds[ 0 ].style.display = ""; + tds[ 1 ].style.display = "none"; + + // Support: IE8 + // Check if empty table cells still have offsetWidth/Height + support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); + + // Check box-sizing and margin behavior. + div.innerHTML = ""; + div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;"; + + // Workaround failing boxSizing test due to offsetWidth returning wrong value + // with some non-1 values of body zoom, ticket #13543 + jQuery.swap( body, body.style.zoom != null ? { zoom: 1 } : {}, function() { + support.boxSizing = div.offsetWidth === 4; + }); + + // Use window.getComputedStyle because jsdom on node.js will break without it. + if ( window.getComputedStyle ) { + support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%"; + support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px"; + + // Check if div with explicit width and no margin-right incorrectly + // gets computed margin-right based on width of container. (#3333) + // Fails in WebKit before Feb 2011 nightlies + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + marginDiv = div.appendChild( document.createElement("div") ); + marginDiv.style.cssText = div.style.cssText = divReset; + marginDiv.style.marginRight = marginDiv.style.width = "0"; + div.style.width = "1px"; + + support.reliableMarginRight = + !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight ); + } + + if ( typeof div.style.zoom !== core_strundefined ) { + // Support: IE<8 + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + div.innerHTML = ""; + div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1"; + support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 ); + + // Support: IE6 + // Check if elements with layout shrink-wrap their children + div.style.display = "block"; + div.innerHTML = "
"; + div.firstChild.style.width = "5px"; + support.shrinkWrapBlocks = ( div.offsetWidth !== 3 ); + + if ( support.inlineBlockNeedsLayout ) { + // Prevent IE 6 from affecting layout for positioned elements #11048 + // Prevent IE from shrinking the body in IE 7 mode #12869 + // Support: IE<8 + body.style.zoom = 1; + } + } + + body.removeChild( container ); + + // Null elements to avoid leaks in IE + container = div = tds = marginDiv = null; + }); + + // Null elements to avoid leaks in IE + all = select = fragment = opt = a = input = null; + + return support; +})({}); + +var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/, + rmultiDash = /([A-Z])/g; + +function internalData( elem, name, data, pvt /* Internal Use Only */ ){ + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var ret, thisCache, + internalKey = jQuery.expando, + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + id = elem[ internalKey ] = core_deletedIds.pop() || jQuery.guid++; + } else { + id = internalKey; + } + } + + if ( !cache[ id ] ) { + // Avoid exposing jQuery metadata on plain JS objects when the object + // is serialized using JSON.stringify + cache[ id ] = isNode ? {} : { toJSON: jQuery.noop }; + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ] = jQuery.extend( cache[ id ], name ); + } else { + cache[ id ].data = jQuery.extend( cache[ id ].data, name ); + } + } + + thisCache = cache[ id ]; + + // jQuery data() is stored in a separate object inside the object's internal data + // cache in order to avoid key collisions between internal data and user-defined + // data. + if ( !pvt ) { + if ( !thisCache.data ) { + thisCache.data = {}; + } + + thisCache = thisCache.data; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // Check for both converted-to-camel and non-converted data property names + // If a data property was specified + if ( typeof name === "string" ) { + + // First Try to find as-is property data + ret = thisCache[ name ]; + + // Test for null|undefined property data + if ( ret == null ) { + + // Try to find the camelCased property + ret = thisCache[ jQuery.camelCase( name ) ]; + } + } else { + ret = thisCache; + } + + return ret; +} + +function internalRemoveData( elem, name, pvt ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, i, + isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + + thisCache = pvt ? cache[ id ] : cache[ id ].data; + + if ( thisCache ) { + + // Support array or space separated string names for data keys + if ( !jQuery.isArray( name ) ) { + + // try the string as a key before any manipulation + if ( name in thisCache ) { + name = [ name ]; + } else { + + // split the camel cased version by spaces unless a key with the spaces exists + name = jQuery.camelCase( name ); + if ( name in thisCache ) { + name = [ name ]; + } else { + name = name.split(" "); + } + } + } else { + // If "name" is an array of keys... + // When data is initially created, via ("key", "val") signature, + // keys will be converted to camelCase. + // Since there is no way to tell _how_ a key was added, remove + // both plain key and camelCase key. #12786 + // This will only penalize the array argument path. + name = name.concat( jQuery.map( name, jQuery.camelCase ) ); + } + + i = name.length; + while ( i-- ) { + delete thisCache[ name[i] ]; + } + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( !pvt ) { + delete cache[ id ].data; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject( cache[ id ] ) ) { + return; + } + } + + // Destroy the cache + if ( isNode ) { + jQuery.cleanData( [ elem ], true ); + + // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080) + /* jshint eqeqeq: false */ + } else if ( jQuery.support.deleteExpando || cache != cache.window ) { + /* jshint eqeqeq: true */ + delete cache[ id ]; + + // When all else fails, null + } else { + cache[ id ] = null; + } +} + +jQuery.extend({ + cache: {}, + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "applet": true, + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data ) { + return internalData( elem, name, data ); + }, + + removeData: function( elem, name ) { + return internalRemoveData( elem, name ); + }, + + // For internal use only. + _data: function( elem, name, data ) { + return internalData( elem, name, data, true ); + }, + + _removeData: function( elem, name ) { + return internalRemoveData( elem, name, true ); + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + // Do not set data on non-element because it will not be cleared (#8335). + if ( elem.nodeType && elem.nodeType !== 1 && elem.nodeType !== 9 ) { + return false; + } + + var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ]; + + // nodes accept data unless otherwise specified; rejection can be conditional + return !noData || noData !== true && elem.getAttribute("classid") === noData; + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var attrs, name, + data = null, + i = 0, + elem = this[0]; + + // Special expections of .data basically thwart jQuery.access, + // so implement the relevant behavior ourselves + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = jQuery.data( elem ); + + if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) { + attrs = elem.attributes; + for ( ; i < attrs.length; i++ ) { + name = attrs[i].name; + + if ( name.indexOf("data-") === 0 ) { + name = jQuery.camelCase( name.slice(5) ); + + dataAttr( elem, name, data[ name ] ); + } + } + jQuery._data( elem, "parsedAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + return arguments.length > 1 ? + + // Sets one value + this.each(function() { + jQuery.data( this, key, value ); + }) : + + // Gets one value + // Try to fetch any internally stored data first + elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : null; + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + + var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + // Only convert to a number if it doesn't change the string + +data + "" === data ? +data : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// checks a cache object for emptiness +function isEmptyDataObject( obj ) { + var name; + for ( name in obj ) { + + // if the public data object is empty, the private is still empty + if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { + continue; + } + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} +jQuery.extend({ + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = jQuery._data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || jQuery.isArray(data) ) { + queue = jQuery._data( elem, type, jQuery.makeArray(data) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // not intended for public consumption - generates a queueHooks object, or returns the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return jQuery._data( elem, key ) || jQuery._data( elem, key, { + empty: jQuery.Callbacks("once memory").add(function() { + jQuery._removeData( elem, type + "queue" ); + jQuery._removeData( elem, key ); + }) + }); + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[0], type ); + } + + return data === undefined ? + this : + this.each(function() { + var queue = jQuery.queue( this, type, data ); + + // ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = setTimeout( next, time ); + hooks.stop = function() { + clearTimeout( timeout ); + }; + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while( i-- ) { + tmp = jQuery._data( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +}); +var nodeHook, boolHook, + rclass = /[\t\r\n\f]/g, + rreturn = /\r/g, + rfocusable = /^(?:input|select|textarea|button|object)$/i, + rclickable = /^(?:a|area)$/i, + ruseDefault = /^(?:checked|selected)$/i, + getSetAttribute = jQuery.support.getSetAttribute, + getSetInput = jQuery.support.input; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each(function() { + jQuery.removeAttr( this, name ); + }); + }, + + prop: function( name, value ) { + return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + name = jQuery.propFix[ name ] || name; + return this.each(function() { + // try/catch handles cases where IE balks (such as removing a property on window) + try { + this[ name ] = undefined; + delete this[ name ]; + } catch( e ) {} + }); + }, + + addClass: function( value ) { + var classes, elem, cur, clazz, j, + i = 0, + len = this.length, + proceed = typeof value === "string" && value; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).addClass( value.call( this, j, this.className ) ); + }); + } + + if ( proceed ) { + // The disjunction here is for better compressibility (see removeClass) + classes = ( value || "" ).match( core_rnotwhite ) || []; + + for ( ; i < len; i++ ) { + elem = this[ i ]; + cur = elem.nodeType === 1 && ( elem.className ? + ( " " + elem.className + " " ).replace( rclass, " " ) : + " " + ); + + if ( cur ) { + j = 0; + while ( (clazz = classes[j++]) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + elem.className = jQuery.trim( cur ); + + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, clazz, j, + i = 0, + len = this.length, + proceed = arguments.length === 0 || typeof value === "string" && value; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).removeClass( value.call( this, j, this.className ) ); + }); + } + if ( proceed ) { + classes = ( value || "" ).match( core_rnotwhite ) || []; + + for ( ; i < len; i++ ) { + elem = this[ i ]; + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( elem.className ? + ( " " + elem.className + " " ).replace( rclass, " " ) : + "" + ); + + if ( cur ) { + j = 0; + while ( (clazz = classes[j++]) ) { + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) >= 0 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + elem.className = value ? jQuery.trim( cur ) : ""; + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value; + + if ( typeof stateVal === "boolean" && type === "string" ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( jQuery.isFunction( value ) ) { + return this.each(function( i ) { + jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + classNames = value.match( core_rnotwhite ) || []; + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( type === core_strundefined || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // If the element has a class name or if we're passed "false", + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " ", + i = 0, + l = this.length; + for ( ; i < l; i++ ) { + if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + var ret, hooks, isFunction, + elem = this[0]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { + return ret; + } + + ret = elem.value; + + return typeof ret === "string" ? + // handle most common string cases + ret.replace(rreturn, "") : + // handle cases where value is null/undef or number + ret == null ? "" : ret; + } + + return; + } + + isFunction = jQuery.isFunction( value ); + + return this.each(function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray( val ) ) { + val = jQuery.map(val, function ( value ) { + return value == null ? "" : value + ""; + }); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + valHooks: { + option: { + get: function( elem ) { + // Use proper attribute retrieval(#6932, #12072) + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + elem.text; + } + }, + select: { + get: function( elem ) { + var value, option, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one" || index < 0, + values = one ? null : [], + max = one ? index + 1 : options.length, + i = index < 0 ? + max : + one ? index : 0; + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // oldIE doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + // Don't return options that are disabled or in a disabled optgroup + ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) && + ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + if ( (option.selected = jQuery.inArray( jQuery(option).val(), values ) >= 0) ) { + optionSet = true; + } + } + + // force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + }, + + attr: function( elem, name, value ) { + var hooks, ret, + nType = elem.nodeType; + + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === core_strundefined ) { + return jQuery.prop( elem, name, value ); + } + + // All attributes are lowercase + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + name = name.toLowerCase(); + hooks = jQuery.attrHooks[ name ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook ); + } + + if ( value !== undefined ) { + + if ( value === null ) { + jQuery.removeAttr( elem, name ); + + } else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + elem.setAttribute( name, value + "" ); + return value; + } + + } else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? + undefined : + ret; + } + }, + + removeAttr: function( elem, value ) { + var name, propName, + i = 0, + attrNames = value && value.match( core_rnotwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( (name = attrNames[i++]) ) { + propName = jQuery.propFix[ name ] || name; + + // Boolean attributes get special treatment (#10870) + if ( jQuery.expr.match.bool.test( name ) ) { + // Set corresponding property to false + if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) { + elem[ propName ] = false; + // Support: IE<9 + // Also clear defaultChecked/defaultSelected (if appropriate) + } else { + elem[ jQuery.camelCase( "default-" + name ) ] = + elem[ propName ] = false; + } + + // See #9699 for explanation of this approach (setting first, then removal) + } else { + jQuery.attr( elem, name, "" ); + } + + elem.removeAttribute( getSetAttribute ? name : propName ); + } + } + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { + // Setting the type on a radio button after the value resets the value in IE6-9 + // Reset value to default in case type is set after value during creation + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + }, + + prop: function( elem, name, value ) { + var ret, hooks, notxml, + nType = elem.nodeType; + + // don't get/set properties on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + if ( notxml ) { + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ? + ret : + ( elem[ name ] = value ); + + } else { + return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ? + ret : + elem[ name ]; + } + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + return tabindex ? + parseInt( tabindex, 10 ) : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + -1; + } + } + } +}); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) { + // IE<8 needs the *property* name + elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name ); + + // Use defaultChecked and defaultSelected for oldIE + } else { + elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true; + } + + return name; + } +}; +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { + var getter = jQuery.expr.attrHandle[ name ] || jQuery.find.attr; + + jQuery.expr.attrHandle[ name ] = getSetInput && getSetAttribute || !ruseDefault.test( name ) ? + function( elem, name, isXML ) { + var fn = jQuery.expr.attrHandle[ name ], + ret = isXML ? + undefined : + /* jshint eqeqeq: false */ + (jQuery.expr.attrHandle[ name ] = undefined) != + getter( elem, name, isXML ) ? + + name.toLowerCase() : + null; + jQuery.expr.attrHandle[ name ] = fn; + return ret; + } : + function( elem, name, isXML ) { + return isXML ? + undefined : + elem[ jQuery.camelCase( "default-" + name ) ] ? + name.toLowerCase() : + null; + }; +}); + +// fix oldIE attroperties +if ( !getSetInput || !getSetAttribute ) { + jQuery.attrHooks.value = { + set: function( elem, value, name ) { + if ( jQuery.nodeName( elem, "input" ) ) { + // Does not return so that setAttribute is also used + elem.defaultValue = value; + } else { + // Use nodeHook if defined (#1954); otherwise setAttribute is fine + return nodeHook && nodeHook.set( elem, value, name ); + } + } + }; +} + +// IE6/7 do not support getting/setting some attributes with get/setAttribute +if ( !getSetAttribute ) { + + // Use this for any attribute in IE6/7 + // This fixes almost every IE6/7 issue + nodeHook = { + set: function( elem, value, name ) { + // Set the existing or create a new attribute node + var ret = elem.getAttributeNode( name ); + if ( !ret ) { + elem.setAttributeNode( + (ret = elem.ownerDocument.createAttribute( name )) + ); + } + + ret.value = value += ""; + + // Break association with cloned elements by also using setAttribute (#9646) + return name === "value" || value === elem.getAttribute( name ) ? + value : + undefined; + } + }; + jQuery.expr.attrHandle.id = jQuery.expr.attrHandle.name = jQuery.expr.attrHandle.coords = + // Some attributes are constructed with empty-string values when not defined + function( elem, name, isXML ) { + var ret; + return isXML ? + undefined : + (ret = elem.getAttributeNode( name )) && ret.value !== "" ? + ret.value : + null; + }; + jQuery.valHooks.button = { + get: function( elem, name ) { + var ret = elem.getAttributeNode( name ); + return ret && ret.specified ? + ret.value : + undefined; + }, + set: nodeHook.set + }; + + // Set contenteditable to false on removals(#10429) + // Setting to empty string throws an error as an invalid value + jQuery.attrHooks.contenteditable = { + set: function( elem, value, name ) { + nodeHook.set( elem, value === "" ? false : value, name ); + } + }; + + // Set width and height to auto instead of 0 on empty string( Bug #8150 ) + // This is for removals + jQuery.each([ "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = { + set: function( elem, value ) { + if ( value === "" ) { + elem.setAttribute( name, "auto" ); + return value; + } + } + }; + }); +} + + +// Some attributes require a special call on IE +// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !jQuery.support.hrefNormalized ) { + // href/src property should get the full normalized URL (#10299/#12915) + jQuery.each([ "href", "src" ], function( i, name ) { + jQuery.propHooks[ name ] = { + get: function( elem ) { + return elem.getAttribute( name, 4 ); + } + }; + }); +} + +if ( !jQuery.support.style ) { + jQuery.attrHooks.style = { + get: function( elem ) { + // Return undefined in the case of empty string + // Note: IE uppercases css property names, but if we were to .toLowerCase() + // .cssText, that would destroy case senstitivity in URL's, like in "background" + return elem.style.cssText || undefined; + }, + set: function( elem, value ) { + return ( elem.style.cssText = value + "" ); + } + }; +} + +// Safari mis-reports the default selected property of an option +// Accessing the parent's selectedIndex property fixes it +if ( !jQuery.support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + var parent = elem.parentNode; + + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + return null; + } + }; +} + +jQuery.each([ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +}); + +// IE6/7 call enctype encoding +if ( !jQuery.support.enctype ) { + jQuery.propFix.enctype = "encoding"; +} + +// Radios and checkboxes getter/setter +jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( jQuery.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); + } + } + }; + if ( !jQuery.support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + // Support: Webkit + // "" is returned instead of "on" if a value isn't specified + return elem.getAttribute("value") === null ? "on" : elem.value; + }; + } +}); +var rformElems = /^(?:input|select|textarea)$/i, + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|contextmenu)|click/, + rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + var tmp, events, t, handleObjIn, + special, eventHandle, handleObj, + handlers, type, namespaces, origType, + elemData = jQuery._data( elem ); + + // Don't attach events to noData or text/comment nodes (but allow plain objects) + if ( !elemData ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !(events = elemData.events) ) { + events = elemData.events = {}; + } + if ( !(eventHandle = elemData.handle) ) { + eventHandle = elemData.handle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ? + jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : + undefined; + }; + // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events + eventHandle.elem = elem; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( core_rnotwhite ) || [""]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend({ + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join(".") + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !(handlers = events[ type ]) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener/attachEvent if the special events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + var j, handleObj, tmp, + origCount, t, events, + special, handlers, type, + namespaces, origType, + elemData = jQuery.hasData( elem ) && jQuery._data( elem ); + + if ( !elemData || !(events = elemData.events) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( core_rnotwhite ) || [""]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + delete elemData.handle; + + // removeData also checks for emptiness and clears the expando if empty + // so use it instead of delete + jQuery._removeData( elem, "events" ); + } + }, + + trigger: function( event, data, elem, onlyHandlers ) { + var handle, ontype, cur, + bubbleType, special, tmp, i, + eventPath = [ elem || document ], + type = core_hasOwn.call( event, "type" ) ? event.type : event, + namespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : []; + + cur = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf(".") >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf(":") < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join("."); + event.namespace_re = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === (elem.ownerDocument || document) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) { + + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) { + event.preventDefault(); + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) && + jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction() check here because IE6/7 fails that test. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + try { + elem[ type ](); + } catch ( e ) { + // IE<9 dies on focus/blur to hidden element (#1486,#12518) + // only reproducible on winXP IE8 native, not IE9 in IE8 mode + } + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + dispatch: function( event ) { + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( event ); + + var i, ret, handleObj, matched, j, + handlerQueue = [], + args = core_slice.call( arguments ), + handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[0] = event; + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) { + + // Triggered event must either 1) have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). + if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) + .apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( (event.result = ret) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var sel, handleObj, matches, i, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + // Black-hole SVG instance trees (#13180) + // Avoid non-left-click bubbling in Firefox (#3861) + if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) { + + /* jshint eqeqeq: false */ + for ( ; cur != this; cur = cur.parentNode || this ) { + /* jshint eqeqeq: true */ + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) { + matches = []; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matches[ sel ] === undefined ) { + matches[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) >= 0 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matches[ sel ] ) { + matches.push( handleObj ); + } + } + if ( matches.length ) { + handlerQueue.push({ elem: cur, handlers: matches }); + } + } + } + } + + // Add the remaining (directly-bound) handlers + if ( delegateCount < handlers.length ) { + handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) }); + } + + return handlerQueue; + }, + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // Create a writable copy of the event object and normalize some properties + var i, prop, copy, + type = event.type, + originalEvent = event, + fixHook = this.fixHooks[ type ]; + + if ( !fixHook ) { + this.fixHooks[ type ] = fixHook = + rmouseEvent.test( type ) ? this.mouseHooks : + rkeyEvent.test( type ) ? this.keyHooks : + {}; + } + copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; + + event = new jQuery.Event( originalEvent ); + + i = copy.length; + while ( i-- ) { + prop = copy[ i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Support: IE<9 + // Fix target property (#1925) + if ( !event.target ) { + event.target = originalEvent.srcElement || document; + } + + // Support: Chrome 23+, Safari? + // Target should not be a text node (#504, #13143) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Support: IE<9 + // For mouse/key events, metaKey==false if it's undefined (#3368, #11328) + event.metaKey = !!event.metaKey; + + return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; + }, + + // Includes some event props shared by KeyEvent and MouseEvent + props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), + + fixHooks: {}, + + keyHooks: { + props: "char charCode key keyCode".split(" "), + filter: function( event, original ) { + + // Add which for key events + if ( event.which == null ) { + event.which = original.charCode != null ? original.charCode : original.keyCode; + } + + return event; + } + }, + + mouseHooks: { + props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), + filter: function( event, original ) { + var body, eventDoc, doc, + button = original.button, + fromElement = original.fromElement; + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && original.clientX != null ) { + eventDoc = event.target.ownerDocument || document; + doc = eventDoc.documentElement; + body = eventDoc.body; + + event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); + event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && fromElement ) { + event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && button !== undefined ) { + event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); + } + + return event; + } + }, + + special: { + load: { + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + focus: { + // Fire native event if possible so blur/focus sequence is correct + trigger: function() { + if ( this !== safeActiveElement() && this.focus ) { + try { + this.focus(); + return false; + } catch ( e ) { + // Support: IE<9 + // If we error on focus to hidden element (#1486, #12518), + // let .trigger() run the handlers + } + } + }, + delegateType: "focusin" + }, + blur: { + trigger: function() { + if ( this === safeActiveElement() && this.blur ) { + this.blur(); + return false; + } + }, + delegateType: "focusout" + }, + click: { + // For checkbox, fire native event so checked state will be right + trigger: function() { + if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) { + this.click(); + return false; + } + }, + + // For cross-browser consistency, don't fire native .click() on links + _default: function( event ) { + return jQuery.nodeName( event.target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Even when returnValue equals to undefined Firefox will still show alert + if ( event.result !== undefined ) { + event.originalEvent.returnValue = event.result; + } + } + } + }, + + simulate: function( type, elem, event, bubble ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true, + originalEvent: {} + } + ); + if ( bubble ) { + jQuery.event.trigger( e, null, elem ); + } else { + jQuery.event.dispatch.call( elem, e ); + } + if ( e.isDefaultPrevented() ) { + event.preventDefault(); + } + } +}; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + var name = "on" + type; + + if ( elem.detachEvent ) { + + // #8545, #7054, preventing memory leaks for custom events in IE6-8 + // detachEvent needed property on element, by name of that event, to properly expose it to GC + if ( typeof elem[ name ] === core_strundefined ) { + elem[ name ] = null; + } + + elem.detachEvent( name, handle ); + } + }; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !(this instanceof jQuery.Event) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false || + src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + if ( !e ) { + return; + } + + // If preventDefault exists, run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // Support: IE + // Otherwise set the returnValue property of the original event to false + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + if ( !e ) { + return; + } + // If stopPropagation exists, run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + + // Support: IE + // Set the cancelBubble property of the original event to true + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + } +}; + +// Create mouseenter/leave events using mouseover/out and event-time checks +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mousenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || (related !== target && !jQuery.contains( target, related )) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +}); + +// IE submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Lazy-add a submit handler when a descendant form may potentially be submitted + jQuery.event.add( this, "click._submit keypress._submit", function( e ) { + // Node name check avoids a VML-related crash in IE (#9807) + var elem = e.target, + form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; + if ( form && !jQuery._data( form, "submitBubbles" ) ) { + jQuery.event.add( form, "submit._submit", function( event ) { + event._submit_bubble = true; + }); + jQuery._data( form, "submitBubbles", true ); + } + }); + // return undefined since we don't need an event listener + }, + + postDispatch: function( event ) { + // If form was submitted by the user, bubble the event up the tree + if ( event._submit_bubble ) { + delete event._submit_bubble; + if ( this.parentNode && !event.isTrigger ) { + jQuery.event.simulate( "submit", this.parentNode, event, true ); + } + } + }, + + teardown: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Remove delegated handlers; cleanData eventually reaps submit handlers attached above + jQuery.event.remove( this, "._submit" ); + } + }; +} + +// IE change delegation and checkbox/radio fix +if ( !jQuery.support.changeBubbles ) { + + jQuery.event.special.change = { + + setup: function() { + + if ( rformElems.test( this.nodeName ) ) { + // IE doesn't fire change on a check/radio until blur; trigger it on click + // after a propertychange. Eat the blur-change in special.change.handle. + // This still fires onchange a second time for check/radio after blur. + if ( this.type === "checkbox" || this.type === "radio" ) { + jQuery.event.add( this, "propertychange._change", function( event ) { + if ( event.originalEvent.propertyName === "checked" ) { + this._just_changed = true; + } + }); + jQuery.event.add( this, "click._change", function( event ) { + if ( this._just_changed && !event.isTrigger ) { + this._just_changed = false; + } + // Allow triggered, simulated change events (#11500) + jQuery.event.simulate( "change", this, event, true ); + }); + } + return false; + } + // Delegated event; lazy-add a change handler on descendant inputs + jQuery.event.add( this, "beforeactivate._change", function( e ) { + var elem = e.target; + + if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) { + jQuery.event.add( elem, "change._change", function( event ) { + if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { + jQuery.event.simulate( "change", this.parentNode, event, true ); + } + }); + jQuery._data( elem, "changeBubbles", true ); + } + }); + }, + + handle: function( event ) { + var elem = event.target; + + // Swallow native change events from checkbox/radio, we already triggered them above + if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { + return event.handleObj.handler.apply( this, arguments ); + } + }, + + teardown: function() { + jQuery.event.remove( this, "._change" ); + + return !rformElems.test( this.nodeName ); + } + }; +} + +// Create "bubbling" focus and blur events +if ( !jQuery.support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler while someone wants focusin/focusout + var attaches = 0, + handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + if ( attaches++ === 0 ) { + document.addEventListener( orig, handler, true ); + } + }, + teardown: function() { + if ( --attaches === 0 ) { + document.removeEventListener( orig, handler, true ); + } + } + }; + }); +} + +jQuery.fn.extend({ + + on: function( types, selector, data, fn, /*INTERNAL*/ one ) { + var type, origFn; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + this.on( type, selector, data, types[ type ], one ); + } + return this; + } + + if ( data == null && fn == null ) { + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return this; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return this.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + }); + }, + one: function( types, selector, data, fn ) { + return this.on( types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each(function() { + jQuery.event.remove( this, types, fn, selector ); + }); + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + triggerHandler: function( type, data ) { + var elem = this[0]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +}); +var isSimple = /^.[^:#\[\.,]*$/, + rparentsprev = /^(?:parents|prev(?:Until|All))/, + rneedsContext = jQuery.expr.match.needsContext, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend({ + find: function( selector ) { + var i, + ret = [], + self = this, + len = self.length; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }) ); + } + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + // Needed because $( selector, context ) becomes $( context ).find( selector ) + ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); + ret.selector = this.selector ? this.selector + " " + selector : selector; + return ret; + }, + + has: function( target ) { + var i, + targets = jQuery( target, this ), + len = targets.length; + + return this.filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector || [], true) ); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector || [], false) ); + }, + + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + ret = [], + pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( ; i < l; i++ ) { + for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) { + // Always skip document fragments + if ( cur.nodeType < 11 && (pos ? + pos.index(cur) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector(cur, selectors)) ) { + + cur = ret.push( cur ); + break; + } + } + } + + return this.pushStack( ret.length > 1 ? jQuery.unique( ret ) : ret ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1; + } + + // index in selector + if ( typeof elem === "string" ) { + return jQuery.inArray( this[0], jQuery( elem ) ); + } + + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( jQuery.unique(all) ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter(selector) + ); + } +}); + +function sibling( cur, dir ) { + do { + cur = cur[ dir ]; + } while ( cur && cur.nodeType !== 1 ); + + return cur; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + if ( this.length > 1 ) { + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + ret = jQuery.unique( ret ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + } + + return this.pushStack( ret ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 && elem.nodeType === 1 ? + jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : + jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + })); + }, + + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + /* jshint -W018 */ + return !!qualifier.call( elem, i, elem ) !== not; + }); + + } + + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + }); + + } + + if ( typeof qualifier === "string" ) { + if ( isSimple.test( qualifier ) ) { + return jQuery.filter( qualifier, elements, not ); + } + + qualifier = jQuery.filter( qualifier, elements ); + } + + return jQuery.grep( elements, function( elem ) { + return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not; + }); +} +function createSafeFragment( document ) { + var list = nodeNames.split( "|" ), + safeFrag = document.createDocumentFragment(); + + if ( safeFrag.createElement ) { + while ( list.length ) { + safeFrag.createElement( + list.pop() + ); + } + } + return safeFrag; +} + +var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" + + "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", + rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g, + rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"), + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, + rtagName = /<([\w:]+)/, + rtbody = /\s*$/g, + + // We have to close these tags to support XHTML (#13200) + wrapMap = { + option: [ 1, "" ], + legend: [ 1, "
", "
" ], + area: [ 1, "", "" ], + param: [ 1, "", "" ], + thead: [ 1, "", "
" ], + tr: [ 2, "", "
" ], + col: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags, + // unless wrapped in a div with non-breaking characters in front of it. + _default: jQuery.support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X
", "
" ] + }, + safeFragment = createSafeFragment( document ), + fragmentDiv = safeFragment.appendChild( document.createElement("div") ); + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +jQuery.fn.extend({ + text: function( value ) { + return jQuery.access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) ); + }, null, value, arguments.length ); + }, + + append: function() { + return this.domManip( arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + }); + }, + + prepend: function() { + return this.domManip( arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + }); + }, + + before: function() { + return this.domManip( arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + }); + }, + + after: function() { + return this.domManip( arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + }); + }, + + // keepData is for internal use only--do not document + remove: function( selector, keepData ) { + var elem, + elems = selector ? jQuery.filter( selector, this ) : this, + i = 0; + + for ( ; (elem = elems[i]) != null; i++ ) { + + if ( !keepData && elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem ) ); + } + + if ( elem.parentNode ) { + if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) { + setGlobalEval( getAll( elem, "script" ) ); + } + elem.parentNode.removeChild( elem ); + } + } + + return this; + }, + + empty: function() { + var elem, + i = 0; + + for ( ; (elem = this[i]) != null; i++ ) { + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + } + + // Remove any remaining nodes + while ( elem.firstChild ) { + elem.removeChild( elem.firstChild ); + } + + // If this is a select, ensure that it displays empty (#12336) + // Support: IE<9 + if ( elem.options && jQuery.nodeName( elem, "select" ) ) { + elem.options.length = 0; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function () { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + }); + }, + + html: function( value ) { + return jQuery.access( this, function( value ) { + var elem = this[0] || {}, + i = 0, + l = this.length; + + if ( value === undefined ) { + return elem.nodeType === 1 ? + elem.innerHTML.replace( rinlinejQuery, "" ) : + undefined; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + ( jQuery.support.htmlSerialize || !rnoshimcache.test( value ) ) && + ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) && + !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) { + + value = value.replace( rxhtmlTag, "<$1>" ); + + try { + for (; i < l; i++ ) { + // Remove element nodes and prevent memory leaks + elem = this[i] || {}; + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch(e) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var + // Snapshot the DOM in case .domManip sweeps something relevant into its fragment + args = jQuery.map( this, function( elem ) { + return [ elem.nextSibling, elem.parentNode ]; + }), + i = 0; + + // Make the changes, replacing each context element with the new content + this.domManip( arguments, function( elem ) { + var next = args[ i++ ], + parent = args[ i++ ]; + + if ( parent ) { + // Don't use the snapshot next if it has moved (#13810) + if ( next && next.parentNode !== parent ) { + next = this.nextSibling; + } + jQuery( this ).remove(); + parent.insertBefore( elem, next ); + } + // Allow new content to include elements from the context set + }, true ); + + // Force removal if there was no new content (e.g., from empty arguments) + return i ? this : this.remove(); + }, + + detach: function( selector ) { + return this.remove( selector, true ); + }, + + domManip: function( args, callback, allowIntersection ) { + + // Flatten any nested arrays + args = core_concat.apply( [], args ); + + var first, node, hasScripts, + scripts, doc, fragment, + i = 0, + l = this.length, + set = this, + iNoClone = l - 1, + value = args[0], + isFunction = jQuery.isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( isFunction || !( l <= 1 || typeof value !== "string" || jQuery.support.checkClone || !rchecked.test( value ) ) ) { + return this.each(function( index ) { + var self = set.eq( index ); + if ( isFunction ) { + args[0] = value.call( this, index, self.html() ); + } + self.domManip( args, callback, allowIntersection ); + }); + } + + if ( l ) { + fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, !allowIntersection && this ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + if ( first ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( this[i], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) { + + if ( node.src ) { + // Hope ajax is available... + jQuery._evalUrl( node.src ); + } else { + jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) ); + } + } + } + } + + // Fix #11809: Avoid leaking memory + fragment = first = null; + } + } + + return this; + } +}); + +// Support: IE<8 +// Manipulating tables requires a tbody +function manipulationTarget( elem, content ) { + return jQuery.nodeName( elem, "table" ) && + jQuery.nodeName( content.nodeType === 1 ? content : content.firstChild, "tr" ) ? + + elem.getElementsByTagName("tbody")[0] || + elem.appendChild( elem.ownerDocument.createElement("tbody") ) : + elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = (jQuery.find.attr( elem, "type" ) !== null) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + var match = rscriptTypeMasked.exec( elem.type ); + if ( match ) { + elem.type = match[1]; + } else { + elem.removeAttribute("type"); + } + return elem; +} + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var elem, + i = 0; + for ( ; (elem = elems[i]) != null; i++ ) { + jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) ); + } +} + +function cloneCopyEvent( src, dest ) { + + if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) { + return; + } + + var type, i, l, + oldData = jQuery._data( src ), + curData = jQuery._data( dest, oldData ), + events = oldData.events; + + if ( events ) { + delete curData.handle; + curData.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + + // make the cloned public data object a copy from the original + if ( curData.data ) { + curData.data = jQuery.extend( {}, curData.data ); + } +} + +function fixCloneNodeIssues( src, dest ) { + var nodeName, e, data; + + // We do not need to do anything for non-Elements + if ( dest.nodeType !== 1 ) { + return; + } + + nodeName = dest.nodeName.toLowerCase(); + + // IE6-8 copies events bound via attachEvent when using cloneNode. + if ( !jQuery.support.noCloneEvent && dest[ jQuery.expando ] ) { + data = jQuery._data( dest ); + + for ( e in data.events ) { + jQuery.removeEvent( dest, e, data.handle ); + } + + // Event data gets referenced instead of copied if the expando gets copied too + dest.removeAttribute( jQuery.expando ); + } + + // IE blanks contents when cloning scripts, and tries to evaluate newly-set text + if ( nodeName === "script" && dest.text !== src.text ) { + disableScript( dest ).text = src.text; + restoreScript( dest ); + + // IE6-10 improperly clones children of object elements using classid. + // IE10 throws NoModificationAllowedError if parent is null, #12132. + } else if ( nodeName === "object" ) { + if ( dest.parentNode ) { + dest.outerHTML = src.outerHTML; + } + + // This path appears unavoidable for IE9. When cloning an object + // element in IE9, the outerHTML strategy above is not sufficient. + // If the src has innerHTML and the destination does not, + // copy the src.innerHTML into the dest.innerHTML. #10324 + if ( jQuery.support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) { + dest.innerHTML = src.innerHTML; + } + + } else if ( nodeName === "input" && manipulation_rcheckableType.test( src.type ) ) { + // IE6-8 fails to persist the checked state of a cloned checkbox + // or radio button. Worse, IE6-7 fail to give the cloned element + // a checked appearance if the defaultChecked value isn't also set + + dest.defaultChecked = dest.checked = src.checked; + + // IE6-7 get confused and end up setting the value of a cloned + // checkbox/radio button to an empty string instead of "on" + if ( dest.value !== src.value ) { + dest.value = src.value; + } + + // IE6-8 fails to return the selected option to the default selected + // state when cloning options + } else if ( nodeName === "option" ) { + dest.defaultSelected = dest.selected = src.defaultSelected; + + // IE6-8 fails to set the defaultValue to the correct value when + // cloning other types of input fields + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +jQuery.each({ + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + i = 0, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone(true); + jQuery( insert[i] )[ original ]( elems ); + + // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get() + core_push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +}); + +function getAll( context, tag ) { + var elems, elem, + i = 0, + found = typeof context.getElementsByTagName !== core_strundefined ? context.getElementsByTagName( tag || "*" ) : + typeof context.querySelectorAll !== core_strundefined ? context.querySelectorAll( tag || "*" ) : + undefined; + + if ( !found ) { + for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) { + if ( !tag || jQuery.nodeName( elem, tag ) ) { + found.push( elem ); + } else { + jQuery.merge( found, getAll( elem, tag ) ); + } + } + } + + return tag === undefined || tag && jQuery.nodeName( context, tag ) ? + jQuery.merge( [ context ], found ) : + found; +} + +// Used in buildFragment, fixes the defaultChecked property +function fixDefaultChecked( elem ) { + if ( manipulation_rcheckableType.test( elem.type ) ) { + elem.defaultChecked = elem.checked; + } +} + +jQuery.extend({ + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var destElements, node, clone, i, srcElements, + inPage = jQuery.contains( elem.ownerDocument, elem ); + + if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) { + clone = elem.cloneNode( true ); + + // IE<=8 does not properly clone detached, unknown element nodes + } else { + fragmentDiv.innerHTML = elem.outerHTML; + fragmentDiv.removeChild( clone = fragmentDiv.firstChild ); + } + + if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) && + (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { + + // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + // Fix all IE cloning issues + for ( i = 0; (node = srcElements[i]) != null; ++i ) { + // Ensure that the destination node is not null; Fixes #9587 + if ( destElements[i] ) { + fixCloneNodeIssues( node, destElements[i] ); + } + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0; (node = srcElements[i]) != null; i++ ) { + cloneCopyEvent( node, destElements[i] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + destElements = srcElements = node = null; + + // Return the cloned set + return clone; + }, + + buildFragment: function( elems, context, scripts, selection ) { + var j, elem, contains, + tmp, tag, tbody, wrap, + l = elems.length, + + // Ensure a safe fragment + safe = createSafeFragment( context ), + + nodes = [], + i = 0; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( jQuery.type( elem ) === "object" ) { + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || safe.appendChild( context.createElement("div") ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + + tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1>" ) + wrap[2]; + + // Descend through wrappers to the right content + j = wrap[0]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Manually add leading whitespace removed by IE + if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { + nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) ); + } + + // Remove IE's autoinserted from table fragments + if ( !jQuery.support.tbody ) { + + // String was a , *may* have spurious + elem = tag === "table" && !rtbody.test( elem ) ? + tmp.firstChild : + + // String was a bare or + wrap[1] === "
" && !rtbody.test( elem ) ? + tmp : + 0; + + j = elem && elem.childNodes.length; + while ( j-- ) { + if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) { + elem.removeChild( tbody ); + } + } + } + + jQuery.merge( nodes, tmp.childNodes ); + + // Fix #12392 for WebKit and IE > 9 + tmp.textContent = ""; + + // Fix #12392 for oldIE + while ( tmp.firstChild ) { + tmp.removeChild( tmp.firstChild ); + } + + // Remember the top-level container for proper cleanup + tmp = safe.lastChild; + } + } + } + + // Fix #11356: Clear elements from fragment + if ( tmp ) { + safe.removeChild( tmp ); + } + + // Reset defaultChecked for any radios and checkboxes + // about to be appended to the DOM in IE 6/7 (#8060) + if ( !jQuery.support.appendChecked ) { + jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked ); + } + + i = 0; + while ( (elem = nodes[ i++ ]) ) { + + // #4087 - If origin and destination elements are the same, and this is + // that element, do not do anything + if ( selection && jQuery.inArray( elem, selection ) !== -1 ) { + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); + + // Append to fragment + tmp = getAll( safe.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( contains ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( (elem = tmp[ j++ ]) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + tmp = null; + + return safe; + }, + + cleanData: function( elems, /* internal */ acceptData ) { + var elem, type, id, data, + i = 0, + internalKey = jQuery.expando, + cache = jQuery.cache, + deleteExpando = jQuery.support.deleteExpando, + special = jQuery.event.special; + + for ( ; (elem = elems[i]) != null; i++ ) { + + if ( acceptData || jQuery.acceptData( elem ) ) { + + id = elem[ internalKey ]; + data = id && cache[ id ]; + + if ( data ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Remove cache only if it was not already removed by jQuery.event.remove + if ( cache[ id ] ) { + + delete cache[ id ]; + + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( deleteExpando ) { + delete elem[ internalKey ]; + + } else if ( typeof elem.removeAttribute !== core_strundefined ) { + elem.removeAttribute( internalKey ); + + } else { + elem[ internalKey ] = null; + } + + core_deletedIds.push( id ); + } + } + } + } + }, + + _evalUrl: function( url ) { + return jQuery.ajax({ + url: url, + type: "GET", + dataType: "script", + async: false, + global: false, + "throws": true + }); + } +}); +jQuery.fn.extend({ + wrapAll: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapAll( html.call(this, i) ); + }); + } + + if ( this[0] ) { + // The elements to wrap the target around + var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true); + + if ( this[0].parentNode ) { + wrap.insertBefore( this[0] ); + } + + wrap.map(function() { + var elem = this; + + while ( elem.firstChild && elem.firstChild.nodeType === 1 ) { + elem = elem.firstChild; + } + + return elem; + }).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapInner( html.call(this, i) ); + }); + } + + return this.each(function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + }); + }, + + wrap: function( html ) { + var isFunction = jQuery.isFunction( html ); + + return this.each(function(i) { + jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html ); + }); + }, + + unwrap: function() { + return this.parent().each(function() { + if ( !jQuery.nodeName( this, "body" ) ) { + jQuery( this ).replaceWith( this.childNodes ); + } + }).end(); + } +}); +var iframe, getStyles, curCSS, + ralpha = /alpha\([^)]*\)/i, + ropacity = /opacity\s*=\s*([^)]*)/, + rposition = /^(top|right|bottom|left)$/, + // swappable if display is none or starts with table except "table", "table-cell", or "table-caption" + // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rmargin = /^margin/, + rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ), + rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ), + rrelNum = new RegExp( "^([+-])=(" + core_pnum + ")", "i" ), + elemdisplay = { BODY: "block" }, + + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: 0, + fontWeight: 400 + }, + + cssExpand = [ "Top", "Right", "Bottom", "Left" ], + cssPrefixes = [ "Webkit", "O", "Moz", "ms" ]; + +// return a css property mapped to a potentially vendor prefixed property +function vendorPropName( style, name ) { + + // shortcut for names that are not vendor prefixed + if ( name in style ) { + return name; + } + + // check for vendor prefixed names + var capName = name.charAt(0).toUpperCase() + name.slice(1), + origName = name, + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in style ) { + return name; + } + } + + return origName; +} + +function isHidden( elem, el ) { + // isHidden might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); +} + +function showHide( elements, show ) { + var display, elem, hidden, + values = [], + index = 0, + length = elements.length; + + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + values[ index ] = jQuery._data( elem, "olddisplay" ); + display = elem.style.display; + if ( show ) { + // Reset the inline display of this element to learn if it is + // being hidden by cascaded rules or not + if ( !values[ index ] && display === "none" ) { + elem.style.display = ""; + } + + // Set elements which have been overridden with display: none + // in a stylesheet to whatever the default browser style is + // for such an element + if ( elem.style.display === "" && isHidden( elem ) ) { + values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) ); + } + } else { + + if ( !values[ index ] ) { + hidden = isHidden( elem ); + + if ( display && display !== "none" || !hidden ) { + jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) ); + } + } + } + } + + // Set the display of most of the elements in a second loop + // to avoid the constant reflow + for ( index = 0; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + if ( !show || elem.style.display === "none" || elem.style.display === "" ) { + elem.style.display = show ? values[ index ] || "" : "none"; + } + } + + return elements; +} + +jQuery.fn.extend({ + css: function( name, value ) { + return jQuery.access( this, function( elem, name, value ) { + var len, styles, + map = {}, + i = 0; + + if ( jQuery.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + }, + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each(function() { + if ( isHidden( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + }); + } +}); + +jQuery.extend({ + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "columnCount": true, + "fillOpacity": true, + "fontWeight": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: { + // normalize float css property + "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat" + }, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = jQuery.camelCase( name ), + style = elem.style; + + name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) ); + + // gets hook for the prefixed version + // followed by the unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // convert relative number strings (+= or -=) to relative numbers. #7345 + if ( type === "string" && (ret = rrelNum.exec( value )) ) { + value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) ); + // Fixes bug #9237 + type = "number"; + } + + // Make sure that NaN and null values aren't set. See: #7116 + if ( value == null || type === "number" && isNaN( value ) ) { + return; + } + + // If a number was passed in, add 'px' to the (except for certain CSS properties) + if ( type === "number" && !jQuery.cssNumber[ origName ] ) { + value += "px"; + } + + // Fixes #8908, it can be done more correctly by specifing setters in cssHooks, + // but it would mean to define eight (for every problematic property) identical functions + if ( !jQuery.support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) { + + // Wrapped to prevent IE from throwing errors when 'invalid' values are provided + // Fixes bug #5509 + try { + style[ name ] = value; + } catch(e) {} + } + + } else { + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) { + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var num, val, hooks, + origName = jQuery.camelCase( name ); + + // Make sure that we're working with the right name + name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) ); + + // gets hook for the prefixed version + // followed by the unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + //convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Return, converting to number if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || jQuery.isNumeric( num ) ? num || 0 : val; + } + return val; + } +}); + +// NOTE: we've included the "window" in window.getComputedStyle +// because jsdom on node.js will break without it. +if ( window.getComputedStyle ) { + getStyles = function( elem ) { + return window.getComputedStyle( elem, null ); + }; + + curCSS = function( elem, name, _computed ) { + var width, minWidth, maxWidth, + computed = _computed || getStyles( elem ), + + // getPropertyValue is only needed for .css('filter') in IE9, see #12537 + ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined, + style = elem.style; + + if ( computed ) { + + if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right + // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels + // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values + if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret; + }; +} else if ( document.documentElement.currentStyle ) { + getStyles = function( elem ) { + return elem.currentStyle; + }; + + curCSS = function( elem, name, _computed ) { + var left, rs, rsLeft, + computed = _computed || getStyles( elem ), + ret = computed ? computed[ name ] : undefined, + style = elem.style; + + // Avoid setting ret to empty string here + // so we don't default to auto + if ( ret == null && style && style[ name ] ) { + ret = style[ name ]; + } + + // From the awesome hack by Dean Edwards + // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 + + // If we're not dealing with a regular pixel number + // but a number that has a weird ending, we need to convert it to pixels + // but not position css attributes, as those are proportional to the parent element instead + // and we can't measure the parent instead because it might trigger a "stacking dolls" problem + if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) { + + // Remember the original values + left = style.left; + rs = elem.runtimeStyle; + rsLeft = rs && rs.left; + + // Put in the new values to get a computed value out + if ( rsLeft ) { + rs.left = elem.currentStyle.left; + } + style.left = name === "fontSize" ? "1em" : ret; + ret = style.pixelLeft + "px"; + + // Revert the changed values + style.left = left; + if ( rsLeft ) { + rs.left = rsLeft; + } + } + + return ret === "" ? "auto" : ret; + }; +} + +function setPositiveNumber( elem, value, subtract ) { + var matches = rnumsplit.exec( value ); + return matches ? + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) : + value; +} + +function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) { + var i = extra === ( isBorderBox ? "border" : "content" ) ? + // If we already have the right measurement, avoid augmentation + 4 : + // Otherwise initialize for horizontal or vertical properties + name === "width" ? 1 : 0, + + val = 0; + + for ( ; i < 4; i += 2 ) { + // both box models exclude margin, so add it if we want it + if ( extra === "margin" ) { + val += jQuery.css( elem, extra + cssExpand[ i ], true, styles ); + } + + if ( isBorderBox ) { + // border-box includes padding, so remove it if we want content + if ( extra === "content" ) { + val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // at this point, extra isn't border nor margin, so remove border + if ( extra !== "margin" ) { + val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } else { + // at this point, extra isn't content, so add padding + val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // at this point, extra isn't content nor padding, so add border + if ( extra !== "padding" ) { + val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + return val; +} + +function getWidthOrHeight( elem, name, extra ) { + + // Start with offset property, which is equivalent to the border-box value + var valueIsBorderBox = true, + val = name === "width" ? elem.offsetWidth : elem.offsetHeight, + styles = getStyles( elem ), + isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // some non-html elements return undefined for offsetWidth, so check for null/undefined + // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285 + // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668 + if ( val <= 0 || val == null ) { + // Fall back to computed then uncomputed css if necessary + val = curCSS( elem, name, styles ); + if ( val < 0 || val == null ) { + val = elem.style[ name ]; + } + + // Computed unit is not pixels. Stop here and return. + if ( rnumnonpx.test(val) ) { + return val; + } + + // we need the check for style in case a browser which returns unreliable values + // for getComputedStyle silently falls back to the reliable elem.style + valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] ); + + // Normalize "", auto, and prepare for extra + val = parseFloat( val ) || 0; + } + + // use the active box-sizing model to add/subtract irrelevant styles + return ( val + + augmentWidthOrHeight( + elem, + name, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles + ) + ) + "px"; +} + +// Try to determine the default display value of an element +function css_defaultDisplay( nodeName ) { + var doc = document, + display = elemdisplay[ nodeName ]; + + if ( !display ) { + display = actualDisplay( nodeName, doc ); + + // If the simple way fails, read from inside an iframe + if ( display === "none" || !display ) { + // Use the already-created iframe if possible + iframe = ( iframe || + jQuery("