diff --git a/README.md b/README.md index cf34370..54df1f5 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,37 @@ -# racalmas -radio calendar management system +#radio calendar management system + +Web View +![public calendar](docs/screenshots/web-view.png) + +Projects +![studios](docs/screenshots/calcms-projects.png) + +Studios +![studios](docs/screenshots/calcms-studios.png) + +Assign Roles by Project and Studio +![roles](docs/screenshots/calcms-roles.png) + +Schedule Studio Broadcast Time +![schedule studios](docs/screenshots/calcms-schedule-studios.png) + +Event Calendar +![management calendar](docs/screenshots/calcms-calendar.png) + +Series +![series](docs/screenshots/calcms-show-series.png) + +Edit Series +![series](docs/screenshots/calcms-edit-series.png) + +Schedule Series +![series](docs/screenshots/calcms-schedule-series.png) + +List Series Events +![series-events](docs/screenshots/calcms-series-events.png) + +Edit Event +![edit-event](docs/screenshots/calcms-edit-event.png) + +Ingegrated View on External Playout System +![import playout status](docs/screenshots/calcms-import-playout-status.png) diff --git a/docs/index.html b/docs/index.html index 2438e66..3a93180 100644 --- a/docs/index.html +++ b/docs/index.html @@ -68,7 +68,7 @@ diff --git a/docs/programm.html b/docs/programm.html index 62c3879..f950a8b 100644 --- a/docs/programm.html +++ b/docs/programm.html @@ -86,7 +86,7 @@ diff --git a/docs/screenshots/calcms-calendar.png b/docs/screenshots/calcms-calendar.png new file mode 100644 index 0000000..bca6351 Binary files /dev/null and b/docs/screenshots/calcms-calendar.png differ diff --git a/docs/screenshots/calcms-edit-event.png b/docs/screenshots/calcms-edit-event.png new file mode 100644 index 0000000..a729d0e Binary files /dev/null and b/docs/screenshots/calcms-edit-event.png differ diff --git a/docs/screenshots/calcms-edit-series.png b/docs/screenshots/calcms-edit-series.png new file mode 100644 index 0000000..5123b49 Binary files /dev/null and b/docs/screenshots/calcms-edit-series.png differ diff --git a/docs/screenshots/calcms-import-playout-status.png b/docs/screenshots/calcms-import-playout-status.png new file mode 100644 index 0000000..dd24b81 Binary files /dev/null and b/docs/screenshots/calcms-import-playout-status.png differ diff --git a/docs/screenshots/calcms-projects.png b/docs/screenshots/calcms-projects.png new file mode 100644 index 0000000..2e870f5 Binary files /dev/null and b/docs/screenshots/calcms-projects.png differ diff --git a/docs/screenshots/calcms-roles.png b/docs/screenshots/calcms-roles.png new file mode 100644 index 0000000..5ee1f24 Binary files /dev/null and b/docs/screenshots/calcms-roles.png differ diff --git a/docs/screenshots/calcms-schedule-series.png b/docs/screenshots/calcms-schedule-series.png new file mode 100644 index 0000000..2566f14 Binary files /dev/null and b/docs/screenshots/calcms-schedule-series.png differ diff --git a/docs/screenshots/calcms-schedule-studios.png b/docs/screenshots/calcms-schedule-studios.png new file mode 100644 index 0000000..2f2f733 Binary files /dev/null and b/docs/screenshots/calcms-schedule-studios.png differ diff --git a/docs/screenshots/calcms-series-events.png b/docs/screenshots/calcms-series-events.png new file mode 100644 index 0000000..eb7dcd6 Binary files /dev/null and b/docs/screenshots/calcms-series-events.png differ diff --git a/docs/screenshots/calcms-series.png b/docs/screenshots/calcms-series.png new file mode 100644 index 0000000..aed2242 Binary files /dev/null and b/docs/screenshots/calcms-series.png differ diff --git a/docs/screenshots/calcms-show-series.png b/docs/screenshots/calcms-show-series.png new file mode 100644 index 0000000..4d61844 Binary files /dev/null and b/docs/screenshots/calcms-show-series.png differ diff --git a/docs/screenshots/calcms-studios.png b/docs/screenshots/calcms-studios.png new file mode 100644 index 0000000..a7d6397 Binary files /dev/null and b/docs/screenshots/calcms-studios.png differ diff --git a/docs/screenshots/web-view.png b/docs/screenshots/web-view.png new file mode 100644 index 0000000..13e2cd1 Binary files /dev/null and b/docs/screenshots/web-view.png differ diff --git a/example/help.html b/example/help.html index a33f32d..3fbab70 100644 --- a/example/help.html +++ b/example/help.html @@ -75,7 +75,7 @@ diff --git a/example/index.html b/example/index.html index 81d4802..7a25995 100644 --- a/example/index.html +++ b/example/index.html @@ -78,7 +78,7 @@ diff --git a/example/programm.html b/example/programm.html index 80050e2..bb5e09e 100644 --- a/example/programm.html +++ b/example/programm.html @@ -68,7 +68,7 @@ Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod diff --git a/install/INSTALL.md b/install/INSTALL.md new file mode 100644 index 0000000..c9ed5cb --- /dev/null +++ b/install/INSTALL.md @@ -0,0 +1,186 @@ + +# setup database + +Edit the file "init.sql" and change the passwords of the three user accounts (calcms_admin, calcms_write and calcms_read). +We use different accounts for different purposes. + +## run init script with root permissions + + mysql -u root -p < ./install/init.sql + +## if using plesk, use + + mysql -u admin mysql -p`cat /etc/psa/.psa.shadow` < ./install/init.sql + +## import database content + + mysql -u calcms_admin -p calcms < ./install/create.sql + +## socket connection issues + +If you use a local database connection and see the error message +"could not connect to database: Can't connect to local MySQL server through socket" +the user "www-data" cannot connect to socket due to missing permissions to the socket +file /var/run/mysqld/mysqld.sock. You can either change the directory/file permissions +or use host "127.0.0.1" in bind-address at /etc/mysql/* for client and server and +additionally as hostname in config.cgi. + +## Apache HTTP Server Setup + +### install mod_perl + +install apache2 + + apt install apache2 + +enable prefork mode + + a2dismod mpm_event + a2enmod mpm_prefork + /etc/init.d/apache2 restart + +install apache2 rewrite + + apt-get install libapache2-rewrite + a2enmod rewrite + +install mod_perl2 + + apt install libapache2-mod-perl2 libapache2-reload-perl libapache2-request-perl + a2enmod perl + +### Apache Configuration + +Copy Virtual host configuration apache2-sites/calcms.conf to /etc/conf/apache2/sites-enabled/. + +* setup domain +* setup database connection +* setup directories + +### install required perl modules + +There are debian packages for most required perl modules. +You can install CPAN packages, if you cannot use debian packages. +For example there is no debian package for Image::Magick::Square, so you can install it by "cpan Image::Magick::Square". + +apt-get install + +#### install debian packages + + mariadb-server + build-essentials + imagemagick + libapreq2-3 + libapache2-request-perl + libapache-dbi-perl + libauthen-passphrase-blowfish-perl + libcalendar-simple-perl + libcrypt-blowfish-perl + libcgi-pm-perl + libcgi-session-perl + libcgi-simple-perl + libconfig-general-perl + libdatetime-perl + libdate-calc-perl + libdate-manip-perl + libdbi-perl + libdbd-mysql-perl + libencode-perl + libjson-perl + libhtml-formattext-withlinks-andtables-perl + libhtml-parser-perl + libhtml-template-perl + libhtml-template-compiled-perl + libmime-base64-urlsafe-perl + libmime-lite-perl + libsession-token-perl + libtext-multimarkdown-perl + libtext-wikicreole-perl + liburi-escape-xs-perl + perlmagick + +#### Install CPAN packages + + cpan + + Apache2::Reload + Apache2::Request + Apache2::Upload + Apache::DBI + Authen::Passphrase + Authen::Passphrase::BlowfishCrypt + Calendar::Simple + CGI + CGI::Carp + CGI::Cookie + CGI::Session + CGI::Simple + Config::General + Data::Dumper + Date::Calc + Date::Manip + DateTime + DBD::mysql + DBI + Digest::MD5 + Encode::Locale + HTML::Entities + HTML::FormatText + HTML::Parse + HTML::Template::Compiled + HTML::Template::Compiled::Plugin::XMLEscape + Image::Magick + Image::Magick::Square + JSON + MIME::Lite + ModPerl::Util + Session::Token + Text::Diff::FormatedHtml + Text::Markdown + Text::WikiCreole + URI::Escape + +#### Configuration + +Copy the configuration from website/config/config.cgi.off to website/config/config.cgi. +Setup the domain and database connection. + +Now you can open the web gui at http:///programm/ + +To edit your radio programm open http:///agenda/planung/ +ccAdmin +shug!3Lu + +# inject calcms into your website + +calcms uses a copy of your web page as a template to have the same layout as your web site. +To update calcms content create a cronjob to run tools/update_page.sh + +you may have to update the paths inside update_page.sh + +# how-to + +## update time zones + + mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql -p + +if using plesk, use + + mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u admin mysql -p`cat /etc/psa/.psa.shadow` + +## create database schema deltas for updates + + cat calcmsOld.sql | mysql -u root calcmsOld + cat calcmsNew.sql | mysql -u root calcmsNew + mysqldiff --force --changes-for=server2 --difftype=sql calcmsOld:calcmsNew > migrate.sql + # make sure lines with "modified_at" contain "ON UPDATE CURRENT_TIMESTAMP" + # for example: `modified_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP + cat migrate | mysql -u root calcms + +## reset the default admin account run + + update calcms_users set pass='$2a$08$oLiwMC1vYD8ZzfjKdpTG3OBFAXbiKslWIe0w005ysdxO0kE/A/12G', salt='oLiwMC1vYD8ZzfjKdpTG3O' where name='ccAdmin'; + +## Image::Magick::Square + +If installation of Image::Magick::Square fails, you probably need to install a recent version of Image::Magick. diff --git a/install/INSTALL.txt b/install/INSTALL.txt deleted file mode 100644 index 477f2ab..0000000 --- a/install/INSTALL.txt +++ /dev/null @@ -1,240 +0,0 @@ - -==== database setup ==== - -=== create database === - - mysqladmin -u root -p create calcms_test - -=== create users === - - mysql -u root -p - -if using plesk, use - - mysql -u admin mysql -p`cat /etc/psa/.psa.shadow` - -# calcms_admin - -CREATE USER 'calcms_admin'@'localhost' IDENTIFIED BY 'taes9Cho'; -GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER ON *.* TO 'calcms_admin'@'localhost' IDENTIFIED BY 'taes9Cho'; -GRANT ALL PRIVILEGES ON `calcms_test`.* TO 'calcms_admin'@'localhost'; - -# calcms_write / for users - -CREATE USER 'calcms_write'@'localhost' IDENTIFIED BY 'Toothok8'; -GRANT SELECT, INSERT, UPDATE, DELETE ON *.* TO 'calcms_write'@'localhost' IDENTIFIED BY 'Toothok8'; -GRANT ALL PRIVILEGES ON `calcms_test`.* TO 'calcms_write'@'localhost'; - -# calcms_read / for all - -CREATE USER 'calcms_read'@'localhost' IDENTIFIED BY 'Ro2chiya'; -GRANT SELECT ON *.* TO 'calcms_read'@'localhost' IDENTIFIED BY 'Ro2chiya' ; -GRANT ALL PRIVILEGES ON `calcms_test`.* TO 'calcms_read'@'localhost'; - -=== deploy time zones === - - mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql -p - -if using plesk, use - - mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u admin mysql -p`cat /etc/psa/.psa.shadow` - -=== create database content === - -mysql -u calcms_admin -p calcms_test < ./install/create.sql - -==== Apache HTTP Server Setup (at /etc/conf/apache2/ server settings or vhost settings) ==== - -=== install mod_perl === - -install - -libapache2-mod-perl2 -libapache2-reload-perl -libapache2-request-perl - -or via cpan - -Apache2::Reload -Apache2::Request - -if mod_perl was installed already make sure it is enabled - - ln -s /etc/apache2/mods-available/perl.load /etc/apache2/mods-enabled/perl.load - -=== enable mod_rewrite === - -install - -libapache2-rewrite - - ln -s /etc/apache2/mods-available/rewrite.load /etc/apache2/mods-enabled/rewrite.load - -=== Apache Configuration ) === - -This has to be put into your apache server or virtual host configuration - -### START OF FILE ### - - # Possible values include: debug, info, notice, warn, error, crit, alert, emerg. - LogLevel debug - - # init mod_perl (should be done at /etc/apache/mods-enabled/perl.load) - # LoadModule perl_module /usr/lib/apache2/modules/mod_perl.so - - # redirect to inject calcms into website - LimitInternalRecursion 4 - - # enable this at HTTP configuration, but disable at HTTPS configuration (!) - Redirect permanent /agenda/planung https://calcms.medienstaatsvertrag.org/agenda/planung - - # alias to inject calcms into website - Alias /agenda /home/calcms/website/agenda - Alias /agenda_files /home/calcms/website/agenda_files - Alias /programm /home/calcms/website/agenda/cache/programm - - - AllowOverride All - Options -Indexes +FollowSymLinks +MultiViews +ExecCGI - Order allow,deny - Allow from all - Require all granted - - - - AllowOverride All - Options -Indexes +FollowSymLinks +MultiViews +ExecCGI - Order allow,deny - Allow from all - Require all granted - - - - AllowOverride All - Options -Indexes -FollowSymLinks -MultiViews -ExecCGI - Order allow,deny - Allow from all - Require all granted - - - #mod_perl - - PerlSetEnv LC_ALL en_US.UTF-8 - PerlSetEnv LANGUAGE en_US.UTF-8 - - PerlWarn On - PerlModule ModPerl::RegistryPrefork - - PerlModule Apache2::Reload - PerlInitHandler Apache2::Reload - #PerlSetVar ReloadAll Off - - SetEnv TMPDIR /var/tmp/ - - # set base library path - PerlSetEnv PERL5LIB /home/calcms/lib/calcms/ - PerlPostConfigRequire /home/calcms/lib/calcms/startup.pl - - -#### END_OF_FILE #### - -=== install required perl modules === - -For debian/ubuntu there are packages for most required modules. -If you cannot install packages you can use the CPAN perl package install. -For Image::Magick::Square no deb package exists, you need to install it by "cpan Image::Magick::Square" - -apt-get install - -== Install by deb package == - -mariadb-server -build-essentials -libapreq2-3 -libapache-dbi-perl -libauthen-passphrase-blowfish-perl -libcalendar-simple-perl -libcgi-pm-perl -libcgi-session-perl -libconfig-general-perl -libdatetime-perl -libdate-calc-perl -libdate-manip-perl -libdbi-perl -libdbd-mysql-perl -libencode-perl -libjson-perl -libhtml-formattext-withlinks-andtables-perl -libhtml-parser-perl -libhtml-template-perl -libhtml-template-compiled-perl -libmime-base64-urlsafe-perl -libtext-wikicreole-perl -liburi-escape-xs-perl -perlmagick - -== Install by CPAN perl packages == - - cpan - -Apache2::Upload -Apache::DBI -Authen::Passphrase -Authen::Passphrase::BlowfishCrypt -Calendar::Simple -CGI::Simple -CGI::Session -CGI -CGI::Carp -CGI::Cookie -Config::General -Data::Dumper -DateTime -Date::Calc -Date::Manip -DBD::mysql -DBI -Encode -File::stat -HTML::FormatText -HTML::Parse -HTML::Template -HTML::Template::Compiled -HTML::Template::Compiled::Plugin::XMLEscape -JSON -MIME::Base64 -MIME::Lite -Text::Diff::FormatedHtml -Text::WikiCreole -Time::Local -Time::localtime -URI::Escape -Image::Magick -Image::Magick::Square - -==== Configure ==== - -edit configuration at website/config/config.cgi - -==== inject calcms into any CMS ==== - -to frequently update calcms integration create a cronjob to run tools/update_page.sh - -you may have to update the paths inside update_page.sh - -=== connect to Admin interface - -https://localhost/agenda/planung/ -ccAdmin -shug!3Lu - -=== how to migrate schema from one version to another one - -cat calcmsOld.sql | mysql -u root calcmsOld -cat calcmsNew.sql | mysql -u root calcmsNew - -mysqldiff --force --changes-for=server2 --difftype=sql calcmsOld:calcmsNew > migrate.sql -# make sure lines with "modified_at" contain "ON UPDATE CURRENT_TIMESTAMP" -# for example: `modified_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP -cat migrate | mysql -u root calcms - diff --git a/install/apache2-sites/calcms.conf b/install/apache2-sites/calcms.conf new file mode 100644 index 0000000..2341144 --- /dev/null +++ b/install/apache2-sites/calcms.conf @@ -0,0 +1,79 @@ +LogLevel info +LimitInternalRecursion 4 + +# redirect HTTP to HTTPS, +# only needed for HTTP configuration, do not use this at HTTPS configuration(!) +# Redirect permanent /agenda/planung https://${domain}/agenda/planung + +Define domain localhost +Define base_dir /home/calcms/racalmas +Define web_dir /home/calcms/racalmas/website/ +Define perl_lib /home/calcms/racalmas/lib +Define archive_dir /home/radio/archive/ + +# Redirect permanent /agenda/planung https://${domain}/agenda/planung +# ^ remove comment to redirect HTTP to HTTPS +# (enabling this in HTTPS templates results in endless routing loop)! + +# calcms endpoints for your website +# frontend +Alias /programm ${web_dir}/programm + +# backend +Alias /agenda ${web_dir}/agenda + +# image base +Alias /media ${base_dir}/media + +# thumbs +Alias /thumbs ${base_dir}/media/thumbs + +# icons +Alias /icons ${base_dir}/media/icons + +# audio upload +Alias /recordings ${base_dir}/recordings + +# audio download +Alias /listen ${archive_dir}/${domain} + +# upload playout status +ScriptAlias /agenda/planung/upload ${archive_dir}/${domain}/agenda/planung/upload + + + AllowOverride All + Options -Indexes +FollowSymLinks +MultiViews +ExecCGI + Require all granted + + + + AllowOverride All + Options -Indexes +FollowSymLinks -MultiViews -ExecCGI + Require all granted + + + + AllowOverride All + Options -Indexes -FollowSymLinks -MultiViews -ExecCGI + Require all granted + + + + PerlSetEnv LC_ALL en_US.UTF-8 + PerlSetEnv LANGUAGE en_US.UTF-8 + + PerlWarn On + PerlModule ModPerl::RegistryPrefork + + PerlModule Apache2::Reload + PerlInitHandler Apache2::Reload + + # set local tmp dir + SetEnv TMPDIR ${base_dir}/tmp/ + + # set library directory + PerlSetEnv PERL5LIB ${base_dir}/lib/calcms/ + + # preload libraries + PerlPostConfigRequire ${base_dir}/lib/calcms/startup.pl + diff --git a/install/create.sql b/install/create.sql index 4404da0..5e17fc0 100644 --- a/install/create.sql +++ b/install/create.sql @@ -1,13 +1,13 @@ --- MySQL dump 10.13 Distrib 5.7.20, for Linux (x86_64) +-- MySQL dump 10.13 Distrib 8.0.32, for Linux (x86_64) -- -- Host: localhost Database: calcms -- ------------------------------------------------------ --- Server version 5.7.20-0ubuntu0.16.04.1 +-- Server version 8.0.32-0ubuntu0.20.04.2 /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!50503 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -21,29 +21,31 @@ DROP TABLE IF EXISTS `calcms_audio_recordings`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!50503 SET character_set_client = utf8mb4 */; CREATE TABLE `calcms_audio_recordings` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `project_id` int(11) NOT NULL, - `studio_id` int(11) NOT NULL, - `event_id` int(11) NOT NULL, - `created_by` varchar(100) NOT NULL, + `id` int unsigned NOT NULL AUTO_INCREMENT, + `project_id` int NOT NULL, + `studio_id` int NOT NULL, + `event_id` int NOT NULL, + `active` tinyint(1) NOT NULL DEFAULT '0', `path` varchar(300) NOT NULL, - `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - `size` bigint(20) unsigned NOT NULL DEFAULT '0', + `size` bigint unsigned NOT NULL DEFAULT '0', `audioDuration` float NOT NULL DEFAULT '0', - `eventDuration` int(11) NOT NULL DEFAULT '0', + `eventDuration` int NOT NULL DEFAULT '0', `rmsLeft` float NOT NULL, `rmsRight` float NOT NULL, `mastered` tinyint(1) NOT NULL DEFAULT '0', `processed` tinyint(1) NOT NULL DEFAULT '0', + `created_by` varchar(100) NOT NULL, + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `modified_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `project_index` (`project_id`), KEY `studio_index` (`studio_id`), KEY `event_index` (`event_id`), - KEY `created_at_index` (`created_at`) -) ENGINE=MyISAM AUTO_INCREMENT=54 DEFAULT CHARSET=utf8; + KEY `created_at_index` (`created_at`), + KEY `active_index` (`active`) +) ENGINE=MyISAM AUTO_INCREMENT=4570 DEFAULT CHARSET=utf8mb3; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -61,17 +63,17 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `calcms_categories`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!50503 SET character_set_client = utf8mb4 */; CREATE TABLE `calcms_categories` ( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `id` bigint unsigned NOT NULL AUTO_INCREMENT, `name` varchar(256) DEFAULT NULL, - `event_id` varchar(256) CHARACTER SET latin1 NOT NULL, + `event_id` varchar(256) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL, `project` varchar(64) DEFAULT NULL, KEY `id` (`id`), KEY `event_id` (`event_id`), KEY `name` (`name`), KEY `project` (`project`) -) ENGINE=MyISAM AUTO_INCREMENT=12646 DEFAULT CHARSET=utf8; +) ENGINE=MyISAM AUTO_INCREMENT=12646 DEFAULT CHARSET=utf8mb3; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -89,11 +91,11 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `calcms_comments`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!50503 SET character_set_client = utf8mb4 */; CREATE TABLE `calcms_comments` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `id` int unsigned NOT NULL AUTO_INCREMENT, `event_start` datetime DEFAULT NULL, - `event_id` int(10) unsigned DEFAULT NULL, + `event_id` int unsigned DEFAULT NULL, `content` text, `ip` varchar(22) DEFAULT NULL, `author` varchar(40) DEFAULT NULL, @@ -101,8 +103,8 @@ CREATE TABLE `calcms_comments` ( `lock_status` varchar(16) NOT NULL DEFAULT 'show', `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `title` varchar(80) DEFAULT NULL, - `parent_id` int(10) unsigned DEFAULT NULL, - `level` int(10) unsigned DEFAULT NULL, + `parent_id` int unsigned DEFAULT NULL, + `level` int unsigned DEFAULT NULL, `news_status` varchar(16) NOT NULL DEFAULT 'unread', `project` varchar(64) DEFAULT NULL, PRIMARY KEY (`id`), @@ -113,7 +115,7 @@ CREATE TABLE `calcms_comments` ( KEY `level` (`level`), KEY `created_at` (`created_at`), KEY `project` (`project`) -) ENGINE=MyISAM AUTO_INCREMENT=5485 DEFAULT CHARSET=utf8; +) ENGINE=MyISAM AUTO_INCREMENT=7314 DEFAULT CHARSET=utf8mb3; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -131,62 +133,58 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `calcms_event_history`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!50503 SET character_set_client = utf8mb4 */; CREATE TABLE `calcms_event_history` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `event_id` int(10) unsigned NOT NULL, + `id` int unsigned NOT NULL AUTO_INCREMENT, + `project_id` int unsigned NOT NULL, + `studio_id` int unsigned DEFAULT NULL, + `series_id` int unsigned DEFAULT NULL, + `event_id` int unsigned NOT NULL, `start` datetime DEFAULT NULL, `end` datetime DEFAULT NULL, `reference` varchar(300) DEFAULT NULL, `title` varchar(200) DEFAULT NULL, `excerpt` longtext, `content` longtext, - `modified_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - `rating` int(11) DEFAULT NULL, + `rating` int DEFAULT NULL, `status` varchar(40) DEFAULT NULL, `visibility` varchar(40) DEFAULT NULL, `responsible` varchar(40) DEFAULT NULL, - `category` varchar(60) DEFAULT NULL, `start_date` date NOT NULL, - `time_of_day` varchar(40) NOT NULL, `end_date` date NOT NULL, `program` varchar(40) DEFAULT NULL, `series_name` varchar(40) DEFAULT NULL, - `comment_count` int(10) unsigned NOT NULL DEFAULT '0', - `category_count` int(10) unsigned NOT NULL DEFAULT '0', - `tag_count` int(10) unsigned NOT NULL DEFAULT '0', + `comment_count` int unsigned NOT NULL DEFAULT '0', + `tag_count` int unsigned NOT NULL DEFAULT '0', `image` varchar(200) DEFAULT NULL, `podcast_url` varchar(300) DEFAULT NULL, `media_url` varchar(300) DEFAULT NULL, `project` varchar(64) DEFAULT NULL, - `recurrence` int(11) NOT NULL DEFAULT '0', + `recurrence` int NOT NULL DEFAULT '0', `location` varchar(100) DEFAULT NULL, `user_title` varchar(200) DEFAULT NULL, `user_excerpt` longtext, `topic` longtext, - `published` tinyint(1) unsigned DEFAULT NULL, - `playout` tinyint(1) unsigned DEFAULT NULL, - `archived` tinyint(1) unsigned DEFAULT NULL, - `episode` int(10) unsigned DEFAULT NULL, - `rerun` int(10) unsigned DEFAULT NULL, - `disable_event_sync` tinyint(1) unsigned DEFAULT NULL, - `live` tinyint(1) unsigned DEFAULT NULL, - `modified_by` varchar(20) DEFAULT NULL, + `published` tinyint unsigned DEFAULT NULL, + `playout` tinyint unsigned DEFAULT NULL, + `archived` tinyint unsigned DEFAULT NULL, + `episode` int unsigned DEFAULT NULL, + `rerun` int unsigned DEFAULT NULL, + `disable_event_sync` tinyint unsigned DEFAULT NULL, + `live` tinyint unsigned DEFAULT NULL, `archive_url` varchar(300) DEFAULT NULL, - `studio_id` int(10) unsigned DEFAULT NULL, - `series_id` int(10) unsigned DEFAULT NULL, - `deleted` tinyint(1) unsigned DEFAULT '0', - `project_id` int(10) unsigned NOT NULL, - `draft` tinyint(3) unsigned NOT NULL DEFAULT '0', + `deleted` tinyint unsigned DEFAULT '0', + `draft` tinyint unsigned NOT NULL DEFAULT '0', + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `modified_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `modified_by` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`), - KEY `end` (`end`), + KEY `project_id` (`project_id`), KEY `start` (`start`), + KEY `end` (`end`), KEY `start_date` (`start_date`), KEY `status` (`status`), KEY `modified_at` (`modified_at`), - KEY `category` (`category`), - KEY `time_of_day` (`time_of_day`), KEY `end_date` (`end_date`), KEY `reference` (`reference`), KEY `series_name` (`series_name`), @@ -199,8 +197,8 @@ CREATE TABLE `calcms_event_history` ( KEY `published` (`published`), KEY `preproduced` (`playout`), KEY `archived` (`archived`), - KEY `project_id` (`project_id`) -) ENGINE=MyISAM AUTO_INCREMENT=24189 DEFAULT CHARSET=utf8; + KEY `draft` (`draft`) +) ENGINE=MyISAM AUTO_INCREMENT=121927 DEFAULT CHARSET=utf8mb3; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -218,60 +216,61 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `calcms_events`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!50503 SET character_set_client = utf8mb4 */; CREATE TABLE `calcms_events` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `id` int unsigned NOT NULL AUTO_INCREMENT, `start` datetime NOT NULL, `end` datetime NOT NULL, - `reference` varchar(300) DEFAULT NULL, + `program` varchar(40) DEFAULT NULL, + `series_name` varchar(40) DEFAULT NULL, `title` varchar(200) DEFAULT NULL, + `episode` int unsigned DEFAULT NULL, `excerpt` longtext, `content` longtext, - `modified_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - `rating` int(11) DEFAULT NULL, + `html_content` longtext, + `rating` int DEFAULT NULL, `status` varchar(40) DEFAULT NULL, `visibility` varchar(40) DEFAULT NULL, `responsible` varchar(40) DEFAULT NULL, - `category` varchar(60) DEFAULT NULL, `start_date` date NOT NULL, - `time_of_day` varchar(40) DEFAULT NULL, `end_date` date NOT NULL, - `html_content` longtext, - `program` varchar(40) DEFAULT NULL, - `series_name` varchar(40) DEFAULT NULL, - `comment_count` int(10) unsigned DEFAULT '0', - `category_count` int(10) unsigned DEFAULT '0', - `tag_count` int(10) unsigned DEFAULT '0', - `image` varchar(200) DEFAULT NULL, + `comment_count` int unsigned DEFAULT '0', + `tag_count` int unsigned DEFAULT '0', `podcast_url` varchar(300) DEFAULT NULL, + `archive_url` varchar(300) DEFAULT NULL, `media_url` varchar(300) DEFAULT NULL, `project` varchar(64) DEFAULT NULL, - `recurrence` int(11) DEFAULT '0', `location` varchar(100) DEFAULT NULL, `user_title` varchar(200) DEFAULT NULL, `user_excerpt` longtext, - `topic` longtext, - `published` tinyint(1) unsigned DEFAULT NULL, - `playout` tinyint(1) unsigned DEFAULT NULL, - `archived` tinyint(1) unsigned DEFAULT NULL, `html_topic` longtext, - `episode` int(10) unsigned DEFAULT NULL, - `rerun` int(10) unsigned DEFAULT NULL, - `disable_event_sync` tinyint(1) unsigned DEFAULT NULL, - `live` tinyint(1) unsigned DEFAULT NULL, + `topic` longtext, + `published` tinyint unsigned DEFAULT NULL, + `playout` tinyint unsigned DEFAULT NULL, + `archived` tinyint unsigned DEFAULT NULL, + `draft` tinyint unsigned NOT NULL DEFAULT '0', + `rerun` int unsigned DEFAULT NULL, + `live` tinyint unsigned DEFAULT NULL, + `recurrence_count` int unsigned NOT NULL DEFAULT '0', + `recurrence` int DEFAULT '0', + `image` varchar(200) DEFAULT NULL, + `image_label` varchar(200) DEFAULT NULL, + `series_image` varchar(200) DEFAULT NULL, + `series_image_label` varchar(200) DEFAULT NULL, + `reference` varchar(300) DEFAULT NULL, + `disable_event_sync` tinyint unsigned DEFAULT NULL, + `content_format` varchar(45) DEFAULT NULL, + `listen_key` varchar(100) DEFAULT NULL, + `upload_status` varchar(45) DEFAULT NULL, + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `modified_by` varchar(20) DEFAULT NULL, - `archive_url` varchar(300) DEFAULT NULL, - `recurrence_count` int(10) unsigned NOT NULL DEFAULT '0', - `draft` tinyint(1) unsigned NOT NULL DEFAULT '0', + `modified_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `end` (`end`), KEY `start` (`start`), KEY `start_date` (`start_date`), KEY `status` (`status`), KEY `modified_at` (`modified_at`), - KEY `category` (`category`), - KEY `time_of_day` (`time_of_day`), KEY `end_date` (`end_date`), KEY `reference` (`reference`), KEY `series_name` (`series_name`), @@ -285,7 +284,7 @@ CREATE TABLE `calcms_events` ( KEY `preproduced` (`playout`), KEY `archived` (`archived`), KEY `draft` (`draft`) -) ENGINE=MyISAM AUTO_INCREMENT=23271 DEFAULT CHARSET=utf8; +) ENGINE=MyISAM AUTO_INCREMENT=56905 DEFAULT CHARSET=utf8mb3; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -303,25 +302,27 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `calcms_images`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!50503 SET character_set_client = utf8mb4 */; CREATE TABLE `calcms_images` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `created_at` datetime DEFAULT CURRENT_TIMESTAMP, - `description` text, - `name` varchar(300) DEFAULT NULL, + `id` int unsigned NOT NULL AUTO_INCREMENT, + `project_id` int unsigned NOT NULL, + `studio_id` int unsigned DEFAULT NULL, `filename` varchar(64) NOT NULL, + `name` varchar(300) DEFAULT NULL, + `description` text, + `licence` varchar(300) DEFAULT NULL, + `public` tinyint unsigned DEFAULT '0', `created_by` varchar(64) DEFAULT NULL, - `studio_id` int(10) unsigned DEFAULT NULL, `modified_by` varchar(64) DEFAULT NULL, + `created_at` datetime DEFAULT CURRENT_TIMESTAMP, `modified_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `project_id` int(10) unsigned NOT NULL, PRIMARY KEY (`id`), + KEY `project_id` (`project_id`), + KEY `studio_id` (`studio_id`), KEY `created_at` (`created_at`), KEY `filename` (`filename`), - KEY `created_by` (`created_by`), - KEY `studio_id` (`studio_id`), - KEY `project_id` (`project_id`) -) ENGINE=MyISAM AUTO_INCREMENT=2141 DEFAULT CHARSET=utf8; + KEY `created_by` (`created_by`) +) ENGINE=MyISAM AUTO_INCREMENT=3150 DEFAULT CHARSET=utf8mb3; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -339,19 +340,19 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `calcms_metas`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!50503 SET character_set_client = utf8mb4 */; CREATE TABLE `calcms_metas` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `id` int unsigned NOT NULL AUTO_INCREMENT, `name` varchar(256) NOT NULL, `value` varchar(256) NOT NULL, `project` varchar(64) DEFAULT NULL, - `event_id` int(10) unsigned NOT NULL, + `event_id` int unsigned NOT NULL, KEY `id` (`id`), KEY `value` (`value`), KEY `project` (`project`), KEY `name` (`name`), KEY `event_id` (`event_id`) -) ENGINE=MyISAM AUTO_INCREMENT=8 DEFAULT CHARSET=utf8; +) ENGINE=MyISAM AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb3; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -363,16 +364,42 @@ LOCK TABLES `calcms_metas` WRITE; /*!40000 ALTER TABLE `calcms_metas` ENABLE KEYS */; UNLOCK TABLES; +-- +-- Table structure for table `calcms_password_requests` +-- + +DROP TABLE IF EXISTS `calcms_password_requests`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `calcms_password_requests` ( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `user` varchar(100) NOT NULL, + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `token` varchar(200) NOT NULL, + `max_attempts` int unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`id`) +) ENGINE=MyISAM AUTO_INCREMENT=168 DEFAULT CHARSET=utf8mb3; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `calcms_password_requests` +-- + +LOCK TABLES `calcms_password_requests` WRITE; +/*!40000 ALTER TABLE `calcms_password_requests` DISABLE KEYS */; +/*!40000 ALTER TABLE `calcms_password_requests` ENABLE KEYS */; +UNLOCK TABLES; + -- -- Table structure for table `calcms_playout` -- DROP TABLE IF EXISTS `calcms_playout`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!50503 SET character_set_client = utf8mb4 */; CREATE TABLE `calcms_playout` ( - `project_id` int(11) NOT NULL, - `studio_id` int(11) NOT NULL, + `project_id` int NOT NULL, + `studio_id` int NOT NULL, `start` datetime NOT NULL, `end` datetime NOT NULL, `duration` float unsigned NOT NULL, @@ -380,10 +407,10 @@ CREATE TABLE `calcms_playout` ( `end_date` date NOT NULL, `file` varchar(300) NOT NULL, `errors` varchar(500) DEFAULT NULL, - `channels` int(11) DEFAULT NULL, - `bitrate` int(11) DEFAULT NULL, - `stream_size` int(11) DEFAULT NULL, - `sampling_rate` int(11) DEFAULT NULL, + `channels` int DEFAULT NULL, + `bitrate` int DEFAULT NULL, + `stream_size` int DEFAULT NULL, + `sampling_rate` int DEFAULT NULL, `bitrate_mode` varchar(10) DEFAULT NULL, `format` varchar(10) DEFAULT NULL, `format_version` varchar(30) DEFAULT NULL, @@ -395,7 +422,7 @@ CREATE TABLE `calcms_playout` ( `rms_image` varchar(300) DEFAULT NULL, `replay_gain` float DEFAULT NULL, `updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, - `modified_at` datetime NOT NULL, + `modified_at` datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`project_id`,`studio_id`,`start`), KEY `project_id` (`project_id`), KEY `studio_id` (`studio_id`), @@ -404,7 +431,7 @@ CREATE TABLE `calcms_playout` ( KEY `start_date` (`start_date`), KEY `end_date` (`end_date`), KEY `modified_at` (`modified_at`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb3; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -422,11 +449,11 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `calcms_project_series`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!50503 SET character_set_client = utf8mb4 */; CREATE TABLE `calcms_project_series` ( - `project_id` int(10) unsigned NOT NULL, - `studio_id` int(10) unsigned NOT NULL, - `series_id` int(10) unsigned NOT NULL, + `project_id` int unsigned NOT NULL, + `studio_id` int unsigned NOT NULL, + `series_id` int unsigned NOT NULL, PRIMARY KEY (`project_id`,`studio_id`,`series_id`), KEY `project_id` (`project_id`), KEY `studio_id` (`studio_id`), @@ -440,7 +467,8 @@ CREATE TABLE `calcms_project_series` ( LOCK TABLES `calcms_project_series` WRITE; /*!40000 ALTER TABLE `calcms_project_series` DISABLE KEYS */; -INSERT INTO `calcms_project_series` VALUES (1,1,223); +INSERT INTO `calcms_project_series` (`project_id`, `studio_id`, `series_id`) VALUES (1,1,1); +INSERT INTO `calcms_project_series` (`project_id`, `studio_id`, `series_id`) VALUES (1,1,1223); /*!40000 ALTER TABLE `calcms_project_series` ENABLE KEYS */; UNLOCK TABLES; @@ -450,14 +478,14 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `calcms_project_studios`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!50503 SET character_set_client = utf8mb4 */; CREATE TABLE `calcms_project_studios` ( - `project_id` int(10) unsigned NOT NULL, - `studio_id` int(10) unsigned NOT NULL, + `project_id` int unsigned NOT NULL, + `studio_id` int unsigned NOT NULL, PRIMARY KEY (`project_id`,`studio_id`), KEY `project_id` (`project_id`), KEY `studio_id` (`studio_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb3; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -466,7 +494,7 @@ CREATE TABLE `calcms_project_studios` ( LOCK TABLES `calcms_project_studios` WRITE; /*!40000 ALTER TABLE `calcms_project_studios` DISABLE KEYS */; -INSERT INTO `calcms_project_studios` VALUES (1,1); +INSERT INTO `calcms_project_studios` (`project_id`, `studio_id`) VALUES (1,1); /*!40000 ALTER TABLE `calcms_project_studios` ENABLE KEYS */; UNLOCK TABLES; @@ -476,9 +504,9 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `calcms_projects`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!50503 SET character_set_client = utf8mb4 */; CREATE TABLE `calcms_projects` ( - `project_id` int(11) NOT NULL AUTO_INCREMENT, + `project_id` int NOT NULL AUTO_INCREMENT, `name` varchar(32) NOT NULL, `title` varchar(100) DEFAULT NULL, `start_date` date NOT NULL, @@ -488,7 +516,7 @@ CREATE TABLE `calcms_projects` ( `email` varchar(100) DEFAULT NULL, PRIMARY KEY (`project_id`), KEY `name` (`name`) -) ENGINE=MyISAM AUTO_INCREMENT=89 DEFAULT CHARSET=utf8; +) ENGINE=MyISAM AUTO_INCREMENT=101 DEFAULT CHARSET=utf8mb3; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -497,6 +525,7 @@ CREATE TABLE `calcms_projects` ( LOCK TABLES `calcms_projects` WRITE; /*!40000 ALTER TABLE `calcms_projects` DISABLE KEYS */; +INSERT INTO `calcms_projects` (`project_id`, `name`, `title`, `start_date`, `end_date`, `subtitle`, `image`, `email`) VALUES (1,'my-project','My Project','2010-05-01','2023-12-31','This is my project','','info@my-radio.org'); /*!40000 ALTER TABLE `calcms_projects` ENABLE KEYS */; UNLOCK TABLES; @@ -506,96 +535,97 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `calcms_roles`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!50503 SET character_set_client = utf8mb4 */; CREATE TABLE `calcms_roles` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `id` int unsigned NOT NULL AUTO_INCREMENT, + `project_id` tinyint unsigned NOT NULL, + `studio_id` int unsigned NOT NULL, `role` varchar(40) NOT NULL, - `create_user` tinyint(1) unsigned DEFAULT NULL, - `read_user` tinyint(1) unsigned DEFAULT NULL, - `update_user` tinyint(1) unsigned DEFAULT NULL, - `disable_user` tinyint(1) unsigned DEFAULT NULL, - `update_studio` tinyint(1) unsigned DEFAULT NULL, - `update_user_role` tinyint(1) unsigned DEFAULT NULL, - `read_user_role` tinyint(1) unsigned DEFAULT NULL, - `create_series` tinyint(1) unsigned DEFAULT NULL, - `read_series` tinyint(1) unsigned DEFAULT NULL, - `update_series` tinyint(1) unsigned DEFAULT NULL, - `delete_series` tinyint(1) unsigned DEFAULT NULL, - `create_event` tinyint(1) unsigned DEFAULT NULL, - `read_event` tinyint(1) unsigned DEFAULT NULL, - `delete_event` tinyint(1) unsigned DEFAULT NULL, - `level` tinyint(3) unsigned NOT NULL DEFAULT '0', - `read_role` tinyint(1) unsigned DEFAULT NULL, - `update_role` tinyint(1) unsigned DEFAULT NULL, - `delete_user` tinyint(1) unsigned DEFAULT NULL, + `level` tinyint unsigned NOT NULL DEFAULT '0', `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `modified_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `update_event_of_series` tinyint(1) unsigned DEFAULT NULL, - `update_event_of_others` tinyint(1) unsigned DEFAULT NULL, - `studio_id` int(10) unsigned NOT NULL, - `update_event_time` tinyint(1) unsigned DEFAULT NULL, - `create_download` tinyint(1) unsigned NOT NULL, - `update_event_status_archived` tinyint(1) unsigned NOT NULL, - `update_event_status_playout` tinyint(1) unsigned NOT NULL, - `read_schedule` tinyint(1) unsigned NOT NULL, - `update_schedule` tinyint(1) unsigned NOT NULL, - `delete_schedule` tinyint(1) unsigned NOT NULL, - `update_series_template` tinyint(1) unsigned NOT NULL, - `assign_series_member` tinyint(1) unsigned NOT NULL, - `remove_series_member` tinyint(1) unsigned NOT NULL, - `update_event_field_content` tinyint(1) unsigned NOT NULL, - `update_event_status_disable_event_sync` tinyint(1) unsigned NOT NULL, - `update_event_status_published` tinyint(1) unsigned NOT NULL, - `update_event_field_episode` tinyint(1) unsigned NOT NULL, - `update_event_status_rerun` tinyint(1) unsigned NOT NULL, - `create_event_from_schedule` tinyint(1) unsigned NOT NULL, - `read_image` tinyint(1) unsigned NOT NULL, - `update_image_own` tinyint(1) unsigned NOT NULL, - `delete_image_own` tinyint(1) unsigned NOT NULL, - `update_image_others` tinyint(1) unsigned NOT NULL, - `delete_image_others` tinyint(1) unsigned NOT NULL, - `create_image` tinyint(1) unsigned NOT NULL, - `scan_series_events` tinyint(1) unsigned NOT NULL, - `read_studio` tinyint(1) unsigned NOT NULL, - `read_studio_timeslot_schedule` tinyint(1) unsigned NOT NULL, - `update_studio_timeslot_schedule` tinyint(1) unsigned NOT NULL, - `update_event_status_live` tinyint(1) unsigned NOT NULL, - `update_event_field_topic` tinyint(1) unsigned NOT NULL, - `update_event_field_excerpt_extension` tinyint(1) unsigned NOT NULL, - `update_event_field_title_extension` tinyint(1) unsigned NOT NULL, - `update_event_field_title` tinyint(1) unsigned NOT NULL, - `update_event_field_excerpt` tinyint(1) unsigned NOT NULL, - `update_event_field_description` tinyint(1) unsigned NOT NULL, - `update_event_field_image` tinyint(1) unsigned NOT NULL, - `assign_series_events` tinyint(1) unsigned NOT NULL, - `update_event_field_podcast_url` tinyint(1) unsigned NOT NULL, - `update_event_field_archive_url` tinyint(1) unsigned NOT NULL, - `read_changes` tinyint(1) unsigned NOT NULL, - `undo_changes` tinyint(1) unsigned NOT NULL, - `project_id` tinyint(1) unsigned NOT NULL, - `create_studio` tinyint(1) unsigned NOT NULL, - `delete_studio` tinyint(1) unsigned NOT NULL, - `create_project` tinyint(1) unsigned NOT NULL, - `delete_project` tinyint(1) unsigned NOT NULL, - `update_project` tinyint(1) unsigned NOT NULL, - `assign_project_studio` tinyint(1) unsigned NOT NULL, - `read_project` tinyint(1) unsigned NOT NULL, - `read_user_stats` tinyint(1) unsigned NOT NULL, - `update_event_after_week` tinyint(1) unsigned NOT NULL, - `create_event_of_series` tinyint(1) unsigned NOT NULL, - `read_comment` tinyint(1) unsigned NOT NULL, - `update_comment_status_lock` tinyint(1) unsigned NOT NULL, - `update_comment_status_read` tinyint(1) unsigned NOT NULL, - `upload_audio_recordings` tinyint(1) unsigned NOT NULL, - `delete_audio_recordings` tinyint(1) unsigned NOT NULL, - `read_playout` tinyint(1) unsigned NOT NULL, - `update_event_status_draft` tinyint(1) unsigned NOT NULL, + `read_role` tinyint unsigned DEFAULT NULL, + `update_role` tinyint unsigned DEFAULT NULL, + `read_user_role` tinyint unsigned DEFAULT NULL, + `create_user` tinyint unsigned DEFAULT NULL, + `read_user` tinyint unsigned DEFAULT NULL, + `update_user` tinyint unsigned DEFAULT NULL, + `delete_user` tinyint unsigned DEFAULT NULL, + `update_user_role` tinyint unsigned DEFAULT NULL, + `disable_user` tinyint unsigned DEFAULT NULL, + `create_project` tinyint unsigned NOT NULL, + `read_project` tinyint unsigned NOT NULL, + `update_project` tinyint unsigned NOT NULL, + `delete_project` tinyint unsigned NOT NULL, + `assign_project_studio` tinyint unsigned NOT NULL, + `create_studio` tinyint unsigned NOT NULL, + `read_studio` tinyint unsigned NOT NULL, + `update_studio` tinyint unsigned DEFAULT NULL, + `delete_studio` tinyint unsigned NOT NULL, + `read_studio_timeslot_schedule` tinyint unsigned NOT NULL, + `update_studio_timeslot_schedule` tinyint unsigned NOT NULL, + `create_series` tinyint unsigned DEFAULT NULL, + `read_series` tinyint unsigned DEFAULT NULL, + `update_series` tinyint unsigned DEFAULT NULL, + `delete_series` tinyint unsigned DEFAULT NULL, + `update_series_template` tinyint unsigned NOT NULL, + `assign_series_member` tinyint unsigned NOT NULL, + `remove_series_member` tinyint unsigned NOT NULL, + `scan_series_events` tinyint unsigned NOT NULL, + `assign_series_events` tinyint unsigned NOT NULL, + `read_schedule` tinyint unsigned NOT NULL, + `update_schedule` tinyint unsigned NOT NULL, + `delete_schedule` tinyint unsigned NOT NULL, + `create_event` tinyint unsigned DEFAULT NULL, + `create_event_from_schedule` tinyint unsigned NOT NULL, + `create_event_of_series` tinyint unsigned NOT NULL, + `read_event` tinyint unsigned DEFAULT NULL, + `delete_event` tinyint unsigned DEFAULT NULL, + `update_event_of_series` tinyint unsigned DEFAULT NULL, + `update_event_of_others` tinyint unsigned DEFAULT NULL, + `update_event_time` tinyint unsigned DEFAULT NULL, + `update_event_after_week` tinyint unsigned NOT NULL, + `update_event_field_title` tinyint unsigned NOT NULL, + `update_event_field_title_extension` tinyint unsigned NOT NULL, + `update_event_field_excerpt` tinyint unsigned NOT NULL, + `update_event_field_content` tinyint unsigned NOT NULL, + `update_event_field_content_format` tinyint unsigned NOT NULL, + `update_event_field_description` tinyint unsigned NOT NULL, + `update_event_field_topic` tinyint unsigned NOT NULL, + `update_event_field_episode` tinyint unsigned NOT NULL, + `update_event_field_excerpt_extension` tinyint unsigned NOT NULL, + `update_event_field_image` tinyint unsigned NOT NULL, + `update_event_field_podcast_url` tinyint unsigned NOT NULL, + `update_event_field_archive_url` tinyint unsigned NOT NULL, + `update_event_status_disable_event_sync` tinyint unsigned NOT NULL, + `update_event_status_published` tinyint unsigned NOT NULL, + `update_event_status_rerun` tinyint unsigned NOT NULL, + `update_event_status_draft` tinyint unsigned NOT NULL, + `update_event_status_live` tinyint unsigned NOT NULL, + `update_event_status_playout` tinyint unsigned NOT NULL, + `update_event_status_archived` tinyint unsigned NOT NULL, + `create_image` tinyint unsigned NOT NULL, + `update_image_own` tinyint unsigned NOT NULL, + `read_image` tinyint unsigned NOT NULL, + `delete_image_own` tinyint unsigned NOT NULL, + `update_image_others` tinyint unsigned NOT NULL, + `delete_image_others` tinyint unsigned NOT NULL, + `read_changes` tinyint unsigned NOT NULL, + `undo_changes` tinyint unsigned NOT NULL, + `read_user_stats` tinyint unsigned NOT NULL, + `read_comment` tinyint unsigned NOT NULL, + `update_comment_status_lock` tinyint unsigned NOT NULL, + `update_comment_status_read` tinyint unsigned NOT NULL, + `upload_audio_recordings` tinyint unsigned NOT NULL, + `delete_audio_recordings` tinyint unsigned NOT NULL, + `read_playout` tinyint unsigned NOT NULL, + `create_download` tinyint unsigned NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `role_2` (`role`), + KEY `project_id` (`project_id`), KEY `studio_id` (`studio_id`), - KEY `role` (`role`), - KEY `project_id` (`project_id`) -) ENGINE=MyISAM AUTO_INCREMENT=40 DEFAULT CHARSET=utf8; + KEY `role` (`role`) +) ENGINE=MyISAM AUTO_INCREMENT=97 DEFAULT CHARSET=utf8mb3; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -604,7 +634,12 @@ CREATE TABLE `calcms_roles` ( LOCK TABLES `calcms_roles` WRITE; /*!40000 ALTER TABLE `calcms_roles` DISABLE KEYS */; -INSERT INTO `calcms_roles` VALUES (7,'Admin',1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,1,1,'0000-00-00 00:00:00','2017-07-30 14:32:32',1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1);/*!40000 ALTER TABLE `calcms_roles` ENABLE KEYS */; +INSERT INTO `calcms_roles` (`id`, `project_id`, `studio_id`, `role`, `level`, `created_at`, `modified_at`, `read_role`, `update_role`, `read_user_role`, `create_user`, `read_user`, `update_user`, `delete_user`, `update_user_role`, `disable_user`, `create_project`, `read_project`, `update_project`, `delete_project`, `assign_project_studio`, `create_studio`, `read_studio`, `update_studio`, `delete_studio`, `read_studio_timeslot_schedule`, `update_studio_timeslot_schedule`, `create_series`, `read_series`, `update_series`, `delete_series`, `update_series_template`, `assign_series_member`, `remove_series_member`, `scan_series_events`, `assign_series_events`, `read_schedule`, `update_schedule`, `delete_schedule`, `create_event`, `create_event_from_schedule`, `create_event_of_series`, `read_event`, `delete_event`, `update_event_of_series`, `update_event_of_others`, `update_event_time`, `update_event_after_week`, `update_event_field_title`, `update_event_field_title_extension`, `update_event_field_excerpt`, `update_event_field_content`, `update_event_field_content_format`, `update_event_field_description`, `update_event_field_topic`, `update_event_field_episode`, `update_event_field_excerpt_extension`, `update_event_field_image`, `update_event_field_podcast_url`, `update_event_field_archive_url`, `update_event_status_disable_event_sync`, `update_event_status_published`, `update_event_status_rerun`, `update_event_status_draft`, `update_event_status_live`, `update_event_status_playout`, `update_event_status_archived`, `create_image`, `update_image_own`, `read_image`, `delete_image_own`, `update_image_others`, `delete_image_others`, `read_changes`, `undo_changes`, `read_user_stats`, `read_comment`, `update_comment_status_lock`, `update_comment_status_read`, `upload_audio_recordings`, `delete_audio_recordings`, `read_playout`, `create_download`) VALUES (7,1,1,'Admin',7,NULL,'2023-02-19 21:32:32',1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1); +INSERT INTO `calcms_roles` (`id`, `project_id`, `studio_id`, `role`, `level`, `created_at`, `modified_at`, `read_role`, `update_role`, `read_user_role`, `create_user`, `read_user`, `update_user`, `delete_user`, `update_user_role`, `disable_user`, `create_project`, `read_project`, `update_project`, `delete_project`, `assign_project_studio`, `create_studio`, `read_studio`, `update_studio`, `delete_studio`, `read_studio_timeslot_schedule`, `update_studio_timeslot_schedule`, `create_series`, `read_series`, `update_series`, `delete_series`, `update_series_template`, `assign_series_member`, `remove_series_member`, `scan_series_events`, `assign_series_events`, `read_schedule`, `update_schedule`, `delete_schedule`, `create_event`, `create_event_from_schedule`, `create_event_of_series`, `read_event`, `delete_event`, `update_event_of_series`, `update_event_of_others`, `update_event_time`, `update_event_after_week`, `update_event_field_title`, `update_event_field_title_extension`, `update_event_field_excerpt`, `update_event_field_content`, `update_event_field_content_format`, `update_event_field_description`, `update_event_field_topic`, `update_event_field_episode`, `update_event_field_excerpt_extension`, `update_event_field_image`, `update_event_field_podcast_url`, `update_event_field_archive_url`, `update_event_status_disable_event_sync`, `update_event_status_published`, `update_event_status_rerun`, `update_event_status_draft`, `update_event_status_live`, `update_event_status_playout`, `update_event_status_archived`, `create_image`, `update_image_own`, `read_image`, `delete_image_own`, `update_image_others`, `delete_image_others`, `read_changes`, `undo_changes`, `read_user_stats`, `read_comment`, `update_comment_status_lock`, `update_comment_status_read`, `upload_audio_recordings`, `delete_audio_recordings`, `read_playout`, `create_download`) VALUES (3,1,1,'Studio Manager',6,NULL,'2023-02-19 21:32:32',1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,0,1,1,0,0,1,1,1,1); +INSERT INTO `calcms_roles` (`id`, `project_id`, `studio_id`, `role`, `level`, `created_at`, `modified_at`, `read_role`, `update_role`, `read_user_role`, `create_user`, `read_user`, `update_user`, `delete_user`, `update_user_role`, `disable_user`, `create_project`, `read_project`, `update_project`, `delete_project`, `assign_project_studio`, `create_studio`, `read_studio`, `update_studio`, `delete_studio`, `read_studio_timeslot_schedule`, `update_studio_timeslot_schedule`, `create_series`, `read_series`, `update_series`, `delete_series`, `update_series_template`, `assign_series_member`, `remove_series_member`, `scan_series_events`, `assign_series_events`, `read_schedule`, `update_schedule`, `delete_schedule`, `create_event`, `create_event_from_schedule`, `create_event_of_series`, `read_event`, `delete_event`, `update_event_of_series`, `update_event_of_others`, `update_event_time`, `update_event_after_week`, `update_event_field_title`, `update_event_field_title_extension`, `update_event_field_excerpt`, `update_event_field_content`, `update_event_field_content_format`, `update_event_field_description`, `update_event_field_topic`, `update_event_field_episode`, `update_event_field_excerpt_extension`, `update_event_field_image`, `update_event_field_podcast_url`, `update_event_field_archive_url`, `update_event_status_disable_event_sync`, `update_event_status_published`, `update_event_status_rerun`, `update_event_status_draft`, `update_event_status_live`, `update_event_status_playout`, `update_event_status_archived`, `create_image`, `update_image_own`, `read_image`, `delete_image_own`, `update_image_others`, `delete_image_others`, `read_changes`, `undo_changes`, `read_user_stats`, `read_comment`, `update_comment_status_lock`, `update_comment_status_read`, `upload_audio_recordings`, `delete_audio_recordings`, `read_playout`, `create_download`) VALUES (1,1,1,'Program Planing',4,NULL,'2023-02-19 21:32:32',1,0,1,1,1,1,0,1,0,0,0,0,0,0,0,1,0,0,1,0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,1); +INSERT INTO `calcms_roles` (`id`, `project_id`, `studio_id`, `role`, `level`, `created_at`, `modified_at`, `read_role`, `update_role`, `read_user_role`, `create_user`, `read_user`, `update_user`, `delete_user`, `update_user_role`, `disable_user`, `create_project`, `read_project`, `update_project`, `delete_project`, `assign_project_studio`, `create_studio`, `read_studio`, `update_studio`, `delete_studio`, `read_studio_timeslot_schedule`, `update_studio_timeslot_schedule`, `create_series`, `read_series`, `update_series`, `delete_series`, `update_series_template`, `assign_series_member`, `remove_series_member`, `scan_series_events`, `assign_series_events`, `read_schedule`, `update_schedule`, `delete_schedule`, `create_event`, `create_event_from_schedule`, `create_event_of_series`, `read_event`, `delete_event`, `update_event_of_series`, `update_event_of_others`, `update_event_time`, `update_event_after_week`, `update_event_field_title`, `update_event_field_title_extension`, `update_event_field_excerpt`, `update_event_field_content`, `update_event_field_content_format`, `update_event_field_description`, `update_event_field_topic`, `update_event_field_episode`, `update_event_field_excerpt_extension`, `update_event_field_image`, `update_event_field_podcast_url`, `update_event_field_archive_url`, `update_event_status_disable_event_sync`, `update_event_status_published`, `update_event_status_rerun`, `update_event_status_draft`, `update_event_status_live`, `update_event_status_playout`, `update_event_status_archived`, `create_image`, `update_image_own`, `read_image`, `delete_image_own`, `update_image_others`, `delete_image_others`, `read_changes`, `undo_changes`, `read_user_stats`, `read_comment`, `update_comment_status_lock`, `update_comment_status_read`, `upload_audio_recordings`, `delete_audio_recordings`, `read_playout`, `create_download`) VALUES (2,1,1,'Editorial',2,NULL,'2023-02-19 21:32:32',0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,1,0,0,0,0,1,0,1,0,0,1,0,1,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,1,1); +INSERT INTO `calcms_roles` (`id`, `project_id`, `studio_id`, `role`, `level`, `created_at`, `modified_at`, `read_role`, `update_role`, `read_user_role`, `create_user`, `read_user`, `update_user`, `delete_user`, `update_user_role`, `disable_user`, `create_project`, `read_project`, `update_project`, `delete_project`, `assign_project_studio`, `create_studio`, `read_studio`, `update_studio`, `delete_studio`, `read_studio_timeslot_schedule`, `update_studio_timeslot_schedule`, `create_series`, `read_series`, `update_series`, `delete_series`, `update_series_template`, `assign_series_member`, `remove_series_member`, `scan_series_events`, `assign_series_events`, `read_schedule`, `update_schedule`, `delete_schedule`, `create_event`, `create_event_from_schedule`, `create_event_of_series`, `read_event`, `delete_event`, `update_event_of_series`, `update_event_of_others`, `update_event_time`, `update_event_after_week`, `update_event_field_title`, `update_event_field_title_extension`, `update_event_field_excerpt`, `update_event_field_content`, `update_event_field_content_format`, `update_event_field_description`, `update_event_field_topic`, `update_event_field_episode`, `update_event_field_excerpt_extension`, `update_event_field_image`, `update_event_field_podcast_url`, `update_event_field_archive_url`, `update_event_status_disable_event_sync`, `update_event_status_published`, `update_event_status_rerun`, `update_event_status_draft`, `update_event_status_live`, `update_event_status_playout`, `update_event_status_archived`, `create_image`, `update_image_own`, `read_image`, `delete_image_own`, `update_image_others`, `delete_image_others`, `read_changes`, `undo_changes`, `read_user_stats`, `read_comment`, `update_comment_status_lock`, `update_comment_status_read`, `upload_audio_recordings`, `delete_audio_recordings`, `read_playout`, `create_download`) VALUES (25,1,1,'Guest',1,NULL,'2023-02-19 21:32:32',0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +/*!40000 ALTER TABLE `calcms_roles` ENABLE KEYS */; UNLOCK TABLES; -- @@ -613,9 +648,9 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `calcms_series`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!50503 SET character_set_client = utf8mb4 */; CREATE TABLE `calcms_series` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `id` int unsigned NOT NULL AUTO_INCREMENT, `series_name` varchar(100) DEFAULT NULL, `title` varchar(100) DEFAULT NULL, `excerpt` longtext, @@ -632,16 +667,18 @@ CREATE TABLE `calcms_series` ( `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `assign_event_series_name` varchar(100) DEFAULT NULL, `assign_event_title` varchar(100) DEFAULT NULL, - `default_duration` int(10) unsigned DEFAULT NULL, + `default_duration` int unsigned DEFAULT NULL, `comment` longtext, - `live` tinyint(1) unsigned DEFAULT NULL, + `live` tinyint unsigned DEFAULT NULL, `archive_url` varchar(300) DEFAULT NULL, `podcast_url` varchar(300) DEFAULT NULL, - `count_episodes` tinyint(1) unsigned DEFAULT '1', - `has_single_events` tinyint(1) unsigned DEFAULT '0', + `count_episodes` tinyint unsigned DEFAULT '1', + `has_single_events` tinyint unsigned DEFAULT '0', + `predecessor_id` int DEFAULT NULL, + `content_format` varchar(45) DEFAULT NULL, PRIMARY KEY (`id`), KEY `location` (`location`) -) ENGINE=MyISAM AUTO_INCREMENT=224 DEFAULT CHARSET=utf8; +) ENGINE=MyISAM AUTO_INCREMENT=1224 DEFAULT CHARSET=utf8mb3; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -650,7 +687,8 @@ CREATE TABLE `calcms_series` ( LOCK TABLES `calcms_series` WRITE; /*!40000 ALTER TABLE `calcms_series` DISABLE KEYS */; -INSERT INTO `calcms_series` VALUES (223,'_single_',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'2016-05-16 13:54:02','',NULL,'2016-05-16 13:54:02',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,1); +INSERT INTO `calcms_series` (`id`, `series_name`, `title`, `excerpt`, `content`, `html_content`, `topic`, `program`, `image`, `project`, `location`, `modified_at`, `modified_by`, `category`, `created_at`, `assign_event_series_name`, `assign_event_title`, `default_duration`, `comment`, `live`, `archive_url`, `podcast_url`, `count_episodes`, `has_single_events`, `predecessor_id`, `content_format`) VALUES (1,'Night Train','Is Coming','','','\n','','','p5skauKk_DoI_lsrsBfxiw.jpg',NULL,NULL,'2023-02-19 21:33:05','ccAdmin',NULL,NULL,'Berliner Runde','Hauptstadtteam',60,'',0,'','',0,0,0,'markdown'); +INSERT INTO `calcms_series` (`id`, `series_name`, `title`, `excerpt`, `content`, `html_content`, `topic`, `program`, `image`, `project`, `location`, `modified_at`, `modified_by`, `category`, `created_at`, `assign_event_series_name`, `assign_event_title`, `default_duration`, `comment`, `live`, `archive_url`, `podcast_url`, `count_episodes`, `has_single_events`, `predecessor_id`, `content_format`) VALUES (1223,'_single_',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'2023-02-19 21:17:18','ccAdmin',NULL,'2023-02-19 21:17:18',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,1,NULL,NULL); /*!40000 ALTER TABLE `calcms_series` ENABLE KEYS */; UNLOCK TABLES; @@ -660,27 +698,27 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `calcms_series_dates`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!50503 SET character_set_client = utf8mb4 */; CREATE TABLE `calcms_series_dates` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `series_id` int(10) unsigned NOT NULL, + `id` int unsigned NOT NULL AUTO_INCREMENT, + `project_id` int unsigned NOT NULL, + `studio_id` int unsigned NOT NULL, + `series_id` int unsigned NOT NULL, `start` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', `end` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', - `studio_id` int(10) unsigned NOT NULL, `start_date` date NOT NULL, `end_date` date NOT NULL, `exclude` tinyint(1) NOT NULL DEFAULT '0', - `project_id` int(10) unsigned NOT NULL, - `series_schedule_id` int(10) unsigned NOT NULL, + `series_schedule_id` int unsigned NOT NULL, PRIMARY KEY (`id`), - KEY `series_id` (`series_id`), + KEY `project_id` (`project_id`), KEY `studio_id` (`studio_id`), + KEY `series_id` (`series_id`), KEY `start` (`start`) USING BTREE, KEY `end` (`end`) USING BTREE, KEY `start_date` (`start_date`), - KEY `end_date` (`end_date`), - KEY `project_id` (`project_id`) -) ENGINE=MyISAM AUTO_INCREMENT=17361 DEFAULT CHARSET=utf8; + KEY `end_date` (`end_date`) +) ENGINE=MyISAM AUTO_INCREMENT=614255 DEFAULT CHARSET=utf8mb3; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -689,6 +727,59 @@ CREATE TABLE `calcms_series_dates` ( LOCK TABLES `calcms_series_dates` WRITE; /*!40000 ALTER TABLE `calcms_series_dates` DISABLE KEYS */; +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614202,1,1,1,'2023-11-15 11:00:00','2023-11-15 12:00:00','2023-11-15','2023-11-15',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614203,1,1,1,'2023-04-12 10:00:00','2023-04-12 11:00:00','2023-04-12','2023-04-12',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614204,1,1,1,'2023-07-12 10:00:00','2023-07-12 11:00:00','2023-07-12','2023-07-12',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614205,1,1,1,'2023-02-08 11:00:00','2023-02-08 12:00:00','2023-02-08','2023-02-08',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614206,1,1,1,'2023-06-07 10:00:00','2023-06-07 11:00:00','2023-06-07','2023-06-07',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614207,1,1,1,'2023-03-29 10:00:00','2023-03-29 11:00:00','2023-03-29','2023-03-29',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614208,1,1,1,'2023-12-06 11:00:00','2023-12-06 12:00:00','2023-12-06','2023-12-06',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614209,1,1,1,'2023-09-20 10:00:00','2023-09-20 11:00:00','2023-09-20','2023-09-20',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614210,1,1,1,'2024-01-31 11:00:00','2024-01-31 12:00:00','2024-01-31','2024-01-31',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614211,1,1,1,'2023-05-03 10:00:00','2023-05-03 11:00:00','2023-05-03','2023-05-03',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614212,1,1,1,'2023-02-22 11:00:00','2023-02-22 12:00:00','2023-02-22','2023-02-22',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614213,1,1,1,'2023-09-27 10:00:00','2023-09-27 11:00:00','2023-09-27','2023-09-27',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614214,1,1,1,'2023-11-22 11:00:00','2023-11-22 12:00:00','2023-11-22','2023-11-22',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614215,1,1,1,'2023-09-13 10:00:00','2023-09-13 11:00:00','2023-09-13','2023-09-13',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614216,1,1,1,'2023-10-11 10:00:00','2023-10-11 11:00:00','2023-10-11','2023-10-11',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614217,1,1,1,'2023-08-02 10:00:00','2023-08-02 11:00:00','2023-08-02','2023-08-02',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614218,1,1,1,'2023-08-23 10:00:00','2023-08-23 11:00:00','2023-08-23','2023-08-23',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614219,1,1,1,'2023-06-21 10:00:00','2023-06-21 11:00:00','2023-06-21','2023-06-21',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614220,1,1,1,'2024-01-24 11:00:00','2024-01-24 12:00:00','2024-01-24','2024-01-24',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614221,1,1,1,'2023-05-10 10:00:00','2023-05-10 11:00:00','2023-05-10','2023-05-10',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614222,1,1,1,'2023-02-15 11:00:00','2023-02-15 12:00:00','2023-02-15','2023-02-15',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614223,1,1,1,'2023-03-01 11:00:00','2023-03-01 12:00:00','2023-03-01','2023-03-01',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614224,1,1,1,'2023-11-08 11:00:00','2023-11-08 12:00:00','2023-11-08','2023-11-08',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614225,1,1,1,'2023-05-17 10:00:00','2023-05-17 11:00:00','2023-05-17','2023-05-17',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614226,1,1,1,'2023-07-05 10:00:00','2023-07-05 11:00:00','2023-07-05','2023-07-05',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614227,1,1,1,'2023-04-05 10:00:00','2023-04-05 11:00:00','2023-04-05','2023-04-05',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614228,1,1,1,'2023-07-19 10:00:00','2023-07-19 11:00:00','2023-07-19','2023-07-19',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614229,1,1,1,'2023-04-19 10:00:00','2023-04-19 11:00:00','2023-04-19','2023-04-19',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614230,1,1,1,'2023-08-30 10:00:00','2023-08-30 11:00:00','2023-08-30','2023-08-30',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614231,1,1,1,'2023-10-18 10:00:00','2023-10-18 11:00:00','2023-10-18','2023-10-18',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614232,1,1,1,'2023-03-22 11:00:00','2023-03-22 12:00:00','2023-03-22','2023-03-22',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614233,1,1,1,'2023-12-27 11:00:00','2023-12-27 12:00:00','2023-12-27','2023-12-27',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614234,1,1,1,'2023-06-14 10:00:00','2023-06-14 11:00:00','2023-06-14','2023-06-14',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614235,1,1,1,'2023-08-16 10:00:00','2023-08-16 11:00:00','2023-08-16','2023-08-16',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614236,1,1,1,'2023-03-08 11:00:00','2023-03-08 12:00:00','2023-03-08','2023-03-08',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614237,1,1,1,'2024-01-03 11:00:00','2024-01-03 12:00:00','2024-01-03','2024-01-03',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614238,1,1,1,'2023-05-31 10:00:00','2023-05-31 11:00:00','2023-05-31','2023-05-31',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614239,1,1,1,'2023-11-01 11:00:00','2023-11-01 12:00:00','2023-11-01','2023-11-01',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614240,1,1,1,'2023-09-06 10:00:00','2023-09-06 11:00:00','2023-09-06','2023-09-06',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614241,1,1,1,'2023-12-20 11:00:00','2023-12-20 12:00:00','2023-12-20','2023-12-20',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614242,1,1,1,'2023-06-28 10:00:00','2023-06-28 11:00:00','2023-06-28','2023-06-28',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614243,1,1,1,'2023-10-04 10:00:00','2023-10-04 11:00:00','2023-10-04','2023-10-04',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614244,1,1,1,'2023-11-29 11:00:00','2023-11-29 12:00:00','2023-11-29','2023-11-29',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614245,1,1,1,'2023-08-09 10:00:00','2023-08-09 11:00:00','2023-08-09','2023-08-09',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614246,1,1,1,'2023-10-25 10:00:00','2023-10-25 11:00:00','2023-10-25','2023-10-25',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614247,1,1,1,'2023-02-01 11:00:00','2023-02-01 12:00:00','2023-02-01','2023-02-01',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614248,1,1,1,'2023-12-13 11:00:00','2023-12-13 12:00:00','2023-12-13','2023-12-13',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614249,1,1,1,'2023-03-15 11:00:00','2023-03-15 12:00:00','2023-03-15','2023-03-15',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614250,1,1,1,'2023-04-26 10:00:00','2023-04-26 11:00:00','2023-04-26','2023-04-26',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614251,1,1,1,'2023-07-26 10:00:00','2023-07-26 11:00:00','2023-07-26','2023-07-26',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614252,1,1,1,'2024-01-17 11:00:00','2024-01-17 12:00:00','2024-01-17','2024-01-17',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614253,1,1,1,'2023-05-24 10:00:00','2023-05-24 11:00:00','2023-05-24','2023-05-24',0,9729); +INSERT INTO `calcms_series_dates` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `start_date`, `end_date`, `exclude`, `series_schedule_id`) VALUES (614254,1,1,1,'2024-01-10 11:00:00','2024-01-10 12:00:00','2024-01-10','2024-01-10',0,9729); /*!40000 ALTER TABLE `calcms_series_dates` ENABLE KEYS */; UNLOCK TABLES; @@ -698,20 +789,20 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `calcms_series_events`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!50503 SET character_set_client = utf8mb4 */; CREATE TABLE `calcms_series_events` ( - `series_id` int(12) unsigned NOT NULL, - `event_id` int(12) unsigned NOT NULL, - `studio_id` int(12) unsigned NOT NULL, - `manual` int(1) unsigned NOT NULL, - `project_id` int(10) unsigned NOT NULL, + `project_id` int unsigned NOT NULL, + `studio_id` int unsigned NOT NULL, + `series_id` int unsigned NOT NULL, + `event_id` int unsigned NOT NULL, + `manual` int unsigned NOT NULL, + KEY `project_id` (`project_id`), + KEY `studio_id` (`studio_id`), KEY `series_id` (`series_id`), KEY `event_id` (`event_id`), - KEY `studio_id` (`studio_id`), - KEY `project_id` (`project_id`), KEY `manual` (`manual`), KEY `pse` (`project_id`,`studio_id`,`event_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb3; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -729,30 +820,30 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `calcms_series_schedule`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!50503 SET character_set_client = utf8mb4 */; CREATE TABLE `calcms_series_schedule` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `series_id` int(10) unsigned NOT NULL, + `id` int unsigned NOT NULL AUTO_INCREMENT, + `project_id` int unsigned NOT NULL DEFAULT '1', + `studio_id` int unsigned DEFAULT NULL, + `series_id` int unsigned NOT NULL, `start` datetime NOT NULL, `end` date DEFAULT NULL, - `studio_id` int(10) unsigned DEFAULT NULL, - `frequency` int(10) unsigned DEFAULT NULL, - `duration` int(10) unsigned DEFAULT NULL, - `exclude` tinyint(1) unsigned DEFAULT NULL, - `weekday` int(10) unsigned DEFAULT NULL, - `week_of_month` int(10) unsigned DEFAULT NULL, + `frequency` int unsigned DEFAULT NULL, + `duration` int unsigned DEFAULT NULL, + `exclude` tinyint unsigned DEFAULT NULL, + `weekday` int unsigned DEFAULT NULL, + `week_of_month` int unsigned DEFAULT NULL, `period_type` varchar(16) DEFAULT NULL, - `month` int(10) unsigned NOT NULL DEFAULT '0', - `project_id` int(10) unsigned NOT NULL DEFAULT '1', - `start_offset` int(11) DEFAULT '0', - `nextDay` int(11) DEFAULT '0', + `month` int unsigned NOT NULL DEFAULT '0', + `start_offset` int DEFAULT '0', + `nextDay` int DEFAULT '0', PRIMARY KEY (`id`), - KEY `series_id` (`series_id`), + KEY `project_id` (`project_id`), KEY `studio_id` (`studio_id`), + KEY `series_id` (`series_id`), KEY `start` (`start`) USING BTREE, - KEY `end` (`end`) USING BTREE, - KEY `project_id` (`project_id`) -) ENGINE=MyISAM AUTO_INCREMENT=402 DEFAULT CHARSET=utf8; + KEY `end` (`end`) USING BTREE +) ENGINE=MyISAM AUTO_INCREMENT=9730 DEFAULT CHARSET=utf8mb3; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -761,6 +852,7 @@ CREATE TABLE `calcms_series_schedule` ( LOCK TABLES `calcms_series_schedule` WRITE; /*!40000 ALTER TABLE `calcms_series_schedule` DISABLE KEYS */; +INSERT INTO `calcms_series_schedule` (`id`, `project_id`, `studio_id`, `series_id`, `start`, `end`, `frequency`, `duration`, `exclude`, `weekday`, `week_of_month`, `period_type`, `month`, `start_offset`, `nextDay`) VALUES (9729,1,1,1,'2023-02-01 12:00:00','2024-02-29',7,60,0,1,1,'days',1,0,0); /*!40000 ALTER TABLE `calcms_series_schedule` ENABLE KEYS */; UNLOCK TABLES; @@ -770,24 +862,24 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `calcms_studio_timeslot_dates`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!50503 SET character_set_client = utf8mb4 */; CREATE TABLE `calcms_studio_timeslot_dates` ( - `studio_id` int(10) unsigned NOT NULL, + `project_id` int unsigned NOT NULL, + `studio_id` int unsigned NOT NULL, + `schedule_id` int unsigned NOT NULL, `start` datetime NOT NULL, `end` datetime NOT NULL, `start_date` date NOT NULL, `end_date` date NOT NULL, - `schedule_id` int(10) unsigned NOT NULL, - `project_id` int(10) unsigned NOT NULL, - PRIMARY KEY (`studio_id`,`start`,`end`,`project_id`) USING BTREE, + PRIMARY KEY (`project_id`,`studio_id`,`start`,`end`) USING BTREE, + KEY `project_id` (`project_id`), KEY `studio_id` (`studio_id`), + KEY `schedule_id` (`schedule_id`), KEY `start_date` (`start_date`), KEY `end_date` (`end_date`), - KEY `schedule_id` (`schedule_id`), KEY `start` (`start`), - KEY `end` (`end`), - KEY `project_id` (`project_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; + KEY `end` (`end`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb3; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -796,7 +888,373 @@ CREATE TABLE `calcms_studio_timeslot_dates` ( LOCK TABLES `calcms_studio_timeslot_dates` WRITE; /*!40000 ALTER TABLE `calcms_studio_timeslot_dates` DISABLE KEYS */; -INSERT INTO `calcms_studio_timeslot_dates` VALUES (1,'2016-05-22 00:00:00','2016-05-23 00:00:00','2016-05-21','2016-05-22',60,1),(1,'2016-05-21 00:00:00','2016-05-22 00:00:00','2016-05-20','2016-05-21',60,1),(1,'2016-05-05 00:00:00','2016-05-06 00:00:00','2016-05-04','2016-05-05',60,1),(1,'2016-05-28 00:00:00','2016-05-29 00:00:00','2016-05-27','2016-05-28',60,1),(1,'2016-05-14 00:00:00','2016-05-15 00:00:00','2016-05-13','2016-05-14',60,1),(1,'2016-05-20 00:00:00','2016-05-21 00:00:00','2016-05-19','2016-05-20',60,1),(1,'2016-05-26 00:00:00','2016-05-27 00:00:00','2016-05-25','2016-05-26',60,1),(1,'2016-05-24 00:00:00','2016-05-25 00:00:00','2016-05-23','2016-05-24',60,1),(1,'2016-05-17 00:00:00','2016-05-18 00:00:00','2016-05-16','2016-05-17',60,1),(1,'2016-05-30 00:00:00','2016-05-31 00:00:00','2016-05-29','2016-05-30',60,1),(1,'2016-05-11 00:00:00','2016-05-12 00:00:00','2016-05-10','2016-05-11',60,1),(1,'2016-05-07 00:00:00','2016-05-08 00:00:00','2016-05-06','2016-05-07',60,1),(1,'2016-05-16 00:00:00','2016-05-17 00:00:00','2016-05-15','2016-05-16',60,1),(1,'2016-05-01 00:00:00','2016-05-02 00:00:00','2016-04-30','2016-05-01',60,1),(1,'2016-05-08 00:00:00','2016-05-09 00:00:00','2016-05-07','2016-05-08',60,1),(1,'2016-05-03 00:00:00','2016-05-04 00:00:00','2016-05-02','2016-05-03',60,1),(1,'2016-05-09 00:00:00','2016-05-10 00:00:00','2016-05-08','2016-05-09',60,1),(1,'2016-05-04 00:00:00','2016-05-05 00:00:00','2016-05-03','2016-05-04',60,1),(1,'2016-05-06 00:00:00','2016-05-07 00:00:00','2016-05-05','2016-05-06',60,1),(1,'2016-05-13 00:00:00','2016-05-14 00:00:00','2016-05-12','2016-05-13',60,1),(1,'2016-05-29 00:00:00','2016-05-30 00:00:00','2016-05-28','2016-05-29',60,1),(1,'2016-05-25 00:00:00','2016-05-26 00:00:00','2016-05-24','2016-05-25',60,1),(1,'2016-05-18 00:00:00','2016-05-19 00:00:00','2016-05-17','2016-05-18',60,1),(1,'2016-05-23 00:00:00','2016-05-24 00:00:00','2016-05-22','2016-05-23',60,1),(1,'2016-05-02 00:00:00','2016-05-03 00:00:00','2016-05-01','2016-05-02',60,1),(1,'2016-05-27 00:00:00','2016-05-28 00:00:00','2016-05-26','2016-05-27',60,1),(1,'2016-05-19 00:00:00','2016-05-20 00:00:00','2016-05-18','2016-05-19',60,1),(1,'2016-05-12 00:00:00','2016-05-13 00:00:00','2016-05-11','2016-05-12',60,1),(1,'2016-05-15 00:00:00','2016-05-16 00:00:00','2016-05-14','2016-05-15',60,1),(1,'2016-05-10 00:00:00','2016-05-11 00:00:00','2016-05-09','2016-05-10',60,1); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-07-12 12:00:00','2023-07-13 12:00:00','2023-07-12','2023-07-13'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-05-14 12:00:00','2023-05-15 12:00:00','2023-05-14','2023-05-15'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-02-11 12:00:00','2023-02-12 12:00:00','2023-02-11','2023-02-12'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-07-30 12:00:00','2023-07-31 12:00:00','2023-07-30','2023-07-31'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-07-04 12:00:00','2023-07-05 12:00:00','2023-07-04','2023-07-05'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-05-02 12:00:00','2023-05-03 12:00:00','2023-05-02','2023-05-03'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-12-22 12:00:00','2023-12-23 12:00:00','2023-12-22','2023-12-23'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-02-28 12:00:00','2023-03-01 12:00:00','2023-02-28','2023-03-01'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-03-21 12:00:00','2023-03-22 12:00:00','2023-03-21','2023-03-22'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-11-28 12:00:00','2023-11-29 12:00:00','2023-11-28','2023-11-29'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-10-26 12:00:00','2023-10-27 12:00:00','2023-10-26','2023-10-27'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-08-08 12:00:00','2023-08-09 12:00:00','2023-08-08','2023-08-09'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-12-17 12:00:00','2023-12-18 12:00:00','2023-12-17','2023-12-18'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2024-01-21 12:00:00','2024-01-22 12:00:00','2024-01-21','2024-01-22'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-07-27 12:00:00','2023-07-28 12:00:00','2023-07-27','2023-07-28'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-06-16 12:00:00','2023-06-17 12:00:00','2023-06-16','2023-06-17'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-11-11 12:00:00','2023-11-12 12:00:00','2023-11-11','2023-11-12'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-03-18 12:00:00','2023-03-19 12:00:00','2023-03-18','2023-03-19'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2024-01-18 12:00:00','2024-01-19 12:00:00','2024-01-18','2024-01-19'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-09-26 12:00:00','2023-09-27 12:00:00','2023-09-26','2023-09-27'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-05-27 12:00:00','2023-05-28 12:00:00','2023-05-27','2023-05-28'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-08-18 12:00:00','2023-08-19 12:00:00','2023-08-18','2023-08-19'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-12-07 12:00:00','2023-12-08 12:00:00','2023-12-07','2023-12-08'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-03-08 12:00:00','2023-03-09 12:00:00','2023-03-08','2023-03-09'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-11-01 12:00:00','2023-11-02 12:00:00','2023-11-01','2023-11-02'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-08-21 12:00:00','2023-08-22 12:00:00','2023-08-21','2023-08-22'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-06-06 12:00:00','2023-06-07 12:00:00','2023-06-06','2023-06-07'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2024-01-08 12:00:00','2024-01-09 12:00:00','2024-01-08','2024-01-09'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-05-04 12:00:00','2023-05-05 12:00:00','2023-05-04','2023-05-05'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2024-02-02 12:00:00','2024-02-03 12:00:00','2024-02-02','2024-02-03'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-07-02 12:00:00','2023-07-03 12:00:00','2023-07-02','2023-07-03'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-04-26 12:00:00','2023-04-27 12:00:00','2023-04-26','2023-04-27'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-10-31 12:00:00','2023-11-01 12:00:00','2023-10-31','2023-11-01'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-12-24 12:00:00','2023-12-25 12:00:00','2023-12-24','2023-12-25'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-02-01 12:00:00','2023-02-02 12:00:00','2023-02-01','2023-02-02'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-05-12 12:00:00','2023-05-13 12:00:00','2023-05-12','2023-05-13'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-07-14 12:00:00','2023-07-15 12:00:00','2023-07-14','2023-07-15'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-05-30 12:00:00','2023-05-31 12:00:00','2023-05-30','2023-05-31'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-02-26 12:00:00','2023-02-27 12:00:00','2023-02-26','2023-02-27'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-07-13 12:00:00','2023-07-14 12:00:00','2023-07-13','2023-07-14'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-04-01 12:00:00','2023-04-02 12:00:00','2023-04-01','2023-04-02'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-12-23 12:00:00','2023-12-24 12:00:00','2023-12-23','2023-12-24'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-05-03 12:00:00','2023-05-04 12:00:00','2023-05-03','2023-05-04'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-03-16 12:00:00','2023-03-17 12:00:00','2023-03-16','2023-03-17'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-10-11 12:00:00','2023-10-12 12:00:00','2023-10-11','2023-10-12'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-06-18 12:00:00','2023-06-19 12:00:00','2023-06-18','2023-06-19'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-12-19 12:00:00','2023-12-20 12:00:00','2023-12-19','2023-12-20'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-09-01 12:00:00','2023-09-02 12:00:00','2023-09-01','2023-09-02'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2024-01-16 12:00:00','2024-01-17 12:00:00','2024-01-16','2024-01-17'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-05-15 12:00:00','2023-05-16 12:00:00','2023-05-15','2023-05-16'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-05-10 12:00:00','2023-05-11 12:00:00','2023-05-10','2023-05-11'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-08-06 12:00:00','2023-08-07 12:00:00','2023-08-06','2023-08-07'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-06-21 12:00:00','2023-06-22 12:00:00','2023-06-21','2023-06-22'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-11-26 12:00:00','2023-11-27 12:00:00','2023-11-26','2023-11-27'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-10-28 12:00:00','2023-10-29 12:00:00','2023-10-28','2023-10-29'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-07-05 12:00:00','2023-07-06 12:00:00','2023-07-05','2023-07-06'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-07-29 12:00:00','2023-07-30 12:00:00','2023-07-29','2023-07-30'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-07-10 12:00:00','2023-07-11 12:00:00','2023-07-10','2023-07-11'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-09-11 12:00:00','2023-09-12 12:00:00','2023-09-11','2023-09-12'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-12-25 12:00:00','2023-12-26 12:00:00','2023-12-25','2023-12-26'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-12-09 12:00:00','2023-12-10 12:00:00','2023-12-09','2023-12-10'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-06-08 12:00:00','2023-06-09 12:00:00','2023-06-08','2023-06-09'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-10-01 12:00:00','2023-10-02 12:00:00','2023-10-01','2023-10-02'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-03-06 12:00:00','2023-03-07 12:00:00','2023-03-06','2023-03-07'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2024-01-06 12:00:00','2024-01-07 12:00:00','2024-01-06','2024-01-07'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-05-29 12:00:00','2023-05-30 12:00:00','2023-05-29','2023-05-30'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-05-05 12:00:00','2023-05-06 12:00:00','2023-05-05','2023-05-06'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-08-16 12:00:00','2023-08-17 12:00:00','2023-08-16','2023-08-17'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-09-28 12:00:00','2023-09-29 12:00:00','2023-09-28','2023-09-29'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-07-15 12:00:00','2023-07-16 12:00:00','2023-07-15','2023-07-16'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-12-20 12:00:00','2023-12-21 12:00:00','2023-12-20','2023-12-21'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-04-11 12:00:00','2023-04-12 12:00:00','2023-04-11','2023-04-12'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-07-03 12:00:00','2023-07-04 12:00:00','2023-07-03','2023-07-04'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-05-13 12:00:00','2023-05-14 12:00:00','2023-05-13','2023-05-14'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-04-28 12:00:00','2023-04-29 12:00:00','2023-04-28','2023-04-29'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-11-15 12:00:00','2023-11-16 12:00:00','2023-11-15','2023-11-16'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-04-12 12:00:00','2023-04-13 12:00:00','2023-04-12','2023-04-13'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-08-19 12:00:00','2023-08-20 12:00:00','2023-08-19','2023-08-20'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2024-01-20 12:00:00','2024-01-21 12:00:00','2024-01-20','2024-01-21'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-03-20 12:00:00','2023-03-21 12:00:00','2023-03-20','2023-03-21'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-04-30 12:00:00','2023-05-01 12:00:00','2023-04-30','2023-05-01'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-06-07 12:00:00','2023-06-08 12:00:00','2023-06-07','2023-06-08'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-02-03 12:00:00','2023-02-04 12:00:00','2023-02-03','2023-02-04'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-12-06 12:00:00','2023-12-07 12:00:00','2023-12-06','2023-12-07'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-04-04 12:00:00','2023-04-05 12:00:00','2023-04-04','2023-04-05'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-03-25 12:00:00','2023-03-26 12:00:00','2023-03-25','2023-03-26'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-03-09 12:00:00','2023-03-10 12:00:00','2023-03-09','2023-03-10'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-09-27 12:00:00','2023-09-28 12:00:00','2023-09-27','2023-09-28'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2024-01-25 12:00:00','2024-01-26 12:00:00','2024-01-25','2024-01-26'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2024-01-09 12:00:00','2024-01-10 12:00:00','2024-01-09','2024-01-10'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-05-26 12:00:00','2023-05-27 12:00:00','2023-05-26','2023-05-27'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-11-10 12:00:00','2023-11-11 12:00:00','2023-11-10','2023-11-11'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-09-30 12:00:00','2023-10-01 12:00:00','2023-09-30','2023-10-01'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-02-10 12:00:00','2023-02-11 12:00:00','2023-02-10','2023-02-11'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-07-31 12:00:00','2023-08-01 12:00:00','2023-07-31','2023-08-01'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-09-12 12:00:00','2023-09-13 12:00:00','2023-09-12','2023-09-13'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-10-02 12:00:00','2023-10-03 12:00:00','2023-10-02','2023-10-03'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-06-24 12:00:00','2023-06-25 12:00:00','2023-06-24','2023-06-25'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-04-27 12:00:00','2023-04-28 12:00:00','2023-04-27','2023-04-28'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-11-03 12:00:00','2023-11-04 12:00:00','2023-11-03','2023-11-04'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-08-23 12:00:00','2023-08-24 12:00:00','2023-08-23','2023-08-24'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-09-04 12:00:00','2023-09-05 12:00:00','2023-09-04','2023-09-05'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-02-15 12:00:00','2023-02-16 12:00:00','2023-02-15','2023-02-16'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-10-14 12:00:00','2023-10-15 12:00:00','2023-10-14','2023-10-15'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-10-30 12:00:00','2023-10-31 12:00:00','2023-10-30','2023-10-31'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-03-23 12:00:00','2023-03-24 12:00:00','2023-03-23','2023-03-24'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-10-12 12:00:00','2023-10-13 12:00:00','2023-10-12','2023-10-13'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-09-02 12:00:00','2023-09-03 12:00:00','2023-09-02','2023-09-03'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2024-01-23 12:00:00','2024-01-24 12:00:00','2024-01-23','2024-01-24'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-05-31 12:00:00','2023-06-01 12:00:00','2023-05-31','2023-06-01'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-11-13 12:00:00','2023-11-14 12:00:00','2023-11-13','2023-11-14'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-06-22 12:00:00','2023-06-23 12:00:00','2023-06-22','2023-06-23'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-10-04 12:00:00','2023-10-05 12:00:00','2023-10-04','2023-10-05'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-02-05 12:00:00','2023-02-06 12:00:00','2023-02-05','2023-02-06'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-09-14 12:00:00','2023-09-15 12:00:00','2023-09-14','2023-09-15'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-08-09 12:00:00','2023-08-10 12:00:00','2023-08-09','2023-08-10'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-08-25 12:00:00','2023-08-26 12:00:00','2023-08-25','2023-08-26'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-04-02 12:00:00','2023-04-03 12:00:00','2023-04-02','2023-04-03'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-11-29 12:00:00','2023-11-30 12:00:00','2023-11-29','2023-11-30'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-11-05 12:00:00','2023-11-06 12:00:00','2023-11-05','2023-11-06'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-07-26 12:00:00','2023-07-27 12:00:00','2023-07-26','2023-07-27'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-02-13 12:00:00','2023-02-14 12:00:00','2023-02-13','2023-02-14'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-06-17 12:00:00','2023-06-18 12:00:00','2023-06-17','2023-06-18'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-03-19 12:00:00','2023-03-20 12:00:00','2023-03-19','2023-03-20'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-04-14 12:00:00','2023-04-15 12:00:00','2023-04-14','2023-04-15'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-12-16 12:00:00','2023-12-17 12:00:00','2023-12-16','2023-12-17'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-10-27 12:00:00','2023-10-28 12:00:00','2023-10-27','2023-10-28'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-08-20 12:00:00','2023-08-21 12:00:00','2023-08-20','2023-08-21'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2024-01-19 12:00:00','2024-01-20 12:00:00','2024-01-19','2024-01-20'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-02-02 12:00:00','2023-02-03 12:00:00','2023-02-02','2023-02-03'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-06-09 12:00:00','2023-06-10 12:00:00','2023-06-09','2023-06-10'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-06-25 12:00:00','2023-06-26 12:00:00','2023-06-25','2023-06-26'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-12-08 12:00:00','2023-12-09 12:00:00','2023-12-08','2023-12-09'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2024-02-01 12:00:00','2024-02-02 12:00:00','2024-02-01','2024-02-02'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-04-13 12:00:00','2023-04-14 12:00:00','2023-04-13','2023-04-14'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-10-10 12:00:00','2023-10-11 12:00:00','2023-10-10','2023-10-11'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-05-28 12:00:00','2023-05-29 12:00:00','2023-05-28','2023-05-29'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-08-17 12:00:00','2023-08-18 12:00:00','2023-08-17','2023-08-18'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-07-01 12:00:00','2023-07-02 12:00:00','2023-07-01','2023-07-02'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2024-01-07 12:00:00','2024-01-08 12:00:00','2024-01-07','2024-01-08'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-09-05 12:00:00','2023-09-06 12:00:00','2023-09-05','2023-09-06'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-09-29 12:00:00','2023-09-30 12:00:00','2023-09-29','2023-09-30'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-02-14 12:00:00','2023-02-15 12:00:00','2023-02-14','2023-02-15'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-10-15 12:00:00','2023-10-16 12:00:00','2023-10-15','2023-10-16'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-06-20 12:00:00','2023-06-21 12:00:00','2023-06-20','2023-06-21'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-05-11 12:00:00','2023-05-12 12:00:00','2023-05-11','2023-05-12'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-03-07 12:00:00','2023-03-08 12:00:00','2023-03-07','2023-03-08'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-09-13 12:00:00','2023-09-14 12:00:00','2023-09-13','2023-09-14'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-10-03 12:00:00','2023-10-04 12:00:00','2023-10-03','2023-10-04'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-11-14 12:00:00','2023-11-15 12:00:00','2023-11-14','2023-11-15'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2024-01-24 12:00:00','2024-01-25 12:00:00','2024-01-24','2024-01-25'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-11-02 12:00:00','2023-11-03 12:00:00','2023-11-02','2023-11-03'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-04-05 12:00:00','2023-04-06 12:00:00','2023-04-05','2023-04-06'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-04-29 12:00:00','2023-04-30 12:00:00','2023-04-29','2023-04-30'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-03-24 12:00:00','2023-03-25 12:00:00','2023-03-24','2023-03-25'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-08-22 12:00:00','2023-08-23 12:00:00','2023-08-22','2023-08-23'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-10-13 12:00:00','2023-10-14 12:00:00','2023-10-13','2023-10-14'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-04-10 12:00:00','2023-04-11 12:00:00','2023-04-10','2023-04-11'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-09-03 12:00:00','2023-09-04 12:00:00','2023-09-03','2023-09-04'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2024-01-22 12:00:00','2024-01-23 12:00:00','2024-01-22','2024-01-23'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-08-24 12:00:00','2023-08-25 12:00:00','2023-08-24','2023-08-25'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-03-22 12:00:00','2023-03-23 12:00:00','2023-03-22','2023-03-23'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-11-04 12:00:00','2023-11-05 12:00:00','2023-11-04','2023-11-05'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-02-27 12:00:00','2023-02-28 12:00:00','2023-02-27','2023-02-28'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-06-23 12:00:00','2023-06-24 12:00:00','2023-06-23','2023-06-24'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-11-30 12:00:00','2023-12-01 12:00:00','2023-11-30','2023-12-01'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-04-15 12:00:00','2023-04-16 12:00:00','2023-04-15','2023-04-16'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-11-12 12:00:00','2023-11-13 12:00:00','2023-11-12','2023-11-13'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-12-18 12:00:00','2023-12-19 12:00:00','2023-12-18','2023-12-19'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-06-19 12:00:00','2023-06-20 12:00:00','2023-06-19','2023-06-20'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-02-12 12:00:00','2023-02-13 12:00:00','2023-02-12','2023-02-13'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-09-10 12:00:00','2023-09-11 12:00:00','2023-09-10','2023-09-11'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-07-11 12:00:00','2023-07-12 12:00:00','2023-07-11','2023-07-12'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-08-07 12:00:00','2023-08-08 12:00:00','2023-08-07','2023-08-08'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-11-27 12:00:00','2023-11-28 12:00:00','2023-11-27','2023-11-28'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-04-03 12:00:00','2023-04-04 12:00:00','2023-04-03','2023-04-04'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-10-05 12:00:00','2023-10-06 12:00:00','2023-10-05','2023-10-06'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-10-29 12:00:00','2023-10-30 12:00:00','2023-10-29','2023-10-30'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-02-04 12:00:00','2023-02-05 12:00:00','2023-02-04','2023-02-05'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-09-15 12:00:00','2023-09-16 12:00:00','2023-09-15','2023-09-16'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2024-01-17 12:00:00','2024-01-18 12:00:00','2024-01-17','2024-01-18'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-12-21 12:00:00','2023-12-22 12:00:00','2023-12-21','2023-12-22'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-03-17 12:00:00','2023-03-18 12:00:00','2023-03-17','2023-03-18'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-05-01 12:00:00','2023-05-02 12:00:00','2023-05-01','2023-05-02'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-07-28 12:00:00','2023-07-29 12:00:00','2023-07-28','2023-07-29'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-12-02 12:00:00','2023-12-03 12:00:00','2023-12-02','2023-12-03'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-02-08 12:00:00','2023-02-09 12:00:00','2023-02-08','2023-02-09'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-05-22 12:00:00','2023-05-23 12:00:00','2023-05-22','2023-05-23'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-07-24 12:00:00','2023-07-25 12:00:00','2023-07-24','2023-07-25'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-12-14 12:00:00','2023-12-15 12:00:00','2023-12-14','2023-12-15'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-04-16 12:00:00','2023-04-17 12:00:00','2023-04-16','2023-04-17'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-07-07 12:00:00','2023-07-08 12:00:00','2023-07-07','2023-07-08'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-08-11 12:00:00','2023-08-12 12:00:00','2023-08-11','2023-08-12'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2024-01-01 12:00:00','2024-01-02 12:00:00','2024-01-01','2024-01-02'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-05-17 12:00:00','2023-05-18 12:00:00','2023-05-17','2023-05-18'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-08-28 12:00:00','2023-08-29 12:00:00','2023-08-28','2023-08-29'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-09-16 12:00:00','2023-09-17 12:00:00','2023-09-16','2023-09-17'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-03-01 12:00:00','2023-03-02 12:00:00','2023-03-01','2023-03-02'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-10-06 12:00:00','2023-10-07 12:00:00','2023-10-06','2023-10-07'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-11-08 12:00:00','2023-11-09 12:00:00','2023-11-08','2023-11-09'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2024-01-28 12:00:00','2024-01-29 12:00:00','2024-01-28','2024-01-29'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-06-26 12:00:00','2023-06-27 12:00:00','2023-06-26','2023-06-27'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-08-01 12:00:00','2023-08-02 12:00:00','2023-08-01','2023-08-02'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-07-17 12:00:00','2023-07-18 12:00:00','2023-07-17','2023-07-18'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-03-28 12:00:00','2023-03-29 12:00:00','2023-03-28','2023-03-29'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-11-21 12:00:00','2023-11-22 12:00:00','2023-11-21','2023-11-22'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2024-01-11 12:00:00','2024-01-12 12:00:00','2024-01-11','2024-01-12'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-12-27 12:00:00','2023-12-28 12:00:00','2023-12-27','2023-12-28'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-11-18 12:00:00','2023-11-19 12:00:00','2023-11-18','2023-11-19'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-10-16 12:00:00','2023-10-17 12:00:00','2023-10-16','2023-10-17'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-03-11 12:00:00','2023-03-12 12:00:00','2023-03-11','2023-03-12'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-09-06 12:00:00','2023-09-07 12:00:00','2023-09-06','2023-09-07'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-05-07 12:00:00','2023-05-08 12:00:00','2023-05-07','2023-05-08'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-02-18 12:00:00','2023-02-19 12:00:00','2023-02-18','2023-02-19'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-12-12 12:00:00','2023-12-13 12:00:00','2023-12-12','2023-12-13'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-12-30 12:00:00','2023-12-31 12:00:00','2023-12-30','2023-12-31'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-02-21 12:00:00','2023-02-22 12:00:00','2023-02-21','2023-02-22'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-04-06 12:00:00','2023-04-07 12:00:00','2023-04-06','2023-04-07'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-12-04 12:00:00','2023-12-05 12:00:00','2023-12-04','2023-12-05'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-07-22 12:00:00','2023-07-23 12:00:00','2023-07-22','2023-07-23'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-05-24 12:00:00','2023-05-25 12:00:00','2023-05-24','2023-05-25'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-05-23 12:00:00','2023-05-24 12:00:00','2023-05-23','2023-05-24'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-04-18 12:00:00','2023-04-19 12:00:00','2023-04-18','2023-04-19'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-12-03 12:00:00','2023-12-04 12:00:00','2023-12-03','2023-12-04'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-04-21 12:00:00','2023-04-22 12:00:00','2023-04-21','2023-04-22'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-03-31 12:00:00','2023-04-01 12:00:00','2023-03-31','2023-04-01'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-02-06 12:00:00','2023-02-07 12:00:00','2023-02-06','2023-02-07'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2024-01-31 12:00:00','2024-02-01 12:00:00','2024-01-31','2024-02-01'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-12-10 12:00:00','2023-12-11 12:00:00','2023-12-10','2023-12-11'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-07-09 12:00:00','2023-07-10 12:00:00','2023-07-09','2023-07-10'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-07-25 12:00:00','2023-07-26 12:00:00','2023-07-25','2023-07-26'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-10-08 12:00:00','2023-10-09 12:00:00','2023-10-08','2023-10-09'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-11-06 12:00:00','2023-11-07 12:00:00','2023-11-06','2023-11-07'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-09-18 12:00:00','2023-09-19 12:00:00','2023-09-18','2023-09-19'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-06-01 12:00:00','2023-06-02 12:00:00','2023-06-01','2023-06-02'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-08-26 12:00:00','2023-08-27 12:00:00','2023-08-26','2023-08-27'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-05-19 12:00:00','2023-05-20 12:00:00','2023-05-19','2023-05-20'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-12-15 12:00:00','2023-12-16 12:00:00','2023-12-15','2023-12-16'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-07-20 12:00:00','2023-07-21 12:00:00','2023-07-20','2023-07-21'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-09-21 12:00:00','2023-09-22 12:00:00','2023-09-21','2023-09-22'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-07-19 12:00:00','2023-07-20 12:00:00','2023-07-19','2023-07-20'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-05-20 12:00:00','2023-05-21 12:00:00','2023-05-20','2023-05-21'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-06-11 12:00:00','2023-06-12 12:00:00','2023-06-11','2023-06-12'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-09-08 12:00:00','2023-09-09 12:00:00','2023-09-08','2023-09-09'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-11-16 12:00:00','2023-11-17 12:00:00','2023-11-16','2023-11-17'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-10-18 12:00:00','2023-10-19 12:00:00','2023-10-18','2023-10-19'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-05-25 12:00:00','2023-05-26 12:00:00','2023-05-25','2023-05-26'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2024-01-26 12:00:00','2024-01-27 12:00:00','2024-01-26','2024-01-27'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-05-09 12:00:00','2023-05-10 12:00:00','2023-05-09','2023-05-10'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-10-21 12:00:00','2023-10-22 12:00:00','2023-10-21','2023-10-22'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-03-26 12:00:00','2023-03-27 12:00:00','2023-03-26','2023-03-27'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-06-28 12:00:00','2023-06-29 12:00:00','2023-06-28','2023-06-29'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-12-05 12:00:00','2023-12-06 12:00:00','2023-12-05','2023-12-06'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-12-29 12:00:00','2023-12-30 12:00:00','2023-12-29','2023-12-30'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-04-08 12:00:00','2023-04-09 12:00:00','2023-04-08','2023-04-09'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-08-31 12:00:00','2023-09-01 12:00:00','2023-08-31','2023-09-01'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-12-13 12:00:00','2023-12-14 12:00:00','2023-12-13','2023-12-14'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-07-23 12:00:00','2023-07-24 12:00:00','2023-07-23','2023-07-24'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-02-16 12:00:00','2023-02-17 12:00:00','2023-02-16','2023-02-17'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-10-17 12:00:00','2023-10-18 12:00:00','2023-10-17','2023-10-18'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-09-07 12:00:00','2023-09-08 12:00:00','2023-09-07','2023-09-08'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2024-01-29 12:00:00','2024-01-30 12:00:00','2024-01-29','2024-01-30'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-05-06 12:00:00','2023-05-07 12:00:00','2023-05-06','2023-05-07'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2024-01-05 12:00:00','2024-01-06 12:00:00','2024-01-05','2024-01-06'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-08-10 12:00:00','2023-08-11 12:00:00','2023-08-10','2023-08-11'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-03-05 12:00:00','2023-03-06 12:00:00','2023-03-05','2023-03-06'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-03-29 12:00:00','2023-03-30 12:00:00','2023-03-29','2023-03-30'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-12-26 12:00:00','2023-12-27 12:00:00','2023-12-26','2023-12-27'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-04-24 12:00:00','2023-04-25 12:00:00','2023-04-24','2023-04-25'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-02-23 12:00:00','2023-02-24 12:00:00','2023-02-23','2023-02-24'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-06-27 12:00:00','2023-06-28 12:00:00','2023-06-27','2023-06-28'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-07-16 12:00:00','2023-07-17 12:00:00','2023-07-16','2023-07-17'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-08-15 12:00:00','2023-08-16 12:00:00','2023-08-15','2023-08-16'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-11-19 12:00:00','2023-11-20 12:00:00','2023-11-19','2023-11-20'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-02-19 12:00:00','2023-02-20 12:00:00','2023-02-19','2023-02-20'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-06-12 12:00:00','2023-06-13 12:00:00','2023-06-12','2023-06-13'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-09-24 12:00:00','2023-09-25 12:00:00','2023-09-24','2023-09-25'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-06-30 12:00:00','2023-07-01 12:00:00','2023-06-30','2023-07-01'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-08-03 12:00:00','2023-08-04 12:00:00','2023-08-03','2023-08-04'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-11-23 12:00:00','2023-11-24 12:00:00','2023-11-23','2023-11-24'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-04-07 12:00:00','2023-04-08 12:00:00','2023-04-07','2023-04-08'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-06-04 12:00:00','2023-06-05 12:00:00','2023-06-04','2023-06-05'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-10-22 12:00:00','2023-10-23 12:00:00','2023-10-22','2023-10-23'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2024-01-13 12:00:00','2024-01-14 12:00:00','2024-01-13','2024-01-14'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-03-13 12:00:00','2023-03-14 12:00:00','2023-03-13','2023-03-14'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-10-24 12:00:00','2023-10-25 12:00:00','2023-10-24','2023-10-25'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-06-02 12:00:00','2023-06-03 12:00:00','2023-06-02','2023-06-03'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-12-31 12:00:00','2024-01-01 12:00:00','2023-12-31','2024-01-01'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-02-25 12:00:00','2023-02-26 12:00:00','2023-02-25','2023-02-26'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-02-09 12:00:00','2023-02-10 12:00:00','2023-02-09','2023-02-10'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-04-17 12:00:00','2023-04-18 12:00:00','2023-04-17','2023-04-18'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-08-13 12:00:00','2023-08-14 12:00:00','2023-08-13','2023-08-14'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-09-22 12:00:00','2023-09-23 12:00:00','2023-09-22','2023-09-23'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2024-01-03 12:00:00','2024-01-04 12:00:00','2024-01-03','2024-01-04'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-06-14 12:00:00','2023-06-15 12:00:00','2023-06-14','2023-06-15'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-02-20 12:00:00','2023-02-21 12:00:00','2023-02-20','2023-02-21'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-03-03 12:00:00','2023-03-04 12:00:00','2023-03-03','2023-03-04'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-05-16 12:00:00','2023-05-17 12:00:00','2023-05-16','2023-05-17'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2024-01-15 12:00:00','2024-01-16 12:00:00','2024-01-15','2024-01-16'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-09-17 12:00:00','2023-09-18 12:00:00','2023-09-17','2023-09-18'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-11-20 12:00:00','2023-11-21 12:00:00','2023-11-20','2023-11-21'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-10-07 12:00:00','2023-10-08 12:00:00','2023-10-07','2023-10-08'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-03-15 12:00:00','2023-03-16 12:00:00','2023-03-15','2023-03-16'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-03-10 12:00:00','2023-03-11 12:00:00','2023-03-10','2023-03-11'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-07-06 12:00:00','2023-07-07 12:00:00','2023-07-06','2023-07-07'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-04-22 12:00:00','2023-04-23 12:00:00','2023-04-22','2023-04-23'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-11-25 12:00:00','2023-11-26 12:00:00','2023-11-25','2023-11-26'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-11-09 12:00:00','2023-11-10 12:00:00','2023-11-09','2023-11-10'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-08-29 12:00:00','2023-08-30 12:00:00','2023-08-29','2023-08-30'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2024-01-10 12:00:00','2024-01-11 12:00:00','2024-01-10','2024-01-11'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-08-05 12:00:00','2023-08-06 12:00:00','2023-08-05','2023-08-06'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-03-27 12:00:00','2023-03-28 12:00:00','2023-03-27','2023-03-28'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-07-18 12:00:00','2023-07-19 12:00:00','2023-07-18','2023-07-19'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-10-19 12:00:00','2023-10-20 12:00:00','2023-10-19','2023-10-20'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2024-01-27 12:00:00','2024-01-28 12:00:00','2024-01-27','2024-01-28'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-12-11 12:00:00','2023-12-12 12:00:00','2023-12-11','2023-12-12'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-09-25 12:00:00','2023-09-26 12:00:00','2023-09-25','2023-09-26'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-09-09 12:00:00','2023-09-10 12:00:00','2023-09-09','2023-09-10'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-05-08 12:00:00','2023-05-09 12:00:00','2023-05-08','2023-05-09'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-09-20 12:00:00','2023-09-21 12:00:00','2023-09-20','2023-09-21'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-07-21 12:00:00','2023-07-22 12:00:00','2023-07-21','2023-07-22'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-11-17 12:00:00','2023-11-18 12:00:00','2023-11-17','2023-11-18'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-02-22 12:00:00','2023-02-23 12:00:00','2023-02-22','2023-02-23'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-12-28 12:00:00','2023-12-29 12:00:00','2023-12-28','2023-12-29'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-06-05 12:00:00','2023-06-06 12:00:00','2023-06-05','2023-06-06'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-06-29 12:00:00','2023-06-30 12:00:00','2023-06-29','2023-06-30'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-03-04 12:00:00','2023-03-05 12:00:00','2023-03-04','2023-03-05'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-08-02 12:00:00','2023-08-03 12:00:00','2023-08-02','2023-08-03'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-11-22 12:00:00','2023-11-23 12:00:00','2023-11-22','2023-11-23'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-04-25 12:00:00','2023-04-26 12:00:00','2023-04-25','2023-04-26'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-04-09 12:00:00','2023-04-10 12:00:00','2023-04-09','2023-04-10'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-02-17 12:00:00','2023-02-18 12:00:00','2023-02-17','2023-02-18'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-06-13 12:00:00','2023-06-14 12:00:00','2023-06-13','2023-06-14'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2024-01-04 12:00:00','2024-01-05 12:00:00','2024-01-04','2024-01-05'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-03-12 12:00:00','2023-03-13 12:00:00','2023-03-12','2023-03-13'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-08-14 12:00:00','2023-08-15 12:00:00','2023-08-14','2023-08-15'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2024-01-30 12:00:00','2024-01-31 12:00:00','2024-01-30','2024-01-31'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-10-23 12:00:00','2023-10-24 12:00:00','2023-10-23','2023-10-24'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-03-30 12:00:00','2023-03-31 12:00:00','2023-03-30','2023-03-31'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-04-20 12:00:00','2023-04-21 12:00:00','2023-04-20','2023-04-21'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2024-01-12 12:00:00','2024-01-13 12:00:00','2024-01-12','2024-01-13'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-04-19 12:00:00','2023-04-20 12:00:00','2023-04-19','2023-04-20'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-08-12 12:00:00','2023-08-13 12:00:00','2023-08-12','2023-08-13'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-03-14 12:00:00','2023-03-15 12:00:00','2023-03-14','2023-03-15'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2024-01-14 12:00:00','2024-01-15 12:00:00','2024-01-14','2024-01-15'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-06-03 12:00:00','2023-06-04 12:00:00','2023-06-03','2023-06-04'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-02-07 12:00:00','2023-02-08 12:00:00','2023-02-07','2023-02-08'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-08-30 12:00:00','2023-08-31 12:00:00','2023-08-30','2023-08-31'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-11-24 12:00:00','2023-11-25 12:00:00','2023-11-24','2023-11-25'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-08-04 12:00:00','2023-08-05 12:00:00','2023-08-04','2023-08-05'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-03-02 12:00:00','2023-03-03 12:00:00','2023-03-02','2023-03-03'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2024-01-02 12:00:00','2024-01-03 12:00:00','2024-01-02','2024-01-03'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-09-23 12:00:00','2023-09-24 12:00:00','2023-09-23','2023-09-24'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-06-10 12:00:00','2023-06-11 12:00:00','2023-06-10','2023-06-11'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-05-21 12:00:00','2023-05-22 12:00:00','2023-05-21','2023-05-22'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-07-08 12:00:00','2023-07-09 12:00:00','2023-07-08','2023-07-09'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-09-19 12:00:00','2023-09-20 12:00:00','2023-09-19','2023-09-20'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-12-01 12:00:00','2023-12-02 12:00:00','2023-12-01','2023-12-02'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-10-25 12:00:00','2023-10-26 12:00:00','2023-10-25','2023-10-26'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-10-09 12:00:00','2023-10-10 12:00:00','2023-10-09','2023-10-10'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-02-24 12:00:00','2023-02-25 12:00:00','2023-02-24','2023-02-25'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-11-07 12:00:00','2023-11-08 12:00:00','2023-11-07','2023-11-08'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-04-23 12:00:00','2023-04-24 12:00:00','2023-04-23','2023-04-24'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-10-20 12:00:00','2023-10-21 12:00:00','2023-10-20','2023-10-21'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-08-27 12:00:00','2023-08-28 12:00:00','2023-08-27','2023-08-28'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-05-18 12:00:00','2023-05-19 12:00:00','2023-05-18','2023-05-19'); +INSERT INTO `calcms_studio_timeslot_dates` (`project_id`, `studio_id`, `schedule_id`, `start`, `end`, `start_date`, `end_date`) VALUES (1,1,152,'2023-06-15 12:00:00','2023-06-16 12:00:00','2023-06-15','2023-06-16'); /*!40000 ALTER TABLE `calcms_studio_timeslot_dates` ENABLE KEYS */; UNLOCK TABLES; @@ -806,21 +1264,21 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `calcms_studio_timeslot_schedule`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!50503 SET character_set_client = utf8mb4 */; CREATE TABLE `calcms_studio_timeslot_schedule` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `studio_id` int(10) unsigned NOT NULL, + `id` int unsigned NOT NULL AUTO_INCREMENT, + `project_id` int unsigned NOT NULL, + `studio_id` int unsigned NOT NULL, `start` datetime NOT NULL, `end` datetime NOT NULL, - `frequency` int(10) unsigned NOT NULL, + `frequency` int unsigned NOT NULL, `end_date` date NOT NULL, - `project_id` int(10) unsigned NOT NULL, PRIMARY KEY (`id`), + KEY `project_id` (`project_id`), KEY `studio_id` (`studio_id`), KEY `start` (`start`), - KEY `end` (`end`), - KEY `project_id` (`project_id`) -) ENGINE=MyISAM AUTO_INCREMENT=61 DEFAULT CHARSET=utf8; + KEY `end` (`end`) +) ENGINE=MyISAM AUTO_INCREMENT=153 DEFAULT CHARSET=utf8mb3; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -829,7 +1287,7 @@ CREATE TABLE `calcms_studio_timeslot_schedule` ( LOCK TABLES `calcms_studio_timeslot_schedule` WRITE; /*!40000 ALTER TABLE `calcms_studio_timeslot_schedule` DISABLE KEYS */; -INSERT INTO `calcms_studio_timeslot_schedule` VALUES (60,1,'2016-05-01 00:00:00','2016-05-02 00:00:00',1,'2016-05-30',1); +INSERT INTO `calcms_studio_timeslot_schedule` (`id`, `project_id`, `studio_id`, `start`, `end`, `frequency`, `end_date`) VALUES (152,1,1,'2023-02-01 12:00:00','2023-02-02 12:00:00',1,'2024-02-02'); /*!40000 ALTER TABLE `calcms_studio_timeslot_schedule` ENABLE KEYS */; UNLOCK TABLES; @@ -839,22 +1297,22 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `calcms_studios`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!50503 SET character_set_client = utf8mb4 */; CREATE TABLE `calcms_studios` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `id` int unsigned NOT NULL AUTO_INCREMENT, `name` varchar(32) NOT NULL, `description` text NOT NULL, `location` varchar(100) NOT NULL, `stream` varchar(100) NOT NULL, + `image` varchar(200) NOT NULL, `google_calendar` varchar(100) NOT NULL, `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, - `modified_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `image` varchar(200) NOT NULL, + `modified_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) USING BTREE, UNIQUE KEY `name_2` (`name`), KEY `location` (`location`), KEY `name` (`name`) -) ENGINE=MyISAM AUTO_INCREMENT=23 DEFAULT CHARSET=utf8; +) ENGINE=MyISAM AUTO_INCREMENT=45 DEFAULT CHARSET=utf8mb3; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -863,7 +1321,7 @@ CREATE TABLE `calcms_studios` ( LOCK TABLES `calcms_studios` WRITE; /*!40000 ALTER TABLE `calcms_studios` DISABLE KEYS */; -INSERT INTO `calcms_studios` VALUES (1,'MeinStudio','Studio','studio','','',NULL,'2016-05-16 13:54:02',''); +INSERT INTO `calcms_studios` (`id`, `name`, `description`, `location`, `stream`, `image`, `google_calendar`, `created_at`, `modified_at`) VALUES (1,'My Studio','My Radio Studio','studio','','','https://my-radio.org',NULL,'2023-02-19 21:17:18'); /*!40000 ALTER TABLE `calcms_studios` ENABLE KEYS */; UNLOCK TABLES; @@ -873,14 +1331,14 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `calcms_tags`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!50503 SET character_set_client = utf8mb4 */; CREATE TABLE `calcms_tags` ( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `id` bigint unsigned NOT NULL AUTO_INCREMENT, `name` varchar(100) DEFAULT NULL, - `event_id` bigint(20) unsigned NOT NULL, + `event_id` bigint unsigned NOT NULL, KEY `id` (`id`), KEY `event_id` (`event_id`) -) ENGINE=MyISAM AUTO_INCREMENT=8 DEFAULT CHARSET=utf8; +) ENGINE=MyISAM AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb3; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -892,33 +1350,88 @@ LOCK TABLES `calcms_tags` WRITE; /*!40000 ALTER TABLE `calcms_tags` ENABLE KEYS */; UNLOCK TABLES; +-- +-- Table structure for table `calcms_user_day_start` +-- + +DROP TABLE IF EXISTS `calcms_user_day_start`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `calcms_user_day_start` ( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `project_id` int unsigned NOT NULL, + `studio_id` int unsigned NOT NULL, + `user` varchar(45) NOT NULL, + `day_start` int unsigned DEFAULT '0', + PRIMARY KEY (`id`), + UNIQUE KEY `select` (`project_id`,`studio_id`,`user`) +) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb3; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `calcms_user_day_start` +-- + +LOCK TABLES `calcms_user_day_start` WRITE; +/*!40000 ALTER TABLE `calcms_user_day_start` DISABLE KEYS */; +INSERT INTO `calcms_user_day_start` (`id`, `project_id`, `studio_id`, `user`, `day_start`) VALUES (1,1,1,'ccAdmin',0); +/*!40000 ALTER TABLE `calcms_user_day_start` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `calcms_user_default_studios` +-- + +DROP TABLE IF EXISTS `calcms_user_default_studios`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `calcms_user_default_studios` ( + `id` int NOT NULL AUTO_INCREMENT, + `project_id` int NOT NULL, + `studio_id` int NOT NULL, + `user` varchar(50) NOT NULL, + PRIMARY KEY (`id`), + KEY `user` (`user`) +) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb3; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `calcms_user_default_studios` +-- + +LOCK TABLES `calcms_user_default_studios` WRITE; +/*!40000 ALTER TABLE `calcms_user_default_studios` DISABLE KEYS */; +INSERT INTO `calcms_user_default_studios` (`id`, `project_id`, `studio_id`, `user`) VALUES (4,1,1,'ccAdmin'); +/*!40000 ALTER TABLE `calcms_user_default_studios` ENABLE KEYS */; +UNLOCK TABLES; + -- -- Table structure for table `calcms_user_events` -- DROP TABLE IF EXISTS `calcms_user_events`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!50503 SET character_set_client = utf8mb4 */; CREATE TABLE `calcms_user_events` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `id` int unsigned NOT NULL AUTO_INCREMENT, `start` datetime DEFAULT NULL, `end` datetime DEFAULT NULL, `title` varchar(200) DEFAULT NULL, `excerpt` longtext, `content` longtext, - `modified_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `modified_by` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', `status` varchar(40) DEFAULT NULL, `program` varchar(40) DEFAULT NULL, `series_name` varchar(40) DEFAULT NULL, `image` varchar(200) DEFAULT NULL, `location` varchar(100) DEFAULT NULL, + `modified_by` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + `modified_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `title` (`title`), KEY `start` (`start`), KEY `end` (`end`), KEY `location` (`location`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb3; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -936,21 +1449,21 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `calcms_user_roles`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!50503 SET character_set_client = utf8mb4 */; CREATE TABLE `calcms_user_roles` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `user_id` int(10) unsigned NOT NULL, - `role_id` int(10) unsigned NOT NULL, - `studio_id` int(10) unsigned NOT NULL DEFAULT '0', + `id` int unsigned NOT NULL AUTO_INCREMENT, + `project_id` int unsigned NOT NULL, + `studio_id` int unsigned NOT NULL DEFAULT '0', + `user_id` int unsigned NOT NULL, + `role_id` int unsigned NOT NULL, `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `modified_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `project_id` int(10) unsigned NOT NULL, PRIMARY KEY (`id`) USING BTREE, - KEY `user_id` (`user_id`), - KEY `role_id` (`role_id`), + KEY `project_id` (`project_id`), KEY `studio_id` (`studio_id`), - KEY `project_id` (`project_id`) -) ENGINE=MyISAM AUTO_INCREMENT=261 DEFAULT CHARSET=utf8; + KEY `user_id` (`user_id`), + KEY `role_id` (`role_id`) +) ENGINE=MyISAM AUTO_INCREMENT=745 DEFAULT CHARSET=utf8mb3; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -959,33 +1472,69 @@ CREATE TABLE `calcms_user_roles` ( LOCK TABLES `calcms_user_roles` WRITE; /*!40000 ALTER TABLE `calcms_user_roles` DISABLE KEYS */; -INSERT INTO `calcms_user_roles` VALUES (1,4,7,1,NULL,'2013-04-14 11:06:38',1); +INSERT INTO `calcms_user_roles` (`id`, `project_id`, `studio_id`, `user_id`, `role_id`, `created_at`, `modified_at`) VALUES (47,1,1,4,7,NULL,'2013-04-14 13:06:38'); +INSERT INTO `calcms_user_roles` (`id`, `project_id`, `studio_id`, `user_id`, `role_id`, `created_at`, `modified_at`) VALUES (48,1,1,4,3,NULL,'2013-04-14 13:06:38'); +INSERT INTO `calcms_user_roles` (`id`, `project_id`, `studio_id`, `user_id`, `role_id`, `created_at`, `modified_at`) VALUES (66,1,1,4,1,NULL,'2013-04-14 13:06:38'); /*!40000 ALTER TABLE `calcms_user_roles` ENABLE KEYS */; UNLOCK TABLES; +-- +-- Table structure for table `calcms_user_selected_events` +-- + +DROP TABLE IF EXISTS `calcms_user_selected_events`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `calcms_user_selected_events` ( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `project_id` int unsigned DEFAULT NULL, + `studio_id` int unsigned DEFAULT NULL, + `series_id` int unsigned DEFAULT NULL, + `user` varchar(45) NOT NULL, + `filter_project_studio` int unsigned DEFAULT NULL, + `filter_series` int unsigned DEFAULT NULL, + `selected_project` int unsigned DEFAULT NULL, + `selected_studio` int unsigned DEFAULT NULL, + `selected_series` int unsigned DEFAULT NULL, + `selected_event` int unsigned DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `unique` (`user`,`project_id`,`studio_id`,`series_id`,`filter_project_studio`,`filter_series`), + KEY `user` (`user`,`project_id`,`studio_id`,`series_id`) +) ENGINE=InnoDB AUTO_INCREMENT=136 DEFAULT CHARSET=utf8mb3; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `calcms_user_selected_events` +-- + +LOCK TABLES `calcms_user_selected_events` WRITE; +/*!40000 ALTER TABLE `calcms_user_selected_events` DISABLE KEYS */; +/*!40000 ALTER TABLE `calcms_user_selected_events` ENABLE KEYS */; +UNLOCK TABLES; + -- -- Table structure for table `calcms_user_series` -- DROP TABLE IF EXISTS `calcms_user_series`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!50503 SET character_set_client = utf8mb4 */; CREATE TABLE `calcms_user_series` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `user_id` int(10) unsigned NOT NULL, - `series_id` int(10) unsigned NOT NULL, + `id` int unsigned NOT NULL AUTO_INCREMENT, + `project_id` int unsigned NOT NULL, + `studio_id` int unsigned NOT NULL, + `series_id` int unsigned NOT NULL, + `user_id` int unsigned NOT NULL, `active` char(1) NOT NULL, `modified_by` varchar(100) DEFAULT NULL, `modified_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `studio_id` int(10) unsigned NOT NULL, - `project_id` int(10) unsigned NOT NULL, PRIMARY KEY (`id`), - KEY `user_id` (`user_id`), - KEY `series_id` (`series_id`), - KEY `active` (`active`), + KEY `project_id` (`project_id`), KEY `studio_id` (`studio_id`), - KEY `project_id` (`project_id`) -) ENGINE=MyISAM AUTO_INCREMENT=216 DEFAULT CHARSET=utf8; + KEY `series_id` (`series_id`), + KEY `user_id` (`user_id`), + KEY `active` (`active`) +) ENGINE=MyISAM AUTO_INCREMENT=1019 DEFAULT CHARSET=utf8mb3; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -994,26 +1543,63 @@ CREATE TABLE `calcms_user_series` ( LOCK TABLES `calcms_user_series` WRITE; /*!40000 ALTER TABLE `calcms_user_series` DISABLE KEYS */; +INSERT INTO `calcms_user_series` (`id`, `project_id`, `studio_id`, `series_id`, `user_id`, `active`, `modified_by`, `modified_at`) VALUES (800,1,1,1,4,'','ccAdmin','2023-02-19 20:15:03'); /*!40000 ALTER TABLE `calcms_user_series` ENABLE KEYS */; UNLOCK TABLES; +-- +-- Table structure for table `calcms_user_sessions` +-- + +DROP TABLE IF EXISTS `calcms_user_sessions`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `calcms_user_sessions` ( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `session_id` varchar(64) NOT NULL, + `user` varchar(30) NOT NULL, + `start` timestamp NULL DEFAULT CURRENT_TIMESTAMP, + `end` timestamp NULL DEFAULT NULL, + `expires_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + `timeout` int unsigned NOT NULL, + `pid` int unsigned NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `id_UNIQUE` (`id`), + UNIQUE KEY `session_id_UNIQUE` (`session_id`), + KEY `user` (`user`), + KEY `session_id` (`session_id`) +) ENGINE=InnoDB AUTO_INCREMENT=4896 DEFAULT CHARSET=utf8mb3; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `calcms_user_sessions` +-- + +LOCK TABLES `calcms_user_sessions` WRITE; +/*!40000 ALTER TABLE `calcms_user_sessions` DISABLE KEYS */; +INSERT INTO `calcms_user_sessions` (`id`, `session_id`, `user`, `start`, `end`, `expires_at`, `timeout`, `pid`) VALUES (4895,'f2633a9294c6d3841dc4c98bba61b94a','ccAdmin','2023-02-19 20:53:39','2023-02-19 21:49:53','2023-02-19 23:49:20',7200,37487); +/*!40000 ALTER TABLE `calcms_user_sessions` ENABLE KEYS */; +UNLOCK TABLES; + -- -- Table structure for table `calcms_user_settings` -- DROP TABLE IF EXISTS `calcms_user_settings`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!50503 SET character_set_client = utf8mb4 */; CREATE TABLE `calcms_user_settings` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `user` varchar(20) CHARACTER SET latin1 NOT NULL, + `id` int unsigned NOT NULL AUTO_INCREMENT, + `project_id` int unsigned DEFAULT NULL, + `studio_id` int unsigned DEFAULT NULL, + `user` varchar(20) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL, `colors` longtext NOT NULL, `language` varchar(3) DEFAULT 'de', `period` varchar(16) DEFAULT 'month', - `calendar_fontsize` smallint(5) unsigned DEFAULT '12', + `calendar_fontsize` smallint unsigned DEFAULT '12', PRIMARY KEY (`id`,`user`) USING BTREE, KEY `user` (`user`) -) ENGINE=MyISAM AUTO_INCREMENT=28 DEFAULT CHARSET=utf8; +) ENGINE=MyISAM AUTO_INCREMENT=49 DEFAULT CHARSET=utf8mb3; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -1022,7 +1608,7 @@ CREATE TABLE `calcms_user_settings` ( LOCK TABLES `calcms_user_settings` WRITE; /*!40000 ALTER TABLE `calcms_user_settings` DISABLE KEYS */; -INSERT INTO `calcms_user_settings` VALUES (27,'ccAdmin','#content .event=#eeeeee\n#content .schedule=#aaaaaa\n#content .event.published=#88ff88\n#content .event.no_series=#aa8822\n#content .event.marked=#0066aa\n#content.conflicts .event.error=#ff0000\n#content.conflicts .schedule.error=#ee4422\n#content .work=#cc00cc','en','month',12); +INSERT INTO `calcms_user_settings` (`id`, `project_id`, `studio_id`, `user`, `colors`, `language`, `period`, `calendar_fontsize`) VALUES (5,1,1,'ccAdmin','#content .event=#c5e1a5\n#content .draft=#eeeeee\n#content .schedule=#dde4e6\n#content .event.published=#a5d6a7\n#content .event.no_series=#fff59d\n#content .event.marked=#81d4fa\n#content.conflicts .event.error=#ffab91\n#content.conflicts .schedule.error=#ffcc80\n#content .work=#b39ddb\n#content .play=#90caf9','en','14',12); /*!40000 ALTER TABLE `calcms_user_settings` ENABLE KEYS */; UNLOCK TABLES; @@ -1032,22 +1618,24 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `calcms_user_stats`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!50503 SET character_set_client = utf8mb4 */; CREATE TABLE `calcms_user_stats` ( - `project_id` int(10) unsigned NOT NULL, - `studio_id` int(10) unsigned NOT NULL, - `series_id` int(10) unsigned NOT NULL DEFAULT '0', + `project_id` int unsigned NOT NULL, + `studio_id` int unsigned NOT NULL, + `series_id` int unsigned NOT NULL DEFAULT '0', `user` varchar(32) NOT NULL, `modified_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `create_events` int(10) unsigned DEFAULT '0', - `update_events` int(10) unsigned DEFAULT '0', - `delete_events` int(10) unsigned DEFAULT '0', - `schedule_event` int(10) unsigned DEFAULT '0', - `create_series` int(10) unsigned DEFAULT '0', - `update_series` int(10) unsigned DEFAULT '0', - `delete_series` int(10) unsigned DEFAULT '0', + `create_events` int unsigned DEFAULT '0', + `update_events` int unsigned DEFAULT '0', + `delete_events` int unsigned DEFAULT '0', + `schedule_event` int unsigned DEFAULT '0', + `create_series` int unsigned DEFAULT '0', + `update_series` int unsigned DEFAULT '0', + `delete_series` int unsigned DEFAULT '0', + `upload_file` int unsigned DEFAULT '0', + `download_file` int unsigned DEFAULT '0', PRIMARY KEY (`project_id`,`studio_id`,`series_id`,`user`) USING BTREE -) ENGINE=MyISAM DEFAULT CHARSET=utf8; +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb3; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -1056,6 +1644,7 @@ CREATE TABLE `calcms_user_stats` ( LOCK TABLES `calcms_user_stats` WRITE; /*!40000 ALTER TABLE `calcms_user_stats` DISABLE KEYS */; +INSERT INTO `calcms_user_stats` (`project_id`, `studio_id`, `series_id`, `user`, `modified_at`, `create_events`, `update_events`, `delete_events`, `schedule_event`, `create_series`, `update_series`, `delete_series`, `upload_file`, `download_file`) VALUES (1,1,1,'ccAdmin','2023-02-19 21:33:05',0,0,0,0,0,1,0,0,0); /*!40000 ALTER TABLE `calcms_user_stats` ENABLE KEYS */; UNLOCK TABLES; @@ -1065,23 +1654,24 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `calcms_users`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!50503 SET character_set_client = utf8mb4 */; CREATE TABLE `calcms_users` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `id` int unsigned NOT NULL AUTO_INCREMENT, `name` varchar(30) NOT NULL, `full_name` varchar(30) DEFAULT NULL, - `salt` varchar(32) NOT NULL, - `pass` varchar(100) NOT NULL, `email` varchar(300) NOT NULL, - `modified_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, - `disabled` int(10) unsigned DEFAULT '0', - `session_timeout` int(10) unsigned NOT NULL DEFAULT '120', + `pass` varchar(100) NOT NULL, + `salt` varchar(32) NOT NULL, + `disabled` int unsigned DEFAULT '0', + `session_timeout` int unsigned NOT NULL DEFAULT '120', `created_by` varchar(30) DEFAULT NULL, - PRIMARY KEY (`id`), + `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, + `modified_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`) USING BTREE, UNIQUE KEY `name` (`name`), + UNIQUE KEY `email` (`email`) USING BTREE, KEY `disabled` (`disabled`) -) ENGINE=MyISAM AUTO_INCREMENT=73 DEFAULT CHARSET=utf8; +) ENGINE=MyISAM AUTO_INCREMENT=260 DEFAULT CHARSET=utf8mb3; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -1090,7 +1680,7 @@ CREATE TABLE `calcms_users` ( LOCK TABLES `calcms_users` WRITE; /*!40000 ALTER TABLE `calcms_users` DISABLE KEYS */; -INSERT INTO `calcms_users` VALUES (4,'ccAdmin','Admin','Edt6Gt8VQk/pXQ1uWRZ8pu','$2a$08$Edt6Gt8VQk/pXQ1uWRZ8pu/KIe/qVFP/lYkbS64/D8URYEm6KshIG','info@localhost','2014-12-23 13:46:06',NULL,0,60,NULL); +INSERT INTO `calcms_users` (`id`, `name`, `full_name`, `email`, `pass`, `salt`, `disabled`, `session_timeout`, `created_by`, `created_at`, `modified_at`) VALUES (4,'ccAdmin','ccAdmin','mc@radiopiloten.de','$2a$08$oLiwMC1vYD8ZzfjKdpTG3OBFAXbiKslWIe0w005ysdxO0kE/A/12G','oLiwMC1vYD8ZzfjKdpTG3O',0,120,NULL,NULL,'2021-12-10 15:43:48'); /*!40000 ALTER TABLE `calcms_users` ENABLE KEYS */; UNLOCK TABLES; @@ -1100,11 +1690,11 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `calcms_work_dates`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!50503 SET character_set_client = utf8mb4 */; CREATE TABLE `calcms_work_dates` ( - `schedule_id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `project_id` int(10) unsigned NOT NULL, - `studio_id` int(10) unsigned NOT NULL, + `schedule_id` int unsigned NOT NULL AUTO_INCREMENT, + `project_id` int unsigned NOT NULL, + `studio_id` int unsigned NOT NULL, `start` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', `end` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', `start_date` date NOT NULL, @@ -1120,7 +1710,7 @@ CREATE TABLE `calcms_work_dates` ( KEY `schedule_id` (`schedule_id`), KEY `start_date` (`start_date`), KEY `end_date` (`end_date`) -) ENGINE=MyISAM AUTO_INCREMENT=18 DEFAULT CHARSET=utf8; +) ENGINE=MyISAM AUTO_INCREMENT=25 DEFAULT CHARSET=utf8mb3; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -1138,27 +1728,27 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `calcms_work_schedule`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!50503 SET character_set_client = utf8mb4 */; CREATE TABLE `calcms_work_schedule` ( - `schedule_id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `project_id` int(10) unsigned NOT NULL, - `studio_id` int(10) unsigned NOT NULL, + `schedule_id` int unsigned NOT NULL AUTO_INCREMENT, + `project_id` int unsigned NOT NULL, + `studio_id` int unsigned NOT NULL, `start` datetime NOT NULL, `end` date DEFAULT NULL, - `frequency` int(10) unsigned DEFAULT NULL, - `duration` int(10) unsigned DEFAULT NULL, - `exclude` tinyint(1) unsigned DEFAULT NULL, - `weekday` int(10) unsigned DEFAULT NULL, - `week_of_month` int(10) unsigned DEFAULT NULL, + `frequency` int unsigned DEFAULT NULL, + `duration` int unsigned DEFAULT NULL, + `exclude` tinyint unsigned DEFAULT NULL, + `weekday` int unsigned DEFAULT NULL, + `week_of_month` int unsigned DEFAULT NULL, `period_type` varchar(16) DEFAULT NULL, - `month` int(10) unsigned NOT NULL, + `month` int unsigned NOT NULL, `type` varchar(32) NOT NULL, `title` varchar(200) NOT NULL, PRIMARY KEY (`schedule_id`), KEY `project_id` (`project_id`), KEY `studio_id` (`studio_id`), KEY `type` (`type`) -) ENGINE=MyISAM AUTO_INCREMENT=18 DEFAULT CHARSET=utf8; +) ENGINE=MyISAM AUTO_INCREMENT=25 DEFAULT CHARSET=utf8mb3; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -1179,4 +1769,4 @@ UNLOCK TABLES; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2018-01-14 17:23:51 +-- Dump completed on 2023-02-19 23:01:42 \ No newline at end of file diff --git a/install/init.sql b/install/init.sql new file mode 100644 index 0000000..6d578d6 --- /dev/null +++ b/install/init.sql @@ -0,0 +1,17 @@ +--- Create DBs +CREATE DATABASE IF NOT EXISTS calcms; +CREATE DATABASE IF NOT EXISTS calcms_test; + +--- Create admin user +CREATE USER IF NOT EXISTS 'calcms_admin'@'localhost' IDENTIFIED BY 'caladmin000'; +GRANT ALL PRIVILEGES ON calcms.* TO 'calcms_admin'@'localhost'; +GRANT ALL PRIVILEGES ON calcms_test.* TO 'calcms_admin'@'localhost'; +--- Create write user +CREATE USER IF NOT EXISTS 'calcms_write'@'localhost' IDENTIFIED BY 'calwrite000'; +GRANT SELECT, INSERT, UPDATE, DELETE ON calcms.* TO 'calcms_write'@'localhost'; +GRANT ALL PRIVILEGES ON calcms_test.* TO 'calcms_write'@'localhost'; +--- Create read user +CREATE USER IF NOT EXISTS 'calcms_read'@'localhost' IDENTIFIED BY 'calread000'; +GRANT SELECT ON calcms.* TO 'calcms_read'@'localhost'; +GRANT ALL PRIVILEGES ON calcms_test.* TO 'calcms_read'@'localhost'; + diff --git a/install/migrate.sql b/install/migrate.sql index a03e086..634d81a 100644 --- a/install/migrate.sql +++ b/install/migrate.sql @@ -94,4 +94,197 @@ ALTER TABLE `calcms_events` ALTER TABLE `calcms_users` CHANGE COLUMN email email varchar(300) NOT NULL; + +ALTER TABLE `calcms_events` ADD COLUMN `series_image` VARCHAR(200) DEFAULT NULL AFTER `draft`; + +ALTER TABLE `calcms_events` ADD COLUMN `image_label` VARCHAR(200) DEFAULT NULL AFTER `series_image`, + ADD COLUMN `series_image_label` VARCHAR(200) DEFAULT NULL AFTER `image_label`; + +ALTER TABLE `calcms_playout` + CHANGE COLUMN `modified_at` `modified_at` datetime DEFAULT CURRENT_TIMESTAMP; + +ALTER TABLE `calcms_images` + ADD COLUMN public tinyint(1) unsigned NULL DEFAULT '0', + ADD COLUMN licence varchar(300) NULL AFTER project_id; + +ALTER TABLE `calcms_event_history` + CHANGE COLUMN draft draft tinyint(1) unsigned NOT NULL DEFAULT '0', + ADD COLUMN series_image_label varchar(200) NULL, + ADD COLUMN series_image varchar(200) NULL AFTER draft, + ADD COLUMN recurrence_count int(10) unsigned NOT NULL DEFAULT '0' AFTER project_id, + ADD COLUMN image_label varchar(200) NULL; + +-- 2018-06-18 refactor columns + +ALTER TABLE `calcms_audio_recordings` +CHANGE COLUMN `created_by` `created_by` VARCHAR(100) NOT NULL AFTER `processed`, +CHANGE COLUMN `created_at` `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP AFTER `created_by`; + +ALTER TABLE `calcms_events` +CHANGE COLUMN `program` `program` VARCHAR(40) NULL DEFAULT NULL AFTER `end`, +CHANGE COLUMN `series_name` `series_name` VARCHAR(40) NULL DEFAULT NULL AFTER `program`, +CHANGE COLUMN `episode` `episode` INT(10) UNSIGNED NULL DEFAULT NULL AFTER `title`, +CHANGE COLUMN `html_content` `html_content` LONGTEXT NULL DEFAULT NULL AFTER `content`, +CHANGE COLUMN `end_date` `end_date` DATE NOT NULL AFTER `start_date`, +CHANGE COLUMN `archive_url` `archive_url` VARCHAR(300) NULL DEFAULT NULL AFTER `podcast_url`, +CHANGE COLUMN `html_topic` `html_topic` LONGTEXT NULL DEFAULT NULL AFTER `user_excerpt`, +CHANGE COLUMN `draft` `draft` TINYINT(1) UNSIGNED NOT NULL DEFAULT '0' AFTER `archived`, +CHANGE COLUMN `recurrence` `recurrence` INT(11) NULL DEFAULT '0' AFTER `recurrence_count`, +CHANGE COLUMN `image` `image` VARCHAR(200) NULL DEFAULT NULL AFTER `recurrence`, +CHANGE COLUMN `image_label` `image_label` VARCHAR(200) NULL DEFAULT NULL AFTER `image`, +CHANGE COLUMN `created_at` `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP AFTER `series_image_label`, +CHANGE COLUMN `modified_by` `modified_by` VARCHAR(20) NULL DEFAULT NULL AFTER `created_at`, +CHANGE COLUMN `modified_at` `modified_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP AFTER `modified_by`, +CHANGE COLUMN `reference` `reference` VARCHAR(300) NULL DEFAULT NULL AFTER `modified_at`, +CHANGE COLUMN `disable_event_sync` `disable_event_sync` TINYINT(1) UNSIGNED NULL DEFAULT NULL AFTER `reference`; + +ALTER TABLE `calcms_images` +CHANGE COLUMN `project_id` `project_id` INT(10) UNSIGNED NOT NULL AFTER `id`, +CHANGE COLUMN `studio_id` `studio_id` INT(10) UNSIGNED NULL DEFAULT NULL AFTER `project_id`, +CHANGE COLUMN `filename` `filename` VARCHAR(64) NOT NULL AFTER `studio_id`, +CHANGE COLUMN `name` `name` VARCHAR(300) NULL DEFAULT NULL AFTER `filename`, +CHANGE COLUMN `licence` `licence` VARCHAR(300) NULL DEFAULT NULL AFTER `description`, +CHANGE COLUMN `public` `public` TINYINT(1) UNSIGNED NULL DEFAULT '0' AFTER `licence`, +CHANGE COLUMN `created_at` `created_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP AFTER `modified_by`; + +ALTER TABLE `calcms_roles` +CHANGE COLUMN `project_id` `project_id` TINYINT(1) UNSIGNED NOT NULL AFTER `id`, +CHANGE COLUMN `studio_id` `studio_id` INT(10) UNSIGNED NOT NULL AFTER `project_id`, +CHANGE COLUMN `level` `level` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0' AFTER `role`, +CHANGE COLUMN `read_role` `read_role` TINYINT(1) UNSIGNED NULL DEFAULT NULL AFTER `level`, +CHANGE COLUMN `update_role` `update_role` TINYINT(1) UNSIGNED NULL DEFAULT NULL AFTER `read_role`, +CHANGE COLUMN `read_user_role` `read_user_role` TINYINT(1) UNSIGNED NULL DEFAULT NULL AFTER `update_role`, +CHANGE COLUMN `delete_user` `delete_user` TINYINT(1) UNSIGNED NULL DEFAULT NULL AFTER `update_user`, +CHANGE COLUMN `update_user_role` `update_user_role` TINYINT(1) UNSIGNED NULL DEFAULT NULL AFTER `delete_user`, +CHANGE COLUMN `create_project` `create_project` TINYINT(1) UNSIGNED NOT NULL AFTER `disable_user`, +CHANGE COLUMN `read_project` `read_project` TINYINT(1) UNSIGNED NOT NULL AFTER `create_project`, +CHANGE COLUMN `update_project` `update_project` TINYINT(1) UNSIGNED NOT NULL AFTER `read_project`, +CHANGE COLUMN `delete_project` `delete_project` TINYINT(1) UNSIGNED NOT NULL AFTER `update_project`, +CHANGE COLUMN `assign_project_studio` `assign_project_studio` TINYINT(1) UNSIGNED NOT NULL AFTER `delete_project`, +CHANGE COLUMN `create_studio` `create_studio` TINYINT(1) UNSIGNED NOT NULL AFTER `assign_project_studio`, +CHANGE COLUMN `read_studio` `read_studio` TINYINT(1) UNSIGNED NOT NULL AFTER `create_studio`, +CHANGE COLUMN `delete_studio` `delete_studio` TINYINT(1) UNSIGNED NOT NULL AFTER `update_studio`, +CHANGE COLUMN `read_studio_timeslot_schedule` `read_studio_timeslot_schedule` TINYINT(1) UNSIGNED NOT NULL AFTER `delete_studio`, +CHANGE COLUMN `update_studio_timeslot_schedule` `update_studio_timeslot_schedule` TINYINT(1) UNSIGNED NOT NULL AFTER `read_studio_timeslot_schedule`, +CHANGE COLUMN `update_series_template` `update_series_template` TINYINT(1) UNSIGNED NOT NULL AFTER `delete_series`, +CHANGE COLUMN `assign_series_member` `assign_series_member` TINYINT(1) UNSIGNED NOT NULL AFTER `update_series_template`, +CHANGE COLUMN `remove_series_member` `remove_series_member` TINYINT(1) UNSIGNED NOT NULL AFTER `assign_series_member`, +CHANGE COLUMN `scan_series_events` `scan_series_events` TINYINT(1) UNSIGNED NOT NULL AFTER `remove_series_member`, +CHANGE COLUMN `assign_series_events` `assign_series_events` TINYINT(1) UNSIGNED NOT NULL AFTER `scan_series_events`, +CHANGE COLUMN `read_schedule` `read_schedule` TINYINT(1) UNSIGNED NOT NULL AFTER `assign_series_events`, +CHANGE COLUMN `update_schedule` `update_schedule` TINYINT(1) UNSIGNED NOT NULL AFTER `read_schedule`, +CHANGE COLUMN `delete_schedule` `delete_schedule` TINYINT(1) UNSIGNED NOT NULL AFTER `update_schedule`, +CHANGE COLUMN `create_event_from_schedule` `create_event_from_schedule` TINYINT(1) UNSIGNED NOT NULL AFTER `create_event`, +CHANGE COLUMN `create_event_of_series` `create_event_of_series` TINYINT(1) UNSIGNED NOT NULL AFTER `create_event_from_schedule`, +CHANGE COLUMN `update_event_after_week` `update_event_after_week` TINYINT(1) UNSIGNED NOT NULL AFTER `update_event_time`, +CHANGE COLUMN `update_event_field_title` `update_event_field_title` TINYINT(1) UNSIGNED NOT NULL AFTER `update_event_after_week`, +CHANGE COLUMN `update_event_field_title_extension` `update_event_field_title_extension` TINYINT(1) UNSIGNED NOT NULL AFTER `update_event_field_title`, +CHANGE COLUMN `update_event_field_excerpt` `update_event_field_excerpt` TINYINT(1) UNSIGNED NOT NULL AFTER `update_event_field_title_extension`, +CHANGE COLUMN `update_event_field_description` `update_event_field_description` TINYINT(1) UNSIGNED NOT NULL AFTER `update_event_field_content`, +CHANGE COLUMN `update_event_field_topic` `update_event_field_topic` TINYINT(1) UNSIGNED NOT NULL AFTER `update_event_field_description`, +CHANGE COLUMN `update_event_field_episode` `update_event_field_episode` TINYINT(1) UNSIGNED NOT NULL AFTER `update_event_field_topic`, +CHANGE COLUMN `update_event_field_excerpt_extension` `update_event_field_excerpt_extension` TINYINT(1) UNSIGNED NOT NULL AFTER `update_event_field_episode`, +CHANGE COLUMN `update_event_field_image` `update_event_field_image` TINYINT(1) UNSIGNED NOT NULL AFTER `update_event_field_excerpt_extension`, +CHANGE COLUMN `update_event_field_podcast_url` `update_event_field_podcast_url` TINYINT(1) UNSIGNED NOT NULL AFTER `update_event_field_image`, +CHANGE COLUMN `update_event_field_archive_url` `update_event_field_archive_url` TINYINT(1) UNSIGNED NOT NULL AFTER `update_event_field_podcast_url`, +CHANGE COLUMN `update_event_status_draft` `update_event_status_draft` TINYINT(1) UNSIGNED NOT NULL AFTER `update_event_status_rerun`, +CHANGE COLUMN `update_event_status_live` `update_event_status_live` TINYINT(1) UNSIGNED NOT NULL AFTER `update_event_status_draft`, +CHANGE COLUMN `update_event_status_playout` `update_event_status_playout` TINYINT(1) UNSIGNED NOT NULL AFTER `update_event_status_live`, +CHANGE COLUMN `update_event_status_archived` `update_event_status_archived` TINYINT(1) UNSIGNED NOT NULL AFTER `update_event_status_playout`, +CHANGE COLUMN `create_image` `create_image` TINYINT(1) UNSIGNED NOT NULL AFTER `update_event_status_archived`, +CHANGE COLUMN `update_image_own` `update_image_own` TINYINT(1) UNSIGNED NOT NULL AFTER `create_image`, +CHANGE COLUMN `created_at` `created_at` TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP AFTER `read_playout`, +CHANGE COLUMN `create_download` `create_download` TINYINT(1) UNSIGNED NOT NULL AFTER `created_at`, +CHANGE COLUMN `modified_at` `modified_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP AFTER `create_download`; + +ALTER TABLE `calcms_series_dates` +CHANGE COLUMN `project_id` `project_id` INT(10) UNSIGNED NOT NULL AFTER `id`, +CHANGE COLUMN `studio_id` `studio_id` INT(10) UNSIGNED NOT NULL AFTER `project_id`; + +ALTER TABLE `calcms_series_events` +CHANGE COLUMN `project_id` `project_id` INT(10) UNSIGNED NOT NULL FIRST, +CHANGE COLUMN `studio_id` `studio_id` INT(12) UNSIGNED NOT NULL AFTER `project_id`; + +ALTER TABLE `calcms_series_schedule` +CHANGE COLUMN `project_id` `project_id` INT(10) UNSIGNED NOT NULL DEFAULT '1' AFTER `id`, +CHANGE COLUMN `studio_id` `studio_id` INT(10) UNSIGNED NULL DEFAULT NULL AFTER `project_id`; + +ALTER TABLE `calcms_studios` +CHANGE COLUMN `image` `image` VARCHAR(200) NOT NULL AFTER `stream`; + +ALTER TABLE `calcms_studio_timeslot_dates` +CHANGE COLUMN `project_id` `project_id` INT(10) UNSIGNED NOT NULL FIRST, +CHANGE COLUMN `schedule_id` `schedule_id` INT(10) UNSIGNED NOT NULL AFTER `studio_id`, +DROP PRIMARY KEY, +ADD PRIMARY KEY USING BTREE (`project_id`, `studio_id`, `start`, `end`); + +ALTER TABLE `calcms_studio_timeslot_schedule` +CHANGE COLUMN `project_id` `project_id` INT(10) UNSIGNED NOT NULL AFTER `id`; + +ALTER TABLE `calcms_user_events` +CHANGE COLUMN `modified_by` `modified_by` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `location`, +CHANGE COLUMN `modified_at` `modified_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP AFTER `modified_by`; + +ALTER TABLE `calcms_user_roles` +CHANGE COLUMN `project_id` `project_id` INT(10) UNSIGNED NOT NULL AFTER `id`, +CHANGE COLUMN `studio_id` `studio_id` INT(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `project_id`; + +ALTER TABLE `calcms_users` +CHANGE COLUMN `email` `email` VARCHAR(300) NOT NULL AFTER `full_name`, +CHANGE COLUMN `pass` `pass` VARCHAR(100) NOT NULL AFTER `email`, +CHANGE COLUMN `created_at` `created_at` TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP AFTER `created_by`, +CHANGE COLUMN `modified_at` `modified_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP AFTER `created_at`; + +ALTER TABLE `calcms_user_series` +CHANGE COLUMN `project_id` `project_id` INT(10) UNSIGNED NOT NULL AFTER `id`, +CHANGE COLUMN `studio_id` `studio_id` INT(10) UNSIGNED NOT NULL AFTER `project_id`; + +ALTER TABLE `calcms_user_stats` +ADD COLUMN `upload_file` INT(10) UNSIGNED NULL DEFAULT 0 AFTER `delete_series`, +ADD COLUMN `download_file` INT(10) UNSIGNED NULL DEFAULT 0 AFTER `upload_file`; + +ALTER TABLE `calcms_user_settings` +ADD COLUMN `project_id` INT(10) UNSIGNED NULL AFTER `calendar_fontsize`, +ADD COLUMN `studio_id` INT(10) UNSIGNED NULL AFTER `project_id`; + +ALTER TABLE `calcms_series` +ADD COLUMN `predecessor_id` INT(10) NULL AFTER `has_single_events`; + +CREATE TABLE `calcms_user_default_studios` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `user` VARCHAR(50) NOT NULL, + `project_id` INT(11) NOT NULL, + `studio_id` INT(11) NOT NULL, + PRIMARY KEY (`id`), + INDEX `user` (`user` ASC)); + + +ALTER TABLE `calcms_series` +ADD COLUMN `content_format` VARCHAR(45) NULL AFTER `predecessor_id`; + +ALTER TABLE `calcms_events` +ADD COLUMN `content_format` VARCHAR(45) NULL DEFAULT NULL AFTER `disable_event_sync`; + +ALTER TABLE `calcms_roles` +ADD COLUMN `update_event_field_content_format` TINYINT(1) UNSIGNED NOT NULL AFTER `modified_at`; + +ALTER TABLE `calcms_events` +ADD COLUMN `listen_key` VARCHAR(100) NULL; + +ALTER TABLE `calcms_audio_recordings` +ADD COLUMN `active` TINYINT(1) NOT NULL DEFAULT 0 AFTER `event_id`; + +ALTER TABLE `calcms`.`calcms_audio_recordings` +ADD INDEX `active_index` (`active`); + +ALTER TABLE `calcms`.`calcms_events` +DROP COLUMN `category_count`, +DROP COLUMN `category`, +DROP INDEX `category` ; +; +ALTER TABLE `calcms`.`calcms_event_history` +DROP COLUMN `category_count`, +DROP COLUMN `category`, +DROP INDEX `category` ; +; diff --git a/lib/calcms/ListenerAccess.pm b/lib/calcms/ListenerAccess.pm new file mode 100644 index 0000000..d109d8d --- /dev/null +++ b/lib/calcms/ListenerAccess.pm @@ -0,0 +1,54 @@ +package ListenerAccess; + +use strict; +use warnings; + +use Data::Dumper; +use File::Basename; +use Time::Local(); + +use Apache2::RequestRec (); +use Apache2::Connection (); +use Apache2::Const -compile => qw(FORBIDDEN OK); + +sub handler { + my $r = shift; + + my $DAYS = 24 * 60 * 60; + my $OK = Apache2::Const::OK; + my $FORBIDDEN = Apache2::Const::FORBIDDEN; + + my $path = $ENV{LISTENER_DIR} . File::Basename::basename( $r->uri() ); + my $file = readlink $path; + + # granted access by temporary symlinks only + return $FORBIDDEN unless ($file); + + # use link age for authorized downloads + if (File::Basename::basename($path) =~ /^shared\-/) { + my $age = time() - (lstat($path))[9]; + return ( $age > 7 * $DAYS ) ? $FORBIDDEN : $OK; + } + + # use age from file name for public access + return $FORBIDDEN unless + File::Basename::basename($file) =~ /(\d\d\d\d)\-(\d\d)\-(\d\d) (\d\d)_(\d\d)/; + + my $age = time() - Time::Local::timelocal( 0, $5, $4, $3, $2 - 1, $1 ); + return ( $age > 7 * $DAYS ) ? $FORBIDDEN : $OK; +} +1; + +__END__ + +# limit access up to 7 days after datetime given by filename. +# The filename links to a file starting with "yyyy-mm-dd hh_mm" in file name. +# +# Access to links starting with "shared-" are allowed up to 7 days after creation. +# +# +# PerlSetEnv PERL5LIB ${perl_lib}/calcms +# PerlSetEnv LISTENER_DIR ${archive_dir}/${domain}/ +# PerlAccessHandler ListenerAccess +# +# diff --git a/lib/calcms/UTF8DBI.pm b/lib/calcms/UTF8DBI.pm deleted file mode 100644 index 2d070d4..0000000 --- a/lib/calcms/UTF8DBI.pm +++ /dev/null @@ -1,45 +0,0 @@ -# UTF8DBI.pm re-implementation by Pavel Kudinov http://search.cpan.org/~kudinov/ -# originally from: http://dysphoria.net/code/perl-utf8/ -# And patched again by Andrew Forrest, Jan 2007 - -use DBI 1.21; -use utf8; -use Encode; - -package UTF8DBI; use base DBI; -sub _utf8_ { - if (ref $_ eq 'ARRAY') { _utf8_() foreach @$_ } - elsif (ref $_ eq 'HASH' ) { _utf8_() foreach values %$_ } - else { - Encode::_utf8_on($_); - if (Encode::is_utf8($_) && ! Encode::is_utf8($_, 1)) { - #$_ = '⁂malformed-UTF8‼' #die "Malformed utf8 string in database" - #print data_string_desc($_)."\n" - #data_string_desc(STRING); - #Encode::decode_utf8($_); - #; - #Encode::_utf8_off($_); - #Encode::decode_utf8($_); - #Encode::encode_utf8($_); - } - }; - $_; -}; - - -package UTF8DBI::db; use base DBI::db; - -sub selectrow_arrayref { return UTF8DBI::_utf8_ for shift->SUPER::selectrow_arrayref(@_) }; -sub selectrow_hashref { return UTF8DBI::_utf8_ for shift->SUPER::selectrow_hashref (@_) }; -sub selectall_arrayref { return UTF8DBI::_utf8_ for shift->SUPER::selectall_arrayref(@_) }; -sub selectall_hashref { return UTF8DBI::_utf8_ for shift->SUPER::selectall_hashref (@_) }; -sub selectcol_arrayref { return UTF8DBI::_utf8_ for shift->SUPER::selectcol_arrayref(@_) }; - -sub selectrow_array { @{shift->selectrow_arrayref(@_)} }; - - -package UTF8DBI::st; use base DBI::st; - -sub fetch { return UTF8DBI::_utf8_ for shift->SUPER::fetch (@_) }; - -1; diff --git a/lib/calcms/aggregator.pm b/lib/calcms/aggregator.pm index ec21f82..95f6b9f 100644 --- a/lib/calcms/aggregator.pm +++ b/lib/calcms/aggregator.pm @@ -1,64 +1,53 @@ -use warnings "all"; -use strict; -use events; -use comments; -use calendar; -use project; - package aggregator; -require Exporter; -our @ISA = qw(Exporter); +use strict; +use warnings; +no warnings 'redefine'; + +use events(); +use comments(); +use calendar(); +use project(); +use Date::Calc; + +#use base 'Exporter'; our @EXPORT_OK = qw(get_cache configure_cache put_cache get_list check_params); -our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ] ); -#my $cgi=undef; +sub get_list($$) { + my $config = shift; + my $request = shift; -sub get_list{ - my $config = shift; - my $request=shift; - - my $params=$request->{params}->{checked}; - my $debug=$config->{system}->{debug}; + my $params = $request->{params}->{checked}; #customize prefiltered request parameters - $request->{params}->{original}->{date}=$request->{params}->{checked}->{date}; - if ($params->{event_id}ne''){ - $request->{params}->{original}->{template}='event_details.html'; - }else{ - $request->{params}->{original}->{template}='event_list.html'; + $request->{params}->{original}->{date} = $request->{params}->{checked}->{date}; + if ( $params->{event_id} ne '' ) { + $request->{params}->{original}->{template} = 'event_details.html'; + } else { + $request->{params}->{original}->{template} = 'event_list.html'; } - $request->{params}->{checked} = events::check_params($config, $request->{params}->{original}); - log::write($config, 'params',$request->{params}->{checked}) if ($debug); - - my $content=''; - my $results=events::get($config, $request); - events::render($content, $config, $request, $results); -# calendar::get_cached_or_render($content,$request); + $request->{params}->{checked} = events::check_params( $config, $request->{params}->{original} ); + my $content = ''; + my $results = events::get( $config, $request ); + events::render( $content, $config, $request, $results ); #set url to embed as last loaded url in javascript - my $date=$params->{date}||''; - $date='heute' if ($params->{date}eq'today'); - $date=$results->[0]->{day} if ($params->{event_id}ne''); - my $url=''; - #$config->{controllers}->{events}.'/'.$date.'/'; - if ($params->{from_date}ne'' && $params->{till_date}ne''){ - $url=$config->{controllers}->{events}.'/'.$params->{from_date}.'/'.$params->{till_date} ; - }else{ - $url=$config->{controllers}->{events}.'/'.$params->{from_date}.'/'.$params->{till_date} ; - } + my $date = $params->{date} || ''; + $date = 'heute' if $params->{date} eq 'today'; + $date = $results->[0]->{day} if $params->{event_id} ne ''; + + my $url = $config->{controllers}->{events} . '/' . $params->{from_date} . '/' . $params->{till_date}; #count most projects - my $used_projects={}; - for my $result (@$results){ - my $project=$result->{project_title}||''; + my $used_projects = {}; + for my $result (@$results) { + my $project = $result->{project_title} || ''; $used_projects->{$project}++; } - my @used_projects=reverse sort {$used_projects->{$a} <=> $used_projects->{$b}} (keys %$used_projects); - my $most_used_project=$used_projects[0]; - #use Data::Dumper;print STDERR Dumper(\@used_projects); - + my @used_projects = reverse sort { $used_projects->{$a} <=> $used_projects->{$b} } ( keys %$used_projects ); + my $most_used_project = $used_projects[0]; + return { day => $results->[0]->{day}, start_datetime => $results->[0]->{start_datetime}, @@ -73,209 +62,163 @@ sub get_list{ }; } -sub get_menu{ - my $config = shift; - my $request=shift; - my $date=shift; - my $results=shift; - - my $params=$request->{params}->{checked}; +sub get_menu($$$$) { + my $config = shift; + my $request = shift; + my $date = shift; + my $results = shift; + + my $params = $request->{params}->{checked}; #load details only on demand - if ($params->{event_id}ne''){ - $request->{params}->{original}->{template}='event_menu.html'; - $request->{params}->{original}->{event_id}=undef; - $request->{params}->{original}->{date}=$date; - $request->{params}->{checked} =events::check_params($config, $request->{params}->{original}); - $results=events::get($config, $request); - }else{ - $request->{params}->{checked}->{template}=template::check('event_menu.html'); + if ( $params->{event_id} ne '' ) { + $request->{params}->{original}->{template} = 'event_menu.html'; + $request->{params}->{original}->{event_id} = undef; + $request->{params}->{original}->{date} = $date; + $request->{params}->{checked} = events::check_params( $config, $request->{params}->{original} ); + $results = events::get( $config, $request ); + } else { + $request->{params}->{checked}->{template} = template::check( $config, 'event_menu.html' ); } #events menu - my $output=''; - events::render($output, $config, $request, $results); + my $output = ''; + events::render( $output, $config, $request, $results ); - return { - content => $output - }; + return { content => $output }; } -sub get_calendar{ - my $config = shift; - my $request=shift; - my $date=shift; - - my $params=$request->{params}->{checked}; - my $debug=$config->{system}->{debug}; +sub get_calendar($$$) { + my $config = shift; + my $request = shift; + my $date = shift; + + my $params = $request->{params}->{checked}; $request->{params}->{original}->{template} = 'calendar.html'; - $request->{params}->{original}->{date} = $date if (defined $date); - $request->{params}->{checked} = calendar::check_params($config, $request->{params}->{original}); + $request->{params}->{original}->{date} = $date if defined $date; + $request->{params}->{checked} = calendar::check_params( $config, $request->{params}->{original} ); $params = $request->{params}->{checked}; - log::write($config, 'params',$params) if ($debug); - #set query string for caching - my $options=[]; - push (@$options,'date='.$params->{date}) if ($params->{date} ne''); - push (@$options,'from_date='.$params->{from_date}) if ($params->{from_date} ne''); - push (@$options,'till_date='.$params->{till_date}) if ($params->{till_date} ne''); - $ENV{QUERY_STRING}=''.join("&",@$options); + #set query string for caching + my $options = []; + push @$options, 'date=' . $params->{date} if $params->{date} ne ''; + push @$options, 'from_date=' . $params->{from_date} if $params->{from_date} ne ''; + push @$options, 'till_date=' . $params->{till_date} if $params->{till_date} ne ''; + $ENV{QUERY_STRING} = '' . join( "&", @$options ); - my $content=''; - calendar::get_cached_or_render($content, $config, $request); + my $content = ''; + calendar::get_cached_or_render( $content, $config, $request ); - return { - content => $content - }; + return { content => $content }; } -sub get_newest_comments{ - my $config = shift; - my $request=shift; +sub get_newest_comments($$) { + my $config = shift; + my $request = shift; - my $params={ - template =>'comments_newest.html', + my $params = { + template => 'comments_newest.html', limit => 10, - type =>'list', + type => 'list', show_max => 3 }; - $request={ + $request = { url => $ENV{QUERY_STRING}, params => { original => $params, - checked => comments::check_params($config, $params), + checked => comments::check_params( $config, $params ), }, - config => $config, - connection => $request->{connection} - }; - my $content=''; - comments::get_cached_or_render($content, $config, $request); - return { - content => $content + config => $config, + connection => $request->{connection} }; + my $content = ''; + comments::get_cached_or_render( $content, $config, $request ); + return { content => $content }; } -sub get_cache{ - my $config = shift; - my $request = shift; - - my $params =$request->{params}->{checked}; - my $debug=$config->{system}->{debug}; - - if ($config->{cache}->{use_cache} == 1){ - configure_cache($config); - log::write($config, 'cache_files',cache::get_map()) if ($debug); - my $cache=cache::load($config, $params); - log::write($config, 'cache_files',$cache->{action}) if ($debug); - return $cache; - } - return{}; -} - -sub configure_cache{ - my $config = shift; - - cache::init(); - my $controllers=$config->{controllers}; - - my $date_pattern=$cache::date_pattern; -# cache::add_map('' ,'programm/index.html'); - cache::add_map('date=today' ,'programm/'.$controllers->{events}.'/today.html'); - cache::add_map('date='.$date_pattern ,'programm/'.$controllers->{events}.'/$1-$2-$3.html'); - cache::add_map('from_date='.$date_pattern.'&till_date='.$date_pattern ,'programm/'.$controllers->{events}.'/$1-$2-$3_$4-$5-$6.html'); - cache::add_map('event_id=(\d+)' ,'programm/'.$controllers->{event}.'/$1.html'); -} - - -sub put_cache{ - my $config = shift; - my $request = shift; - my $cache = shift; - - #write to cache - if ($config->{cache}->{use_cache} == 1){ - cache::save($cache); - } -} - -sub check_params{ +sub check_params($$) { my $config = shift; my $params = shift; #get start and stop from projects - my $range= project::get_date_range($config); + my $range = project::get_date_range($config); my $start_date = $range->{start_date}; my $end_date = $range->{end_date}; - -# my $project_name=$config->{project}||''; -# log::error($config, 'no default project configured') if($project_name eq ''); -# log::error($config, "no configuration found for project '$project_name'") unless(exists($config->{projects}->{$project_name})); -# my $project=$config->{projects}->{$project_name}||''; -# log::erorr($config, 'no configuration found for project') if($project eq''); -# if ((defined $params->{project}) && ($params->{project}=~/(\w+)/)){ -# $project=$config->{projects}->{$1} if exists($config->{projects}->{$1}); -# } #filter for date - my $date=time::check_date($params->{date}); - #print STDERR $date."\n"; - if ($date eq ''){ - $date=time::time_to_date(time()) ; - } - # - if ($date eq 'today'){ - $date=time::get_event_date($config); - } + my $date = time::check_date( $params->{date} ); -# $date =$config->{date}->{start_date} if ($date lt $config->{date}->{start_date}); -# $date =$config->{date}->{end_date} if ($date gt $config->{date}->{end_date}); - $date =$start_date if $date lt $start_date; - $date =$end_date if $date gt $end_date; + $date = time::time_to_date( time() ) if $date eq ''; + $date = time::get_event_date($config) if $date eq 'today'; + + $date = $start_date if $date lt $start_date; + $date = $end_date if $date gt $end_date; #filter for date -# my $date=time::check_date($params->{date}); - my $time=time::check_time($params->{time}); - if ((defined $params->{today}) && ($params->{today}eq'1')){ - $date =time::time_to_date(time()); - $params->{date}=$date; - }; - - my $from_date=time::check_date($params->{from_date}); - my $till_date=time::check_date($params->{till_date}); - - my $previous_series=$params->{previous_series} || ''; - if(($previous_series)&&($previous_series=~/(\d+)/)){ - $params->{event_id}=events::get_previous_event_of_series(undef, $config, $1); + my $time = time::check_time( $params->{time} ); + if ( ( defined $params->{today} ) && ( $params->{today} eq '1' ) ) { + $date = time::time_to_date( time() ); + $params->{date} = $date; } - my $next_series=$params->{next_series} || ''; - if(($next_series)&&($next_series=~/(\d+)/)){ - $params->{event_id}=events::get_next_event_of_series(undef, $config, $1); - } - - my $event_id=$params->{event_id}||''; - unless ($event_id eq''){ - if ($event_id=~/(\d+)/){ - $event_id=$1; - }else{ - log::error($config, "invalid event_id"); + if (defined $params->{month}){ + if ($params->{month} eq 'this') { + my ($y, $m) = split /-/, time::time_to_date(); + $params->{from_date} = time::datetime_to_date("$y-$m-01"); + $params->{till_date} = time::datetime_to_date("$y-$m-".Date::Calc::Days_in_Month($y,$m)); + } elsif (my ($y, $m) = $params->{month} =~ m/^(\d\d\d\d)-(\d\d)$/) { + if ($m) { + $params->{from_date} = time::datetime_to_date("$y-$m-01"); + $params->{till_date} = time::datetime_to_date("$y-$m-".Date::Calc::Days_in_Month($y,$m)); + } } } - my $debug=$params->{debug}||''; - if ($debug=~/([a-z\_\,]+)/){ - $debug=$1; + my $from_date = time::check_date( $params->{from_date} ); + my $till_date = time::check_date( $params->{till_date} ); + + my $previous_series = $params->{previous_series} || ''; + if ( ($previous_series) && ( $previous_series =~ /(\d+)/ ) ) { + $params->{event_id} = events::get_previous_event_of_series( + undef, $config, + { + event_id => $1, + exclude_projects => 1, + exclude_locations => 1, + } + ); } - #set query string for caching - if ((!exists $ENV{QUERY_STRING}) || ($ENV{QUERY_STRING}eq'')){ - my $options=[]; - push (@$options,'date='.$date) if $date ne''; - push (@$options,'from_date='.$from_date) if $from_date ne''; - push (@$options,'till_date='.$till_date) if $till_date ne''; - push (@$options,'event_id='.$event_id) if $event_id ne''; - $ENV{QUERY_STRING}=''.join("&",@$options); + my $next_series = $params->{next_series} || ''; + if ( ($next_series) && ( $next_series =~ /(\d+)/ ) ) { + $params->{event_id} = events::get_next_event_of_series( + undef, $config, + { + event_id => $1, + exclude_projects => 1, + exclude_locations => 1, + } + ); + } + + my $event_id = $params->{event_id} || ''; + unless ( $event_id eq '' ) { + if ( $event_id =~ /(\d+)/ ) { + $event_id = $1; + } else { + log::error( $config, "invalid event_id" ); + } + } + + #set query string for caching + if ( ( !exists $ENV{QUERY_STRING} ) || ( $ENV{QUERY_STRING} eq '' ) ) { + my $options = []; + push @$options, 'date=' . $date if $date ne ''; + push @$options, 'from_date=' . $from_date if $from_date ne ''; + push @$options, 'till_date=' . $till_date if $till_date ne ''; + push @$options, 'event_id=' . $event_id if $event_id ne ''; + $ENV{QUERY_STRING} = '' . join( "&", @$options ); } return { @@ -284,10 +227,8 @@ sub check_params{ from_date => $from_date, till_date => $till_date, event_id => $event_id, -# project => $project, - debug => $debug, + ro => $params->{ro}//'' ? 1 : 0 }; -; } #do not delete last line! diff --git a/lib/calcms/audio.pm b/lib/calcms/audio.pm new file mode 100644 index 0000000..3db95a9 --- /dev/null +++ b/lib/calcms/audio.pm @@ -0,0 +1,118 @@ +package audio; +use warnings; +use strict; + +sub durationToSeconds($) { + my $duration = shift; + + if ( $duration =~ /(\d+):(\d\d):(\d\d).(\d\d)/ ) { + return $1 * 3600 + $2 * 60 + $3 + $4 / 100; + } + return $duration; +} + +sub formatDuration($$$;$) { + my $audioDuration = shift; + my $eventDuration = shift; + my $value = shift; + my $mouseOver = shift; + + return '' unless $audioDuration; + return '' unless $eventDuration; + return '' unless $value; + + $audioDuration = durationToSeconds($audioDuration); + $eventDuration = durationToSeconds($eventDuration); + + my $class = "ok"; + my $title = $mouseOver; + + my $delta = 100 * $audioDuration / ($eventDuration+.00000000000001); + + if ( $delta > 101 ) { + $class = "warn"; + $title = sprintf( + qq{file is too long! It should be %d minutes, but is %d}, + ($eventDuration+30) / 60, + ($audioDuration+30) / 60 + ); + } + + if ( $delta < 99.97 ) { + $class = "error"; + $title = sprintf( + qq{file is too short! should be %d minutes, but is %d}, + ($eventDuration+30) / 60, + ($audioDuration+30) / 60 + ); + + } + + return sprintf( qq{
%s
}, $class, $title, $value ); +} + +sub formatChannels($) { + my $channels = shift; + return '' unless $channels; + my $class = "ok"; + $class = "error" if $channels != 2; + return sprintf( qq{
%d ch.
}, $class, $channels ); +} + +sub formatSamplingRate($) { + my $samplingRate = shift; + return '' unless $samplingRate; + my $class = "ok"; + $class = "error" if $samplingRate != 44100; + return sprintf( qq{
%s Hz
}, $class, $samplingRate ); +} + +sub formatBitrate($) { + my $bitrate = shift; + return '' unless $bitrate; + my $class = 'ok'; + $class = 'warn' if $bitrate >= 200; + $class = 'error' if $bitrate < 192; + return sprintf( qq{
%s kBit/s
}, $class, $bitrate ); +} + +sub formatBitrateMode($) { + my $mode = shift; + return '' unless $mode; + my $class = 'ok'; + $class = 'error' if $mode ne 'CBR'; + return sprintf( qq{
%s
}, $class, $mode ); +} + +sub formatLoudness { + my $value = shift; + my $prefix = shift || ''; + my $round = shift || ''; + return '' unless $value; + + $value = sprintf( "%.1f", $value ); + + my $class = 'ok'; + $class = 'warn' if $value > -18.5; + $class = 'error' if $value > -16.0; + $class = 'warn' if $value < -24.0; + $class = 'error' if $value < -27.0; + $value = int($value+0.5) if $round; + + return qq{
$prefix$value dB
}; +} + +sub formatFile{ + my $file = shift; + my $event_id = shift; + + return '' unless $file; + + my ($id) = $file =~ /id(\d+)/; + return '' unless $id; + return '' if $id eq $event_id; + return qq{
Playout
}; +} + +# do not delete this line +1; diff --git a/lib/calcms/audio_recordings.pm b/lib/calcms/audio_recordings.pm index 802251a..c9a77e0 100644 --- a/lib/calcms/audio_recordings.pm +++ b/lib/calcms/audio_recordings.pm @@ -1,18 +1,14 @@ -#!/bin/perl - -package audio_recordings; +package audio_recordings; -use warnings "all"; use strict; +use warnings; +no warnings 'redefine'; use Data::Dumper; -use db; +use db(); -require Exporter; - -our @ISA = qw(Exporter); +#use base 'Exporter'; our @EXPORT_OK = qw(get_columns get); -our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ] ); # columns: # id, project_id, studio_id, event_id @@ -20,74 +16,66 @@ our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ] ); # mastered, processed # audioDuration, eventDuration, rmsLeft, rmsRight -sub debug; +sub get_columns($) { + my $config = shift; -sub get_columns{ - my $config=shift; - - my $dbh=db::connect($config); - my $cols=db::get_columns($dbh, 'calcms_audio_recordings'); - my $columns={}; - for my $col (@$cols){ - $columns->{$col}=1; - } - return $columns; + my $dbh = db::connect($config); + return db::get_columns_hash( $dbh, 'calcms_audio_recordings' ); } -# get playout entries -sub get{ - my $config = shift; - my $condition = shift; +# get playout entries +sub get($$) { + my $config = shift; + my $condition = shift; - return undef unless defined $condition->{project_id}; - return undef unless defined $condition->{studio_id}; + my $date_range_include = 0; + $date_range_include = 1 + if ( defined $condition->{date_range_include} ) && ( $condition->{date_range_include} == 1 ); - my $date_range_include=0; - $date_range_include=1 if (defined $condition->{date_range_include}) && ($condition->{date_range_include}==1); + my $dbh = db::connect($config); - my $dbh=db::connect($config); + my $conditions = []; + my $bind_values = []; - my $conditions=[]; - my $bind_values=[]; - - if ((defined $condition->{id}) && ($condition->{id} ne '')){ - push @$conditions, 'id=?'; - push @$bind_values, $condition->{id}; - } - - if ((defined $condition->{project_id}) && ($condition->{project_id} ne '')){ - push @$conditions, 'project_id=?'; - push @$bind_values, $condition->{project_id}; - } - - if ((defined $condition->{studio_id}) && ($condition->{studio_id} ne '')){ - push @$conditions, 'studio_id=?'; - push @$bind_values, $condition->{studio_id}; - } - - if ((defined $condition->{event_id}) && ($condition->{event_id} ne '')){ - push @$conditions, 'event_id=?'; - push @$bind_values, $condition->{event_id}; - } - - if ((defined $condition->{path}) && ($condition->{path} ne '')){ - push @$conditions, 'path=?'; - push @$bind_values, $condition->{path}; - } - - my $limit=''; - if ((defined $condition->{limit}) && ($condition->{limit} ne '')){ - $limit= 'limit '.$condition->{limit}; + if ( ( defined $condition->{id} ) && ( $condition->{id} ne '' ) ) { + push @$conditions, 'id=?'; + push @$bind_values, $condition->{id}; } - my $whereClause=''; - $whereClause=" where ".join(" and ",@$conditions) if (scalar @$conditions>0); + if ( ( defined $condition->{project_id} ) && ( $condition->{project_id} ne '' ) ) { + push @$conditions, 'project_id=?'; + push @$bind_values, $condition->{project_id}; + } - my $query=qq{ + if ( ( defined $condition->{studio_id} ) && ( $condition->{studio_id} ne '' ) ) { + push @$conditions, 'studio_id=?'; + push @$bind_values, $condition->{studio_id}; + } + + if ( ( defined $condition->{event_id} ) && ( $condition->{event_id} ne '' ) ) { + push @$conditions, 'event_id=?'; + push @$bind_values, $condition->{event_id}; + } + + if ( ( defined $condition->{path} ) && ( $condition->{path} ne '' ) ) { + push @$conditions, 'path=?'; + push @$bind_values, $condition->{path}; + } + + my $limit = ''; + if ( ( defined $condition->{limit} ) && ( $condition->{limit} ne '' ) ) { + $limit = 'limit ' . $condition->{limit}; + } + + my $whereClause = ''; + $whereClause = " where " . join( " and ", @$conditions ) if ( scalar @$conditions > 0 ); + + my $query = qq{ select id ,project_id ,studio_id ,event_id + ,active ,path ,size ,created_by @@ -103,34 +91,29 @@ sub get{ $whereClause order by created_at desc }; - - #print STDERR Dumper($query).Dumper($bind_values); - my $entries=db::get($dbh, $query, $bind_values); - return $entries; + my $entries = db::get( $dbh, $query, $bind_values ); + return $entries; } - # update playout entry if differs to old values -sub update{ - my $config = shift; - my $dbh = shift; - my $entry = shift; - - #print STDERR "update:".Dumper($entry); +sub update($$$) { + my $config = shift; + my $dbh = shift; + my $entry = shift; - my $day_start=$config->{date}->{day_starting_hour}; + my $day_start = $config->{date}->{day_starting_hour}; - my $bind_values=[ - $entry->{path}, $entry->{size}, - $entry->{created_by}, $entry->{created_at}, - $entry->{modified_at} || time::time_to_datetime(time()), - $entry->{processed}, $entry->{mastered}, - $entry->{eventDuration}, $entry->{audioDuration}, - $entry->{rmsLeft}, $entry->{rmsRight}, - $entry->{project_id}, $entry->{studio_id}, $entry->{event_id} + my $bind_values = [ + $entry->{path}, $entry->{size}, + $entry->{created_by}, $entry->{created_at}, + $entry->{modified_at} || time::time_to_datetime( time() ), $entry->{processed}, + $entry->{mastered}, $entry->{eventDuration}, + $entry->{audioDuration}, $entry->{rmsLeft}, + $entry->{rmsRight}, $entry->{project_id}, + $entry->{studio_id}, $entry->{event_id} ]; - - my $query=qq{ + + my $query = qq{ update calcms_audio_recordings set path=?, size=?, created_by=?, created_at=?, @@ -140,66 +123,105 @@ sub update{ rmsLeft=?, rmsRight=? where project_id=? and studio_id=? and event_id=? }; - if (defined $entry->{id}){ - $query.=' and id=?'; + if ( defined $entry->{id} ) { + $query .= ' and id=?'; push @$bind_values, $entry->{id}; } - #print STDERR Dumper($query).Dumper($bind_values); - return db::put($dbh, $query, $bind_values); + my $result = db::put( $dbh, $query, $bind_values ); + update_active($config, $dbh, $entry); + return $result; } # insert playout entry -sub insert{ +sub insert ($$$) { my $config = shift; my $dbh = shift; my $entry = shift; - return undef unless defined $entry->{project_id}; - return undef unless defined $entry->{studio_id}; - return undef unless defined $entry->{event_id}; - return undef unless defined $entry->{path}; + return undef unless defined $entry->{project_id}; + return undef unless defined $entry->{studio_id}; + return undef unless defined $entry->{event_id}; + return undef unless defined $entry->{path}; - #print STDERR "insert into audio_recordings:".Dumper($entry); - return db::insert($dbh, 'calcms_audio_recordings', { - project_id => $entry->{project_id}, - studio_id => $entry->{studio_id}, - event_id => $entry->{event_id}, - path => $entry->{path}, - size => $entry->{size}, - created_by => $entry->{created_by}, - eventDuration => $entry->{eventDuration}, - audioDuration => $entry->{audioDuration}, - rmsLeft => $entry->{rmsLeft}, - rmsRight => $entry->{rmsRight}, - processed => $entry->{processed}, - mastered => $entry->{mastered} || '0', - }); + $entry = { + project_id => $entry->{project_id}, + studio_id => $entry->{studio_id}, + event_id => $entry->{event_id}, + path => $entry->{path}, + size => $entry->{size}, + created_by => $entry->{created_by}, + eventDuration => $entry->{eventDuration}, + audioDuration => $entry->{audioDuration}, + rmsLeft => $entry->{rmsLeft}, + rmsRight => $entry->{rmsRight}, + processed => $entry->{processed}, + mastered => $entry->{mastered} || '0', + }; + my $result = db::insert( $dbh, 'calcms_audio_recordings', $entry ); + update_active($config, $dbh, $entry); + return $result; } # delete playout entry -sub delete{ +sub delete ($$$) { my $config = shift; - my $dbh = shift; - my $entry = shift; - - return undef unless defined $entry->{project_id}; - return undef unless defined $entry->{studio_id}; - return undef unless defined $entry->{event_id}; - return undef unless defined $entry->{path}; + my $dbh = shift; + my $entry = shift; - my $query=qq{ - delete + return undef unless defined $entry->{project_id}; + return undef unless defined $entry->{studio_id}; + return undef unless defined $entry->{event_id}; + return undef unless defined $entry->{path}; + + my $query = qq{ + delete from calcms_audio_recordings where project_id=? and studio_id=? and event_id=? and path=? }; - my $bind_values = [ $entry->{project_id}, $entry->{studio_id}, $entry->{event_id}, $entry->{path} ]; - return db::put($dbh, $query, $bind_values); + my $bind_values = [ $entry->{project_id}, $entry->{studio_id}, $entry->{event_id}, $entry->{path} ]; + my $result = db::put( $dbh, $query, $bind_values ); + + update_active($config, $dbh, $entry); + return $result; } -sub error{ - my $msg = shift; - print "ERROR: $msg
\n"; +sub update_active($$$) { + my $config = shift; + my $dbh = shift; + my $entry = shift; + + return undef unless defined $entry->{project_id}; + return undef unless defined $entry->{studio_id}; + return undef unless defined $entry->{event_id}; + + my $bind_values = [ $entry->{project_id}, $entry->{studio_id}, $entry->{event_id} ]; + my $query = qq{ + update calcms_audio_recordings + set active=0 + where project_id=? and studio_id=? and event_id=? and active=1 + }; + db::put( $dbh, $query, $bind_values ); + + $query = qq{ + select max(id) id from calcms_audio_recordings + where project_id=? and studio_id=? and event_id=? + }; + my $entries = db::get( $dbh, $query, $bind_values ); + my $max = $entries->[0]; + return undef unless defined $max->{id}; + + $query = qq{ + update calcms_audio_recordings + set active=1 + where id=? + }; + return db::put( $dbh, $query, [$max->{id}] ); +} + +sub error($) { + my $msg = shift; + print "ERROR: $msg
\n"; } #do not delete last line! diff --git a/lib/calcms/auth.pm b/lib/calcms/auth.pm index 799b380..3df3fb7 100644 --- a/lib/calcms/auth.pm +++ b/lib/calcms/auth.pm @@ -1,281 +1,256 @@ -#!/bin/perl +package auth; -use CGI; -#use CGI::Carp qw(warningsToBrowser fatalsToBrowser); -use CGI::Session qw(-ip-match); -use CGI::Cookie; -#$CGI::Session::IP_MATCH=1; - -package auth; - -use warnings "all"; use strict; +use warnings; +no warnings 'redefine'; + +use CGI::Simple(); +use CGI::Cookie(); use Data::Dumper; -use Authen::Passphrase::BlowfishCrypt; -use time; +use Authen::Passphrase::BlowfishCrypt(); +use time(); +use user_sessions (); -require Exporter; -our @ISA = qw(Exporter); +#use base 'Exporter'; our @EXPORT_OK = qw(get_user login logout crypt_password); -our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ] ); +my $defaultExpiration = 60; - -my $defaultExpiration=60; -my $tmp_dir='/var/tmp/'; -my $debug=0; - -sub debug; - -sub get_user{ - my $cgi=shift; - my $config=shift; - - my %parms=$cgi->Vars(); - my $parms=\%parms; - - debug("get_user")if ($debug); +#TODO: remove CGI +sub get_user($$$) { + my ($config, $params, $cgi) = @_; # login or logout on action - if (defined $parms->{action}){ - if ($parms->{action} eq 'login'){ - my $user=login($cgi, $config, $parms->{user}, $parms->{password}); - $cgi->delete('user','password','uri','action'); - return $user; - }elsif($parms->{action} eq 'logout'){ - logout($cgi); - $cgi->delete('user','password','uri','action'); - return undef; - } - } + if ( defined $params->{authAction} ) { + if ( $params->{authAction} eq 'login' ) { + my $user = login( $config, $params->{user}, $params->{password} ); + $cgi->delete( 'user', 'password', 'uri', 'authAction' ) if defined $cgi; + return $user; + } elsif ( $params->{authAction} eq 'logout' ) { + $cgi = new CGI::Simple() unless defined $cgi; + logout($config, $cgi); + $cgi->delete( 'user', 'password', 'uri', 'authAction' ); + return undef; + } + } # read session id from cookie - my $session_id=read_cookie($cgi); + my $session_id = read_cookie(); # login if no cookie found - return show_login_form($parms->{user}, 'Please login') unless defined $session_id; + return show_login_form( $params->{user}, 'Please login' ) unless defined $session_id; # read session - my $session=read_session($session_id); + my $session = read_session($config, $session_id); # login if user not found - return show_login_form($parms->{user}, 'unknown User') unless defined $session; + return show_login_form( $params->{user}, 'unknown User' ) unless defined $session; - $parms->{user} = $session->{user}; - $parms->{expires} = $session->{expires}; - debug($parms->{expires}); - return $session->{user}, $session->{expires}; + $params->{user} = $session->{user}; + $params->{expires} = $session->{expires}; + return $session->{user}, $session->{expires}; } -sub crypt_password{ - my $password=shift; +sub crypt_password($) { + my $password = shift; - my $ppr = Authen::Passphrase::BlowfishCrypt->new( - cost => 8, - salt_random => 1, - passphrase => $password - ); - return{ - salt => $ppr->salt_base64, - crypt => $ppr->as_crypt - }; + my $ppr = Authen::Passphrase::BlowfishCrypt->new( + cost => 8, + salt_random => 1, + passphrase => $password + ); + return { + salt => $ppr->salt_base64, + crypt => $ppr->as_crypt + }; } -sub login{ - my $cgi=shift; - my $config=shift; - my $user=shift; - my $password=shift; - debug("login")if ($debug); - - #print STDERR "login $user $password\n"; - my $result = authenticate($config, $user, $password); - #print STDERR Dumper($result); +sub login($$$) { + my $config = shift; + my $user = shift; + my $password = shift; - return show_login_form($user,'Could not authenticate you') unless defined $result; - return unless defined $result->{login}eq '1'; + my $result = authenticate( $config, $user, $password ); - my $timeout=$result->{timeout} || $defaultExpiration; - $timeout='+'.$timeout.'m'; + return show_login_form( $user, 'Could not authenticate you' ) unless defined $result; + return unless defined $result->{login} eq '1'; - my $session_id=create_session($user, $password, $timeout); - return $user if(create_cookie($cgi, $session_id, $timeout)); - return undef; + my $timeout = $result->{timeout} || $defaultExpiration; + my $session_id = create_session( $config, $user, $timeout * 60 ); + + # here timeout is in minutes + $timeout = '+' . $timeout . 'm'; + return $user if create_cookie( $session_id, $timeout ); + return undef; } -sub logout{ - my $cgi=shift; - my $session_id=read_cookie($cgi); - debug("logout")if ($debug); - unless(delete_session($session_id)){ - return show_login_form('Cant delete session', 'logged out'); - }; - unless(delete_cookie($cgi)){ - return show_login_form('Cant remove cookie', 'logged out'); - } - my $uri=$ENV{HTTP_REFERER}||''; - $uri=~s/action=logout//g; - print $cgi->redirect($uri); -# return show_login_form('', 'logged out'); +#TODO: remove cgi +sub logout($$) { + my $config = shift; + my $cgi = shift; + + my $session_id = read_cookie(); + unless ( delete_session($config, $session_id) ) { + return show_login_form( 'Cant delete session', 'logged out' ); + } + unless ( delete_cookie($cgi) ) { + return show_login_form( 'Cant remove cookie', 'logged out' ); + } + my $uri = $ENV{HTTP_REFERER} || ''; + $uri =~ s/authAction=logout//g; + print $cgi->redirect($uri); + return; } #read and write data from browser, http://perldoc.perl.org/CGI/Cookie.html -sub create_cookie{ - my $cgi=shift; - my $session_id=shift; - my $timeout=shift; - #debug("create_cookie")if ($debug); +sub create_cookie($$) { + my $session_id = shift; + my $timeout = shift; - my $cookie = CGI::Cookie->new( - -name => 'sessionID', - -value => $session_id, - -expires => $timeout, -# -domain => '.capricorn.com', -# -path => '/agenda/admin/', - -secure => 1 - ); - print "Set-Cookie: ",$cookie->as_string,"\n"; - print STDERR "#Set-Cookie: ",$cookie->as_string,"\n"; -# print $cgi->header( -cookie => $cookie ); - return 1; + my $cookie = CGI::Cookie->new( + -name => 'sessionID', + -value => $session_id, + -expires => $timeout, + -secure => 1, + -samesite=> "Lax" + ); + print "Set-Cookie: " . $cookie->as_string . "\n"; + + return 1; } -sub read_cookie{ - my $cgi=shift; - - debug("read_cookie")if ($debug); - my %cookie = CGI::Cookie->fetch; - debug("cookies: ".Dumper(\%cookie))if ($debug); - my $cookie=$cookie{'sessionID'}; - debug("cookie: ".$cookie)if ($debug); - return undef unless (defined $cookie); - my $session_id= $cookie->value || undef; - debug("sid: ".$session_id)if ($debug); - return $session_id; - #return $cgi->cookie('sessionID') || undef; -}; - -sub delete_cookie{ - my $cgi=shift; - - debug("delete_cookie")if ($debug); - my $cookie = $cgi->cookie( - -name => 'sessionID', - -value => '', - -expires => '+1s' - ); - print $cgi->header( -cookie => $cookie ); - return 1; +sub read_cookie() { + my %cookie = CGI::Cookie->fetch; + my $cookie = $cookie{'sessionID'}; + return undef unless defined $cookie; + my $session_id = $cookie->value || undef; + return $session_id; } -#read and write server-side session data -sub create_session{ - my $user=shift; - my $password=shift; - my $expiration=shift; +#TODO: remove CGI +sub delete_cookie($) { + my $cgi = shift; - debug("create_session")if ($debug); - my $session = new CGI::Session(undef, undef, {Directory=>$tmp_dir}); - $session->expire($expiration); - $session->param("user", $user); - $session->param("pid", $$); -# $session->param("password", $password); - return $session->id(); + my $cookie = $cgi->cookie( + -name => 'sessionID', + -value => '', + -expires => '+1s' + ); + print $cgi->header( -cookie => $cookie ); + return 1; } -sub read_session{ - my $session_id=shift; +# read and write server-side session data +# timeout is in seconds +sub create_session ($$$) { + my $config = shift; + my $user = shift; + my $timeout = shift; - debug("read_session")if $debug; - return undef unless(defined $session_id); - - debug("read_session2")if $debug; - my $session = new CGI::Session(undef, $session_id, {Directory=>$tmp_dir}); - return undef unless defined $session; - - debug("read_session3")if $debug; - my $user = $session->param("user") || undef; - return undef unless defined $user; - my $expires = time::time_to_datetime($session->param("_SESSION_ATIME")+$session->param("_SESSION_ETIME")); - return { - user => $user, - expires => $expires - } + my $session_id = user_sessions::start( + $config, { + user => $user, + timeout => $timeout, + } + ); + return $session_id; } -sub delete_session{ - my $session_id=shift; +sub read_session($$) { + my $config = shift; + my $session_id = shift; - debug("delete_session")if ($debug); - return undef unless(defined $session_id); - my $session = new CGI::Session(undef, $session_id, {Directory=>$tmp_dir}); - $session->delete(); - return 1; + return undef unless defined $session_id; + + my $session = user_sessions::check( $config, { session_id => $session_id } ); + return undef unless defined $session; + + return { + user => $session->{user}, + expires => $session->{expires_at} + }; } +sub delete_session($$) { + my $config = shift; + my $session_id = shift; + + return undef unless defined $session_id; + + user_sessions::stop( $config, { session_id => $session_id } ); + return 1; +} #check user authentication -sub authenticate{ - my $config=shift; - my $user=shift; - my $password=shift; +sub authenticate($$$) { + my $config = shift; + my $user = shift; + my $password = shift; - $config->{access}->{write}=0; - my $dbh = db::connect($config); - my $query = qq{ + $config->{access}->{write} = 0; + my $dbh = db::connect($config); + my $query = qq{ select * from calcms_users where name=? }; - my $bind_values = [$user]; - #print STDERR "query:".Dumper($query).Dumper($bind_values); + my $bind_values = [$user]; - my $users = db::get($dbh,$query,$bind_values); - #print STDERR "result:".Dumper($users); - - if (scalar(@$users) != 1){ - print STDERR "auth: did not find user '$user'\n"; - return undef; - } - #print STDERR Dumper($users); + my $users = db::get( $dbh, $query, $bind_values ); - my $salt=$users->[0]->{salt}; - my $ppr = Authen::Passphrase::BlowfishCrypt->from_crypt( - $users->[0]->{pass}, - $users->[0]->{salt} - ); - - return undef unless $ppr->match($password); - if($users->[0]->{disabled} == 1){ - print STDERR "user '$user' is disabled\n"; + if ( scalar(@$users) != 1 ) { + print STDERR "auth: did not find user '$user'\n"; return undef; } + my $salt = $users->[0]->{salt}; + my $ppr = Authen::Passphrase::BlowfishCrypt->from_crypt( $users->[0]->{pass}, $users->[0]->{salt} ); + + return undef unless $ppr->match($password); + if ( $users->[0]->{disabled} == 1 ) { + print STDERR "user '$user' is disabled\n"; + return undef; + } + + # timeout in seconds my $timeout = $users->[0]->{session_timeout} || 120; - $timeout =10 if $timeout < 10; - $timeout =12*60 if $timeout > 12*60; + $timeout = 60 if $timeout < 60; return { timeout => $timeout, login => 1 - } + }; } -sub show_login_form{ - my $user=shift||''; - my $uri=$ENV{HTTP_REFERER}||''; - my $message=shift||''; - debug("show_login_form")if ($debug); - print qq{Content-type:text/html +sub show_login_form ($$) { + my $user = shift || ''; + my $uri = $ENV{HTTP_REFERER} || ''; + my $message = shift || ''; + my $requestReset = ''; + + if ( ( $user ne '' ) && ( $message ne '' ) ) { + $requestReset = qq{ + Passwort vergessen? + }; + } + + print qq{Content-type:text/html + @@ -331,24 +347,19 @@ sub show_login_form{
- - + +
+ $requestReset }; - return undef; + return undef; } -sub debug{ - my $message=shift; - print STDERR "$message\n" if $debug>0; -} - - #do not delete last line! 1; diff --git a/lib/calcms/cache.pm b/lib/calcms/cache.pm deleted file mode 100644 index dc00789..0000000 --- a/lib/calcms/cache.pm +++ /dev/null @@ -1,179 +0,0 @@ -use warnings "all"; -use strict; -#use Data::Dumper; - -use config; -use time; -use log; -use markup; - -package cache; - -require Exporter; -our @ISA = qw(Exporter); -our @EXPORT_OK = qw(init add_map get_map get_map_keys load save get_filename escape_regexp escape_regexp_line); -our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ] ); - -my $cache_map ={}; -my $cache_map_keys =[]; -my $header_printed =0; - -our $date_pattern ='(\d{4})\-(\d{2})\-(\d{2})'; -our $datetime_pattern ='(\d{4})\-(\d{2})\-(\d{2})[T\+](\d{2})\:(\d{2})(\:\d{2})?'; - -sub init{ - $cache_map ={}; - $cache_map_keys =[]; - $header_printed =0; -} - -sub add_map{ - my $key =$_[0]; - my $value =$_[1]; - - $key='^'.$key.'$'; - push @$cache_map_keys,$key; - $cache_map->{$key}=$value; -} - -sub get_map{ - return $cache_map; -} - -sub get_map_keys{ - return $cache_map_keys; -} - -#get cache from params -sub load{ - my $params=shift; - - my $filename=get_filename($params); - - my $result={ - filename=>$filename - }; - - if (defined $filename){ - my @file_info=stat($filename); - my $modified=$file_info[9]||''; - if ($modified ne ''){ - #file exists - my @now =localtime(time()); - my @modified =localtime($modified); - if ($now[2]==$modified[2]){ - #file is elder than a hour - my $content=log::load_file($filename); - if (defined $content){ - $result->{content} =$content; - $result->{action} ='read'; - return $result; - } - } - } - } - - $result->{action}='save'; - return $result; -} - -#get filename from params -sub get_filename{ - my $config = shift; - my $params = shift; - -# my $url=$ENV{REQUEST_URI}; - my $url=$ENV{QUERY_STRING}||''; - if ($url ne''){ - $url=~s/(^|\&)update\=\d//gi; - $url=~s/(^|\&)debug\=.*//gi; - $url=~s/\?\&/\?/g; - $url=~s/\&{2,99}/\&/g; - $url=~s/\&$//g; - $url=~s/^\/\//\//g; - } - foreach my $pattern (@$cache_map_keys){ - - my $filename=$url; - log::write($config, 'cache_trace',"look at \"$filename\" for $pattern") if ($config->{system}->{debug}); - if ($filename =~/$pattern/){ - my $m1=$1; - my $m2=$2; - my $m3=$3; - my $m4=$4; - my $m5=$5; - my $m6=$6; - my $m7=$7; - my $m8=$8; -# my $m9=$9; - - my $result=$cache_map->{$pattern}; - - $filename=~s/$pattern/$result/; - $filename=~s/\$1/$m1/ if (defined $m1); - $filename=~s/\$2/$m2/ if (defined $m2); - $filename=~s/\$3/$m3/ if (defined $m3); - $filename=~s/\$4/$m4/ if (defined $m4); - $filename=~s/\$5/$m5/ if (defined $m5); - $filename=~s/\$6/$m6/ if (defined $m6); - $filename=~s/\$7/$m7/ if (defined $m7); - $filename=~s/\$8/$m8/ if (defined $m8); -# $filename=~s/\$9/$m9/ if (defined $m9); - $filename=$config->{cache}->{cache_dir}.$filename; - return $filename; - } - } - return undef; -} - -#deprecated: set file from params -sub set{ - my $params=shift; - my $content=shift; - - my $filename=get_filename($params); - my $cache={ - filename => $filename, - content => $content - }; -# print $filename.":file\n"; - - if (defined $filename){ - cache::save($cache); - } -} - - -sub save{ - my $cache=shift; - - return if ($cache->{action}ne'save'); - return if ((!defined $cache->{filename}) || ($cache->{filename}eq'')); - - log::save_file($cache->{filename},$cache->{content}); - chmod 0664, $cache->{filename}; -} - - -sub escape_regexp{ - my $reg_exp=shift; - $reg_exp=~s/([\^\$\\(\)\[\]\{\}\|\/\*\+\.\-\&\:])/\\$1/gi; - return $reg_exp; -} - -sub escape_regexp_line{ - my $reg_exp=shift; - $reg_exp=~s/([\^\$\\(\)\[\]\{\}\|\/\*\+\.\-\&\:])/\\$1/gi; - return '^'.$reg_exp.'$'; -} - -sub configure{ - my $file_name=shift; - - cache::init(); - cache::add_map('',$file_name); -} - - -#do not delete last line! -1; diff --git a/lib/calcms/calendar.pm b/lib/calcms/calendar.pm index 7038713..cb5b070 100644 --- a/lib/calcms/calendar.pm +++ b/lib/calcms/calendar.pm @@ -1,290 +1,259 @@ -#use Calendar::Simple qw(date_span); -use Date::Calc; +package calendar; -use config; -use template; -use markup; -use cache; -use log; -use time; -use project; -use events; - -package calendar; -use warnings "all"; use strict; +use warnings; +no warnings 'redefine'; + use Data::Dumper; +use Date::Calc(); -require Exporter; -our @ISA = qw(Exporter); +use template(); +use events(); + +#use base 'Exporter'; our @EXPORT_OK = qw(init get_cached_or_render get render get_calendar_weeks configure_cache); -our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ] ); -#my $debug=''; - -sub init{ +sub init() { } -sub get_cached_or_render{ -# my $output = $_[0] +sub get_cached_or_render($$$) { + # my $output = $_[0] my $config = $_[1]; my $request = $_[2]; - my $parms =$request->{params}->{checked}; - my $debug=$config->{system}->{debug}; - - my $cache={}; - if ($config->{cache}->{use_cache} == 1){ - calendar::configure_cache($config); - $cache=cache::load($config, $parms); - log::write($config, 'cache',$cache->{action}) if ($debug); - if (defined $cache->{content}){ - $_[0]=$cache->{content}; - return; - } - } - - my $calendar=calendar::get($config, $request); - log::write($config, 'calendar',$calendar) if ($debug); - #print STDERR Dumper($calendar); - - calendar::render($_[0], $config, $request, $calendar); - - #write to cache - if ($config->{cache}->{use_cache} == 1){ - #todo:put out reference only - $cache->{content}=$_[0]; - log::write($config, 'cache_files',$cache) if ($debug); - cache::save($cache); - } + my $parms = $request->{params}->{checked}; + my $calendar = calendar::get( $config, $request ); + calendar::render( $_[0], $config, $request, $calendar ); } - -sub get{ +sub get($$) { my $config = shift; my $request = shift; - my $params=$request->{params}->{checked}; - my $debug=$config->{system}->{debug}; + my $params = $request->{params}->{checked}; + my $language = $config->{date}->{language} || 'en'; - my $language = $config->{date}->{language} || 'en'; + my $date = $params->{date} || ''; + my $template = $params->{template} || ''; + my $from_time = $params->{from_time} || ''; + my $till_time = $params->{till_time} || ''; - my $date = $params->{date}||''; - my $template = $params->{template}||''; - my $from_time = $params->{from_time}||''; - my $till_time = $params->{till_time}||''; + my @today = localtime( time() ); + my $today = sprintf( '%04d-%02d-%02d', 1900 + $today[5], $today[4] + 1, $today[3] ); - my @today=localtime(time()); - my $today=sprintf('%04d-%02d-%02d', 1900+$today[5], $today[4]+1, $today[3]); - - my $weekday_names = $time::names->{$language}->{weekdays}; - my $weekday_short_names = $time::names->{$language}->{weekdays_abbr}; - my $week_label={}; - my $c=0; - for my $weekday (@$weekday_short_names){ - $week_label->{$weekday}=$weekday_names->[$c]||''; + my $weekday_names = time::getWeekdayNames($language); + my $weekday_short_names = time::getWeekdayNamesShort($language); + my $week_label = {}; + my $c = 0; + for my $weekday (@$weekday_short_names) { + $week_label->{$weekday} = $weekday_names->[$c] || ''; $c++; } - $template=~s/\'//gi; - $from_time=~s/\'//gi; - $till_time=~s/\'//gi; + $template =~ s/\'//gi; + $from_time =~ s/\'//gi; + $till_time =~ s/\'//gi; #put "clear all" filter into final results - my $day_result={}; - my $clear_filter=$day_result; + my $day_result = {}; + my $clear_filter = $day_result; #put "week day" filter into final results - my $days=[]; - $c=0; - for my $weekday (@$weekday_short_names){ - my $day_result={ - label => $week_label->{$weekday}, - weekday => $c+1, - weekday_parameter => 'weekday='.$c, - weekday_short_name => $weekday_short_names->[$c] ||'', - weekday_name => $weekday_names->[$c] ||'', - description => qq{alle $week_label->{$weekday}-Termine anzeigen}, + my $days = []; + $c = 0; + for my $weekday (@$weekday_short_names) { + my $day_result = { + label => $week_label->{$weekday}, + weekday => $c + 1, + weekday_parameter => 'weekday=' . $c, + weekday_short_name => $weekday_short_names->[$c] || '', + weekday_name => $weekday_names->[$c] || '', + description => qq{alle $week_label->{$weekday}-Termine anzeigen}, }; - push @$days,$day_result; + push @$days, $day_result; $c++; } #weeks and days array - my $weekAndDayResults=[]; + my $weekAndDayResults = []; #weekday array - my $weekdayResults=$days; + my $weekdayResults = $days; #week array - my $weekResults=[]; + my $weekResults = []; #info hash by timedate - my $dateInfo={}; + my $dateInfo = {}; #generate content for each day in a week in a month in a year #get today - my $start_date=''; - my $end_date=''; - if ($date=~/(\d{4})\-(\d{2})/){ - my $year=$1; - my $month=$2; - $start_date = "$year-$month-01"; - $end_date = "$year-$month-".Date::Calc::Days_in_Month($year,$month); - }else{ - $start_date = $params->{start_date}; - $end_date = $params->{end_date}; + my $start_date = ''; + my $end_date = ''; + if ( $date =~ /(\d{4})\-(\d{2})/ ) { + my $year = $1; + my $month = $2; + $start_date = "$year-$month-01"; + $end_date = "$year-$month-" . Date::Calc::Days_in_Month( $year, $month ); + } else { + $start_date = $params->{start_date}; + $end_date = $params->{end_date}; } - my $previous_month=$start_date; - if ($previous_month=~/(\d{4})\-(\d{2})/){ - my $year =$1; - my $month=$2-1; - $month='0'.$month if (length($month)<2); - if ($month lt '01'){ - $year-=1; - $month='12'; + my $previous_month = $start_date; + if ( $previous_month =~ /(\d{4})\-(\d{2})/ ) { + my $year = $1; + my $month = $2 - 1; + $month = '0' . $month if ( length($month) < 2 ); + if ( $month lt '01' ) { + $year -= 1; + $month = '12'; } - $previous_month="$year-$month-01"; - $previous_month=$params->{start_date} if ($previous_month lt $params->{start_date}); + $previous_month = "$year-$month-01"; + $previous_month = $params->{start_date} if ( $previous_month lt $params->{start_date} ); } - my $next_month=$end_date; - if ($next_month=~/(\d{4})\-(\d{2})/){ - my $year=$1; - my $month=$2+1; - $month='0'.$month if (length($month)<2); - if ($month gt '12'){ - $year+=1; - $month='01'; + my $next_month = $end_date; + if ( $next_month =~ /(\d{4})\-(\d{2})/ ) { + my $year = $1; + my $month = $2 + 1; + $month = '0' . $month if ( length($month) < 2 ); + if ( $month gt '12' ) { + $year += 1; + $month = '01'; } - $next_month="$year-$month-01"; - $next_month=$params->{end_date} if ($next_month gt $params->{end_date}); + $next_month = "$year-$month-01"; + $next_month = $params->{end_date} if ( $next_month gt $params->{end_date} ); } - my $start_year=undef; - my $start_month=undef; - if ($start_date=~/(\d{4})\-(\d{2})/){ - $start_year=$1; - $start_month=$2; + my $start_year = undef; + my $start_month = undef; + if ( $start_date =~ /(\d{4})\-(\d{2})/ ) { + $start_year = $1; + $start_month = $2; } - my $start_month_name=$time::names->{$language}->{months_abbr}->[$start_month-1]; + my $monthNames = time::getMonthNamesShort($language); + my $start_month_name = $monthNames->[ $start_month - 1 ]; - if($params->{month_only}eq'1'){ + if ( $params->{month_only} eq '1' ) { return { - next_month => $next_month, - previous_month => $previous_month, - start_year => $start_year, - start_month => $start_month, - start_month_name => $start_month_name + next_month => $next_month, + previous_month => $previous_month, + start_year => $start_year, + start_month => $start_month, + start_month_name => $start_month_name }; } - my $years=calendar::get_calendar_weeks($config, $start_date, $end_date); + my $years = calendar::get_calendar_weeks( $config, $start_date, $end_date ); - my $dbh=db::connect($config, $request); + my $dbh = db::connect( $config, $request ); - my $used_days=events::get_by_date_range($dbh, $config, $start_date, $end_date); - my $used_day={}; - for my $day(@$used_days){ - $used_day->{$day->{start_date}}=1; - } + my $used_days = events::get_by_date_range( + $dbh, $config, + $start_date, + $end_date, + { + exclude_projects => 1, + exclude_locations => 1, + } + ); + my $used_day = { map { $_->{start_date} => 1 } @$used_days }; - for my $year (sort {$a <=> $b} keys %$years){ - my $months=$years->{$year}; + for my $year ( sort { $a <=> $b } keys %$years ) { + my $months = $years->{$year}; - for my $month (sort {$a <=> $b} keys %$months){ - my $weeks=$months->{$month}; + for my $month ( sort { $a <=> $b } keys %$months ) { + my $weeks = $months->{$month}; - my $weekCounter=1; - for my $week (@$weeks){ - my $dayResults=[]; + my $weekCounter = 1; + for my $week (@$weeks) { + my $dayResults = []; - my $week_end =undef; - my $week_start=undef; + my $week_end = undef; + my $week_start = undef; - my $week_of_year=undef; - my $woy_year = undef; + my $week_of_year = undef; + my $woy_year = undef; - for my $date (@$week){ - my ($year, $month, $day)=split(/\-/,$date); - my $weekday=0; - my $day_result=undef; + for my $date (@$week) { + my ( $year, $month, $day ) = split( /\-/, $date, 3 ); + my $weekday = 0; + my $day_result = undef; - ($week_of_year,$woy_year) = Date::Calc::Week_of_Year($year,$month,$day) unless defined $week_of_year; + ( $week_of_year, $woy_year ) = Date::Calc::Week_of_Year( $year, $month, $day ) + unless defined $week_of_year; - $day_result={ - date => $date, - date_parameter => 'date='.$date, - day => $day, - year => $year, - month => $month, + $day_result = { + date => $date, + date_parameter => 'date=' . $date, + day => $day, + year => $year, + month => $month, }; - $day_result->{time} =$from_time if defined $from_time; + $day_result->{time} = $from_time if defined $from_time; - $day_result->{class}.= ' calcms_today' if $date eq $today; - $day_result->{class}.= ' selected' if defined $used_day->{$date}; - $day_result->{class}.= " week_$weekCounter"; - $day_result->{class}.= " other_month" if ($weekCounter<2) && ($day gt "15"); - $day_result->{class}.= " other_month" if ($weekCounter>3) && ($day lt "15"); - $day_result->{class}=~s/^\s+//g; + $day_result->{class} .= ' calcms_today' if $date eq $today; + $day_result->{class} .= ' selected' if defined $used_day->{$date}; + $day_result->{class} .= " week_$weekCounter"; + $day_result->{class} .= " other_month" if ( $weekCounter < 2 ) && ( $day gt "15" ); + $day_result->{class} .= " other_month" if ( $weekCounter > 3 ) && ( $day lt "15" ); + $day_result->{class} =~ s/^\s+//g; - $week_start =$day unless defined $week_start; - $week_end =$day; + $week_start = $day unless defined $week_start; + $week_end = $day; - log::write($config, 'day_results',$day_result)if ($debug); + $day_result->{weekday_name} = $weekday_names->[$weekday]; + $day_result->{weekday_short_name} = $weekday_short_names->[$weekday]; + $day_result->{weekday} = $weekday + 1; - $day_result->{weekday_name}=$weekday_names->[$weekday]; - $day_result->{weekday_short_name}=$weekday_short_names->[$weekday]; - $day_result->{weekday}=$weekday+1; - - $dateInfo->{$day_result->{date}}=$day_result->{weekday} if defined $day_result->{date}; + $dateInfo->{ $day_result->{date} } = $day_result->{weekday} if defined $day_result->{date}; push @$dayResults, $day_result; $weekday++; - }#end for days + } #end for days #week filter - my $start_date=$week->[0]; - my $end_date =$week->[-1]; + my $start_date = $week->[0]; + my $end_date = $week->[-1]; - my $week_result={ - from_date => $start_date, - till_date => $end_date, - week_start => $week_start, - week_end => $week_end, - week_month => sprintf("%2d",$month), - week_year => $year, - week_of_year => $week_of_year, + my $week_result = { + from_date => $start_date, + till_date => $end_date, + week_start => $week_start, + week_end => $week_end, + week_month => sprintf( "%2d", $month ), + week_year => $year, + week_of_year => $week_of_year, }; - $week_result->{class}.= ' selected' if ( - ((defined $params->{from_date}) && ($start_date eq $params->{from_date})) - || ((defined $params->{till_date}) && ($end_date eq $params->{till_date})) - ); - $week_result->{class}.= " week_$weekCounter"; - $week_result->{class}=~s/^\s+//g; + $week_result->{class} .= ' selected' + if ( ( defined $params->{from_date} ) && ( $start_date eq $params->{from_date} ) ) + || ( ( defined $params->{till_date} ) && ( $end_date eq $params->{till_date} ) ); + $week_result->{class} .= " week_$weekCounter"; + $week_result->{class} =~ s/^\s+//g; push @$weekResults, $week_result; - - push @$weekAndDayResults,{ - days=>$dayResults, - week=>[$week_result] - }; + + push @$weekAndDayResults, + { + days => $dayResults, + week => [$week_result] + }; $weekCounter++; - }#end week + } #end week - }#end month + } #end month - }#end year + } #end year - for my $weekday (@$weekdayResults){ + for my $weekday (@$weekdayResults) { $weekday->{start_date} = $start_date; $weekday->{end_date} = $end_date; } - + return { week_and_days => $weekAndDayResults, weekdays => $weekdayResults, @@ -304,117 +273,119 @@ sub get{ } -sub render{ -# my $out = $_[0]; +sub render($$$$) { + + # my $out = $_[0]; my $config = $_[1]; my $request = $_[2]; my $calendar = $_[3]; - my $parms =$request->{params}->{checked}; - my $debug=$config->{system}->{debug}; - - my $template_parameters=$calendar; - $template_parameters->{debug} = $config->{system}->{debug}; + my $parms = $request->{params}->{checked}; + my $template_parameters = $calendar; $template_parameters->{base_url} = $config->{locations}->{base_url}; $template_parameters->{cache_base_url} = $config->{cache}->{base_url}; - $template_parameters->{server_cache} = $config->{cache}->{server_cache} if ($config->{cache}->{server_cache}); - $template_parameters->{use_client_cache} = $config->{cache}->{use_client_cache} if ($config->{cache}->{use_client_cache}); + $template_parameters->{server_cache} = $config->{cache}->{server_cache} if ( $config->{cache}->{server_cache} ); + $template_parameters->{use_client_cache} = $config->{cache}->{use_client_cache} + if ( $config->{cache}->{use_client_cache} ); - template::process($_[0], $parms->{template}, $template_parameters); + template::process( $config, $_[0], $parms->{template}, $template_parameters ); } -sub get_calendar_weeks{ +sub get_calendar_weeks($$$) { my $config = shift; my $start = shift; my $end = shift; - my $debug = $config->{system}->{debug}; + $start = time::date_to_array($start); + $end = time::date_to_array($end); - $start = time::date_to_array($start); - $end = time::date_to_array($end); + my $start_year = int( $start->[0] ); + my $end_year = int( $end->[0] ); - my $start_year = int($start->[0]); - my $end_year = int($end->[0]); + my $start_month = int( $start->[1] ); + my $end_month = int( $end->[1] ); - my $start_month = int($start->[1]); - my $end_month = int($end->[1]); + my $years = {}; + for my $year ( $start_year .. $end_year ) { + my $months = {}; + for my $month ( $start_month .. $end_month ) { - my $years={}; - for my $year ($start_year..$end_year){ - my $months={}; - for my $month ($start_month..$end_month){ #get week arrays of days of the month - my $weeks=getWeeksOfMonth($year, $month); - $months->{$month}=$weeks; + my $weeks = getWeeksOfMonth( $year, $month ); + $months->{$month} = $weeks; } - $years->{$year}=$months; + $years->{$year} = $months; } - log::write($config, 'years',$years)if ($debug); - return $years; + return $years; } -sub getWeeksOfMonth{ +sub getWeeksOfMonth($$) { my $thisYear = shift; my $thisMonth = shift; my $thisDay = 1; # get weekday of 1st of month - my $thisMonthWeekday = Date::Calc::Day_of_Week($thisYear,$thisMonth,1); - + my $thisMonthWeekday = Date::Calc::Day_of_Week( $thisYear, $thisMonth, 1 ); + # get next month date - my($nextYear, $nextMonth, $nextDay)=Date::Calc::Add_Delta_YM($thisYear,$thisMonth,$thisDay, 0,1); + my ( $nextYear, $nextMonth, $nextDay ) = Date::Calc::Add_Delta_YM( $thisYear, $thisMonth, $thisDay, 0, 1 ); + # get weekday of 1st of next month - my $nextMonthWeekday = Date::Calc::Day_of_Week($nextYear, $nextMonth, $nextDay); - my($lastYear, $lastMonth, $lastDayOfMonth)=Date::Calc::Add_Delta_Days($nextYear,$nextMonth,$nextDay, -1); + my $nextMonthWeekday = Date::Calc::Day_of_Week( $nextYear, $nextMonth, $nextDay ); + my ( $lastYear, $lastMonth, $lastDayOfMonth ) = Date::Calc::Add_Delta_Days( $nextYear, $nextMonth, $nextDay, -1 ); # get date of 1st of row - my( $week,$year) = Date::Calc::Week_of_Year($thisYear,$thisMonth,$thisDay); - ($year,my $month, my $day) = Date::Calc::Monday_of_Week($week,$year); - - my @weeks=(); - my $weekday=1; + my ( $week, $year ) = Date::Calc::Week_of_Year( $thisYear, $thisMonth, $thisDay ); + ( $year, my $month, my $day ) = Date::Calc::Monday_of_Week( $week, $year ); + + my @weeks = (); + my $weekday = 1; { # first week - my @days=(); - for $weekday(0 .. $thisMonthWeekday-2){ - push @days, sprintf("%04d-%02d-%02d",$year,$month,$day); + my @days = (); + for $weekday ( 0 .. $thisMonthWeekday - 2 ) { + push @days, sprintf( "%04d-%02d-%02d", $year, $month, $day ); $day++; } + # set current month $month = $thisMonth; $year = $thisYear; $day = 1; - for $weekday($thisMonthWeekday..7){ - push @days, sprintf("%04d-%02d-%02d",$year,$month,$day); + for $weekday ( $thisMonthWeekday .. 7 ) { + push @days, sprintf( "%04d-%02d-%02d", $year, $month, $day ); $day++; } + # next week push @weeks, \@days; } - + # weeks until end of month - while(scalar(@weeks)<6){ - my @days=(); - $weekday=1; - while($weekday<=7){ - push @days, sprintf("%04d-%02d-%02d",$year,$month,$day); + while ( scalar(@weeks) < 6 ) { + my @days = (); + $weekday = 1; + while ( $weekday <= 7 ) { + push @days, sprintf( "%04d-%02d-%02d", $year, $month, $day ); $day++; $weekday++; - last if $day>$lastDayOfMonth; + last if $day > $lastDayOfMonth; } - if ($day>$lastDayOfMonth){ - # set next month - $month=$nextMonth; - $year=$nextYear; - $day=1; + if ( $day > $lastDayOfMonth ) { + + # set next month + $month = $nextMonth; + $year = $nextYear; + $day = 1; + + if ( $nextMonthWeekday != 1 ) { - if ($nextMonthWeekday!=1){ # finish end week - if($weekday<=7){ - while( $weekday<=7){ - push @days, sprintf("%04d-%02d-%02d",$year,$month,$day); + if ( $weekday <= 7 ) { + while ( $weekday <= 7 ) { + push @days, sprintf( "%04d-%02d-%02d", $year, $month, $day ); $day++; $weekday++; } @@ -422,15 +393,15 @@ sub getWeeksOfMonth{ } push @weeks, \@days; last; - }; + } push @weeks, \@days if $weeks[-1]->[-1] ne $days[-1]; - } - + } + #coming weeks - while(scalar(@weeks)<6){ - my @days=(); - for $weekday(1..7){ - push @days, sprintf("%04d-%02d-%02d",$year,$month,$day); + while ( scalar(@weeks) < 6 ) { + my @days = (); + for $weekday ( 1 .. 7 ) { + push @days, sprintf( "%04d-%02d-%02d", $year, $month, $day ); $day++; } push @weeks, \@days; @@ -438,79 +409,58 @@ sub getWeeksOfMonth{ return \@weeks; } -sub configure_cache{ +sub check_params($$) { my $config = shift; - my $debug=$config->{system}->{debug}; - - cache::init(); - - my $date_pattern = $cache::date_pattern; - my $controllers = $config->{controllers}; - - cache::add_map('' , $controllers->{calendar}.'/cal.html'); - cache::add_map('date='.$date_pattern , $controllers->{calendar}.'/$1-$2.html'); - cache::add_map('from_date='.$date_pattern.'&till_date='.$date_pattern , $controllers->{calendar}.'/$1-$2_$5-$6.html'); - - log::write($config, 'cache_files',cache::get_map()) if ($debug); -} - -sub check_params{ - my $config=shift; - my $params=shift; + my $params = shift; #get start and stop from projects - my $range= project::get_date_range($config); + my $range = project::get_date_range($config); my $start_date = $range->{start_date}; my $end_date = $range->{end_date}; #switch off limiting end date by project - my $open_end=0; - if((defined $params->{'open_end'})&&($params->{'open_end'}=~/(\d+)/)){ + my $open_end = 0; + if ( ( defined $params->{'open_end'} ) && ( $params->{'open_end'} =~ /(\d+)/ ) ) { $open_end = $1; - $end_date = time::add_days_to_datetime(time::time_to_datetime(), 365); + $end_date = time::add_days_to_datetime( time::time_to_datetime(), 365 ); } - my $month_only=$params->{month_only}||''; + my $month_only = $params->{month_only} || ''; #filter for date - my $date=time::check_date($params->{date}); + my $date = time::check_date( $params->{date} ); - $date =$start_date if ($date lt $start_date); - $date =$end_date if ($date gt $end_date); - log::error($config, "no valid year-month format given!") if ($date eq"-1"); + $date = $start_date if ( $date lt $start_date ); + $date = $end_date if ( $date gt $end_date ); + log::error( $config, "no valid year-month format given!" ) if ( $date eq "-1" ); - my $time=time::check_time($params->{time}); - log::error($config, "no valid time format given!") if ($time eq"-1"); + my $time = time::check_time( $params->{time} ); + log::error( $config, "no valid time format given!" ) if ( $time eq "-1" ); - my $from_date=time::check_date($params->{from_date})||''; - log::error($config, "no valid date format given!") if (defined $from_date && $from_date eq"-1"); - $from_date =$start_date if ($from_date lt $start_date); - $from_date =$end_date if ($from_date gt $end_date); + my $from_date = time::check_date( $params->{from_date} ) || ''; + log::error( $config, "no valid date format given!" ) if ( defined $from_date && $from_date eq "-1" ); + $from_date = $start_date if ( $from_date lt $start_date ); + $from_date = $end_date if ( $from_date gt $end_date ); - my $till_date=time::check_date($params->{till_date}||''); - log::error($config, "no valid date format given!") if (defined $till_date && $till_date eq"-1"); - $till_date =$start_date if ($till_date lt $start_date); - $till_date =$end_date if ($till_date gt $end_date); + my $till_date = time::check_date( $params->{till_date} || '' ); + log::error( $config, "no valid date format given!" ) if ( defined $till_date && $till_date eq "-1" ); + $till_date = $start_date if ( $till_date lt $start_date ); + $till_date = $end_date if ( $till_date gt $end_date ); - my $template=template::check($params->{template},'calendar.html'); - - my $debug=$params->{debug}; - if ((defined $debug) && ($debug=~/([a-z\_\,]+)/)){ - $debug=$1; - } + my $template = template::check( $config, $params->{template}, 'calendar.html' ); return { - template => $template, - date => $date, - from_date => $from_date, - till_date => $till_date, - debug => $debug, - month_only => $month_only, - open_end => $open_end, - start_date => $start_date, - end_date => $end_date - } + template => $template, + date => $date, + from_date => $from_date, + till_date => $till_date, + month_only => $month_only, + open_end => $open_end, + start_date => $start_date, + end_date => $end_date + }; } + #do not delete last line! 1; diff --git a/lib/calcms/comments.pm b/lib/calcms/comments.pm index d1078e1..e6c1991 100644 --- a/lib/calcms/comments.pm +++ b/lib/calcms/comments.pm @@ -1,258 +1,243 @@ -use warnings "all"; -use strict; -use Data::Dumper; -use config; -use template; -use time; +package comments; -package comments; -use warnings "all"; use strict; +use warnings; +no warnings 'redefine'; use Data::Dumper; -require Exporter; -our @ISA = qw(Exporter); -#our @EXPORT = qw(all); -our @EXPORT_OK = qw(init get_cached_or_render get modify_results render configure_cache get_query get_by_event get_level get_events check insert set_lock_status set_news_status lock update_comment_count sort); -our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ] ); +use db(); +use config(); +use markup(); +use template(); +use time(); -sub init{ +#use base 'Exporter'; +our @EXPORT_OK = + qw(init get_cached_or_render get modify_results render configure_cache get_query get_by_event get_level get_events check insert set_lock_status set_news_status lock update_comment_count sort); + +sub init() { } -sub get_cached_or_render{ -# my $response=$_[0]; +sub get_cached_or_render($$$;$) { + + # my $response=$_[0]; my $config = $_[1]; my $request = $_[2]; my $mark_locked = $_[3]; - my $params=$request->{params}->{checked}; - #print STDERR Dumper($params); - $config->{app_name}=$config->{controllers}->{comments}; + my $params = $request->{params}->{checked}; + $config->{app_name} = $config->{controllers}->{comments}; - my $comment=$request->{params}->{checked}; + my $comment = $request->{params}->{checked}; + my $filename = ''; + my $results = comments::get( $config, $request ); - my $filename=''; - my $cache={}; - - my $results=comments::get($config, $request); - - if((defined $mark_locked) && ($mark_locked eq 'mark_locked')){ - for my $result(@$results){ - if($result->{lock_status}ne'show'){ - $result->{author}='Zensur'; - $result->{content}='Dieser Eintrag wurde gelöscht.'; + if ( ( defined $mark_locked ) && ( $mark_locked eq 'mark_locked' ) ) { + for my $result (@$results) { + if ( $result->{lock_status} ne 'show' ) { + $result->{author} = 'Zensur'; + $result->{content} = 'Dieser Eintrag wurde gelöscht.'; } } - }elsif((defined $mark_locked) && ($mark_locked eq 'filter_locked')){ - my @results2=(); - for my $result(@$results){ - push @results2, $result if($result->{lock_status}eq'show'); + } elsif ( ( defined $mark_locked ) && ( $mark_locked eq 'filter_locked' ) ) { + my @results2 = (); + for my $result (@$results) { + push @results2, $result if ( $result->{lock_status} eq 'show' ); } - $results=\@results2; + $results = \@results2; } - comments::modify_results($results, $config, $request); + comments::modify_results( $results, $config, $request ); - #print STDERR Dumper($results); - $results=comments::sort($config, $results) if ($comment->{type}eq'tree'); + $results = comments::sort( $config, $results ) if ( $comment->{type} eq 'tree' ); - #print STDERR Dumper($results); -# if ($comment->{sort_order}eq'desc'){ -# my @results= reverse(@$results); -# $results=\@results; -# } - - if ( - ($params->{show_max} ne'') - && ($params->{limit} ne'') - && ($params->{show_max}<$params->{limit}) - ){ - my @results2=(); - my $c=0; - for my $result(@$results){ - push @results2,$result; + if ( ( $params->{show_max} ne '' ) + && ( $params->{limit} ne '' ) + && ( $params->{show_max} < $params->{limit} ) ) + { + my @results2 = (); + my $c = 0; + for my $result (@$results) { + push @results2, $result; $c++; - last if ($c>=$params->{show_max}); + last if ( $c >= $params->{show_max} ); } - $results=\@results2; + $results = \@results2; } - comments::render($_[0], $config, $request, $results); + comments::render( $_[0], $config, $request, $results ); } -sub get{ - my $config = shift; - my $request= shift; +sub get($$) { + my $config = shift; + my $request = shift; - my $params=$request->{params}->{checked}; - - my $dbh=db::connect($config, $request); - - (my $query, my $bind_values)=comments::get_query($dbh, $config, $request); - #print STDERR Dumper($$query); - #print STDERR Dumper($bind_values); - my $results=db::get($dbh, $$query, $bind_values); - #print STDERR Dumper($results); + my $params = $request->{params}->{checked}; + my $dbh = db::connect( $config, $request ); + ( my $query, my $bind_values ) = comments::get_query( $dbh, $config, $request ); + my $results = db::get( $dbh, $$query, $bind_values ); return $results; } -sub get_query{ - my $dbh = shift; - my $config = shift; - my $request=shift; +sub get_query($$$) { + my $dbh = shift; + my $config = shift; + my $request = shift; - my $params=$request->{params}->{checked}; + my $params = $request->{params}->{checked}; my $event_id = undef; my $event_start = undef; my $from = 'calcms_comments c'; my $where = ''; my $limit = ''; - my @conditions=(); - my $bind_values=[]; + my @conditions = (); + my $bind_values = []; - #exclude comments from config filter/exclude_locations - if ( - (defined $config->{filter}) - && (defined $config->{filter}->{exclude_locations}) - ){ - my @exclude_locations=split(/[,\s]+/,$config->{filter}->{exclude_locations}); - my $exclude_locations=join(', ',map {'?'} @exclude_locations); - - $from.=',calcms_events e'; - push @conditions,'e.id=c.event_id'; - push @conditions,'e.location not in ('.$exclude_locations.')'; - for my $location (@exclude_locations){ + #exclude comments from config filter/locations_to_exclude + if ( ( defined $config->{filter} ) + && ( defined $config->{filter}->{locations_to_exclude} ) ) + { + my @locations_to_exclude = split( /[,\s]+/, $config->{filter}->{locations_to_exclude} ); + my $locations_to_exclude = join( ', ', map { '?' } @locations_to_exclude ); + + $from .= ',calcms_events e'; + push @conditions, 'e.id=c.event_id'; + push @conditions, 'e.location not in (' . $locations_to_exclude . ')'; + for my $location (@locations_to_exclude) { push @$bind_values, $location; } } - if ( - (defined $params->{event_id} && $params->{event_id}ne'') && - (defined $params->{event_start} && $params->{event_start}ne'') - ){ + if ( ( defined $params->{event_id} && $params->{event_id} ne '' ) + && ( defined $params->{event_start} && $params->{event_start} ne '' ) ) + { #$where =qq{ and (event_id=? or event_start=?) }; - push @conditions, q{ (event_id=? or event_start=?) }; + push @conditions, q{ (event_id=? or event_start=?) }; push @$bind_values, $params->{event_id}; push @$bind_values, $params->{event_start}; } - my $sort_order=$params->{sort_order}; + my $sort_order = $params->{sort_order}; - if ($params->{limit} ne''){ - $limit ='limit ?'; - push @$bind_values,$params->{limit}; + if ( $params->{limit} ne '' ) { + $limit = 'limit ?'; + push @$bind_values, $params->{limit}; } - if (@conditions>0){ - $where= 'where '.join(' and ',@conditions); + if ( @conditions > 0 ) { + $where = 'where ' . join( ' and ', @conditions ); } - my $dbcols=['id', 'event_start', 'event_id', 'content', 'ip', 'author', 'email', - 'lock_status', 'created_at', 'title', 'parent_id', 'level', 'news_status', 'project']; - my $cols=join(', ',map { 'c.'.$_ } @$dbcols); - my $query=qq{ + my $dbcols = [ + 'id', 'event_start', 'event_id', 'content', 'ip', 'author', + 'email', 'lock_status', 'created_at', 'title', 'parent_id', 'level', + 'news_status', 'project' + ]; + my $cols = join( ', ', map { 'c.' . $_ } @$dbcols ); + my $query = qq{ select $cols from $from $where order by created_at $sort_order $limit }; -# where lock_status='show' -# use Data::Dumper;print STDERR Dumper($query); - return (\$query, $bind_values); + return ( \$query, $bind_values ); } -sub modify_results{ +sub modify_results($$$) { my $results = $_[0]; my $config = $_[1]; my $request = $_[2]; - my $params=$request->{params}->{checked}; + my $params = $request->{params}->{checked}; - my $time_diff=''; - if ($params->{template}=~/\.xml/){ - $time_diff=time::utc_offset($config->{date}->{time_zone}); - $time_diff=~s/(\d\d)(\d\d)/$1\:$2/g; + my $time_diff = ''; + if ( $params->{template} =~ /\.xml/ ) { + $time_diff = time::utc_offset( $config->{date}->{time_zone} ); + $time_diff =~ s/(\d\d)(\d\d)/$1\:$2/g; } my $language = $config->{date}->{language} || 'en'; - - for my $result (@$results){ - $result->{allow}->{new_comments} = 1 if ($params->{allow}->{new_comments}); - $result->{start_date_name} = time::date_format($result->{created_at}, $language); - $result->{start_time_name} = time::time_format($result->{created_at}); - my $comment_limit=100; - if (length($result->{content})>$comment_limit){ - $result->{short_content} = substr($result->{content},0,$comment_limit).'...' ; - }else{ - $result->{short_content} = $result->{content}; + + for my $result (@$results) { + $result->{allow}->{new_comments} = 1 if ( $params->{allow}->{new_comments} ); + $result->{start_date_name} = time::date_format( $config, $result->{created_at}, $language ); + $result->{start_time_name} = time::time_format( $result->{created_at} ); + my $comment_limit = 100; + if ( length( $result->{content} ) > $comment_limit ) { + $result->{short_content} = substr( $result->{content}, 0, $comment_limit ) . '...'; + } else { + $result->{short_content} = $result->{content}; } - $result->{base_url} = $config->{locations}->{base_url}; - $result->{cache_base_url} = $config->{cache}->{base_url}; + $result->{base_url} = $config->{locations}->{base_url}; + $result->{cache_base_url} = $config->{cache}->{base_url}; - if($params->{template}=~/\.xml/){ -# $result->{content} =~s/(\[\[.*?\]\])//gi; -# $result->{content} =markup::plain_to_xml($result->{content}); -# $result->{content} =$result->{html_content}; + if ( $params->{template} =~ /\.xml/ ) { - $result->{content} = markup::html_to_plain($result->{html_content}); - $result->{short_content}= markup::html_to_plain($result->{short_content}); - $result->{excerpt} = "lass dich ueberraschen" if ((defined $result->{excerpt}) && ($result->{excerpt}eq'')); - $result->{excerpt} = markup::html_to_plain($result->{excerpt}); - $result->{title} = markup::html_to_plain($result->{title}); - $result->{series_name} = markup::html_to_plain($result->{series_name}); - $result->{program} = markup::html_to_plain($result->{program}); + # $result->{content} =~s/(\[\[.*?\]\])//gi; + # $result->{content} =markup::plain_to_xml($result->{content}); + # $result->{content} =$result->{html_content}; - if (defined $result->{created_at}){ - $result->{created_at}=~s/ /T/gi; - $result->{created_at}.=$time_diff; + $result->{content} = markup::html_to_plain( $result->{html_content} ); + $result->{short_content} = markup::html_to_plain( $result->{short_content} ); + $result->{excerpt} = "lass dich ueberraschen" + if ( defined $result->{excerpt} ) && ( $result->{excerpt} eq '' ); + $result->{excerpt} = markup::html_to_plain( $result->{excerpt} ); + $result->{title} = markup::html_to_plain( $result->{title} ); + $result->{series_name} = markup::html_to_plain( $result->{series_name} ); + $result->{program} = markup::html_to_plain( $result->{program} ); + + if ( defined $result->{created_at} ) { + $result->{created_at} =~ s/ /T/gi; + $result->{created_at} .= $time_diff; } - if (defined $result->{modified_at}){ - $result->{modified_at}=~s/ /T/gi; - $result->{modified_at}.=$time_diff; + if ( defined $result->{modified_at} ) { + $result->{modified_at} =~ s/ /T/gi; + $result->{modified_at} .= $time_diff; } } } return $results; } +sub render($$$$) { -sub render{ -# my $response =$_[0]; + # my $response =$_[0]; my $config = $_[1]; my $request = $_[2]; my $results = $_[3]; - my $params =$request->{params}->{checked}; + my $params = $request->{params}->{checked}; - my %template_parameters=%$params; - my $template_parameters=\%template_parameters; + my %template_parameters = %$params; + my $template_parameters = \%template_parameters; - $template_parameters->{comments} = $results; - $template_parameters->{comment_count} =(@$results)+0; - $template_parameters->{one_result} =1 if($template_parameters->{comment_count}==1); - $template_parameters->{allow}->{new_comments} =1 if ($params->{allow}->{new_comments}); + $template_parameters->{comments} = $results; + $template_parameters->{comment_count} = scalar(@$results) + 0; + $template_parameters->{one_result} = 1 if ( $template_parameters->{comment_count} == 1 ); + $template_parameters->{allow}->{new_comments} = 1 if ( $params->{allow}->{new_comments} ); - $template_parameters->{event_id} = $params->{event_id}; - $template_parameters->{event_start} = $params->{event_start}; + $template_parameters->{event_id} = $params->{event_id}; + $template_parameters->{event_start} = $params->{event_start}; - $template_parameters->{server_cache} = $config->{cache}->{server_cache} if ($config->{cache}->{server_cache}); - $template_parameters->{use_client_cache}= $config->{cache}->{use_client_cache} if ($config->{cache}->{use_client_cache}); - $template_parameters->{controllers} = $config->{controllers}; - template::process($_[0],$params->{template},$template_parameters); + $template_parameters->{server_cache} = $config->{cache}->{server_cache} if ( $config->{cache}->{server_cache} ); + $template_parameters->{use_client_cache} = $config->{cache}->{use_client_cache} + if ( $config->{cache}->{use_client_cache} ); + $template_parameters->{controllers} = $config->{controllers}; + template::process( $config, $_[0], $params->{template}, $template_parameters ); } #check if comment exists already -sub check{ +sub check ($$$) { my $dbh = shift; my $config = shift; my $comment = shift; - my $query=qq{ + my $query = qq{ select id from calcms_comments where ( @@ -264,38 +249,34 @@ sub check{ and ip=? and content=? }; - my $bind_values=[ - $comment->{event_start}, - $comment->{event_id}, - $comment->{parent_id}, - $comment->{author}, - $comment->{ip}, - $comment->{content} + my $bind_values = [ + $comment->{event_start}, $comment->{event_id}, $comment->{parent_id}, + $comment->{author}, $comment->{ip}, $comment->{content} ]; - my $comments=db::get($dbh,$query,$bind_values); + my $comments = db::get( $dbh, $query, $bind_values ); - my @comments=@$comments; - return 0 if (@comments>0); + my @comments = @$comments; + return 0 if scalar @comments > 0; return 1; } #used for insert -sub get_level{ +sub get_level($$$) { my $dbh = shift; my $config = shift; my $comment = shift; - my $parent_id=$comment->{parent_id}; + my $parent_id = $comment->{parent_id}; return 0 unless defined $parent_id; - if($parent_id=~/(\d+)/){ - $parent_id=$1; + if ( $parent_id =~ /(\d+)/ ) { + $parent_id = $1; } - return 0 unless $parent_id=~/^\d+$/; - return 0 if $parent_id==0; + return 0 unless $parent_id =~ /^\d+$/; + return 0 if $parent_id == 0; #get level from parent node - my $query=qq{ + my $query = qq{ select level from calcms_comments where ( @@ -305,80 +286,68 @@ sub get_level{ and id=? limit 1 }; - my $bind_values=[ - $comment->{event_start}, - $comment->{event_id}, - $parent_id - ]; + my $bind_values = [ $comment->{event_start}, $comment->{event_id}, $parent_id ]; - my $comments=db::get($dbh,$query,$bind_values); + my $comments = db::get( $dbh, $query, $bind_values ); - my @comments=@$comments; - if (@comments>0){ - return $comments->[0]->{level}+1; + my @comments = @$comments; + if ( scalar @comments > 0 ) { + return $comments->[0]->{level} + 1; } return 0; } -sub get_by_event{ +sub get_by_event($$$) { my $dbh = shift; my $config = shift; - my $request =$_[0]; + my $request = $_[0]; my $params = $request->{params}->{checked}->{comment}; - my $event_id = undef; - my $search = undef; - my $where = ''; - my $limit = ''; - my $bind_values=[]; + my $event_id = undef; + my $search = undef; + my $where = ''; + my $limit = ''; + my $bind_values = []; - if ($params->{event_id}ne''){ - $where =qq{ event_id=? }; - $bind_values=[$params->{event_id}]; + if ( $params->{event_id} ne '' ) { + $where = qq{ event_id=? }; + $bind_values = [ $params->{event_id} ]; } - if ((defined $params->{search}) && ($params->{search}ne'')){ - $search ='%'.$params->{search}.'%'; - $where =qq{ (content like ?) or (email like ?) or (author like ?) or (ip like ?)}; - $bind_values=[ - $search, - $search, - $search, - $search - ]; + if ( ( defined $params->{search} ) && ( $params->{search} ne '' ) ) { + $search = '%' . $params->{search} . '%'; + $where = qq{ (content like ?) or (email like ?) or (author like ?) or (ip like ?)}; + $bind_values = [ $search, $search, $search, $search ]; } - my $sort_order=$params->{sort_order} || 'desc'; + my $sort_order = $params->{sort_order} || 'desc'; - if ((defined $params->{limit}) && ($params->{limit} ne'')){ - $limit ='limit ?'; - push @$bind_values,$params->{limit}; + if ( ( defined $params->{limit} ) && ( $params->{limit} ne '' ) ) { + $limit = 'limit ?'; + push @$bind_values, $params->{limit}; } - my $query=qq{ + my $query = qq{ select * from calcms_comments where $where order by created_at $sort_order $limit }; - - #print STDERR $query."\n"; - my $comments=db::get($dbh, $query, $bind_values); - + my $comments = db::get( $dbh, $query, $bind_values ); return $comments; } -sub get_by_time{ +sub get_by_time($$$) { my $dbh = shift; my $config = shift; my $comment = shift; - my $where=''; - my $bind_values=[]; - if ($comment->{age} ne ''){ - $where=qq{ + my $where = ''; + my $bind_values = []; + if ( $comment->{age} ne '' ) { + $where = qq{ where event_id in ( select distinct event_id from calcms_comments @@ -387,11 +356,9 @@ sub get_by_time{ ) ) }; - $bind_values=[ - $comment->{age}*3600, - ]; - }elsif (($comment->{from} ne '') && ($comment->{till} ne '')){ - $where=qq{ + $bind_values = [ $comment->{age} * 3600, ]; + } elsif ( ( $comment->{from} ne '' ) && ( $comment->{till} ne '' ) ) { + $where = qq{ where event_id in ( select distinct event_id from calcms_comments @@ -399,96 +366,90 @@ sub get_by_time{ and created_at <= ? ) }; - $bind_values=[ - $comment->{from}, - $comment->{till} - ]; + $bind_values = [ $comment->{from}, $comment->{till} ]; } - my $query=qq{ + my $query = qq{ select * from calcms_comments $where order by event_id, id }; - my $comments=db::get($dbh, $query, $bind_values); + my $comments = db::get( $dbh, $query, $bind_values ); return $comments; } -sub get_events{ - my $dbh=shift; - my $config = shift; - my $request=shift; - my $comments=shift; +sub get_events($$$$) { + my $dbh = shift; + my $config = shift; + my $request = shift; + my $comments = shift; - my $params=$request->{params}->{checked}->{comment}; + my $params = $request->{params}->{checked}->{comment}; #get event_ids from comments - my $event_ids={}; - for my $comment (@$comments){ - my $event_id=$comment->{event_id}; - $event_ids->{$event_id}=1; - } - + my $event_ids = { map { $_->{event_id} => 1 } @$comments }; + my @keys = keys %{$event_ids}; #get events from comment's event ids - return [] if ((keys %{$event_ids})==0); + return [] if ( scalar @keys ) == 0; - #my $quoted_event_ids=join "," ,(map {$dbh->quote($_)}(keys %{$event_ids})); - my @bind_values=keys %{$event_ids}; - my $event_id_values=join "," ,(map {'?'}(keys %{$event_ids})); + #my $quoted_event_ids=join "," ,(map {$dbh->quote($_)}(@keys)); + my @bind_values = @keys; + my $event_id_values = join ",", ( map { '?' } ( @keys ) ); - my $query=qq{ + my $query = qq{ select id, start, program, series_name, title, excerpt from calcms_events where id in ($event_id_values) }; - my $events=db::get($dbh, $query, \@bind_values); + my $events = db::get( $dbh, $query, \@bind_values ); #build lookup table for events by id - my $events_by_id={}; - for my $event (@$events){ - $events_by_id->{$event->{id}}=$event; - $event->{max_comment_id}=0; + my $events_by_id = {}; + for my $event (@$events) { + $events_by_id->{ $event->{id} } = $event; + $event->{max_comment_id} = 0; } #add unassigned events -# for my $event_id (keys %{$event_ids}){ -# if ($events_by_id->{$event_id}eq''){ -# my $event={ -# title => "not assigned", -# max_comment_id => 0 -# -# }; -# push @$events,$event; -# $events_by_id->{$event_id}=$event; -# } -# } + # for my $event_id (@keys){ + # if ($events_by_id->{$event_id}eq''){ + # my $event={ + # title => "not assigned", + # max_comment_id => 0 + # + # }; + # push @$events,$event; + # $events_by_id->{$event_id}=$event; + # } + # } - for my $comment (@$comments){ - my $event_id=$comment->{event_id}; - my $event=$events_by_id->{$event_id}; - next unless (defined $event); + for my $comment (@$comments) { + my $event_id = $comment->{event_id}; + my $event = $events_by_id->{$event_id}; + next unless defined $event; $event->{comment_count}++; - push @{$event->{comments}},$comment;# if ($params->{event_id}ne''); - $event->{max_comment_id}=$comment->{id} if ($comment->{id} > $event->{max_comment_id}); - for my $name (keys %{$config->{controllers}}){ - $comment->{"controller_".$name}=$config->{controllers}->{$name}||''; -# $event->{"controller_$name"}=$config->{controllers}->{$name}; + push @{ $event->{comments} }, $comment; # if ($params->{event_id}ne''); + $event->{max_comment_id} = $comment->{id} if $comment->{id} > $event->{max_comment_id}; + for my $name ( keys %{ $config->{controllers} } ) { + $comment->{ "controller_" . $name } = $config->{controllers}->{$name} || ''; + + # $event->{"controller_$name"}=$config->{controllers}->{$name}; } } - my @sorted_events=reverse sort {$a->{max_comment_id} <=> $b->{max_comment_id}} @$events; + my @sorted_events = reverse sort { $a->{max_comment_id} <=> $b->{max_comment_id} } @$events; return \@sorted_events; } -sub insert{ +sub insert ($$$) { my $dbh = shift; my $config = shift; my $comment = shift; - $comment->{level}=comments::get_level($dbh, $config, $comment); + $comment->{level} = comments::get_level( $dbh, $config, $comment ); - my $entry={ - event_start => $comment->{event_start}, + my $entry = { + event_start => $comment->{event_start}, event_id => $comment->{event_id}, parent_id => $comment->{parent_id}, level => $comment->{level}, @@ -499,214 +460,193 @@ sub insert{ ip => $comment->{ip} }; - my $comment_id=db::insert($dbh, 'calcms_comments', $entry); + my $comment_id = db::insert( $dbh, 'calcms_comments', $entry ); return $comment_id; } -sub set_lock_status{ - my $dbh=shift; - my $config = shift; - my $comment=shift; +sub set_lock_status ($$$) { + my $dbh = shift; + my $config = shift; + my $comment = shift; my $id = $comment->{id}; my $lock_status = $comment->{set_lock_status}; - my $query=qq{ + my $query = qq{ update calcms_comments set lock_status = ? where id = ? }; - my $bind_values=[ - $lock_status, - $id - ]; - db::put($dbh,$query,$bind_values); + my $bind_values = [ $lock_status, $id ]; + db::put( $dbh, $query, $bind_values ); - $query=qq{ + $query = qq{ select event_id from calcms_comments where id=? }; - $bind_values=[$id]; - my $comments=db::get($dbh,$query,$bind_values); - if (@$comments>0){ - $comment->{event_id}=$comments->[0]->{event_id}; - update_comment_count($dbh,$comment); + $bind_values = [$id]; + my $comments = db::get( $dbh, $query, $bind_values ); + if ( scalar @$comments > 0 ) { + $comment->{event_id} = $comments->[0]->{event_id}; + update_comment_count( $dbh, $config, $comment ); } } -sub set_news_status{ - my $dbh=shift; - my $config = shift; - my $comment=shift; +sub set_news_status($$$) { + my $dbh = shift; + my $config = shift; + my $comment = shift; my $id = $comment->{id}; my $news_status = $comment->{set_news_status}; - my $query=qq{ + my $query = qq{ update calcms_comments set news_status= ? where id = ? }; - my $bind_values=[$news_status,$id]; - db::put($dbh,$query,$bind_values); + my $bind_values = [ $news_status, $id ]; + db::put( $dbh, $query, $bind_values ); } -sub update_comment_count{ - my $dbh=shift; - my $config = shift; - my $comment=shift; +sub update_comment_count ($$$) { + my $dbh = shift; + my $config = shift; + my $comment = shift; - my $query=qq{ + my $query = qq{ select count(id) count from calcms_comments where lock_status='show' and event_id=? }; - my $bind_values=[$comment->{event_id}]; - my $comments=db::get($dbh,$query,$bind_values); + my $bind_values = [ $comment->{event_id} ]; + my $comments = db::get( $dbh, $query, $bind_values ); - my $count=0; - $count=$comments->[0]->{count} if (@$comments>0); - $query=qq{ + my $count = 0; + $count = $comments->[0]->{count} if scalar @$comments > 0; + $query = qq{ update calcms_events set comment_count=? where id=? }; - $bind_values=[ - $count, - $comment->{event_id} - ]; - db::put($dbh,$query,$bind_values); + $bind_values = [ $count, $comment->{event_id} ]; + db::put( $dbh, $query, $bind_values ); +} + +sub sort_childs { + my $node = shift; + my $nodes = shift; + my $sorted_nodes = shift; + + #push node into list of sorted nodes + push @{$sorted_nodes}, $node; + + #return if node is leaf + return $sorted_nodes unless defined $node->{childs}; + + #process child nodes + for my $child ( @{ $node->{childs} } ) { + $sorted_nodes = sort_childs( $child, $nodes, $sorted_nodes ); + } + return $sorted_nodes; } #precondition: results are presorted by creation date (by sql) -sub sort{ - my $config = shift; - my $results=shift; +sub sort($$) { + my $config = shift; + my $results = shift; #define parent nodes - my $nodes={}; - for my $node (@$results){ - $nodes->{$node->{id}}=$node; + my $nodes = {}; + for my $node (@$results) { + $nodes->{ $node->{id} } = $node; } - my @root_nodes=(); - for my $node (@$results){ + my @root_nodes = (); + for my $node (@$results) { + #fill childs into parent nodes - push @{$nodes->{$node->{parent_id}}->{childs}},$node; + push @{ $nodes->{ $node->{parent_id} }->{childs} }, $node; + #define root nodes - push @root_nodes,$node if ($node->{level}==0); + push @root_nodes, $node if ( $node->{level} == 0 ); } - #print STDERR Dumper(\@root_nodes); #sort root nodes from newest to oldest - my $sorted_nodes=[]; - for my $node (@root_nodes){ - #for my $node (reverse @root_nodes){ - sort_childs($node,$nodes,$sorted_nodes); + my $sorted_nodes = []; + for my $node (@root_nodes) { + + #for my $node (reverse @root_nodes){ + sort_childs( $node, $nodes, $sorted_nodes ); } return $sorted_nodes; } -sub sort_childs{ - my $node=shift; - my $nodes=shift; - my $sorted_nodes=shift; +sub check_params ($$) { + my $config = shift; + my $params = shift; + my $comment = {}; - #push node into list of sorted nodes - push @{$sorted_nodes},$node; - - #return if node is leaf - return $sorted_nodes unless (defined $node->{childs}); - - #process child nodes - for my $child (@{$node->{childs}}){ - $sorted_nodes=sort_childs($child,$nodes,$sorted_nodes); - } - return $sorted_nodes; -} - -sub configure_cache{ - my $config = shift; - - cache::init(); - - my $date_pattern = $cache::date_pattern; - my $datetime_pattern = $cache::datetime_pattern; - my $controllers = $config->{controllers}; - - cache::add_map('template=comments_newest&limit=3&type=list' ,$controllers->{comments}.'/neueste.html'); - cache::add_map('template=comments_atom.xml&limit=20' ,$controllers->{comments}.'/feed.xml'); - cache::add_map('template=comments.html&event_id=(\d+)&event_start='.$datetime_pattern ,$controllers->{comments}.'/$1_$2-$3-$4_$5-$6.html'); -} - -sub check_params{ - my $config = shift; - my $params = shift; - - my $comment={}; - - $comment->{event_start}=''; - if ( (defined $params->{event_start}) && ($params->{event_start}=~/(\d\d\d\d\-\d\d\-\d\d[T ]\d\d\:\d\d)(\:\d\d)?/) ){ - $comment->{event_start}=$1; + $comment->{event_start} = ''; + if ( ( defined $params->{event_start} ) + && ( $params->{event_start} =~ /(\d\d\d\d\-\d\d\-\d\d[T ]\d\d\:\d\d)(\:\d\d)?/ ) ) + { + $comment->{event_start} = $1; } - $comment->{sort_order}='desc'; - $comment->{limit}=''; - if ( (defined $params->{limit}) && ($params->{limit}=~/(\d+)/) ){ - $comment->{limit}=$1; + $comment->{sort_order} = 'desc'; + $comment->{limit} = ''; + if ( ( defined $params->{limit} ) && ( $params->{limit} =~ /(\d+)/ ) ) { + $comment->{limit} = $1; } - $comment->{show_max}=''; - if ( (defined $params->{show_max}) && ($params->{show_max}=~/(\d+)/) ){ - $comment->{show_max}=$1; + $comment->{show_max} = ''; + if ( ( defined $params->{show_max} ) && ( $params->{show_max} =~ /(\d+)/ ) ) { + $comment->{show_max} = $1; } - if ( (defined $params->{sort_order}) && ($params->{sort_order}eq'asc') ){ - $comment->{sort_order}='asc'; + if ( ( defined $params->{sort_order} ) && ( $params->{sort_order} eq 'asc' ) ) { + $comment->{sort_order} = 'asc'; } - $comment->{event_id}=''; - if ( (defined $params->{event_id}) && ($params->{event_id}=~/(\d+)/) ){ - $comment->{event_id}=$1; + $comment->{event_id} = ''; + if ( ( defined $params->{event_id} ) && ( $params->{event_id} =~ /(\d+)/ ) ) { + $comment->{event_id} = $1; } - if ( (defined $params->{parent_id}) && ($params->{parent_id}=~/(\d+)/) ){ - $comment->{parent_id}=$1; + if ( ( defined $params->{parent_id} ) && ( $params->{parent_id} =~ /(\d+)/ ) ) { + $comment->{parent_id} = $1; } - if ((defined $params->{type}) && ($params->{type} eq 'list')){ - $comment->{type}='list'; - }else{ - $comment->{type}='tree'; + if ( ( defined $params->{type} ) && ( $params->{type} eq 'list' ) ) { + $comment->{type} = 'list'; + } else { + $comment->{type} = 'tree'; } - my $debug=$params->{debug}||''; - if ($debug=~/([a-z\_\,]+)/){ - $comment->{debug}=$1; + log::error( $config, 'missing parameter a' ) if ( defined $params->{limit} ) && ( $comment->{limit} eq '' ); + log::error( $config, 'missing parameter b' ) if ( defined $params->{event_id} ) && ( $comment->{event_id} eq '' ); + log::error( $config, 'missing parameter c' ) + if ( defined $params->{event_start} ) && ( $comment->{event_start} eq '' ); + + my $delta_days = 1; + if ( $comment->{event_start} ne '' ) { + my $today = time::datetime_to_array( time::time_to_datetime() ); + my $date = time::datetime_to_array( $comment->{event_start} ); + $delta_days = time::days_between( $today, $date ); + } + if ( ( $delta_days > $config->{permissions}->{no_new_comments_before} ) + || ( $delta_days < -1 * $config->{permissions}->{no_new_comments_after} ) ) + { + $comment->{allow}->{new_comments} = 0; + } else { + $comment->{allow}->{new_comments} = 1; } - log::error($config, 'missing parameter a') if ( (defined $params->{limit}) && ($comment->{limit} eq'') ); - log::error($config, 'missing parameter b') if ( (defined $params->{event_id}) && ($comment->{event_id} eq'') ); - log::error($config, 'missing parameter c') if ( (defined $params->{event_start}) && ($comment->{event_start} eq'') ); - - my $delta_days=1; - if ($comment->{event_start}ne''){ - my $today = time::datetime_to_array(time::time_to_datetime()); - my $date = time::datetime_to_array($comment->{event_start}); - $delta_days = time::days_between($today,$date); - } - if( - ($delta_days > $config->{permissions}->{no_new_comments_before} ) - || ($delta_days < -1*$config->{permissions}->{no_new_comments_after} ) - ){ - $comment->{allow}->{new_comments}=0; - }else{ - $comment->{allow}->{new_comments}=1; - } - - $comment->{template}=template::check($params->{template},'comments.html'); + $comment->{template} = template::check( $config, $params->{template}, 'comments.html' ); return $comment; } #do not delete last line! 1; + diff --git a/lib/calcms/config.pm b/lib/calcms/config.pm index 64e5cd3..07ea1bf 100644 --- a/lib/calcms/config.pm +++ b/lib/calcms/config.pm @@ -1,32 +1,78 @@ package config; -require Exporter; -my @ISA = qw(Exporter); -my @EXPORT_OK = qw(get $config); -my %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ] ); +use strict; +use warnings; +no warnings 'redefine'; -use Config::General; -our $modified_at=-999; -our $config= undef; +use FindBin(); -sub get{ - my $filename=shift; +#use base 'Exporter'; +our @EXPORT_OK = qw(get set); - #return config if known - #my $age=(-M $filename); - #return $config::config if ((defined $config::config) && ($age <= $config::modified_at)); +my $config = undef; - #reload config if changed - my $configuration = new Config::General( - -ConfigFile=>$filename, - -UTF8=>1 - ); - $config::config=$configuration->{DefaultConfig}->{config}; - $config::modified_at=$age; - #print STDERR "reload $filename\n"; - return $config::config; +sub get($) { + my $filename = shift; + return read_config($filename); +} + +sub getFromScriptLocation() { + FindBin::again(); + my $configFile = $FindBin::Bin . '/config/config.cgi'; + return config::get($configFile); +} + +sub read_config { + my $file = $_[0]; + + my $vars = {}; + my @stack = (); + my $entry = {}; + + open my $fh, '<:encoding(UTF-8)', $file or die; + while ( my $line = <$fh> ) { + chomp $line; + + # comments + $line =~ s/\#.*//; + + # trim + $line =~ s/(^\s+)|(\s+)$//; + next unless length $line; + if ( $line =~ /^<\/([^>]+)>$/ ) { + + # close tag + my $name = $1; + my $sentry = pop @stack; + die unless $sentry->{name} eq $name; + $entry = $sentry->{value}; + } elsif ( $line =~ /^<([^>]+)>$/ ) { + + # open tag + my $name = $1; + $entry->{$name} = {}; + push @stack, { name => $name, value => $entry }; + $entry = $entry->{$name}; + } elsif ( $line =~ /^Define\s/ ) { + # define vars + my ( $attr, $key, $value ) = split /\s+/, $line, 3; + for my $var ( keys %$vars ) { + $value =~ s/\$\{$var\}/$vars->{$var}/; + } + $vars->{$key} = $value; + } else { + # attributes + my ( $key, $value ) = split /\s+/, $line, 2; + for my $var ( keys %$vars ) { + $value =~ s/\$\{$var\}/$vars->{$var}/; + } + $entry->{$key} = $value; + } + } + close $fh or die; + return $entry->{config}; } #do not delete last line diff --git a/lib/calcms/creole_wiki.pm b/lib/calcms/creole_wiki.pm index e3fe386..c5f35d7 100644 --- a/lib/calcms/creole_wiki.pm +++ b/lib/calcms/creole_wiki.pm @@ -1,261 +1,229 @@ -use warnings; +package creole_wiki; + use strict; +use warnings; +no warnings 'redefine'; + use Data::Dumper; -use markup; +use markup(); -package creole_wiki; +#use base 'Exporter'; +our @EXPORT_OK = + qw(extractEventFromWikiText removeMeta eventToWikiText extractMeta removeMeta metaToWiki); -require Exporter; -our @ISA = qw(Exporter); -our @EXPORT_OK = qw(extractEventFromWikiText removeMeta eventToWikiText extractMeta removeMeta metaToWiki); -our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ] ); +#convert creole wiki text to event +sub extractEventFromWikiText($;$) { + my $params = shift; + my $event = shift; + $event = {} unless defined $event; -#convert creole wiki text to event -sub extractEventFromWikiText{ - my $params=shift; - my $event=shift; - $event={} unless (defined $event); + my $title = $params->{title} || ''; + my $content = $params->{content} || ''; + my $local_media_url = $params->{local_media_url} || ''; - my $title =$params->{title}||''; - my $content =$params->{content}||''; - my $local_media_url =$params->{local_media_url}||''; + #split content into excerpt, content and comments + $content =~ s/\s*\,\s*/, /g; + my @lines = split( /\s*\-{10,99}\s*/, $content ); + my $lines = \@lines; + for my $line (@$lines) { + $line =~ s/^\s+|\s+$//g; + } + if ( @lines == 1 ) { + $event->{content} = shift @lines; + } elsif ( @lines == 2 ) { + $event->{excerpt} = shift @lines; + $event->{content} = shift @lines; + } else { + $event->{excerpt} = shift @lines; + $event->{content} = shift @lines; + $event->{comments} = join( "--------------------\n", @lines ); + } + if ( defined $event->{excerpt} ) { + $event->{excerpt} = markup::html_to_plain( $event->{excerpt} ); + } - #split content into excerpt, content and comments - $content=~s/\s*\,\s*/, /g; - my @lines=split(/\s*\-{10,99}\s*/,$content); - my $lines=\@lines; - for my $line (@$lines){ - $line=~s/^\s+|\s+$//g; - } - if (@lines==1){ - $event->{content}=shift @lines; - }elsif(@lines==2){ - $event->{excerpt}=shift @lines; - $event->{content}=shift @lines; - }else{ - $event->{excerpt}=shift @lines; - $event->{content}=shift @lines; - $event->{comments}=join("--------------------\n",@lines); - } - if (defined $event->{excerpt}){ - $event->{excerpt}=markup::html_to_plain($event->{excerpt}); - } - #extract program from title - $event->{program}=''; + #extract program from title + $event->{program} = ''; - if ($title=~/^(.*?)\:/){ - my $program=$1; - unless ($program=~/\s\-\s/){ - $event->{program}=$program; - $event->{program}=~s/^\s+|\s+$//g; - $event->{program}=~s/\s+/ /g; - $title=~s/^.*?\:\s+//gi; - } - } + if ( $title =~ /^(.*?)\:/ ) { + my $program = $1; + unless ( $program =~ /\s\-\s/ ) { + $event->{program} = $program; + $event->{program} =~ s/^\s+|\s+$//g; + $event->{program} =~ s/\s+/ /g; + $title =~ s/^.*?\:\s+//gi; + } + } - #extract series_name from title - $event->{series_name}=''; - if ($title=~/^(.*?)\s+\-\s+/){ - $event->{series_name}=$1; - $event->{series_name}=~s/^\s+|\s+$//g; - $event->{series_name}=~s/\s+/ /g; - $title=~s/^(.*?)\s+\-\s+//gi; - } - - #extract categories from title - my @categories=(); - while ($title=~/\((.*?),(.*?)\)/){ - my $category=$1; - $category =~s/\s+/ /g; - $category =~s/^\s+|\s+$//g; - $category =~s/\&/\+/g; - push @categories,$category if (defined $category && $category=~/\S/); + #extract series_name from title + $event->{series_name} = ''; + if ( $title =~ /^(.*?)\s+\-\s+/ ) { + $event->{series_name} = $1; + $event->{series_name} =~ s/^\s+|\s+$//g; + $event->{series_name} =~ s/\s+/ /g; + $title =~ s/^(.*?)\s+\-\s+//gi; + } - $category=''; - $category=$2 if (defined $2); - $category =~s/\s+/ /g; - $category =~s/^\s+|\s+$//g; - $category =~s/\&/\+/g; - push @categories,$category if (defined $category && $category=~/\S/); - $title=~s/\((.*?),(.*?)\)/\($2\)/; - } - if ($title=~/\((.*?)\)/){ - my $category=$1; - $category =~s/\s+/ /g; - $category =~s/^\s+|\s+$//g; - $category =~s/\&/\+/g; + #extract categories from title + my @categories = (); + while ( $title =~ /\((.*?),(.*?)\)/ ) { + $title =~ s/\((.*?),(.*?)\)/\($2\)/; + } + if ( $title =~ /\((.*?)\)/ ) { + $title =~ s/\((.*?)\)//; + } + $event->{title} = $title; + $event->{title} =~ s/^\s+|\s+$//g; -# print $category."\n"; - push @categories,$category if (defined $category && $category=~/\S/); - $title=~s/\((.*?)\)//; - } - $event->{categories} = \@categories if (@categories>0); - $event->{title} = $title; - $event->{title} =~s/^\s+|\s+$//g; + if ( defined $event->{content} ) { - if (defined $event->{content}){ - #extract podcast_url from content link 'podcast' - my $podcast_url=''; - if ($event->{content}=~/\[\[\s*([^\|\]]+)\s*\|\s*podcast\s*\]\]/i){ - $podcast_url=$1; - # $podcast_url=~s/\|.*//g; - # print "found podcast:".$podcast_url."\n"; - } - $event->{podcast_url} = $podcast_url; + #extract podcast_url from content link 'podcast' + my $podcast_url = ''; + if ( $event->{content} =~ /\[\[\s*([^\|\]]+)\s*\|\s*podcast\s*\]\]/i ) { + $podcast_url = $1; + } + $event->{podcast_url} = $podcast_url; - #extract media_url from content link 'download' - my $media_url=''; - if ($event->{content}=~/\[\[\s*([^\|\]]+)\s*\|\s*(direct\s+)?download\s*\]\]/i){ - $media_url=$1; - # $podcast_url=~s/\|.*//g; - # print "found media:".$media_url."\n"; - } - $event->{media_url} = $media_url; + #extract media_url from content link 'download' + my $media_url = ''; + if ( $event->{content} =~ /\[\[\s*([^\|\]]+)\s*\|\s*(direct\s+)?download\s*\]\]/i ) { + $media_url = $1; + } + $event->{media_url} = $media_url; - #replace "thumbs/xxx" link by link to local media URI - $event->{content}=~s/\{\{\s*thumbs\/+(.*?)\s*\|\s*(.*?)\s*\}\}/\[\[$local_media_url\/images\/$1\|\{\{$local_media_url\/thumbs\/$1\|$2\}\}\]\]/g; + #replace "thumbs/xxx" link by link to local media URI + $event->{content} =~ +s/\{\{\s*thumbs\/+(.*?)\s*\|\s*(.*?)\s*\}\}/\[\[$local_media_url\/images\/$1\|\{\{$local_media_url\/thumbs\/$1\|$2\}\}\]\]/g; - #extract image from content - if ($event->{content}=~/\{\{(.*?)(\||\}\})/){ - $event->{image}=$1; - } - } + #extract image from content + if ( $event->{content} =~ /\{\{(.*?)(\||\}\})/ ) { + $event->{image} = $1; + } + } - #meta - if (defined $event->{comments}){ - my $meta=extractMeta($event->{comments}); - $event->{meta} = $meta if (@$meta>0); - } + #meta + if ( defined $event->{comments} ) { + my $meta = extractMeta( $event->{comments} ); + $event->{meta} = $meta if scalar @$meta > 0; + } - return $event; + return $event; } -sub eventToWikiText{ - my $event=shift; - my $local_media_url =$event->{local_media_url}||''; +sub eventToWikiText($$) { + my $event = shift; + my $local_media_url = $event->{local_media_url} || ''; - $event->{program} =~s/^\s+|\s+$//g; - $event->{series_name} =~s/^\s+|\s+$//g; - $event->{title} =~s/^\s+|\s+$//g; - $event->{excerpt} =~s/^\s+|\s+$//g; - $event->{content} =~s/^\s+|\s+$//g; - $event->{comments} =~s/^\s+|\s+$//g; + $event->{program} =~ s/^\s+|\s+$//g; + $event->{series_name} =~ s/^\s+|\s+$//g; + $event->{title} =~ s/^\s+|\s+$//g; + $event->{excerpt} =~ s/^\s+|\s+$//g; + $event->{content} =~ s/^\s+|\s+$//g; + $event->{comments} =~ s/^\s+|\s+$//g; - my $title=''; - if($event->{program} ne''){ - $title=$event->{program}; - $title.=': ' if (($event->{series_name} ne'') || ($event->{title} ne'')); - } - if($event->{series_name} ne''){ - $title.=$event->{series_name}; - $title.=' - ' if ($event->{title} ne''); - } - $title.=$event->{title}; - if ($event->{categories}){ - $title.=' ('.join(",", @{$event->{categories}} ).')' if (@{$event->{categories}}>0); - } + my $title = ''; + if ( $event->{program} ne '' ) { + $title = $event->{program}; + $title .= ': ' if ( $event->{series_name} ne '' ) || ( $event->{title} ne '' ); + } + if ( $event->{series_name} ne '' ) { + $title .= $event->{series_name}; + $title .= ' - ' if ( $event->{title} ne '' ); + } + $title .= $event->{title}; + if ( $event->{categories} ) { + my $categories = $event->{categories}; + $title .= ' (' . join( ",", @$categories ) . ')' if ( scalar @$categories > 0 ); + } - my $meta=extractMeta($event->{comments}, $event->{meta}); - #use Data::Dumper;print "extracted meta".Dumper($meta); - - $event->{comments}=removeMeta($event->{comments}); - $event->{wiki_comments}=$event->{comments}."\n\n".metaToWiki($meta); - #use Data::Dumper;print "event content".Dumper($event->{content}); - - #rich content editors: - #$event->{wiki_content}=markup::html_to_creole($event->{content}); - - #markup editors - $event->{wiki_content}=$event->{content}; + my $meta = extractMeta( $event->{comments}, $event->{meta} ); + $event->{comments} = removeMeta( $event->{comments} ); + $event->{wiki_comments} = $event->{comments} . "\n\n" . metaToWiki($meta); + #markup editors + $event->{wiki_content} = $event->{content}; # [[http://localhost/agenda_files/media/images/Vl8X7YmaWrmm9RMN_OMywA.jpg|{{http://localhost/agenda_files/media/thumbs/Vl8X7YmaWrmm9RMN_OMywA.jpg|}}]] - #replace "thumbs/xxx" link by link to local media URI -# while ($event->{wiki_content}=~/\[\[.*?\/+media\/+images\/+(.*?)\s*\|.*?\{\{.*?\/+media\/+thumbs\/+(.*?)\s*\|\s*(.*?)\s*\}\}\]\]/){ - $event->{wiki_content}=~s/\[\[.*?\/+media\/+images\/+(.*?)\s*\|.*?\{\{.*?\/+media\/+thumbs\/+(.*?)\s*\|\s*(.*?)\s*\}\}\]\]/\{\{thumbs\/$1\|$3\}\}/g; -# } +#replace "thumbs/xxx" link by link to local media URI + $event->{wiki_content} =~ +s/\[\[.*?\/+media\/+images\/+(.*?)\s*\|.*?\{\{.*?\/+media\/+thumbs\/+(.*?)\s*\|\s*(.*?)\s*\}\}\]\]/\{\{thumbs\/$1\|$3\}\}/g; - my $wiki_content=join("\n".("-"x20)."\n",($event->{excerpt}, $event->{wiki_content}) ); - $wiki_content.="\n".("-"x20)."\n".$event->{wiki_comments} if ($event->{wiki_comments}=~/\S/); + my $wiki_content = + join( "\n" . ( "-" x 20 ) . "\n", ( $event->{excerpt}, $event->{wiki_content} ) ); + $wiki_content .= "\n" . ( "-" x 20 ) . "\n" . $event->{wiki_comments} + if ( $event->{wiki_comments} =~ /\S/ ); + + return { + title => $title, + content => $event->{content}, + wiki_content => $wiki_content + }; - return { - title => $title, - content => $event->{content}, - wiki_content => $wiki_content - }; - } #extrace meta tags from comment text -sub extractMeta{ - my $comments =shift; - my $meta =shift; +sub extractMeta ($$) { + my $comments = shift; + my $meta = shift; - $meta=[] unless (defined $meta); + $meta = [] unless defined $meta; - #push meta tags into meta list - if (defined $comments){ - #build index for meta already defined - my $meta_keys={}; - for my $pair (@$meta){ - $meta_keys->{$pair->{name}.'='.$pair->{value}}=1; - } + #push meta tags into meta list + if ( defined $comments ) { - while ($comments=~/\~\~META\:(.+?)\=(.+?)\~\~/g){ - my $name=$1; - my $value=$2; + #build index for meta already defined + my $meta_keys = { map { $_->{name}."=".$_->{value} => 1 } @$meta }; - #fix meta values - $name=lc($name); - $name=~s/^\s+|\s+$//g; - $value=~s/^\s+|\s+$//g; + while ( $comments =~ /\~\~META\:(.+?)\=(.+?)\~\~/g ) { + my $name = $1; + my $value = $2; - #insert into list, if not defined yet - unless( ($name eq'') || ($value eq'') || (exists $meta_keys->{$name.'='.$value}) ){ - push @$meta,{ - name=>$name, - value=>$value, - }; - $meta_keys->{$name.'='.$value}=1; - } - }; - } -# use Data::Dumper;print Dumper($meta); - return $meta; + #fix meta values + $name = lc($name); + $name =~ s/^\s+|\s+$//g; + $value =~ s/^\s+|\s+$//g; + + #insert into list, if not defined yet + unless ( ( $name eq '' ) + || ( $value eq '' ) + || ( exists $meta_keys->{ $name . '=' . $value } ) ) + { + push @$meta, + { + name => $name, + value => $value, + }; + $meta_keys->{ $name . '=' . $value } = 1; + } + } + } + return $meta; } #remove meta tags from comment text -sub removeMeta{ - my $comments=shift||''; +sub removeMeta($) { + my $comments = shift || ''; - my $result=''; - for my $line (split(/\n/,$comments)){ - $result.=$line unless ($line=~/\~\~META\:(.+?)\=(.+?)\~\~/g); - } - #use Data::Dumper;print "removed metsas:".Dumper($result); - $result=~s/^\s+//g; - $result=~s/\s+$//g; + my $result = ''; + for my $line ( split( /\n/, $comments ) ) { + $result .= $line unless ( $line =~ /\~\~META\:(.+?)\=(.+?)\~\~/g ); + } + $result =~ s/^\s+//g; + $result =~ s/\s+$//g; - return $result; + return $result; } #add meta tags to comment text -sub metaToWiki{ - my $meta =shift; - - my $result=''; - for my $pair (@$meta){ -# use Data::Dumper;print Dumper($pair); - $result.='~~META:'.$pair->{name}.'='.$pair->{value}.'~~'."\n"; - } - return $result; - #use Data::Dumper;print Dumper($meta); +sub metaToWiki { + my $meta = shift; + my $result = ''; + for my $pair (@$meta) { + $result .= '~~META:' . $pair->{name} . '=' . $pair->{value} . '~~' . "\n"; + } + return $result; } - -#test: -#perl -e 'use creole_wiki;$a=creole_wiki::extractEventFromWikiText("teaser\n----------------------\nbody[[asd|download]][[bsd|hallo]][[csd|podcast]]{{a|b}}[[dsd|wer]]\n----------------------\ncomments",{title=>" a : b - c ( d e - f , g h i - j, k - m - l) "});use Data::Dumper;print Dumper($a)'; - #do not delete last line! 1; diff --git a/lib/calcms/db.pm b/lib/calcms/db.pm index 087a919..6f115e0 100644 --- a/lib/calcms/db.pm +++ b/lib/calcms/db.pm @@ -1,277 +1,210 @@ -use warnings "all"; +package db; + use strict; +use warnings; +no warnings 'redefine'; +use feature 'state'; -#use DBI; -#use Apache::DBI; -use DBD::mysql; - -package db; +use DBD::mysql(); +use Digest::MD5 qw(); use Data::Dumper; -require Exporter; -our @ISA = qw(Exporter); +#use base 'Exporter'; our @EXPORT_OK = qw( - connect disconnect - get insert put - next_id get_max_id - shift_date_by_hours shift_datetime_by_minutes - get_columns get_columns_hash - $write - $read + connect disconnect + get insert put + next_id get_max_id + shift_date_by_hours shift_datetime_by_minutes + get_columns get_columns_hash + $write + $read ); -our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ] ); - -#debug settings -our $debug_read=0; -our $debug_write=0; #database control -our $read=1; -our $write=1; +our $read = 1; +our $write = 1; # connect to database -sub connect{ - my $options=shift; - my $request=shift; +my $database; +sub connect($;$) { + my ($options, $request) = @_; - return $request->{connection} if ((defined $request) && (defined $request->{connection})); + return $request->{connection} if defined $request and defined $request->{connection}; - my $access_options=$options->{access}; + my $access_options = $options->{access}; + my $hostname = $access_options->{hostname}; + my $port = $access_options->{port}; + $database = $access_options->{database}; + my $username = $access_options->{username}; + my $password = $access_options->{password}; - my $hostname =$access_options->{hostname}; - my $port =$access_options->{port}; - my $database =$access_options->{database}; - my $username =$access_options->{username}; - my $password =$access_options->{password}; + if ( ( defined $access_options->{write} ) && ( $access_options->{write} eq '1' ) ) { + $username = $access_options->{username_write}; + $password = $access_options->{password_write}; + } - if ((defined $access_options->{write}) && ($access_options->{write}eq'1')){ - $username =$access_options->{username_write}; - $password =$access_options->{password_write}; - } + my $dsn = "DBI:mysql:database=$database;host=$hostname;port=$port"; + my $key = Digest::MD5::md5_hex($dsn.$username.$password); + return $options->{connections}->{$key} if defined $options->{connections}->{$key}; + state $connections = {}; + return $connections->{$key} if defined $connections->{$key} and $connections->{$key}->ping; - my $dbh=undef; - my $dsn = "DBI:mysql:database=$database;host=$hostname;port=$port"; -# if ($db::utf8dbi eq '1'){ -# use UTF8DBI; -# $dbh = UTF8DBI->connect( $dsn,$username,$password) || die "Database connection not made: $DBI::errstr"; # \nfor $dsn, $username -# }else{ -# use DBI; - $dbh = DBI->connect( $dsn,$username,$password,{mysql_enable_utf8 => 1}) || die "could not connect to database: $DBI::errstr"; # \nfor $dsn, $username -# } - #print STDERR "db connect $username\n" if ($debug_read==1); - #print STDERR "db connect $username\n"; - $dbh->{RaiseError} = 1; - - $dbh->{'mysql_enable_utf8'} = 1; - put($dbh,"set character set utf8"); - put($dbh,"set names utf8"); - put($dbh,"set time_zone='".$options->{date}->{time_zone}."'"); - - $request->{connection}=$dbh; - return $dbh; + my $dbh = DBI->connect( $dsn, $username, $password, { mysql_enable_utf8 => 1 } ) + || die "could not connect to database: $DBI::errstr"; + $dbh->{RaiseError} = 1; + $dbh->{'mysql_enable_utf8'} = 1; + put( $dbh, "set character set utf8", undef ); + put( $dbh, "set names utf8", undef ); + put( $dbh, "set time_zone='" . $options->{date}->{time_zone} . "'", undef ); + $request->{connection} = $dbh; + #$options->{connections}->{$key} = $dbh; + $connections->{$key} = $dbh; + return $dbh; } -sub disconnect{ - my $request=shift; - my $dbh=$request->{connection}; - $dbh->disconnect; - delete $request->{connection}; +sub disconnect ($){ + my ($request) = @_; + my $dbh = $request->{connection}; + $dbh->disconnect; + delete $request->{connection}; + return; } # get all database entries of an sql query (as list of hashs) -sub get{ - my $dbh=shift; - my $sql=shift; - my $bind_values=shift; +sub get($$;$) { + my ( $dbh, $sql, $bind_values ) = @_; - if ($debug_read==1){ - print STDERR $sql."\n"; - print STDERR Dumper($bind_values)."\n" if defined $bind_values; + my $sth = $dbh->prepare($sql); + if ( ( defined $bind_values ) && ( ref($bind_values) eq 'ARRAY' ) ) { + my $result = $sth->execute(@$bind_values); + unless ($result) { + print STDERR $sql . "\n"; + die "db: $DBI::errstr $sql" if ( $read == 1 ); + } + } else { + $sth->execute() or die "db: $DBI::errstr $sql" if $read == 1; } - my $sth = $dbh->prepare( $sql ); - if ((defined $bind_values)&&(ref($bind_values)eq'ARRAY')){ -# print STDERR Dumper($bind_values)."\n"; - my $result = $sth->execute(@$bind_values); - unless ($result){ - print STDERR $sql."\n"; - die "db: $DBI::errstr $sql" if ($read==1); - } - }else{ - $sth->execute() || die "db: $DBI::errstr $sql" if ($read==1); - } + my $results = $sth->fetchall_arrayref({}); - my @results=(); - while ( my $row=$sth->fetchrow_hashref){ - my $result={}; - foreach my $key (keys %$row){ - $result->{$key}=$row->{$key}; - } - push @results, $result; - } - - if ($debug_read==1){ - print STDERR Dumper($results[0])."\n" if (@results==1); - print STDERR @results."\n" if (@results!=1); - } - - $sth->finish; - return \@results; + $sth->finish; + return $results; } # get list of table columns -sub get_columns{ - my $dbh=shift; - my $table=shift; - - my $columns=db::get($dbh, 'select column_name from information_schema.columns where table_name=?',[$table]); - my @result=map {$_->{column_name}} (@$columns); - return \@result; +sub get_columns($$) { + my ($dbh, $table) = @_; + my $columns = db::get( $dbh, + qq{ + select column_name from information_schema.columns + where table_schema=? + and table_name = ? + order by ordinal_position + }, + [$database, $table] + ); + return [ map { values %$_ } @$columns ]; } # get hash with table columns as keys -sub get_columns_hash{ - my $dbh=shift; - my $table=shift; - - my $columns=db::get_columns($dbh, $table); - my $result={}; - for my $column (@$columns){ - $result->{$column}=1; - } - return $result; -} - - -# insert an entry into database (select from where) -sub insert_old{ - my $dbh=shift; - my $tablename=shift; - my $entry=shift; - my $do_not_quote=shift; - - my $keys =join(",", map {$_} (keys %$entry)); - my $values =undef; - if (defined $do_not_quote && $do_not_quote ne ''){ - $values =join("\n,", map {$entry->{$_}} (keys %$entry)); - }else{ - $values =join("\n,", map {$dbh->quote($entry->{$_})} (keys %$entry)); - } - my $sql ="insert into $tablename \n ($keys) \n values ($values);\n"; - print STDERR $sql."\n" if ($debug_write==1); - put($dbh,$sql); - +sub get_columns_hash($$) { + my ($dbh, $table) = @_; + my $columns = get_columns($dbh, $table); + return { map { $_ => 1 } @$columns }; } #returns last inserted id -sub insert{ - my $dbh=shift; - my $tablename=shift; - my $entry=shift; -# my $do_not_quote=shift; +sub insert ($$$){ + my ($dbh, $table, $entry) =@_; - my $keys =join(",", map {$_} (keys %$entry)); - my $values =join(",", map {'?'} (keys %$entry)); - my @bind_values =map {$entry->{$_}} (keys %$entry); + my @keys = sort keys %$entry; + my $keys = join( ",", @keys ); + my $values = join( ",", map { '?' } @keys ); + my @bind_values = map { $entry->{$_} } @keys; - my $sql ="insert into $tablename \n ($keys) \n values ($values);\n"; - - if ($debug_write==1){ - print STDERR $sql."\n"; - print STDERR Dumper(\@bind_values)."\n" if (@bind_values); - } - - put($dbh, $sql, \@bind_values); - my $result=get($dbh, 'SELECT LAST_INSERT_ID() id;'); - return $result->[0]->{id} if $result->[0]->{id}>0; - return undef; + my $sql = "insert into $table \n ($keys) \n values ($values);\n"; + put( $dbh, $sql, \@bind_values ); + my $result = get( $dbh, 'SELECT LAST_INSERT_ID() id;' ); + return $result->[0]->{id} if $result->[0]->{id} > 0; + return undef; } -# execute a modifying database command (update,insert,...) -sub put{ - my $dbh=shift; - my $sql=shift; - my $bind_values=shift; +# execute a modifying database command (update,insert,...) +sub put($$$) { + my ($dbh, $sql, $bind_values) =@_; - if ($debug_write==1){ - print STDERR $sql."\n"; - print STDERR Dumper($bind_values)."\n" if defined $bind_values; + my $sth = $dbh->prepare($sql); + if ( $write == 1 ) { + if ( ( defined $bind_values ) && ( ref($bind_values) eq 'ARRAY' ) ) { + $sth->execute(@$bind_values); + } else { + $sth->execute(); + } } + $sth->finish; - my $sth = $dbh->prepare( $sql ); - if ($write==1){ - if ((defined $bind_values)&&(ref($bind_values)eq'ARRAY')){ - $sth->execute(@$bind_values); - }else{ - $sth->execute(); - } - }; - $sth->finish; - print STDERR "1\n" if ($debug_write==1); - - my $result=get($dbh, 'SELECT ROW_COUNT() changes;'); - return $result->[0]->{changes} if $result->[0]->{changes}>0; - return undef; + my $result = get( $dbh, 'SELECT ROW_COUNT() changes;' ); + return $result->[0]->{changes} if $result->[0]->{changes} > 0; + return undef; } -sub quote{ - my $dbh=shift; - my $sql=shift; - - $sql=~s/\_/\\\_/g; - return $dbh->quote($sql); +# deprecated +sub quote($$) { + my $dbh = shift; + my $sql = shift; + + $sql =~ s/\_/\\\_/g; + return $dbh->quote($sql); } #subtract hours, deprecated(!) -sub shift_date_by_hours{ - my $dbh=shift; - my $date=shift; - my $offset=shift; +sub shift_date_by_hours($$$) { + my $dbh = shift; + my $date = shift; + my $offset = shift; - my $query='select date(? - INTERVAL ? HOUR) date'; - my $bind_values=[$date,$offset]; - my $results=db::get($dbh, $query, $bind_values); - return $results->[0]->{date}; + my $query = 'select date(? - INTERVAL ? HOUR) date'; + my $bind_values = [ $date, $offset ]; + my $results = db::get( $dbh, $query, $bind_values ); + return $results->[0]->{date}; } #add minutes, deprecated(!) -sub shift_datetime_by_minutes{ - my $dbh=shift; - my $datetime=shift; - my $offset=shift; +sub shift_datetime_by_minutes($$$) { + my $dbh = shift; + my $datetime = shift; + my $offset = shift; - my $query="select ? + INTERVAL ? MINUTE date"; - my $bind_values=[$datetime,$offset]; - my $results=db::get($dbh, $query, $bind_values); - return $results->[0]->{date}; + my $query = "select ? + INTERVAL ? MINUTE date"; + my $bind_values = [ $datetime, $offset ]; + my $results = db::get( $dbh, $query, $bind_values ); + return $results->[0]->{date}; } # get next free id of a database table -sub next_id{ - my $dbh=shift; - my $table=shift; +sub next_id ($$){ + my ($dbh, $table) = @_; - my $query=qq{ + my $query = qq{ select max(id) id from $table where 1 }; - my $results=get($dbh,$query); - return $results->[0]->{id}+1; + my $results = get( $dbh, $query ); + return $results->[0]->{id} + 1; } # get max id from table -sub get_max_id{ - my $dbh=shift; - my $table=shift; +sub get_max_id($$) { + my ($dbh, $table) = @_; - my $query=qq{ + my $query = qq{ select max(id) id from $table where 1 }; - my $results=get($dbh,$query); - return $results->[0]->{id}; + my $results = get( $dbh, $query ); + return $results->[0]->{id}; } #do not delete last line! diff --git a/lib/calcms/entry.pm b/lib/calcms/entry.pm new file mode 100644 index 0000000..699abfb --- /dev/null +++ b/lib/calcms/entry.pm @@ -0,0 +1,51 @@ +package entry; + +use warnings; +use strict; + +sub from_valid($$) { + my ( $params, $attrs ) = @_; + return { map { defined $params->{$_} ? { $_ => $params->{$_} } : () } @$attrs }; +} + +sub set_numbers($$$) { + my ( $entry, $params, $fields ) = @_; + for my $field (@$fields) { + my $value = $params->{$field}; + next unless defined $value; + if ( $value =~ /([\-\d]+)/ ){ + $entry->{$field} = $1; + } + } +} + +sub set_bools($$$) { + my ( $entry, $params, $fields ) = @_; + for my $field (@$fields) { + my $value = $params->{$field}; + next unless defined $value; + if ($value=~/([01])/){ + $entry->{$field} = $1; + } + } +} + +sub set_strings($$$) { + my ( $entry, $params, $attrs ) = @_; + for my $field (@$attrs) { + my $value = $params->{$field}; + next unless defined $value; + $entry->{$field} = $value; + $entry->{$field} =~ s/^\s+//g; + $entry->{$field} =~ s/\s+$//g; + } +} + +sub element_of($$) { + my ( $value, $attrs ) = @_; + return unless $value; + return { map { $_ => $_ } @$attrs }->{$value} //''; +} + +# do not delete last line +1; diff --git a/lib/calcms/eventOps.pm b/lib/calcms/eventOps.pm index 9de5cee..6c2fd39 100644 --- a/lib/calcms/eventOps.pm +++ b/lib/calcms/eventOps.pm @@ -1,134 +1,323 @@ -package eventOps; -use warnings "all"; +package eventOps; + use strict; +use warnings; +no warnings 'redefine'; -use series; -use series_dates; -use time; +use uac(); +use events(); +use series(); +use series_dates(); +use time(); +use studios(); +use series_events(); +use user_stats(); -require Exporter; -our @ISA = qw(Exporter); +#use base 'Exporter'; our @EXPORT_OK = qw( - setAttributesFromSeriesTemplate - setAttributesFromSchedule - setAttributesFromOtherEvent - setAttributesForCurrentTime - getRecurrenceBaseId + setAttributesFromSeriesTemplate + setAttributesFromSchedule + setAttributesFromOtherEvent + setAttributesForCurrentTime + getRecurrenceBaseId ); -our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ] ); # functions: to be separated -sub setAttributesFromSeriesTemplate{ - my $config=shift; - my $params=shift; - my $event=shift; - - #get attributes from series - my $series=series::get( - $config,{ - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - series_id => $params->{series_id}, - } - ); - if(@$series!=1){ - uac::print_error("series not found"); - return undef; - } +sub setAttributesFromSeriesTemplate($$$) { + my $config = shift; + my $params = shift; + my $event = shift; - #copy fields from series template - my $serie=$series->[0]; - for my $attr( - 'program','series_name','title', - 'excerpt', 'topic', 'content', 'html_content', - 'project','category','location','image', 'live', - 'archive_url', 'podcast_url' - ){ - $event->{$attr}=$serie->{$attr}; - } - return $serie; + #get attributes from series + my $series = series::get( + $config, + { + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + series_id => $params->{series_id}, + } + ); + if ( scalar @$series != 1 ) { + uac::print_error("series not found"); + return undef; + } + + #copy fields from series template + my $serie = $series->[0]; + for my $attr ( + 'program', 'series_name', 'title', 'excerpt', 'topic', 'content', 'html_content', 'project', + 'location', 'image', 'live', 'archive_url', 'podcast_url', 'content_format' + ) + { + $event->{$attr} = $serie->{$attr}; + } + $event->{series_image} = $serie->{image}; + $event->{series_image_label} = $serie->{licence}; + return $serie; } -sub setAttributesFromSchedule{ - my $config=shift; - my $params=shift; - my $event=shift; +sub setAttributesFromSchedule ($$$){ + my $config = shift; + my $params = shift; + my $event = shift; - #set attributes from schedule - my $schedules=series_dates::get( - $config, { - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - series_id => $params->{series_id}, - start_at => $params->{start_date} - } - ); + #set attributes from schedule + my $schedules = series_dates::get( + $config, + { + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + series_id => $params->{series_id}, + start_at => $params->{start_date} + } + ); - if(@$schedules!=1){ - uac::print_error("schedule not found"); - return undef; - } + if ( @$schedules != 1 ) { + uac::print_error("schedule not found"); + return undef; + } - my $schedule=$schedules->[0]; - for my $attr( - 'start','end', - 'day', 'weekday', - 'start_date', 'end_date' - ){ - $event->{$attr}=$schedule->{$attr}; - } + my $schedule = $schedules->[0]; + for my $attr ( 'start', 'end', 'day', 'weekday', 'start_date', 'end_date' ) { + $event->{$attr} = $schedule->{$attr}; + } - my $timezone=$config->{date}->{time_zone}; - $event->{duration} = time::get_duration($event->{start}, $event->{end}, $timezone); + my $timezone = $config->{date}->{time_zone}; + $event->{duration} = time::get_duration( $event->{start}, $event->{end}, $timezone ); - return $event; + return $event; } -sub setAttributesFromOtherEvent{ - my $config=shift; - my $params=shift; - my $event=shift; +sub setAttributesFromOtherEvent ($$$){ + my $config = shift; + my $params = shift; + my $event = shift; - my $event2=series::get_event($config, { - allow_any => 1, - #project_id => $params->{project_id}, - #studio_id => $params->{studio_id}, - #series_id => $params->{series_id}, - event_id => $params->{source_event_id} - }); - if (defined $event2){ - for my $attr ('title', 'user_title', 'excerpt', 'user_excerpt', 'content', 'html_content', 'topics', 'image', 'live', 'no_event_sync', 'podcast_url', 'archive_url'){ - $event->{$attr}=$event2->{$attr}; - } - $event->{rerun}=1; - $event->{recurrence}=getRecurrenceBaseId($event2); - } + my $event2 = series::get_event( + $config, + { + allow_any => 1, - return $event; + #project_id => $params->{project_id}, + #studio_id => $params->{studio_id}, + #series_id => $params->{series_id}, + event_id => $params->{source_event_id} + } + ); + if ( defined $event2 ) { + for my $attr ( + 'title', 'user_title', 'excerpt', 'user_excerpt', 'content', 'html_content', + 'topics', 'image', 'series_image', 'live', 'no_event_sync', 'podcast_url', + 'archive_url', 'image_label', 'series_image_label', 'content_format' + ) + { + $event->{$attr} = $event2->{$attr}; + } + $event->{rerun} = 1; + $event->{recurrence} = getRecurrenceBaseId($event2); + } + + return $event; } -sub setAttributesForCurrentTime{ - my $serie=shift; - my $event=shift; - - #on new event not from schedule use current time - if($event->{start}eq''){ - $event->{start}=time::time_to_datetime(); - if ($event->{start}=~/(\d\d\d\d\-\d\d\-\d\d \d\d)/){ - $event->{start}=$1.':00'; - } - } - $event->{duration}=$serie->{duration}||60; - $event->{end} =time::add_minutes_to_datetime($event->{start}, $event->{duration}); - $event->{end}=~s/(\d\d:\d\d)\:\d\d/$1/; +sub setAttributesForCurrentTime ($$){ + my $serie = shift; + my $event = shift; - return $event; + #on new event not from schedule use current time + if ( $event->{start} eq '' ) { + $event->{start} = time::time_to_datetime(); + if ( $event->{start} =~ /(\d\d\d\d\-\d\d\-\d\d \d\d)/ ) { + $event->{start} = $1 . ':00'; + } + } + $event->{duration} = $serie->{duration} || 60; + $event->{end} = time::add_minutes_to_datetime( $event->{start}, $event->{duration} ); + $event->{end} =~ s/(\d\d:\d\d)\:\d\d/$1/; + + return $event; } -# get recurrence base id -sub getRecurrenceBaseId{ - my $event = shift; - return $event->{recurrence} if (defined $event->{recurrence}) && ($event->{recurrence} ne '') && ($event->{recurrence} ne '0'); - return $event->{event_id}; +# get recurrence base id +sub getRecurrenceBaseId ($){ + my $event = shift; + return $event->{recurrence} if ( defined $event->{recurrence} ) && ( $event->{recurrence} ne '' ) && ( $event->{recurrence} ne '0' ); + return $event->{event_id}; } +# get a new event for given series +sub getNewEvent($$$) { + my $config = shift; + my $params = shift; + my $action = shift; + + # check for missing parameters + my $required_fields = [ 'project_id', 'studio_id', 'series_id' ]; + push @$required_fields, 'start_date' if ( $action eq 'show_new_event_from_schedule' ); + + my $event = {}; + for my $attr (@$required_fields) { + unless ( defined $params->{$attr} ) { + uac::print_error( "missing " . $attr ); + return undef; + } + $event->{$attr} = $params->{$attr}; + } + + my $serie = eventOps::setAttributesFromSeriesTemplate( $config, $params, $event ); + + if ( $action eq 'show_new_event_from_schedule' ) { + eventOps::setAttributesFromSchedule( $config, $params, $event ); + } else { + eventOps::setAttributesForCurrentTime( $serie, $event ); + } + + if ( defined $params->{source_event_id} ) { + + #overwrite by existing event (rerun) + eventOps::setAttributesFromOtherEvent( $config, $params, $event ); + } + + $event = events::calc_dates( $config, $event ); + + if ( $serie->{has_single_events} eq '1' ) { + $event->{has_single_events} = 1; + $event->{series_name} = undef; + $event->{episode} = undef; + } + + #get next episode + $event->{episode} = series::get_next_episode( + $config, + { + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + series_id => $params->{series_id}, + } + ); + delete $event->{episode} if $event->{episode} == 0; + + $event->{disable_event_sync} = 1; + $event->{published} = 1; + $event->{new_event} = 1; + + return $event; +} + +# add user, action +sub createEvent($$$) { + my $request = shift; + my $event = shift; + my $action = shift; + + my $config = $request->{config}; + my $permissions = $request->{permissions}; + my $user = $request->{user}; + + my $checklist = [ 'studio', 'user', 'create_events', 'studio_timeslots' ]; + if ( $action eq 'create_event_from_schedule' ) { + push @$checklist, 'schedule' if $action eq 'create_event_from_schedule'; + } + + my $start = $event->{start_date}, my $end = time::add_minutes_to_datetime( $event->{start_date}, $event->{duration} ); + + my $result = series_events::check_permission( + $request, + { + permission => 'create_event,create_event_of_series', + check_for => $checklist, + project_id => $event->{project_id}, + studio_id => $event->{studio_id}, + series_id => $event->{series_id}, + start_date => $event->{start_date}, + draft => $event->{draft}, + start => $start, + end => $end, + } + ); + + unless ( $result eq '1' ) { + uac::print_error($result); + return undef; + } + + #get series name from series + my $series = series::get( + $config, + { + project_id => $event->{project_id}, + studio_id => $event->{studio_id}, + series_id => $event->{series_id}, + } + ); + if ( scalar @$series != 1 ) { + uac::print_error("series not found"); + return undef; + } + my $serie = $series->[0]; + + #get studio location from studios + my $studios = studios::get( + $config, + { + project_id => $event->{project_id}, + studio_id => $event->{studio_id} + } + ); + unless ( defined $studios ) { + uac::print_error("studio not found"); + return undef; + } + unless ( scalar @$studios == 1 ) { + uac::print_error("studio not found"); + return undef; + } + my $studio = $studios->[0]; + + $config->{access}->{write} = 1; + + #insert event content and save history + my $event_id = series_events::insert_event( + $config, + { + project_id => $event->{project_id}, + studio => $studio, + serie => $serie, + event => $event, + user => $user + } + ); + uac::print_error("could not insert event") if $event_id <= 0; + + #assign event to series + $result = series::assign_event( + $config, + { + project_id => $event->{project_id}, + studio_id => $event->{studio_id}, + series_id => $event->{series_id}, + event_id => $event_id + } + ); + uac::print_error("could not assign event") unless defined $result; + + #update recurrences + $event->{event_id} = $event_id; + series::update_recurring_events( $config, $event ); + + # update user stats + user_stats::increase( + $config, + 'create_events', + { + project_id => $event->{project_id}, + studio_id => $event->{studio_id}, + series_id => $event->{series_id}, + user => $user + } + ); + + return $event_id; +} + +return 1; diff --git a/lib/calcms/event_history.pm b/lib/calcms/event_history.pm index 72ad67b..591a9fd 100644 --- a/lib/calcms/event_history.pm +++ b/lib/calcms/event_history.pm @@ -1,134 +1,124 @@ -#!/bin/perl - -package event_history; -use warnings "all"; +package event_history; + use strict; +use warnings; +no warnings 'redefine'; + use Data::Dumper; -require Exporter; -our @ISA = qw(Exporter); -our @EXPORT_OK = qw(get_columns get get_by_id insert insert_by_event_id delete); -our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ] ); +#use base 'Exporter'; +our @EXPORT_OK = qw(get_columns get get_by_id insert insert_by_event_id delete); -sub debug; +sub get_columns ($){ + my $config = shift; -sub get_columns{ - my $config=shift; - - my $dbh=db::connect($config); - my $cols=db::get_columns($dbh, 'calcms_event_history'); - my $columns={}; - for my $col (@$cols){ - $columns->{$col}=1; - } - return $columns; + my $dbh = db::connect($config); + return db::get_columns_hash( $dbh, 'calcms_event_history' ); } -sub get{ - my $config=shift; - my $condition=shift; +sub get ($$){ + my $config = shift; + my $condition = shift; return undef unless defined $condition->{studio_id}; - my $dbh=db::connect($config); + my $dbh = db::connect($config); - my @conditions=(); - my @bind_values=(); + my @conditions = (); + my @bind_values = (); - if ((defined $condition->{project_id}) && ($condition->{project_id} ne '')){ - push @conditions, 'project_id=?'; - push @bind_values, $condition->{project_id}; - } - - if ((defined $condition->{studio_id}) && ($condition->{studio_id} ne '')){ - push @conditions, 'studio_id=?'; - push @bind_values, $condition->{studio_id}; - } - - if ((defined $condition->{series_id}) && ($condition->{series_id} ne '')){ - push @conditions, 'series_id=?'; - push @bind_values, $condition->{series_id}; - } - - if ((defined $condition->{event_id}) && ($condition->{event_id} ne '')){ - push @conditions, 'event_id=?'; - push @bind_values, $condition->{event_id}; - } - - if ((defined $condition->{change_id}) && ($condition->{change_id} ne '')){ - push @conditions, 'id=?'; - push @bind_values, $condition->{change_id}; - } - - my $limit=''; - if ((defined $condition->{limit}) && ($condition->{limit} ne '')){ - $limit= 'limit '.$condition->{limit}; + if ( ( defined $condition->{project_id} ) && ( $condition->{project_id} ne '' ) ) { + push @conditions, 'project_id=?'; + push @bind_values, $condition->{project_id}; } - my $conditions=''; - $conditions=" where ".join(" and ",@conditions) if (@conditions>0); + if ( ( defined $condition->{studio_id} ) && ( $condition->{studio_id} ne '' ) ) { + push @conditions, 'studio_id=?'; + push @bind_values, $condition->{studio_id}; + } - my $query=qq{ + if ( ( defined $condition->{series_id} ) && ( $condition->{series_id} ne '' ) ) { + push @conditions, 'series_id=?'; + push @bind_values, $condition->{series_id}; + } + + if ( ( defined $condition->{event_id} ) && ( $condition->{event_id} ne '' ) ) { + push @conditions, 'event_id=?'; + push @bind_values, $condition->{event_id}; + } + + if ( ( defined $condition->{change_id} ) && ( $condition->{change_id} ne '' ) ) { + push @conditions, 'id=?'; + push @bind_values, $condition->{change_id}; + } + + my $limit = ''; + if ( ( defined $condition->{limit} ) && ( $condition->{limit} ne '' ) ) { + $limit = 'limit ' . $condition->{limit}; + } + + my $conditions = ''; + $conditions = " where " . join( " and ", @conditions ) if ( @conditions > 0 ); + + my $query = qq{ select * from calcms_event_history $conditions order by modified_at desc $limit }; - #print STDERR Dumper($query).Dumper(\@bind_values); - my $changes=db::get($dbh, $query, \@bind_values); - #print STDERR Dumper($changes); + my $changes = db::get( $dbh, $query, \@bind_values ); - for my $change (@$changes){ - $change->{change_id}=$change->{id}; - delete $change->{id}; - } - return $changes; + for my $change (@$changes) { + $change->{change_id} = $change->{id}; + delete $change->{id}; + } + return $changes; } -sub get_by_id{ - my $config=shift; - my $id=shift; +sub get_by_id($$) { + my $config = shift; + my $id = shift; - my $dbh=db::connect($config); + my $dbh = db::connect($config); - my $query=qq{ + my $query = qq{ select * from calcms_event_history where event_id=? }; - my $studios=db::get($dbh,$query,[$id]); - return undef if (@$studios!=1); - return $studios->[0]; + my $studios = db::get( $dbh, $query, [$id] ); + return undef if ( @$studios != 1 ); + return $studios->[0]; } -sub insert{ - my $config=shift; - my $entry=shift; +sub insert($$) { + my $config = shift; + my $entry = shift; - $entry->{modified_at}= time::time_to_datetime(time()); + $entry->{modified_at} = time::time_to_datetime( time() ); - $entry->{event_id}=$entry->{id} if((defined $entry->{id})&&(!(defined $entry->{event_id}))); + $entry->{event_id} = $entry->{id} if ( defined $entry->{id} ) && ( !( defined $entry->{event_id} ) ); delete $entry->{id}; #TODO:filter for existing attributes - my $columns=get_columns($config); - my $event={}; - for my $column (keys %$columns){ - $event->{$column}=$entry->{$column} if defined $entry->{$column}; + my $columns = get_columns($config); + my $event = {}; + for my $column ( keys %$columns ) { + $event->{$column} = $entry->{$column} if defined $entry->{$column}; } - my $dbh=db::connect($config); - my $id=db::insert($dbh, 'calcms_event_history', $event); + my $dbh = db::connect($config); + my $id = db::insert( $dbh, 'calcms_event_history', $event ); return $id; } # insert event -sub insert_by_event_id{ - my $config=shift; - my $options=shift; +sub insert_by_event_id ($$){ + my $config = shift; + my $options = shift; return undef unless defined $options->{project_id}; return undef unless defined $options->{studio_id}; @@ -136,40 +126,40 @@ sub insert_by_event_id{ return undef unless defined $options->{event_id}; return undef unless defined $options->{user}; - my $sql=q{ + my $sql = q{ select * from calcms_events where id=? }; - my $bind_values=[$options->{event_id}]; - my $dbh=db::connect($config); - my $results=db::get($dbh, $sql, $bind_values); - if(@$results!=1){ + my $bind_values = [ $options->{event_id} ]; + my $dbh = db::connect($config); + my $results = db::get( $dbh, $sql, $bind_values ); + if ( @$results != 1 ) { print STDERR "cannot find event with event_id=$options->{event_id}"; return 0; } # add to history - my $event=$results->[0]; - $event->{project_id} = $options->{project_id}; - $event->{studio_id} = $options->{studio_id}; - $event->{series_id} = $options->{series_id}; - $event->{event_id} = $options->{event_id}; - $event->{user} = $options->{user}; - $event->{deleted} = 1; - event_history::insert($config, $event); + my $event = $results->[0]; + $event->{project_id} = $options->{project_id}; + $event->{studio_id} = $options->{studio_id}; + $event->{series_id} = $options->{series_id}; + $event->{event_id} = $options->{event_id}; + $event->{user} = $options->{user}; + $event->{deleted} = 1; + event_history::insert( $config, $event ); } -sub delete{ - my $config=shift; - my $entry=shift; - - my $dbh=db::connect($config); - db::put($dbh, 'delete from calcms_event_history where event_id=?', [$entry->{id}]); +sub delete ($$){ + my $config = shift; + my $entry = shift; + + my $dbh = db::connect($config); + db::put( $dbh, 'delete from calcms_event_history where event_id=?', [ $entry->{id} ] ); } -sub error{ - my $msg=shift; - print "ERROR: $msg
\n"; +sub error ($){ + my $msg = shift; + print "ERROR: $msg
\n"; } #do not delete last line! diff --git a/lib/calcms/events.pm b/lib/calcms/events.pm index 3ce30f1..11445db 100644 --- a/lib/calcms/events.pm +++ b/lib/calcms/events.pm @@ -1,997 +1,1086 @@ -use warnings "all"; -use strict; - -use DBI; -use template; - -use config; -use time; -use db; -use cache; -use markup; -use log; - package events; -use Data::Dumper; -use project; -use studios; -require Exporter; -our @ISA = qw(Exporter); +use strict; +use warnings; +no warnings 'redefine'; + +use Data::Dumper; +$Data::Dumper::Sortkeys=1; +use MIME::Base64(); +use Encode(); +use Storable 'dclone'; + +use DBI(); +use template(); + +use config(); +use time(); +use db(); + +use markup(); +use log(); +use project(); +use studios(); + +#use base 'Exporter'; our @EXPORT_OK = qw( - init - get_cached_or_render - get - modify_results - get_query - render - get_running_event_id - delete - check_params - configure_cache - get_duration - calc_dates - get_keys - add_recordings + init + get_cached_or_render + get + modify_results + get_query + render + get_running_event_id + delete + check_params + configure_cache + get_duration + calc_dates + get_keys + add_recordings ); -our %EXPORT_TAGS = ( 'all' => [@EXPORT_OK] ); sub init { } -sub get_cached_or_render { +sub get_cached_or_render($$$) { + my ($response, $config, $request) = @_; - # my $response=$_[0]; - my $config = $_[1]; - my $request = $_[2]; - - my $params = $request->{params}->{checked}; - my $debug = $config->{system}->{debug}; - - my $cache = {}; - if ( $config->{cache}->{use_cache} == 1 ) { - events::configure_cache($config); - $cache = cache::load( $config, $params ); - log::write( $config, 'cache', $cache->{action} ); - if ( defined $cache->{content} ) { - $_[0] = $cache->{content}; - return; - } - } - - my $results = events::get( $config, $request ); - events::render( $_[0], $config, $request, $results ); - - #write to cache - if ( $config->{cache}->{use_cache} == 1 ) { - - #todo:put out reference only - log::write( $config, 'cache', $cache ); - $cache->{content} = $_[0]; - cache::save($cache); - } - log::mem( $config, 'events not_cached' ) if ( $debug > 2 ); - return $_[0]; + my $params = $request->{params}->{checked}; + my $results = events::get( $config, $request ); + events::render( $response, $config, $request, $results ); + return $response; } -sub get { - my $config = shift; - my $request = shift; +sub get_prev{ + my ($config, $event) = @_; + my $params = { + till_date => time::check_date($event->{start}), + till_time => time::check_time($event->{start}), + archive => 'all', + order => 'desc', + limit => 1, + exclude_locations => 1, + exclude_projects => 1, + }; + my $request = { + url => $ENV{QUERY_STRING}, + params => { + original => $params, + checked => events::check_params( $config, $params ), + } + }; + $request->{params}->{checked}->{stop_nav} = 1; + my $results = events::get( $config, $request ); + return $results->[0]; +} - my $debug = $config->{system}->{debug}; +sub get_next{ + my ($config, $event) = @_; - my $dbh = db::connect( $config, $request ); + my $params = { + from_date => time::check_date($event->{end}), + from_time => time::check_time($event->{end}), + archive => 'all', + order => 'asc', + limit => 1, + exclude_locations => 1, + exclude_projects => 1, + }; + my $request = { + url => $ENV{QUERY_STRING}, + params => { + original => $params, + checked => events::check_params( $config, $params ), + }, + }; + $request->{params}->{checked}->{stop_nav} = 1; + my $results = events::get( $config, $request ); + return $results->[0]; +} - ( my $query, my $bind_values ) = events::get_query( $dbh, $config, $request ); +sub get($$); +sub get($$) { + my ($config, $request) = @_; - #print STDERR Dumper($query).Dumper($bind_values)."\n"; - - my $results = db::get( $dbh, $$query, $bind_values ); + my $dbh = db::connect( $config, $request ); + ( my $query, my $bind_values ) = events::get_query( $dbh, $config, $request ); + my $results = db::get( $dbh, $$query, $bind_values ); #$results = events::add_recordings($dbh, $config, $request, $results); + $results = events::modify_results( $dbh, $config, $request, $results ); - #print STDERR Dumper($results); - $results = events::modify_results( $dbh, $config, $request, $results ); + # get prev and next event + if ( @$results==1 + and !$request->{params}->{checked}->{stop_nav} #< prevent recursion! + and my $event_id = $request->{params}->{original}->{event_id} + ){ + my $event = $results->[0]; + $event->{prev_event_id} = (get_prev($config, $event)//{})->{event_id}; + $event->{next_event_id} = (get_next($config, $event)//{})->{event_id}; + } - return $results; + return $results; } -sub modify_results { - my $dbh = shift; - my $config = shift; - my $request = shift; - my $results = shift; +sub modify_results ($$$$) { + my ($dbh, $config, $request, $results) = @_; - my $params = $request->{params}->{checked}; + my $params = $request->{params}->{checked}; - my $running_event_id = 0; - my $projects = {}; - my $studios = {}; + my $running_event_id = 0; + my $projects = {}; + my $studios = {}; - # print $running_event_id." ".$running_events->[0]->{start}." ".$running_events->[0]->{title} if ($debug ne''); - my $time_diff = ''; - if ( scalar @$results > 0 ) { - $results->[0]->{__first__} = 1; - $results->[-1]->{__last__} = 1; - $running_event_id = events::get_running_event_id($dbh); - } + my $time_diff = ''; + if ( scalar @$results > 0 ) { + $results->[0]->{__first__} = 1; + $results->[-1]->{__last__} = 1; + $running_event_id = events::get_running_event_id($dbh); + } - if ( ( defined $params->{template} ) && ( $params->{template} =~ /\.xml/ ) ) { - $time_diff = time::utc_offset( $config->{date}->{time_zone} ); - $time_diff =~ s/(\d\d)(\d\d)/$1\:$2/g; - } + if ( ( defined $params->{template} ) && ( $params->{template} =~ /\.xml/ ) ) { + $time_diff = time::utc_offset( $config->{date}->{time_zone} ); + $time_diff =~ s/(\d\d)(\d\d)/$1\:$2/g; + } - my $previous_result = { start_date => '' }; - my $counter = 1; - for my $result (@$results) { - if ( defined $params->{template} ) { - if ( $params->{template} =~ /\.ics$/ ) { - $result->{content_ical} = - markup::plain_to_ical( $result->{content} ); - $result->{title_ical} = - markup::plain_to_ical( $result->{title} ); - $result->{user_title_ical} = - markup::plain_to_ical( $result->{user_title} ); - $result->{excerpt_ical} = - markup::plain_to_ical( $result->{excerpt} ); - $result->{user_excerpt_ical} = - markup::plain_to_ical( $result->{user_excerpt} ); - $result->{series_name} = - markup::plain_to_ical( $result->{series_name} ); - $result->{created_at} =~ s/ /T/gi; - $result->{created_at} =~ s/[\:\-]//gi; - $result->{modified_at} =~ s/ /T/gi; - $result->{modified_at} =~ s/[\:\-]//gi; + my $previous_result = { start_date => '' }; + my $counter = 1; + for my $result (@$results) { + if ( defined $params->{template} ) { + if ( $params->{template} =~ /\.ics$/ ) { + $result->{content_ical} = + markup::plain_to_ical( $result->{content} ); + $result->{title_ical} = + markup::plain_to_ical( $result->{title} ); + $result->{user_title_ical} = + markup::plain_to_ical( $result->{user_title} ); + $result->{excerpt_ical} = + markup::plain_to_ical( $result->{excerpt} ); + $result->{user_excerpt_ical} = + markup::plain_to_ical( $result->{user_excerpt} ); + $result->{series_name} = + markup::plain_to_ical( $result->{series_name} ); + $result->{created_at} =~ s/ /T/gi; + $result->{created_at} =~ s/[\:\-]//gi; + $result->{modified_at} =~ s/ /T/gi; + $result->{modified_at} =~ s/[\:\-]//gi; - } elsif ( $params->{template} =~ /\.atom\.xml/ ) { - $result->{excerpt} = '' unless defined( $result->{excerpt} ); - $result->{excerpt} = "lass dich ueberraschen" - if ( $result->{excerpt} eq '' ); + } elsif ( $params->{template} =~ /\.atom\.xml/ ) { + $result->{excerpt} = '' unless defined( $result->{excerpt} ); + $result->{excerpt} = "lass dich ueberraschen" + if ( $result->{excerpt} eq '' ); - # $result->{excerpt} =markup::plain_to_xml($result->{excerpt}); - # $result->{title} =markup::plain_to_xml($result->{title}); - # $result->{series_name} =markup::plain_to_xml($result->{series_name}); - # $result->{program} =markup::plain_to_xml($result->{program}); + # $result->{excerpt} =markup::plain_to_xml($result->{excerpt}); + # $result->{title} =markup::plain_to_xml($result->{title}); + # $result->{series_name} =markup::plain_to_xml($result->{series_name}); + # $result->{program} =markup::plain_to_xml($result->{program}); - $result->{created_at} =~ s/ /T/gi; - $result->{created_at} .= $time_diff; - $result->{modified_at} =~ s/ /T/gi; - $result->{modified_at} .= $time_diff; - } elsif ( $params->{template} =~ /\.rss\.xml/ ) { - $result->{excerpt} = '' unless defined( $result->{excerpt} ); - $result->{excerpt} = "lass dich ueberraschen" - if ( $result->{excerpt} eq '' ); + $result->{created_at} =~ s/ /T/gi; + $result->{created_at} .= $time_diff; + $result->{modified_at} =~ s/ /T/gi; + $result->{modified_at} .= $time_diff; + } elsif ( $params->{template} =~ /\.rss\.xml/ ) { + $result->{excerpt} = '' unless defined( $result->{excerpt} ); + $result->{excerpt} = "lass dich ueberraschen" + if ( $result->{excerpt} eq '' ); - # $result->{excerpt} =markup::plain_to_xml($result->{excerpt}); - # $result->{title} =markup::plain_to_xml($result->{title}); - # $result->{series_name} =markup::plain_to_xml($result->{series_name}); - # $result->{program} =markup::plain_to_xml($result->{program}); - #print STDERR "created:$result->{created_at} modified:$result->{modified_at}\n"; - $result->{modified_at} = - time::datetime_to_rfc822( $result->{modified_at} ); - if ( $result->{created_at} =~ /[1-9]/ ) { - $result->{created_at} = - time::datetime_to_rfc822( $result->{created_at} ); - } else { - $result->{created_at} = $result->{modified_at}; - } + # $result->{excerpt} =markup::plain_to_xml($result->{excerpt}); + # $result->{title} =markup::plain_to_xml($result->{title}); + # $result->{series_name} =markup::plain_to_xml($result->{series_name}); + # $result->{program} =markup::plain_to_xml($result->{program}); + #print STDERR "created:$result->{created_at} modified:$result->{modified_at}\n"; + $result->{modified_at} = + time::datetime_to_rfc822( $result->{modified_at} ); + if ( $result->{created_at} =~ /[1-9]/ ) { + $result->{created_at} = + time::datetime_to_rfc822( $result->{created_at} ); + } else { + $result->{created_at} = $result->{modified_at}; + } - } - } - $result->{series_name} ||= ''; - $result->{series_name} = '' if $result->{series_name} eq '_single_'; + } + } + $result->{series_name} ||= ''; + $result->{series_name} = '' if $result->{series_name} eq '_single_'; - $result->{rerun} = '' unless defined $result->{rerun}; + $result->{rerun} = '' unless defined $result->{rerun}; - if ( $result->{title} =~ /\#(\d+)([a-z])?\s*$/ ) { - $result->{episode} = $1 unless defined $result->{episode}; - $result->{rerun} = $2 || '' unless ( $result->{rerun} =~ /\d/ ); - $result->{title} =~ s/\#\d+[a-z]?\s*$//; - $result->{title} =~ s/\s+$//; - } - $result->{rerun} = '' if ( $result->{rerun} eq '0' ); + $result->{title} = '' unless defined $result->{title}; + if ( $result->{title} =~ /\#(\d+)([a-z])?\s*$/ ) { + $result->{episode} = $1 unless defined $result->{episode}; + $result->{rerun} = $2 || '' unless ( $result->{rerun} =~ /\d/ ); + $result->{title} =~ s/\#\d+[a-z]?\s*$//; + $result->{title} =~ s/\s+$//; + } + $result->{rerun} = '' if ( $result->{rerun} eq '0' ); - if ( ( defined $result->{recurrence_count} ) - && ( $result->{recurrence_count} > 0 ) ) - { - $result->{recurrence_count_alpha} = - markup::base26( $result->{recurrence_count} + 1 ); - $result->{recurrence_id} = $result->{recurrence}; - } else { - $result->{recurrence_count_alpha} = ''; - $result->{recurrence_count} = ''; - } + if ( ( defined $result->{recurrence_count} ) + && ( $result->{recurrence_count} > 0 ) ) + { + $result->{recurrence_count_alpha} = + markup::base26( $result->{recurrence_count} + 1 ); + $result->{recurrence_id} = $result->{recurrence}; + } else { + $result->{recurrence_count_alpha} = ''; + $result->{recurrence_count} = ''; + } - # set title keys - my $keys = get_keys($result); - for my $key ( keys %$keys ) { - $result->{$key} = $keys->{$key}; - } + # set title keys + my $keys = get_keys($result); + for my $key ( keys %$keys ) { + $result->{$key} = $keys->{$key}; + } - $result = calc_dates( $config, $result, $params, $previous_result, $time_diff ); + $result = calc_dates( $config, $result, $params, $previous_result, $time_diff ); + get_listen_key($config, $result) unless $params->{set_no_listen_keys}; - $result->{event_uri} = ''; - if ( ( defined $result->{program} ) && ( $result->{program} ne '' ) ) { - $result->{event_uri} .= $result->{program}; - $result->{event_uri} .= '-' - if ( ( $result->{series_name} ne '' ) - || ( $result->{title} ne '' ) ); - } - if ( $result->{series_name} ne '' ) { - $result->{event_uri} .= $result->{series_name}; - $result->{event_uri} .= '-' if ( $result->{title} ne '' ); - } - $result->{event_uri} .= $result->{title} if ( $result->{title} ne '' ); - $result->{event_uri} =~ s/\#/Nr./g; - $result->{event_uri} =~ s/\&/und/g; - $result->{event_uri} =~ s/\//\%2f/g; - $result->{event_uri} =~ s/[?]//g; + $result->{event_uri} = ''; + if ( ( defined $result->{program} ) && ( $result->{program} ne '' ) ) { + $result->{event_uri} .= $result->{program}; + $result->{event_uri} .= '-' + if ( ( $result->{series_name} ne '' ) + || ( $result->{title} ne '' ) ); + } + if ( ($result->{series_name}//'') ne '' ) { + $result->{event_uri} .= $result->{series_name}; + $result->{event_uri} .= '-' if ( $result->{title} ne '' ); + } + $result->{event_uri} .= $result->{title} if length $result->{title}; + $result->{event_uri} =~ s/\#/Nr./g; + $result->{event_uri} =~ s/\&/und/g; + $result->{event_uri} =~ s/\//\%2f/g; + $result->{event_uri} =~ s/[?]//g; - $result->{rds_title} = $result->{event_uri}; - $result->{rds_title} =~ s/[^a-zA-Z0-9\-]/\_/gi; - $result->{rds_title} =~ s/\_{2,99}/\_/gi; - $result->{rds_title} = substr( $result->{rds_title}, 0, 63 ); + $result->{rds_title} = $result->{event_uri}; + $result->{rds_title} =~ s/[^a-zA-Z0-9\-]/\_/gi; + $result->{rds_title} =~ s/\_{2,99}/\_/gi; + $result->{rds_title} = substr( $result->{rds_title}, 0, 63 ); - # $result->{event_id}=$result->{id}; + #$result->{event_id}=$result->{id}; - $result->{base_url} = $request->{base_url}; - $result->{base_domain} = $config->{locations}->{base_domain}; - $result->{static_files_url} = $config->{locations}->{static_files_url}; - $result->{source_base_url} = $config->{locations}->{source_base_url}; - $result->{cache_base_url} = $config->{cache}->{base_url}; + $result->{base_url} = $request->{base_url}; + $result->{base_domain} = $config->{locations}->{base_domain}; + $result->{static_files_url} = $config->{locations}->{static_files_url}; + $result->{source_base_url} = $config->{locations}->{source_base_url}; + $result->{local_base_url} = $config->{locations}->{local_base_url}; + $result->{cache_base_url} = $config->{cache}->{base_url}; - $result->{is_running} = 1 - if ( $running_event_id eq $result->{event_id} ); - $result->{one_comment} = 1 if ( $result->{comment_count} == 1 ); - $result->{no_comment} = 1 if ( $result->{comment_count} == 0 ); + $result->{is_running} = 1 if $running_event_id + && $result->{event_id} + && $running_event_id eq $result->{event_id}; - #fix image url - if ( defined $result->{image} ) { - $result->{thumb} = $result->{image}; - $result->{icon} = $result->{image}; + if (defined $result->{comment_count}){ + $result->{one_comment} = 1 if ( $result->{comment_count} == 1 ); + $result->{no_comment} = 1 if ( $result->{comment_count} == 0 ); + } - $result->{image} =~ s/thumbs/images/g; - $result->{image} =~ s/icons/images/g; + { + my $url = $config->{locations}->{local_media_url} // ''; + my $image = $result->{image}; + my $conf = $config->{locations}; + my $basic_url = "$url/images/"; - #fix thumbs url - $result->{thumb} =~ s/images/thumbs/s; - $result->{thumb} =~ s/icons/thumbs/s; + if ( defined $result->{image} ) { + $result->{thumb_url} = ($conf->{thumbs_url} // $basic_url) . $image; + $result->{icon_url} = ($conf->{icons_url} // $basic_url) . $image; + $result->{image_url} = ($conf->{images_url} // $basic_url) . $image; + } - #fix icon url - $result->{icon} =~ s/thumbs/icons/s; - $result->{icon} =~ s/images/icons/s; - } + if ( defined $result->{series_image} ) { + $result->{series_thumb_url} = ($conf->{thumbs_url} // $basic_url) . $image; + $result->{series_icon_url} = ($conf->{icons_url} // $basic_url) . $image; + $result->{series_image_url} = ($conf->{images_url} // $basic_url) . $image; + } + } - $result->{location_css} = $result->{location} || ''; - $result->{location_css} = lc( $result->{location_css} ); - $result->{location_css} =~ s/\.//g; - $result->{location_css} =~ s/\s//g; - $result->{ 'location_label_' . $result->{location_css} } = 1; + $result->{location_css} = $result->{location} || ''; + $result->{location_css} = lc( $result->{location_css} ); + $result->{location_css} =~ s/\.//g; + $result->{location_css} =~ s/\s//g; + $result->{ 'location_label_' . $result->{location_css} } = 1; - # add project by name - my $project_name = $result->{project}; - if ( defined $project_name ) { + # add project by name + my $project_name = $result->{project}; + if ( defined $project_name ) { - #print STDERR "found project:$project_name\n"; - unless ( defined $projects->{$project_name} ) { - my $results = project::get( $config, { name => $project_name } ); - $projects->{$project_name} = $results->[0] || {}; - } - my $project = $projects->{$project_name}; - for my $key ( keys %$project ) { - $result->{ 'project_' . $key } = $project->{$key}; - } - } else { - print STDERR "events::get - unknown project for event $result->{id}\n"; - } + #print STDERR "found project:$project_name\n"; + unless ( defined $projects->{$project_name} ) { + my $results = project::get( $config, { name => $project_name } ); + $projects->{$project_name} = $results->[0] || {}; + } + my $project = $projects->{$project_name}; + for my $key ( keys %$project ) { + $result->{ 'project_' . $key } = $project->{$key}; + } + } else { + printf STDERR "events::get - unknown project for event %s\n", $result->{id} // "undef"; + } - #if project_id is set add columns from project (cached) - my $project_id = $result->{project_id}; - if ( defined $project_id ) { - unless ( defined $projects->{$project_id} ) { - my $results = project::get( $config, { project_id => $project_id } ); - $projects->{$project_id} = $results->[0] || {}; - } - my $project = $projects->{$project_id}; - for my $key ( keys %$project ) { - $result->{ 'project_' . $key } = $project->{$key}; - } - } + #if project_id is set add columns from project (cached) + my $project_id = $result->{project_id}; + if ( defined $project_id ) { + unless ( defined $projects->{$project_id} ) { + my $results = project::get( $config, { project_id => $project_id } ); + $projects->{$project_id} = $results->[0] || {}; + } + my $project = $projects->{$project_id}; + for my $key ( keys %$project ) { + $result->{ 'project_' . $key } = $project->{$key}; + } + } - #if studio_id is set add columns from studio (cached) - my $studio_id = $result->{studio_id}; - if ( defined $studio_id ) { - unless ( defined $studios->{$studio_id} ) { - my $results = studios::get( $config, { studio_id => $studio_id } ); - $studios->{$studio_id} = $results->[0] || {}; - } - my $studio = $studios->{$studio_id}; - for my $key ( keys %$studio ) { - $result->{ 'studio_' . $key } = $studio->{$key}; - } - } + #if studio_id is set add columns from studio (cached) + my $studio_id = $result->{studio_id}; + if ( defined $studio_id ) { + unless ( defined $studios->{$studio_id} ) { + my $results = studios::get( $config, { studio_id => $studio_id } ); + $studios->{$studio_id} = $results->[0] || {}; + } + my $studio = $studios->{$studio_id}; + for my $key ( keys %$studio ) { + $result->{ 'studio_' . $key } = $studio->{$key}; + } + } - #$result->{'project_title'}=$project->{title} if (defined $project->{title} && $project->{title} ne ''); + #$result->{'project_title'}=$project->{title} if (defined $project->{title} && $project->{title} ne ''); - #print STDERR "project:'$project_name'\n"; - #print STDERR "title:'$result->{project_title}'\n"; - #use Data::Dumper;print STDERR Dumper($result); + for my $name ( keys %{ $config->{mapping}->{events} } ) { + my $val = ''; + if ( ( defined $name ) + && ( defined $config->{mapping}->{events}->{$name} ) + && ( defined $result->{$name} ) ) + { + $val = $config->{mapping}->{events}->{$name}->{ $result->{$name} } + || ''; + $result->{ $name . '_mapped' } = $val if ( $val ne '' ); + } + } - for my $name ( keys %{ $config->{mapping}->{events} } ) { - my $val = ''; - if ( ( defined $name ) - && ( defined $config->{mapping}->{events}->{$name} ) - && ( defined $result->{$name} ) ) - { - $val = $config->{mapping}->{events}->{$name}->{ $result->{$name} } - || ''; - $result->{ $name . '_mapped' } = $val if ( $val ne '' ); - } - } + #for my $name (keys %{$config->{controllers}}){ + # $result->{"controller_$name"}=$config->{controllers}->{$name}; + #} - #for my $name (keys %{$config->{controllers}}){ - # $result->{"controller_$name"}=$config->{controllers}->{$name}; - #} + $previous_result = $result; - $previous_result = $result; + $result->{ 'counter_' . $counter } = 1; + $counter++; - #print "Content-type:text/text\n\n"; - #use Data::Dumper;print STDERR Dumper($result); - $result->{ 'counter_' . $counter } = 1; - $counter++; + if ( ( defined $params->{template} ) + && ( $params->{template} =~ /(list|details)/ ) ) + { + if ( ( defined $result->{excerpt} ) && ( length( $result->{excerpt} ) > 250 ) ) { + $result->{excerpt} = substr( $result->{excerpt}, 0, 250 ) . '...'; + } - if ( ( defined $params->{template} ) - && ( $params->{template} =~ /(list|details)/ ) ){ - if ( ( defined $result->{excerpt} ) && ( length($result->{excerpt}) > 250) ){ - $result->{excerpt} = substr($result->{excerpt}, 0, 250).'...'; - } + if ( ( defined $result->{user_excerpt} ) && ( length( $result->{user_excerpt} ) > 250 ) ) { + $result->{user_excerpt} = substr( $result->{user_excerpt}, 0, 250 ) . '...'; + } + } - if ( (defined $result->{user_excerpt}) && (length($result->{user_excerpt}) > 250) ){ - $result->{user_excerpt} = substr($result->{user_excerpt}, 0, 250).'...'; - } - } + #build content + if ( ( defined $params->{template} ) && ( $params->{template} =~ /\.html/ ) ) { + $result->{html_content} = events::format($result, 'content') if defined $result->{content}; + $result->{html_topic} = events::format($result, 'topic') if defined $result->{topic}; + } - #build content - if ( ( defined $params->{template} ) - && ( $params->{template} =~ /\.html/ ) ) - { - if ( defined $result->{content} ) { - $result->{content} = - markup::fix_line_ends( $result->{content} ); - $result->{content} = - markup::creole_to_html( $result->{content} ); - $result->{html_content} = $result->{content}; + #detect if images are in content or topic field + my $image_in_text = 0; + $image_in_text = 1 + if ( defined $result->{content} ) + && ( $result->{content} =~ /{topic} ) + && ( $result->{topic} =~ /{no_image_in_text} = 1 if $image_in_text == 0; - } - if ( defined $result->{topic} ) { - $result->{topic} = markup::fix_line_ends( $result->{topic} ); - $result->{topic} = markup::creole_to_html( $result->{topic} ); - $result->{html_topic} = $result->{topic}; - } - } + if ( + ( defined $params->{template} ) + && ( ( $params->{template} =~ /event_perl\.txt$/ ) + || ( $params->{template} =~ /event_file_export\.txt$/ ) ) - #detect if images are in content or topic field - my $image_in_text = 0; - $image_in_text = 1 - if ( ( defined $result->{content} ) - && ( $result->{content} =~ /{topic} ) - && ( $result->{topic} =~ /{no_image_in_text} = 1 if $image_in_text == 0; + ) + { + for my $key ( keys %$result ) { + $result->{$key} =~ s/\|/\\\|/g if defined $result->{$key}; + } - if ( - ( defined $params->{template} ) - && ( ( $params->{template} =~ /event_perl\.txt$/ ) - || ( $params->{template} =~ /event_file_export\.txt$/ ) ) + # $result->{content}='no'; + } - ) - { - for my $key ( keys %$result ) { - $result->{$key} =~ s/\|/\\\|/g if ( defined $result->{$key} ); - } + } # end for results + add_recurrence_dates( $config, $results ); + return $results; +} - # $result->{content}='no'; - } - - } # end for results - add_recurrence_dates( $config, $results ); - return $results; +sub format { + my ($event, $field) = @_; + if (($event->{content_format}//'') eq 'markdown'){ + $event->{$field} = markup::markdown_to_html( $event->{$field} ); + } else { + $event->{$field} = markup::fix_line_ends( $event->{$field} ); + $event->{$field} = markup::creole_to_html( $event->{$field} ); + } + return $event->{$field}; } sub add_recurrence_dates { - my $config = shift; - my $results = shift; + my ($config, $results) = @_; - # get unique list of recurrence ids from results - my $recurrence_dates = {}; - for my $result (@$results) { - next unless defined $result->{recurrence}; - next if $result->{recurrence} == 0; - $recurrence_dates->{ $result->{recurrence} } = 0; - } + # get unique list of recurrence ids from results + my $recurrence_dates = {}; + for my $result (@$results) { + next unless defined $result->{recurrence}; + next if $result->{recurrence} == 0; + $recurrence_dates->{ $result->{recurrence} } = 0; + } - my @event_ids = keys %$recurrence_dates; - return if @event_ids == 0; + my @event_ids = keys %$recurrence_dates; + return if @event_ids == 0; - # query start date of recurrences - my $conditions = []; - my $bind_values = []; - for my $id (@event_ids) { - push @$conditions, '?'; - push @$bind_values, $id; - } - $conditions = join( ',', @$conditions ); + # query start date of recurrences + my $conditions = []; + my $bind_values = []; + for my $id (@event_ids) { + push @$conditions, '?'; + push @$bind_values, $id; + } + $conditions = join( ',', @$conditions ); - my $query = qq{ - select id event_id, start + my $query = qq{ + select id event_id, start from calcms_events where id in ($conditions) }; - #print STDERR Dumper($query); - #return; - my $dbh = db::connect($config); - my $events = db::get( $dbh, $query, $bind_values ); + my $dbh = db::connect($config); + my $events = db::get( $dbh, $query, $bind_values ); - # store start dates by recurrence id - for my $event (@$events) { - $recurrence_dates->{ $event->{event_id} } = $event->{start}; - } + # store start dates by recurrence id + for my $event (@$events) { + $recurrence_dates->{ $event->{event_id} } = $event->{start}; + } - # set start dates to results - for my $result (@$results) { - next unless defined $result->{recurrence}; - next if $result->{recurrence} == 0; - $result->{recurrence_date} = - $recurrence_dates->{ $result->{recurrence} }; - } + # set start dates to results + my $language = $config->{date}->{language} || 'en'; + for my $result (@$results) { + next unless defined $result->{recurrence}; + next if $result->{recurrence} == 0; + my $rdate = $recurrence_dates->{ $result->{recurrence} }; + if ($rdate){ + $result->{recurrence_date} = $rdate; + $result->{recurrence_date_name} = time::date_format( $config, $rdate, $language ); + ( $result->{recurrence_time_name} ) = $rdate =~ m/(\d\d\:\d\d)\:\d\d/ ; + my $ymd = time::date_to_array($rdate); + my $weekdayIndex = time::weekday( $ymd->[0], $ymd->[1], $ymd->[2] ); + $result->{recurrence_weekday_name} = time::getWeekdayNames($language)->[$weekdayIndex]; + $result->{recurrence_weekday_short_name} = time::getWeekdayNamesShort($language)->[$weekdayIndex]; + } + + } - #print STDERR Dumper($recurrence_dates); } sub calc_dates { - my $config = shift; - my $result = shift; - my $params = shift || {}; - my $previous_result = shift || {}; - my $time_diff = shift || ''; + my $config = shift; + my $result = shift; + my $params = shift || {}; + my $previous_result = shift || {}; + my $time_diff = shift || ''; - $result->{utc_offset} = $time_diff; - $result->{time_zone} = $config->{date}->{time_zone}; - my $language = $config->{date}->{language} || 'en'; + $result->{utc_offset} = $time_diff; + $result->{time_zone} = $config->{date}->{time_zone}; + my $language = $config->{date}->{language} || 'en'; - $result->{start_datetime} = $result->{start}; - $result->{start_datetime} =~ s/ /T/gi; - if ( $result->{start_datetime} =~ /(\d\d\d\d)\-(\d\d)\-(\d\d)T(\d\d)\:(\d\d)/ ) { - $result->{start_year} = $1; - $result->{start_month} = $2; - $result->{start_day} = $3; - $result->{start_hour} = $4; - $result->{start_minute} = $5; - } + $result->{start_datetime} = $result->{start}; + $result->{start_datetime} =~ s/ /T/gi; + if ( $result->{start_datetime} =~ /(\d\d\d\d)\-(\d\d)\-(\d\d)T(\d\d)\:(\d\d)/ ) { + $result->{start_year} = $1; + $result->{start_month} = $2; + $result->{start_day} = $3; + $result->{start_hour} = $4; + $result->{start_minute} = $5; + } - unless ( defined $result->{day} ) { - my $d = time::datetime_to_array( $result->{start} ); - my $hour = $d->[3]; - if ( ( defined $hour ) && ( $hour < 6 ) ) { - $result->{day} = time::add_days_to_date( $result->{start}, -1 ); - } else { - $result->{day} = time::datetime_to_date( $result->{start} ); - } - } - unless ( defined $result->{start_date} ) { - $result->{start_date} = time::datetime_to_date( $result->{start} ); - } - unless ( defined $result->{end_date} ) { - $result->{end_date} = time::datetime_to_date( $result->{end} ); - } + unless ( defined $result->{day} ) { + my $d = time::datetime_to_array( $result->{start} ); + my $hour = $d->[3]; + if ( ( defined $hour ) && ( $hour < 6 ) ) { + $result->{day} = time::add_days_to_date( $result->{start}, -1 ); + } else { + $result->{day} = time::datetime_to_date( $result->{start} ); + } + } + unless ( defined $result->{start_date} ) { + $result->{start_date} = time::datetime_to_date( $result->{start} ); + } + unless ( defined $result->{end_date} ) { + $result->{end_date} = time::datetime_to_date( $result->{end} ); + } - $result->{dtstart} = $result->{start_datetime}; - $result->{dtstart} =~ s/[\:\-]//gi; + $result->{dtstart} = $result->{start_datetime}; + $result->{dtstart} =~ s/[\:\-]//gi; - if ( ( defined $params->{template} ) - && ( $params->{template} =~ /(\.txt|\.json)/ ) ) - { - $result->{start_utc_epoch} = time::datetime_to_utc( $result->{start_datetime}, $config->{date}->{time_zone} ); - } - if ( ( defined $params->{template} ) - && ( $params->{template} =~ /(\.xml)/ ) ) - { - $result->{start_datetime_utc} = time::datetime_to_utc_datetime( $result->{start_datetime}, $config->{date}->{time_zone} ); - } + if ( ( defined $params->{template} ) + && ( $params->{template} =~ /(\.txt|\.json)/ ) ) + { + $result->{start_utc_epoch} = time::datetime_to_utc( $result->{start_datetime}, $config->{date}->{time_zone} ); + } + if ( ( defined $params->{template} ) + && ( $params->{template} =~ /(\.xml)/ ) ) + { + $result->{start_datetime_utc} = + time::datetime_to_utc_datetime( $result->{start_datetime}, $config->{date}->{time_zone} ); + } - $result->{end_datetime} = $result->{end}; - $result->{end_datetime} =~ s/ /T/gi; + $result->{end_datetime} = $result->{end}; + $result->{end_datetime} =~ s/ /T/gi; - $result->{dtend} = $result->{end_datetime}; - $result->{dtend} =~ s/[\:\-]//gi; + $result->{dtend} = $result->{end_datetime}; + $result->{dtend} =~ s/[\:\-]//gi; - if ( ( defined $params->{template} ) - && ( $params->{template} =~ /(\.txt|\.json)/ ) ) - { - $result->{end_utc_epoch} = time::datetime_to_utc( $result->{end_datetime}, $config->{date}->{time_zone} ); - } - if ( ( defined $params->{template} ) - && ( $params->{template} =~ /(\.xml)/ ) ) - { - $result->{end_datetime_utc} = time::datetime_to_utc_datetime( $result->{end_datetime}, $config->{date}->{time_zone} ); - } + if ( ( defined $params->{template} ) + && ( $params->{template} =~ /(\.txt|\.json)/ ) ) + { + $result->{end_utc_epoch} = time::datetime_to_utc( $result->{end_datetime}, $config->{date}->{time_zone} ); + } + if ( ( defined $params->{template} ) + && ( $params->{template} =~ /(\.xml)/ ) ) + { + $result->{end_datetime_utc} = + time::datetime_to_utc_datetime( $result->{end_datetime}, $config->{date}->{time_zone} ); + } - if ( ( defined $previous_result ) - && ( defined $previous_result->{start_date} ) - && ( $result->{start_date} ne $previous_result->{start_date} ) ) - { - $result->{is_first_of_day} = 1; - $previous_result->{is_last_of_day} = 1; - } + if ( ( defined $previous_result ) + && ( defined $previous_result->{start_date} ) + && ( $result->{start_date} ne $previous_result->{start_date} ) ) + { + $result->{is_first_of_day} = 1; + $previous_result->{is_last_of_day} = 1; + } - $result->{start_date_name} = - time::date_format( $result->{start_date}, $language ); - $result->{end_date_name} = - time::date_format( $result->{end_date}, $language ); + $result->{start_date_name} = + time::date_format( $config, $result->{start_date}, $language ); + $result->{end_date_name} = + time::date_format( $config, $result->{end_date}, $language ); - if ( $result->{start} =~ /(\d\d\:\d\d)\:\d\d/ ) { - $result->{start_time_name} = $1; - $result->{start_time} = $1; - } + if ( $result->{start} =~ /(\d\d\:\d\d)\:\d\d/ ) { + $result->{start_time_name} = $1; + $result->{start_time} = $1; + } - if ( $result->{end} =~ /(\d\d\:\d\d)\:\d\d/ ) { - $result->{end_time_name} = $1; - $result->{end_time} = $1; - } + if ( $result->{end} =~ /(\d\d\:\d\d)\:\d\d/ ) { + $result->{end_time_name} = $1; + $result->{end_time} = $1; + } - if ( defined $result->{weekday} ) { - my $language = $config::config->{date}->{language} || 'en'; + if ( defined $result->{weekday} ) { + my $language = $config->{date}->{language} || 'en'; + my $weekdayIndex = time::getWeekdayIndex( $result->{weekday} ) || 0; + $result->{weekday_name} = time::getWeekdayNames($language)->[$weekdayIndex]; + $result->{weekday_short_name} = time::getWeekdayNamesShort($language)->[$weekdayIndex]; + } - #my $weekdays=time::get_weekdays(); - my $weekday_index = $time::weekday_index->{ $result->{weekday} . '' } || 0; - $result->{weekday_name} = - $time::names->{$language}->{weekdays}->[$weekday_index]; - $result->{weekday_short_name} = - $time::names->{$language}->{weekdays_abbr}->[$weekday_index]; - } - return $result; + return $result; } -sub add_recordings{ - my $dbh = shift; - my $config = shift; - my $request = shift; - my $events = shift; +sub get_listen_key($$){ + my ($config, $event) =@_; + + my $time_zone = $config->{date}->{time_zone}; + my $start = time::datetime_to_utc( $event->{start_datetime}, $time_zone ); + my $now = time::datetime_to_utc( time::time_to_datetime( time() ), $time_zone); + my $over_since = $now-$start; + + return if $over_since < 0; + return if $over_since > 7*24*60*60; + + my $archive_dir = $config->{locations}->{local_archive_dir}; + my $archive_url = $config->{locations}->{listen_url}; + return $event->{listen_url} = $archive_url . '/' . $event->{listen_key} if + defined $event->{listen_key} and -l $archive_dir .'/'. $event->{listen_key}; + set_listen_key($config, $event) unless $event->{listen_key}; +} + +sub set_listen_key{ + my ($config, $event) =@_; + my $archive_dir = $config->{locations}->{local_archive_dir}; + my $archive_url = $config->{locations}->{listen_url}; + my $datetime = $event->{start_datetime}; + if ( $datetime =~ /(\d\d\d\d\-\d\d\-\d\d)[ T](\d\d)\:(\d\d)/ ) { + $datetime = $1 . '\ ' . $2 . '_' . $3; + } else { + print STDERR "update_recording_link: no valid datetime found $datetime\n"; + return; + } + my @files = glob( $archive_dir . '/' . $datetime . '*.mp3' ); + return if @files <= 0; + + my $key = int( rand(99999999999999999) ); + $key = MIME::Base64::encode_base64($key); + $key =~ s/[^a-zA-Z0-9]//g; + $key .='.mp3'; + + my $audio_file = Encode::decode( "UTF-8", $files[0] ); + my $link = $archive_dir . '/' . $key; + symlink $audio_file, $link or die "cannot create $link, $!"; + $event->{listen_url} = $archive_url . '/' . $key; + $event->{listen_key} = $key; + + return undef unless defined $event->{event_id}; + return undef unless defined $event->{listen_key}; + my $bindValues = [ $event->{listen_key}, $event->{event_id} ]; + + my $query = qq{ + update calcms_events + set listen_key=? + where id=?; + }; + my $dbh = db::connect($config); + my $recordings = db::put( $dbh, $query, $bindValues ); +} + +sub set_upload_status($$){ + my ($config, $event) = @_; + + print STDERR "set upload_status=$event->{upload_status} for ".$event->{event_id}."\n"; + return undef unless defined $event->{event_id}; + return undef unless defined $event->{upload_status}; + my $bindValues = [ $event->{upload_status}, $event->{event_id}, $event->{upload_status} ]; + + my $query = qq{ + update calcms_events + set upload_status=? + where id=? and upload_status!=?; + }; + my $dbh = db::connect($config); + my $recordings = db::put( $dbh, $query, $bindValues ); +} + +sub add_recordings($$$$) { + my ($dbh, $config, $request, $events) = @_; -# print STDERR Dumper($results); return $events unless defined $events; my $params = $request->{params}->{checked}; return $events unless defined $params; return $events unless defined $params->{recordings}; - my @ids=(); - my $eventsById={}; + my @ids = (); + my $eventsById = {}; + #my $events = $results; - - for my $event (@$events){ + + for my $event (@$events) { my $eventId = $event->{event_id}; push @ids, $eventId; $eventsById->{$eventId} = $event; } + my $qms = join( ', ', ( map { '?' } @$events ) ); + my $bindValues = join( ', ', ( map { $_->{event_id} } @$events ) ); - my $qms = join( ', ', (map { '?' } @$events)); - my $bindValues = join( ', ', (map { $_->{event_id} } @$events)); - - my $query = qq{ + my $query = qq{ select * from calcms_audio_recordings where event_id in ($qms) order by created_at; }; - $dbh = db::connect($config) unless defined $dbh; - my $recordings = db::get( $dbh, $query, $bindValues ); - #print STDERR Dumper($recordings); + $dbh = db::connect($config) unless defined $dbh; + my $recordings = db::get( $dbh, $query, $bindValues ); - for my $entry (@$recordings){ + for my $entry (@$recordings) { my $eventId = $entry->{event_id}; - my $event = $eventsById->{$eventId}; + my $event = $eventsById->{$eventId}; push @{ $event->{recordings} }, $entry; } - - return $events; + + return $events; +} + +sub getDateQueryConditions ($$$) { + my ($config, $params, $bind_values) = @_; + + # conditions by date + my $date_conds = []; + + #date, today, tomorrow, yesterday + my $date = ''; + $date = time::date_cond( $params->{date} ) if $params->{date} ne ''; + + my $from_date = ''; + $from_date = time::date_cond( $params->{from_date} ) if $params->{from_date} ne ''; + + my $till_date = ''; + $till_date = time::date_cond( $params->{till_date} ) if $params->{till_date} ne ''; + + my $from_time = ''; + $from_time = time::time_cond( $params->{from_time} ) if $params->{from_time} ne ''; + + my $till_time = ''; + $till_time = time::time_cond( $params->{till_time} ) if $params->{till_time} ne ''; + + my $time = $params->{time}; + $time = '' unless defined $time; + + my $date_range_include = $params->{date_range_include}; + my $day_starting_hour = $config->{date}->{day_starting_hour}; + + if ( $date eq 'today' ) { + my $date = time::get_event_date($config); + push @$date_conds, ' ( start_date = ? ) '; + push @$bind_values, $date; + return $date_conds; + } + + # given date + my $start = time::datetime_cond( $date . 'T00:00:00' ); + if ( $start ne '' ) { + $start = time::add_hours_to_datetime( $start, $day_starting_hour ); + my $end = time::add_hours_to_datetime( $start, 24 ); + + if ( $date_range_include eq '1' ) { + push @$date_conds, ' end > ? '; + push @$bind_values, $start; + } else { + push @$date_conds, ' start >= ? '; + push @$bind_values, $start; + } + + push @$date_conds, ' start < ? '; + push @$bind_values, $end; + return $date_conds; + } + + if ( $time eq 'now' ) { + push @$date_conds, qq{ + ( + ( unix_timestamp(end) > unix_timestamp(now() ) ) + and + ( unix_timestamp(start) <= unix_timestamp(now() ) ) + ) + }; + return $date_conds; + } + + if ( $time eq 'future' ) { + push @$date_conds, qq{ + ( + ( unix_timestamp(end) > unix_timestamp(now() ) ) + and + ( unix_timestamp(end) - unix_timestamp(now() ) ) < 7*24*3600 + ) + }; + return $date_conds; + } + + #from_date and from_time is defined + if ( ( $from_date ne '' ) && ( $from_time ne '' ) ) { + my $datetime = time::datetime_cond( $from_date . 'T' . $from_time ); + if ( $datetime ne '' ) { + if ( $date_range_include eq '1' ) { + push @$date_conds, ' end > ? '; + push @$bind_values, $datetime; + $from_date = ''; + } else { + push @$date_conds, ' start >= ? '; + push @$bind_values, $datetime; + $from_date = ''; + } + } + } + + #till_date and till_time is defined + if ( ( $till_date ne '' ) && ( $till_time ne '' ) ) { + my $datetime = time::datetime_cond( $till_date . 'T' . $till_time ); + if ( $datetime ne '' ) { + push @$date_conds, ' start < ? '; + push @$bind_values, $datetime; + $till_date = ''; + } + } + + # after start of daily broadcast + if ( ( $from_date ne '' ) && ( $from_time eq '' ) ) { + my $start = time::datetime_cond( $from_date . 'T00:00:00' ); + $start = time::add_hours_to_datetime( $start, $day_starting_hour ); + + if ( $date_range_include eq '1' ) { + + # end is after start + push @$date_conds, ' ( end >= ? )'; + push @$bind_values, $start; + } else { + push @$date_conds, ' ( start >= ? ) '; + push @$bind_values, $start; + } + } + + # before end of daily broadcast + if ( ( $till_date ne '' ) && ( $till_time eq '' ) ) { + my $end = time::datetime_cond( $till_date . 'T00:00:00' ); + $end = time::add_hours_to_datetime( $end, $day_starting_hour ); + if ( $date_range_include eq '1' ) { + + # start is before end + push @$date_conds, ' ( start <= ? )'; + push @$bind_values, $end; + } else { + push @$date_conds, ' ( end <= ? ) '; + push @$bind_values, $end; + } + } + + if ( $params->{weekday} ne '' ) { + my $weekday = $params->{weekday}; + $weekday += 1; + $weekday -= 7 if ( $weekday > 7 ); + push @$date_conds, ' (dayofweek(start)= ?) '; + push @$bind_values, $weekday; + } + + if ( $params->{last_days} ) { + my $d = int $params->{last_days}; + push @$date_conds, qq{ ( end between date_sub(now(),INTERVAL $d DAY) and now() ) }; + } elsif ( $params->{archive} eq 'past' ) { + my $date = time::get_event_date($config); + if ( $date ne '' ) { + push @$date_conds, ' ( start < ? ) '; + push @$bind_values, $date; + } + + } elsif ( $params->{archive} eq 'future' ) { + my $date = time::get_event_date($config); + if ( $date ne '' ) { + push @$date_conds, ' ( end >= ? ) '; + push @$bind_values, $date; + } + } + return $date_conds; + } # if recordings is set in params, recordings date and path will be included -sub get_query { - my $dbh = shift; - my $config = shift; - my $request = shift; - - my $params = $request->{params}->{checked}; - my $debug = $config->{system}->{debug}; +sub get_query($$$) { + my ($dbh, $config, $request) = @_; + my $params = $request->{params}->{checked}; $params->{recordings} = '' unless defined $params->{recordings}; - my $bind_values = []; - my $where_cond = []; - my $order_cond = ''; - my $limit_cond = ''; + my $bind_values = []; + my $where_cond = []; + my $order_cond = ''; + my $limit_cond = ''; - if ( $params->{event_id} ne '' ) { + if ( $params->{event_id} ne '' ) { - # conditions by event id - push @$where_cond, 'e.id=?'; - $bind_values = [ $params->{event_id} ]; + # conditions by event id + push @$where_cond, 'e.id=?'; + $bind_values = [ $params->{event_id} ]; - #filter by published, default=1 to see published only, set published='all' to see all - my $published = $params->{published} || 1; - if ( ( $published eq '0' ) || ( $published eq '1' ) ) { - push @$where_cond, 'published=?'; - push @$bind_values, $published; - } + #filter by published, default=1 to see published only, set published='all' to see all + my $published = $params->{published} || '1'; + if ( ( $published eq '0' ) || ( $published eq '1' ) ) { + push @$where_cond, 'published=?'; + push @$bind_values, $published; + } - my $draft = $params->{draft} || '0'; - if ( ( $draft eq '0' ) || ( $draft eq '1' ) ) { - push @$where_cond, 'draft=?'; - push @$bind_values, $draft; - } + my $draft = $params->{draft} || '0'; + if ( ( $draft eq '0' ) || ( $draft eq '1' ) ) { + push @$where_cond, 'draft=?'; + push @$bind_values, $draft; + } - } else { + } else { - # conditions by date - my @date_conds = (); + my $date_conds = getDateQueryConditions( $config, $params, $bind_values ); + my $date_cond = join " and ", @$date_conds; - #date, today, tomorrow, yesterday - my $date = ''; - $date = time::date_cond( $params->{date} ) if ( $params->{date} ne '' ); + push @$where_cond, $date_cond if ( $date_cond ne '' ); + } - my $from_date = ''; - $from_date = time::date_cond( $params->{from_date} ) - if ( $params->{from_date} ne '' ); + # location + my $location_cond = ''; + if ( $params->{location} ne '' ) { + my $location = ( split( /\,/, $params->{location} ) )[0]; + $location =~ s/[^a-zA-Z0-9\-\_]/%/g; + $location =~ s/%{2,99}/%/g; + if ( $location ne '' ) { + $location_cond = ' location like ? '; + push @$bind_values, $location; + } + } - my $till_date = ''; - $till_date = time::date_cond( $params->{till_date} ) - if ( $params->{till_date} ne '' ); + # exclude location + my $exclude_location_cond = ''; + if ( $params->{exclude_locations} eq '1' ) { + if ( $params->{locations_to_exclude} ne '' ) { + my @locations_to_exclude = split( /,/, $params->{locations_to_exclude} ); + $exclude_location_cond = 'location not in (' . join( ",", map { '?' } @locations_to_exclude ) . ')'; + for my $location (@locations_to_exclude) { + $location =~ s/^\s+//g; + $location =~ s/\s+$//g; + push @$bind_values, $location; + } + } + } - my $from_time = ''; - $from_time = time::time_cond( $params->{from_time} ) - if ( $params->{from_time} ne '' ); + # exclude project + my $exclude_project_cond = ''; + if ( $params->{exclude_projects} eq '1' ) { + if ( $params->{projects_to_exclude} ne '' ) { + my @projects_to_exclude = split( /,/, $params->{projects_to_exclude} ); + $exclude_project_cond = 'project not in (' . join( ",", map { '?' } @projects_to_exclude ) . ')'; + for my $project (@projects_to_exclude) { + $project =~ s/^\s+//g; + $project =~ s/\s+$//g; + push @$bind_values, $project; + } + } + } - my $till_time = ''; - $till_time = time::time_cond( $params->{till_time} ) - if ( $params->{till_time} ne '' ); + my $series_name_cond = ''; + if ( ( defined $params->{series_name} ) + && ( $params->{series_name} ne '' ) ) + { + my $series_name = ( split( /\,/, $params->{series_name} ) )[0]; + $series_name =~ s/[^a-zA-Z0-9]/%/g; + $series_name =~ s/%{2,99}/%/g; + if ( $series_name ne '' ) { + $series_name_cond = ' series_name like ? '; + push @$bind_values, $series_name; + } + } - my $date_range_include = $params->{date_range_include}; - - #from_time is defined - if ( ( $params->{from_date} ne '' ) && ( $params->{from_time} ne '' ) ) { - my $datetime = time::datetime_cond( $from_date . 'T' . $from_time ); - if ( $datetime ne '' ) { - if ( $date_range_include eq '1' ) { - push @date_conds, ' end > ? '; - push @$bind_values, $datetime; - $from_date = ''; - } else { - push @date_conds, ' start >= ? '; - push @$bind_values, $datetime; - $from_date = ''; - } - } - } - - #till_time is defined - if ( ( $params->{till_date} ne '' ) && ( $params->{till_time} ne '' ) ) { - my $datetime = time::datetime_cond( $till_date . 'T' . $till_time ); - if ( $datetime ne '' ) { - push @date_conds, ' start < ? '; - push @$bind_values, $datetime; - $till_date = ''; - } - } - - #time is defined - if ( ( defined $params->{time} ) - && ( $params->{time} ne '' ) - && ( $params->{time} ne 'now' ) - && ( $params->{time} ne 'future' ) ) - { - my $time = time::time_cond( $params->{time} ); - if ( $time ne '' ) { - push @date_conds, ' time(start) = ? '; - push @$bind_values, $time; - } - } - - #event is not over - if ( ( defined $params->{time} ) && ( $params->{time} eq 'now' ) ) { - push @date_conds, qq{ - ( - ( unix_timestamp(end) > unix_timestamp(now() ) ) - and - ( unix_timestamp(start) <= unix_timestamp(now() ) ) - ) - }; - - } elsif ( ( defined $params->{time} ) && ( $params->{time} eq 'future' ) ) { - push @date_conds, qq{ - ( - ( unix_timestamp(end) > unix_timestamp(now() ) ) - and - ( unix_timestamp(end) - unix_timestamp(now() ) ) < 7*24*3600 - ) - }; - - } elsif ( $date ne '' ) { - if ( $date eq 'today' ) { - my $date = time::get_event_date($config); - if ( $date ne '' ) { - push @date_conds, ' ( start_date = ? ) '; - push @$bind_values, $date; - } - - } else { - if ( $date ne '' ) { - push @date_conds, ' ( start_date = ? ) '; - push @$bind_values, $date; - } - } - } else { - if ( $from_date ne '' ) { - if ( $date_range_include eq '1' ) { - - # end is after start - push @date_conds, ' ( end_date >= ? )'; - push @$bind_values, $from_date; - } else { - push @date_conds, ' ( start_date >= ? ) '; - push @$bind_values, $from_date; - } - } - - if ( $till_date ne '' ) { - if ( $date_range_include eq '1' ) { - - # start is before end - push @date_conds, ' ( start_date <= ? )'; - push @$bind_values, $till_date; - } else { - push @date_conds, ' ( end_date <= ? ) '; - push @$bind_values, $till_date; - } - } - - if ( $params->{weekday} ne '' ) { - my $weekday = $params->{weekday}; - $weekday += 1; - $weekday -= 7 if ( $weekday > 7 ); - push @date_conds, ' (dayofweek(start_date)= ?) '; - push @$bind_values, $weekday; - } - - if ( $params->{archive} eq 'past' ) { - my $date = time::get_event_date($config); - if ( $date ne '' ) { - push @date_conds, ' ( start_date < ? ) '; - push @$bind_values, $date; - } - - } elsif ( $params->{archive} eq 'future' ) { - my $date = time::get_event_date($config); - if ( $date ne '' ) { - push @date_conds, ' ( start_date >= ? ) '; - push @$bind_values, $date; - } - } - - } - - my $date_cond = join " and ", @date_conds; - push @$where_cond, $date_cond if ( $date_cond ne '' ); - } - - # location - my $location_cond = ''; - if ( $params->{location} ne '' ) { - my $location = ( split( /\,/, $params->{location} ) )[0]; - $location =~ s/[^a-zA-Z0-9]/%/g; - $location =~ s/%{2,99}/%/g; - if ( $location ne '' ) { - $location_cond = ' location like ? '; - push @$bind_values, $location; - } - } - - # exclude location - my $exclude_location_cond = ''; - if ( $params->{no_exclude} ne '1' ) { - if ( $params->{exclude_locations} ne '' ) { - my @exclude_locations = split( /,/, $params->{exclude_locations} ); - $exclude_location_cond = 'location not in (' . join( ",", map { '?' } @exclude_locations ) . ')'; - for my $location (@exclude_locations) { - $location =~ s/^\s+//g; - $location =~ s/\s+$//g; - push @$bind_values, $location; - } - } - } - - # exclude project - my $exclude_project_cond = ''; - if ( $params->{no_exclude} ne '1' ) { - if ( $params->{exclude_projects} ne '' ) { - my @exclude_projects = split( /,/, $params->{exclude_projects} ); - $exclude_project_cond = 'project not in (' . join( ",", map { '?' } @exclude_projects ) . ')'; - for my $project (@exclude_projects) { - $project =~ s/^\s+//g; - $project =~ s/\s+$//g; - push @$bind_values, $project; - } - } - } - - #filter for category - my $category_cond = ''; - if ( $params->{category} ne '' ) { - my $category = ( split( /\,/, $params->{category} ) )[0]; - $category =~ s/[^a-zA-Z0-9]/%/g; - $category =~ s/%{2,99}/%/g; - if ( $category ne '' ) { - $category_cond = qq{ - id in( - select event_id from calcms_categories - where name like ? - ) - }; - } - push @$bind_values, $category; - } - - my $series_name_cond = ''; - if ( ( defined $params->{series_name} ) - && ( $params->{series_name} ne '' ) ) - { - my $series_name = ( split( /\,/, $params->{series_name} ) )[0]; - $series_name =~ s/[^a-zA-Z0-9]/%/g; - $series_name =~ s/%{2,99}/%/g; - if ( $series_name ne '' ) { - $series_name_cond = ' series_name like ? '; - push @$bind_values, $series_name; - } - } - - #filter for tags - my $tag_cond = ''; - if ( ( defined $params->{tag} ) && ( $params->{tag} ne '' ) ) { - my @tags = ( split( /\,/, $params->{tag} ) ); - if ( scalar @tags > 0 ) { - my $tags = join ",", ( map { '?' } @tags ); - for my $tag (@tags) { - push @$bind_values, $tag; - } - $tag_cond = qq{ + #filter for tags + my $tag_cond = ''; + if ( ( defined $params->{tag} ) && ( $params->{tag} ne '' ) ) { + my @tags = ( split( /\,/, $params->{tag} ) ); + if ( scalar @tags > 0 ) { + my $tags = join ",", ( map { '?' } @tags ); + for my $tag (@tags) { + push @$bind_values, $tag; + } + $tag_cond = qq{ id in( select event_id from calcms_tags where name in($tags) ) }; - } - } - $tag_cond = ''; + } + } + $tag_cond = ''; - my $title_cond = ''; - if ( ( defined $params->{title} ) && ( $params->{title} ne '' ) ) { - my $title = ( split( /\,/, $params->{title} ) )[0]; - $title =~ s/[^a-zA-Z0-9]/%/g; - $title =~ s/%{2,99}/%/g; - $title =~ s/^\%//; - $title =~ s/\%$//; - $title = '%' . $title . '%'; - if ( $title ne '' ) { - $title_cond = ' title like ? '; - push @$bind_values, $title; - } - } + my $title_cond = ''; + if ( ( defined $params->{title} ) && ( $params->{title} ne '' ) ) { + my $title = ( split( /\,/, $params->{title} ) )[0]; + $title =~ s/[^a-zA-Z0-9]/%/g; + $title =~ s/%{2,99}/%/g; + $title =~ s/^\%//; + $title =~ s/\%$//; + $title = '%' . $title . '%'; + if ( $title ne '' ) { + $title_cond = ' title like ? '; + push @$bind_values, $title; + } + } - my $search_cond = ''; - if ( ( defined $params->{search} ) && ( $params->{search} ne '' ) ) { - my $search = lc $params->{search}; - $search =~ s/[^a-z0-9\_\.\-\:\!öäüßÖÄÜ \&]/%/; - $search =~ s/\%+/\%/; - $search =~ s/^[\%\s]+//; - $search =~ s/[\%\s]+$//; - if ( $search ne '' ) { - $search = '%' . $search . '%'; - my @attr = ( 'title', 'series_name', 'excerpt', 'category', 'content', 'topic' ); - $search_cond = "(" . join( " or ", map { 'lower(' . $_ . ') like ?' } @attr ) . ")"; - for my $attr (@attr) { - push @$bind_values, $search; - } - } - } + my $search_cond = ''; + if ( ( defined $params->{search} ) && ( $params->{search} ne '' ) ) { + my $search = lc $params->{search}; + $search =~ s/(?=[\\%_])/\\/g; + $search =~ s/^[\%\s]+//; + $search =~ s/[\%\s]+$//; + if ( $search ne '' ) { + $search = '%' . $search . '%'; + my @attr = ( 'title', 'series_name', 'excerpt', 'content', 'topic' ); + $search_cond = "(" . join( " or ", map { 'lower(' . $_ . ') like ?' } @attr ) . ")"; + for my $attr (@attr) { + push @$bind_values, $search; + } + } + } - my $project_cond = ''; + my $project_cond = ''; - # if ($filter_by_project eq'1'){ - my $project = undef; #$params->{default_project}; - $project = $params->{project} - if ( ( defined $params->{project} ) && ( $params->{project} ne '' ) ); - my $project_name = ''; - $project_name = $project->{name} - if ( ( defined $project ) - && ( defined $project->{name} ) - && ( $project->{name} ne '' ) ); - if ( ( $project_name ne '' ) && ( $project_name ne 'all' ) ) { - $project_cond = '(project=?)'; - push @$bind_values, $project_name; - } + my $project = undef; + $project = $params->{project} + if ( defined $params->{project} ) && ( $params->{project} ne '' ); - # } + my $project_name = ''; + $project_name = $project->{name} + if ( defined $project ) + && ( defined $project->{name} ) + && ( $project->{name} ne '' ); - #filter by published, default =1, set to 'all' to see all - my $published_cond = ''; - my $published = $params->{published} || 1; - if ( ( $published eq '0' ) || ( $published eq '1' ) ) { - $published_cond = 'published=?'; - push @$bind_values, $published; - } + if ( ( $project_name ne '' ) && ( $project_name ne 'all' ) ) { + $project_cond = '(project=?)'; + push @$bind_values, $project_name; + } - #filter by draft, default =1, set to 'all' to see all - my $draft_cond = ''; - my $draft = $params->{draft} || '0'; - if ( ( $draft eq '0' ) || ( $draft eq '1' ) ) { - $draft_cond = 'draft=?'; - push @$bind_values, $draft; - } + #filter by published, default =1, set to 'all' to see all + my $published_cond = ''; + my $published = $params->{published} || '1'; + if ( ( $published eq '0' ) || ( $published eq '1' ) ) { + $published_cond = 'published=?'; + push @$bind_values, $published; + } - my $disable_event_sync_cond = ''; - my $disable_event_sync = $params->{disable_event_sync} || ''; - if ( ( $disable_event_sync eq '0' ) || ( $disable_event_sync eq '1' ) ) { - $disable_event_sync_cond = 'disable_event_sync=?'; - push @$bind_values, $disable_event_sync; - } + #filter by draft, default =1, set to 'all' to see all + my $draft_cond = ''; + my $draft = $params->{draft} || '0'; + if ( ( $draft eq '0' ) || ( $draft eq '1' ) ) { + $draft_cond = 'draft=?'; + push @$bind_values, $draft; + } - #print STDERR $disable_event_sync_cond." ".$bind_values->[-1]."\n"; + my $disable_event_sync_cond = ''; + my $disable_event_sync = $params->{disable_event_sync} || ''; + if ( ( $disable_event_sync eq '0' ) || ( $disable_event_sync eq '1' ) ) { + $disable_event_sync_cond = 'disable_event_sync=?'; + push @$bind_values, $disable_event_sync; + } - #combine date, location, category, series_name, tag, search and project + #print STDERR $disable_event_sync_cond." ".$bind_values->[-1]."\n"; - push @$where_cond, $location_cond if ( $location_cond =~ /\S/ ); - push @$where_cond, $exclude_location_cond - if ( $exclude_location_cond =~ /\S/ ); - push @$where_cond, $exclude_project_cond - if ( $exclude_project_cond =~ /\S/ ); - push @$where_cond, $category_cond if ( $category_cond =~ /\S/ ); - push @$where_cond, $series_name_cond if ( $series_name_cond =~ /\S/ ); - push @$where_cond, $tag_cond if ( $tag_cond =~ /\S/ ); - push @$where_cond, $title_cond if ( $title_cond =~ /\S/ ); - push @$where_cond, $search_cond if ( $search_cond =~ /\S/ ); - push @$where_cond, $project_cond if ( $project_cond =~ /\S/ ); - push @$where_cond, $published_cond if ( $published_cond =~ /\S/ ); - push @$where_cond, $draft_cond if ( $draft_cond =~ /\S/ ); - push @$where_cond, $disable_event_sync_cond - if ( $disable_event_sync_cond ne '' ); + #combine date, location, series_name, tag, search and project - #print STDERR Dumper($where_cond); + push @$where_cond, $location_cond if ( $location_cond =~ /\S/ ); + push @$where_cond, $exclude_location_cond + if ( $exclude_location_cond =~ /\S/ ); + push @$where_cond, $exclude_project_cond + if ( $exclude_project_cond =~ /\S/ ); + push @$where_cond, $series_name_cond if ( $series_name_cond =~ /\S/ ); + push @$where_cond, $tag_cond if ( $tag_cond =~ /\S/ ); + push @$where_cond, $title_cond if ( $title_cond =~ /\S/ ); + push @$where_cond, $search_cond if ( $search_cond =~ /\S/ ); + push @$where_cond, $project_cond if ( $project_cond =~ /\S/ ); + push @$where_cond, $published_cond if ( $published_cond =~ /\S/ ); + push @$where_cond, $draft_cond if ( $draft_cond =~ /\S/ ); + push @$where_cond, $disable_event_sync_cond + if ( $disable_event_sync_cond ne '' ); - #order is forced - if ( $params->{order} eq 'asc' ) { - $order_cond = 'order by start'; - } elsif ( $params->{order} eq 'desc' ) { - $order_cond = 'order by start desc'; - } else { + #order is forced + if ( $params->{order} eq 'asc' ) { + $order_cond = 'order by start'; + } elsif ( $params->{order} eq 'desc' ) { + $order_cond = 'order by start desc'; + } else { - #derivate order from archive flag - if ( $params->{archive} eq 'past' ) { - $order_cond = 'order by start desc'; - } else { - $order_cond = 'order by start'; - } - } + #derivate order from archive flag + if ( $params->{archive} eq 'past' ) { + $order_cond = 'order by start desc'; + } else { + $order_cond = 'order by start'; + } + } - if ( ( defined $params->{limit} ne '' ) && ( $params->{limit} ne '' ) ) { - $limit_cond = 'limit ' . $params->{limit}; - } + if ( ( defined $params->{limit} ne '' ) && ( $params->{limit} ne '' ) ) { + $limit_cond = 'limit ' . $params->{limit}; + } - my $query = qq{ + my $query = qq{ select date(e.start) start_date ,date(e.end) end_date @@ -1002,6 +1091,7 @@ sub get_query { ,e.id event_id ,e.start ,e.end + ,TIMEDIFF(e.end,e.start) duration ,e.program ,e.series_name ,e.title @@ -1010,6 +1100,9 @@ sub get_query { ,e.modified_by ,e.comment_count ,e.image + ,e.image_label + ,e.series_image + ,e.series_image_label ,e.reference ,e.recurrence ,e.recurrence_count @@ -1029,179 +1122,176 @@ sub get_query { ,e.live ,e.disable_event_sync ,e.episode + ,e.listen_key + ,e.upload_status + ,e.content_format }; - my $template = $params->{template} || ''; + my $template = $params->{template} || ''; - $query .= ',e.excerpt' unless ( $template =~ /menu/ ); + $query .= ',e.excerpt' unless ( $template =~ /menu/ ); - # $query.=',e.project' unless ($template=~/menu/ || $template=~/list/); + # $query.=',e.project' unless ($template=~/menu/ || $template=~/list/); - my $get = $params->{get} || ''; - unless ( $get eq 'no_content' ) { - if ( $template =~ /\.html/ ) { - unless ( $template =~ /menu/ || $template =~ /list/ ) { - $query .= ', e.content, e.topic, e.html_content, e.html_topic'; + my $get = $params->{get} || ''; + unless ( $get eq 'no_content' ) { + unless ( $template =~ /menu/ || $template =~ /list/ ) { + $query .= ', e.content, e.topic, e.html_content, e.html_topic'; + } + } - #$query.=',html_content content, html_topic topic' ; - } - } else { - unless ( $template =~ /menu/ || $template =~ /list/ ) { - $query .= ', e.content, e.topic, e.html_content, e.html_topic'; - } - } - } + # add project id and series id + if ( ( $params->{project_id} ne '' ) || ( $params->{studio_id} ne '' ) ) { + if ( $params->{project_id} ne '' ) { + push @$where_cond, 'se.project_id=?'; + push @$bind_values, $params->{project_id}; + $query .= ', se.project_id'; + } + if ( $params->{studio_id} ne '' ) { + push @$where_cond, 'se.studio_id=?'; + push @$bind_values, $params->{studio_id}; + $query .= ', se.studio_id'; + } - # add project id and series id - if ( ( $params->{project_id} ne '' ) || ( $params->{studio_id} ne '' ) ) { - if ( $params->{project_id} ne '' ) { - push @$where_cond, 'se.project_id=?'; - push @$bind_values, $params->{project_id}; - $query .= ', se.project_id'; - } - if ( $params->{studio_id} ne '' ) { - push @$where_cond, 'se.studio_id=?'; - push @$bind_values, $params->{studio_id}; - $query .= ', se.studio_id'; - } - #push @$where_cond, 'se.event_id=e.id'; - } + #push @$where_cond, 'se.event_id=e.id'; + } - # add recordings field and conditions - if ($params->{recordings} eq '1' ) { - $query .= ', ar.path'; - $query .= ', ar.size'; - $query .= ', ar.created_by uploaded_by'; - $query .= ', ar.modified_at uploaded_at'; - #push @$where_cond, 'e.id=ar.event_id'; - } - - $query .= "\n from"; - - # add tables - if ( ( $params->{project_id} ne '' ) || ( $params->{studio_id} ne '' ) ) { - # prepent series_events - $query .= "\n calcms_series_events se inner join calcms_events e on se.event_id=e.id"; - }else{ - $query .= "\n calcms_events e"; - } + # add recordings field and conditions + if ( $params->{recordings} eq '1' ) { + $query .= ', ar.path'; + $query .= ', ar.size'; + $query .= ', ar.created_by uploaded_by'; + $query .= ', ar.modified_at uploaded_at'; - # add recordings table - if ( $params->{recordings} eq '1' ) { - $query .= "\n left join calcms_audio_recordings ar on e.id=ar.event_id"; - } + #push @$where_cond, 'e.id=ar.event_id'; + } - if ( scalar @$where_cond > 0 ) { - $query .= "\nwhere " . join( ' and ', @$where_cond ); - } + $query .= "\n from"; - $query .= "\n" . $order_cond if ( $order_cond ne '' ); - $query .= "\n" . $limit_cond if ( $limit_cond ne '' ); + # add tables + if ( ( $params->{project_id} ne '' ) || ( $params->{studio_id} ne '' ) ) { - #print STDERR Dumper($query).Dumper($bind_values)."\n"; + # prepent series_events + $query .= "\n calcms_series_events se inner join calcms_events e on se.event_id=e.id"; + } else { + $query .= "\n calcms_events e"; + } - return ( \$query, $bind_values ); + # add recordings table + if ( $params->{recordings} ) { + my $type = $params->{only_recordings}//'' ? 'inner' : 'left'; + $query .= "\n $type join calcms_audio_recordings ar on e.id=ar.event_id and ar.active=1"; + } + + if ( scalar @$where_cond > 0 ) { + $query .= "\nwhere " . join( ' and ', @$where_cond ); + } + + $query .= "\n" . $order_cond if ( $order_cond ne '' ); + $query .= "\n" . $limit_cond if ( $limit_cond ne '' ); + + return ( \$query, $bind_values ); } -sub render { +sub render($$$$;$) { + my ($response, $config, $request, $results, $root_params) = @_; - # my $response = $_[0]; - my $config = $_[1]; - my $request = $_[2]; - my $results = $_[3]; - my $root_params = $_[4]; + my $params = $request->{params}->{checked}; + if ( ref($root_params) eq 'HASH' ) { + for my $param ( keys %$root_params ) { + $params->{$param} = $root_params->{$param}; + } + } + my %tparams = %$params; + my $tparams = \%tparams; + $tparams->{events} = $results; + $tparams->{server_cache} = $config->{cache}->{server_cache} + if ( $config->{cache}->{server_cache} ); + $tparams->{use_client_cache} = $config->{cache}->{use_client_cache} + if ( $config->{cache}->{use_client_cache} ); - my $params = $request->{params}->{checked}; - if ( ref($root_params) eq 'HASH' ) { - for my $param ( keys %$root_params ) { - $params->{$param} = $root_params->{$param}; - } - } - my $debug = $config->{system}->{debug}; + if ( scalar @$results > 0 ) { + my $result = $results->[0]; + $tparams->{event_id} = $result->{event_id}; + $tparams->{event_dtstart} = $result->{dtstart}; + $tparams->{first_date} = $results->[0]->{start_date}; + $tparams->{last_date} = $results->[-1]->{start_date}; + } - my %template_parameters = %$params; - my $template_parameters = \%template_parameters; - $template_parameters->{events} = $results; - $template_parameters->{debug} = $debug; - $template_parameters->{server_cache} = $config->{cache}->{server_cache} - if ( $config->{cache}->{server_cache} ); - $template_parameters->{use_client_cache} = $config->{cache}->{use_client_cache} - if ( $config->{cache}->{use_client_cache} ); + # $tparams->{print} =1 if ($params->{print} eq '1'); + $tparams->{base_url} = $config->{locations}->{base_url}; + $tparams->{base_domain} = $config->{locations}->{base_domain}; + $tparams->{local_base_url} = $config->{locations}->{local_base_url}; + $tparams->{cache_base_url} = $config->{cache}->{base_url}; + $tparams->{modified_at} = time::time_to_datetime( time() ); + if ( ( defined $params->{template} ) + && ( $params->{template} =~ /(\.xml)/ ) ) + { + $tparams->{modified_at_datetime_utc} = + time::datetime_to_utc_datetime( $tparams->{modified_at}, $config->{date}->{time_zone} ); + } - if ( scalar @$results > 0 ) { - my $result = $results->[0]; - $template_parameters->{event_id} = $result->{event_id}; - $template_parameters->{event_dtstart} = $result->{dtstart}; - } + #$tparams->{tags} = $tags; - # $template_parameters->{print} =1 if ($params->{print} eq '1'); - $template_parameters->{base_url} = $config->{locations}->{base_url}; - $template_parameters->{base_domain} = $config->{locations}->{base_domain}; - $template_parameters->{cache_base_url} = $config->{cache}->{base_url}; - $template_parameters->{modified_at} = time::time_to_datetime( time() ); - if ( ( defined $params->{template} ) - && ( $params->{template} =~ /(\.xml)/ ) ) - { - $template_parameters->{modified_at_datetime_utc} = - time::datetime_to_utc_datetime( $template_parameters->{modified_at}, $config->{date}->{time_zone} ); - } + if ( scalar @$results == 0 ) { + if ( ( $params->{search} ne '' ) + || ( $params->{series_name} ne '' ) ) + { + $tparams->{no_search_result} = '1'; + } else { + $tparams->{no_result} = '1'; + } + } else { + if ( ( !defined $params->{event_id} ) || ( $params->{event_id} eq '' ) ) { + $tparams->{event_count} = scalar @$results . ''; + $tparams->{first_of_list} = $results->[0]->{event_id}; + } + my $start = $results->[0]->{start_datetime} || ''; + if ( $start =~ /(\d{4}\-\d{2})/ ) { + $tparams->{month} = $1; + } + } - #$template_parameters->{tags} = $tags; + my $time_diff = time::utc_offset( $config->{date}->{time_zone} ); + $time_diff =~ s/(\d\d)(\d\d)/$1\:$2/g; + $tparams->{time_zone} = $config->{date}->{time_zone}; + $tparams->{utc_offset} = $time_diff; - if ( @$results == 0 ) { - if ( ( $params->{search} ne '' ) - || ( $params->{category} ne '' ) - || ( $params->{series_name} ne '' ) ) - { - $template_parameters->{no_search_result} = '1'; - } else { - $template_parameters->{no_result} = '1'; - } - } else { - if ( ( !defined $params->{event_id} ) || ( $params->{event_id} eq '' ) ) { - $template_parameters->{event_count} = @$results . ''; - $template_parameters->{first_of_list} = $results->[0]->{event_id}; - } - my $start = $results->[0]->{start_datetime} || ''; - if ( $start =~ /(\d{4}\-\d{2})/ ) { - $template_parameters->{month} = $1; - } - } + if ( $params->{template} =~ /\.atom\.xml/ ) { + $tparams->{modified_at} =~ s/ /T/gi; + $tparams->{modified_at} .= $time_diff; + } elsif ( $params->{template} =~ /\.rss\.xml/ ) { + $tparams->{modified_at} = + time::datetime_to_rfc822( $tparams->{modified_at} ); + } elsif ( $params->{template} =~ /\.txt/ ) { + $tparams->{modified_at_utc} = + time::datetime_to_utc( $tparams->{modified_at}, $config->{date}->{time_zone} ); + } - my $time_diff = time::utc_offset( $config->{date}->{time_zone} ); - $time_diff =~ s/(\d\d)(\d\d)/$1\:$2/g; - $template_parameters->{time_zone} = $config->{date}->{time_zone}; - $template_parameters->{utc_offset} = $time_diff; + my $project = $params->{default_project}; + foreach my $key ( keys %$project ) { + $tparams->{ 'project_' . $key } = $project->{$key}; + } + $tparams->{ 'project_' . $project->{name} } = 1 + if ( $project->{name} ne '' ); - if ( $params->{template} =~ /\.atom\.xml/ ) { - $template_parameters->{modified_at} =~ s/ /T/gi; - $template_parameters->{modified_at} .= $time_diff; - } elsif ( $params->{template} =~ /\.rss\.xml/ ) { - $template_parameters->{modified_at} = - time::datetime_to_rfc822( $template_parameters->{modified_at} ); - } elsif ( $params->{template} =~ /\.txt/ ) { - $template_parameters->{modified_at_utc} = - time::datetime_to_utc( $template_parameters->{modified_at}, $config->{date}->{time_zone} ); - } + $tparams->{controllers} = $config->{controllers}; + $tparams->{hide_event_images} = 1 + if ( defined $config->{permissions}->{hide_event_images} ) + && ( $config->{permissions}->{hide_event_images} == 1 ); - my $project = $params->{default_project}; - foreach my $key ( keys %$project ) { - $template_parameters->{ 'project_' . $key } = $project->{$key}; - } - $template_parameters->{ 'project_' . $project->{name} } = 1 - if ( $project->{name} ne '' ); + for my $attr (qw(no_result events_title events_description)){ + $tparams->{$attr} = $config->{$attr}; + } - $template_parameters->{controllers} = $config->{controllers}, + template::process( $config, $_[0], $params->{template}, $tparams ); - # use Data::Dumper;print STDERR Dumper($template_parameters)."\n"; - template::process( $_[0], $params->{template}, $template_parameters ); - - return $_[0]; + return $_[0]; } -sub get_running_event_id { - my $dbh = shift; +sub get_running_event_id($) { + my ($dbh) = @_; - my $query = qq{ + my $query = qq{ select id event_id, start, title from calcms_events where @@ -1217,95 +1307,99 @@ sub get_running_event_id { limit 1 }; - my $running_events = db::get( $dbh, $query ); - my @running_events = @$running_events; + my $running_events = db::get( $dbh, $query ); + my @running_events = @$running_events; - return $running_events->[0]->{event_id} if ( scalar @running_events > 0 ); - return 0; + return $running_events->[0]->{event_id} if ( scalar @running_events > 0 ); + return 0; } # add filters to query -sub setDefaultEventConditions { - my $config = shift; - my $conditions = $_[0]; - my $bind_values = $_[1]; +sub setDefaultEventConditions ($$$$) { + my ($config, $conditions, $bind_values, $options) = @_; - # exclude projects - if ( ( defined $config->{filter} ) - && ( defined $config->{filter}->{exclude_projects} ) ) - { - my @exclude_projects = - split( /,/, $config->{filter}->{exclude_projects} ); - push @$conditions, 'project not in (' . join( ",", map { '?' } @exclude_projects ) . ')'; - for my $project (@exclude_projects) { - push @$bind_values, $project; - } - } + $options = {} unless defined $options; - # exclude locations - if ( ( defined $config->{filter} ) - && ( defined $config->{filter}->{exclude_locations} ) ) - { - my @exclude_locations = - split( /,/, $config->{filter}->{exclude_locations} ); - push @$conditions, 'location not in (' . join( ",", map { '?' } @exclude_locations ) . ')'; - for my $location (@exclude_locations) { - push @$bind_values, $location; - } - } + # exclude projects + if ( ( defined $options->{exclude_projects} ) + && ( $options->{exclude_projects} == 1 ) + && ( defined $config->{filter} ) + && ( defined $config->{filter}->{projects_to_exclude} ) ) + { + my @projects_to_exclude = + split( /,/, $config->{filter}->{projects_to_exclude} ); + push @$conditions, 'project not in (' . join( ",", map { '?' } @projects_to_exclude ) . ')'; + for my $project (@projects_to_exclude) { + push @$bind_values, $project; + } + } + + # exclude locations + if ( ( defined $options->{exclude_locations} ) + && ( $options->{exclude_locations} == 1 ) + && ( defined $config->{filter} ) + && ( defined $config->{filter}->{locations_to_exclude} ) ) + { + my @locations_to_exclude = + split( /,/, $config->{filter}->{locations_to_exclude} ); + push @$conditions, 'location not in (' . join( ",", map { '?' } @locations_to_exclude ) . ')'; + for my $location (@locations_to_exclude) { + push @$bind_values, $location; + } + } } -sub getEventById { - my $dbh = shift; - my $config = shift; - my $event_id = shift; +# for local use only or add support for exclude_projects and exclude_locations +sub getEventById ($$$$) { + my ($dbh, $config, $event_id, $options) = @_; - $dbh = db::connect($config) unless defined $dbh; + $dbh = db::connect($config) unless defined $dbh; - my $conditions = []; - my $bind_values = []; + my $conditions = []; + my $bind_values = []; - push @$conditions, "id=?"; - push @$bind_values, $event_id; + push @$conditions, "id=?"; + push @$bind_values, $event_id; - setDefaultEventConditions( $config, $conditions, $bind_values ); - $conditions = join( ' and ', @$conditions ); + setDefaultEventConditions( $config, $conditions, $bind_values, $options ); + $conditions = join( ' and ', @$conditions ); - my $query = qq{ + my $query = qq{ select * from calcms_events where $conditions }; - my $events = db::get( $dbh, $query, $bind_values ); - return $events; + my $events = db::get( $dbh, $query, $bind_values ); + return $events; } -sub get_next_event_of_series { - my $dbh = shift; - my $config = shift; - my $event_id = shift; +sub get_next_event_of_series ($$$) { + my ($dbh, $config, $options) = @_; - $dbh = db::connect($config) unless defined $dbh; + my $eventId = $options->{event_id}; + return undef unless defined $eventId; - my $events = getEventById( $dbh, $config, $event_id ); - return undef unless @$events == 1; - my $event = $events->[0]; + $dbh = db::connect($config) unless defined $dbh; - my $conditions = []; - my $bind_values = []; + my $events = getEventById( $dbh, $config, $eventId, $options ); + return undef unless scalar(@$events) == 1; + my $event = $events->[0]; - push @$conditions, "start>?"; - push @$bind_values, $event->{start}; + my $conditions = []; + my $bind_values = []; - push @$conditions, "series_name=?"; - push @$bind_values, $event->{series_name}; + push @$conditions, "start>?"; + push @$bind_values, $event->{start}; - setDefaultEventConditions( $config, $conditions, $bind_values ); - $conditions = join( ' and ', @$conditions ); + push @$conditions, "series_name=?"; + push @$bind_values, $event->{series_name}; - my $query = qq{ + setDefaultEventConditions( $config, $conditions, $bind_values, $options ); + $conditions = join( ' and ', @$conditions ); + + my $query = qq{ select id from calcms_events where $conditions @@ -1313,476 +1407,441 @@ sub get_next_event_of_series { limit 1 }; - $events = db::get( $dbh, $query, $bind_values ); - return undef unless @$events == 1; + $events = db::get( $dbh, $query, $bind_values ); + return undef unless scalar @$events == 1; - return $events->[0]->{id}; + return $events->[0]->{id}; } -sub get_previous_event_of_series { - my $dbh = shift; - my $config = shift; - my $event_id = shift; +sub get_previous_event_of_series($$$) { + my ($dbh, $config, $options) = @_; - $dbh = db::connect($config) unless defined $dbh; + my $eventId = $options->{event_id}; + return undef unless defined $eventId; - my $events = getEventById( $dbh, $config, $event_id ); - return undef unless @$events == 1; - my $event = $events->[0]; + $dbh = db::connect($config) unless defined $dbh; + my $events = getEventById( $dbh, $config, $eventId, $options ); + return undef unless scalar(@$events) == 1; + my $event = $events->[0]; - my $conditions = []; - my $bind_values = []; + my $conditions = []; + my $bind_values = []; - push @$conditions, "start{start}; + push @$conditions, "start{start}; - push @$conditions, "series_name=?"; - push @$bind_values, $event->{series_name}; + push @$conditions, "series_name=?"; + push @$bind_values, $event->{series_name}; - setDefaultEventConditions( $config, $conditions, $bind_values ); - $conditions = join( ' and ', @$conditions ); + setDefaultEventConditions( $config, $conditions, $bind_values, $options ); + $conditions = join( ' and ', @$conditions ); - my $query = qq{ + my $query = qq{ select id from calcms_events where $conditions order by start desc limit 1 }; - $events = db::get( $dbh, $query, $bind_values ); + $events = db::get( $dbh, $query, $bind_values ); - return undef unless @$events == 1; - return $events->[0]->{id}; + return undef unless scalar(@$events) == 1; + return $events->[0]->{id}; } -sub get_by_date_range { - my $dbh = shift; - my $config = shift; - my $start_date = shift; - my $end_date = shift; +# used by calendar +sub get_by_date_range ($$$$$) { + my ($dbh, $config, $start_date, $end_date, $options) = @_; - my $conditions = []; - push @$conditions, 'start_date between ? and ?'; - my $bind_values = [ $start_date, $end_date ]; + my $day_starting_hour = $config->{date}->{day_starting_hour}; - setDefaultEventConditions( $config, $conditions, $bind_values ); + my $start = time::datetime_cond( $start_date . 'T00:00:00' ); + $start = time::add_hours_to_datetime( $start, $day_starting_hour ); - $conditions = join( ' and ', @$conditions ); + my $end = time::datetime_cond( $end_date . 'T00:00:00' ); + $end = time::add_hours_to_datetime( $end, $day_starting_hour ); - my $query = qq{ - select start_date + my $conditions = []; + push @$conditions, 'published = 1'; + push @$conditions, 'start between ? and ?'; + my $bind_values = [ $start, $end ]; + + setDefaultEventConditions( $config, $conditions, $bind_values, $options ); + + $conditions = join( ' and ', @$conditions ); + + my $select = qq{distinct date(start) 'start_date'}; + $select = qq{distinct date(DATE_SUB(start, INTERVAL $day_starting_hour HOUR)) 'start_date'} + if defined $day_starting_hour; + + my $query = qq{ + select $select from calcms_events where $conditions - group by start_date }; - my $events = db::get( $dbh, $query, $bind_values ); + my $events = db::get( $dbh, $query, $bind_values ); - return $events; + return $events; } -sub get_by_image { - my $dbh = shift; - my $config = shift; - my $filename = shift; +sub get_by_image ($$$) { + my ($dbh, $config, $filename) = @_; - #$filename=$dbh->quote('%'.$filename.'%'); - - #$filename='%'.$filename.'%'; - my $query = qq{ + my $query = qq{ select * from calcms_events where content like ? order by start desc limit 1 }; - my $bind_values = [ '%' . $filename . '%' ]; + my $bind_values = [ '%' . $filename . '%' ]; - my $events = db::get( $dbh, $query, $bind_values ); + my $events = db::get( $dbh, $query, $bind_values ); - # print STDERR Dumper($events); - return undef if ( @$events == 0 ); - return $events->[0]; + return undef if scalar @$events == 0; + return $events->[0]; } -sub delete { - return; - my $request = shift; - my $config = shift; - my $event_id = shift; +# deleting an event is currently disabled +sub delete ($$$) { + return; + my $request = shift; + my $config = shift; + my $event_id = shift; - my $params = $request->{params}->{checked}; - my $debug = $config->{system}->{debug}; + my $params = $request->{params}->{checked}; + my $dbh = db::connect($config); - my $dbh = db::connect($config); + my $query = 'delete from calcms_events where id=?'; + db::put( $dbh, $query, [$event_id] ); - my $query = 'delete from calcms_events where id=?'; - db::put( $dbh, $query, [$event_id] ); + $query = 'delete from calcms_categories where id=?'; + db::put( $dbh, $query, [$event_id] ); - $query = 'delete from calcms_categories where id=?'; - db::put( $dbh, $query, [$event_id] ); + $query = 'delete from calcms_tags where id=?'; + db::put( $dbh, $query, [$event_id] ); - $query = 'delete from calcms_tags where id=?'; - db::put( $dbh, $query, [$event_id] ); - - $query = 'delete from calcms_series_events where event_id=?'; - db::put( $dbh, $query, [$event_id] ); + $query = 'delete from calcms_series_events where event_id=?'; + db::put( $dbh, $query, [$event_id] ); } -#TODO: add location to cache map -sub configure_cache { - my $config = shift; - my $debug = $config->{system}->{debug}; +sub get_duration ($$) { + my ($config, $event) = @_; + + my $timezone = $config->{date}->{time_zone}; + my $start = time::get_datetime( $event->{start}, $timezone ); + my $end = time::get_datetime( $event->{end}, $timezone ); - my $date_pattern = $cache::date_pattern; - my $controllers = $config->{controllers}; + #my $seconds = $end->subtract($start)->in_units("minutes"); + #return $seconds; + return undef unless defined $start; + return undef unless defined $end; + my $duration = $end->epoch() - $start->epoch(); - cache::init(); - cache::add_map( '', 'index.html' ); - - my $name = ''; - my $extension = ''; - my $templates = $config->{templates}->{events}; - - for my $template (@$templates) { - if ( $template =~ /^(.+)\.([^\.]+)$/ ) { - $name = $1; - $extension = $2; - } - cache::add_map( 'template=' . $template, $controllers->{events} . '/' . $name . '.' . $extension ); - cache::add_map( 'template=' . $template . '&date=today', $controllers->{events} . '/' . $template . '_today.' . $extension ); - cache::add_map( 'template=' . $template . '&date=' . $date_pattern, - $controllers->{events} . '/' . $name . '_date_$1-$2-$3.' . $extension ); - cache::add_map( 'template=' . $template . '&time=now', $controllers->{events} . '/' . $template . '_now.html' ); - cache::add_map( 'template=' . $template . '&time=now&limit=(\d+)', - $controllers->{events} . '/' . $name . '_now_limit_$1.' . $extension ); - cache::add_map( - 'template=' . $template . '&from_date=' . $date_pattern . '&till_date=' . $date_pattern, - $controllers->{events} . '/' . $name . '_from_$1-$2-$3_till_$4_$5_$6.' . $extension - ); - cache::add_map( - 'template=' . $template . '&from_date=' . $date_pattern . '&till_date=' . $date_pattern . '&weekday=(\d)', - $controllers->{events} . '/' . $template . '_from_$1-$2-$3_till_$4_$5_$6_weekday_$7.' . $extension - ); - cache::add_map( - 'template=' . $template . '&from_date=' . $date_pattern . '&till_date=' . $date_pattern . '&limit=(\d)', - $controllers->{events} . '/' . $template . '_from_$1-$2-$3_till_$4_$5_$6_limit_$7.' . $extension - ); - cache::add_map( 'template=' . $template . '&weekday=(\d)', $controllers->{events} . '/' . $name . '_weekday_$1.' . $extension ); - cache::add_map( 'template=' . $template . '&event_id=(\d+)', $controllers->{event} . '/' . $name . '_page_$1.' . $extension ); - } + #print STDERR "duration=$duration, end=".$end->datetime()." start=".$start->datetime()."\n"; + return $duration / 60; } -sub get_duration { - my $config = shift; - my $event = shift; - my $timezone = $config->{date}->{time_zone}; - my $start = time::get_datetime( $event->{start}, $timezone ); - my $end = time::get_datetime( $event->{end}, $timezone ); - #my $seconds = $end->subtract($start)->in_units("minutes"); - #return $seconds; - return undef unless defined $start; - return undef unless defined $end; - my $duration = $end->epoch() - $start->epoch(); - #print STDERR "duration=$duration, end=".$end->datetime()." start=".$start->datetime()."\n"; - return $duration / 60; +sub check_params ($$) { + my ($config, $params) = @_; + + #define running at + my $running_at = $params->{running_at} || ''; + if ( ( defined $running_at ) && ( $running_at ne '' ) ) { + my $run_date = time::check_date($running_at); + my $run_time = time::check_time($running_at); + if ( ( $run_date ne '' ) && ( $run_time ne '' ) ) { + $params->{till_date} = $run_date; + $params->{till_time} = $run_time; + $params->{order} = 'asc'; + $params->{limit} = 1; + $params->{archive} = 'all'; + } + } + + #set time + my $time = time::check_time( $params->{time} ); + my $from_time = time::check_time( $params->{from_time} ); + my $till_time = time::check_time( $params->{till_time} ); + + #set date + my $date = ''; + my $from_date = time::check_date( $params->{from_date} ); + my $till_date = time::check_date( $params->{till_date} ); + if ( ( $from_date eq '' ) && ( $till_date eq '' ) ) { + $date = time::check_date( $params->{date} ); + } + + #set date interval (including) + my $date_range_include = 0; + $date_range_include = 1 + if ( defined $params->{date_range_include} ) + && ( $params->{date_range_include} eq '1' ); + + my $order = ''; + if ( defined $params->{order} ) { + $order = 'desc' if ( $params->{order} eq 'desc' ); + $order = 'asc' if ( $params->{order} eq 'asc' ); + } + + my $weekday = $params->{weekday} || ''; + + if ( ( defined $weekday ) && ( $weekday ne '' ) ) { + if ( $weekday =~ /\d/ ) { + $weekday = int($weekday); + log::error( $config, 'invalid weekday' ) + if ( $weekday < 1 || $weekday > 7 ); + } else { + log::error( $config, 'invalid weekday' ); + } + } + + my $tag = $params->{tag} || ''; + if ( ( defined $tag ) && ( $tag ne '' ) ) { + log::error( $config, "invalid tag" ) if ( $tag =~ /\s/ ); + log::error( $config, "invalid tag" ) if ( $tag =~ /\;/ ); + $tag =~ s/\'//gi; + } + + my $series_name = $params->{series_name} || ''; + if ( ( defined $series_name ) && ( $series_name ne '' ) ) { + log::error( $config, "invalid series_name" ) + if ( $series_name =~ /\;/ ); + $series_name =~ s/^\s+//gi; + $series_name =~ s/\s+$//gi; + $series_name =~ s/\'//gi; + } + + my $title = $params->{title} || ''; + if ( ( defined $title ) && ( $title ne '' ) ) { + log::error( $config, "invalid title" ) if ( $title =~ /\;/ ); + $title =~ s/^\s+//gi; + $title =~ s/\s+$//gi; + $title =~ s/\'//gi; + } + + my $location = $params->{location} || ''; + if ( ( defined $location ) && ( $location ne '' ) ) { + log::error( $config, "invalid location" ) if ( $location =~ /\;/ ); + $location =~ s/^\s+//gi; + $location =~ s/\s+$//gi; + $location =~ s/\'//gi; + } + + #if no location is set, use exclude location filter from default config + my $locations_to_exclude = ''; + if ( ( $location eq '' ) + && ( defined $config->{filter} ) + && ( defined $config->{filter}->{locations_to_exclude} ) ) + { + $locations_to_exclude = $config->{filter}->{locations_to_exclude} || ''; + $locations_to_exclude =~ s/\s+/ /g; + } + + my $projects_to_exclude = ''; + if ( ( defined $config->{filter} ) + && ( defined $config->{filter}->{projects_to_exclude} ) ) + { + $projects_to_exclude = $config->{filter}->{projects_to_exclude} || ''; + $projects_to_exclude =~ s/\s+/ /g; + } + + #enable exclude locations filter + my $exclude_locations = 0; + $exclude_locations = 1 if ( defined $params->{exclude_locations} ) && ( $params->{exclude_locations} eq '1' ); + + my $exclude_projects = 0; + $exclude_projects = 1 if ( defined $params->{exclude_projects} ) && ( $params->{exclude_projects} eq '1' ); + + my $exclude_event_images = 0; + $exclude_event_images = 1 + if ( defined $params->{exclude_event_images} ) && ( $params->{exclude_event_images} eq '1' ); + + #show future events by default + my $archive = 'future'; + if ( defined $params->{archive} ) { + $archive = 'all' if ( $params->{archive} eq 'all' ); + $archive = 'past' if ( $params->{archive} eq 'gone' ); + $archive = 'future' if ( $params->{archive} eq 'coming' ); + } + + my $last_days = defined $params->{last_days} ? int($params->{last_days}) : 0; + + my $disable_event_sync = ''; + if ( ( defined $params->{disable_event_sync} ) + && ( $params->{disable_event_sync} =~ /([01])/ ) ) + { + $disable_event_sync = $1; + } + + #show all on defined timespans + if ( ( $from_date ne '' ) && ( $till_date ne '' ) ) { + $archive = 'all'; + } + + my $event_id = $params->{event_id} || ''; + if ( ( defined $event_id ) && ( $event_id ne '' ) ) { + if ( $event_id =~ /(\d+)/ ) { + $event_id = $1; + } else { + log::error( $config, "invalid event_id" ); + } + } + + my $get = 'all'; + $get = 'no_content' + if ( defined $params->{get} ) && ( $params->{get} eq 'no_content' ); + + my $search = $params->{search} || ''; + if ( ( defined $search ) && ( $search ne '' ) ) { + $search = substr( $search, 0, 100 ); + $search =~ s/^\s+//gi; + $search =~ s/\s+$//gi; + } + + #print STDERR $params->{template}."\n"; + my $template = '.html'; + if ( ($params->{template}//'') eq 'no' ) { + $template = 'no'; + } elsif ( ($params->{template}//'') eq 'html' ) { + $template = 'html'; + } else { + $template = template::check( $config, $params->{template}, 'event_list.html' ); + } + + my $limit_config = $config->{permissions}->{result_limit} || 100; + my $limit = $params->{limit} || $limit_config; + log::error( $config, 'invalid limit!' ) if ( $limit =~ /\D/ ); + $limit = $limit_config if ( $limit_config < $limit ); + + #read project from configuration file + my $project_name = $config->{project} || ''; + log::error( $config, 'no default project configured' ) + if ( $project_name eq '' ); + + #get default project + my $default_project = undef; + my $projects = project::get( $config, { name => $project_name } ); + log::error( $config, "no configuration found for project '$project_name'" ) + unless ( scalar(@$projects) == 1 ); + $default_project = $projects->[0]; + + # get project from parameter (by name) + my $project = ''; + if ( ( defined $params->{project} ) + && ( $params->{project} =~ /\w+/ ) + && ( $params->{project} ne 'all' ) ) + { + my $project_name = $params->{project}; + my $projects = project::get( $config, { name => $project_name } ); + log::error( $config, 'invalid project ' . $project_name ) + unless scalar(@$projects) == 1; + $project = $projects->[0]; + } + + $project_name = $params->{project_name} || ''; + my $studio_name = $params->{studio_name} || ''; + + my $project_id = $params->{project_id} || ''; + my $studio_id = $params->{studio_id} || ''; + + my $json_callback = $params->{json_callback} || ''; + if ( $json_callback ne '' ) { + $json_callback =~ s/[^a-zA-Z0-9\_]//g; + } + + # use relative links + my $extern = 0; + $extern = 1 if ( defined $params->{extern} ) && ( $params->{extern} eq '1' ); + + my $only_recordings = $params->{only_recordings} // ''; + my $recordings = 0; + $recordings = 1 if $params->{recordings}//''; + $recordings = 1 if $only_recordings; + my $set_no_listen_keys = !$recordings ; + + my $checked = { + date => $date, + time => $time, + from_date => $from_date, + till_date => $till_date, + date_range_include => $date_range_include, + from_time => $from_time, + till_time => $till_time, + weekday => $weekday, + limit => $limit, + template => $template, + location => $location, + series_name => $series_name, + tag => $tag, + title => $title, + event_id => $event_id, + search => $search, + archive => $archive, + last_days => $last_days, + order => $order, + project => $project, + default_project => $default_project, + project_name => $project_name, + project_id => $project_id, + studio_name => $studio_name, + studio_id => $studio_id, + json_callback => $json_callback, + get => $get, + locations_to_exclude => $locations_to_exclude, + projects_to_exclude => $projects_to_exclude, + exclude_locations => $exclude_locations, + exclude_projects => $exclude_projects, + exclude_event_images => $exclude_event_images, + disable_event_sync => $disable_event_sync, + extern => $extern, + recordings => $recordings, + only_recordings => $only_recordings, + set_no_listen_keys => $set_no_listen_keys, + ro => ($params->{ro}//'') ? 1 : 0 + }; + return $checked; } -sub check_params { - my $config = shift; - my $params = shift; - - #define running at - my $running_at = $params->{running_at} || ''; - if ( ( defined $running_at ) && ( $running_at ne '' ) ) { - my $run_date = time::check_date($running_at); - my $run_time = time::check_time($running_at); - if ( ( $run_date ne '' ) && ( $run_time ne '' ) ) { - $params->{till_date} = $run_date; - $params->{till_time} = $run_time; - $params->{order} = 'asc'; - $params->{limit} = 1; - $params->{archive} = 'all'; - } - } - - #set time - my $time = time::check_time( $params->{time} ); - my $from_time = time::check_time( $params->{from_time} ); - my $till_time = time::check_time( $params->{till_time} ); - - #set date - my $date = ''; - my $from_date = time::check_date( $params->{from_date} ); - my $till_date = time::check_date( $params->{till_date} ); - if ( ( $from_date eq '' ) && ( $till_date eq '' ) ) { - $date = time::check_date( $params->{date} ); - } - - #set date interval (including) - my $date_range_include = 0; - $date_range_include = 1 - if ( defined $params->{date_range_include} ) - && ( $params->{date_range_include} eq '1' ); - - my $order = ''; - if ( defined $params->{order} ) { - $order = 'desc' if ( $params->{order} eq 'desc' ); - $order = 'asc' if ( $params->{order} eq 'asc' ); - } - - my $weekday = $params->{weekday} || ''; - - if ( ( defined $weekday ) && ( $weekday ne '' ) ) { - if ( $weekday =~ /\d/ ) { - $weekday = int($weekday); - log::error( $config, 'invalid weekday' ) - if ( $weekday < 1 || $weekday > 7 ); - } else { - log::error( $config, 'invalid weekday' ); - } - } - - my $tag = $params->{tag} || ''; - if ( ( defined $tag ) && ( $tag ne '' ) ) { - log::error( $config, "invalid tag" ) if ( $tag =~ /\s/ ); - log::error( $config, "invalid tag" ) if ( $tag =~ /\;/ ); - $tag =~ s/\'//gi; - } - - my $category = $params->{category} || ''; - if ( ( defined $category ) && ( $category ne '' ) ) { - log::error( $config, "invalid category" ) if ( $category =~ /\;/ ); - $category =~ s/^\s+//gi; - $category =~ s/\s+$//gi; - $category =~ s/\'//gi; - } - - my $series_name = $params->{series_name} || ''; - if ( ( defined $series_name ) && ( $series_name ne '' ) ) { - log::error( $config, "invalid series_name" ) - if ( $series_name =~ /\;/ ); - $series_name =~ s/^\s+//gi; - $series_name =~ s/\s+$//gi; - $series_name =~ s/\'//gi; - } - - my $title = $params->{title} || ''; - if ( ( defined $title ) && ( $title ne '' ) ) { - log::error( $config, "invalid title" ) if ( $title =~ /\;/ ); - $title =~ s/^\s+//gi; - $title =~ s/\s+$//gi; - $title =~ s/\'//gi; - } - - my $location = $params->{location} || ''; - if ( ( defined $location ) && ( $location ne '' ) ) { - log::error( $config, "invalid location" ) if ( $location =~ /\;/ ); - $location =~ s/^\s+//gi; - $location =~ s/\s+$//gi; - $location =~ s/\'//gi; - } - - #if no location is set, use exclude location filter from default config - my $exclude_locations = ''; - if ( ( $location eq '' ) - && ( defined $config->{filter} ) - && ( defined $config->{filter}->{exclude_locations} ) ) - { - $exclude_locations = $config->{filter}->{exclude_locations} || ''; - $exclude_locations =~ s/\s+/ /g; - } - - my $exclude_projects = ''; - if ( ( defined $config->{filter} ) - && ( defined $config->{filter}->{exclude_projects} ) ) - { - $exclude_projects = $config->{filter}->{exclude_projects} || ''; - $exclude_projects =~ s/\s+/ /g; - } - - #disable exclude filter by 'no_exlude=1' - my $no_exclude = ''; - $no_exclude = '1' - if ( ( defined $params->{no_exclude} ) - && ( $params->{no_exclude} eq '1' ) ); - - #show future events by default - my $archive = 'future'; - if ( defined $params->{archive} ) { - $archive = 'all' if ( $params->{archive} eq 'all' ); - $archive = 'past' if ( $params->{archive} eq 'gone' ); - $archive = 'future' if ( $params->{archive} eq 'coming' ); - } - - my $disable_event_sync = ''; - if ( ( defined $params->{disable_event_sync} ) - && ( $params->{disable_event_sync} =~ /([01])/ ) ) - { - $disable_event_sync = $1; - } - - #show all on defined timespans - if ( ( $from_date ne '' ) && ( $till_date ne '' ) ) { - $archive = 'all'; - } - - my $event_id = $params->{event_id} || ''; - if ( ( defined $event_id ) && ( $event_id ne '' ) ) { - if ( $event_id =~ /(\d+)/ ) { - $event_id = $1; - } else { - log::error( $config, "invalid event_id" ); - } - } - - my $get = 'all'; - $get = 'no_content' - if ( ( defined $params->{get} ) && ( $params->{get} eq 'no_content' ) ); - - my $search = $params->{search} || ''; - if ( ( defined $search ) && ( $search ne '' ) ) { - $search = substr( $search, 0, 100 ); - $search =~ s/^\s+//gi; - $search =~ s/\s+$//gi; - } - - #print STDERR $params->{template}."\n"; - my $template = '.html'; - if ( $params->{template} eq 'no' ) { - $template = 'no'; - } else { - $template = template::check( $params->{template}, 'event_list.html' ); - } - - my $limit_config = $config->{permissions}->{result_limit} || 100; - my $limit = $params->{limit} || $limit_config; - log::error( $config, 'invalid limit!' ) if ( $limit =~ /\D/ ); - $limit = $limit_config if ( $limit_config < $limit ); - - #read project from configuration file - my $project_name = $config->{project} || ''; - log::error( $config, 'no default project configured' ) - if ( $project_name eq '' ); - - #get default project - my $default_project = undef; - my $projects = project::get( $config, { name => $project_name } ); - log::error( $config, "no configuration found for project '$project_name'" ) - unless ( @$projects == 1 ); - $default_project = $projects->[0]; - - # get project from parameter (by name) - my $project = ''; - if ( ( defined $params->{project} ) - && ( $params->{project} =~ /\w+/ ) - && ( $params->{project} ne 'all' ) ) - { - my $project_name = $params->{project}; - my $projects = project::get( $config, { name => $project_name } ); - log::error( $config, 'invalid project ' . $project_name ) - unless @$projects == 1; - $project = $projects->[0]; - } - - $project_name = $params->{project_name} || ''; - my $studio_name = $params->{studio_name} || ''; - - my $project_id = $params->{project_id} || ''; - my $studio_id = $params->{studio_id} || ''; - - my $debug = $params->{debug} || ''; - if ( $debug =~ /([a-z\_\,]+)/ ) { - $debug = $1; - } - - my $json_callback = $params->{json_callback} || ''; - if ( $json_callback ne '' ) { - $json_callback =~ s/[^a-zA-Z0-9\_]//g; - } - - # use relative links - my $extern = 0; - $extern = 1 if ( defined $params->{extern} ) && ( $params->{extern} eq '1' ); - - my $recordings = 0; - $recordings = 1 if ( defined $params->{recordings} ) && ( $params->{recordings} eq '1' ); - - my $checked = { - date => $date, - time => $time, - from_date => $from_date, - till_date => $till_date, - date_range_include => $date_range_include, - from_time => $from_time, - till_time => $till_time, - weekday => $weekday, - limit => $limit, - template => $template, - location => $location, - category => $category, - series_name => $series_name, - tag => $tag, - title => $title, - event_id => $event_id, - search => $search, - debug => $debug, - archive => $archive, - order => $order, - project => $project, - default_project => $default_project, - project_name => $project_name, - project_id => $project_id, - studio_name => $studio_name, - studio_id => $studio_id, - json_callback => $json_callback, - get => $get, - exclude_locations => $exclude_locations, - exclude_projects => $exclude_projects, - no_exclude => $no_exclude, - disable_event_sync => $disable_event_sync, - extern => $extern, - recordings => $recordings, - }; - - #print STDERR Dumper($checked); - return $checked; +sub l($){ + my ($word) = @_; + return length $word ? $word : (); } -sub get_keys { - my $event = shift; +sub get_keys($) { + my ($event) = @_; - my $program = $event->{program} || ''; - my $series_name = $event->{series_name} || ''; - my $title = $event->{title} || ''; - my $user_title = $event->{user_title} || ''; - my $episode = $event->{episode} || ''; - my $recurrence_count_alpha = $event->{recurrence_count_alpha} || ''; + #my $program = $event->{program} || ''; + my $series_name = $event->{series_name} || ''; + my $title = $event->{title} || ''; + my $user_title = $event->{user_title} || ''; + my $episode = $event->{episode} || ''; + my $recurrence_count_alpha = $event->{recurrence_count_alpha} || ''; - my $skey = ''; - $skey .= $series_name if $series_name ne ''; - $skey .= ' - ' - if ( $series_name ne '' ) - && ( ( $title ne '' ) || ( $user_title ne '' ) ); + # ": <user-title>" + my $tkey = join (': ', (l($title), l($user_title))); - my $tkey = ''; - $tkey = $title if $title ne ''; - $tkey .= ': ' if ( $title ne '' ) && ( $user_title ne '' ); - $tkey .= $user_title if $user_title ne ''; - $tkey .= ' #' . $episode if $episode ne ''; - $tkey .= $recurrence_count_alpha if $recurrence_count_alpha ne ''; + # episode "#123c" + my $ekey = join '', ( + (length $episode) ? '#'.$episode : '', + $recurrence_count_alpha + ); - my $pkey = ''; - $pkey = ' (' . $program . ')' if $program ne ''; + # "<title> <episode>" + my $te = join " ", (l($tkey), l($ekey)); - return { - key => $skey . $tkey . $pkey, - full_title => $skey . $tkey . $pkey, - full_title_no_series => $tkey . $pkey, - full_title_no_program => $skey . $tkey, - full_title_no_program_no_series => $tkey - }; + # separation between <series> and <title> + my $stkey = ( length($series_name) and length($te) ) ? ' - ' : ''; + + return { + skey => $series_name, + stkey => $stkey, + tkey => $tkey, + ekey => $ekey, + full_title => $series_name . $stkey . $te, + full_title_no_series => $te, + }; } #do not delete last line! 1; - diff --git a/lib/calcms/images.pm b/lib/calcms/images.pm index c0f8900..cf7db0c 100644 --- a/lib/calcms/images.pm +++ b/lib/calcms/images.pm @@ -1,297 +1,526 @@ -use warnings "all"; -use strict; -use config; -use template; +package images; -package images; -use warnings "all"; use strict; +use warnings; +no warnings 'redefine'; + +use config(); +use template(); use Data::Dumper; -require Exporter; -our @ISA = qw(Exporter); -#our @EXPORT = qw(all); +#use base 'Exporter'; our @EXPORT_OK = qw(get insert update insert_or_update delete delete_files); -our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ] ); #column 'created_at' will be set at insert #column 'modified_at' will be set by default (do not update) -my $sql_columns =['filename', 'name', 'description', 'created_by', 'modified_by', 'modified_at', 'studio_id', 'project_id']; +my $sql_columns = [ + 'filename', 'name', 'description', 'created_by', 'modified_by', 'modified_at', + 'studio_id', 'project_id', 'public', 'licence' +]; -sub get{ - my $config=shift; - my $options=shift; +sub get($$) { + my $config = shift; + my $options = shift; - my @cond=(); - my $bind_values=[]; - if ((defined $options->{project_id}) && ($options->{project_id}ne'')){ - push @cond, 'project_id = ?'; - push @$bind_values, $options->{project_id}; - } - if ((defined $options->{studio_id}) && ($options->{studio_id}ne'')){ - push @cond, 'studio_id = ?'; - push @$bind_values, $options->{studio_id}; - } - if ((defined $options->{filename}) && ($options->{filename}ne'')){ - push @cond, 'filename = ?'; - push @$bind_values,$options->{filename}; - } - if ((defined $options->{from}) && ($options->{from}ne'')){ - push @cond, 'date(created_at) >= ?'; - push @$bind_values,$options->{from}; - } - if ((defined $options->{till}) && ($options->{till}ne'')){ - push @cond, 'date(created_at) <= ?'; - push @$bind_values,$options->{till}; - } - if ((defined $options->{created_by}) && ($options->{created_by}ne'')){ - push @cond, 'created_by = ?'; - push @$bind_values,$options->{created_by}; - } - if ((defined $options->{modified_by}) && ($options->{modified_by}ne'')){ - push @cond, 'modified_by = ?'; - push @$bind_values,$options->{modified_by}; - } - if ((defined $options->{search}) && ($options->{search}ne'')){ - push @cond, '(filename like ?' - .' or name like ?' - .' or description like ?' - .' or created_by like ?' - .')'; - my $search='%'.$options->{search}.'%'; - push @$bind_values,$search; - push @$bind_values,$search; - push @$bind_values,$search; - push @$bind_values,$search; -# push @$bind_values,$search; - } + my @cond = (); + my $bind_values = []; + if ( ( defined $options->{project_id} ) && ( $options->{project_id} ne '' ) ) { + push @cond, 'project_id = ?'; + push @$bind_values, $options->{project_id}; + } + if ( ( defined $options->{studio_id} ) && ( $options->{studio_id} ne '' ) ) { + push @cond, 'studio_id = ?'; + push @$bind_values, $options->{studio_id}; + } + if ( ( defined $options->{filename} ) && ( $options->{filename} ne '' ) ) { + push @cond, 'filename = ?'; + push @$bind_values, $options->{filename}; + } + if ( ( defined $options->{from} ) && ( $options->{from} ne '' ) ) { + push @cond, 'date(created_at) >= ?'; + push @$bind_values, $options->{from}; + } + if ( ( defined $options->{till} ) && ( $options->{till} ne '' ) ) { + push @cond, 'date(created_at) <= ?'; + push @$bind_values, $options->{till}; + } + if ( ( defined $options->{created_by} ) && ( $options->{created_by} ne '' ) ) { + push @cond, 'created_by = ?'; + push @$bind_values, $options->{created_by}; + } + if ( ( defined $options->{modified_by} ) && ( $options->{modified_by} ne '' ) ) { + push @cond, 'modified_by = ?'; + push @$bind_values, $options->{modified_by}; + } + if ( ( defined $options->{licence} ) && ( $options->{licence} ne '' ) ) { + push @cond, 'licence = ?'; + push @$bind_values, $options->{licence}; + } + if ( ( defined $options->{public} ) && ( $options->{public} ne '' ) ) { + push @cond, 'public = ?'; + push @$bind_values, $options->{public}; + } - my $where=''; - if (@cond>0){ - $where = 'where '.join (' and ', @cond); - } + if ( ( defined $options->{search} ) && ( $options->{search} ne '' ) ) { + push @cond, + '(filename like ?' . ' or name like ?' . ' or description like ?' . ' or created_by like ?' . ')'; + my $search = '%' . $options->{search} . '%'; + push @$bind_values, $search; + push @$bind_values, $search; + push @$bind_values, $search; + push @$bind_values, $search; - my $limit=''; - if ( (defined $options->{limit}) && ($options->{limit}=~/(\d+)/) ){ - $limit=' limit '.$1; - } + # push @$bind_values,$search; + } - my $query=qq{ + my $where = ''; + if ( @cond > 0 ) { + $where = 'where ' . join( ' and ', @cond ); + } + + my $limit = ''; + if ( ( defined $options->{limit} ) && ( $options->{limit} =~ /(\d+)/ ) ) { + $limit = ' limit ' . $1; + } + + my $query = qq{ select * from calcms_images $where order by created_at desc $limit }; - #print STDERR Dumper($query).Dumper($bind_values); - my $dbh=db::connect($config); - my $results=db::get($dbh, $query, $bind_values); + my $dbh = db::connect($config); + my $results = db::get( $dbh, $query, $bind_values ); #print STDERR @$results."\n"; - return $results; + return $results; } -sub insert_or_update{ - my $dbh=shift; - my $image=shift; +sub insert_or_update($$) { + my $dbh = shift; + my $image = shift; - $image->{name}='new' if ($image->{name}eq''); - my $entry=get_by_filename($dbh, $image->{filename}); - if (defined $entry){ - update($dbh, $image); - }else{ - insert($dbh, $image); - } + $image->{name} = 'new' if $image->{name} eq ''; + my $entry = get_by_filename( $dbh, $image->{filename} ); + if ( defined $entry ) { + update( $dbh, $image ); + } else { + insert( $dbh, $image ); + } } -sub insert{ - my $dbh=shift; - my $image=shift; +sub insert ($$) { + my $dbh = shift; + my $image = shift; - my @sql_columns=@$sql_columns; + my @sql_columns = @$sql_columns; #set created at timestamp - push @sql_columns,'created_at'; - $image->{created_at}=time::time_to_datetime(); + push @sql_columns, 'created_at'; + $image->{created_at} = time::time_to_datetime(); - unless (defined $image->{created_by}){ + unless ( defined $image->{created_by} ) { print STDERR "missing created_by at image::insert\n"; return undef; } - unless (defined $image->{studio_id}){ + unless ( defined $image->{studio_id} ) { print STDERR "missing studio_id at image::insert\n"; return undef; } - unless (defined $image->{project_id}){ + unless ( defined $image->{project_id} ) { print STDERR "missing project_id at image::insert\n"; return undef; } - - my $query=q{ - insert into calcms_images( - }.join(',',@sql_columns).qq{ - ) - values( }.join(', ', (map {'?'} @sql_columns)).q{ ) - }; - my @bind_values=map { $image->{$_} } @sql_columns; - #print STDERR Dumper($query).Dumper(\@bind_values); - return db::put($dbh, $query, \@bind_values); + for my $attr ('public') { + $image->{$attr} = 0 unless ( defined $image->{$attr} ) && ( $image->{$attr} eq '1' ); + } + + my $query = q{ + insert into calcms_images( + } . join( ',', @sql_columns ) . qq{ + ) + values( } . join( ', ', ( map { '?' } @sql_columns ) ) . q{ ) + }; + my @bind_values = map { $image->{$_} } @sql_columns; + my $result = db::put( $dbh, $query, \@bind_values ); + + images::setSeriesLabels( $dbh, $image ); + images::setEventLabels( $dbh, $image ); + + return $result; } +sub update($$) { + my $dbh = shift; + my $image = shift; -sub update{ - my $dbh=shift; - my $image=shift; - - unless (defined $image->{studio_id}){ + unless ( defined $image->{studio_id} ) { print STDERR "missing studio_id at images::update\n"; return undef; } - unless (defined $image->{project_id}){ + unless ( defined $image->{project_id} ) { print STDERR "missing project_id at image::update\n"; return undef; } + unless ( defined $image->{filename} ) { + print STDERR "missing filename at image::update\n"; + return undef; + } - $image->{modified_at}=time::time_to_datetime(); + $image->{modified_at} = time::time_to_datetime(); - my @set=(); - my $bind_values=[]; - for my $column (@$sql_columns){ - if (defined $image->{$column}){ - push @set, $column.' = ?'; - push @$bind_values,$image->{$column}; - } - } + for my $attr ('public') { + $image->{$attr} = 0 unless ( defined $image->{$attr} ) && ( $image->{$attr} eq '1' ); + } + + my @set = (); + my $bind_values = []; + for my $column (@$sql_columns) { + if ( defined $image->{$column} ) { + push @set, $column . ' = ?'; + push @$bind_values, $image->{$column}; + } + } #conditions - my $conditions=['filename=?']; - push @$bind_values,$image->{filename}; + my $conditions = ['filename=?']; + push @$bind_values, $image->{filename}; - push @$conditions, 'project_id=?'; - push @$bind_values, $image->{project_id}||0; + push @$conditions, 'project_id=?'; + push @$bind_values, $image->{project_id} || 0; - push @$conditions, 'studio_id=?'; - push @$bind_values, $image->{studio_id}||0; + push @$conditions, 'studio_id=?'; + push @$bind_values, $image->{studio_id} || 0; - return if (@set==0); - - my $set=join (",",@set); - $conditions=join(' and ', @$conditions); - my $query=qq{ + return if ( @set == 0 ); + + my $set = join( ",", @set ); + $conditions = join( ' and ', @$conditions ); + my $query = qq{ update calcms_images set $set where $conditions }; - #print STDERR Dumper($query).Dumper($bind_values); - return db::put($dbh,$query,$bind_values); + my $result = db::put( $dbh, $query, $bind_values ); + + images::setSeriesLabels( $dbh, $image ); + images::setEventLabels( $dbh, $image ); + + return $result; } -sub delete{ - my $dbh=shift; - my $image=shift; +sub delete($$) { + my $dbh = shift; + my $image = shift; - unless (defined $image->{project_id}){ + unless ( defined $image->{project_id} ) { print STDERR "missing project_id at images::delete\n"; return undef; } - unless (defined $image->{project_id}){ - print STDERR "missing project_id at images::delete\n"; + unless ( defined $image->{studio_id} ) { + print STDERR "missing studio_id at images::delete\n"; return undef; } - unless (defined $image->{filename}){ + unless ( defined $image->{filename} ) { print STDERR "missing filename at images::delete\n"; return undef; } - + my $project_id = $image->{project_id}; - my $studio_id = $image->{studio_id}; - my $filename = $image->{filename}; + my $studio_id = $image->{studio_id}; + my $filename = $image->{filename}; my $conditions = ['filename=?']; - my $bind_values = [$filename]; - - push @$conditions, 'project_id=?'; + my $bind_values = [$filename]; + + push @$conditions, 'project_id=?'; push @$bind_values, $studio_id; - push @$conditions, 'studio_id=?'; + push @$conditions, 'studio_id=?'; push @$bind_values, $project_id; - $conditions=join(' and ', @$conditions); - my $query=qq{ + $conditions = join( ' and ', @$conditions ); + my $query = qq{ delete from calcms_images where $conditions }; - #print STDERR Dumper($query).Dumper($bind_values); - return db::put($dbh, $query, $bind_values); + return db::put( $dbh, $query, $bind_values ); } # deactivated -sub delete_files{ +sub delete_files($$$$$) { my $config = $_[0]; - my $local_media_dir = $_[1]; - my $filename = $_[2]; - my $action_result = $_[3]; - my $errors = $_[4]; + my $local_media_dir = $_[1]; + my $filename = $_[2]; + my $action_result = $_[3]; + my $errors = $_[4]; return undef; - - print log::error($config, 'missing permissions on writing into local media dir')unless(-w $local_media_dir); - if ($filename=~/[^a-zA-Z0-9\.\_\-]/){ - log::error($config, "invalid filename: '$filename'"); - return; - } - if ($filename=~/\.\./ || $filename=~/^\// || $filename=~/\//){ - log::error($config, "invalid filename: '$filename'"); - return; - } + print log::error( $config, 'missing permissions on writing into local media dir' ) unless ( -w $local_media_dir ); - log::error($config, 'missing permissions on writing into local_media_dir/images/')unless(-w $local_media_dir.'images/'); - log::error($config, 'missing permissions on writing into local_media_dir/thumbs/')unless(-w $local_media_dir.'thumbs/'); - log::error($config, 'missing permissions on writing into local_media_dir/icons/') unless(-w $local_media_dir.'icons/'); + if ( $filename =~ /[^a-zA-Z0-9\.\_\-]/ ) { + log::error( $config, "invalid filename: '$filename'" ); + return; + } + if ( $filename =~ /\.\./ || $filename =~ /^\// || $filename =~ /\// ) { + log::error( $config, "invalid filename: '$filename'" ); + return; + } - my $path=$local_media_dir.'/upload/'.$filename; - #delete_file($path,"Upload $filename",$action_result,$errors); + log::error( $config, 'missing permissions on writing into local_media_dir/images/' ) + unless ( -w $local_media_dir . 'images/' ); + log::error( $config, 'missing permissions on writing into local_media_dir/thumbs/' ) + unless ( -w $local_media_dir . 'thumbs/' ); + log::error( $config, 'missing permissions on writing into local_media_dir/icons/' ) + unless ( -w $local_media_dir . 'icons/' ); - $path=$local_media_dir.'/images/'.$filename; - delete_file($path,"Image $filename",$action_result,$errors); + my $path = $local_media_dir . '/upload/' . $filename; - $path=$local_media_dir.'/thumbs/'.$filename; - delete_file($path,"Thumb $filename",$action_result,$errors); + #delete_file($path,"Upload $filename",$action_result,$errors); - $path=$local_media_dir.'/icons/'.$filename; - delete_file($path,"Icon $filename",$action_result,$errors); + $path = $local_media_dir . '/images/' . $filename; + delete_file( $path, "Image $filename", $action_result, $errors ); + + $path = $local_media_dir . '/thumbs/' . $filename; + delete_file( $path, "Thumb $filename", $action_result, $errors ); + + $path = $local_media_dir . '/icons/' . $filename; + delete_file( $path, "Icon $filename", $action_result, $errors ); } # deactivated -sub delete_file{ - my $path = $_[0]; - my $type = $_[1]; - my $action_result = $_[2]; - my $errors = $_[3]; +sub delete_file ($$$$) { + my $path = $_[0]; + my $type = $_[1]; + my $action_result = $_[2]; + my $errors = $_[3]; return undef; - unless (-e $path){ - $errors.= qq{Error: File does not exist!<br>}; - return; - } + unless ( -e $path ) { + $errors .= qq{Error: File does not exist!<br>}; + return; + } - unless (-w $path){ - $errors.= qq{Error: Cannot write $type<br>}; - return; - } + unless ( -w $path ) { + $errors .= qq{Error: Cannot write $type<br>}; + return; + } - unlink($path); - if ($?==0){ - $action_result.= qq{$type deleted<br>}; - }else{ - $errors.= qq{Error on deleting $type<br>}; - } + unlink($path); + if ( $? == 0 ) { + $action_result .= qq{$type deleted<br>}; + } else { + $errors .= qq{Error on deleting $type<br>}; + } } +sub getPath { + my $config = shift; + my $options = shift; + + my $dir = $config->{locations}->{local_media_dir}; + return undef unless defined $dir; + return undef unless -e $dir; + + my $filename = $options->{filename}; + return undef unless defined $filename; + $filename =~ s/^.*\///g; + + my $type = 'thumbs'; + $type = $options->{type} if ( defined $options->{type} ) && ( $options->{type} =~ /^(images|thumbs|icons)$/ ); + + my $path = $dir . '/' . $type . '/' . $filename; + $path =~ s/\/+/\//g; + return $path; +} + +sub getInternalPath ($$) { + my $config = shift; + my $options = shift; + + my $dir = $config->{locations}->{local_media_dir}; + return undef unless defined $dir; + return undef unless -e $dir; + + my $filename = $options->{filename}; + return undef unless defined $filename; + $filename =~ s/^.*\///g; + + my $type = 'thumbs'; + $type = $options->{type} if ( defined $options->{type} ) && ( $options->{type} =~ /^(images|thumbs|icons)$/ ); + + my $path = $dir . '/internal/' . $type . '/' . $filename; + $path =~ s/\/+/\//g; + return $path; +} + +sub normalizeName (;$) { + my $name = shift; + return undef unless defined $name; + $name =~ s/.*\///g; + return $name; +} + +sub readFile($) { + my $path = shift; + my $content = ''; + + print STDERR "read '$path'\n"; + return { error => "source '$path' does not exist" } unless -e $path; + return { error => "cannot read source '$path'" } unless -r $path; + + open my $file, '< :raw', $path or return { error => 'could not open image file. ' . $! . " $path" }; + binmode $file; + $content = join( "", <$file> ); + close $file; + return { content => $content }; +} + +sub writeFile ($$) { + my $path = shift; + my $content = shift; + + print STDERR "save '$path'\n"; + open my $fh, '> :raw', $path or return { error => 'could not save image. ' . $! . " $path" }; + binmode $fh; + print $fh $content; + close $fh; + return {}; +} + +sub deleteFile($) { + my $path = shift; + return { error => "source '$path' does not exist" } unless -e $path; + + #unlink $path; + return {}; + +} + +sub copyFile ($$$) { + my $source = shift; + my $target = shift; + my $errors = shift; + + my $read = images::readFile($source); + return $read if defined $read->{error}; + + my $write = images::writeFile( $target, $read->{content} ); + return $write; +} + +sub publish($$) { + my $config = shift; + my $filename = shift; + + print STDERR "publish\n"; + return undef unless defined $config; + return undef unless defined $filename; + my $errors = []; + for my $type ( 'images', 'thumbs', 'icons' ) { + my $source = getInternalPath( $config, { filename => $filename, type => $type } ); + my $target = getPath( $config, { filename => $filename, type => $type } ); + my $result = copyFile( $source, $target, $errors ); + if ( defined $result->{error} ) { + push @$errors, $result->{error}; + print STDERR "error on copy '$source' to '$target': $result->{error}\n"; + } + } + return $errors; +} + +sub depublish ($$) { + my $config = shift; + my $filename = shift; + + print STDERR "depublish\n"; + return undef unless defined $config; + return undef unless defined $filename; + my $errors = []; + for my $type ( 'images', 'thumbs', 'icons' ) { + my $path = getPath( $config, { filename => $filename, type => $type } ); + next unless defined $path; + print STDERR "remove '$path'\n"; + unlink $path; + + #push @$errors, $result->{error} if defined $result->{error}; + } + return $errors; +} + +sub checkLicence ($$) { + my $config = shift; + my $result = shift; + + print STDERR "depublish\n"; + return undef unless defined $config; + return undef unless defined $result; + + return if $result->{licence} =~ /\S/; + if ( ( defined $result->{public} ) && ( $result->{public} eq '1' ) ) { + depublish( $config, $result->{filename} ); + $result->{public} = 0; + } +} + +sub setEventLabels($$) { + my $dbh = shift; + my $image = shift; + + unless ( defined $image->{project_id} ) { + print STDERR "missing project_id at images::setEventLabels\n"; + return undef; + } + unless ( defined $image->{studio_id} ) { + print STDERR "missing studio_id at images::setEventLabels\n"; + return undef; + } + unless ( defined $image->{filename} ) { + print STDERR "missing filename at images::setEventLabels\n"; + return undef; + } + + my $query = qq{ + update calcms_events + set image_label=? + where image=? + }; + my $bind_values = [ $image->{licence}, $image->{filename} ]; + my $results = db::put( $dbh, $query, $bind_values ); + return $results; +} + +sub setSeriesLabels($$) { + my $dbh = shift; + my $image = shift; + + unless ( defined $image->{project_id} ) { + print STDERR "missing project_id at images::setSeriesLabels\n"; + return undef; + } + unless ( defined $image->{studio_id} ) { + print STDERR "missing studio_id at images::setSeriesLabels\n"; + return undef; + } + unless ( defined $image->{filename} ) { + print STDERR "missing filename at images::setSeriesLabels\n"; + return undef; + } + + my $query = qq{ + update calcms_events + set series_image_label=? + where series_image=? + }; + my $bind_values = [ $image->{licence}, $image->{filename} ]; + my $results = db::put( $dbh, $query, $bind_values ); + return $results; +} #do not delete last line! 1; diff --git a/lib/calcms/localization.pm b/lib/calcms/localization.pm index f1ee00a..74f277d 100644 --- a/lib/calcms/localization.pm +++ b/lib/calcms/localization.pm @@ -1,109 +1,112 @@ -package localization; +package localization; -use warnings "all"; use strict; +use warnings; +no warnings 'redefine'; + use Data::Dumper; -use uac; -use user_settings; +use uac(); +use user_settings(); -require Exporter; -our @ISA = qw(Exporter); +#use base 'Exporter'; our @EXPORT_OK = qw(get getJavascript); -our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ] ); - -sub debug; # get localisation # file : po file # language : get for selected language # user : get from user settings # loc : add to existing localization, optional -sub get{ - my $config =shift; - my $options=shift; - - #print STDERR Dumper($options); +sub get($$) { + my $config = shift; + my $options = shift; #get pot file - unless (defined $options->{file}){ + unless ( defined $options->{file} ) { print STDERR "missing po file\n"; - return $options->{loc}||{}; + return $options->{loc} || {}; } - my $language=undef; + my $language = undef; + #get language from options - $language=$options->{language} if (defined $options->{language}); + $language = $options->{language} if defined $options->{language}; #get language from user - if ( (!(defined $language)) && (defined $options->{user})){ - my $user_settings=user_settings::get($config, {user=>$options->{user}}); - $language=$user_settings->{language}; + if ( ( !( defined $language ) ) && ( defined $options->{user} ) ) { + my $user_settings = user_settings::get( $config, { user => $options->{user} } ); + $language = $user_settings->{language}; } - $language='en' unless defined $language; - $language='en' unless $language eq 'de'; + $language = 'en' unless defined $language; + $language = 'en' unless $language eq 'de'; - my $loc={}; - $loc=$options->{loc} if defined $options->{loc}; + my $loc = {}; + $loc = $options->{loc} if defined $options->{loc}; + + my $files = $options->{file}; + $files =~ s/[^a-zA-Z\,\_\-]//g; - my $files=$options->{file}; - $files=~s/[^a-zA-Z\,\_\-]//g; #get all comma separated po files - for my $file (split/\,/,$files){ + for my $file ( split /\,/, $files ) { + #read default language #my $po_file=$config->{locations}->{admin_pot_dir}.'/en/'.$file.'.po'; #$loc=read_po_file($po_file, $loc); #read selected language #if($language ne 'en'){ - my $po_file=$config->{locations}->{admin_pot_dir}.'/'.$language.'/'.$file.'.po'; - $loc=read_po_file($po_file, $loc); + my $po_file = $config->{locations}->{admin_pot_dir} . '/' . $language . '/' . $file . '.po'; + $loc = read_po_file( $po_file, $loc ); + #} } return $loc; } -sub read_po_file{ - my $po_file=shift; - my $loc =shift; +sub read_po_file($$) { + my $po_file = shift; + my $loc = shift; - unless (-e $po_file){ + unless ( -e $po_file ) { print STDERR "po file $po_file does not exist\n"; return $loc; } - unless (-r $po_file){ + unless ( -r $po_file ) { print STDERR "cannot read po file $po_file\n"; return $loc; } - - my $key=''; + + my $key = ''; open my $file, '<:encoding(UTF-8)', $po_file; - while (<$file>){ - my $line=$_; + return $loc unless defined $file; + while (<$file>) { + my $line = $_; + #print STDERR $line; - if ($line=~/^msgid\s*\"(.*)\"\s*$/){ - $key=$1; - $key=~s/\'//g; - $key=~s/\"//g; + if ( $line =~ /^msgid\s*\"(.*)\"\s*$/ ) { + $key = $1; + $key =~ s/\'//g; + $key =~ s/\"//g; } - if ($line=~/^msgstr\s*\"(.*)\"\s*$/){ - my $val=$1; - $val=~s/\'//g; - $val=~s/\"//g; - $loc->{$key}=$val; + if ( $line =~ /^msgstr\s*\"(.*)\"\s*$/ ) { + my $val = $1; + $val =~ s/\'//g; + $val =~ s/\"//g; + $loc->{$key} = $val; } } + close $file; return $loc; } -sub getJavascript{ - my $loc=shift; +sub getJavascript ($){ + my $loc = shift; - my $out='<script>'; - $out.="var loc={};\n"; - for my $key (sort keys %$loc){ - $out.=qq{loc['$key']='$loc->{$key}';}."\n"; + my $out = '<script>'; + $out .= "var loc={};\n"; + for my $key ( sort keys %$loc ) { + $out .= qq{loc['$key']='$loc->{$key}';} . "\n"; } - $out.="</script>\n"; + $out .= "</script>\n"; return $out; } diff --git a/lib/calcms/log.pm b/lib/calcms/log.pm index 758d3ef..7f7147f 100644 --- a/lib/calcms/log.pm +++ b/lib/calcms/log.pm @@ -1,166 +1,76 @@ -use warnings "all"; -use strict; -use template; -use config; - package log; -use Data::Dumper; -require Exporter; -our @ISA = qw(Exporter); -#our @EXPORT = qw(all); -our @EXPORT_OK = qw(init write read error mem); -our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ] ); +use strict; +use warnings; +no warnings 'redefine'; -#our $debug=0; -our $debug_params=''; -our $header="Content-type:text/html\n\n"; +#use base 'Exporter'; +our @EXPORT_OK = qw(error load_file save_file append_file); -our $gtop = undef; -our $proc = undef; +use config(); -sub init{ - my $request =$_[0]; - $log::debug_params =$request->{params}->{checked}->{debug}||''; - $log::header =$request->{header}if (defined $request->{header}); +#TODO: check if config is given +sub error($$) { + my $config = $_[0]; + my $message = "Error: $_[1]\n"; - #if ($config->{system}->{debug_memory}>0){ - #use GTop(); - #$log::gtop=GTop->new; - #$log::proc=$gtop->proc_mem($$); - #} -} - -sub write{ - my $config = shift; - my $key = shift; - my $data = shift; - my $dump = shift; - - return unless(defined $config::config->{system}->{debug}); - return unless(($config::config->{system}->{debug}>0) &&($log::debug_params=~/$key/)); - - my $line=Dumper($data); - $line=~s/^\$VAR1 = \{\n/<code>/g; - $line=~s/\};\n$/<\/code>/g; - $line=~s/\n/\\n/g; - my $msg=localtime()." [$key] ".$ENV{REQUEST_URI}."\\n".$line; - $msg.=Dumper($dump) if (defined $dump); - $msg.="\n"; - - log::print($config, $msg); -} - -sub print{ - my $config = $_[0]; - my $message= $_[1]; - - unless (defined $config){ + print STDERR $message; + unless ( defined $config ) { print STDERR "missing config at log::error\n"; - return; + die(); } - - my $filename=$config->{system}->{log_debug_file}||''; - if ($filename eq ''){ - print STDERR "calcms config parameter 'system/log_debug_file' not set!\n"; - return; - }; - - open my $FILE, ">>:utf8", $filename or warn("cant write log file '$filename'"); - print $FILE $message; - close $FILE; -} - -sub error{ - my $config = $_[0]; - my $message="Error: $_[1]\n"; - - unless (defined $config){ - print STDERR "missing config at log::error\n"; - } - - print STDERR $message."\n"; - if($config::config->{system}->{debug}){ - log::write($config, '', $message);# if ($config::config->{system}->{debug}>1); - - my $out=''; - #do not call template::check to avoid deep recursion! - template::process('print','templates/default.html', { - static_files_url => $config::config->{locations}->{static_files_url}, - error=>$message - }); - } - # TODO: remove exit die(); - #exit; } -sub mem{ - my $config = $_[0]; - return unless $config::config->{system}->{debug_memory}; - my $size=$log::gtop->proc_mem($$)->size(); - my $format_size=$size; - $format_size=~s/(\d)(\d\d\d)$/$1\.$2/g; - $format_size=~s/(\d)(\d\d\d)(\d\d\d)$/$1\.$2\.$3/g; - my $line=localtime(time())."\t".$$."\t".$format_size."\t".$_[0]; - $line.="\t\t".($size-$_[1]) if(defined $_[1]); - log::error($config, "log_memory_file is not defined!") if (!defined $config::config->{system}->{log_debug_memory_file}); - log::append_file($config::config->{system}->{log_debug_memory_file} , $line); +sub load_file($) { + my $filename = shift; + + my $content = ''; + if ( -e $filename ) { + my $FILE = undef; + open( $FILE, "<:utf8", $filename ) || warn "cant read file '$filename'"; + $content = join "", (<$FILE>); + close $FILE; + return $content; + } } -sub load_file{ - my $filename=$_[0]; -# my $content=$_[1]; +sub save_file($$) { + my $filename = shift; + my $content = shift; -# binmode STDOUT, ":utf8"; - my $content=''; - if (-e $filename){ - my $FILE=undef; - open $FILE, "<:utf8", $filename || warn "cant read file '$filename'"; - $content=join "",(<$FILE>); - close $FILE; - return $content; - } -} + #check if directory is writeable + if ( $filename =~ /^(.+?)\/[^\/]+$/ ) { + my $dir = $1; + unless ( -w $dir ) { + print STDERR "log::save_file : cannot write to directory ($dir)\n"; + return; + } + } -sub save_file{ - my $filename=$_[0]; - my $content=$_[1]; - - #check if directory is writeable - if ($filename=~/^(.+?)\/[^\/]+$/){ - my $dir=$1; - unless (-w $dir){ - print STDERR `pwd;id -a;`; - print STDERR "log::save_file : cannot write to directory ($dir)\n"; - return; - } - } - - open my $FILE, ">:utf8", $filename || warn("cant write file '$filename'"); - if (defined $FILE){ - print $FILE $content."\n"; - close $FILE; - } + open my $FILE, ">:utf8", $filename || warn("cant write file '$filename'"); + if ( defined $FILE ) { + print $FILE $content . "\n"; + close $FILE; + } } -sub append_file{ - my $filename =$_[0]; - my $content =$_[1]; +sub append_file($$) { + my $filename = shift; + my $content = shift; - unless ( (defined $filename) && ($filename ne'') && (-e $filename) ){ - print STDERR "cannot append, file '$filename' does not exist\n"; + unless ( ( defined $filename ) && ( $filename ne '' ) && ( -e $filename ) ) { + print STDERR "cannot append, file '$filename' does not exist\n"; return; } - if (defined $content){ - open my $FILE, ">>:utf8", $filename or warn("cant write file '$filename'"); - print $FILE $content."\n"; - close $FILE; - } -} + return unless defined $content; + open my $FILE, ">>:utf8", $filename or warn("cant write file '$filename'"); + print $FILE $content . "\n"; + close $FILE; +} #do not delete last line! 1; diff --git a/lib/calcms/mail.pm b/lib/calcms/mail.pm new file mode 100644 index 0000000..8fb4309 --- /dev/null +++ b/lib/calcms/mail.pm @@ -0,0 +1,26 @@ +package mail; + +use strict; +use warnings; +no warnings 'redefine'; + +use MIME::Lite(); + +sub send($) { + my $mail = shift; + + my $msg = MIME::Lite->new( + 'From' => $mail->{'From'}, + 'To' => $mail->{'To'}, + 'Cc' => $mail->{'Cc'}, + 'Reply-To' => $mail->{'Reply-To'}, + 'Subject' => $mail->{'Subject'}, + 'Data' => $mail->{'Data'}, + ); + + $msg->print( \*STDERR ); + $msg->send; +} + +# do not delete next line +return 1; diff --git a/lib/calcms/markup.pm b/lib/calcms/markup.pm index 48f3f09..e5056d8 100644 --- a/lib/calcms/markup.pm +++ b/lib/calcms/markup.pm @@ -1,484 +1,412 @@ -use warnings "all"; -use strict; -use Data::Dumper; -use Text::WikiCreole; - -use HTML::Parse; -use HTML::FormatText; - -use log; - package markup; -use Encode; +use strict; +use warnings; +no warnings 'redefine'; -require Exporter; -our @ISA = qw(Exporter); -#our @EXPORT = qw(all); -our @EXPORT_OK = qw(fix_line_ends html_to_creole creole_to_html creole_to_plain plain_to_ical ical_to_plain ical_to_xml html_to_plain fix_utf8 uri_encode compress base26); -our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ] ); +use Data::Dumper; +use Text::WikiCreole(); +use HTML::Parse(); +use HTML::FormatText(); +use Encode(); +use HTML::Entities(); +use Text::Markdown(); -sub fix_line_ends{ - my $s=shift; - $s=~s/\r?\n|\r/\n/g; +use log(); + +#use base 'Exporter'; +our @EXPORT_OK = + qw(fix_line_ends html_to_creole creole_to_html creole_to_plain plain_to_ical ical_to_plain ical_to_xml html_to_plain fix_utf8 uri_encode compress base26); + +sub fix_line_ends ($) { + my $s = shift; + $s =~ s/\r?\n|\r/\n/g; return $s; } # convert 1..26 to a..z, 27 to aa, inspired by ConvertAA -sub base26{ - my $num = shift ; +sub base26($) { + my $num = shift; return '' if $num <= 0; my $s = ""; - while($num){ - $s= chr (--$num % 26 + ord "a").$s; - $num = int $num/26; - } + while ($num) { + $s = chr( --$num % 26 + ord "a" ) . $s; + $num = int $num / 26; + } return $s; } -sub html_to_creole{ - my $s=shift; +sub html_to_creole($) { + my $s = shift; - #remove elements -# $s=~s/[\r\f\n]+/\n/gi; -# $s=~s/<\/p.*?>//gi; -# $s=~s/<\/br.*?>//gi; - $s=~s/\<\!\-\-[\s\S]*?\-\-\>//gi; - $s=~s/<script.*?>.*?<\/script.*?>//gi; -# $s=~s/<\/?span.*?>//gi; -# $s=~s/<\/?font.*?>//gi; -# $s=~s/<\/?meta.*?>//gi; -# $s=~s/<\/?title.*?>//gi; -# $s=~s/<\/?style.*?>//gi; -# $s=~s/<\/?col.*?>//gi; -# $s=~s/<\/?thead.*?>//gi; -# $s=~s/<\/?tbody.*?>//gi; - $s=~s/<\/?form.*?>//gi; - $s=~s/<\/?select.*?>//gi; - $s=~s/<\/?option.*?//gi; - $s=~s/<\/?input.*?>//gi; -# $s=~s/<\/?button.*?>//gi; -# $s=~s/<\/?textarea.*?>//gi; - $s=~s/<\/?script.*?>//gi; + #remove elements + $s =~ s/\<\!\-\-[\s\S]*?\-\-\>//gi; + $s =~ s/<script.*?>.*?<\/script.*?>//gi; + $s =~ s/<\/?form.*?>//gi; + $s =~ s/<\/?select.*?>//gi; + $s =~ s/<\/?option.*?//gi; + $s =~ s/<\/?input.*?>//gi; + $s =~ s/<\/?script.*?>//gi; - #table elements -# $s=~s/\s*<\/?td.*?>//gi; -# $s=~s/\s*<\/?th.*?>//gi; + #remove line breaks + $s =~ s/[\r\n]+/ /gi; - #remove line breaks - $s=~s/[\r\n]+/ /gi; + #formats + $s =~ s/<img.*?src="(.*?)".*?>/{{$1\|}}/gi; + $s =~ s/<img.*?title="(.*?)".*?>/{{$2\|$1}}/gi; + $s =~ s/<img.*?src="(.*?)"[^>]*?title="(.*?)".*?>/{{$1\|$2}}/gi; + $s =~ s/<img.*?title="(.*?)"[^>]*?src="(.*?)".*?>/{{$2\|$1}}/gi; + $s =~ s/<\/?img.*?>//gi; - #formats - $s=~s/<img.*?src="(.*?)".*?>/{{$1\|}}/gi; - $s=~s/<img.*?title="(.*?)".*?>/{{$2\|$1}}/gi; - $s=~s/<img.*?src="(.*?)"[^>]*?title="(.*?)".*?>/{{$1\|$2}}/gi; - $s=~s/<img.*?title="(.*?)"[^>]*?src="(.*?)".*?>/{{$2\|$1}}/gi; - $s=~s/<\/?img.*?>//gi; - #replace line breaks from images - $s=~s/(\{\{[^\}\n]*?)\n([^\}\n]*?\}\})/$1$2/g; - $s=~s/(\{\{[^\}\n]*?)\n([^\}\n]*?\}\})/$1$2/g; - $s=~s/(\{\{[^\}\n]*?)\n([^\}\n]*?\}\})/$1$2/g; + #replace line breaks from images + $s =~ s/(\{\{[^\}\n]*?)\n([^\}\n]*?\}\})/$1$2/g; + $s =~ s/(\{\{[^\}\n]*?)\n([^\}\n]*?\}\})/$1$2/g; + $s =~ s/(\{\{[^\}\n]*?)\n([^\}\n]*?\}\})/$1$2/g; - $s=~s/<i.*?>(.*?)<\/i>/\/\/$1\/\//gi; - $s=~s/<\/?i.*?>//gi; - $s=~s/<b.*?>(.*?)<\/b>/\*\*$1\*\*/gi; -# $s=~s/<\/?b.*?>//gi; + $s =~ s/<i.*?>(.*?)<\/i>/\/\/$1\/\//gi; + $s =~ s/<\/?i.*?>//gi; + $s =~ s/<b.*?>(.*?)<\/b>/\*\*$1\*\*/gi; - $s=~s/<strong.*?>(.*?)<\/strong>/\*\*$1\*\*/gi; - $s=~s/<em.*?>(.*?)<\/em>/\/\/$1\/\//gi; - $s=~s/<blockquote.*?>((\W+|\w+)*?)<\/blockquote>/{{{$1}}}/gi; -# $s=~s/<a\s+.*?href="(.*?)".*?>((\W+|\w+)*?)<\/a>/\[\[$1\|$2\]\]$3/gi; - $s=~s/<a\s+.*?href="(.*?)".*?>(.*?)(\s*)<\/a>/\[\[$1\|$2\]\]$3/gi; - $s=~s/<a.*?>//gi; - #replace line breaks from links - $s=~s/(\[\[[^\]\n]*?)\n([^\]]*?\]\])/$1$2/g; - $s=~s/(\[\[[^\]\n]*?)\n([^\]]*?\]\])/$1$2/g; - $s=~s/(\[\[[^\]\n]*?)\n([^\]]*?\]\])/$1$2/g; + $s =~ s/<strong.*?>(.*?)<\/strong>/\*\*$1\*\*/gi; + $s =~ s/<em.*?>(.*?)<\/em>/\/\/$1\/\//gi; + $s =~ s/<blockquote.*?>((\W+|\w+)*?)<\/blockquote>/{{{$1}}}/gi; -# print STDERR Dumper($s) if ($s=~/</); + $s =~ s/<a\s+.*?href="(.*?)".*?>(.*?)(\s*)<\/a>/\[\[$1\|$2\]\]$3/gi; + $s =~ s/<a.*?>//gi; - $s=~s/[\s]+/ /gi; -# $s=~s/\n[ \t\r\n]+\n/\n\n/gi; -# $s=~s/\n[ ]+/\n /gi; -# $s=~s/\n+/\n/gi; -# $s=~s/\n+/\\\n/gi; + #replace line breaks from links + $s =~ s/(\[\[[^\]\n]*?)\n([^\]]*?\]\])/$1$2/g; + $s =~ s/(\[\[[^\]\n]*?)\n([^\]]*?\]\])/$1$2/g; + $s =~ s/(\[\[[^\]\n]*?)\n([^\]]*?\]\])/$1$2/g; - #line elements, increase head line level to avoid breaking single = chars - $s=~s/\s*<h1.*?>/== /gi; - $s=~s/\s*<h2.*?>/=== /gi; - $s=~s/\s*<h3.*?>/==== /gi; - $s=~s/\s*<h\d.*?>/===== /gi; -# $s=~s/\s*<\/h\d.*?>/\n/gi; + $s =~ s/[\s]+/ /gi; -# $s=~s/<br.*?>/\\\\<br>/gi; -# $s=~s/\s*<div.*?>//gi; -# $s=~s/\s*<\/div>/\n/gi; + #line elements, increase head line level to avoid breaking single = chars + $s =~ s/\s*<h1.*?>/== /gi; + $s =~ s/\s*<h2.*?>/=== /gi; + $s =~ s/\s*<h3.*?>/==== /gi; + $s =~ s/\s*<h\d.*?>/===== /gi; -# $s=~s/<table.*?>/\n/gi; -# $s=~s/<\/table>/\n/gi; -# $s=~s/\s*<tr.*?>//gi; -# $s=~s/\s*<\/tr>//gi; + my $tree = HTML::Parse::parse_html( '<body>' . $s . '</body>' ); + my $formatter = HTML::FormatText->new( leftmargin => 0, rightmargin => 2000 ); + $s = $formatter->format($tree); -# $s=~s/\s*<ol.*?>/\n/gi; -# $s=~s/\s*<\/ol>/\n/gi; -# $s=~s/\s*<ul.*?>/\n/gi; -# $s=~s/\s*<\/ul>/\n/gi; -# $s=~s/\s*<li.*?>/\n\* /gi; -# $s=~s/\s*<\/li>//gi; + $s =~ s/\</\</g; -# $s=~s/\s*<p.*?>\s*/\n\n/gi; -# $s=~s/\s*<br.*?>\s*/\n /gi; + #fix line endings + $s =~ s/\n[ \t]+/\n/gi; - my $tree=HTML::Parse::parse_html('<body>'.$s.'</body>'); - my $formatter = HTML::FormatText->new(leftmargin => 0, rightmargin => 2000); - $s= $formatter->format($tree); - #use Data::Dumper; print "asd:<textarea cols=100 rows=5>".Dumper($s);print "</textarea>"; - $s=~s/\</\</g; + $s =~ s/\n{3,99}/\n\n/g; + $s =~ s/\n*\*[\s]+/\n\* /g; - #fix line endings - $s=~s/\n[ \t]+/\n/gi; - #$s=~s/\n[\t\r ]+\n/\n\n/g; - $s=~s/\n{3,99}/\n\n/g; - $s=~s/\n*\*[\s]+/\n\* /g; - #$s=~s/(\n\*.*?\n)([^\*])/$1\n\n$2/g; + #enter line break before headlines + $s =~ s/(={2,99})/\n$1/g; - #enter line break before headlines - $s=~s/(={2,99})/\n$1/g; - #reduce head line level - $s=~s/=(=+)/$1/g; + #reduce head line level + $s =~ s/=(=+)/$1/g; - $s=~s/^\s+//gi; - $s=~s/\s+$//gi; - $s=~s/\n{3,99}/\n\n/g; -# $s=~s/\n\n+/ \\\\\n/g; - $s=~s/\n/\\\\\n/g; - $s=~s/\\\\\n\=/\n\=/g; + $s =~ s/^\s+//gi; + $s =~ s/\s+$//gi; + $s =~ s/\n{3,99}/\n\n/g; - #$s=~s/\n\n/ \\\\\n/g; -# $s=~s/(\\\\\n){3,99}/\\\\\n\\\\\n/g; - #$s=~s/\\\\[ \t]+/\\\\\n/g; - -# $s=~s/<\/a>//gi; + $s =~ s/\n/\\\\\n/g; + $s =~ s/\\\\\n\=/\n\=/g; - return $s; + return $s; } -sub creole_to_html{ - my $s=$_[0]||''; - - #$s=~s/\n\#\n/\n/g; - #fix_line_ends($s); - $s=~s/<a\s+.*?href="(.*?)".*?>(.*?)(\s*)<\/a>/\[\[$1\|$2\]\]$3/gi; - $s=~s/<a.*?>//gi; +sub creole_to_html ($) { + my $s = $_[0] || ''; - $s=~s/(\[\[[^\]\n]*?)\n([^\]]*?\]\])/$1$2/g; - $s=~s/(\[\[[^\]\n]*?)\n([^\]]*?\]\])/$1$2/g; - $s=~s/(\[\[[^\]\n]*?)\n([^\]]*?\]\])/$1$2/g; - $s=~s/^\s+//g; - $s=~s/\s+$//g; + $s =~ s/<a\s+.*?href="(.*?)".*?>(.*?)(\s*)<\/a>/\[\[$1\|$2\]\]$3/gi; + $s =~ s/<a.*?>//gi; - $s=Text::WikiCreole::creole_parse($s)||''; -# $s=~s/<p>/\n/gi; -# $s=~s/\{\{\{((\W+|\w+)+?)\}\}\}/<blockquote>$1<\/blockquote>/g; -# $s=~s/\{\{(.+?)\|(.*?)\}\}/<img src="$1" title="$2" \/>/g; -# $s=~s/\[\[(.+?)\|(.*?)\]\]/<a href="$1">$2<\/a>/g; -# $s=~s/([^\:])\/\/(.*?[^\:])\/\//$1<em>$2<\/em> /g; -# $s=~s/\n=== (.*?)\n/<h3>$1<\/h3>\n/g; -# $s=~s/\n== (.*?)\n/<h2>$1<\/h2>\n/g; - #replace line breaks from images - $s=~s/(\{\{[^\}\n]*?)\n([^\}\n]*?\}\})/$1$2/g; - $s=~s/(\{\{[^\}\n]*?)\n([^\}\n]*?\}\})/$1$2/g; - $s=~s/(\{\{[^\}\n]*?)\n([^\}\n]*?\}\})/$1$2/g; - #replace line breaks from links -# $s=~s/\n= (.*?)\n/<h1>$1<\/h1>\n/g; -# $s=~s/\*\*(.*?)\*\*/<strong>$1<\/strong> /g; -# $s=~s/^== (.*?)\n/<h2>$1<\/h2>\n/g; -# $s=~s/\n\* (.*?)([\r\n]+)/<li>$1<\/li>\n/g; -# $s=~s/\n\- (.*?)\n/<lo>$1<\/lo>\n/g; -# $s=~s/\n\n/<p>/gi; -# $s=~s/\n+/<br \/>/gi; -# $s=~s/\</\</g; + $s =~ s/(\[\[[^\]\n]*?)\n([^\]]*?\]\])/$1$2/g; + $s =~ s/(\[\[[^\]\n]*?)\n([^\]]*?\]\])/$1$2/g; + $s =~ s/(\[\[[^\]\n]*?)\n([^\]]*?\]\])/$1$2/g; + $s =~ s/^\s+//g; + $s =~ s/\s+$//g; + + $s = Text::WikiCreole::creole_parse($s) || ''; + + #replace line breaks from images + $s =~ s/(\{\{[^\}\n]*?)\n([^\}\n]*?\}\})/$1$2/g; + $s =~ s/(\{\{[^\}\n]*?)\n([^\}\n]*?\}\})/$1$2/g; + $s =~ s/(\{\{[^\}\n]*?)\n([^\}\n]*?\}\})/$1$2/g; #remove whitespaces and break lines at start or end of elements - for my $elem ('p','li'){ - $s=~s|<$elem>\s*<br/><br/>|<$elem>|g; - $s=~s|<br/><br/>\s*</$elem>|</$elem>|g; + for my $elem ( 'p', 'li' ) { + $s =~ s|<$elem>\s*<br/><br/>|<$elem>|g; + $s =~ s|<br/><br/>\s*</$elem>|</$elem>|g; } - return $s; + return $s; } -sub creole_to_plain{ - my $s=shift; - - $s=~s/\<p\>/\n/gi; - $s=~s/\{\{\{((\W+|\w+)+?)\}\}\}/<blockquote>$1<\/blockquote>/g; - $s=~s/\{\{(.+?)\|(.*?)\}\}//g; - $s=~s/\[\[(.+?)\|(.*?)\]\]/$2/g; - $s=~s/\/\/([^\/\/]*?)\/\//<em>$1<\/em> /g; - $s=~s/\n=== (.*?)\n/\n<h3>$1<\/h3>\n/g; - $s=~s/\n== (.*?)\n/\n<h2>$1<\/h2>\n/g; - $s=~s/\*\*(.*?)\*\*/<strong>$1<\/strong> /g; - $s=~s/^== (.*?)\n/<h2>$1<\/h2>\n/g; - $s=~s/\n\* (.*?)\n/\n<li>$1<\/li>\n/g; - $s=~s/\n\* (.*?)\n/\n<li>$1<\/li>\n/g; - $s=~s/\n\- (.*?)\n/\n<lo>$1<\/lo>\n/g; - $s=~s/\n\- (.*?)\n/\n<lo>$1<\/lo>\n/g; - $s=~s/\n\n/\n<p>/gi; - $s=~s/\n/\n<br\/>/gi; - return $s; +sub markdown_to_html($){ + my $text = $_[0] // ''; + my $html = Text::Markdown::markdown($text); + $html=~s!(\s)(https?://[^\s]+)(\s)!$1<a href="$2">$2</a>$3!g; + return $html; } -sub html_to_plain{ - my $s=shift; - return '' unless (defined $s); - my $tree=HTML::Parse::parse_html('<body>'.$s.'</body>'); - my $formatter = HTML::FormatText->new(leftmargin => 0, rightmargin => 2000); - $s= $formatter->format($tree); - return $s; +sub creole_to_plain($) { + my $s = shift; + + $s =~ s/\<p\>/\n/gi; + $s =~ s/\{\{\{((\W+|\w+)+?)\}\}\}/<blockquote>$1<\/blockquote>/g; + $s =~ s/\{\{(.+?)\|(.*?)\}\}//g; + $s =~ s/\[\[(.+?)\|(.*?)\]\]/$2/g; + $s =~ s/\/\/([^\/\/]*?)\/\//<em>$1<\/em> /g; + $s =~ s/\n=== (.*?)\n/\n<h3>$1<\/h3>\n/g; + $s =~ s/\n== (.*?)\n/\n<h2>$1<\/h2>\n/g; + $s =~ s/\*\*(.*?)\*\*/<strong>$1<\/strong> /g; + $s =~ s/^== (.*?)\n/<h2>$1<\/h2>\n/g; + $s =~ s/\n\* (.*?)\n/\n<li>$1<\/li>\n/g; + $s =~ s/\n\* (.*?)\n/\n<li>$1<\/li>\n/g; + $s =~ s/\n\- (.*?)\n/\n<lo>$1<\/lo>\n/g; + $s =~ s/\n\- (.*?)\n/\n<lo>$1<\/lo>\n/g; + $s =~ s/\n\n/\n<p>/gi; + $s =~ s/\n/\n<br\/>/gi; + return $s; } -sub ical_to_plain{ - return '' unless defined ($_[0]); - $_[0]=~s/\\n/\n/gi; - $_[0]=~s/ /\t/gi; - $_[0]=~s/\\\./\./gi; - $_[0]=~s/\\\,/\,/gi; - $_[0]=~s/\\\\/\\/gi; - return $_[0]; +sub html_to_plain ($) { + my $s = shift; + return '' unless defined $s; + my $tree = HTML::Parse::parse_html( '<body>' . $s . '</body>' ); + my $formatter = HTML::FormatText->new( leftmargin => 0, rightmargin => 2000 ); + $s = $formatter->format($tree); + return $s; } -sub plain_to_ical{ - return '' unless defined ($_[0]); - #remove images + links - $_[0]=~s/\[\[.+?\|(.+?)\]\]/$1/g; - $_[0]=~s/\{\{.+?\}\}//g; - $_[0]=~s/^\s+//g; - $_[0]=~s/\\/\\\\/gi; - $_[0]=~s/\,/\\\,/gi; -# $_[0]=~s/\./\\\./gi; - $_[0]=~s/[\r\n]/\\n/gi; - $_[0]=~s/\t/ /gi; - return $_[0]; +sub ical_to_plain ($) { + return '' unless defined( $_[0] ); + $_[0] =~ s/\\n/\n/gi; + $_[0] =~ s/ /\t/gi; + $_[0] =~ s/\\\./\./gi; + $_[0] =~ s/\\\,/\,/gi; + $_[0] =~ s/\\\\/\\/gi; + return $_[0]; } -sub plain_to_xml{ - return '' unless defined ($_[0]); - $_[0]=~s/\n\={1,6} (.*?)\s+/\n\[\[$1\]\]\n/gi; - #remove images + links - $_[0]=~s/\[\[.+?\|(.+?)\]\]/$1/g; - $_[0]=~s/\{\{.+?\}\}//g; - return encode_xml_element($_[0]); +sub plain_to_ical ($) { + return '' unless defined( $_[0] ); -# $_[0]=~s/\ä/ä/gi; -# $_[0]=~s/\ö/ö/gi; -# $_[0]=~s/\ü/ü/gi; -# $_[0]=~s/\Ä/Ä/gi; -# $_[0]=~s/\Ö/Ö/gi; -# $_[0]=~s/\Ü/Ü/gi; -# $_[0]=~s/\ß/ß/gi; -# $_[0]=~s/\&/\&/gi; -# $_[0]=~s/\</\</gi; -# $_[0]=~s/\>/\>/gi; -# $_[0]=~s/\"/\"/gi; + #remove images + links + $_[0] =~ s/\[\[.+?\|(.+?)\]\]/$1/g; + $_[0] =~ s/\{\{.+?\}\}//g; + $_[0] =~ s/^\s+//g; + $_[0] =~ s/\\/\\\\/gi; + $_[0] =~ s/\,/\\\,/gi; -## $_[0]=~s/\n/<br\/>/gi; -## $_[0]=~s/\&amp;/\&/gi; -## $_[0]=~s/\&amp;/+/gi; -## $_[0]=~s/\&/+/gi; -## $_[0]=~s/\&/+/gi; -# return $_[0]; + # $_[0]=~s/\./\\\./gi; + $_[0] =~ s/[\r\n]/\\n/gi; + $_[0] =~ s/\t/ /gi; + return $_[0]; } -sub fix_utf8{ - $_[0] = decode( 'cp1252', $_[0] ); - return $_[0]; +sub plain_to_xml($) { + return '' unless defined( $_[0] ); + $_[0] =~ s/\n\={1,6} (.*?)\s+/\n\[\[$1\]\]\n/gi; + + #remove images + links + $_[0] =~ s/\[\[.+?\|(.+?)\]\]/$1/g; + $_[0] =~ s/\{\{.+?\}\}//g; + return encode_xml_element( $_[0] ); } -sub uri_encode{ - $_[0] =~s/([^a-zA-Z0-9_\.\-])/sprintf("%%%02lx",ord($1))/esg; - return $_[0]; +sub fix_utf8($) { + $_[0] = Encode::decode( 'cp1252', $_[0] ); + return $_[0]; } -sub compress{ - my $header=''; +sub uri_encode ($) { + $_[0] =~ s/([^a-zA-Z0-9_\.\-])/sprintf("%%%02lx",ord($1))/esg; + return $_[0]; +} - if($_[0]=~/(Content\-type\:[^\n]+[\n]+)/){ - $header=$1; - }else{ - #return; - } +sub compress ($) { + my $header = ''; - my $start=index($_[0],$header); - return if ($start<0); + if ( $_[0] =~ /(Content\-type\:[^\n]+[\n]+)/ ) { + $header = $1; + } + my $start = index( $_[0], $header ); + return if ( $start < 0 ); - my $header_length=length($header); - $header =substr($_[0],0,$start+$header_length); -# print $header."\n"; + my $header_length = length($header); + $header = substr( $_[0], 0, $start + $header_length ); - my $content=substr($_[0],$start+$header_length); + my $content = substr( $_[0], $start + $header_length ); -# #remove multiple line breaks - $content=~s/[\r\n]+[\s]*[\r\n]+/\n/g; + #remove multiple line breaks + $content =~ s/[\r\n]+[\s]*[\r\n]+/\n/g; - #remove leading whitespaces - $content=~s/[\r\n]+[\s]+/\n/g; + #remove leading whitespaces + $content =~ s/[\r\n]+[\s]+/\n/g; - #remove tailing whitespaces - $content=~s/[\t ]*[\r\n]+/\n/g; + #remove tailing whitespaces + $content =~ s/[\t ]*[\r\n]+/\n/g; - #remove whitespaces inside tags - $content=~s/([\n]\<[^\n]+)[\r\n]+/$1 /g; - $content=~s/\"\s+\>/\"\>/g; + #remove whitespaces inside tags + $content =~ s/([\n]\<[^\n]+)[\r\n]+/$1 /g; + $content =~ s/\"\s+\>/\"\>/g; - #get closing tags closer - $content=~s/[\r\n]+(\<[\/\!])/$1/g; - $content=~s/(\>)[\r\n]+([^\<])/$1$2/g; + #get closing tags closer + $content =~ s/[\r\n]+(\<[\/\!])/$1/g; + $content =~ s/(\>)[\r\n]+([^\<])/$1$2/g; - #remove leading whitespaces - #$content=~s/[\r\n]+([\d\S])/$1/g; + #remove leading whitespaces + #$content=~s/[\r\n]+([\d\S])/$1/g; - #remove empty lines - $content=~s/[\n\r]+/\n/g; + #remove empty lines + $content =~ s/[\n\r]+/\n/g; - #remove whitespaces between tags - $content=~s/\>[\t ]+\<(^\/T)/\>\<$1/g; + #remove whitespaces between tags + $content =~ s/\>[\t ]+\<(^\/T)/\>\<$1/g; - #multiple whitespaces - $content=~s/[\t ]+/ /g; + #multiple whitespaces + $content =~ s/[\t ]+/ /g; - #restore content-type line break - $_[0]=$header.$content; - #$_[0]=~s/HTTP_CONTENT_TYPE/\n\n/; -# return $_[0]; + #restore content-type line break + $_[0] = $header . $content; + + #$_[0]=~s/HTTP_CONTENT_TYPE/\n\n/; + # return $_[0]; } #from XML::RSS.pm my %entity = ( - nbsp => " ", - iexcl => "¡", - cent => "¢", - pound => "£", - curren => "¤", - yen => "¥", - brvbar => "¦", - sect => "§", - uml => "¨", - copy => "©", - ordf => "ª", - laquo => "«", - not => "¬", - shy => "­", - reg => "®", - macr => "¯", - deg => "°", - plusmn => "±", - sup2 => "²", - sup3 => "³", - acute => "´", - micro => "µ", - para => "¶", - middot => "·", - cedil => "¸", - sup1 => "¹", - ordm => "º", - raquo => "»", - frac14 => "¼", - frac12 => "½", - frac34 => "¾", - iquest => "¿", - Agrave => "À", - Aacute => "Á", - Acirc => "Â", - Atilde => "Ã", - Auml => "Ä", - Aring => "Å", - AElig => "Æ", - Ccedil => "Ç", - Egrave => "È", - Eacute => "É", - Ecirc => "Ê", - Euml => "Ë", - Igrave => "Ì", - Iacute => "Í", - Icirc => "Î", - Iuml => "Ï", - ETH => "Ð", - Ntilde => "Ñ", - Ograve => "Ò", - Oacute => "Ó", - Ocirc => "Ô", - Otilde => "Õ", - Ouml => "Ö", - times => "×", - Oslash => "Ø", - Ugrave => "Ù", - Uacute => "Ú", - Ucirc => "Û", - Uuml => "Ü", - Yacute => "Ý", - THORN => "Þ", - szlig => "ß", - agrave => "à", - aacute => "á", - acirc => "â", - atilde => "ã", - auml => "ä", - aring => "å", - aelig => "æ", - ccedil => "ç", - egrave => "è", - eacute => "é", - ecirc => "ê", - euml => "ë", - igrave => "ì", - iacute => "í", - icirc => "î", - iuml => "ï", - eth => "ð", - ntilde => "ñ", - ograve => "ò", - oacute => "ó", - ocirc => "ô", - otilde => "õ", - ouml => "ö", - divide => "÷", - oslash => "ø", - ugrave => "ù", - uacute => "ú", - ucirc => "û", - uuml => "ü", - yacute => "ý", - thorn => "þ", - yuml => "ÿ", - ); + nbsp => " ", + iexcl => "¡", + cent => "¢", + pound => "£", + curren => "¤", + yen => "¥", + brvbar => "¦", + sect => "§", + uml => "¨", + copy => "©", + ordf => "ª", + laquo => "«", + not => "¬", + shy => "­", + reg => "®", + macr => "¯", + deg => "°", + plusmn => "±", + sup2 => "²", + sup3 => "³", + acute => "´", + micro => "µ", + para => "¶", + middot => "·", + cedil => "¸", + sup1 => "¹", + ordm => "º", + raquo => "»", + frac14 => "¼", + frac12 => "½", + frac34 => "¾", + iquest => "¿", + Agrave => "À", + Aacute => "Á", + Acirc => "Â", + Atilde => "Ã", + Auml => "Ä", + Aring => "Å", + AElig => "Æ", + Ccedil => "Ç", + Egrave => "È", + Eacute => "É", + Ecirc => "Ê", + Euml => "Ë", + Igrave => "Ì", + Iacute => "Í", + Icirc => "Î", + Iuml => "Ï", + ETH => "Ð", + Ntilde => "Ñ", + Ograve => "Ò", + Oacute => "Ó", + Ocirc => "Ô", + Otilde => "Õ", + Ouml => "Ö", + times => "×", + Oslash => "Ø", + Ugrave => "Ù", + Uacute => "Ú", + Ucirc => "Û", + Uuml => "Ü", + Yacute => "Ý", + THORN => "Þ", + szlig => "ß", + agrave => "à", + aacute => "á", + acirc => "â", + atilde => "ã", + auml => "ä", + aring => "å", + aelig => "æ", + ccedil => "ç", + egrave => "è", + eacute => "é", + ecirc => "ê", + euml => "ë", + igrave => "ì", + iacute => "í", + icirc => "î", + iuml => "ï", + eth => "ð", + ntilde => "ñ", + ograve => "ò", + oacute => "ó", + ocirc => "ô", + otilde => "õ", + ouml => "ö", + divide => "÷", + oslash => "ø", + ugrave => "ù", + uacute => "ú", + ucirc => "û", + uuml => "ü", + yacute => "ý", + thorn => "þ", + yuml => "ÿ", +); -my $entities = join('|', keys %entity); +my $entities = join( '|', keys %entity ); -sub encode_xml_element { - my $text = shift; - - my $encoded_text = ''; - - while ( $text =~ s/(.*?)(\<\!\[CDATA\[.*?\]\]\>)//s ) { - $encoded_text .= encode_xml_element_text($1) . $2; - } - $encoded_text .= encode_xml_element_text($text); +sub encode_xml_element($) { + my $text = shift; - return $encoded_text; + my $encoded_text = ''; + + while ( $text =~ s/(.*?)(\<\!\[CDATA\[.*?\]\]\>)//s ) { + $encoded_text .= encode_xml_element_text($1) . $2; + } + $encoded_text .= encode_xml_element_text($text); + + return $encoded_text; } -sub encode_xml_element_text { - my $text = shift; - - $text =~ s/&(?!(#[0-9]+|#x[0-9a-fA-F]+|\w+);)/&/g; - $text =~ s/&($entities);/$entity{$1}/g; - $text =~ s/\</\<\;/g; - $text =~ s/\>/\>\;/g; +sub encode_xml_element_text ($) { + my $text = shift; - return $text; + $text =~ s/&(?!(#[0-9]+|#x[0-9a-fA-F]+|\w+);)/&/g; + $text =~ s/&($entities);/$entity{$1}/g; + $text =~ s/\</\<\;/g; + $text =~ s/\>/\>\;/g; + + return $text; +} + +sub escapeHtml($) { + my $s = shift; + return HTML::Entities::encode_entities( $s, q{&<>"'} ); } #do not delete last line! diff --git a/lib/calcms/params.pm b/lib/calcms/params.pm index a9f96b5..6398fb4 100644 --- a/lib/calcms/params.pm +++ b/lib/calcms/params.pm @@ -1,83 +1,65 @@ -package params; -use warnings "all"; +package params; + use strict; +use warnings; +no warnings 'redefine'; + use Data::Dumper; -use CGI; -use Apache2::Request; +use Apache2::Request(); -require Exporter; -our @ISA = qw(Exporter); +#use base 'Exporter'; our @EXPORT_OK = qw(get isJson); -our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ] ); -sub debug; -my $isJson=0; +my $isJson = 0; -sub isJson{ +sub isJson () { return $isJson; } -sub get{ - #get the Apache2::RequestRec - my $r=shift; +sub get ($) { + my $r = shift; - my $tmp_dir ='/var/tmp/'; - my $upload_limit=1000*1024; + my $tmp_dir = '/var/tmp/'; + my $upload_limit = 1000 * 1024; - my $cgi = undef; - my $status = undef; - my $params = {}; + my $cgi = undef; + my $status = undef; + my $params = {}; - $isJson=0; + $isJson = 0; - if (defined $r){ - #print STDERR "Apache2::Request\n"; - #get Apache2::Request - my $req = Apache2::Request->new($r, POST_MAX => $upload_limit, TEMP_DIR => $tmp_dir); + if ( defined $r ) { + my $req = Apache2::Request->new( $r, POST_MAX => $upload_limit, TEMP_DIR => $tmp_dir ); - for my $key ($req->param){ - $params->{scalar($key)}=scalar($req->param($key)); + for my $key ( $req->param ) { + $params->{ scalar($key) } = scalar( $req->param($key) ); } - #copy params to hash - #my $body=$req->body(); - #if (defined $body){ - # for my $key (keys %$body){ - # $params->{scalar($key)}=scalar($req->param($key)); - # } - #} - $status = $req->parse; #parse - }else{ - #print STDERR "CGI\n"; - $CGI::POST_MAX = $upload_limit; - $CGI::TMPDIRECTORY=$tmp_dir; - $cgi=new CGI(); - $status=$cgi->cgi_error()||$status; - my %params=$cgi->Vars(); - $params=\%params; - } - $cgi=new CGI() unless(defined $cgi); - - $isJson=1 if (defined $params->{json}) && ($params->{json}eq'1'); - - if(defined $status){ - $status='' if ($status eq 'Success'); - $status='' if ($status eq 'Missing input data'); - print $cgi->header.$status."\n" if($status ne''); + $status = $req->parse; + } else { + print STDERR "$0: require CGI\n"; + require "CGI.pm"; + $CGI::POST_MAX = $upload_limit; + $CGI::TMPDIRECTORY = $tmp_dir; + $cgi = new CGI(); + $status = $cgi->cgi_error() || $status; + my %params = $cgi->Vars(); + $params = \%params; } - #print STDERR Dumper($params); - #print $cgi->header.Dumper($params).$status; - return ($cgi, $params, $status); + $isJson = 1 if ( defined $params->{json} ) && ( $params->{json} eq '1' ); + + if ( defined $status ) { + $status = '' if $status eq 'Success'; + $status = '' if $status eq 'Missing input data'; + if ( $status ne '' ) { + $cgi = new CGI::Simple() unless defined $cgi; + print $cgi->header . $status . "\n"; + } + } + + return ( $cgi, $params, $status ); } -sub debug{ - my $message=shift; - #print "$msg<br/>\n" if ($debug>0); - #print "$message<br>\n"; - #log::print($message."\n") if ($debug); -} - - #do not delete last line! 1; diff --git a/lib/calcms/password_requests.pm b/lib/calcms/password_requests.pm new file mode 100644 index 0000000..f7e8789 --- /dev/null +++ b/lib/calcms/password_requests.pm @@ -0,0 +1,224 @@ +package password_requests; + +use strict; +use warnings; +no warnings 'redefine'; + +use Data::Dumper; +use Session::Token(); + +# table: calcms_password_requests +#use base 'Exporter'; +our @EXPORT_OK = qw(get insert delete get_columns); + +use mail; +use uac; +use db; +use auth; + +sub get_columns ($) { + my $config = shift; + + my $dbh = db::connect($config); + return db::get_columns_hash( $dbh, 'calcms_password_requests' ); +} + +sub get ($$) { + my $config = shift; + my $condition = shift; + + my $dbh = db::connect($config); + + my @conditions = (); + my @bind_values = (); + + if ( defined $condition->{user} ) { + push @conditions, 'user=?'; + push @bind_values, $condition->{user}; + } + + if ( defined $condition->{token} ) { + push @conditions, 'token=?'; + push @bind_values, $condition->{token}; + } + + return undef if ( scalar @conditions ) == 0; + + my $conditions = " where " . join( " and ", @conditions ); + my $query = qq{ + select * + from calcms_password_requests + $conditions + }; + + my $entries = db::get( $dbh, $query, \@bind_values ); + return $entries->[0] || undef; +} + +sub update($$) { + my $config = shift; + my $entry = shift; + + return unless defined $entry->{user}; + + my $dbh = db::connect($config); + my @keys = sort keys %$entry; + my $values = join( ",", map { $_ . '=?' } @keys); + my @bind_values = map { $entry->{$_} } @keys; + push @bind_values, $entry->{token}; + + my $query = qq{ + update calcms_password_requests + set $values + where token=? + }; + db::put( $dbh, $query, \@bind_values ); +} + +sub insert ($$) { + my $config = shift; + my $entry = shift; + + return undef unless defined $entry->{user}; + + my $dbh = db::connect($config); + return db::insert( $dbh, 'calcms_password_requests', $entry ); +} + +sub delete ($$) { + my $config = shift; + my $condition = shift; + + my @conditions = (); + my @bind_values = (); + + if ( ( defined $condition->{user} ) && ( $condition->{user} ne '' ) ) { + push @conditions, 'user=?'; + push @bind_values, $condition->{user}; + } + + if ( ( defined $condition->{token} ) && ( $condition->{token} ne '' ) ) { + push @conditions, 'token=?'; + push @bind_values, $condition->{token}; + } + + return if ( scalar @conditions ) == 0; + my $conditions = " where " . join( " and ", @conditions ); + + my $dbh = db::connect($config); + + my $query = qq{ + delete + from calcms_password_requests + $conditions + }; + + db::put( $dbh, $query, \@bind_values ); +} + +sub sendToken ($$) { + my $config = shift; + my $entry = shift; + + return undef unless defined $entry->{user}; + + my $user = uac::get_user( $config, $entry->{user} ); + return undef unless defined $user; + + # check age of existing entry + my $oldEntry = password_requests::get( $config, { user => $entry->{user} } ); + if ( defined $oldEntry ) { + my $createdAt = $oldEntry->{created_at}; + my $age = time() - time::datetime_to_time($createdAt); + if ( $age < 60 ) { + print STDERR "too many requests"; + return undef; + } + print STDERR "age=$age\n"; + } + password_requests::delete( $config, $entry ); + + $entry->{max_attempts} = 0; + $entry->{token} = Session::Token->new->get; + + my $baseUrl = $config->{locations}->{source_base_url} . $config->{locations}->{editor_base_url}; + my $url = $baseUrl . "/request-password.cgi?token=" . $entry->{token}; + my $content = "Hi,$user->{full_name}\n\n"; + $content .= "Someone has just tried to reset your password for $baseUrl.\n\n"; + $content .= "If you want to set a new password, please follow this link\n"; + $content .= $url . "\n\n"; + $content .= "If you do not want to set a new password, please ignore this mail.\n"; + + mail::send( + { + "To" => $user->{email}, + "Subject" => "request to change password for $baseUrl", + "Data" => $content + } + ); + + password_requests::insert( $config, $entry ); +} + +sub changePassword ($$$) { + my $config = shift; + my $request = shift; + my $userName = shift; + + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + + unless ( ( defined $userName ) || ( $userName eq '' ) ) { + return { error => 'The User could not be found.' }; + } + + my $user = uac::get_user( $config, $userName ); + + unless ( ( defined $user ) && ( defined $user->{id} ) && ( $user->{id} ne '' ) ) { + return { error => 'Te User ID could not be found.' }; + } + + if ( my $msg = password_requests::isPasswordInvalid( $params->{user_password} ) ) { + return { error => $msg } if $msg; + } + + if ( $params->{user_password} ne $params->{user_password2} ) { + return { error => 'The passwords entered do not match.' }; + } + + my $crypt = auth::crypt_password( $params->{user_password} ); + $user = { id => $user->{id} }; + $user->{salt} = $crypt->{salt}; + $user->{pass} = $crypt->{crypt}; + + $config->{access}->{write} = 1; + my $result = uac::update_user( $config, $user ); + $config->{access}->{write} = 0; + return { success => "The password was changed for $userName." }; +} + +sub isPasswordInvalid($) { + my $password = shift; + unless ( defined $password || $password eq '' ) { + return "The password must not be empty."; + } + if ( length($password) < 8 ) { + return "The password must have at least 8 characters."; + } + unless ( $password =~ /[a-z]/ ) { + return "The password must contain at least one small character."; + } + unless ( $password =~ /[A-Z]/ ) { + return "The password must contain at least one big character"; + } + unless ( $password =~ /[0-9]/ ) { + return "The password must contain at least one number."; + } + unless ( $password =~ /[^a-zA-Z0-9]/ ) { + return "The password must contain at least one special character."; + } + return 0; +} + +#do not delete last line! +1; diff --git a/lib/calcms/playout.pm b/lib/calcms/playout.pm index 39a461c..ec2aa03 100644 --- a/lib/calcms/playout.pm +++ b/lib/calcms/playout.pm @@ -1,95 +1,195 @@ -#!/bin/perl - -package playout; -use warnings "all"; +package playout; + use strict; +use warnings; +no warnings 'redefine'; + use Data::Dumper; -use Date::Calc; -use db; -use time; -use series_events; +use Date::Calc(); +use db(); +use time(); +use series_events(); -require Exporter; -our @ISA = qw(Exporter); +#use base 'Exporter'; our @EXPORT_OK = qw(get_columns get sync); -our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ] ); -sub debug; +sub get_columns ($) { + my $config = shift; -sub get_columns{ - my $config=shift; - - my $dbh=db::connect($config); - my $cols=db::get_columns($dbh, 'calcms_playout'); - my $columns={}; - for my $col (@$cols){ - $columns->{$col}=1; - } - return $columns; + my $dbh = db::connect($config); + return db::get_columns_hash( $dbh, 'calcms_playout' ); } -# get playout entries -sub get{ - my $config=shift; - my $condition=shift; + + +# get playout entries +sub get_scheduled($$) { + my $config = shift; + my $condition = shift; return undef unless defined $condition->{studio_id}; - my $date_range_include=0; - $date_range_include=1 if $condition->{date_range_include}==1; + my $date_range_include = 0; + $date_range_include = 1 + if ( defined $condition->{date_range_include} ) && ( $condition->{date_range_include} == 1 ); - my $dbh=db::connect($config); + my $dbh = db::connect($config); - my @conditions=(); - my @bind_values=(); + my @conditions = (); + my @bind_values = (); - if ((defined $condition->{project_id}) && ($condition->{project_id} ne '')){ - push @conditions, 'project_id=?'; - push @bind_values, $condition->{project_id}; - } - - if ((defined $condition->{studio_id}) && ($condition->{studio_id} ne '')){ - push @conditions, 'studio_id=?'; - push @bind_values, $condition->{studio_id}; - } - - if ((defined $condition->{start_at}) && ($condition->{start_at} ne '')){ - push @conditions, 'start=?'; - push @bind_values, $condition->{start_at}; - } - - if ((defined $condition->{from}) && ($condition->{from} ne '')){ - if ($date_range_include==1){ - push @conditions, 'end_date>=?'; - push @bind_values, $condition->{from}; - }else{ - push @conditions, 'start_date>=?'; - push @bind_values, $condition->{from}; - } - } - - if ((defined $condition->{till}) && ($condition->{till} ne '')){ - if ($date_range_include==1){ - push @conditions, 'start_date<=?'; - push @bind_values, $condition->{till}; - }else{ - push @conditions, 'end_date<=?'; - push @bind_values, $condition->{till}; - } - } - - my $limit=''; - if ((defined $condition->{limit}) && ($condition->{limit} ne '')){ - $limit= 'limit '.$condition->{limit}; + if ( ( defined $condition->{project_id} ) && ( $condition->{project_id} ne '' ) ) { + push @conditions, 'p.project_id=?'; + push @bind_values, $condition->{project_id}; } - my $conditions=''; - $conditions=" where ".join(" and ",@conditions) if (@conditions>0); - - my $order='start'; - $order=$condition->{order} if (defined $condition->{order} ) && ($condition->{order} ne''); + if ( ( defined $condition->{studio_id} ) && ( $condition->{studio_id} ne '' ) ) { + push @conditions, 'p.studio_id=?'; + push @bind_values, $condition->{studio_id}; + } - my $query=qq{ + if ( ( defined $condition->{start_at} ) && ( $condition->{start_at} ne '' ) ) { + push @conditions, 'p.start=?'; + push @bind_values, $condition->{start_at}; + } + + if ( ( defined $condition->{from} ) && ( $condition->{from} ne '' ) ) { + if ( $date_range_include == 1 ) { + push @conditions, 'p.end_date>=?'; + push @bind_values, $condition->{from}; + } else { + push @conditions, 'p.start_date>=?'; + push @bind_values, $condition->{from}; + } + } + + if ( ( defined $condition->{till} ) && ( $condition->{till} ne '' ) ) { + if ( $date_range_include == 1 ) { + push @conditions, 'p.start_date<=?'; + push @bind_values, $condition->{till}; + } else { + push @conditions, 'p.end_date<=?'; + push @bind_values, $condition->{till}; + } + } + + my $limit = ''; + if ( ( defined $condition->{limit} ) && ( $condition->{limit} ne '' ) ) { + $limit = 'limit ' . $condition->{limit}; + } + + my $conditions = ''; + $conditions = " and " . join( " and ", @conditions ) if scalar @conditions > 0; + + my $order = 'p.start'; + $order = $condition->{order} if ( defined $condition->{order} ) && ( $condition->{order} ne '' ); + + my $query = qq{ + select date(p.start) start_date + , date(p.end) end_date + , dayname(p.start) weekday + , p.start_date day + , p.start + , p.end + , p.studio_id + , p.project_id + , p.duration + , p.file + , p.errors + , p.channels + , p.format + , p.format_version + , p.format_profile + , p.format_settings + , p.stream_size + , p.bitrate + , p.bitrate_mode + , p.sampling_rate + , p.writing_library + , p.rms_left + , p.rms_right + , p.rms_image + , p.modified_at + , p.updated_at + , TIMESTAMPDIFF(SECOND,e.start,e.end) "event_duration" + from calcms_playout p, calcms_events e, calcms_series_events se + where p.start=e.start + and e.id=se.event_id + and p.studio_id=se.studio_id + and p.project_id=se.project_id + $conditions + order by $order + $limit + }; + + my $entries = db::get( $dbh, $query, \@bind_values ); + return $entries; +} + + +# get playout entries +sub get($$) { + my $config = shift; + my $condition = shift; + + return undef unless defined $condition->{studio_id}; + + my $date_range_include = 0; + $date_range_include = 1 + if ( defined $condition->{date_range_include} ) && ( $condition->{date_range_include} == 1 ); + + my $dbh = db::connect($config); + + my @conditions = (); + my @bind_values = (); + + if ( ( defined $condition->{project_id} ) && ( $condition->{project_id} ne '' ) ) { + push @conditions, 'project_id=?'; + push @bind_values, $condition->{project_id}; + } + + if ( ( defined $condition->{studio_id} ) && ( $condition->{studio_id} ne '' ) ) { + push @conditions, 'studio_id=?'; + push @bind_values, $condition->{studio_id}; + } + + if ( ( defined $condition->{start_at} ) && ( $condition->{start_at} ne '' ) ) { + push @conditions, 'start=?'; + push @bind_values, $condition->{start_at}; + } + + if ( ( defined $condition->{from} ) && ( $condition->{from} ne '' ) ) { + if ( $date_range_include == 1 ) { + push @conditions, 'end_date>=?'; + push @bind_values, $condition->{from}; + } else { + push @conditions, 'start_date>=?'; + push @bind_values, $condition->{from}; + } + } + + if ( ( defined $condition->{till} ) && ( $condition->{till} ne '' ) ) { + if ( $date_range_include == 1 ) { + push @conditions, 'start_date<=?'; + push @bind_values, $condition->{till}; + } else { + push @conditions, 'end_date<=?'; + push @bind_values, $condition->{till}; + } + } + + my $limit = ''; + if ( ( defined $condition->{limit} ) && ( $condition->{limit} ne '' ) ) { + $limit = 'limit ' . $condition->{limit}; + } + + my $conditions = ''; + $conditions = " where " . join( " and ", @conditions ) if ( @conditions > 0 ); + + my $order = 'start'; + $order = $condition->{order} if ( defined $condition->{order} ) && ( $condition->{order} ne '' ); + + my $query = qq{ select date(start) start_date ,date(end) end_date ,dayname(start) weekday @@ -122,43 +222,36 @@ sub get{ $limit }; - #print STDERR Dumper($query).Dumper(\@bind_values); - my $entries=db::get($dbh, $query, \@bind_values); - return $entries; + my $entries = db::get( $dbh, $query, \@bind_values ); + return $entries; } # update playout entries for a given date span # insert, update and delete entries -sub sync{ - my $config=shift; - my $options=shift; +sub sync ($$) { + my $config = shift; + my $options = shift; - #print STDERR Dumper($config); - print STDERR "upload ".Dumper($options); - return undef unless defined $options->{project_id} ; - return undef unless defined $options->{studio_id} ; - return undef unless defined $options->{from} ; - return undef unless defined $options->{till} ; - return undef unless defined $options->{events} ; + return undef unless defined $options->{project_id}; + return undef unless defined $options->{studio_id}; + return undef unless defined $options->{from}; + return undef unless defined $options->{till}; + return undef unless defined $options->{events}; my $project_id = $options->{project_id}; my $studio_id = $options->{studio_id}; my $updates = $options->{events}; - #print STDERR "sync\n"; - #print STDERR Dumper($updates); - - # get new entries by date - my $update_by_date={}; - for my $entry (@$updates){ - $update_by_date->{$entry->{start}}=$entry; - } - # get database entries - my $bind_values=[ - $options->{project_id}, $options->{studio_id}, $options->{from}, $options->{till} - ]; - - my $query=qq{ + # get new entries by date + my $update_by_date = {}; + for my $entry (@$updates) { + $update_by_date->{ $entry->{start} } = $entry; + } + + # get database entries + my $bind_values = [ $options->{project_id}, $options->{studio_id}, $options->{from}, $options->{till} ]; + + my $query = qq{ select * from calcms_playout where project_id=? @@ -167,111 +260,127 @@ sub sync{ and end <= ? order by start }; - print STDERR "from:$options->{from} till:$options->{till}\n"; - my $dbh=db::connect($config); - my $entries=db::get($dbh, $query, $bind_values); - #print STDERR "entries:".Dumper($entries); + print STDERR "from:$options->{from} till:$options->{till}\n"; + my $dbh = db::connect($config); + my $entries = db::get( $dbh, $query, $bind_values ); # get database entries by date - my $entries_by_date={}; - for my $entry (@$entries){ - # store entry by date - my $start=$entry->{start}; - $entries_by_date->{$start}=$entry; + my $entries_by_date = {}; + for my $entry (@$entries) { + + # store entry by date + my $start = $entry->{start}; + $entries_by_date->{$start} = $entry; + + # remove outdated entries + unless ( defined $update_by_date->{$start} ) { + playout::delete( $config, $dbh, $entry ); + my $result = series_events::set_playout_status( + $config, + { + project_id => $project_id, + studio_id => $studio_id, + start => $entry->{start}, + playout => 0, + } + ); + print STDERR "delete playout_status result=" . ($result // 'undef') . "\n"; + next; + } - # remove outdated entries - unless (defined $update_by_date->{$start}){ - print STDERR "delete:".Dumper($entry); - playout::delete($config, $dbh, $entry); - my $result=series_events::set_playout_status($config, { - project_id => $project_id, - studio_id => $studio_id, - start => $entry->{start}, - playout => 0, - }); - print STDERR "delete playout_status result=".$result."\n"; - next; - } # update existing entries - if (defined $update_by_date->{$start}){ - next if has_changed($entry, $update_by_date->{$start})==0; - print STDERR "update:".Dumper($entry); - playout::update($config, $dbh, $entry, $update_by_date->{$start}); - my $result=series_events::set_playout_status($config, { - project_id => $project_id, - studio_id => $studio_id, - start => $entry->{start}, - playout => 1, - }); - print STDERR "update playout_status result=".$result."\n"; - next; - } - } + if ( defined $update_by_date->{$start} ) { + #next if has_changed( $entry, $update_by_date->{$start} ) == 0; + playout::update( $config, $dbh, $entry, $update_by_date->{$start} ); + my $result = series_events::set_playout_status( + $config, + { + project_id => $project_id, + studio_id => $studio_id, + start => $entry->{start}, + playout => 1, + } + ); + print STDERR "update playout_status result=" . ($result // 'undef') . "\n"; + next; + } + } # insert new entries - for my $entry (@$updates){ - my $start=$entry->{start}; - unless (defined $entries_by_date->{$start}){ + for my $entry (@$updates) { + my $start = $entry->{start}; + unless ( defined $entries_by_date->{$start} ) { $entry->{project_id} = $project_id; $entry->{studio_id} = $studio_id; - print STDERR "insert:".Dumper($entry); - playout::insert($config, $dbh, $entry); - my $result=series_events::set_playout_status($config, { - project_id => $project_id, - studio_id => $studio_id, - start => $entry->{start}, - playout => 1, - }); - print STDERR "insert playout_status result=".$result."\n"; - } - } - return 1; + playout::insert( $config, $dbh, $entry ); + my $result = series_events::set_playout_status( + $config, + { + project_id => $project_id, + studio_id => $studio_id, + start => $entry->{start}, + playout => 1, + } + ); + print STDERR "insert playout_status result=" . ($result // 'undef'). "\n"; + } + } + return 1; } -sub has_changed{ - my $oldEntry=shift; - my $newEntry=shift; +sub has_changed ($$) { + my $oldEntry = shift; + my $newEntry = shift; - my $update=0; - for my $key ('duration', 'errors', 'file', 'channels', 'format', 'format_version', 'format_profile', 'format_settings', 'stream_size', 'bitrate', 'bitrate_mode', 'sampling_rate', 'writing_library', 'modified_at'){ - return 1 if ($oldEntry->{$key}||'') ne ($newEntry->{$key}||''); + for my $key ( + 'duration', 'errors', 'file', 'channels', + 'format', 'format_version', 'format_profile', 'format_settings', + 'stream_size', 'bitrate', 'bitrate_mode', 'sampling_rate', + 'writing_library', 'modified_at' + ) + { + return 1 if ( $oldEntry->{$key} // '' ) ne ( $newEntry->{$key} // '' ); } return 0; } # update playout entry if differs to old values -sub update{ - my $config=shift; - my $dbh=shift; - my $oldEntry=shift; - my $newEntry=shift; - - return if has_changed($oldEntry, $newEntry)==0; - - for my $key ('duration', 'errors', 'file', 'channels', 'format', 'format_version', 'format_profile', 'format_settings', 'stream_size', 'bitrate', 'bitrate_mode', 'sampling_rate', 'writing_library', 'rms_left', 'rms_right', 'rms_image', 'replay_gain', 'modified_at'){ - if (($oldEntry->{$key}||'') ne ($newEntry->{$key}||'')){ - $oldEntry->{$key}=$newEntry->{$key}; +sub update ($$$$) { + my $config = shift; + my $dbh = shift; + my $oldEntry = shift; + my $newEntry = shift; + + #return if has_changed( $oldEntry, $newEntry ) == 0; + + for my $key ( + 'duration', 'errors', 'file', 'channels', + 'format', 'format_version', 'format_profile', 'format_settings', + 'stream_size', 'bitrate', 'bitrate_mode', 'sampling_rate', + 'writing_library', 'rms_left', 'rms_right', 'rms_image', + 'replay_gain', 'modified_at' + ) + { + if ( ( $oldEntry->{$key} || '' ) ne ( $newEntry->{$key} || '' ) ) { + $oldEntry->{$key} = $newEntry->{$key}; } } - my $entry=$oldEntry; - print STDERR "update:".Dumper($entry); + my $entry = $oldEntry; + my $day_start = $config->{date}->{day_starting_hour}; + $entry->{end} = playout::getEnd( $entry->{start}, $entry->{duration} ); + $entry->{start_date} = time::add_hours_to_datetime( $entry->{start}, -$day_start ); + $entry->{end_date} = time::add_hours_to_datetime( $entry->{end}, -$day_start ); - my $day_start=$config->{date}->{day_starting_hour}; - $entry->{end} = playout::getEnd($entry->{start}, $entry->{duration}); - $entry->{start_date} = time::add_hours_to_datetime($entry->{start}, -$day_start); - $entry->{end_date} = time::add_hours_to_datetime($entry->{end}, -$day_start); - - my $bind_values=[ - $entry->{end}, $entry->{duration}, $entry->{file}, $entry->{errors}, - $entry->{start_date}, $entry->{end_date}, - $entry->{channels}, $entry->{'format'}, $entry->{format_version}, $entry->{format_profile}, $entry->{format_settings}, $entry->{stream_size}, - $entry->{bitrate}, $entry->{bitrate_mode}, $entry->{sampling_rate}, $entry->{writing_library}, - $entry->{rms_left}, $entry->{rms_right}, $entry->{rms_image}, - $entry->{replay_gain}, $entry->{modified_at}, - $entry->{project_id}, $entry->{studio_id}, $entry->{start} + my $bind_values = [ + $entry->{end}, $entry->{duration}, $entry->{file}, $entry->{errors}, + $entry->{start_date}, $entry->{end_date}, $entry->{channels}, $entry->{'format'}, + $entry->{format_version}, $entry->{format_profile}, $entry->{format_settings}, $entry->{stream_size}, + $entry->{bitrate}, $entry->{bitrate_mode}, $entry->{sampling_rate}, $entry->{writing_library}, + $entry->{rms_left}, $entry->{rms_right}, $entry->{rms_image}, $entry->{replay_gain}, + $entry->{modified_at}, $entry->{project_id}, $entry->{studio_id}, $entry->{start} ]; - my $query=qq{ + my $query = qq{ update calcms_playout set end=?, duration=?, file=?, errors=?, start_date=?, end_date=?, @@ -281,93 +390,97 @@ sub update{ replay_gain=?, modified_at=? where project_id=? and studio_id=? and start=? }; - return db::put($dbh, $query, $bind_values); + return db::put( $dbh, $query, $bind_values ); } # insert playout entry -sub insert{ - my $config=shift; - my $dbh=shift; - my $entry=shift; +sub insert ($$$) { + my $config = shift; + my $dbh = shift; + my $entry = shift; - return undef unless defined $entry->{project_id}; - return undef unless defined $entry->{studio_id}; - return undef unless defined $entry->{start}; - return undef unless defined $entry->{duration}; - return undef unless defined $entry->{file}; + return undef unless defined $entry->{project_id}; + return undef unless defined $entry->{studio_id}; + return undef unless defined $entry->{start}; + return undef unless defined $entry->{duration}; + return undef unless defined $entry->{file}; - my $day_start=$config->{date}->{day_starting_hour}; - $entry->{end} = playout::getEnd($entry->{start}, $entry->{duration}); - $entry->{start_date} = time::add_hours_to_datetime($entry->{start}, -$day_start); - $entry->{end_date} = time::add_hours_to_datetime($entry->{end}, -$day_start); - - return db::insert($dbh, 'calcms_playout', { - project_id => $entry->{project_id}, - studio_id => $entry->{studio_id}, - start => $entry->{start}, - end => $entry->{end}, - start_date => $entry->{start_date}, - end_date => $entry->{end_date}, - duration => $entry->{duration}, - rms_left => $entry->{rms_left}, - rms_right => $entry->{rms_right}, - rms_image => $entry->{rms_image}, - replay_gain => $entry->{replay_gain}, - file => $entry->{file}, - errors => $entry->{errors}, - channels => $entry->{channels}, - "format" => $entry->{"format"}, - format_version => $entry->{format_version}, - format_profile => $entry->{format_profile}, - format_settings => $entry->{format_settings}, - stream_size => $entry->{stream_size}, - bitrate => $entry->{bitrate}, - bitrate_mode => $entry->{bitrate_mode}, - sampling_rate => $entry->{sampling_rate}, - writing_library => $entry->{writing_library}, - modified_at => $entry->{modified_at} - }); + my $day_start = $config->{date}->{day_starting_hour}; + $entry->{end} = playout::getEnd( $entry->{start}, $entry->{duration} ); + $entry->{start_date} = time::add_hours_to_datetime( $entry->{start}, -$day_start ); + $entry->{end_date} = time::add_hours_to_datetime( $entry->{end}, -$day_start ); + + return db::insert( + $dbh, + 'calcms_playout', + { + project_id => $entry->{project_id}, + studio_id => $entry->{studio_id}, + start => $entry->{start}, + end => $entry->{end}, + start_date => $entry->{start_date}, + end_date => $entry->{end_date}, + duration => $entry->{duration}, + rms_left => $entry->{rms_left}, + rms_right => $entry->{rms_right}, + rms_image => $entry->{rms_image}, + replay_gain => $entry->{replay_gain}, + file => $entry->{file}, + errors => $entry->{errors}, + channels => $entry->{channels}, + "format" => $entry->{"format"}, + format_version => $entry->{format_version}, + format_profile => $entry->{format_profile}, + format_settings => $entry->{format_settings}, + stream_size => $entry->{stream_size}, + bitrate => $entry->{bitrate}, + bitrate_mode => $entry->{bitrate_mode}, + sampling_rate => $entry->{sampling_rate}, + writing_library => $entry->{writing_library}, + modified_at => $entry->{modified_at} + } + ); } # delete playout entry -sub delete{ - my $config=shift; - my $dbh=shift; - my $entry=shift; - - return undef unless defined $entry->{project_id}; - return undef unless defined $entry->{studio_id}; - return undef unless defined $entry->{start}; +sub delete($$$) { + my $config = shift; + my $dbh = shift; + my $entry = shift; - my $query=qq{ + return undef unless defined $entry->{project_id}; + return undef unless defined $entry->{studio_id}; + return undef unless defined $entry->{start}; + + my $query = qq{ delete from calcms_playout where project_id=? and studio_id=? and start=? }; - my $bind_values=[$entry->{project_id}, $entry->{studio_id}, $entry->{start}]; - return db::put($dbh, $query, $bind_values); + my $bind_values = [ $entry->{project_id}, $entry->{studio_id}, $entry->{start} ]; + return db::put( $dbh, $query, $bind_values ); } -sub getEnd{ - my $start=shift; - my $duration=shift; +sub getEnd ($$) { + my $start = shift; + my $duration = shift; + # calculate end from start + duration - my @start = @{time::datetime_to_array($start)}; - next unless @start>=6; - #print STDERR Dumper(\@start); - my @end_datetime = Date::Calc::Add_Delta_DHMS( - $start[0], $start[1], $start[2], # start date - $start[3], $start[4], $start[5], # start time - 0, 0, 0, int($duration) # delta days, hours, minutes, seconds - ); - #print STDERR Dumper(\@end_datetime); - return time::array_to_datetime(\@end_datetime); + my @start = @{ time::datetime_to_array($start) }; + next unless @start >= 6; + + my @end_datetime = Date::Calc::Add_Delta_DHMS( + $start[0], $start[1], $start[2], # start date + $start[3], $start[4], $start[5], # start time + 0, 0, 0, int($duration) # delta days, hours, minutes, seconds + ); + return time::array_to_datetime( \@end_datetime ); } -sub error{ - my $msg=shift; - print "ERROR: $msg<br/>\n"; +sub error($) { + my $msg = shift; + print "ERROR: $msg<br/>\n"; } #do not delete last line! diff --git a/lib/calcms/project.pm b/lib/calcms/project.pm index 151eba4..9462e3e 100644 --- a/lib/calcms/project.pm +++ b/lib/calcms/project.pm @@ -1,477 +1,487 @@ -#!/bin/perl - -package project; -use warnings "all"; +package project; + use strict; +use warnings; +no warnings 'redefine'; use Data::Dumper; use Date::Calc; -use config; -use log; -use template; -require Exporter; -our @ISA = qw(Exporter); +use config(); +use log(); +use template(); +use images(); + +#use base 'Exporter'; our @EXPORT_OK = qw( - check get_columns get insert delete get_date_range - get_studios assign_studio unassign_studio is_studio_assigned get_studio_assignments - get_series_ids assign_series unassign_series is_series_assigned get_series_assignments - get_with_dates get_sorted + check get_columns get insert delete get_date_range + get_studios assign_studio unassign_studio is_studio_assigned get_studio_assignments + get_series_ids assign_series unassign_series is_series_assigned get_series_assignments + get_with_dates get_sorted ); + #TODO: globally replace get_studios by get_studio_assignments -our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ] ); - -sub debug; - # get project columns -sub get_columns{ - my $config=shift; +sub get_columns ($) { + my $config = shift; - my $dbh=db::connect($config); - my $cols=db::get_columns($dbh, 'calcms_projects'); - my $columns={}; - for my $col (@$cols){ - $columns->{$col}=1; - } - return $columns; + my $dbh = db::connect($config); + return db::get_columns_hash( $dbh, 'calcms_projects' ); } # get projects -sub get{ - my $config=shift; - my $condition=shift; +sub get ($;$) { + my $config = shift; + my $condition = shift; - my $dbh=db::connect($config); + my $dbh = db::connect($config); - my @conditions=(); - my @bind_values=(); + my @conditions = (); + my @bind_values = (); - if ((defined $condition->{project_id}) && ($condition->{project_id} ne '')){ - push @conditions, 'project_id=?'; - push @bind_values, $condition->{project_id}; - } - - if ((defined $condition->{name}) && ($condition->{name} ne '')){ - push @conditions, 'name=?'; - push @bind_values, $condition->{name}; - } - - my $limit=''; - if ((defined $condition->{limit}) && ($condition->{limit} ne '')){ - $limit= 'limit '.$condition->{limit}; + if ( ( defined $condition->{project_id} ) && ( $condition->{project_id} ne '' ) ) { + push @conditions, 'project_id=?'; + push @bind_values, $condition->{project_id}; } - my $conditions=''; - $conditions=" where ".join(" and ",@conditions) if (@conditions>0); + if ( ( defined $condition->{name} ) && ( $condition->{name} ne '' ) ) { + push @conditions, 'name=?'; + push @bind_values, $condition->{name}; + } - my $query=qq{ + my $limit = ''; + if ( ( defined $condition->{limit} ) && ( $condition->{limit} ne '' ) ) { + $limit = 'limit ' . $condition->{limit}; + } + + my $conditions = ''; + $conditions = " where " . join( " and ", @conditions ) if ( @conditions > 0 ); + + my $query = qq{ select * from calcms_projects $conditions order by start_date $limit }; - #print STDERR Dumper($query).Dumper(\@bind_values); - my $projects=db::get($dbh, $query, \@bind_values); - return $projects; + my $projects = db::get( $dbh, $query, \@bind_values ); + return $projects; } -sub get_date_range{ - my $config=shift; - my $query=qq{ +# requires at least project_id +sub getImageById($$) { + my $config = shift; + my $conditions = shift; + + return undef unless defined $conditions->{project_id}; + my $projects = project::get( $config, $conditions ); + return undef if scalar(@$projects) != 1; + return $projects->[0]->{image}; +} + +sub get_date_range($) { + my $config = shift; + + my $query = qq{ select min(start_date) start_date, max(end_date) end_date from calcms_projects }; - my $dbh=db::connect($config); + my $dbh = db::connect($config); - my $projects=db::get($dbh, $query); - return $projects->[0]; + my $projects = db::get( $dbh, $query ); + return $projects->[0]; } # insert project -sub insert{ - my $config=shift; - my $entry=shift; +sub insert($$) { + my $config = shift; + my $entry = shift; - my $columns=get_columns($config); - my $project={}; - for my $column (keys %$columns){ - $project->{$column}=$entry->{$column} if defined $entry->{$column}; + my $columns = get_columns($config); + my $project = {}; + for my $column ( keys %$columns ) { + $project->{$column} = $entry->{$column} if defined $entry->{$column}; } - my $dbh=db::connect($config); - my $id=db::insert($dbh, 'calcms_projects', $project); + $project->{image} = images::normalizeName( $project->{image} ) if defined $project->{image}; + + my $dbh = db::connect($config); + my $id = db::insert( $dbh, 'calcms_projects', $project ); return $id; } -# delete project -sub delete{ - my $config=shift; - my $entry=shift; - - my $dbh=db::connect($config); - db::put($dbh, 'delete from calcms_projects where project_id=?', [$entry->{project_id}]); -} - # update project -sub update{ - my $config=shift; - my $project=shift; +sub update($$) { + my $config = shift; + my $project = shift; - my $columns=project::get_columns($config); - my $entry={}; - for my $column (keys %$columns){ - $entry->{$column}=$project->{$column} if defined $project->{$column}; + my $columns = project::get_columns($config); + my $entry = {}; + for my $column ( keys %$columns ) { + $entry->{$column} = $project->{$column} if defined $project->{$column}; } - my $values =join(",", map {$_.'=?'} (keys %$entry)); - my @bind_values =map {$entry->{$_}} (keys %$entry); - push @bind_values,$entry->{project_id}; + $entry->{image} = images::normalizeName( $entry->{image} ) if defined $entry->{image}; - my $query=qq{ + my @keys = sort keys %$entry; + my $values = join( ",", map { $_ . '=?' } @keys ); + my @bind_values = map { $entry->{$_} } @keys; + push @bind_values, $entry->{project_id}; + + my $query = qq{ update calcms_projects set $values where project_id=? }; - #print STDERR Dumper($query).Dumper(\@bind_values); - my $dbh=db::connect($config); - db::put($dbh, $query, \@bind_values); + my $dbh = db::connect($config); + db::put( $dbh, $query, \@bind_values ); } +# delete project +sub delete ($$) { + my $config = shift; + my $entry = shift; + + my $dbh = db::connect($config); + db::put( $dbh, 'delete from calcms_projects where project_id=?', [ $entry->{project_id} ] ); +} # get studios of a project -sub get_studios{ - my $config=shift; - my $options=shift; - - return undef unless defined $options->{project_id}; - my $project_id=$options->{project_id}; +sub get_studios($$) { + my $config = shift; + my $options = shift; - my $query=qq{ + return undef unless defined $options->{project_id}; + my $project_id = $options->{project_id}; + + my $query = qq{ select * from calcms_project_studios where project_id=? }; - my $dbh=db::connect($config); - my $project_studios=db::get($dbh,$query,[$project_id]); + my $dbh = db::connect($config); + my $project_studios = db::get( $dbh, $query, [$project_id] ); - return $project_studios; + return $project_studios; } -sub get_studio_assignments{ - my $config=shift; - my $options=shift; +sub get_studio_assignments($$) { + my $config = shift; + my $options = shift; - my @conditions=(); - my @bind_values=(); + my @conditions = (); + my @bind_values = (); - if ((defined $options->{project_id}) && ($options->{project_id} ne '')){ - push @conditions, 'project_id=?'; - push @bind_values, $options->{project_id}; - } + if ( ( defined $options->{project_id} ) && ( $options->{project_id} ne '' ) ) { + push @conditions, 'project_id=?'; + push @bind_values, $options->{project_id}; + } - if ((defined $options->{studio_id}) && ($options->{studio_id} ne '')){ - push @conditions, 'studio_id=?'; - push @bind_values, $options->{studio_id}; - } + if ( ( defined $options->{studio_id} ) && ( $options->{studio_id} ne '' ) ) { + push @conditions, 'studio_id=?'; + push @bind_values, $options->{studio_id}; + } - my $conditions=''; - $conditions=" where ".join(" and ",@conditions) if (@conditions>0); + my $conditions = ''; + $conditions = " where " . join( " and ", @conditions ) if ( @conditions > 0 ); - my $query=qq{ + my $query = qq{ select * from calcms_project_studios $conditions }; - my $dbh=db::connect($config); - my $results=db::get($dbh, $query, \@bind_values); + my $dbh = db::connect($config); + my $results = db::get( $dbh, $query, \@bind_values ); - return $results; + return $results; } # is studio assigned to project -sub is_studio_assigned{ - my $config=shift; - my $entry=shift; +sub is_studio_assigned ($$) { + my $config = shift; + my $entry = shift; - return 0 unless defined $entry->{project_id}; - return 0 unless defined $entry->{studio_id}; + return 0 unless defined $entry->{project_id}; + return 0 unless defined $entry->{studio_id}; - my $project_id=$entry->{project_id}; - my $studio_id= $entry->{studio_id}; + my $project_id = $entry->{project_id}; + my $studio_id = $entry->{studio_id}; - my $query=qq{ + my $query = qq{ select * from calcms_project_studios where project_id=? and studio_id=? }; - my $bind_values=[$project_id, $studio_id]; + my $bind_values = [ $project_id, $studio_id ]; - my $dbh=db::connect($config); - my $project_studios=db::get($dbh, $query, $bind_values); - return 1 if @$project_studios==1; - return 0; + my $dbh = db::connect($config); + my $project_studios = db::get( $dbh, $query, $bind_values ); + return 1 if scalar @$project_studios == 1; + return 0; } # assign studio to project -sub assign_studio{ - my $config=shift; - my $entry=shift; +sub assign_studio($$) { + my $config = shift; + my $entry = shift; - return undef unless defined $entry->{project_id}; - return undef unless defined $entry->{studio_id}; - my $project_id=$entry->{project_id}; - my $studio_id= $entry->{studio_id}; + return undef unless defined $entry->{project_id}; + return undef unless defined $entry->{studio_id}; + my $project_id = $entry->{project_id}; + my $studio_id = $entry->{studio_id}; - if (is_studio_assigned($entry)){ + if ( is_studio_assigned( $config, $entry ) ) { print STDERR "studio $entry->{studio_id} already assigned to project $entry->{project_id}\n"; return 1; } - my $dbh=db::connect($config); - my $id=db::insert($dbh, 'calcms_project_studios', $entry); + my $dbh = db::connect($config); + my $id = db::insert( $dbh, 'calcms_project_studios', $entry ); return $id; } # unassign studio from project -sub unassign_studio{ - my $config=shift; - my $entry=shift; - - return undef unless defined $entry->{project_id}; - return undef unless defined $entry->{studio_id}; - my $project_id=$entry->{project_id}; - my $studio_id= $entry->{studio_id}; +sub unassign_studio($$) { + my $config = shift; + my $entry = shift; - my $sql='delete from calcms_project_studios where project_id=? and studio_id=?'; - my $bind_values=[$project_id, $studio_id]; - my $dbh=db::connect($config); - return db::put($dbh, $sql, $bind_values); + return undef unless defined $entry->{project_id}; + return undef unless defined $entry->{studio_id}; + my $project_id = $entry->{project_id}; + my $studio_id = $entry->{studio_id}; + + my $sql = 'delete from calcms_project_studios where project_id=? and studio_id=?'; + my $bind_values = [ $project_id, $studio_id ]; + my $dbh = db::connect($config); + return db::put( $dbh, $sql, $bind_values ); } # get series by project and studio -sub get_series{ - my $config=shift; - my $options=shift; - - return undef unless defined $options->{project_id}; - return undef unless defined $options->{studio_id}; - my $project_id=$options->{project_id}; - my $studio_id= $options->{studio_id}; +sub get_series ($$) { + my $config = shift; + my $options = shift; - my $query=qq{ + return undef unless defined $options->{project_id}; + return undef unless defined $options->{studio_id}; + my $project_id = $options->{project_id}; + my $studio_id = $options->{studio_id}; + + my $query = qq{ select * from calcms_project_series where project_id=? and studio_id=? }; - my $bind_values=[$project_id, $studio_id]; - my $dbh=db::connect($config); - my $project_series=db::get($dbh, $query, $bind_values); + my $bind_values = [ $project_id, $studio_id ]; + my $dbh = db::connect($config); + my $project_series = db::get( $dbh, $query, $bind_values ); - return $project_series; + return $project_series; } -sub get_series_assignments{ - my $config=shift; - my $options=shift; +sub get_series_assignments ($$) { + my $config = shift; + my $options = shift; - my @conditions=(); - my @bind_values=(); + my @conditions = (); + my @bind_values = (); - if ((defined $options->{project_id}) && ($options->{project_id} ne '')){ - push @conditions, 'project_id=?'; - push @bind_values, $options->{project_id}; - } + if ( ( defined $options->{project_id} ) && ( $options->{project_id} ne '' ) ) { + push @conditions, 'project_id=?'; + push @bind_values, $options->{project_id}; + } - if ((defined $options->{studio_id}) && ($options->{studio_id} ne '')){ - push @conditions, 'studio_id=?'; - push @bind_values, $options->{studio_id}; - } + if ( ( defined $options->{studio_id} ) && ( $options->{studio_id} ne '' ) ) { + push @conditions, 'studio_id=?'; + push @bind_values, $options->{studio_id}; + } - if ((defined $options->{series_id}) && ($options->{series_id} ne '')){ - push @conditions, 'series_id=?'; - push @bind_values, $options->{series_id}; - } + if ( ( defined $options->{series_id} ) && ( $options->{series_id} ne '' ) ) { + push @conditions, 'series_id=?'; + push @bind_values, $options->{series_id}; + } - my $conditions=''; - $conditions=" where ".join(" and ",@conditions) if (@conditions>0); + my $conditions = ''; + $conditions = " where " . join( " and ", @conditions ) if ( @conditions > 0 ); - my $query=qq{ + my $query = qq{ select * from calcms_project_series $conditions }; - my $dbh=db::connect($config); - my $results=db::get($dbh, $query, \@bind_values); + my $dbh = db::connect($config); + my $results = db::get( $dbh, $query, \@bind_values ); - return $results; + return $results; } # is series assigned to project and studio -sub is_series_assigned{ - my $config=shift; - my $entry=shift; +sub is_series_assigned ($$) { + my $config = shift; + my $entry = shift; - return 0 unless defined $entry->{project_id}; - return 0 unless defined $entry->{studio_id}; - return 0 unless defined $entry->{series_id}; + return 0 unless defined $entry->{project_id}; + return 0 unless defined $entry->{studio_id}; + return 0 unless defined $entry->{series_id}; - my $project_id=$entry->{project_id}; - my $studio_id= $entry->{studio_id}; - my $series_id= $entry->{series_id}; + my $project_id = $entry->{project_id}; + my $studio_id = $entry->{studio_id}; + my $series_id = $entry->{series_id}; - my $query=qq{ + my $query = qq{ select * from calcms_project_series where project_id=? and studio_id=? and series_id=? }; - my $bind_values=[$project_id, $studio_id, $series_id]; + my $bind_values = [ $project_id, $studio_id, $series_id ]; - my $dbh=db::connect($config); - my $project_series=db::get($dbh,$query, $bind_values); - return 1 if @$project_series==1; - return 0; + my $dbh = db::connect($config); + my $project_series = db::get( $dbh, $query, $bind_values ); + return 1 if scalar @$project_series == 1; + return 0; } # assign series to project and studio -sub assign_series{ - my $config=shift; - my $entry=shift; +sub assign_series($$) { + my $config = shift; + my $entry = shift; - return undef unless defined $entry->{project_id}; - return undef unless defined $entry->{studio_id}; - return undef unless defined $entry->{series_id}; + return undef unless defined $entry->{project_id}; + return undef unless defined $entry->{studio_id}; + return undef unless defined $entry->{series_id}; - my $project_id=$entry->{project_id}; - my $studio_id= $entry->{studio_id}; - my $series_id= $entry->{series_id}; + my $project_id = $entry->{project_id}; + my $studio_id = $entry->{studio_id}; + my $series_id = $entry->{series_id}; - if (is_series_assigned($entry)){ + if ( is_series_assigned( $config, $entry ) ) { print STDERR "series $series_id already assigned to project $project_id and studio $studio_id\n"; return return undef; } - my $dbh=db::connect($config); - my $id=db::insert($dbh, 'calcms_project_series', $entry); - print STDERR "assigned series $series_id to project $project_id and studio $studio_id\n"; + my $dbh = db::connect($config); + my $id = db::insert( $dbh, 'calcms_project_series', $entry ); + print STDERR "assigned series $series_id to project $project_id and studio $studio_id\n"; return $id; } # unassign series from project # TODO: remove series _single_ if no event is assigned to -sub unassign_series{ - my $config=shift; - my $entry=shift; - - return undef unless defined $entry->{project_id}; - return undef unless defined $entry->{studio_id}; - return undef unless defined $entry->{series_id}; +sub unassign_series ($$) { + my $config = shift; + my $entry = shift; - my $project_id=$entry->{project_id}; - my $studio_id= $entry->{studio_id}; - my $series_id= $entry->{series_id}; + return undef unless defined $entry->{project_id}; + return undef unless defined $entry->{studio_id}; + return undef unless defined $entry->{series_id}; - my $sql='delete from calcms_project_series where project_id=? and studio_id=? and series_id=?'; - my $bind_values=[$project_id, $studio_id, $series_id]; - my $dbh=db::connect($config); - return db::put($dbh, $sql, $bind_values); + my $project_id = $entry->{project_id}; + my $studio_id = $entry->{studio_id}; + my $series_id = $entry->{series_id}; + + my $sql = 'delete from calcms_project_series where project_id=? and studio_id=? and series_id=?'; + my $bind_values = [ $project_id, $studio_id, $series_id ]; + my $dbh = db::connect($config); + return db::put( $dbh, $sql, $bind_values ); } -sub get_with_dates{ - my $config=shift; - my $options=shift; +sub get_with_dates($;$) { + my $config = shift; + my $options = shift; my $language = $config->{date}->{language} || 'en'; - my $projects=project::get($config, {}); + my $projects = project::get( $config, {} ); - foreach my $project (reverse sort { $a->{end_date} cmp $b->{end_date} } (@$projects) ){ - $project->{months} = get_months($config, $project, $language); - $project->{user} = $ENV{REMOTE_USER}; - $project->{current} = 1 if ($project->{name} eq $config::config->{project}); + foreach my $project ( reverse sort { $a->{end_date} cmp $b->{end_date} } (@$projects) ) { + $project->{months} = get_months( $config, $project, $language ); + $project->{user} = $ENV{REMOTE_USER}; + $project->{current} = 1 if ( $project->{name} eq $config->{project} ); } return $projects; } #TODO: add config -sub get_sorted{ - my $config=shift; - my $projects=project::get($config, {}); - my @projects=reverse sort { $a->{end_date} cmp $b->{end_date} } (@$projects); +sub get_sorted($) { + my $config = shift; + my $projects = project::get( $config, {} ); + my @projects = reverse sort { $a->{end_date} cmp $b->{end_date} } (@$projects); - unshift @projects,{ - name => 'all', - title => 'alle', - priority => '0', - start_date => $projects[-1]->{start_date}, - end_date => $projects[0]->{end_date}, - }; + unshift @projects, + { + name => 'all', + title => 'alle', + priority => '0', + start_date => $projects[-1]->{start_date}, + end_date => $projects[0]->{end_date}, + }; return \@projects; } # internal -sub get_months{ - my $config=shift; +sub get_months ($$;$) { + my $config = shift; my $project = shift; my $language = shift || $config->{date}->{language} || 'en'; - my $start = $project->{start_date}; - my $end = $project->{end_date}; + my $start = $project->{start_date}; + my $end = $project->{end_date}; - (my $start_year,my $start_month,my $start_day)=split(/\-/,$start); - my $last_day = Date::Calc::Days_in_Month($start_year,$start_month); - $start_day = 1 if ($start_day<1); - $start_day = $last_day if ($start_day gt $last_day); + ( my $start_year, my $start_month, my $start_day ) = split( /\-/, $start ); + my $last_day = Date::Calc::Days_in_Month( $start_year, $start_month ); + $start_day = 1 if ( $start_day < 1 ); + $start_day = $last_day if ( $start_day gt $last_day ); - (my $end_year,my $end_month,my $end_day)=split(/\-/,$end); - $last_day = Date::Calc::Days_in_Month($end_year,$end_month); - $end_day = 1 if ($end_day<1); - $end_day = $last_day if ($end_day gt $last_day); + ( my $end_year, my $end_month, my $end_day ) = split( /\-/, $end ); + $last_day = Date::Calc::Days_in_Month( $end_year, $end_month ); + $end_day = 1 if ( $end_day < 1 ); + $end_day = $last_day if ( $end_day gt $last_day ); - my @months=(); - for my $year($start_year..$end_year){ - my $m1=1; - my $m2=12; - $m1=$start_month if $year eq $start_year; - $m2=$end_month if $year eq $end_year; + my $monthNamesShort = time::getMonthNamesShort($language); + my @months = (); + for my $year ( $start_year .. $end_year ) { + my $m1 = 1; + my $m2 = 12; + $m1 = $start_month if $year eq $start_year; + $m2 = $end_month if $year eq $end_year; - for my $month($m1..$m2){ - my $d1=1; - my $d2=Date::Calc::Days_in_Month($year,$month); - $d1=$start_day if $month eq $start_month; - $d2=$end_day if $month eq $end_month; - push @months,{ - start => time::array_to_date($year,$month,$d1), - end => time::array_to_date($year,$month,$d2), + for my $month ( $m1 .. $m2 ) { + my $d1 = 1; + my $d2 = Date::Calc::Days_in_Month( $year, $month ); + $d1 = $start_day if $month eq $start_month; + $d2 = $end_day if $month eq $end_month; + push @months, + { + start => time::array_to_date( $year, $month, $d1 ), + end => time::array_to_date( $year, $month, $d2 ), year => $year, month => $month, - month_name => $time::names->{$language}->{months_abbr}->[$month-1], + month_name => $monthNamesShort->[ $month - 1 ], title => $project->{title}, user => $ENV{REMOTE_USER} - }; + }; } } - @months=reverse @months; + @months = reverse @months; return \@months; } # check project_id -sub check{ - my $config=shift; - my $options=shift; +sub check ($$) { + my $config = shift; + my $options = shift; return "missing project_id at checking project" unless defined $options->{project_id}; - return "Please select a project" if($options->{project_id}eq'-1'); - return "Please select a project" if($options->{project_id}eq''); - my $projects=project::get($config, { project_id=>$options->{project_id} } ); - return "Sorry. unknown project" unless defined $projects; + return "Please select a project" if ( $options->{project_id} eq '-1' ); + return "Please select a project" if ( $options->{project_id} eq '' ); + my $projects = project::get( $config, { project_id => $options->{project_id} } ); + return "Sorry. unknown project" unless defined $projects; return 1; } -sub error{ - my $msg=shift; - print "ERROR: $msg<br/>\n"; +sub error($) { + my $msg = shift; + print "ERROR: $msg<br/>\n"; } #do not delete last line! diff --git a/lib/calcms/projects.pm b/lib/calcms/projects.pm deleted file mode 100644 index 6630b3e..0000000 --- a/lib/calcms/projects.pm +++ /dev/null @@ -1,8 +0,0 @@ -use warnings "all"; -use strict; - -package projects; - -print STDERR "projects.pm is not used anymore!\n"; -#do not delete last line! -1; diff --git a/lib/calcms/roles.pm b/lib/calcms/roles.pm index 2ee7a48..eb3f1a6 100644 --- a/lib/calcms/roles.pm +++ b/lib/calcms/roles.pm @@ -1,146 +1,162 @@ package roles; -use Apache2::Reload; -require Exporter; -my @ISA = qw(Exporter); -my @EXPORT_OK = qw($roles get_user get_user_permissions get_template_parameters); -my %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ] ); -our $roles={ - 'admin' => { - access_events => 1, - access_images => 1, - access_comments => 1, - access_sync => 1, - access_system => 1, - read_event_all => 1, - create_event => 1, - delete_event => 1, - update_comment => 1, - create_image => 1, - read_image_own => 1, - read_image_all => 1, - update_image_own => 1, - update_image_all => 1, - delete_image_own => 1, - delete_image_all => 1, - sync_own => 1, - sync_all => 1, - sync_select_range => 1, - upload_playlist => 1, - }, - 'dev' => { - access_events => 1, - access_images => 1, - access_comments => 1, - access_sync => 1, - access_system => 0, - read_event_all => 1, - create_event => 1, - delete_event => 1, - update_comment => 1, - create_image => 1, - read_image_own => 1, - read_image_all => 1, - update_image_own => 1, - update_image_all => 1, - delete_image_own => 1, - delete_image_all => 1, - sync_own => 0, - sync_all => 1, - sync_select_range => 1, - upload_playlist => 1, - }, - 'editor' => { - access_events => 1, - access_images => 1, - access_comments => 1, - access_sync => 1, - access_system => 0, - read_event_all => 0, - create_event => 1, - delete_event => 0, - update_comment => 0, - create_image => 1, - read_image_own => 1, - read_image_all => 1, - update_image_own => 1, - update_image_all => 0, - delete_image_own => 1, - delete_image_all => 0, - sync_own => 1, - sync_all => 0, - sync_select_range => 0, - upload_playlist => 1, - }, - 'nobody' => { - access_events => 0, - access_images => 0, - access_comments => 0, - access_sync => 0, - access_system => 0, - read_event_all => 0, - create_event => 0, - delete_event => 0, - update_comment => 0, - create_image => 0, - read_image_own => 0, - read_image_all => 0, - update_image_own => 0, - update_image_all => 0, - delete_image_own => 0, - delete_image_all => 0, - sync_own => 0, - sync_all => 0, - sync_select_range => 0, - upload_playlist => 0, - } +use strict; +use warnings; +no warnings 'redefine'; + +use Apache2::Reload(); + +use config(); + +#use base 'Exporter'; +my @EXPORT_OK = qw(get_user get_user_permissions get_template_parameters get_jobs); + +my $ROLES = { + 'admin' => { + access_events => 1, + access_images => 1, + access_comments => 1, + access_sync => 1, + access_system => 1, + read_event_all => 1, + create_event => 1, + delete_event => 1, + update_comment => 1, + create_image => 1, + read_image_own => 1, + read_image_all => 1, + update_image_own => 1, + update_image_all => 1, + delete_image_own => 1, + delete_image_all => 1, + sync_own => 1, + sync_all => 1, + sync_select_range => 1, + upload_playlist => 1, + }, + 'dev' => { + access_events => 1, + access_images => 1, + access_comments => 1, + access_sync => 1, + access_system => 0, + read_event_all => 1, + create_event => 1, + delete_event => 1, + update_comment => 1, + create_image => 1, + read_image_own => 1, + read_image_all => 1, + update_image_own => 1, + update_image_all => 1, + delete_image_own => 1, + delete_image_all => 1, + sync_own => 0, + sync_all => 1, + sync_select_range => 1, + upload_playlist => 1, + }, + 'editor' => { + access_events => 1, + access_images => 1, + access_comments => 1, + access_sync => 1, + access_system => 0, + read_event_all => 0, + create_event => 1, + delete_event => 0, + update_comment => 0, + create_image => 1, + read_image_own => 1, + read_image_all => 1, + update_image_own => 1, + update_image_all => 0, + delete_image_own => 1, + delete_image_all => 0, + sync_own => 1, + sync_all => 0, + sync_select_range => 0, + upload_playlist => 1, + }, + 'nobody' => { + access_events => 0, + access_images => 0, + access_comments => 0, + access_sync => 0, + access_system => 0, + read_event_all => 0, + create_event => 0, + delete_event => 0, + update_comment => 0, + create_image => 0, + read_image_own => 0, + read_image_all => 0, + update_image_own => 0, + update_image_all => 0, + delete_image_own => 0, + delete_image_all => 0, + sync_own => 0, + sync_all => 0, + sync_select_range => 0, + upload_playlist => 0, + } }; -sub get_user{ - my $user= $ENV{REMOTE_USER}; - my $users=$config::config->{users}; - return $user if (defined $users->{$user}); - return 'nobody'; +sub get_user($) { + my $config = shift; + + my $user = $ENV{REMOTE_USER}; + my $users = $config->{users}; + return $user if defined $users->{$user}; + return 'nobody'; } -sub get_user_permissions{ - my $user= $ENV{REMOTE_USER}||''; - return $roles::roles->{nobody} unless ($user=~/\S/); - my $users=$config::config->{users}; - if (defined $users->{$user}){ - my $role=$users->{$user}; - if (defined $roles::roles->{$role}){ - return $roles::roles->{$role}; - } - } - return $roles::roles->{nobody}; +sub get_user_permissions($) { + my $config = shift; + + my $user = $ENV{REMOTE_USER} || ''; + my $roles = $roles::ROLES; + return $roles->{nobody} unless $user =~ /\S/; + my $users = $config->{users}; + if ( defined $users->{$user} ) { + my $role = $users->{$user}; + return $roles->{$role} if defined $roles->{$role}; + } + return $roles->{nobody}; } -sub get_user_jobs{ - my $user= $ENV{REMOTE_USER}||''; - return [] unless($user =~/\S/); - my $result=[]; - my $jobs=$config::config->{jobs}->{job}; - - for my $job (@$jobs){ - for my $job_user (split /\,/,$job->{users}){ - push @$result,$job if ($user eq $job_user); - } - } - return $result; +sub get_user_jobs ($;$) { + my $config = shift; + + my $user = $ENV{REMOTE_USER} || ''; + return [] unless ( $user =~ /\S/ ); + my $result = []; + my $jobs = $config->{jobs}->{job}; + + for my $job (@$jobs) { + for my $job_user ( split /\,/, $job->{users} ) { + push @$result, $job if ( $user eq $job_user ); + } + } + return $result; } -sub get_jobs{ - return $config::config->{jobs}->{job}; +sub get_jobs($) { + my $config = shift; + + return $config->{jobs}->{job}; } -sub get_template_parameters{ - my $user_permissions=shift; - $user_permissions=roles::get_user_permissions() unless(defined $user_permissions); - my @user_permissions=(); - for my $usecase (keys %$user_permissions){ - push @user_permissions, $usecase if ($user_permissions->{$usecase}eq'1'); - } - return \@user_permissions; +sub get_template_parameters($$) { + my $config = shift; + my $user_permissions = shift; + + $user_permissions = roles::get_user_permissions($config) unless defined $user_permissions; + my @user_permissions = (); + for my $usecase ( keys %$user_permissions ) { + push @user_permissions, $usecase if $user_permissions->{$usecase} eq '1'; + } + return \@user_permissions; } +return 1; diff --git a/lib/calcms/series.pm b/lib/calcms/series.pm index 97275c4..1ece629 100644 --- a/lib/calcms/series.pm +++ b/lib/calcms/series.pm @@ -1,114 +1,110 @@ -package series; +package series; -use warnings "all"; use strict; -use Data::Dumper; -use events; +use warnings; +no warnings 'redefine'; -require Exporter; -our @ISA = qw(Exporter); +use Data::Dumper; + +use events(); +use images(); + +#use base 'Exporter'; our @EXPORT_OK = qw( - get_columns get insert update delete - get_users add_user remove_user - get_events get_event get_next_episode search_events - get_event_age is_event_older_than_days - get_images - assign_event unassign_event - add_series_ids_to_events set_event_ids - can_user_update_events can_user_create_events - is_series_assigned_to_user is_event_assigned_to_user - update_recurring_events update_recurring_event + get_columns get insert update delete + get_users add_user remove_user + get_events get_event get_next_episode search_events + get_event_age is_event_older_than_days + get_images + assign_event unassign_event + add_series_ids_to_events set_event_ids + can_user_update_events can_user_create_events + is_series_assigned_to_user is_event_assigned_to_user + update_recurring_events update_recurring_event ); -our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ] ); #TODO: remove studio_id #TODO: get project_id, studio_id by join with project_series -sub debug; - # get series columns -sub get_columns{ - my $config=shift; +sub get_columns ($) { + my $config = shift; - my $dbh=db::connect($config); - my $cols=db::get_columns($dbh, 'calcms_series'); - my $columns={}; - for my $col (@$cols){ - $columns->{$col}=1; - } - return $columns; + my $dbh = db::connect($config); + return db::get_columns_hash( $dbh, 'calcms_series' ); } # get series content -sub get{ - my $config=shift; - my $condition=shift; +sub get ($$) { + my $config = shift; + my $condition = shift; - my @conditions=(); - my @bind_values=(); + my @conditions = (); + my @bind_values = (); - if ((defined $condition->{series_id}) && ($condition->{series_id} ne '')){ - push @conditions, 'id=?'; - push @bind_values, $condition->{series_id}; - } + if ( ( defined $condition->{series_id} ) && ( $condition->{series_id} ne '' ) ) { + push @conditions, 'id=?'; + push @bind_values, $condition->{series_id}; + } - if ((defined $condition->{series_name}) && ($condition->{series_name} ne '')){ - push @conditions, 'series_name=?'; - push @bind_values, $condition->{series_name}; - } + if ( defined $condition->{series_name} ) { + push @conditions, 'series_name=?'; + push @bind_values, $condition->{series_name}; + } - if ((defined $condition->{title}) && ($condition->{title} ne '')){ - push @conditions, 'title=?'; - push @bind_values, $condition->{title}; - } + if ( defined $condition->{title} ) { + push @conditions, 'title=?'; + push @bind_values, $condition->{title}; + } - if ((defined $condition->{has_single_events}) && ($condition->{has_single_events} ne '')){ - push @conditions, 'has_single_events=?'; - push @bind_values, $condition->{has_single_events}; - } + if ( ( defined $condition->{has_single_events} ) && ( $condition->{has_single_events} ne '' ) ) { + push @conditions, 'has_single_events=?'; + push @bind_values, $condition->{has_single_events}; + } - my $search_cond=''; - if ((defined $condition->{search}) && ($condition->{search} ne'')){ - my $search=lc $condition->{search}; - $search=~s/[^a-z0-9\_\.\-\:\!öäüßÖÄÜ \&]/%/; - $search=~s/\%+/\%/; - $search=~s/^[\%\s]+//; - $search=~s/[\%\s]+$//; - if ($search ne ''){ - $search='%'.$search.'%'; - my @attr=('title', 'series_name', 'excerpt', 'category', 'content'); - push @conditions, "(".join(" or ", map {'lower('.$_.') like ?'} @attr ).")"; - for my $attr (@attr){ - push @bind_values,$search; - } - } - } + my $search_cond = ''; + if ( ( defined $condition->{search} ) && ( $condition->{search} ne '' ) ) { + my $search = lc $condition->{search}; + $search =~ s/[^a-z0-9\_\.\-\:\!öäüßÖÄÜ \&]/%/; + $search =~ s/\%+/\%/; + $search =~ s/^[\%\s]+//; + $search =~ s/[\%\s]+$//; + if ( $search ne '' ) { + $search = '%' . $search . '%'; + my @attr = ( 'title', 'series_name', 'excerpt', 'content' ); + push @conditions, "(" . join( " or ", map { 'lower(' . $_ . ') like ?' } @attr ) . ")"; + for my $attr (@attr) { + push @bind_values, $search; + } + } + } - my $query=''; - my $conditions=''; - - if ((defined $condition->{project_id}) || (defined $condition->{studio_id})){ - if ((defined $condition->{project_id}) && ($condition->{project_id} ne '')){ - push @conditions, 'ps.project_id=?'; - push @bind_values, $condition->{project_id}; - } + my $query = ''; + my $conditions = ''; - if ((defined $condition->{studio_id}) && ($condition->{studio_id} ne '')){ - push @conditions, 'ps.studio_id=?'; - push @bind_values, $condition->{studio_id}; - } + if ( ( defined $condition->{project_id} ) || ( defined $condition->{studio_id} ) ) { + if ( ( defined $condition->{project_id} ) && ( $condition->{project_id} ne '' ) ) { + push @conditions, 'ps.project_id=?'; + push @bind_values, $condition->{project_id}; + } + + if ( ( defined $condition->{studio_id} ) && ( $condition->{studio_id} ne '' ) ) { + push @conditions, 'ps.studio_id=?'; + push @bind_values, $condition->{studio_id}; + } push @conditions, 'ps.series_id=s.id'; - $conditions=" where ".join(" and ",@conditions) if (@conditions>0); - $query=qq{ + $conditions = " where " . join( " and ", @conditions ) if ( @conditions > 0 ); + $query = qq{ select * from calcms_series s, calcms_project_series ps $conditions order by has_single_events desc, series_name, title }; - }else{ + } else { + # simple query - $conditions=" where ".join(" and ",@conditions) if (@conditions>0); - $query=qq{ + $conditions = " where " . join( " and ", @conditions ) if ( @conditions > 0 ); + $query = qq{ select * from calcms_series $conditions @@ -116,911 +112,924 @@ sub get{ }; } - my $dbh=db::connect($config); - my $series=db::get($dbh, $query, \@bind_values); - #print STDERR Dumper(time()); - for my $serie (@$series){ - $serie->{series_id}=$serie->{id}; - delete $serie->{id}; - } - #print STDERR Dumper($series); - return $series; + my $dbh = db::connect($config); + my $series = db::get( $dbh, $query, \@bind_values ); + + for my $serie (@$series) { + $serie->{series_id} = $serie->{id}; + delete $serie->{id}; + } + return $series; } # insert series -sub insert{ - my $config=shift; - my $series=shift; +sub insert ($$) { + my $config = shift; + my $series = shift; - #print STDERR Dumper($series); - return undef unless defined $series->{project_id}; - return undef unless defined $series->{studio_id}; + return undef unless defined $series->{project_id}; + return undef unless defined $series->{studio_id}; - my $project_id=$series->{project_id}; - my $studio_id =$series->{studio_id}; + my $project_id = $series->{project_id}; + my $studio_id = $series->{studio_id}; - my $columns=series::get_columns($config); - - my $entry={}; - for my $column (keys %$columns){ - $entry->{$column}=$series->{$column} if defined $series->{$column}; + my $columns = series::get_columns($config); + my $entry = {}; + for my $column ( keys %$columns ) { + $entry->{$column} = $series->{$column} if defined $series->{$column}; } + $entry->{image} = images::normalizeName( $entry->{image} ) if defined $entry->{image}; - $entry->{created_at} = time::time_to_datetime(time()); - $entry->{modified_at}= time::time_to_datetime(time()); - #print STDERR Dumper($entry); + $entry->{created_at} = time::time_to_datetime( time() ); + $entry->{modified_at} = time::time_to_datetime( time() ); - my $dbh=db::connect($config); - my $series_id=db::insert($dbh, 'calcms_series', $entry); - - return undef unless defined $series_id; - - my $result=project::assign_series($config, { - project_id => $project_id, - studio_id => $studio_id, - series_id => $series_id - }); + my $dbh = db::connect($config); + my $series_id = db::insert( $dbh, 'calcms_series', $entry ); + + return undef unless defined $series_id; + + my $result = project::assign_series( + $config, + { + project_id => $project_id, + studio_id => $studio_id, + series_id => $series_id + } + ); return undef unless defined $result; return $series_id; } # update series -sub update{ - my $config=shift; - my $series=shift; +sub update ($$) { + my $config = shift; + my $series = shift; - return undef unless defined $series->{project_id}; - return undef unless defined $series->{studio_id}; - return undef unless defined $series->{series_id}; + return undef unless defined $series->{project_id}; + return undef unless defined $series->{studio_id}; + return undef unless defined $series->{series_id}; - my $columns=series::get_columns($config); - - my $entry={}; - for my $column (keys %$columns){ - $entry->{$column}=$series->{$column} if defined $series->{$column}; + my $columns = series::get_columns($config); + my $entry = {}; + for my $column ( keys %$columns ) { + $entry->{$column} = $series->{$column} if defined $series->{$column}; } - $entry->{id} = $series->{series_id}; - $entry->{modified_at}= time::time_to_datetime(time()); - my $values =join(",", map {$_.'=?'} (keys %$entry)); - my @bind_values =map {$entry->{$_}} (keys %$entry); - push @bind_values, $entry->{id}; + $entry->{image} = images::normalizeName( $entry->{image} ) if defined $entry->{image}; + $entry->{id} = $series->{series_id}; + $entry->{modified_at} = time::time_to_datetime( time() ); - my $query=qq{ - update calcms_series + my @keys = keys %$entry; + my $values = join( ",", map { $_ . '=?' } @keys ); + my @bind_values = map { $entry->{$_} } @keys; + push @bind_values, $entry->{id}; + + my $query = qq{ + update calcms_series set $values where id=? }; - #print STDERR Dumper($query).Dumper(\@bind_values); - - my $dbh=db::connect($config); - return db::put($dbh, $query, \@bind_values); + my $dbh = db::connect($config); + return db::put( $dbh, $query, \@bind_values ); } # delete series, its schedules and series dates # unassign its users and events -sub delete{ - my $config=shift; - my $series=shift; - - return undef unless defined $series->{project_id}; - return undef unless defined $series->{studio_id}; - return undef unless defined $series->{series_id}; +sub delete($$) { + my $config = shift; + my $series = shift; + + return undef unless defined $series->{project_id}; + return undef unless defined $series->{studio_id}; + return undef unless defined $series->{series_id}; my $project_id = $series->{project_id}; my $studio_id = $series->{studio_id}; my $series_id = $series->{series_id}; - unless(project::is_series_assigned($config, $series)==1){ + unless ( project::is_series_assigned( $config, $series ) == 1 ) { print STDERR "series is not assigned to project $project_id and studio $studio_id\n"; return undef; - }; + } my $query = undef; my $bind_values = undef; - my $dbh=db::connect($config); + my $dbh = db::connect($config); + + $bind_values = [ $project_id, $studio_id, $series_id ]; - $bind_values=[$project_id, $studio_id, $series_id]; #delete schedules - $query=qq{ + $query = qq{ delete from calcms_series_schedule where project_id=? and studio_id=? and series_id=? }; - db::put($dbh, $query, $bind_values); + db::put( $dbh, $query, $bind_values ); #delete series dates - $query=qq{ + $query = qq{ delete from calcms_series_dates where project_id=? and studio_id=? and series_id=? }; - db::put($dbh, $query, $bind_values); + db::put( $dbh, $query, $bind_values ); #unassign users series::remove_user( - $config, { - project_id => $project_id, - studio_id => $studio_id, - series_id => $series_id + $config, + { + project_id => $project_id, + studio_id => $studio_id, + series_id => $series_id } ); #unassign events - $bind_values=[$project_id, $studio_id, $series_id]; - $query=qq{ + $bind_values = [ $project_id, $studio_id, $series_id ]; + $query = qq{ delete from calcms_series_events where project_id=? and studio_id=? and series_id=? }; - #print '<pre>$query'.$query.Dumper($bind_values).'</pre>'; - db::put($dbh, $query, $bind_values); - - project::unassign_series($config, { - project_id => $project_id, - studio_id => $studio_id, - series_id => $series_id - }); - #delete series + db::put( $dbh, $query, $bind_values ); - my $series_assignments=project::get_series_assignments( - $config, { + project::unassign_series( + $config, + { + project_id => $project_id, + studio_id => $studio_id, series_id => $series_id } ); - if(@$series_assignments>1){ + + #delete series + + my $series_assignments = project::get_series_assignments( + $config, + { + series_id => $series_id + } + ); + if ( scalar @$series_assignments > 1 ) { print STDERR "do not delete series, due to assigned to other project or studio"; return; } - $bind_values=[$series_id]; - $query=qq{ - delete from calcms_series + $bind_values = [$series_id]; + $query = qq{ + delete from calcms_series where id=? }; - #print STDERR $query.$query.Dumper($bind_values); - db::put($dbh, $query, $bind_values); + + db::put( $dbh, $query, $bind_values ); } - # get users directly assigned to project, studio, series (editors) -sub get_users{ - my $config = shift; - my $condition = shift; - - my @conditions=(); - my @bind_values=(); +sub get_users ($$) { + my $config = shift; + my $condition = shift; - if ((defined $condition->{project_id}) && ($condition->{project_id} ne '')){ - push @conditions, 'us.project_id=?'; - push @bind_values, $condition->{project_id}; - } + my @conditions = (); + my @bind_values = (); - if ((defined $condition->{studio_id}) && ($condition->{studio_id} ne '')){ - push @conditions, 'us.studio_id=?'; - push @bind_values, $condition->{studio_id}; - } + if ( ( defined $condition->{project_id} ) && ( $condition->{project_id} ne '' ) ) { + push @conditions, 'us.project_id=?'; + push @bind_values, $condition->{project_id}; + } - if ((defined $condition->{series_id}) && ($condition->{series_id} ne '')){ - push @conditions, 'us.series_id=?'; - push @bind_values, $condition->{series_id}; - } + if ( ( defined $condition->{studio_id} ) && ( $condition->{studio_id} ne '' ) ) { + push @conditions, 'us.studio_id=?'; + push @bind_values, $condition->{studio_id}; + } - if ((defined $condition->{name}) && ($condition->{name} ne '')){ - push @conditions, 'u.name=?'; - push @bind_values, $condition->{name}; - } + if ( ( defined $condition->{series_id} ) && ( $condition->{series_id} ne '' ) ) { + push @conditions, 'us.series_id=?'; + push @bind_values, $condition->{series_id}; + } - my $conditions=''; - $conditions=" and ".join(" and ",@conditions) if (@conditions>0); + if ( ( defined $condition->{name} ) && ( $condition->{name} ne '' ) ) { + push @conditions, 'u.name=?'; + push @bind_values, $condition->{name}; + } - my $query=qq{ + my $conditions = ''; + $conditions = " and " . join( " and ", @conditions ) if ( @conditions > 0 ); + + my $query = qq{ select u.id, u.name, u.full_name, u.email, us.modified_by, us.modified_at - from calcms_users u, calcms_user_series us + from calcms_users u, calcms_user_series us where us.user_id=u.id $conditions }; - #print STDERR $query." ".Dumper(\@bind_values)."\n"; - my $dbh =db::connect($config); - my $result=db::get($dbh, $query, \@bind_values); - #print STDERR $query." ".Dumper($result)."\n"; - return $result; + + my $dbh = db::connect($config); + my $result = db::get( $dbh, $query, \@bind_values ); + + return $result; } # assign user to series -sub add_user{ - my $config = shift; - my $entry = shift; +sub add_user ($$) { + my $config = shift; + my $entry = shift; - return unless defined $entry->{project_id}; - return unless defined $entry->{studio_id}; - return unless defined $entry->{series_id}; - return unless defined $entry->{user_id}; - return unless defined $entry->{user}; + return unless defined $entry->{project_id}; + return unless defined $entry->{studio_id}; + return unless defined $entry->{series_id}; + return unless defined $entry->{user_id}; + return unless defined $entry->{user}; - my $query=qq{ - select id - from calcms_user_series + my $query = qq{ + select id + from calcms_user_series where project_id=? and studio_id=? and series_id=? and user_id=? }; - my $bind_values=[$entry->{project_id}, $entry->{studio_id}, $entry->{series_id}, $entry->{user_id}]; + my $bind_values = [ $entry->{project_id}, $entry->{studio_id}, $entry->{series_id}, $entry->{user_id} ]; - my $dbh =db::connect($config); - my $results=db::get($dbh, $query, $bind_values); - return unless (@$results==0); + my $dbh = db::connect($config); + my $results = db::get( $dbh, $query, $bind_values ); + return unless scalar @$results == 0; - $query=qq{ - insert calcms_user_series + $query = qq{ + insert calcms_user_series set project_id=?, studio_id=?, series_id=?, user_id=?, modified_by=?, modified_at=now() }; - $bind_values=[$entry->{project_id}, $entry->{studio_id}, $entry->{series_id}, $entry->{user_id}, $entry->{user}]; - db::put($dbh, $query, $bind_values); + $bind_values = + [ $entry->{project_id}, $entry->{studio_id}, $entry->{series_id}, $entry->{user_id}, $entry->{user} ]; + db::put( $dbh, $query, $bind_values ); } # remove user(s) from series. -sub remove_user{ - my $config = shift; - my $condition = shift; - - return unless(defined $condition->{project_id}); - return unless(defined $condition->{studio_id}); - return unless(defined $condition->{series_id}); +sub remove_user ($$) { + my $config = shift; + my $condition = shift; - my @conditions=(); - my @bind_values=(); + return unless defined $condition->{project_id}; + return unless defined $condition->{studio_id}; + return unless defined $condition->{series_id}; - if ((defined $condition->{project_id}) && ($condition->{project_id} ne '')){ - push @conditions, 'project_id=?'; - push @bind_values, $condition->{project_id}; - } + my @conditions = (); + my @bind_values = (); - if ((defined $condition->{studio_id}) && ($condition->{studio_id} ne '')){ - push @conditions, 'studio_id=?'; - push @bind_values, $condition->{studio_id}; - } + if ( ( defined $condition->{project_id} ) && ( $condition->{project_id} ne '' ) ) { + push @conditions, 'project_id=?'; + push @bind_values, $condition->{project_id}; + } - if ((defined $condition->{series_id}) && ($condition->{series_id} ne '')){ - push @conditions, 'series_id=?'; - push @bind_values, $condition->{series_id}; - } + if ( ( defined $condition->{studio_id} ) && ( $condition->{studio_id} ne '' ) ) { + push @conditions, 'studio_id=?'; + push @bind_values, $condition->{studio_id}; + } - if ((defined $condition->{user_id}) && ($condition->{user_id} ne '')){ - push @conditions, 'user_id=?'; - push @bind_values, $condition->{user_id}; - } + if ( ( defined $condition->{series_id} ) && ( $condition->{series_id} ne '' ) ) { + push @conditions, 'series_id=?'; + push @bind_values, $condition->{series_id}; + } - my $conditions=''; - $conditions=join(" and ",@conditions) if (@conditions>0); + if ( ( defined $condition->{user_id} ) && ( $condition->{user_id} ne '' ) ) { + push @conditions, 'user_id=?'; + push @bind_values, $condition->{user_id}; + } - my $query=qq{ - delete from calcms_user_series + my $conditions = ''; + $conditions = join( " and ", @conditions ) if ( @conditions > 0 ); + + my $query = qq{ + delete from calcms_user_series where $conditions }; - my $dbh =db::connect($config); - db::put($dbh, $query, \@bind_values); + my $dbh = db::connect($config); + db::put( $dbh, $query, \@bind_values ); } -#search events by series_name and title (for events not assigned yet) +#search events by series_name and title (for events not assigned yet) #TODO: add location -sub search_events{ +sub search_events ($$$) { my $config = shift; - my $request = shift; - my $options = shift; + my $request = shift; + my $options = shift; - my $series_name =$options->{series_name}||''; - my $title =$options->{title}||''; - return undef if(($series_name eq '') && ($title eq '') ); + my $series_name = $options->{series_name} || ''; + my $title = $options->{title} || ''; + return undef if ( $series_name eq '' ) && ( $title eq '' ); - $series_name=~s/[^a-zA-Z0-9 \-]+/\?/g; - $title =~s/[^a-zA-Z0-9 \-]+/\?/g; + $series_name =~ s/[^a-zA-Z0-9 \-]+/\?/g; + $title =~ s/[^a-zA-Z0-9 \-]+/\?/g; - $series_name=~s/\?+/\?/g; - $title =~s/\?+/\?/g; + $series_name =~ s/\?+/\?/g; + $title =~ s/\?+/\?/g; - my $params={ - series_name => $series_name, - title => $title, - template => 'no' - }; - if (defined $options){ - $params->{from_date} = $options->{from_date} if (defined $options->{from_date}); - $params->{till_date} = $options->{till_date} if (defined $options->{till_date}); - $params->{location} = $options->{location} if (defined $options->{location}); - $params->{limit} = $options->{limit} if (defined $options->{limit}); - $params->{archive} = $options->{archive} if (defined $options->{archive}); - $params->{get} = $options->{get} if (defined $options->{get}); - } + my $params = { + series_name => $series_name, + title => $title, + template => 'no' + }; + if ( defined $options ) { + $params->{from_date} = $options->{from_date} if defined $options->{from_date}; + $params->{till_date} = $options->{till_date} if defined $options->{till_date}; + $params->{location} = $options->{location} if defined $options->{location}; + $params->{limit} = $options->{limit} if defined $options->{limit}; + $params->{archive} = $options->{archive} if defined $options->{archive}; + $params->{get} = $options->{get} if defined $options->{get}; + } - my $checked_params=events::check_params($config, $params); - #print STDERR '<pre>'.Dumper($checked_params).'</pre>'; - my $request2={ - params=>{ - checked=>$checked_params - }, - config => $request->{config}, - permissions => $request->{permissions} - }; - #my $debug=1; - #print STDERR Dumper($request2->{params}); - my $events=events::get($config, $request2); - #print Dumper($events); - return $events; + my $checked_params = events::check_params( $config, $params ); + my $request2 = { + params => { + checked => $checked_params + }, + config => $request->{config}, + permissions => $request->{permissions} + }; + + my $events = events::get( $config, $request2 ); + return $events; } #get events (only assigned ones) by project_id,studio_id,series_id, -sub get_events{ - my $config=shift; - my $options=shift; +sub get_events ($$) { + my $config = shift; + my $options = shift; - #print STDERR Dumper($options); - return [] if defined ($options->{series_id}) && ($options->{series_id} <=0); + return [] if defined( $options->{series_id} ) && ( $options->{series_id} <= 0 ); - my @conditions=(); - my @bind_values=(); + my @conditions = (); + my @bind_values = (); - if(defined $options->{project_id}){ - push @conditions, 'se.project_id = ?'; - push @bind_values, $options->{project_id}; - } - if(defined $options->{studio_id}){ - push @conditions, 'se.studio_id = ?'; - push @bind_values, $options->{studio_id}; - } - if( (defined $options->{series_id}) && ($options->{series_id}=~/(\d+)/) ){ - push @bind_values, $1; - push @conditions, 'se.series_id = ?'; - } + if ( defined $options->{project_id} ) { + push @conditions, 'se.project_id = ?'; + push @bind_values, $options->{project_id}; + } + if ( defined $options->{studio_id} ) { + push @conditions, 'se.studio_id = ?'; + push @bind_values, $options->{studio_id}; + } + if ( ( defined $options->{series_id} ) && ( $options->{series_id} =~ /(\d+)/ ) ) { + push @bind_values, $1; + push @conditions, 'se.series_id = ?'; + } - if(defined $options->{event_id}){ - push @bind_values, $options->{event_id}; - push @conditions, 'e.id = ?'; - } + if ( defined $options->{event_id} ) { + push @bind_values, $options->{event_id}; + push @conditions, 'e.id = ?'; + } - if( (defined $options->{from_date}) && ($options->{from_date}=~/(\d\d\d\d\-\d\d\-\d\d)/) ){ - push @bind_values, $1; - push @conditions, 'e.start_date >= ?'; - } - if( (defined $options->{till_date}) && ($options->{till_date}=~/(\d\d\d\d\-\d\d\-\d\d)/) ){ - push @bind_values, $1; - push @conditions, 'e.start_date <= ?'; - } - if(defined $options->{location}){ - push @conditions, 'e.location = ?'; - push @bind_values, $options->{location}; - } + if ( ( defined $options->{from_date} ) && ( $options->{from_date} =~ /(\d\d\d\d\-\d\d\-\d\d)/ ) ) { + push @bind_values, $1; + push @conditions, 'e.start_date >= ?'; + } + if ( ( defined $options->{till_date} ) && ( $options->{till_date} =~ /(\d\d\d\d\-\d\d\-\d\d)/ ) ) { + push @bind_values, $1; + push @conditions, 'e.start_date <= ?'; + } + if ( defined $options->{location} ) { + push @conditions, 'e.location = ?'; + push @bind_values, $options->{location}; + } - if(defined $options->{draft}){ - push @conditions, 'e.draft = ?'; - push @bind_values, $options->{draft}; - } + if ( defined $options->{draft} ) { + push @conditions, 'e.draft = ?'; + push @bind_values, $options->{draft}; + } - my $conditions=''; - if (@conditions>0){ - $conditions=' and '.join(' and ', @conditions); - } - - my $limit=''; - if( (defined $options->{limit}) && ($limit=~/(\d+)/) ){ - $limit='limit '.$1; - } + my $conditions = ''; + if ( @conditions > 0 ) { + $conditions = ' where ' . join( ' and ', @conditions ); + } - my $query=qq{ - select * - ,date(start) start_date - ,date(end) end_date - ,weekday(start) weekday - ,weekofyear(start) week_of_year - ,dayofyear(start) day_of_year - ,start_date day - ,id event_id - ,location location - from calcms_series_events se, calcms_events e - where se.event_id = e.id - $conditions + my $limit = ''; + if ( ( defined $options->{limit} ) && ( $limit =~ /(\d+)/ ) ) { + $limit = 'limit ' . $1; + } + + my $query = qq{ + select se.*,e.* + ,date(start) start_date + ,date(end) end_date + ,weekday(start) weekday + ,weekofyear(start) week_of_year + ,dayofyear(start) day_of_year + ,start_date day + ,e.id event_id + ,ar.path path + from calcms_series_events se + inner join calcms_events e on se.event_id = e.id + left join calcms_audio_recordings ar on se.event_id=ar.event_id and ar.active=1 + $conditions order by start_date desc $limit }; - #print STDERR '<pre>'.$query.Dumper(\@bind_values).'</pre>'; - my $dbh=db::connect($config); - my $results=db::get($dbh, $query, \@bind_values); - $results=events::modify_results($dbh, $config, {base_url=>'', params=>{checked=>{template=>''}}}, $results); + my $dbh = db::connect($config); + my $results = db::get( $dbh, $query, \@bind_values ); + $results = events::modify_results( + $dbh, $config, + { + base_url => '', + params => { + checked => { + template => '', + set_no_listen_keys => ($options->{set_no_listen_keys}//'') ? 1:0 + } + } + }, + $results + ); #add studio id to events - my $studios=studios::get($config, $options); + my $studios = studios::get( $config, $options ); - my $studio_id_by_location={}; - for my $studio (@$studios){ - $studio_id_by_location->{$studio->{location}}=$studio->{id}; - } - for my $result (@$results){ - $result->{studio_id}=$studio_id_by_location->{$result->{location}}; + my $studio_id_by_location = {}; + for my $studio (@$studios) { + $studio_id_by_location->{ $studio->{location} } = $studio->{id}; + } + for my $result (@$results) { + $result->{studio_id} = $studio_id_by_location->{ $result->{location} }; } - #print STDERR Dumper($results); - return $results; + return $results; } # load event given by studio_id, series_id and event_id # helper for gui - errors are written to gui output # return undef on error -sub get_event{ - my $config=shift; - my $options=shift; +sub get_event ($$) { + my $config = shift; + my $options = shift; - my $project_id = $options->{project_id}||''; - my $studio_id = $options->{studio_id}||''; - my $series_id = $options->{series_id}||''; - my $event_id = $options->{event_id} ||''; - my $draft = $options->{draft} ||''; + my $project_id = $options->{project_id} || ''; + my $studio_id = $options->{studio_id} || ''; + my $series_id = $options->{series_id} || ''; + my $event_id = $options->{event_id} || ''; + my $draft = $options->{draft} || ''; - unless(defined($options->{allow_any})){ - if ($project_id eq''){ + unless ( defined $options->{allow_any} ) { + if ( $project_id eq '' ) { uac::print_error("missing project_id"); return undef; } - if ($studio_id eq''){ + if ( $studio_id eq '' ) { uac::print_error("missing studio_id"); return undef; } - if ($series_id eq''){ + if ( $series_id eq '' ) { uac::print_error("missing series_id"); return undef; } } - if ($event_id eq''){ + if ( $event_id eq '' ) { uac::print_error("missing event_id"); return undef; } - my $queryOptions={}; + my $queryOptions = {}; $queryOptions->{project_id} = $project_id if $project_id ne ''; - $queryOptions->{studio_id} = $studio_id if $studio_id ne ''; - $queryOptions->{series_id} = $series_id if $series_id ne ''; - $queryOptions->{event_id} = $event_id if $event_id ne ''; - $queryOptions->{draft} = $draft if $draft ne ''; + $queryOptions->{studio_id} = $studio_id if $studio_id ne ''; + $queryOptions->{series_id} = $series_id if $series_id ne ''; + $queryOptions->{event_id} = $event_id if $event_id ne ''; + $queryOptions->{draft} = $draft if $draft ne ''; - my $events=series::get_events($config, $queryOptions); + my $events = series::get_events( $config, $queryOptions ); - unless (defined $events){ + unless ( defined $events ) { uac::print_error("error on loading event"); return undef; } - if(@$events==0){ + if ( scalar(@$events) == 0 ) { uac::print_error("event not found"); return undef; } - if(@$events>1){ + if ( scalar(@$events) > 1 ) { print STDERR q{multiple assignments found for } - .q{project_id=}.$options->{project_id} - .q{, studio_id=}.$options->{studio_id} - .q{, series_id=}.$options->{series_id} - .q{, event_id=}.$options->{event_id} - ."\n"; + . q{project_id=} + . $options->{project_id} + . q{, studio_id=} + . $options->{studio_id} + . q{, series_id=} + . $options->{series_id} + . q{, event_id=} + . $options->{event_id} . "\n"; } - my $event=$events->[0]; + my $event = $events->[0]; return $event; } # get name and title of series and age in days ('days_over') -sub get_event_age{ - my $config=shift; - my $options=shift; +sub get_event_age($$) { + my $config = shift; + my $options = shift; - #print STDERR Dumper($options); - return undef unless defined $options->{project_id}; - return undef unless defined $options->{studio_id}; + return undef unless defined $options->{project_id}; + return undef unless defined $options->{studio_id}; - my @conditions=(); - my @bind_values=(); + my @conditions = (); + my @bind_values = (); - if( (defined $options->{project_id}) && ($options->{project_id}=~/(\d+)/) ){ - push @bind_values, $1; - push @conditions, 'ps.project_id = ?'; - } + if ( ( defined $options->{project_id} ) && ( $options->{project_id} =~ /(\d+)/ ) ) { + push @bind_values, $1; + push @conditions, 'ps.project_id = ?'; + } - if( (defined $options->{studio_id}) && ($options->{studio_id}=~/(\d+)/) ){ - push @bind_values, $1; - push @conditions, 'ps.studio_id = ?'; - } + if ( ( defined $options->{studio_id} ) && ( $options->{studio_id} =~ /(\d+)/ ) ) { + push @bind_values, $1; + push @conditions, 'ps.studio_id = ?'; + } - if( (defined $options->{series_id}) && ($options->{series_id}=~/(\d+)/) ){ - push @bind_values, $1; - push @conditions, 's.id = ?'; - } + if ( ( defined $options->{series_id} ) && ( $options->{series_id} =~ /(\d+)/ ) ) { + push @bind_values, $1; + push @conditions, 's.id = ?'; + } - if( (defined $options->{event_id}) && ($options->{event_id}=~/(\d+)/) ){ - push @bind_values, $1; - push @conditions, 'e.id = ?'; - } + if ( ( defined $options->{event_id} ) && ( $options->{event_id} =~ /(\d+)/ ) ) { + push @bind_values, $1; + push @conditions, 'e.id = ?'; + } - my $conditions=''; - if (@conditions>0){ - $conditions=join(' and ', @conditions); - } - my $query=qq{ - select s.id series_id, s.series_name, s.title, s.has_single_events has_single_events, (to_days(now())-to_days(max(e.start))) days_over + my $conditions = ''; + if ( @conditions > 0 ) { + $conditions = join( ' and ', @conditions ); + } + my $query = qq{ + select s.id series_id, s.series_name, s.title, s.has_single_events has_single_events, (to_days(now())-to_days(max(e.start))) days_over from calcms_project_series ps - left join calcms_series s on ps.series_id=s.id - left join calcms_series_events se on s.id=se.series_id + left join calcms_series s on ps.series_id=s.id + left join calcms_series_events se on s.id=se.series_id left join calcms_events e on e.id=se.event_id where $conditions - group by s.id + group by s.id order by has_single_events desc, days_over }; - - #print STDERR $query." ".Dumper(\@bind_values); - my $dbh=db::connect($config); - my $results=db::get($dbh, $query, \@bind_values); - for my $result (@$results){ - $result->{days_over}=0 unless defined $result->{days_over}; + my $dbh = db::connect($config); + my $results = db::get( $dbh, $query, \@bind_values ); + + for my $result (@$results) { + $result->{days_over} = 0 unless defined $result->{days_over}; } - return $results; + return $results; } # is event older than max_age days -sub is_event_older_than_days{ - my $config=shift; - my $options=shift; - #print STDERR Dumper($options); +sub is_event_older_than_days ($$) { + my $config = shift; + my $options = shift; - return 1 unless defined $options->{project_id}; - return 1 unless defined $options->{studio_id}; - return 1 unless defined $options->{series_id}; - return 1 unless defined $options->{event_id}; - return 1 unless defined $options->{max_age}; + return 1 unless defined $options->{project_id}; + return 1 unless defined $options->{studio_id}; + return 1 unless defined $options->{series_id}; + return 1 unless defined $options->{event_id}; + return 1 unless defined $options->{max_age}; - my $events=series::get_event_age($config, { - project_id => $options->{project_id}, - studio_id => $options->{studio_id}, - series_id => $options->{series_id}, - event_id => $options->{event_id} - }); + my $events = series::get_event_age( + $config, + { + project_id => $options->{project_id}, + studio_id => $options->{studio_id}, + series_id => $options->{series_id}, + event_id => $options->{event_id} + } + ); - if (scalar(@$events)==0){ - print STDERR "series_events::event_over_in_days: event $options->{event_id} is not assigned to project $options->{project_id}, studio $options->{studio_id}, series $options->{series_id}\n"; + if ( scalar(@$events) == 0 ) { + print STDERR +"series_events::event_over_in_days: event $options->{event_id} is not assigned to project $options->{project_id}, studio $options->{studio_id}, series $options->{series_id}\n"; return 1; } - my $event=$events->[0]; - #print STDERR Dumper($event); + my $event = $events->[0]; return 1 if $event->{days_over} > $options->{max_age}; return 0; } -sub get_next_episode{ - my $config=shift; - my $options=shift; +sub get_next_episode($$) { + my $config = shift; + my $options = shift; return 0 unless defined $options->{project_id}; return 0 unless defined $options->{studio_id}; return 0 unless defined $options->{series_id}; #return if episodes should not be counted for this series - my $query=q{ - select count_episodes + my $query = q{ + select count_episodes from calcms_series where id=? }; - my $bind_values=[$options->{series_id}]; - my $dbh=db::connect($config); - my $results=db::get($dbh, $query, $bind_values); - return 0 if (@$results != 1); - return 0 if ($results->[0]->{count_episodes}eq'0'); - #print STDERR Dumper($results); + my $bind_values = [ $options->{series_id} ]; + my $dbh = db::connect($config); + my $results = db::get( $dbh, $query, $bind_values ); + return 0 if ( @$results != 1 ); + return 0 if ( $results->[0]->{count_episodes} eq '0' ); - #get all - $query=q{ + #get all + $query = q{ select title,episode from calcms_events e, calcms_series_events se where se.project_id=? and se.studio_id=? and se.series_id=? and se.event_id=e.id }; - $bind_values=[$options->{project_id}, $options->{studio_id}, $options->{series_id}]; - $results=db::get($dbh, $query, $bind_values); - - my $max=0; - for my $result (@$results){ - if ($result->{title}=~/\#(\d+)/){ - my $value=$1; - $max=$value if $value>$max; + $bind_values = [ $options->{project_id}, $options->{studio_id}, $options->{series_id} ]; + $results = db::get( $dbh, $query, $bind_values ); + + my $max = 0; + for my $result (@$results) { + if ( $result->{title} =~ /\#(\d+)/ ) { + my $value = $1; + $max = $value if $value > $max; } next unless defined $result->{episode}; - $max=$result->{episode} if $result->{episode}>$max; + $max = $result->{episode} if $result->{episode} > $max; } - return $max+1; + return $max + 1; } -sub get_images{ - my $config=shift; - my $options=shift; +sub get_images ($$) { + my $config = shift; + my $options = shift; return undef unless defined $options->{project_id}; return undef unless defined $options->{studio_id}; return undef unless defined $options->{series_id}; #get images from all events of the series - my $dbh=db::connect($config); - my $events=series::get_events( $config, { - project_id => $options->{project_id}, - studio_id => $options->{studio_id}, - series_id => $options->{series_id} - }); - my $images={}; - my $found=0; - for my $event (@$events){ - my $image=$event->{image}; - $image=~s/.*\///; - $images->{$image}=1; - $found++; + my $dbh = db::connect($config); + my $events = series::get_events( + $config, + { + project_id => $options->{project_id}, + studio_id => $options->{studio_id}, + series_id => $options->{series_id} + } + ); + my $images = { + map { + my $image = $_->{image}; + $image =~ s/.*\///; + { $image => 1 }; + } @$events + }; + my $found = scalar(keys %$images); + + return undef if $found == 0; + + # get all images from database + my @cond = (); + my $bind_values = []; + for my $image ( keys %$images ) { + push @cond, 'filename=?'; + push @$bind_values, $image; } - - return undef if $found==0; - # get all images from database - my @cond=(); - my $bind_values=[]; - for my $image (keys %$images){ - push @cond, 'filename=?'; - push @$bind_values, $image; - } + my $where = ''; + if ( @cond > 0 ) { + $where = 'where ' . join( ' or ', @cond ); + } - my $where=''; - if (@cond>0){ - $where = 'where '.join (' or ', @cond); - } + my $limit = ''; + if ( ( defined $options->{limit} ) && ( $options->{limit} =~ /(\d+)/ ) ) { + $limit = ' limit ' . $1; + } - my $limit=''; - if ( (defined $options->{limit}) && ($options->{limit}=~/(\d+)/) ){ - $limit=' limit '.$1; - } - - my $query=qq{ + my $query = qq{ select * from calcms_images $where order by created_at desc $limit }; - #print STDERR Dumper($query).Dumper($bind_values); - my $results=db::get($dbh, $query, $bind_values); - #print STDERR @$results."\n"; - return $results; + my $results = db::get( $dbh, $query, $bind_values ); + return $results; } #assign event to series #TODO: manual assign needs to update automatic one -sub assign_event{ - my $config=shift; - my $entry=shift; - - #print STDERR Dumper($entry); - return undef unless defined $entry->{project_id}; - return undef unless defined $entry->{studio_id}; - return undef unless defined $entry->{series_id}; - return undef unless defined $entry->{event_id}; - $entry->{manual}=0 unless ((defined $entry->{manual})&&($entry->{manual}eq'1')); +sub assign_event($$) { + my $config = shift; + my $entry = shift; - my $conditions=''; - $conditions='and manual=1' if ($entry->{manual}eq'1'); + return undef unless defined $entry->{project_id}; + return undef unless defined $entry->{studio_id}; + return undef unless defined $entry->{series_id}; + return undef unless defined $entry->{event_id}; + $entry->{manual} = 0 unless ( defined $entry->{manual} ) && ( $entry->{manual} eq '1' ); - my $query=qq{ - select * from calcms_series_events + my $conditions = ''; + $conditions = 'and manual=1' if $entry->{manual} eq '1'; + + my $query = qq{ + select * from calcms_series_events where project_id=? and studio_id=? and series_id=? and event_id=? $conditions }; - my $bind_values=[$entry->{project_id}, $entry->{studio_id}, $entry->{series_id}, $entry->{event_id}]; - my $dbh=db::connect($config); - my $results=db::get($dbh, $query, $bind_values); + my $bind_values = [ $entry->{project_id}, $entry->{studio_id}, $entry->{series_id}, $entry->{event_id} ]; + my $dbh = db::connect($config); + my $results = db::get( $dbh, $query, $bind_values ); - if(@$results>1){ - print STDERR "multiple assignments of project_id=$entry->{project_id}, studio_id=$entry->{studio_id}, series_id=$entry->{series_id}, event_id=$entry->{event_id}\n"; + if ( scalar @$results > 1 ) { + print STDERR +"multiple assignments of project_id=$entry->{project_id}, studio_id=$entry->{studio_id}, series_id=$entry->{series_id}, event_id=$entry->{event_id}\n"; return; } - if(@$results==1){ - print STDERR "already assigned: project_id=$entry->{project_id}, studio_id=$entry->{studio_id}, series_id=$entry->{series_id}, event_id=$entry->{event_id}\n"; + if ( scalar @$results == 1 ) { + print STDERR +"already assigned: project_id=$entry->{project_id}, studio_id=$entry->{studio_id}, series_id=$entry->{series_id}, event_id=$entry->{event_id}\n"; return; } - $query=qq{ + $query = qq{ insert into calcms_series_events (project_id, studio_id, series_id, event_id, manual) values (?,?,?,?,?) }; - $bind_values=[$entry->{project_id}, $entry->{studio_id}, $entry->{series_id}, $entry->{event_id}, $entry->{manual}]; - #print STDERR '<pre>'.$query.Dumper($bind_values).'</pre>'; - return db::put($dbh, $query, $bind_values); + $bind_values = + [ $entry->{project_id}, $entry->{studio_id}, $entry->{series_id}, $entry->{event_id}, $entry->{manual} ]; + + return db::put( $dbh, $query, $bind_values ); } #unassign event from series -sub unassign_event{ - my $config=shift; - my $entry=shift; - - return unless defined $entry->{project_id}; - return unless defined $entry->{studio_id}; - return unless defined $entry->{series_id}; - return unless defined $entry->{event_id}; +sub unassign_event($$) { + my $config = shift; + my $entry = shift; - my $conditions=''; - $conditions='and manual=1' if ((defined $entry->{manual}) && ($entry->{manual}eq'1')); + return unless defined $entry->{project_id}; + return unless defined $entry->{studio_id}; + return unless defined $entry->{series_id}; + return unless defined $entry->{event_id}; - my $query=qq{ - delete from calcms_series_events - where project_id=? and studio_id=? and series_id=? and event_id=? + my $conditions = ''; + $conditions = 'and manual=1' if ( defined $entry->{manual} ) && ( $entry->{manual} eq '1' ); + + my $query = qq{ + delete from calcms_series_events + where project_id=? and studio_id=? and series_id=? and event_id=? $conditions }; - my $bind_values=[$entry->{project_id}, $entry->{studio_id}, $entry->{series_id}, $entry->{event_id}]; - #print STDERR '<pre>'.$query.Dumper($bind_values).'</pre>'; - my $dbh=db::connect($config); - return db::put($dbh, $query, $bind_values); -} + my $bind_values = [ $entry->{project_id}, $entry->{studio_id}, $entry->{series_id}, $entry->{event_id} ]; + my $dbh = db::connect($config); + return db::put( $dbh, $query, $bind_values ); +} # put series id to given events (for legacy handling) # used by calendar # TODO: optionally add project_id and studio_id to conditions -sub add_series_ids_to_events{ - my $config=shift; - my $events=shift; +sub add_series_ids_to_events ($$) { + my $config = shift; + my $events = shift; - #get event ids from given events - my @event_ids=(); - for my $event (@$events){ - push @event_ids, $event->{event_id}; - } + #get event ids from given events + my @event_ids = (); + for my $event (@$events) { + push @event_ids, $event->{event_id}; + } - return if (@event_ids==0); + return if scalar @event_ids == 0; - my @bind_values =@event_ids; - my $event_ids =join(',', map {'?'} @event_ids); + my @bind_values = @event_ids; + my $event_ids = join( ',', map { '?' } @event_ids ); - #query series ids - my $dbh=db::connect($config); - my $query=qq{ + #query series ids + my $dbh = db::connect($config); + my $query = qq{ select project_id, studio_id, series_id, event_id - from calcms_series_events + from calcms_series_events where event_id in ($event_ids) }; - my $results=db::get($dbh, $query, \@bind_values); - my @results=@$results; - return [] unless (@results>0); + my $results = db::get( $dbh, $query, \@bind_values ); + my @results = @$results; + return [] unless scalar @results > 0; - #build hash of series ids by event ids - my $assignments_by_event_id={}; - for my $entry (@$results){ - my $event_id=$entry->{event_id}; - $assignments_by_event_id->{$event_id}=$entry; - } - - #fill in ids into events - for my $event (@$events){ - my $event_id=$event->{event_id}; - my $assignment=$assignments_by_event_id->{$event_id}; - if (defined $assignment){ - $event->{project_id} = $assignment->{project_id}; - $event->{studio_id} = $assignment->{studio_id}; - $event->{series_id} = $assignment->{series_id}; + #build hash of series ids by event ids + my $assignments_by_event_id = {}; + for my $entry (@$results) { + my $event_id = $entry->{event_id}; + $assignments_by_event_id->{$event_id} = $entry; + } + + #fill in ids into events + for my $event (@$events) { + my $event_id = $event->{event_id}; + my $assignment = $assignments_by_event_id->{$event_id}; + if ( defined $assignment ) { + $event->{project_id} = $assignment->{project_id}; + $event->{studio_id} = $assignment->{studio_id}; + $event->{series_id} = $assignment->{series_id}; } - } + } } - # add event_ids to series and remove all event ids from series, not given event_ids # for scan only, used at series -sub set_event_ids{ - my $config=shift; - my $project_id=shift; - my $studio_id=shift; - my $serie=shift; - my $event_ids=shift; +sub set_event_ids ($$$$$) { + my $config = shift; + my $project_id = shift; + my $studio_id = shift; + my $serie = shift; + my $event_ids = shift; - my $serie_id=$serie->{series_id}; - return unless defined $project_id; - return unless defined $studio_id; - return unless defined $serie_id; - return unless defined $event_ids; + my $serie_id = $serie->{series_id}; + return unless defined $project_id; + return unless defined $studio_id; + return unless defined $serie_id; + return unless defined $event_ids; - #make lookup table from events - my $event_id_hash={}; - for my $event_id (@$event_ids){ - $event_id_hash->{$event_id}=1; - } + #make lookup table from events + my $event_id_hash = { map { $_ => 1 } @$event_ids }; - #get series_entries from db - #my $bind_names=join(',', (map { '?' } @$event_ids)); - my $query=qq{ + #get series_entries from db + #my $bind_names=join(',', (map { '?' } @$event_ids)); + my $query = qq{ select event_id from calcms_series_events - where project_id=? and studio_id=? and series_id=? + where project_id=? and studio_id=? and series_id=? }; - my $bind_values=[$project_id, $studio_id, $serie_id]; + my $bind_values = [ $project_id, $studio_id, $serie_id ]; - my $dbh=db::connect($config); - my $results=db::get($dbh, $query, $bind_values); + my $dbh = db::connect($config); + my $results = db::get( $dbh, $query, $bind_values ); - my $found={}; - #mark events found assigned to series - my $i=1; - for my $event (@$results){ - #print "found event $i: $event->{event_id}\n"; - $found->{$event->{event_id}}=1; - $i++; - } - #insert events from list, not found in db - for my $event_id (@$event_ids){ - #print "insert event_id $event_id\n"; - series::assign_event( - $config, { - project_id => $project_id, - studio_id => $studio_id, - series_id => $serie_id, - event_id => $event_id - } - ) unless ($found->{$event_id}); - } - #delete events found in db, but not in list - for my $event_id (keys %$found){ - #print "delete event_id $event_id\n"; - series::unassign_event( - $config, { - project_id => $project_id, - studio_id => $studio_id, - series_id => $serie_id, - event_id => $event_id, + #mark events found assigned to series + my $found = { map { $_->{event_id} => 1 } @$results }; + + #insert events from list, not found in db + for my $event_id (@$event_ids) { + + #print "insert event_id $event_id\n"; + series::assign_event( + $config, + { + project_id => $project_id, + studio_id => $studio_id, + series_id => $serie_id, + event_id => $event_id + } + ) unless ( $found->{$event_id} ); + } + + #delete events found in db, but not in list + for my $event_id ( keys %$found ) { + + #print "delete event_id $event_id\n"; + series::unassign_event( + $config, + { + project_id => $project_id, + studio_id => $studio_id, + series_id => $serie_id, + event_id => $event_id, manual => 0 } - ) unless (defined $event_id_hash->{$event_id}); - } + ) unless defined $event_id_hash->{$event_id}; + } } # check if user allowed to update series events # evaluate permissions and consider editors directly assigned to series -sub can_user_update_events{ - my $request=shift; - my $options=shift; +sub can_user_update_events ($$) { + my $request = shift; + my $options = shift; - my $config = $request->{config}; - my $permissions = $request->{permissions}; + my $config = $request->{config}; + my $permissions = $request->{permissions}; return 0 unless defined $request->{user}; return 0 unless defined $options->{project_id}; return 0 unless defined $options->{studio_id}; return 0 unless defined $options->{series_id}; - return 1 if ( (defined $permissions->{update_event_of_others}) && ($permissions->{update_event_of_others}eq'1')); - return 1 if ( (defined $permissions->{is_admin}) && ($permissions->{is_admin} eq'1')); - return 0 if ( $permissions->{update_event_of_series}ne'1'); + return 1 if ( defined $permissions->{update_event_of_others} ) && ( $permissions->{update_event_of_others} eq '1' ); + return 1 if ( defined $permissions->{is_admin} ) && ( $permissions->{is_admin} eq '1' ); + return 0 if $permissions->{update_event_of_series} ne '1'; - return is_series_assigned_to_user($request, $options); + return is_series_assigned_to_user( $request, $options ); } # check if user allowed to create series events # evaluate permissions and consider editors directly assigned to series -sub can_user_create_events{ - my $request=shift; - my $options=shift; +sub can_user_create_events ($$) { + my $request = shift; + my $options = shift; - my $config = $request->{config}; - my $permissions = $request->{permissions}; + my $config = $request->{config}; + my $permissions = $request->{permissions}; return 0 unless defined $request->{user}; return 0 unless defined $options->{project_id}; return 0 unless defined $options->{studio_id}; return 0 unless defined $options->{series_id}; - return 1 if ( (defined $permissions->{create_event}) && ($permissions->{create_event}eq'1')); - return 1 if ( (defined $permissions->{is_admin}) && ($permissions->{is_admin} eq'1')); - return 0 if ( $permissions->{create_event_of_series}ne'1'); + return 1 if ( defined $permissions->{create_event} ) && ( $permissions->{create_event} eq '1' ); + return 1 if ( defined $permissions->{is_admin} ) && ( $permissions->{is_admin} eq '1' ); + return 0 if $permissions->{create_event_of_series} ne '1'; - return is_series_assigned_to_user($request, $options); + return is_series_assigned_to_user( $request, $options ); } -sub is_series_assigned_to_user{ - my $request=shift; - my $options=shift; +sub is_series_assigned_to_user ($$) { + my $request = shift; + my $options = shift; - my $config = $request->{config}; - my $permissions = $request->{permissions}; + my $config = $request->{config}; + my $permissions = $request->{permissions}; return 0 unless defined $options->{project_id}; return 0 unless defined $options->{studio_id}; @@ -1028,24 +1037,25 @@ sub is_series_assigned_to_user{ return 0 unless defined $request->{user}; my $series_users = series::get_users( - $config, { + $config, + { project_id => $options->{project_id}, - studio_id => $options->{studio_id}, + studio_id => $options->{studio_id}, series_id => $options->{series_id}, name => $request->{user} } ); - return 0 if (@$series_users==0); + return 0 if scalar @$series_users == 0; return 1; } # check if user is assigned to studio where location matchs to event # return 1 on success or error text -sub is_event_assigned_to_user{ - my $request=shift; - my $options=shift; +sub is_event_assigned_to_user ($$) { + my $request = shift; + my $options = shift; - my $config = $request->{config}; + my $config = $request->{config}; return "missing user" unless defined $request->{user}; return "missing project_id" unless defined $options->{project_id}; @@ -1054,164 +1064,218 @@ sub is_event_assigned_to_user{ return "missing event_id" unless defined $options->{event_id}; #check roles - my $user_studios=uac::get_studios_by_user( - $config, { - project_id => $options->{project_id}, - studio_id => $options->{studio_id}, - user => $request->{user}, - } - ); - return "user is not assigned to studio" if @$user_studios==0; - my $studio=$user_studios->[0]; - my $location=$studio->{location}; - return "could not get studio location" if $location eq''; + my $user_studios = uac::get_studios_by_user( + $config, + { + project_id => $options->{project_id}, + studio_id => $options->{studio_id}, + user => $request->{user}, + } + ); + return "user is not assigned to studio" if scalar @$user_studios == 0; + my $studio = $user_studios->[0]; + my $location = $studio->{location}; + return "could not get studio location" if $location eq ''; #TODO: replace legacy support - my $events=series::get_events( - $config, { - project_id => $options->{project_id}, - studio_id => $options->{studio_id}, + my $events = series::get_events( + $config, + { + project_id => $options->{project_id}, + studio_id => $options->{studio_id}, series_id => $options->{series_id}, event_id => $options->{event_id}, - location => $location, - limit => 1 - } - ); - #print STDERR Dumper(@$events); - return "no event found for" - ." project $options->{project_id}," - ." studio $options->{studio_id}," - ." location $location," - ." series $options->{series_id}" - ." and event $options->{event_id}" if @$events==0; - return 1; + location => $location, + limit => 1 + } + ); + + return + "no event found for" + . " project $options->{project_id}," + . " studio $options->{studio_id}," + . " location $location," + . " series $options->{series_id}" + . " and event $options->{event_id}" + if scalar @$events == 0; + return 1; } -# to find multiple recurrences this does not include the recurrence_count +sub get_rebuilt_episodes ($$) { + my $config = shift; + my $options = shift; + + return "missing project_id" unless defined $options->{project_id}; + return "missing studio_id" unless defined $options->{studio_id}; + return "missing series_id" unless defined $options->{series_id}; + + # ignore project and studio as series can be used in multiple studios + my $events = series::get_events( + $config, + { + #project_id => $options->{project_id}, + #studio_id => $options->{studio_id}, + series_id => $options->{series_id}, + draft => 0 + } + ); + @$events = sort { $a->{start} cmp $b->{start} } @$events; + + my $events_by_episode = {}; + for my $event (@$events) { + next unless $event->{episode}; + push @{ $events_by_episode->{$event->{episode}} }, $event; + } + + my $done={}; + my $episode = $events->[0]->{episode} // 0; + $episode-=1; + + for my $i (0..$#$events){ + my $event = $events->[$i]; + next if $done->{$event->{id}}; + $episode++; + # increase episode for not set values + if ( ($event->{episode}//'') eq ''){ + $event->{old_episode} = $event->{episode}; + $event->{episode} = $episode; + next; + } + # set new value to all episodes with same value + for my $event2 (@{$events_by_episode->{$event->{episode}}}){ + $event2->{old_episode} = $event2->{episode}; + $event2->{episode} = $episode; + $done->{$event2->{id}}=1; + }; + } + return $events; +} + +# to find multiple recurrences this does not include the recurrence_count # use events::get_key to add the recurrence -sub get_event_key{ - my $event=shift; - - my $program = $event->{program} || ''; +sub get_event_key ($) { + my $event = shift; + + my $program = $event->{program} || ''; my $series_name = $event->{series_name} || ''; - my $title = $event->{title} || ''; - my $user_title = $event->{user_title} || ''; - my $episode = $event->{episode} || ''; - - my $key=''; - $key.=$series_name if $series_name ne ''; - $key.=' - ' if ($series_name ne '') && ($title ne ''); - $key.=$title if $title ne ''; - $key.=': ' if ($title ne '') && ($user_title ne ''); - $key.=$user_title if $user_title ne ''; - $key.=' #'.$episode if $episode ne ''; + my $title = $event->{title} || ''; + my $user_title = $event->{user_title} || ''; + my $episode = $event->{episode} || ''; + + my $key = ''; + $key .= $series_name if $series_name ne ''; + $key .= ' - ' if ( $series_name ne '' ) && ( $title ne '' ); + $key .= $title if $title ne ''; + $key .= ': ' if ( $title ne '' ) && ( $user_title ne '' ); + $key .= $user_title if $user_title ne ''; + $key .= ' #' . $episode if $episode ne ''; return $key; } -sub update_recurring_events{ - my $config=shift; - my $options=shift; +sub update_recurring_events ($$) { + my $config = shift; + my $options = shift; return "missing project_id" unless defined $options->{project_id}; return "missing studio_id" unless defined $options->{studio_id}; return "missing series_id" unless defined $options->{series_id}; return "missing event_id" unless defined $options->{event_id}; - my $events=series::get_events( - $config, { - project_id => $options->{project_id}, - studio_id => $options->{studio_id}, + my $events = series::get_events( + $config, + { + #project_id => $options->{project_id}, + #studio_id => $options->{studio_id}, series_id => $options->{series_id}, draft => 0 - } - ); - @$events=sort { $a->{start} cmp $b->{start}} @$events; + } + ); + @$events = sort { $a->{start} cmp $b->{start} } @$events; # store events with recurrences by key (series_name, title, user_title, episode) - my $events_by_key={}; - for my $event (@$events){ - my $key=get_event_key($event); - next unless $key=~/\#\d+$/; - $event->{key}=$key; - push @{$events_by_key->{$key}}, $event; - } - - # handle all events with the same key - for my $key (keys %$events_by_key){ - my $events=$events_by_key->{$key}; - next unless scalar @$events >0; + my $events_by_key = {}; + for my $event (@$events) { + my $key = get_event_key($event); + next unless $key =~ /\#\d+$/; + $event->{key} = $key; + push @{ $events_by_key->{$key} }, $event; + } + + # handle all events with the same key + for my $key ( sort keys %$events_by_key ) { + my $events = $events_by_key->{$key}; + next unless scalar @$events > 0; + + if ( scalar @$events == 1 ) { - if(scalar @$events ==1){ # one event found -> check if recurrence is to be removed - my $event=$events->[0]; - next if $event->{recurrence}==0; - next if $event->{recurrence_count}==0; - print STDERR "remove recurrence\t'$event->{event_id}'\t'$event->{start}'\t'$event->{rerun}'\t'$event->{recurrence}'\t'$event->{key}'\n"; - $event->{recurrence}=0; - $event->{recurrence_count}=0; - $event->{rerun}=0; - series::update_recurring_event($config, $event); - - }elsif(scalar @$events >1){ + my $event = $events->[0]; + next if $event->{recurrence} == 0; + next if $event->{recurrence_count} == 0; + $event->{recurrence} = 0; + $event->{recurrence_count} = 0; + $event->{rerun} = 0; + series::update_recurring_event( $config, $event ); + + } elsif ( scalar @$events > 1 ) { + # multiple events found with same key # first event is the original - my $event=$events->[0]; + my $event = $events->[0]; my $originalId = $event->{event_id}; - print STDERR "0\t'$event->{recurrence_count}'\t'$event->{event_id}'\t'$event->{start}'\t'$event->{rerun}'\t'$event->{recurrence}'\t'$event->{key}'\n"; # succeeding events are reruns - for (my $c=1; $c < scalar(@$events); $c++){ - my $event=$events->[$c]; - print STDERR "$c\t'$event->{recurrence_count}'\t'$event->{event_id}'\t'$event->{start}'\t'$event->{rerun}'\t'$event->{recurrence}'\t'$event->{key}'\n"; + for ( my $c = 1 ; $c < scalar(@$events) ; $c++ ) { + my $event = $events->[$c]; - my $update=0; + my $update = 0; $update = 1 if $event->{recurrence} ne $originalId; $update = 1 if $event->{rerun} ne '1'; $update = 1 if $event->{recurrence_count} ne $c; next if $update == 0; - - $event->{recurrence}=$originalId; - $event->{recurrence_count}=$c; - $event->{rerun}=1; - series::update_recurring_event($config, $event); + + $event->{recurrence} = $originalId; + $event->{recurrence_count} = $c; + $event->{rerun} = 1; + series::update_recurring_event( $config, $event ); } } - } + } } -sub update_recurring_event{ - my $config=shift; - my $event =shift; - +sub update_recurring_event($$) { + my $config = shift; + my $event = shift; + return undef unless defined $event->{event_id}; return undef unless defined $event->{recurrence}; return undef unless defined $event->{recurrence_count}; return undef unless defined $event->{rerun}; - - return unless $event->{event_id}=~/^\d+$/; - return unless $event->{recurrence}=~/^\d+$/; - return unless $event->{recurrence_count}=~/^\d+$/; - return unless $event->{rerun}=~/^\d+$/; - my $bind_values=[]; - push @$bind_values, $event->{recurrence}; - push @$bind_values, $event->{recurrence_count}; - push @$bind_values, $event->{rerun}; - push @$bind_values, $event->{id}; + return unless $event->{event_id} =~ /^\d+$/; + return unless $event->{recurrence} =~ /^\d+$/; + return unless $event->{recurrence_count} =~ /^\d+$/; + return unless $event->{rerun} =~ /^\d+$/; - my $update_sql=qq{ + my $bind_values = []; + push @$bind_values, $event->{recurrence}; + push @$bind_values, $event->{recurrence_count}; + push @$bind_values, $event->{rerun}; + push @$bind_values, $event->{id}; + + my $update_sql = qq{ update calcms_events set recurrence=?, recurrence_count=?, rerun=? where id=? }; - #print STDERR $update_sql."\n".Dumper($bind_values)."\n"; - my $dbh=db::connect($config); - db::put($dbh, $update_sql, $bind_values); + + my $dbh = db::connect($config); + db::put( $dbh, $update_sql, $bind_values ); } -sub error{ - my $msg=shift; - print "ERROR: $msg<br/>\n"; +sub error($) { + my $msg = shift; + print "ERROR: $msg<br/>\n"; } #do not delete last line! diff --git a/lib/calcms/series_dates.pm b/lib/calcms/series_dates.pm index e6f5353..a7c308c 100644 --- a/lib/calcms/series_dates.pm +++ b/lib/calcms/series_dates.pm @@ -1,93 +1,85 @@ -package series_dates; +package series_dates; -use warnings "all"; use strict; +use warnings; +no warnings 'redefine'; + use Data::Dumper; -use Date::Calc; -use time; -use db; -use log; -use studio_timeslot_dates; -use series_schedule; +use Date::Calc(); +use time(); +use db(); +use log(); +use studio_timeslot_dates(); +use series_schedule(); # schedule dates for series_schedule # table: calcms_series_dates # columns: id, studio_id, series_id, start(datetime), end(datetime) # TODO: delete column schedule_id -require Exporter; -our @ISA = qw(Exporter); +#use base 'Exporter'; our @EXPORT_OK = qw(get_columns get insert update delete get_dates get_series); -our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ] ); -sub debug; +sub get_columns ($) { + my $config = shift; -sub get_columns{ - my $config=shift; - - my $dbh=db::connect($config); - my $cols=db::get_columns($dbh, 'calcms_series_dates'); - my $columns={}; - for my $col (@$cols){ - $columns->{$col}=1; - } - return $columns; + my $dbh = db::connect($config); + return db::get_columns_hash( $dbh, 'calcms_series_dates' ); } # get all series_dates for studio_id and series_id within given time range # calculate start_date, end_date, weeday, day from start and end(datetime) -sub get{ - my $config=shift; - my $condition=shift; +sub get ($;$) { + my $config = shift; + my $condition = shift; - my $dbh=db::connect($config); + my $dbh = db::connect($config); - my @conditions=(); - my @bind_values=(); + my @conditions = (); + my @bind_values = (); - if ((defined $condition->{project_id}) && ($condition->{project_id} ne '')){ - push @conditions, 'project_id=?'; - push @bind_values, $condition->{project_id}; - } + if ( ( defined $condition->{project_id} ) && ( $condition->{project_id} ne '' ) ) { + push @conditions, 'project_id=?'; + push @bind_values, $condition->{project_id}; + } + if ( ( defined $condition->{studio_id} ) && ( $condition->{studio_id} ne '' ) ) { + push @conditions, 'studio_id=?'; + push @bind_values, $condition->{studio_id}; + } - if ((defined $condition->{studio_id}) && ($condition->{studio_id} ne '')){ - push @conditions, 'studio_id=?'; - push @bind_values, $condition->{studio_id}; - } + if ( ( defined $condition->{series_id} ) && ( $condition->{series_id} ne '' ) ) { + push @conditions, 'series_id=?'; + push @bind_values, $condition->{series_id}; + } - if ((defined $condition->{series_id}) && ($condition->{series_id} ne '')){ - push @conditions, 'series_id=?'; - push @bind_values, $condition->{series_id}; - } + if ( ( defined $condition->{start_at} ) && ( $condition->{start_at} ne '' ) ) { + push @conditions, 'start=?'; + push @bind_values, $condition->{start_at}; + } - if ((defined $condition->{start_at}) && ($condition->{start_at} ne '')){ - push @conditions, 'start=?'; - push @bind_values, $condition->{start_at}; - } + if ( ( defined $condition->{from} ) && ( $condition->{from} ne '' ) ) { + push @conditions, 'start_date>=?'; + push @bind_values, $condition->{from}; + } - if ((defined $condition->{from}) && ($condition->{from} ne '')){ - push @conditions, 'start_date>=?'; - push @bind_values, $condition->{from}; - } + if ( ( defined $condition->{till} ) && ( $condition->{till} ne '' ) ) { + push @conditions, 'end_date<?'; + push @bind_values, $condition->{till}; + } - if ((defined $condition->{till}) && ($condition->{till} ne '')){ - push @conditions, 'end_date<?'; - push @bind_values, $condition->{till}; - } + if ( ( defined $condition->{schedule_id} ) && ( $condition->{schedule_id} ne '' ) ) { + push @conditions, 'id=?'; + push @bind_values, $condition->{schedule_id}; + } - if ((defined $condition->{schedule_id}) && ($condition->{schedule_id} ne '')){ - push @conditions, 'id=?'; - push @bind_values, $condition->{schedule_id}; - } + if ( ( defined $condition->{exclude} ) && ( $condition->{exclude} ne '' ) ) { + push @conditions, 'exclude=?'; + push @bind_values, $condition->{exclude}; + } - if ((defined $condition->{exclude}) && ($condition->{exclude} ne '')){ - push @conditions, 'exclude=?'; - push @bind_values, $condition->{exclude}; - } + my $conditions = ''; + $conditions = " where " . join( " and ", @conditions ) if ( @conditions > 0 ); - my $conditions=''; - $conditions=" where ".join(" and ",@conditions) if (@conditions>0); - - my $query=qq{ + my $query = qq{ select date(start) start_date ,date(end) end_date ,dayname(start) weekday @@ -104,128 +96,128 @@ sub get{ $conditions order by start }; - #print STDERR $query."\n"; - #print STDERR Dumper(\@bind_values); - my $entries=db::get($dbh, $query, \@bind_values); - for my $entry (@$entries){ - $entry->{weekday}=substr($entry->{weekday},0,2); - } - - return $entries; + my $entries = db::get( $dbh, $query, \@bind_values ); + for my $entry (@$entries) { + $entry->{weekday} = substr( $entry->{weekday}, 0, 2 ); + } + + return $entries; } #check if event is scheduled (on permission check) -sub is_event_scheduled{ - my $request=shift; - my $options=shift; +sub is_event_scheduled($$) { + my $request = shift; + my $options = shift; - return 0 unless defined $options->{project_id}; - return 0 unless defined $options->{studio_id}; - return 0 unless defined $options->{series_id}; - return 0 unless defined $options->{start_at}; + return 0 unless defined $options->{project_id}; + return 0 unless defined $options->{studio_id}; + return 0 unless defined $options->{series_id}; + return 0 unless defined $options->{start_at}; - my $config = $request->{config}; - my $schedules=series_dates::get( - $config, { - project_id => $options->{project_id}, - studio_id => $options->{studio_id}, - series_id => $options->{series_id}, - start_at => $options->{start_at} + my $config = $request->{config}; + my $schedules = series_dates::get( + $config, + { + project_id => $options->{project_id}, + studio_id => $options->{studio_id}, + series_id => $options->{series_id}, + start_at => $options->{start_at} } ); - return 0 if(@$schedules!=1); + return 0 if scalar @$schedules != 1; return 1; } - #get all series for given studio_id, time range and search -sub get_series{ - my $config=shift; - my $condition=shift; +sub get_series($;$) { + my $config = shift; + my $condition = shift; - my $date_range_include=0; - $date_range_include=1 if $condition->{date_range_include}==1; + my $date_range_include = 0; + $date_range_include = 1 + if ( defined $condition->{date_range_include} ) && ( $condition->{date_range_include} == 1 ); - my $dbh=db::connect($config); + my $dbh = db::connect($config); - my @conditions=(); - my @bind_values=(); + my @conditions = (); + my @bind_values = (); push @conditions, 'd.series_id=s.id'; -# push @conditions, 'd.studio_id=s.studio_id'; - if ((defined $condition->{project_id}) && ($condition->{project_id} ne '')){ - push @conditions, 'd.project_id=?'; - push @bind_values, $condition->{project_id}; - } + # push @conditions, 'd.studio_id=s.studio_id'; - if ((defined $condition->{studio_id}) && ($condition->{studio_id} ne '')){ - push @conditions, 'd.studio_id=?'; - push @bind_values, $condition->{studio_id}; - } + if ( ( defined $condition->{project_id} ) && ( $condition->{project_id} ne '' ) ) { + push @conditions, 'd.project_id=?'; + push @bind_values, $condition->{project_id}; + } - if ((defined $condition->{series_id}) && ($condition->{series_id} ne '')){ - push @conditions, 'd.series_id=?'; - push @bind_values, $condition->{series_id}; - } + if ( ( defined $condition->{studio_id} ) && ( $condition->{studio_id} ne '' ) ) { + push @conditions, 'd.studio_id=?'; + push @bind_values, $condition->{studio_id}; + } - if ((defined $condition->{start_at}) && ($condition->{start_at} ne '')){ - push @conditions, 'd.start=?'; - push @bind_values, $condition->{start_at}; - } + if ( ( defined $condition->{series_id} ) && ( $condition->{series_id} ne '' ) ) { + push @conditions, 'd.series_id=?'; + push @bind_values, $condition->{series_id}; + } - if ((defined $condition->{from}) && ($condition->{from} ne '')){ - if ($date_range_include==1){ - push @conditions, 'd.end_date>=?'; - push @bind_values, $condition->{from}; - }else{ - push @conditions, 'd.start_date>=?'; - push @bind_values, $condition->{from}; + if ( ( defined $condition->{start_at} ) && ( $condition->{start_at} ne '' ) ) { + push @conditions, 'd.start=?'; + push @bind_values, $condition->{start_at}; + } + + if ( ( defined $condition->{from} ) && ( $condition->{from} ne '' ) ) { + if ( $date_range_include == 1 ) { + push @conditions, 'd.end_date>=?'; + push @bind_values, $condition->{from}; + } else { + push @conditions, 'd.start_date>=?'; + push @bind_values, $condition->{from}; } - } + } - if ((defined $condition->{till}) && ($condition->{till} ne '')){ - if ($date_range_include==1){ - push @conditions, 'd.start_date<=?'; - push @bind_values, $condition->{till}; - }else{ - push @conditions, 'd.end_date<?'; - push @bind_values, $condition->{till}; + if ( ( defined $condition->{till} ) && ( $condition->{till} ne '' ) ) { + if ( $date_range_include == 1 ) { + push @conditions, 'd.start_date<=?'; + push @bind_values, $condition->{till}; + } else { + push @conditions, 'd.end_date<?'; + push @bind_values, $condition->{till}; } - } + } - if ((defined $condition->{schedule_id}) && ($condition->{schedule_id} ne '')){ - push @conditions, 'd.id=?'; - push @bind_values, $condition->{schedule_id}; - } + if ( ( defined $condition->{schedule_id} ) && ( $condition->{schedule_id} ne '' ) ) { + push @conditions, 'd.id=?'; + push @bind_values, $condition->{schedule_id}; + } - if ((defined $condition->{exclude}) && ($condition->{exclude} ne '')){ - push @conditions, 'd.exclude=?'; - push @bind_values, $condition->{exclude}; - } + if ( ( defined $condition->{exclude} ) && ( $condition->{exclude} ne '' ) ) { + push @conditions, 'd.exclude=?'; + push @bind_values, $condition->{exclude}; + } - my $search_cond=''; - if ((defined $condition->{search}) && ($condition->{search} ne'')){ - my $search=lc $condition->{search}; - $search=~s/[^a-z0-9\_\.\-\:\!öäüßÖÄÜ \&]/%/; - $search=~s/\%+/\%/; - $search=~s/^[\%\s]+//; - $search=~s/[\%\s]+$//; - if ($search ne ''){ - $search='%'.$search.'%'; - my @attr=('s.title', 's.series_name', 's.excerpt', 's.category', 's.content'); - push @conditions, "(".join(" or ", map {'lower('.$_.') like ?'} @attr ).")"; - for my $attr (@attr){ - push @bind_values,$search; - } - } - } + my $search_cond = ''; + if ( ( defined $condition->{search} ) && ( $condition->{search} ne '' ) ) { + my $search = lc $condition->{search}; + $search =~ s/[^a-z0-9\_\.\-\:\!öäüßÖÄÜ \&]/%/; + $search =~ s/\%+/\%/; + $search =~ s/^[\%\s]+//; + $search =~ s/[\%\s]+$//; + if ( $search ne '' ) { + $search = '%' . $search . '%'; + my @attr = ( 's.title', 's.series_name', 's.excerpt', 's.content' ); + push @conditions, "(" . join( " or ", map { 'lower(' . $_ . ') like ?' } @attr ) . ")"; + for my $attr (@attr) { + push @bind_values, $search; + } + } + } - my $conditions=''; - $conditions=" where ".join(" and ",@conditions) if (@conditions>0); + my $conditions = ''; + $conditions = " where " . join( " and ", @conditions ) if ( @conditions > 0 ); - my $query=qq{ + my $query = qq{ select date(d.start) start_date ,date(d.end) end_date ,dayname(d.start) weekday @@ -246,309 +238,339 @@ sub get_series{ order by start }; - my $entries=db::get($dbh, $query, \@bind_values); + my $entries = db::get( $dbh, $query, \@bind_values ); - for my $entry (@$entries){ - $entry->{weekday} = substr($entry->{weekday},0,2); - } + for my $entry (@$entries) { + $entry->{weekday} = substr( $entry->{weekday}, 0, 2 ); + } # add series schedule - $entries=series_dates::addSeriesScheduleAttributes($config, $entries); + $entries = series_dates::addSeriesScheduleAttributes( $config, $entries ); - return $entries; + return $entries; } -sub addSeriesScheduleAttributes{ - my $config=shift; - my $entries=shift; +sub addSeriesScheduleAttributes ($$) { + my $config = shift; + my $entries = shift; - my $scheduleIds={}; # get series schedule ids used at entries - for my $entry (@$entries){ - $scheduleIds->{$entry->{series_schedule_id}}=1; - } - my @scheduleIds=keys %$scheduleIds; - return $entries if scalar(@scheduleIds)==0; + my $scheduleIds = { map { $_->{series_schedule_id} => 1 } @$entries }; + my @scheduleIds = keys %$scheduleIds; + return $entries if scalar(@scheduleIds) == 0; # get schedules with schedule ids - my $schedules=series_schedule::get($config, { - schedule_ids => \@scheduleIds - }); + my $schedules = series_schedule::get( + $config, + { + schedule_ids => \@scheduleIds + } + ); # get schedules by id - my $scheduleById={}; - for my $schedule (@$schedules){ - $scheduleById->{$schedule->{schedule_id}}=$schedule; - } + my $scheduleById = {}; + for my $schedule (@$schedules) { + $scheduleById->{ $schedule->{schedule_id} } = $schedule; + } - for my $entry (@$entries){ - $entry->{frequency} = $scheduleById->{$entry->{series_schedule_id}}->{frequency}; - $entry->{period_type} = $scheduleById->{$entry->{series_schedule_id}}->{period_type}; + for my $entry (@$entries) { + $entry->{frequency} = $scheduleById->{ $entry->{series_schedule_id} }->{frequency}; + $entry->{period_type} = $scheduleById->{ $entry->{series_schedule_id} }->{period_type}; } return $entries; } - #update series dates for all schedules of a series and studio_id -sub update{ - my $config=shift; - my $entry=shift; +sub update($$) { + my $config = shift; + my $entry = shift; - return undef unless defined $entry->{project_id} ; - return undef unless defined $entry->{studio_id} ; - return undef unless defined $entry->{series_id} ; + return undef unless defined $entry->{project_id}; + return undef unless defined $entry->{studio_id}; + return undef unless defined $entry->{series_id}; - my $dbh=db::connect($config); + my $dbh = db::connect($config); - #delete all dates for series (by studio and series id) - series_dates::delete($config, $entry); + #delete all dates for series (by studio and series id) + series_dates::delete( $config, $entry ); - my $day_start=$config->{date}->{day_starting_hour}; + my $day_start = $config->{date}->{day_starting_hour}; - #get all schedules for series ordered by exclude, date - my $schedules=series_schedule::get($config, { - project_id => $entry->{project_id}, - studio_id => $entry->{studio_id}, - series_id => $entry->{series_id}, - }); - - #add scheduled series dates and remove exluded dates - my $series_dates={}; + #get all schedules for series ordered by exclude, date + my $schedules = series_schedule::get( + $config, + { + project_id => $entry->{project_id}, + studio_id => $entry->{studio_id}, + series_id => $entry->{series_id}, + } + ); + + #add scheduled series dates and remove exluded dates + my $series_dates = {}; #TODO:set schedules exclude to 0 if not 1 #insert all normal dates (not excludes) - for my $schedule (@$schedules){ - my $dates=get_schedule_dates($schedule, {exclude => 0}); - for my $date (@$dates){ - $date->{exclude}=0; - $series_dates->{$date->{start}}=$date; - #print STDERR Dumper($date)."\n" if ($date->{start} eq'2014-02-05 19:00:00'); - } - } - - #insert / overwrite all exlude dates - for my $schedule (@$schedules){ - my $dates=get_schedule_dates($schedule, {exclude => 1}); - for my $date (@$dates){ - $date->{exclude}=1; - $series_dates->{$date->{start}}=$date; - #print STDERR Dumper($date)."\n" if ($date->{start} eq'2014-02-05 19:00:00'); - } - } - - #print STDERR Dumper($series_dates->{'2014-02-05 19:00:00'}); - - my $request={ - config => $config - }; - - my $i=0; - my $j=0; - for my $date (keys %$series_dates){ - my $series_date=$series_dates->{$date}; - #insert date - my $entry={ - project_id => $entry->{project_id}, - studio_id => $entry->{studio_id}, - series_id => $entry->{series_id}, - series_schedule_id => $series_date->{series_schedule_id}, - start => $series_date->{start}, - end => $series_date->{end}, - exclude => $series_date->{exclude}, - }; - if(studio_timeslot_dates::can_studio_edit_events($config, $entry)==1){ # by studio_id, start, end - $entry->{start_date}= time::add_hours_to_datetime($entry->{start}, -$day_start); - $entry->{end_date}= time::add_hours_to_datetime($entry->{end}, -$day_start); - db::insert($dbh, 'calcms_series_dates', $entry); - #print STDERR "$entry->{start_date}\n"; - $i++; - }else{ - $j++; - #print STDERR Dumper($entry); + for my $schedule (@$schedules) { + my $dates = get_schedule_dates( $schedule, { exclude => 0 } ); + for my $date (@$dates) { + $date->{exclude} = 0; + $series_dates->{ $date->{start} } = $date; } } + + #insert / overwrite all exlude dates + for my $schedule (@$schedules) { + my $dates = get_schedule_dates( $schedule, { exclude => 1 } ); + for my $date (@$dates) { + $date->{exclude} = 1; + $series_dates->{ $date->{start} } = $date; + } + } + + my $request = { config => $config }; + + my $i = 0; + my $j = 0; + for my $date ( keys %$series_dates ) { + my $series_date = $series_dates->{$date}; + + #insert date + my $entry = { + project_id => $entry->{project_id}, + studio_id => $entry->{studio_id}, + series_id => $entry->{series_id}, + series_schedule_id => $series_date->{series_schedule_id}, + start => $series_date->{start}, + end => $series_date->{end}, + exclude => $series_date->{exclude}, + }; + if ( studio_timeslot_dates::can_studio_edit_events( $config, $entry ) == 1 ) { # by studio_id, start, end + $entry->{start_date} = time::add_hours_to_datetime( $entry->{start}, -$day_start ); + $entry->{end_date} = time::add_hours_to_datetime( $entry->{end}, -$day_start ); + db::insert( $dbh, 'calcms_series_dates', $entry ); + $i++; + } else { + $j++; + } + } + #print STDERR "$i series_dates updates\n"; - return $j." dates out of studio times, ".$i; + return $j . " dates out of studio times, " . $i; } -sub get_schedule_dates{ - my $schedule=shift; - my $options=shift; +sub get_schedule_dates($$) { + my $schedule = shift; + my $options = shift; - my $is_exclude=$options->{exclude}||0; - my $dates=[]; - return $dates if (($is_exclude eq'1') && ($schedule->{exclude}ne'1')); - return $dates if (($is_exclude eq'0') && ($schedule->{exclude}eq'1')); + my $is_exclude = $options->{exclude} || 0; + my $dates = []; + return $dates if ( $is_exclude eq '1' ) && ( $schedule->{exclude} ne '1' ); + return $dates if ( $is_exclude eq '0' ) && ( $schedule->{exclude} eq '1' ); - if ($schedule->{period_type}eq'single'){ - $dates=get_single_date($schedule->{start}, $schedule->{duration}) ; - }elsif($schedule->{period_type}eq'days'){ - $dates=get_dates($schedule->{start}, $schedule->{end}, $schedule->{duration}, $schedule->{frequency}) ; - }elsif($schedule->{period_type}eq'week_of_month'){ - $dates=get_week_of_month_dates($schedule->{start}, $schedule->{end}, $schedule->{duration}, $schedule->{week_of_month}, $schedule->{weekday}, $schedule->{month}, $schedule->{nextDay}); - }else{ + if ( $schedule->{period_type} eq 'single' ) { + $dates = get_single_date( $schedule->{start}, $schedule->{duration} ); + } elsif ( $schedule->{period_type} eq 'days' ) { + $dates = get_dates( $schedule->{start}, $schedule->{end}, $schedule->{duration}, $schedule->{frequency} ); + } elsif ( $schedule->{period_type} eq 'week_of_month' ) { + $dates = get_week_of_month_dates( + $schedule->{start}, $schedule->{end}, $schedule->{duration}, $schedule->{week_of_month}, + $schedule->{weekday}, $schedule->{month}, $schedule->{nextDay} + ); + } else { print STDERR "unknown schedule period_type\n"; } # set series schedule id - for my $date (@$dates){ - $date->{series_schedule_id}=$schedule->{schedule_id}; + for my $date (@$dates) { + $date->{series_schedule_id} = $schedule->{schedule_id}; } return $dates; } +sub get_week_of_month_dates ($$$$$$$) { + my $start = shift; # datetime string + my $end = shift; # datetime string + my $duration = shift; # in minutes + my $week = shift; # every nth week of month + my $weekday = shift; # weekday [1..7] + my $frequency = shift; # every 1st,2nd,3th time + my $nextDay = shift; # add 24 hours to start, (for night hours at last weekday of month) -sub get_week_of_month_dates{ - my $start =shift; # datetime string - my $end =shift; # datetime string - my $duration =shift; # in minutes - my $week =shift; # every nth week of month - my $weekday =shift; # weekday [1..7] - my $frequency =shift; # every 1st,2nd,3th time - my $nextDay =shift; # add 24 hours to start, (for night hours at last weekday of month) + return undef if $start eq ''; + return undef if $end eq ''; + return undef if $duration eq ''; + return undef if $week eq ''; + return undef if $weekday eq ''; + return undef if $frequency eq ''; + return undef if $frequency == 0; - return undef if $start eq''; - return undef if $end eq''; - return undef if $duration eq''; - return undef if $week eq''; - return undef if $weekday eq''; - return undef if $frequency eq''; - return undef if $frequency==0; + my $start_dates = time::get_nth_weekday_in_month( $start, $end, $week, $weekday ); - my $start_dates=time::get_nth_weekday_in_month($start, $end, $week, $weekday-1); - - if ((defined $nextDay) && ($nextDay>0)){ - for (my $i=0;$i<@$start_dates;$i++){ - $start_dates->[$i]=time::add_hours_to_datetime($start_dates->[$i],24); + if ( ( defined $nextDay ) && ( $nextDay > 0 ) ) { + for ( my $i = 0 ; $i < @$start_dates ; $i++ ) { + $start_dates->[$i] = time::add_hours_to_datetime( $start_dates->[$i], 24 ); } } - my $results=[]; - - my $c=-1; - for my $start_datetime (@$start_dates){ + my $results = []; + + my $c = -1; + for my $start_datetime (@$start_dates) { $c++; - my @start = @{time::datetime_to_array($start_datetime)}; - next unless @start>=6; - next if (($c % $frequency)!=0); + my @start = @{ time::datetime_to_array($start_datetime) }; + next unless @start >= 6; + next if ( $c % $frequency ) != 0; - my @end_datetime = Date::Calc::Add_Delta_DHMS( - $start[0], $start[1], $start[2], # start date - $start[3], $start[4], $start[5], # start time - 0, 0, $duration, 0 # delta days, hours, minutes, seconds - ); - my $end_datetime=time::array_to_datetime(\@end_datetime); + my @end_datetime = Date::Calc::Add_Delta_DHMS( + $start[0], $start[1], $start[2], # start date + $start[3], $start[4], $start[5], # start time + 0, 0, $duration, 0 # delta days, hours, minutes, seconds + ); + my $end_datetime = time::array_to_datetime( \@end_datetime ); - push @$results, { + push @$results, + { start => $start_datetime, end => $end_datetime - }; + }; } return $results; } #add duration to a single date -sub get_single_date{ - my $start_datetime = shift; +sub get_single_date ($$) { + my $start_datetime = shift; my $duration = shift; - my @start = @{time::datetime_to_array($start_datetime)}; - return unless @start>=6; + my @start = @{ time::datetime_to_array($start_datetime) }; + return unless @start >= 6; - my @end_datetime = Date::Calc::Add_Delta_DHMS( - $start[0], $start[1], $start[2], # start date - $start[3], $start[4], $start[5], # start time - 0, 0, $duration, 0 # delta days, hours, minutes, seconds - ); - my $date={ + my @end_datetime = Date::Calc::Add_Delta_DHMS( + $start[0], $start[1], $start[2], # start date + $start[3], $start[4], $start[5], # start time + 0, 0, $duration, 0 # delta days, hours, minutes, seconds + ); + my $date = { start => $start_datetime, - end => time::array_to_datetime(\@end_datetime) + end => time::array_to_datetime( \@end_datetime ) }; - return [$date]; + return [$date]; } #calculate all dates between start_datetime and end_date with duration(minutes) and frequency(days) -sub get_dates{ - my $start_datetime = shift; - my $end_date = shift; - my $duration = shift; # in minutes - my $frequency = shift; # in days - #print "start_datetime:$start_datetime end_date:$end_date duration:$duration frequency:$frequency\n"; +sub get_dates($$$$) { + my $start_datetime = shift; + my $end_date = shift; + my $duration = shift; # in minutes + my $frequency = shift; # in days + #print "start_datetime:$start_datetime end_date:$end_date duration:$duration frequency:$frequency\n"; - my @start = @{time::datetime_to_array($start_datetime)}; - return unless @start>=6; - my @start_date = ($start[0], $start[1], $start[2]); - my $start_time = sprintf('%02d:%02d:%02d', $start[3], $start[4], $start[5]); + my @start = @{ time::datetime_to_array($start_datetime) }; + return unless @start >= 6; + my @start_date = ( $start[0], $start[1], $start[2] ); + my $start_time = sprintf( '%02d:%02d:%02d', $start[3], $start[4], $start[5] ); #print STDERR "$start_datetime,$end_date,$duration,$frequency\n"; #return on single date - my $date={}; - $date->{start}= sprintf("%04d-%02d-%02d",@start_date).' '.$start_time; - return undef if $duration eq ''; + my $date = {}; + $date->{start} = sprintf( "%04d-%02d-%02d", @start_date ) . ' ' . $start_time; + return undef if $duration eq ''; - return undef if (($frequency eq '')||($end_date eq'')); + return undef if ( $frequency eq '' ) || ( $end_date eq '' ); #continue on recurring date - my @end = @{time::datetime_to_array($end_date)}; - return unless @end>=3; - my @end_date = ($end[0], $end[1], $end[2]); + my @end = @{ time::datetime_to_array($end_date) }; + return unless scalar @end >= 3; + my @end_date = ( $end[0], $end[1], $end[2] ); - my $today=time::time_to_date(); - my ($year, $month, $day)=split(/\-/,$today); + my $today = time::time_to_date(); + my ( $year, $month, $day ) = split( /\-/, $today ); - my $dates=[]; - return $dates if ($end_date lt $today); - return $dates if ($frequency<1); + my $dates = []; + return $dates if $end_date lt $today; + return $dates if $frequency < 1; - my $j = Date::Calc::Delta_Days(@start_date, @end_date); - my $c=0; - for (my $i = 0; $i <= $j; $i+=$frequency ){ - my @date = Date::Calc::Add_Delta_Days($start[0], $start[1], $start[2], $i); - my $date={}; - $date->{start}=sprintf("%04d-%02d-%02d",@date).' '.$start_time; - - #if($date->{start} gt $today){ - my @end_datetime = Date::Calc::Add_Delta_DHMS( - $date[0], $date[1], $date[2], # start date - $start[3], $start[4], $start[5], # start time - 0, 0, $duration, 0 # delta days, hours, minutes, seconds - ); - $date->{end}=time::array_to_datetime(\@end_datetime); - push @$dates,$date; - #} - last if ($c>200); - $c++; - } - return $dates; + my $j = Date::Calc::Delta_Days( @start_date, @end_date ); + my $c = 0; + for ( my $i = 0 ; $i <= $j ; $i += $frequency ) { + my @date = Date::Calc::Add_Delta_Days( $start[0], $start[1], $start[2], $i ); + my $date = {}; + $date->{start} = sprintf( "%04d-%02d-%02d", @date ) . ' ' . $start_time; + + #if($date->{start} gt $today){ + my @end_datetime = Date::Calc::Add_Delta_DHMS( + $date[0], $date[1], $date[2], # start date + $start[3], $start[4], $start[5], # start time + 0, 0, $duration, 0 # delta days, hours, minutes, seconds + ); + $date->{end} = time::array_to_datetime( \@end_datetime ); + push @$dates, $date; + + #} + last if ( $c > 200 ); + $c++; + } + return $dates; } #remove all series_dates for studio_id and series_id -sub delete{ - my $config=shift; - my $entry=shift; - - return unless defined $entry->{project_id}; - return unless defined $entry->{studio_id}; - return unless defined $entry->{series_id}; +sub delete ($$) { + my $config = shift; + my $entry = shift; - my $dbh=db::connect($config); + return unless defined $entry->{project_id}; + return unless defined $entry->{studio_id}; + return unless defined $entry->{series_id}; - my $query=qq{ + my $dbh = db::connect($config); + + my $query = qq{ delete from calcms_series_dates where project_id=? and studio_id=? and series_id=? }; - my $bind_values=[$entry->{project_id}, $entry->{studio_id}, $entry->{series_id}]; - #print '<pre>$query'.$query.Dumper($bind_values).'</pre>'; - db::put($dbh, $query, $bind_values); + my $bind_values = [ $entry->{project_id}, $entry->{studio_id}, $entry->{series_id} ]; + + db::put( $dbh, $query, $bind_values ); } +# get all series dates where no event has been created for +sub getDatesWithoutEvent ($$) { + my $config = shift; + my $options = shift; -sub error{ - my $msg=shift; - print "ERROR: $msg<br/>\n"; + return unless defined $options->{project_id}; + return unless defined $options->{studio_id}; + return unless defined $options->{from}; + return unless defined $options->{till}; + + my $dbh = db::connect($config); + + my $query = q{ + SELECT sd.* + FROM calcms_series_dates sd LEFT JOIN calcms_events e + on (sd.start = e.start) + where e.start is null + and sd.exclude != 1 + and sd.project_id = ? + and sd.studio_id = ? + and sd.start > ? + and sd.end < ? + order by sd.start + }; + + my $bind_values = [ $options->{project_id}, $options->{studio_id}, $options->{from}, $options->{till} ]; + my $entries = db::get( $dbh, $query, $bind_values ); + return $entries; + +} + +sub error($) { + my $msg = shift; + print "ERROR: $msg<br/>\n"; } #do not delete last line! diff --git a/lib/calcms/series_events.pm b/lib/calcms/series_events.pm index d083290..ee510f6 100644 --- a/lib/calcms/series_events.pm +++ b/lib/calcms/series_events.pm @@ -1,166 +1,193 @@ -package series_events; +package series_events; -use warnings "all"; use strict; +use warnings; +no warnings 'redefine'; use Data::Dumper; use Date::Calc; -use markup; +use markup(); -use db; -use log; -use time; -use uac; -use events; -use series; -use series_dates; -use studios; -use studio_timeslot_dates; -use event_history; +use db(); +use log(); +use time(); +use uac(); +use events(); +use series(); +use series_dates(); +use studios(); +use studio_timeslot_dates(); +use event_history(); +use images(); # check permissions, insert and update events related to series -require Exporter; -our @ISA = qw(Exporter); +#use base 'Exporter'; our @EXPORT_OK = qw( - check_permission - save_content - save_event_time - insert_event - delete_event - set_playout_status + check_permission + save_content + save_event_time + insert_event + delete_event + set_playout_status ); -our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ] ); -sub debug; - -# update main fields of the event by id +# update main fields of the event by id # do not check for project,studio,series # all changed columns are returned for history handling -sub save_content{ - my $config=shift; - my $entry=shift; +sub save_content($$) { + my $config = shift; + my $entry = shift; - my $dbh=db::connect($config); + return undef unless defined $entry->{id}; - return undef unless(defined $entry->{id}); + for my $attr ( keys %$entry ) { + next unless defined $entry->{$attr}; + $entry->{$attr} =~ s/^\s+//g; + $entry->{$attr} =~ s/\s+$//g; + } - for my $attr (keys %$entry){ - $entry->{$attr}=~s/^\s+//g; - $entry->{$attr}=~s/\s+$//g; - } + for my $attr ( 'image', 'series_image' ) { + $entry->{$attr} = images::normalizeName( $entry->{$attr} ) if defined $entry->{$attr}; + } - #print STDERR Dumper(\$entry->{content}); - for my $attr ('content', 'topic'){ - if (defined $entry->{$attr}){ - $entry->{'html_'.$attr}=markup::creole_to_html($entry->{$attr}); - #$entry->{'html_'.$attr}=~s/([^\>])\n+([^\<])/$1<br\/><br\/>$2/g; - #$entry->{'html_'.$attr}=~s/^\s*(<p>)?//g; - #$entry->{'html_'.$attr}=~s/(<\/p>)?\s*$//g; + for my $attr ( 'content', 'topic' ) { + next unless defined $entry->{$attr}; + if (($entry->{content_format}//'') eq 'markdown'){ + $entry->{ 'html_' . $attr } = markup::markdown_to_html( $entry->{$attr} ); + }else{ + $entry->{ 'html_' . $attr } = markup::creole_to_html( $entry->{$attr} ); } - } + } - #print STDERR Dumper(\$entry->{html_content}); - #print STDERR "ok2\n"; - #return; - $entry->{modified_at}= time::time_to_datetime(time()); - #return; + $entry->{modified_at} = time::time_to_datetime( time() ); #update only existing atributes #TODO: double check series_name (needed for reassignment but not for editing...) - my @keys=(); - for my $key ('series_name', 'title', 'excerpt', 'content', 'html_content', - 'user_title', 'user_excerpt', 'topic', 'html_topic', - 'episode', 'image', 'podcast_url', 'archive_url', - 'live', 'published', 'playout', 'archived', 'rerun', 'draft', 'disable_event_sync', - 'modified_by' - ){ - push @keys, $key if defined $entry->{$key}; - } - $entry->{episode} = undef if (defined $entry->{episode}) && ($entry->{episode} eq '0'); - $entry->{published} = 0 if (defined $entry->{draft}) && ($entry->{draft} eq '1'); + my @keys = (); + for my $key ( + 'series_name', 'title', 'excerpt', 'content', + 'html_content', 'user_title', 'user_excerpt', 'topic', + 'html_topic', 'episode', 'image', 'image_label', + 'series_image', 'series_image_label', 'podcast_url', 'archive_url', + 'live', 'published', 'playout', 'archived', + 'rerun', 'draft', 'disable_event_sync', 'modified_by', + 'content_format' + ) + { + push @keys, $key if defined $entry->{$key}; + } + $entry->{episode} = undef if ( defined $entry->{episode} ) && ( $entry->{episode} eq '0' ); + $entry->{published} = 0 if ( defined $entry->{draft} ) && ( $entry->{draft} eq '1' ); - my $values =join(",", map {$_.'=?'} (@keys)); - my @bind_values =map {$entry->{$_}} (@keys); + my $values = join( ",", map { $_ . '=?' } (@keys) ); + my @bind_values = map { $entry->{$_} } (@keys); - push @bind_values,$entry->{id}; - my $query=qq{ + push @bind_values, $entry->{id}; + my $query = qq{ update calcms_events set $values where id=? }; - print STDERR $query.Dumper(\@bind_values); - db::put($dbh, $query, \@bind_values); - return $entry; + my $dbh = db::connect($config); + my $result = db::put( $dbh, $query, \@bind_values ); + unless ( defined $result ) { + print STDERR "error on updating event\n"; + return undef; + } + + return $entry; +} + +sub set_episode{ + my $config = shift; + my $entry = shift; + + return undef unless defined $entry->{id}; + return undef unless defined $entry->{episode}; + + my $query = qq{ + update calcms_events + set episode=? + where id=? + }; + my $bind_values= [ $entry->{episode}, $entry->{id} ]; + my $dbh = db::connect($config); + my $result = db::put( $dbh, $query, $bind_values ); + unless ( defined $result ) { + print STDERR "error on setting episode in event\n"; + return undef; + } + return $entry; } # save event time by id # do not check project, studio, series # for history handling all changed columns are returned -sub save_event_time{ - my $config=shift; - my $entry=shift; +sub save_event_time($$) { + my $config = shift; + my $entry = shift; - return undef unless(defined $entry->{id}); - return undef unless(defined $entry->{duration}); - return undef unless(defined $entry->{start_date}); + return undef unless defined $entry->{id}; + return undef unless defined $entry->{duration}; + return undef unless defined $entry->{start_date}; - my $dbh=db::connect($config); - my $event={ - id => $entry->{id}, - start => $entry->{start_date}, - end => time::add_minutes_to_datetime($entry->{start_date}, $entry->{duration}) - }; - - my $day_start=$config->{date}->{day_starting_hour}; - my $event_hour=int((split(/[\-\:\sT]/,$event->{start}))[3]); + my $dbh = db::connect($config); + my $event = { + id => $entry->{id}, + start => $entry->{start_date}, + end => time::add_minutes_to_datetime( $entry->{start_date}, $entry->{duration} ) + }; - my @update_columns=(); - my $bind_values=[]; - push @update_columns,'start=?'; - push @$bind_values,$event->{start}; + my $day_start = $config->{date}->{day_starting_hour}; + my $event_hour = int( ( split( /[\-\:\sT]/, $event->{start} ) )[3] ); - push @update_columns, 'end=?'; - push @$bind_values, $event->{end}; + my @update_columns = (); + my $bind_values = []; + push @update_columns, 'start=?'; + push @$bind_values, $event->{start}; + + push @update_columns, 'end=?'; + push @$bind_values, $event->{end}; # add start date - my $start_date= time::add_hours_to_datetime($event->{start}, -$day_start); - push @update_columns, 'start_date=?'; - push @$bind_values, $start_date; - $event->{start_date} =$start_date; + my $start_date = time::add_hours_to_datetime( $event->{start}, -$day_start ); + push @update_columns, 'start_date=?'; + push @$bind_values, $start_date; + $event->{start_date} = $start_date; # add end date - my $end_date= time::add_hours_to_datetime($event->{end}, -$day_start); - push @update_columns, 'end_date=?'; - push @$bind_values, $end_date; - $event->{end_date} = $end_date; + my $end_date = time::add_hours_to_datetime( $event->{end}, -$day_start ); + push @update_columns, 'end_date=?'; + push @$bind_values, $end_date; + $event->{end_date} = $end_date; - my $update_columns=join(",\n", @update_columns); - my $update_sql=qq{ + my $update_columns = join( ",\n", @update_columns ); + my $update_sql = qq{ update calcms_events set $update_columns where id=? }; - push @$bind_values, $event->{id}; - #print STDERR $update_sql."\n".Dumper($bind_values)."\n"; - db::put($dbh, $update_sql, $bind_values); - return $event; + push @$bind_values, $event->{id}; + + db::put( $dbh, $update_sql, $bind_values ); + return $event; } -sub set_playout_status{ - my $config=shift; - my $entry=shift; +sub set_playout_status ($$) { + my $config = shift; + my $entry = shift; - return undef unless defined $entry->{project_id}; - return undef unless defined $entry->{studio_id}; - return undef unless defined $entry->{start}; - return undef unless defined $entry->{playout}; + return undef unless defined $entry->{project_id}; + return undef unless defined $entry->{studio_id}; + return undef unless defined $entry->{start}; + return undef unless defined $entry->{playout}; - my $dbh=db::connect($config); + my $dbh = db::connect($config); # check if event is assigned to project and studio - my $sql=qq{ + my $sql = qq{ select se.event_id event_id from calcms_series_events se, calcms_events e where @@ -169,222 +196,233 @@ sub set_playout_status{ and se.project_id=? and se.studio_id=? }; - my $bind_values=[$entry->{start}, $entry->{project_id}, $entry->{studio_id}]; - #print STDERR Dumper($sql).Dumper($bind_values); - my $events=db::get($dbh, $sql, $bind_values); - #print STDERR Dumper($events); - return undef if scalar(@$events)!=1; - my $event_id=$events->[0]->{event_id}; - $sql=qq{ + my $bind_values = [ $entry->{start}, $entry->{project_id}, $entry->{studio_id} ]; + + my $events = db::get( $dbh, $sql, $bind_values ); + return undef if scalar(@$events) != 1; + my $event_id = $events->[0]->{event_id}; + $sql = qq{ update calcms_events set playout=? where id=? and start=? }; - $bind_values=[$entry->{playout}, $event_id, $entry->{start}]; - #print STDERR $sql."\n".Dumper($bind_values)."\n"; - my $result=db::put($dbh, $sql, $bind_values); - return $result; + $bind_values = [ $entry->{playout}, $event_id, $entry->{start} ]; + my $result = db::put( $dbh, $sql, $bind_values ); + return $result; } # is event assigned to project, studio and series? -sub is_event_assigned{ - my $config=shift; - my $entry=shift; +sub is_event_assigned($$) { + my $config = shift; + my $entry = shift; - return 0 unless defined $entry->{project_id}; - return 0 unless defined $entry->{studio_id}; - return 0 unless defined $entry->{series_id}; - return 0 unless defined $entry->{event_id}; + return 0 unless defined $entry->{project_id}; + return 0 unless defined $entry->{studio_id}; + return 0 unless defined $entry->{series_id}; + return 0 unless defined $entry->{event_id}; - my $dbh=db::connect($config); + my $dbh = db::connect($config); - my $sql=q{ + my $sql = q{ select * from calcms_series_events where project_id=? and studio_id=? and series_id=? and event_id=? }; - my $bind_values=[$entry->{project_id}, $entry->{studio_id}, $entry->{series_id}, $entry->{event_id}]; - my $results=db::get($dbh, $sql, $bind_values); + my $bind_values = [ $entry->{project_id}, $entry->{studio_id}, $entry->{series_id}, $entry->{event_id} ]; + my $results = db::get( $dbh, $sql, $bind_values ); - return 1 if @$results>=1; + return 1 if scalar @$results >= 1; return 0; } -sub delete_event{ - my $config=shift; - my $entry=shift; +sub delete_event ($$) { + my $config = shift; + my $entry = shift; - return undef unless defined $entry->{project_id}; - return undef unless defined $entry->{studio_id}; - return undef unless defined $entry->{series_id}; - return undef unless defined $entry->{event_id}; - return undef unless defined $entry->{user}; + return undef unless defined $entry->{project_id}; + return undef unless defined $entry->{studio_id}; + return undef unless defined $entry->{series_id}; + return undef unless defined $entry->{event_id}; + return undef unless defined $entry->{user}; #is event assigned to project, studio and series? - unless(is_event_assigned($config, $entry)==1){ - print STDERR "cannot delete event with project_id=$entry->{project_id}, studio_id=$entry->{studio_id}, series_id=$entry->{series_id}, event_id=$entry->{event_id}"; + unless ( is_event_assigned( $config, $entry ) == 1 ) { + print STDERR +"cannot delete event with project_id=$entry->{project_id}, studio_id=$entry->{studio_id}, series_id=$entry->{series_id}, event_id=$entry->{event_id}"; return 0; } - event_history::insert_by_event_id($config, $entry); + event_history::insert_by_event_id( $config, $entry ); #delete the association - series::unassign_event($config, $entry); + series::unassign_event( $config, $entry ); # delete the event - my $dbh=db::connect($config); - my $sql=q{ + my $dbh = db::connect($config); + my $sql = q{ delete from calcms_events where id=? }; - my $bind_values=[$entry->{event_id}]; - db::put($dbh, $sql, $bind_values); + my $bind_values = [ $entry->{event_id} ]; + db::put( $dbh, $sql, $bind_values ); return 1; } - #check permissions # options: conditions (studio_id, series_id,...) # key permission: permissions to be checked (one of) # key check_for: user, studio, series, events, schedule # return error text or 1 if okay -sub check_permission{ - my $request=shift; - my $options=shift; +sub check_permission($$) { + my $request = shift; + my $options = shift; - return "missing permission at check" unless defined $options->{permission}; - return "missing check_for at check" unless defined $options->{check_for}; - return "missing user at check" unless defined $request->{user}; - return "missing project_id at check" unless defined $options->{project_id}; - return "missing studio_id at check" unless defined $options->{studio_id}; - return "missing series_id at check" unless defined $options->{series_id}; + return "missing permission at check" unless defined $options->{permission}; + return "missing check_for at check" unless defined $options->{check_for}; + return "missing user at check" unless defined $request->{user}; + return "missing project_id at check" unless defined $options->{project_id}; + return "missing studio_id at check" unless defined $options->{studio_id}; + return "missing series_id at check" unless defined $options->{series_id}; - my $permissions = $request->{permissions}; - my $config = $request->{config}; + my $permissions = $request->{permissions}; + my $config = $request->{config}; - my $studio_check=studios::check($config, $options); - return $studio_check if($studio_check ne '1'); + my $studio_check = studios::check( $config, $options ); + return $studio_check if ( $studio_check ne '1' ); print STDERR "check studio ok\n"; - my $project_check=project::check($config, $options); - return $project_check if($project_check ne '1'); + my $project_check = project::check( $config, $options ); + return $project_check if ( $project_check ne '1' ); print STDERR "check project ok\n"; - + #check if permissions are set (like create_event) - my $found=0; - for my $permission (split /\,/,$options->{permission}){ - $found=1 if ((defined $permissions->{$permission})&&($permissions->{$permission})eq'1'); - } - return 'missing permission to '.$options->{permission} if $found==0; + my $found = 0; + for my $permission ( split /\,/, $options->{permission} ) { + $found = 1 if ( defined $permissions->{$permission} ) && ( $permissions->{$permission} ) eq '1'; + } + return 'missing permission to ' . $options->{permission} if $found == 0; delete $options->{permission}; #convert check list to hash - my $check={}; - for my $permission (@{$options->{check_for}}){ - $check->{$permission}=1; - } - delete $options->{check_for}; + my $check = { map { $_ => 1 } @{ $options->{check_for} } }; + delete $options->{check_for}; # is project assigned to studio - return "studio is not assigned to project" unless project::is_studio_assigned($config, $options)==1; + return "studio is not assigned to project" unless project::is_studio_assigned( $config, $options ) == 1; #get studio names - my $studios=studios::get($config, { - project_id => $options->{project_id}, - studio_id => $options->{studio_id} - }); + my $studios = studios::get( + $config, + { + project_id => $options->{project_id}, + studio_id => $options->{studio_id} + } + ); return "unknown studio" unless defined $studios; - return "unknown studio" unless (@$studios==1); - my $studio=$studios->[0]; - my $studio_name=$studio->{name}||''; + return "unknown studio" unless scalar @$studios == 1; + my $studio = $studios->[0]; + my $studio_name = $studio->{name} || ''; #get series names - my $series=series::get($config, { - project_id => $options->{project_id}, - studio_id => $options->{studio_id}, - series_id => $options->{series_id} - }); - my $series_name=$series->[0]->{series_name}||''; - $series_name.=' - '.$series->[0]->{title} if $series->[0]->{series_name} ne ''; - + my $series = series::get( + $config, + { + project_id => $options->{project_id}, + studio_id => $options->{studio_id}, + series_id => $options->{series_id} + } + ); + my $series_name = $series->[0]->{series_name} || ''; + $series_name .= ' - ' . $series->[0]->{title} if $series->[0]->{series_name} ne ''; + my $draft = 0; - $draft = 1 if (defined $options->{draft}) && ($options->{draft} == 1 ); + $draft = 1 if ( defined $options->{draft} ) && ( $options->{draft} == 1 ); #check all items from checklist - if((defined $check->{user})&&(uac::is_user_assigned_to_studio($request, $options)==0)){ - return "User '$request->{user}' is not assigned to studio $studio_name ($options->{studio_id})"; - } - - if((defined $check->{studio})&&(project::is_series_assigned($config, $options)==0)){ - return "Series '$series_name' ($options->{series_id}) is not assigned to studio '$studio_name' ($options->{studio_id})"; + if ( ( defined $check->{user} ) && ( uac::is_user_assigned_to_studio( $request, $options ) == 0 ) ) { + return "User '$request->{user}' is not assigned to studio $studio_name ($options->{studio_id})"; } - - # check series and can user update events - if((defined $check->{series})&&(series::can_user_update_events($request, $options)==0)){ + + if ( ( defined $check->{studio} ) && ( project::is_series_assigned( $config, $options ) == 0 ) ) { + return +"Series '$series_name' ($options->{series_id}) is not assigned to studio '$studio_name' ($options->{studio_id})"; + } + + # check series and can user update events + if ( ( defined $check->{series} ) && ( series::can_user_update_events( $request, $options ) == 0 ) ) { return "unknown series" unless defined $series; - return "User $request->{user} cannot update events for series '$series_name' ($options->{series_id})"; - } - - # check series and can user create events - if((defined $check->{create_events})&&(series::can_user_create_events($request, $options)==0)){ + return "User $request->{user} cannot update events for series '$series_name' ($options->{series_id})"; + } + + # check series and can user create events + if ( ( defined $check->{create_events} ) && ( series::can_user_create_events( $request, $options ) == 0 ) ) { return "unknown series" unless defined $series; - return "User $request->{user} cannot create events for series '$series_name' ($options->{series_id})"; - } - - if( ($draft==0) && (defined $check->{studio_timeslots}) && (studio_timeslot_dates::can_studio_edit_events($config, $options)==0) ){ - return "requested time is not assigned to studio '$studio_name' ($options->{studio_id})"; + return "User $request->{user} cannot create events for series '$series_name' ($options->{series_id})"; + } + + if ( ( $draft == 0 ) + && ( defined $check->{studio_timeslots} ) + && ( studio_timeslot_dates::can_studio_edit_events( $config, $options ) == 0 ) ) + { + return "requested time is not assigned to studio '$studio_name' ($options->{studio_id})"; } #check if event is assigned to user,project,studio,series,location - if(defined $check->{events}){ - return "missing event_id" unless defined $options->{event_id}; - my $result=series::is_event_assigned_to_user($request, $options); - return $result if $result ne '1'; + if ( defined $check->{events} ) { + return "missing event_id" unless defined $options->{event_id}; + my $result = series::is_event_assigned_to_user( $request, $options ); + return $result if $result ne '1'; } # prevent editing events that are over for more than 14 days - if( ($draft==0) && (defined $check->{event_age}) ){ - if (series::is_event_older_than_days($config, { - project_id => $options->{project_id}, - studio_id => $options->{studio_id}, - series_id => $options->{series_id}, - event_id => $options->{event_id}, - max_age => 14 - })==1){ - return "show is over for more than 2 weeks" unless( - (defined $permissions->{update_event_after_week}) - && ($permissions->{update_event_after_week} eq '1') - ); + if ( ( $draft == 0 ) && ( defined $check->{event_age} ) ) { + if ( + series::is_event_older_than_days( + $config, + { + project_id => $options->{project_id}, + studio_id => $options->{studio_id}, + series_id => $options->{series_id}, + event_id => $options->{event_id}, + max_age => 14 + } + ) == 1 + ) + { + return "show is over for more than 2 weeks" + unless ( ( defined $permissions->{update_event_after_week} ) + && ( $permissions->{update_event_after_week} eq '1' ) ); } } - #check if schedule event exists for given date - if( ($draft == 0) && (defined $check->{schedule}) ){ + #check if schedule event exists for given date + if ( ( $draft == 0 ) && ( defined $check->{schedule} ) ) { return "unknown series" unless defined $series; - return "missing start_at at check_permission" unless defined $options->{start_date}; + return "missing start_at at check_permission" unless defined $options->{start_date}; + #TODO: check "is_event_scheduled" if start_at could be moved to start_date - $options->{start_at}=$options->{start_date}; - return "No event scheduled for series '$series_name' ($options->{series_id})" if(series_dates::is_event_scheduled($request, $options)==0); - } - - return '1'; + $options->{start_at} = $options->{start_date}; + return "No event scheduled for series '$series_name' ($options->{series_id})" + if ( series_dates::is_event_scheduled( $request, $options ) == 0 ); + } + + return '1'; } #not handled, yet: -# responsible, status, rating, podcast_url, media_url, visible, time_of_day, recurrence, reference, created_at -# category, time_of_day, +# responsible, status, rating, podcast_url, media_url, visible, recurrence, reference, created_at #insert event -sub insert_event{ - my $config=shift; - my $options=shift; +sub insert_event ($$) { + my $config = shift; + my $options = shift; my $project_id = $options->{project_id}; - my $studio = $options->{studio}; - my $serie = $options->{serie}; - my $params = $options->{event}; - my $user = $options->{user}; + my $studio = $options->{studio}; + my $serie = $options->{serie}; + my $params = $options->{event}; + my $user = $options->{user}; return 0 unless defined $studio; return 0 unless defined $serie; @@ -392,79 +430,121 @@ sub insert_event{ return 0 unless defined $user; return 0 unless defined $studio->{location}; - my $projects=project::get($config, {project_id=>$project_id}); - if(@$projects==0){ + my $projects = project::get( $config, { project_id => $project_id } ); + if ( scalar @$projects == 0 ) { print STDERR "project not found at insert event\n"; return 0; } - my $projectName=$projects->[0]->{name}; - my $event={ - project => $projectName, - location => $studio->{location}, # location from studio + my $projectName = $projects->[0]->{name}; + my $event = { + project => $projectName, + location => $studio->{location}, # location from studio }; + #print '<pre>'; - $event=series_events::add_event_dates($config, $event, $params); + $event = series_events::add_event_dates( $config, $event, $params ); #get event content from series - for my $attr ('program', 'series_name', 'title', 'excerpt', 'content', 'topic', 'image', 'episode', 'podcast_url', 'archive_url'){ - $event->{$attr}=$serie->{$attr} if defined $serie->{$attr}; + for my $attr ( + 'program', 'series_name', 'title', 'excerpt', 'content', 'topic', + 'image', 'episode', 'podcast_url', 'archive_url', 'content_format' + ) + { + $event->{$attr} = $serie->{$attr} if defined $serie->{$attr}; } + $event->{series_image} = $serie->{image} if defined $serie->{image}; + $event->{series_image_label} = $serie->{licence} if defined $serie->{licence}; #overwrite series values from parameters - for my $attr ('program', 'series_name', 'title', 'user_title', 'excerpt', 'user_except', 'content', 'topic', 'image', 'episode', 'podcast_url', 'archive_url'){ - $event->{$attr}=$params->{$attr} if defined $params->{$attr}; + for my $attr ( + 'program', 'series_name', 'title', 'user_title', 'excerpt', 'user_except', + 'content', 'topic', 'image', 'episode', 'podcast_url', 'archive_url', + 'content_format' + ) + { + $event->{$attr} = $params->{$attr} if defined $params->{$attr}; + } + + if (($event->{'content_format'}//'') eq 'markdown'){ + $event->{'html_content'} = markup::markdown_to_html( $event->{'content'} ) if defined $event->{'content'}; + $event->{'html_topic'} = markup::markdown_to_html( $event->{'topic'} ) if defined $event->{'topic'}; + }else{ + $event->{'html_content'} = markup::creole_to_html( $event->{'content'} ) if defined $event->{'content'}; + $event->{'html_topic'} = markup::creole_to_html( $event->{'topic'} ) if defined $event->{'topic'}; } - $event->{'html_content'} = markup::creole_to_html($event->{'content'}) if defined $event->{'content'}; - $event->{'html_topic'} = markup::creole_to_html($event->{'topic'}) if defined $event->{'topic'}; #add event status - for my $attr ('live', 'published', 'playout', 'archived', 'rerun', 'draft', 'disable_event_sync'){ - $event->{$attr}=$params->{$attr}||0; + for my $attr ( 'live', 'published', 'playout', 'archived', 'rerun', 'draft', 'disable_event_sync' ) { + $event->{$attr} = $params->{$attr} || 0; } - if($serie->{has_single_events}eq'1'){ + if ( $serie->{has_single_events} eq '1' ) { delete $event->{series_name}; delete $event->{episode}; } - $event->{modified_at} = time::time_to_datetime(time()); - $event->{created_at} = time::time_to_datetime(time()); + $event->{modified_at} = time::time_to_datetime( time() ); + $event->{created_at} = time::time_to_datetime( time() ); $event->{modified_by} = $user; - #print STDERR Dumper($event); - my $dbh=db::connect($config); - my $event_id= db::insert($dbh, 'calcms_events', $event); + my $dbh = db::connect($config); + my $event_id = db::insert( $dbh, 'calcms_events', $event ); #add to history - $event->{project_id}= $project_id; - $event->{studio_id} = $studio->{id}; - $event->{series_id} = $serie->{series_id}; - $event->{event_id} = $event_id; - event_history::insert($config, $event); - return $event_id; + $event->{project_id} = $project_id; + $event->{studio_id} = $studio->{id}; + $event->{series_id} = $serie->{series_id}; + $event->{event_id} = $event_id; + event_history::insert( $config, $event ); + return $event_id; } - #set start, end, start-date, end_date to an event -sub add_event_dates{ - my $config =shift; - my $event =shift; - my $params =shift; +sub add_event_dates($$$) { + my $config = shift; + my $event = shift; + my $params = shift; #start and end datetime - $event->{start} = $params->{start_date}; - $event->{end} = time::add_minutes_to_datetime($params->{start_date}, $params->{duration}); + $event->{start} = $params->{start_date}; + $event->{end} = time::add_minutes_to_datetime( $params->{start_date}, $params->{duration} ); #set program days - my $day_start=$config->{date}->{day_starting_hour}; - $event->{start_date} = time::date_cond(time::add_hours_to_datetime($event->{start}, -$day_start)); - $event->{end_date} = time::date_cond(time::add_hours_to_datetime($event->{end}, -$day_start)); + my $day_start = $config->{date}->{day_starting_hour}; + $event->{start_date} = time::date_cond( time::add_hours_to_datetime( $event->{start}, -$day_start ) ); + $event->{end_date} = time::date_cond( time::add_hours_to_datetime( $event->{end}, -$day_start ) ); return $event; } -sub error{ - my $msg=shift; - print "ERROR: $msg<br/>\n"; +sub update_series_images ($$) { + my $config = shift; + my $options = shift; + + return "missing project_id" unless defined $options->{project_id}; + return "missing studio_id" unless defined $options->{studio_id}; + return "missing series_id" unless defined $options->{series_id}; + return "missing series_image" unless defined $options->{series_image}; + + #print "save $options->{series_image}\n"; + + my $events = series::get_events( + $config, + { + project_id => $options->{project_id}, + studio_id => $options->{studio_id}, + series_id => $options->{series_id}, + } + ); + + for my $event (@$events) { + $event->{series_image} = $options->{series_image}; + series_events::save_content( $config, $event ); + } +} + +sub error ($) { + my $msg = shift; + print "ERROR: $msg<br/>\n"; } #do not delete last line! diff --git a/lib/calcms/series_schedule.pm b/lib/calcms/series_schedule.pm index 849e478..1e0064b 100644 --- a/lib/calcms/series_schedule.pm +++ b/lib/calcms/series_schedule.pm @@ -1,182 +1,174 @@ -package series_schedule; -use warnings "all"; +package series_schedule; + use strict; +use warnings; +no warnings 'redefine'; + use Data::Dumper; -use series_dates; +use series_dates(); # table: calcms_series_schedule -# columns: id, studio_id, series_id, - # start (datetime), - # duration (minutes), - # frequency (days), - # end (date), - # weekday (1..7) - # week_of_month (1..5) - # month - # nextDay (add 24 hours to start) +# columns: id, studio_id, series_id, +# start (datetime), +# duration (minutes), +# frequency (days), +# end (date), +# weekday (1..7) +# week_of_month (1..5) +# month +# nextDay (add 24 hours to start) -require Exporter; -our @ISA = qw(Exporter); +#use base 'Exporter'; our @EXPORT_OK = qw(get_columns get insert update delete); -our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ] ); -sub debug; +sub get_columns ($) { + my $config = shift; -sub get_columns{ - my $config=shift; - - my $dbh=db::connect($config); - my $cols=db::get_columns($dbh, 'calcms_series_schedule'); - my $columns={}; - for my $col (@$cols){ - $columns->{$col}=1; - } - return $columns; + my $dbh = db::connect($config); + return db::get_columns_hash( $dbh, 'calcms_series_schedule' ); } #map schedule id to id -sub get{ - my $config=shift; - my $condition=shift; +sub get($$) { + my $config = shift; + my $condition = shift; - my $dbh=db::connect($config); + my $dbh = db::connect($config); - my @conditions=(); - my @bind_values=(); + my @conditions = (); + my @bind_values = (); - if ((defined $condition->{project_id}) && ($condition->{project_id} ne '')){ - push @conditions, 'project_id=?'; - push @bind_values, $condition->{project_id}; - } - if ((defined $condition->{studio_id}) && ($condition->{studio_id} ne '')){ - push @conditions, 'studio_id=?'; - push @bind_values, $condition->{studio_id}; - } + if ( ( defined $condition->{project_id} ) && ( $condition->{project_id} ne '' ) ) { + push @conditions, 'project_id=?'; + push @bind_values, $condition->{project_id}; + } + if ( ( defined $condition->{studio_id} ) && ( $condition->{studio_id} ne '' ) ) { + push @conditions, 'studio_id=?'; + push @bind_values, $condition->{studio_id}; + } - if ((defined $condition->{series_id}) && ($condition->{series_id} ne '')){ - push @conditions, 'series_id=?'; - push @bind_values, $condition->{series_id}; - } + if ( ( defined $condition->{series_id} ) && ( $condition->{series_id} ne '' ) ) { + push @conditions, 'series_id=?'; + push @bind_values, $condition->{series_id}; + } - if ((defined $condition->{schedule_id}) && ($condition->{schedule_id} ne '')){ - push @conditions, 'id=?'; - push @bind_values, $condition->{schedule_id}; - } + if ( ( defined $condition->{schedule_id} ) && ( $condition->{schedule_id} ne '' ) ) { + push @conditions, 'id=?'; + push @bind_values, $condition->{schedule_id}; + } - if ((defined $condition->{schedule_ids}) && (ref($condition->{schedule_ids}) eq 'ARRAY')){ - my @scheduleIds = @{$condition->{schedule_ids}}; - push @conditions, 'id in ('.(join(',', (map {'?'} @scheduleIds) )).')'; - for my $id (@scheduleIds){ - push @bind_values, $id; + if ( ( defined $condition->{schedule_ids} ) && ( ref( $condition->{schedule_ids} ) eq 'ARRAY' ) ) { + my @scheduleIds = @{ $condition->{schedule_ids} }; + push @conditions, 'id in (' . ( join( ',', ( map { '?' } @scheduleIds ) ) ) . ')'; + for my $id (@scheduleIds) { + push @bind_values, $id; } - } + } - if ((defined $condition->{start}) && ($condition->{start} ne '')){ - push @conditions, 'start=?'; - push @bind_values, $condition->{start}; - } + if ( ( defined $condition->{start} ) && ( $condition->{start} ne '' ) ) { + push @conditions, 'start=?'; + push @bind_values, $condition->{start}; + } - if ((defined $condition->{exclude}) && ($condition->{exclude} ne '')){ - push @conditions, 'exclude=?'; - push @bind_values, $condition->{exclude}; - } + if ( ( defined $condition->{exclude} ) && ( $condition->{exclude} ne '' ) ) { + push @conditions, 'exclude=?'; + push @bind_values, $condition->{exclude}; + } - if ((defined $condition->{period_type}) && ($condition->{period_type} ne '')){ - push @conditions, 'period_type=?'; - push @bind_values, $condition->{period_type}; - } + if ( ( defined $condition->{period_type} ) && ( $condition->{period_type} ne '' ) ) { + push @conditions, 'period_type=?'; + push @bind_values, $condition->{period_type}; + } - my $conditions=''; - $conditions=" where ".join(" and ",@conditions) if (@conditions>0); + my $conditions = ''; + $conditions = " where " . join( " and ", @conditions ) if ( @conditions > 0 ); - my $query=qq{ + my $query = qq{ select * from calcms_series_schedule $conditions order by exclude, start }; - #print STDERR $query."\n".Dumper(\@bind_values); - my $entries=db::get($dbh, $query, \@bind_values); - for my $entry (@$entries){ - $entry->{schedule_id}=$entry->{id}; - delete $entry->{id}; - } - #print STDERR Dumper($entries); - return $entries; + my $entries = db::get( $dbh, $query, \@bind_values ); + for my $entry (@$entries) { + $entry->{schedule_id} = $entry->{id}; + delete $entry->{id}; + } + return $entries; } +sub insert($$) { + my $config = shift; + my $entry = shift; -sub insert{ - my $config=shift; - my $entry=shift; - - return undef unless defined $entry->{project_id}; - return undef unless defined $entry->{studio_id}; - return undef unless defined $entry->{series_id}; - return undef unless defined $entry->{start}; - my $dbh=db::connect($config); - return db::insert($dbh, 'calcms_series_schedule', $entry); + return undef unless defined $entry->{project_id}; + return undef unless defined $entry->{studio_id}; + return undef unless defined $entry->{series_id}; + return undef unless defined $entry->{start}; + my $dbh = db::connect($config); + return db::insert( $dbh, 'calcms_series_schedule', $entry ); } #schedule id to id -sub update{ - my $config=shift; - my $entry=shift; +sub update($$) { + my $config = shift; + my $entry = shift; - return undef unless defined $entry->{project_id}; - return undef unless defined $entry->{studio_id}; - return undef unless defined $entry->{series_id}; - return undef unless defined $entry->{schedule_id}; - return undef unless defined $entry->{start}; - $entry->{nextDay}=0 unless defined $entry->{nextDay}; + return undef unless defined $entry->{project_id}; + return undef unless defined $entry->{studio_id}; + return undef unless defined $entry->{series_id}; + return undef unless defined $entry->{schedule_id}; + return undef unless defined $entry->{start}; + $entry->{nextDay} = 0 unless defined $entry->{nextDay}; - $entry->{id}=$entry->{schedule_id}; - delete $entry->{schedule_id}; + $entry->{id} = $entry->{schedule_id}; + delete $entry->{schedule_id}; - my $dbh=db::connect($config); - my $values =join(",", map {$_.'=?'} (keys %$entry)); - my @bind_values =map {$entry->{$_}} (keys %$entry); + my $dbh = db::connect($config); + my @keys = sort keys %$entry; + my $values = join( ",", map { $_ . '=?' } @keys ); + my @bind_values = map { $entry->{$_} } @keys; - push @bind_values,$entry->{project_id}; - push @bind_values,$entry->{studio_id}; - push @bind_values,$entry->{id}; + push @bind_values, $entry->{project_id}; + push @bind_values, $entry->{studio_id}; + push @bind_values, $entry->{id}; - my $query=qq{ + my $query = qq{ update calcms_series_schedule set $values where project_id=? and studio_id=? and id=? }; - #print STDERR Dumper($query).Dumper(\@bind_values); - db::put($dbh, $query, \@bind_values); - print "done\n"; + + db::put( $dbh, $query, \@bind_values ); + print "done\n"; } #map schedule id to id -sub delete{ - my $config=shift; - my $entry=shift; - - return undef unless defined $entry->{project_id}; - return undef unless defined $entry->{studio_id}; - return undef unless defined $entry->{series_id}; - return undef unless defined $entry->{schedule_id}; +sub delete($$) { + my $config = shift; + my $entry = shift; - my $dbh=db::connect($config); + return undef unless defined $entry->{project_id}; + return undef unless defined $entry->{studio_id}; + return undef unless defined $entry->{series_id}; + return undef unless defined $entry->{schedule_id}; - my $query=qq{ + my $dbh = db::connect($config); + + my $query = qq{ delete from calcms_series_schedule where project_id=? and studio_id=? and series_id=? and id=? }; - my $bind_values=[$entry->{project_id}, $entry->{studio_id}, $entry->{series_id}, $entry->{schedule_id}]; - #print '<pre>$query'.$query.Dumper($bind_values).'</pre>'; - db::put($dbh, $query, $bind_values); + my $bind_values = [ $entry->{project_id}, $entry->{studio_id}, $entry->{series_id}, $entry->{schedule_id} ]; + + db::put( $dbh, $query, $bind_values ); } -sub error{ - my $msg=shift; - print "ERROR: $msg<br/>\n"; +sub error($) { + my $msg = shift; + print "ERROR: $msg<br/>\n"; } #do not delete last line! diff --git a/lib/calcms/startup.pl b/lib/calcms/startup.pl index 88b1967..12bffc0 100644 --- a/lib/calcms/startup.pl +++ b/lib/calcms/startup.pl @@ -1,32 +1,18 @@ use lib qw(/home/calcms/racalmas/lib/calcms/); +use lib qw(/home/radio/calcms/calcms/); +use lib qw(/home/calcms/lib/calcms/); -return 1; -#use B::TerseSize - -#load mod_perl modules -#use Apache2; -#use ModPerl::RegistryPrefork; -#use Apache::compat; - -#on upload CGI open of tmpfile: Permission denied -#use CGI; - -#load common used modules -#use Data::Dumper; -#use DBI; -use Apache::DBI; -#$Apache::DBI::DEBUG = 2; - -use Time::Local; -use Date::Calc; +use Data::Dumper; +#use Apache::DBI(); +use Time::Local(); +use Date::Calc(); use Calendar::Simple qw(date_span); -use config; -use log; -use time; -use db; -use cache; -use template; +use config(); +use log(); +use time(); +use db(); +use template(); #do not delete last line! -1; +return 1; diff --git a/lib/calcms/studio_timeslot_dates.pm b/lib/calcms/studio_timeslot_dates.pm index 7cb4006..9a844d2 100644 --- a/lib/calcms/studio_timeslot_dates.pm +++ b/lib/calcms/studio_timeslot_dates.pm @@ -1,98 +1,92 @@ -package studio_timeslot_dates; -use warnings "all"; +package studio_timeslot_dates; + use strict; +use warnings; +no warnings 'redefine'; + use Data::Dumper; -use Date::Calc; -use time; +use Date::Calc(); +use time(); # schedule dates for calcms_studio_schedule # table: calcms_studio_timeslot_dates # columns: id, studio_id, start(datetime), end(datetime) # TODO: delete column schedule_id -require Exporter; -our @ISA = qw(Exporter); -our @EXPORT_OK = qw(get_columns get insert update delete get_dates); -our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ] ); +#use base 'Exporter'; +our @EXPORT_OK = qw(get_columns get insert update delete get_dates); -sub debug; +sub get_columns ($){ + my $config = shift; -sub get_columns{ - my $config=shift; - - my $dbh=db::connect($config); - my $cols=db::get_columns($dbh, 'calcms_studio_timeslot_dates'); - my $columns={}; - for my $col (@$cols){ - $columns->{$col}=1; - } - return $columns; + my $dbh = db::connect($config); + return db::get_columns_hash( $dbh, 'calcms_studio_timeslot_dates' ); } # get all studio_timeslot_dates for studio_id within given time range # calculate start_date, end_date, weeday, day from start and end(datetime) -sub get{ - my $config=shift; - my $condition=shift; +sub get ($$){ + my $config = shift; + my $condition = shift; - my $date_range_include=0; - $date_range_include=1 if $condition->{date_range_include}==1; + my $date_range_include = 0; + $date_range_include = 1 if ( defined $condition->{date_range_include} ) && ( $condition->{date_range_include} == 1 ); - my $dbh=db::connect($config); + my $dbh = db::connect($config); - my @conditions=(); - my @bind_values=(); + my @conditions = (); + my @bind_values = (); - if ((defined $condition->{project_id}) && ($condition->{project_id} ne '')){ - push @conditions, 'project_id=?'; - push @bind_values, $condition->{project_id}; - } + if ( ( defined $condition->{project_id} ) && ( $condition->{project_id} ne '' ) ) { + push @conditions, 'project_id=?'; + push @bind_values, $condition->{project_id}; + } - if ((defined $condition->{studio_id}) && ($condition->{studio_id} ne '')){ - push @conditions, 'studio_id=?'; - push @bind_values, $condition->{studio_id}; - } + if ( ( defined $condition->{studio_id} ) && ( $condition->{studio_id} ne '' ) ) { + push @conditions, 'studio_id=?'; + push @bind_values, $condition->{studio_id}; + } - if ((defined $condition->{schedule_id}) && ($condition->{schedule_id} ne '')){ - push @conditions, 'schedule_id=?'; - push @bind_values, $condition->{schedule_id}; - } + if ( ( defined $condition->{schedule_id} ) && ( $condition->{schedule_id} ne '' ) ) { + push @conditions, 'schedule_id=?'; + push @bind_values, $condition->{schedule_id}; + } # from and till range from an event should beween start and end of the studio's permission - if ((defined $condition->{start}) && ($condition->{start} ne '')){ - push @conditions, 'start<=?'; - push @bind_values, $condition->{start}; - } + if ( ( defined $condition->{start} ) && ( $condition->{start} ne '' ) ) { + push @conditions, 'start<=?'; + push @bind_values, $condition->{start}; + } - if ((defined $condition->{end}) && ($condition->{end} ne '')){ - push @conditions, 'end>=?'; - push @bind_values, $condition->{end}; - } + if ( ( defined $condition->{end} ) && ( $condition->{end} ne '' ) ) { + push @conditions, 'end>=?'; + push @bind_values, $condition->{end}; + } # check only a given date date range (without time) - if ((defined $condition->{from}) && ($condition->{from} ne '')){ - if ($date_range_include==1){ - push @conditions, 'end_date>=?'; - push @bind_values, $condition->{from}; - }else{ - push @conditions, 'start_date>=?'; - push @bind_values, $condition->{from}; + if ( ( defined $condition->{from} ) && ( $condition->{from} ne '' ) ) { + if ( $date_range_include == 1 ) { + push @conditions, 'end_date>=?'; + push @bind_values, $condition->{from}; + } else { + push @conditions, 'start_date>=?'; + push @bind_values, $condition->{from}; } - } + } - if ((defined $condition->{till}) && ($condition->{till} ne '')){ - if ($date_range_include==1){ - push @conditions, 'start_date<=?'; - push @bind_values, $condition->{till}; - }else{ - push @conditions, 'end_date<=?'; - push @bind_values, $condition->{till}; + if ( ( defined $condition->{till} ) && ( $condition->{till} ne '' ) ) { + if ( $date_range_include == 1 ) { + push @conditions, 'start_date<=?'; + push @bind_values, $condition->{till}; + } else { + push @conditions, 'end_date<=?'; + push @bind_values, $condition->{till}; } - } + } - my $conditions=''; - $conditions=" where ".join(" and ",@conditions) if (@conditions>0); + my $conditions = ''; + $conditions = " where " . join( " and ", @conditions ) if ( @conditions > 0 ); - my $query=qq{ + my $query = qq{ select date(start) start_date ,date(end) end_date ,dayname(start) start_weekday @@ -107,244 +101,246 @@ sub get{ $conditions order by start }; - #print STDERR $query."\n"; - #print STDERR Dumper(\@bind_values); - my $entries=db::get($dbh, $query, \@bind_values); - for my $entry (@$entries){ - $entry->{start_weekday}=substr($entry->{start_weekday},0,2); - $entry->{end_weekday}=substr($entry->{end_weekday},0,2); - } - #print STDERR Dumper($entries); - return $entries; + my $entries = db::get( $dbh, $query, \@bind_values ); + for my $entry (@$entries) { + $entry->{start_weekday} = substr( $entry->{start_weekday}, 0, 2 ); + $entry->{end_weekday} = substr( $entry->{end_weekday}, 0, 2 ); + } + + return $entries; } - - #get all studio_timeslot_schedules for studio_id and update studio_timeslot_dates -sub update{ - my $config=shift; - my $entry=shift; +sub update { + my $config = shift; + my $entry = shift; - return undef unless(defined $entry->{schedule_id}); + return undef unless defined $entry->{schedule_id}; - my $dbh=db::connect($config); + my $dbh = db::connect($config); - #delete all dates for schedule id - studio_timeslot_dates::delete($config, $entry); + #delete all dates for schedule id + studio_timeslot_dates::delete( $config, $entry ); - my $day_start=$config->{date}->{day_starting_hour}; + my $day_start = $config->{date}->{day_starting_hour}; - #get the schedule with schedule id ordered by date - my $schedules=studio_timeslot_schedule::get($config, { - schedule_id => $entry->{schedule_id} - }); - #add scheduled dates - my $i=0; - my $dates={}; - for my $schedule (@$schedules){ - #calculate dates from start to end_date - my $dateList=get_dates($schedule->{start}, $schedule->{end}, $schedule->{end_date}, $schedule->{frequency}); - #print STDERR Dumper($dateList); - for my $date (@$dateList){ - #set studio i from - $date->{project_id} = $schedule->{project_id}; - $date->{studio_id} = $schedule->{studio_id}; - $date->{schedule_id} = $schedule->{schedule_id}; - $dates->{$date->{start}.$date->{studio_id}}=$date; - } - } + #get the schedule with schedule id ordered by date + my $schedules = studio_timeslot_schedule::get( + $config, + { + schedule_id => $entry->{schedule_id} + } + ); - for my $date (keys %$dates){ - my $timeslot_date=$dates->{$date}; - #insert date - my $entry={ - project_id => $timeslot_date->{project_id}, - studio_id => $timeslot_date->{studio_id}, + #add scheduled dates + my $i = 0; + my $dates = {}; + for my $schedule (@$schedules) { + + #calculate dates from start to end_date + my $dateList = get_dates( $schedule->{start}, $schedule->{end}, $schedule->{end_date}, $schedule->{frequency} ); + + for my $date (@$dateList) { + #set studio i from + $date->{project_id} = $schedule->{project_id}; + $date->{studio_id} = $schedule->{studio_id}; + $date->{schedule_id} = $schedule->{schedule_id}; + $dates->{ $date->{start} . $date->{studio_id} } = $date; + } + } + + for my $date ( keys %$dates ) { + my $timeslot_date = $dates->{$date}; + + #insert date + my $entry = { + project_id => $timeslot_date->{project_id}, + studio_id => $timeslot_date->{studio_id}, schedule_id => $timeslot_date->{schedule_id}, - start => $timeslot_date->{start}, - end => $timeslot_date->{end}, - }; - $entry->{start_date}= time::add_hours_to_datetime($entry->{start}, -$day_start); - $entry->{end_date}= time::add_hours_to_datetime($entry->{end}, -$day_start); - db::insert($dbh, 'calcms_studio_timeslot_dates', $entry); - #print STDERR "$entry->{start_date}\n"; + start => $timeslot_date->{start}, + end => $timeslot_date->{end}, + }; + $entry->{start_date} = time::add_hours_to_datetime( $entry->{start}, -$day_start ); + $entry->{end_date} = time::add_hours_to_datetime( $entry->{end}, -$day_start ); + db::insert( $dbh, 'calcms_studio_timeslot_dates', $entry ); $i++; } - #print STDERR "$i studio_timeslot_dates updates\n"; return $i; } # calculate all start/end datetimes between start_date and stop_date with a frequency(days) # returns list of hashs with start and end -sub get_dates{ - my $start_datetime = shift; # start - my $end_datetime = shift; # start - my $stop_date = shift; # limit recurring events - my $frequency = shift; # in days +sub get_dates { + my $start_datetime = shift; # start + my $end_datetime = shift; # start + my $stop_date = shift; # limit recurring events + my $frequency = shift; # in days - my @start = @{time::datetime_to_array($start_datetime)}; - return unless @start>=6; - my @start_date = ($start[0], $start[1], $start[2]); - my $start_date = sprintf("%04d-%02d-%02d",@start_date); - my $start_time = sprintf('%02d:%02d:%02d', $start[3], $start[4], $start[5]); + my @start = @{ time::datetime_to_array($start_datetime) }; + return unless @start >= 6; + my @start_date = ( $start[0], $start[1], $start[2] ); + my $start_date = sprintf( "%04d-%02d-%02d", @start_date ); + my $start_time = sprintf( '%02d:%02d:%02d', $start[3], $start[4], $start[5] ); - my @end = @{time::datetime_to_array($end_datetime)}; - return unless @end>=6; - my @end_date = ($end[0], $end[1], $end[2]); - my $end_date = sprintf("%04d-%02d-%02d",@end_date); - my $end_time = sprintf('%02d:%02d:%02d', $end[3], $end[4], $end[5]); + my @end = @{ time::datetime_to_array($end_datetime) }; + return unless @end >= 6; + my @end_date = ( $end[0], $end[1], $end[2] ); + my $end_date = sprintf( "%04d-%02d-%02d", @end_date ); + my $end_time = sprintf( '%02d:%02d:%02d', $end[3], $end[4], $end[5] ); - my @stop = @{time::date_to_array($stop_date)}; - return unless @end>=3; - my @stop_date = ($stop[0], $stop[1], $stop[2]); - $stop_date = sprintf("%04d-%02d-%02d",@stop_date); + my @stop = @{ time::date_to_array($stop_date) }; + return unless @end >= 3; + my @stop_date = ( $stop[0], $stop[1], $stop[2] ); + $stop_date = sprintf( "%04d-%02d-%02d", @stop_date ); - my $date={}; - $date->{start}= $start_date.' '.$start_time; - $date->{end} = $end_date.' '.$end_time; + my $date = {}; + $date->{start} = $start_date . ' ' . $start_time; + $date->{end} = $end_date . ' ' . $end_time; - my $dates=[]; - return $dates if ($date->{end} le $date->{start}); + my $dates = []; + return $dates if ( $date->{end} le $date->{start} ); - return $dates if ($stop_date lt $end_date); + return $dates if ( $stop_date lt $end_date ); - my $j = Date::Calc::Delta_Days(@start_date, @stop_date); - return $dates if $j<0; + my $j = Date::Calc::Delta_Days( @start_date, @stop_date ); + return $dates if $j < 0; # split full time events into single days - if($frequency<1){ + if ( $frequency < 1 ) { + #start day - my @next_date = Date::Calc::Add_Delta_Days($start[0], $start[1], $start[2], 1); - my $next_date = sprintf("%04d-%02d-%02d",@next_date); - push @$dates,{ - start => $start_date.' '.$start_time, - end => $next_date .' 00:00:00', - }; - my $c=0; - for (my $i = 1; $i < $j; $i++){ - my @start_date = Date::Calc::Add_Delta_Days($start[0], $start[1], $start[2], $i); - my $start_date = sprintf("%04d-%02d-%02d",@start_date); - my @next_date = Date::Calc::Add_Delta_Days($start[0], $start[1], $start[2], $i+1); - my $next_date = sprintf("%04d-%02d-%02d",@next_date); - push @$dates,{ - start => $start_date.' 00:00:00', - end => $next_date.' 00:00:00', - }; - last if ($c>1000); - $c++; + my @next_date = Date::Calc::Add_Delta_Days( $start[0], $start[1], $start[2], 1 ); + my $next_date = sprintf( "%04d-%02d-%02d", @next_date ); + push @$dates, + { + start => $start_date . ' ' . $start_time, + end => $next_date . ' 00:00:00', + }; + my $c = 0; + for ( my $i = 1 ; $i < $j ; $i++ ) { + my @start_date = Date::Calc::Add_Delta_Days( $start[0], $start[1], $start[2], $i ); + my $start_date = sprintf( "%04d-%02d-%02d", @start_date ); + my @next_date = Date::Calc::Add_Delta_Days( $start[0], $start[1], $start[2], $i + 1 ); + my $next_date = sprintf( "%04d-%02d-%02d", @next_date ); + push @$dates, + { + start => $start_date . ' 00:00:00', + end => $next_date . ' 00:00:00', + }; + last if ( $c > 1000 ); + $c++; } + #end day - push @$dates,{ - start => $end_date.' 00:00:00', - end => $end_date.' '.$end_time, - } if($end_time ne '00:00:00'); + push @$dates, + { + start => $end_date . ' 00:00:00', + end => $end_date . ' ' . $end_time, + } if ( $end_time ne '00:00:00' ); return $dates; } - # multiple time events - my $c=0; - for (my $i = 0; $i <= $j; $i+=$frequency ){ + # multiple time events + my $c = 0; + for ( my $i = 0 ; $i <= $j ; $i += $frequency ) { + #add frequency to start and end date - my @start_date = Date::Calc::Add_Delta_Days($start[0], $start[1], $start[2], $i); - my @end_date = Date::Calc::Add_Delta_Days($end[0], $end[1], $end[2], $i); - #print STDERR Dumper(\@start_date); - #print STDERR Dumper(\@end_date); - my $start_date=sprintf("%04d-%02d-%02d",@start_date); - my $end_date =sprintf("%04d-%02d-%02d",@end_date); - push @$dates,{ - start => $start_date.' '.$start_time, - end => $end_date.' '.$end_time, - }; - last if ($c>1000); - $c++; - } - return $dates; + my @start_date = Date::Calc::Add_Delta_Days( $start[0], $start[1], $start[2], $i ); + my @end_date = Date::Calc::Add_Delta_Days( $end[0], $end[1], $end[2], $i ); + + my $start_date = sprintf( "%04d-%02d-%02d", @start_date ); + my $end_date = sprintf( "%04d-%02d-%02d", @end_date ); + push @$dates, + { + start => $start_date . ' ' . $start_time, + end => $end_date . ' ' . $end_time, + }; + last if ( $c > 1000 ); + $c++; + } + return $dates; } #remove all studio_timeslot_dates for studio_id and schedule_id -sub delete{ - my $config=shift; - my $entry=shift; - - #print STDERR "delete:".Dumper($entry); - return unless(defined $entry->{project_id}); - return unless(defined $entry->{studio_id}); - return unless(defined $entry->{schedule_id}); +sub delete { + my $config = shift; + my $entry = shift; - my $dbh=db::connect($config); + return unless defined $entry->{project_id}; + return unless defined $entry->{studio_id}; + return unless defined $entry->{schedule_id}; - my $query=qq{ + my $dbh = db::connect($config); + + my $query = qq{ delete from calcms_studio_timeslot_dates where schedule_id=? }; - my $bind_values=[$entry->{schedule_id}]; - #print '<pre>$query'.$query.Dumper($bind_values).'</pre>'; - db::put($dbh, $query, $bind_values); + my $bind_values = [ $entry->{schedule_id} ]; + + db::put( $dbh, $query, $bind_values ); } # time based filter to check if studio is assigned to an studio at a given time range # return 1 if there is a schedule date starting before start and ending after end -sub can_studio_edit_events{ - my $config=shift; - my $condition=shift; +sub can_studio_edit_events { + my $config = shift; + my $condition = shift; - my @conditions=(); - my @bind_values=(); - #print Dumper($condition); + my @conditions = (); + my @bind_values = (); #return 0 unless defined $condition->{project_id}; return 0 unless defined $condition->{studio_id}; return 0 unless defined $condition->{start}; return 0 unless defined $condition->{end}; - if ((defined $condition->{project_id}) && ($condition->{project_id} ne '')){ - push @conditions, 'project_id=?'; - push @bind_values, $condition->{project_id}; - } + if ( ( defined $condition->{project_id} ) && ( $condition->{project_id} ne '' ) ) { + push @conditions, 'project_id=?'; + push @bind_values, $condition->{project_id}; + } - if ((defined $condition->{studio_id}) && ($condition->{studio_id} ne '')){ - push @conditions, 'studio_id=?'; - push @bind_values, $condition->{studio_id}; - } + if ( ( defined $condition->{studio_id} ) && ( $condition->{studio_id} ne '' ) ) { + push @conditions, 'studio_id=?'; + push @bind_values, $condition->{studio_id}; + } - if ((defined $condition->{start}) && ($condition->{start} ne '')){ - push @conditions, 'start<=?'; - push @bind_values, $condition->{start}; - } + if ( ( defined $condition->{start} ) && ( $condition->{start} ne '' ) ) { + push @conditions, 'start<=?'; + push @bind_values, $condition->{start}; + } - if ((defined $condition->{end}) && ($condition->{end} ne '')){ - push @conditions, 'end>=?'; - push @bind_values, $condition->{end}; - } + if ( ( defined $condition->{end} ) && ( $condition->{end} ne '' ) ) { + push @conditions, 'end>=?'; + push @bind_values, $condition->{end}; + } - my $conditions=''; - $conditions=" where ".join(" and ",@conditions) if (@conditions>0); + my $conditions = ''; + $conditions = " where " . join( " and ", @conditions ) if ( @conditions > 0 ); - my $dbh=db::connect($config); - my $query=qq{ + my $dbh = db::connect($config); + my $query = qq{ select count(*) permission from calcms_studio_timeslot_dates $conditions }; - #print STDERR Dumper($query).Dumper(\@bind_values); - my $entries=db::get($dbh, $query, \@bind_values); - #print STDERR Dumper($entries); + my $entries = db::get( $dbh, $query, \@bind_values ); + return 0 if scalar(@$entries) == 0; - return 1 if $entries->[0]->{permission}>0; + return 1 if $entries->[0]->{permission} > 0; - if ($entries->[0]->{permission}==0){ - my $timeslot=getMergedDays($config, $condition); + if ( $entries->[0]->{permission} == 0 ) { + my $timeslot = getMergedDays( $config, $condition ); return 0 unless defined $timeslot; - if ( - ($condition->{start} ge $timeslot->{start}) - && ($condition->{end} le $timeslot->{end}) - ){ + if ( ( $condition->{start} ge $timeslot->{start} ) + && ( $condition->{end} le $timeslot->{end} ) ) + { #print STDERR "($condition->{start} ge $timeslot->{start}) ".($condition->{start} ge $timeslot->{start}); #print STDERR "($condition->{end} le $timeslot->{end}) ".($condition->{end} le $timeslot->{end}); - return 1; + return 1; } } return 0; @@ -353,71 +349,66 @@ sub can_studio_edit_events{ # merge two subsequent days if first day ends at same time as next day starts # returns hashref with start and end of merged slot # returns undef if not slot could be found -sub getMergedDays{ - my $config=shift; - my $condition=shift; +sub getMergedDays { + my $config = shift; + my $condition = shift; - my @conditions=(); - my @bind_values=(); - #print Dumper($condition); + my @conditions = (); + my @bind_values = (); #return 0 unless defined $condition->{project_id}; return 0 unless defined $condition->{studio_id}; return 0 unless defined $condition->{start}; return 0 unless defined $condition->{end}; - if ((defined $condition->{project_id}) && ($condition->{project_id} ne '')){ - push @conditions, 'project_id=?'; - push @bind_values, $condition->{project_id}; - } + if ( ( defined $condition->{project_id} ) && ( $condition->{project_id} ne '' ) ) { + push @conditions, 'project_id=?'; + push @bind_values, $condition->{project_id}; + } - if ((defined $condition->{studio_id}) && ($condition->{studio_id} ne '')){ - push @conditions, 'studio_id=?'; - push @bind_values, $condition->{studio_id}; - } + if ( ( defined $condition->{studio_id} ) && ( $condition->{studio_id} ne '' ) ) { + push @conditions, 'studio_id=?'; + push @bind_values, $condition->{studio_id}; + } # set start to next day at 00:00 - my $start=undef; - if ($condition->{start}=~/(\d\d\d\d\-\d\d\-\d\d)/){ - $start=$1.' 00:00'; - $start=time::add_days_to_datetime($start, 1); - push @bind_values, $start; + my $start = undef; + if ( $condition->{start} =~ /(\d\d\d\d\-\d\d\-\d\d)/ ) { + $start = $1 . ' 00:00'; + $start = time::add_days_to_datetime( $start, 1 ); + push @bind_values, $start; } # set end to end days at 00:00 - my $end=undef; - if ($condition->{end}=~/(\d\d\d\d\-\d\d\-\d\d)/){ - $end=$1.' 00:00'; - push @bind_values, $end; + my $end = undef; + if ( $condition->{end} =~ /(\d\d\d\d\-\d\d\-\d\d)/ ) { + $end = $1 . ' 00:00'; + push @bind_values, $end; } return undef unless defined $start; return undef unless defined $end; push @conditions, '(start=? or end=?)'; - my $conditions=''; - $conditions='where '.join(" and ",@conditions) if (@conditions>0); + my $conditions = ''; + $conditions = 'where ' . join( " and ", @conditions ) if ( @conditions > 0 ); # get all days starting on first day or ending at next day - my $dbh=db::connect($config); - my $query=qq{ + my $dbh = db::connect($config); + my $query = qq{ select start, end from calcms_studio_timeslot_dates $conditions order by start }; - # print STDERR Dumper($query).Dumper(\@bind_values); - my $entries=db::get($dbh, $query, \@bind_values); - # print STDERR Dumper($entries); - - if (scalar(@$entries)==2){ - if ($entries->[0]->{end} eq $entries->[1]->{start}){ - $entries={ - start => $entries->[0]->{start}, - end => $entries->[1]->{end} + my $entries = db::get( $dbh, $query, \@bind_values ); + if ( scalar(@$entries) == 2 ) { + if ( $entries->[0]->{end} eq $entries->[1]->{start} ) { + $entries = { + start => $entries->[0]->{start}, + end => $entries->[1]->{end} }; - # print STDERR "found".Dumper($entries)."\n"; return $entries; } } @@ -425,9 +416,9 @@ sub getMergedDays{ return undef; } -sub error{ - my $msg=shift; - print "ERROR: $msg<br/>\n"; +sub error { + my $msg = shift; + print "ERROR: $msg<br/>\n"; } #do not delete last line! diff --git a/lib/calcms/studio_timeslot_schedule.pm b/lib/calcms/studio_timeslot_schedule.pm index 7d9a8bc..003ddaf 100644 --- a/lib/calcms/studio_timeslot_schedule.pm +++ b/lib/calcms/studio_timeslot_schedule.pm @@ -1,142 +1,136 @@ -package studio_timeslot_schedule; -use warnings "all"; +package studio_timeslot_schedule; + use strict; +use warnings; +no warnings 'redefine'; + use Data::Dumper; -use studio_timeslot_dates; +use studio_timeslot_dates(); # table: calcms_studio_timeslot_schedule -# columns: id, project_id, studio_id, start(datetime), end(datetime), end_date(date), +# columns: id, project_id, studio_id, start(datetime), end(datetime), end_date(date), # frequency(days), duration(minutes), create_events(days), publish_events(days) -require Exporter; -our @ISA = qw(Exporter); -our @EXPORT_OK = qw(get_columns get insert update delete); -our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ] ); +#use base 'Exporter'; +our @EXPORT_OK = qw(get_columns get insert update delete); -sub debug; +sub get_columns($) { + my $config = shift; -sub get_columns{ - my $config=shift; - - my $dbh=db::connect($config); - my $cols=db::get_columns($dbh, 'calcms_studio_timeslot_schedule'); - my $columns={}; - for my $col (@$cols){ - $columns->{$col}=1; - } - return $columns; + my $dbh = db::connect($config); + return db::get_columns_hash( $dbh, 'calcms_studio_timeslot_schedule' ); } #map schedule id to id -sub get{ - my $config=shift; - my $condition=shift; +sub get($$) { + my $config = shift; + my $condition = shift; - my $dbh=db::connect($config); + my $dbh = db::connect($config); - my @conditions=(); - my @bind_values=(); + my @conditions = (); + my @bind_values = (); - if ((defined $condition->{project_id}) && ($condition->{project_id} ne '')){ - push @conditions, 'project_id=?'; + if ( ( defined $condition->{project_id} ) && ( $condition->{project_id} ne '' ) ) { + push @conditions, 'project_id=?'; push @bind_values, $condition->{project_id}; } - if ((defined $condition->{studio_id}) && ($condition->{studio_id} ne '')){ - push @conditions, 'studio_id=?'; + if ( ( defined $condition->{studio_id} ) && ( $condition->{studio_id} ne '' ) ) { + push @conditions, 'studio_id=?'; push @bind_values, $condition->{studio_id}; } - if ((defined $condition->{schedule_id}) && ($condition->{schedule_id} ne '')){ - push @conditions, 'id=?'; + if ( ( defined $condition->{schedule_id} ) && ( $condition->{schedule_id} ne '' ) ) { + push @conditions, 'id=?'; push @bind_values, $condition->{schedule_id}; } - my $conditions=''; - $conditions=" where ".join(" and ",@conditions) if (@conditions>0); + my $conditions = ''; + $conditions = " where " . join( " and ", @conditions ) if ( @conditions > 0 ); - my $query=qq{ + my $query = qq{ select * from calcms_studio_timeslot_schedule $conditions order by start }; - #print $query."\n"; - #print Dumper(\@bind_values); - my $entries=db::get($dbh, $query, \@bind_values); - for my $entry (@$entries){ - $entry->{schedule_id}=$entry->{id}; + my $entries = db::get( $dbh, $query, \@bind_values ); + for my $entry (@$entries) { + $entry->{schedule_id} = $entry->{id}; delete $entry->{id}; } return $entries; } -sub insert{ - my $config=shift; - my $entry=shift; +sub insert($$) { + my $config = shift; + my $entry = shift; - return unless(defined $entry->{project_id}); - return unless(defined $entry->{studio_id}); - return unless(defined $entry->{start}); - return unless(defined $entry->{end}); - return unless(defined $entry->{frequency}); + return unless defined $entry->{project_id}; + return unless defined $entry->{studio_id}; + return unless defined $entry->{start}; + return unless defined $entry->{end}; + return unless defined $entry->{frequency}; - my $dbh=db::connect($config); - return db::insert($dbh, 'calcms_studio_timeslot_schedule', $entry); + my $dbh = db::connect($config); + return db::insert( $dbh, 'calcms_studio_timeslot_schedule', $entry ); } #schedule id to id -sub update{ - my $config=shift; - my $entry=shift; +sub update($$) { + my $config = shift; + my $entry = shift; - return unless(defined $entry->{project_id}); - return unless(defined $entry->{studio_id}); - return unless(defined $entry->{schedule_id}); - return unless(defined $entry->{start}); - return unless(defined $entry->{end}); - return unless(defined $entry->{frequency}); + return unless defined $entry->{project_id}; + return unless defined $entry->{studio_id}; + return unless defined $entry->{schedule_id}; + return unless defined $entry->{start}; + return unless defined $entry->{end}; + return unless defined $entry->{frequency}; - $entry->{id}=$entry->{schedule_id}; + $entry->{id} = $entry->{schedule_id}; delete $entry->{schedule_id}; - my $dbh=db::connect($config); - my $values =join(",", map {$_.'=?'} (keys %$entry)); - my @bind_values =map {$entry->{$_}} (keys %$entry); - push @bind_values,$entry->{id}; + my $dbh = db::connect($config); + my @keys = sort keys %$entry; + my $values = join( ",", map { $_ . '=?' } @keys ); + my @bind_values = map { $entry->{$_} } @keys; + push @bind_values, $entry->{id}; - my $query=qq{ + my $query = qq{ update calcms_studio_timeslot_schedule set $values where id=? }; - db::put($dbh, $query, \@bind_values); + db::put( $dbh, $query, \@bind_values ); + #print "done\n"; - $entry->{schedule_id}=$entry->{id}; + $entry->{schedule_id} = $entry->{id}; delete $entry->{id}; } #map schedule id to id -sub delete{ - my $config=shift; - my $entry=shift; - - return unless(defined $entry->{schedule_id}); +sub delete ($$){ + my $config = shift; + my $entry = shift; - my $dbh=db::connect($config); + return unless defined $entry->{schedule_id}; - my $query=qq{ + my $dbh = db::connect($config); + + my $query = qq{ delete from calcms_studio_timeslot_schedule where id=? }; - my $bind_values=[$entry->{schedule_id}]; - #print '<pre>$query'.$query.Dumper($bind_values).'</pre>'; - db::put($dbh, $query, $bind_values); + my $bind_values = [ $entry->{schedule_id} ]; + + db::put( $dbh, $query, $bind_values ); } -sub error{ - my $msg=shift; +sub error($) { + my $msg = shift; print "ERROR: $msg<br/>\n"; } diff --git a/lib/calcms/studios.pm b/lib/calcms/studios.pm index c828299..17069c1 100644 --- a/lib/calcms/studios.pm +++ b/lib/calcms/studios.pm @@ -1,156 +1,158 @@ -#!/bin/perl +package studios; -use CGI; -#use CGI::Carp qw(warningsToBrowser fatalsToBrowser); -use CGI::Session qw(-ip-match); -use CGI::Cookie; -#$CGI::Session::IP_MATCH=1; - -package studios; -use warnings "all"; use strict; +use warnings; +no warnings 'redefine'; + use Data::Dumper; +use images(); -require Exporter; -our @ISA = qw(Exporter); +#use base 'Exporter'; our @EXPORT_OK = qw(get_columns get get_by_id insert update delete check check_studio); -our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ] ); -sub debug; +sub get_columns($) { + my $config = shift; -sub get_columns{ - my $config=shift; - - my $dbh=db::connect($config); - my $cols=db::get_columns($dbh, 'calcms_studios'); - my $columns={}; - for my $col (@$cols){ - $columns->{$col}=1; - } - return $columns; + my $dbh = db::connect($config); + return db::get_columns_hash( $dbh, 'calcms_studios' ); } +sub get($;$) { + my $config = shift; + my $condition = shift || {}; -sub get{ - my $config=shift; - my $condition=shift||{}; + my @conditions = (); + my @bind_values = (); - my @conditions=(); - my @bind_values=(); - - if ((defined $condition->{studio_id}) && ($condition->{studio_id} ne '')){ - push @conditions, 's.id=?'; - push @bind_values, $condition->{studio_id}; - } - - if ((defined $condition->{name}) && ($condition->{name} ne '')){ - push @conditions, 's.name=?'; - push @bind_values, $condition->{name}; - } - - my $limit=''; - if ((defined $condition->{limit}) && ($condition->{limit} ne '')){ - $limit= 'limit '.$condition->{limit}; + if ( ( defined $condition->{studio_id} ) && ( $condition->{studio_id} ne '' ) ) { + push @conditions, 's.id=?'; + push @bind_values, $condition->{studio_id}; } - my $query=''; - unless ((defined $condition->{project_id}) && ($condition->{project_id} ne '')){ - my $conditions=''; - $conditions=" where ".join(" and ",@conditions) if (@conditions>0); - $query=qq{ + if ( ( defined $condition->{name} ) && ( $condition->{name} ne '' ) ) { + push @conditions, 's.name=?'; + push @bind_values, $condition->{name}; + } + + if ( ( defined $condition->{location} ) && ( $condition->{location} ne '' ) ) { + push @conditions, 's.location=?'; + push @bind_values, $condition->{location}; + } + + my $limit = ''; + if ( ( defined $condition->{limit} ) && ( $condition->{limit} ne '' ) ) { + $limit = 'limit ' . $condition->{limit}; + } + + my $query = ''; + unless ( ( defined $condition->{project_id} ) && ( $condition->{project_id} ne '' ) ) { + my $conditions = ''; + $conditions = " where " . join( " and ", @conditions ) if ( scalar @conditions > 0 ); + $query = qq{ select * from calcms_studios s $conditions $limit }; - }else{ - push @conditions, 's.id=ps.studio_id'; - - push @conditions, 'ps.project_id=?'; + } else { + push @conditions, 's.id=ps.studio_id'; + push @conditions, 'ps.project_id=?'; push @bind_values, $condition->{project_id}; - my $conditions=" where ".join(" and ",@conditions) if (@conditions>0); - $query=qq{ + + my $conditions = " where " . join( " and ", @conditions ); + $query = qq{ select * from calcms_studios s, calcms_project_studios ps $conditions $limit }; } - my $dbh=db::connect($config); - #print STDERR Dumper($query).Dumper(\@bind_values); - my $studios=db::get($dbh, $query,\@bind_values); - return $studios; + my $dbh = db::connect($config); + my $studios = db::get( $dbh, $query, \@bind_values ); + return $studios; } -sub insert{ - my $config=shift; - my $entry=shift; +sub getImageById($$) { + my $config = shift; + my $conditions = shift; - $entry->{created_at} = time::time_to_datetime(time()); - $entry->{modified_at}= time::time_to_datetime(time()); - - my $dbh=db::connect($config); - my $id=db::insert($dbh, 'calcms_studios', $entry); + return undef unless defined $conditions->{project_id}; + return undef unless defined $conditions->{studio_id}; + my $studios = studios::get( $config, $conditions ); + return undef if scalar(@$studios) != 1; + return $studios->[0]->{image}; +} + +sub insert ($$) { + my $config = shift; + my $entry = shift; + + $entry->{created_at} = time::time_to_datetime( time() ); + $entry->{modified_at} = time::time_to_datetime( time() ); + $entry->{image} = images::normalizeName( $entry->{image} ) if defined $entry->{image}; + + my $dbh = db::connect($config); + my $id = db::insert( $dbh, 'calcms_studios', $entry ); return $id; } +sub update ($$) { + my $config = shift; + my $studio = shift; -sub update{ - my $config=shift; - my $studio=shift; + $studio->{modified_at} = time::time_to_datetime( time() ); - $studio->{modified_at}= time::time_to_datetime(time()); - - my $columns=get_columns($config); - my $entry={}; - for my $column (keys %$columns){ - $entry->{$column}=$studio->{$column} if defined $studio->{$column}; + my $columns = get_columns($config); + my $entry = {}; + for my $column ( keys %$columns ) { + $entry->{$column} = $studio->{$column} if defined $studio->{$column}; } + $entry->{image} = images::normalizeName( $entry->{image} ) if defined $entry->{image}; - my $values =join(",", map {$_.'=?'} (keys %$entry)); - my @bind_values =map {$entry->{$_}} (keys %$entry); - push @bind_values,$entry->{id}; + my @keys = sort keys %$entry; + my $values = join( ",", map { $_ . '=?' } @keys ); + my @bind_values = map { $entry->{$_} } @keys; + push @bind_values, $entry->{id}; - my $query=qq{ + my $query = qq{ update calcms_studios set $values where id=? }; - my $dbh=db::connect($config); - db::put($dbh, $query, \@bind_values); + my $dbh = db::connect($config); + db::put( $dbh, $query, \@bind_values ); } -sub delete{ - my $config=shift; - my $studio=shift; - - my $dbh=db::connect($config); - db::put($dbh, 'delete from calcms_studios where id=?', [$studio->{id}]); +sub delete ($$) { + my $config = shift; + my $studio = shift; + + my $dbh = db::connect($config); + db::put( $dbh, 'delete from calcms_studios where id=?', [ $studio->{id} ] ); } #TODO rename to check -sub check_studio{ - my $config=shift; - my $options=shift; - return check($config, $options); +sub check_studio($$) { + my $config = shift; + my $options = shift; + return check( $config, $options ); } -sub check{ - my $config=shift; - my $options=shift; - return "missing studio_id" unless defined $options->{studio_id}; - return "Please select a studio" if($options->{studio_id}eq'-1'); - return "Please select a studio" if($options->{studio_id}eq''); - my $studios=studios::get($config, {studio_id => $options->{studio_id}}); - return "Sorry. unknown studio" unless defined $studios; - return "Sorry. unknown studio" unless @$studios==1; +sub check ($$) { + my $config = shift; + my $options = shift; + return "missing studio_id" unless defined $options->{studio_id}; + return "Please select a studio" if ( $options->{studio_id} eq '-1' ); + return "Please select a studio" if ( $options->{studio_id} eq '' ); + my $studios = studios::get( $config, { studio_id => $options->{studio_id} } ); + return "Sorry. unknown studio" unless defined $studios; + return "Sorry. unknown studio" unless scalar @$studios == 1; return 1; } - -sub error{ - my $msg=shift; - print "ERROR: $msg<br/>\n"; +sub error { + my $msg = shift; + print "ERROR: $msg<br/>\n"; } #do not delete last line! diff --git a/lib/calcms/tags.pm b/lib/calcms/tags.pm index 28b8b56..e4b4807 100644 --- a/lib/calcms/tags.pm +++ b/lib/calcms/tags.pm @@ -1,23 +1,22 @@ -use warnings "all"; +package tags; + use strict; +use warnings; +no warnings 'redefine'; use Data::Dumper; -package tags; +#use base 'Exporter'; +our @EXPORT_OK = qw(get_tags); -require Exporter; -our @ISA = qw(Exporter); -our @EXPORT_OK = qw(get_tags); -our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ] ); - -sub get_tags{ - my $dbh=shift; - my $query=qq{ +sub get_tags($) { + my $dbh = shift; + my $query = qq{ select name, count(name) sum from calcms_tags group by name order by sum desc }; - my $tags=db::get($dbh,$query); - return $tags; + my $tags = db::get( $dbh, $query ); + return $tags; } #do not delete last line! diff --git a/lib/calcms/template.pm b/lib/calcms/template.pm index f51c8ce..6d360f7 100644 --- a/lib/calcms/template.pm +++ b/lib/calcms/template.pm @@ -1,226 +1,225 @@ -use warnings "all"; -use strict; - package template; + +use strict; +use warnings; +no warnings 'redefine'; +use feature 'state'; + use Data::Dumper; -use HTML::Template::Compiled; -use HTML::Template::Compiled::Plugin::XMLEscape; -use JSON; -use Cwd; +use HTML::Template::Compiled(); +use HTML::Template::Compiled::Plugin::XMLEscape(); -use config; -use params; -use project; -use log; -use roles; +#use HTML::Template::JIT(); +use JSON(); +use Cwd(); +use Digest::MD5 qw(md5_hex); +use config(); +use params(); +use project(); +use log(); +use roles(); -require Exporter; -our @ISA = qw(Exporter); -#our @EXPORT = qw(all); +#use base 'Exporter'; our @EXPORT_OK = qw(check process exit_on_missing_permission clear_cache); -our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ] ); -sub process{ -# my $output=$_[0]; - my $filename=$_[1]; - my $params=$_[2]; +# TODO:config +sub process($$$$) { + my ($config, $output, $filename, $params) = @_; - my $config=$config::config; - for my $key (keys %{$config::config->{locations}}){ - $params->{$key} =$config::config->{locations}->{$key} if ($key=~/\_url$/); - } - - # add current project - unless (defined $params->{project_title}){ - my $projects = project::get_with_dates($config, { name => $config->{project} }); - if (@$projects==1){ - my $project= $projects->[0]; - foreach my $key (keys %$project){ - $params->{'project_'.$key}=$project->{$key}; - } - } + #TODO: get config + for my $key ( keys %{ $config->{locations} } ) { + $params->{$key} = $config->{locations}->{$key} if ( $key =~ /\_url$/ && $key !~/local/); } - $params->{user}=$ENV{REMOTE_USER} unless defined $params->{user}; + # add current project + unless ( defined $params->{project_title} ) { + my $projects = project::get_with_dates( $config, { name => $config->{project} } ); + if ( scalar @$projects == 1 ) { + my $project = $projects->[0]; + foreach my $key ( keys %$project ) { + $params->{ 'project_' . $key } = $project->{$key}; + } + } + } - my $user_permissions=roles::get_user_permissions(); - for my $permission (keys %$user_permissions){ - $params->{$permission}=$user_permissions->{$permission} if ($user_permissions->{$permission} eq '1'); - } + $params->{user} = $ENV{REMOTE_USER} unless defined $params->{user}; - $params->{jobs}=roles::get_user_jobs(); + my $user_permissions = roles::get_user_permissions($config); + for my $permission ( keys %$user_permissions ) { + $params->{$permission} = $user_permissions->{$permission} + if ( $user_permissions->{$permission} eq '1' ); + } - log::write($config, 'template',$params) if ($config::config->{system}->{debug}>0); -# my $html_template = HTML::Template->new( -# filename => $filename, -# die_on_bad_params =>0, -## cache =>1, -## cache_debug => 1 -# ); + $params->{jobs} = roles::get_user_jobs($config); + if ( ( $filename =~ /json\-p/ ) || (params::isJson) ) { + my $header = "Content-type:application/json; charset=utf-8\n\n"; + my $json = JSON->new->pretty(1)->canonical()->encode($params); + $json = $header . $params->{json_callback} . $json; + if ( ( defined $_[1] ) && ( $_[1] eq 'print' ) ) { + print $json. "\n"; + } else { + $_[1] = $json . "\n"; + } + return; + } - if (($filename =~/json\-p/) || (params::isJson)){ - my $header="Content-type:application/json; charset=utf-8\n\n"; - my $json=to_json($params, {pretty => 1}); -# $json=$header.$params->{json_callback}.'['.$json.']'; - $json=$header.$params->{json_callback}.$json; - if((defined $_[0]) && ($_[0]eq'print')){ - print $json."\n"; - }else{ - $_[0]= $json."\n"; - } - return; - } - #print STDERR $filename."\n"; - log::error($config, "cannot find template $filename ") unless -e $filename; - log::error($config, "cannot read template $filename ") unless -r $filename; + unless ( -r $filename ) { + log::error( $config, qq{template "$filename" does not exist} ) unless -e $filename; + log::error( $config, qq{missing permissions to read "$filename"} ); + } + my $html_template = initTemplate($filename); - my $default_escape='0'; - $default_escape='JS' if ($filename=~/\.js$/); - $default_escape='JS' if ($filename=~/\.json$/); - $default_escape='HTML_ALL' if ($filename=~/\.html$/); + setRelativeUrls( $params, 0 ) + unless ( defined $params->{extern} ) && ( $params->{extern} eq '1' ); - my $html_template=undef; - - unless ($filename=~/\.xml$/){ - $html_template = HTML::Template::Compiled->new( - filename => $filename, - die_on_bad_params => 0, - case_sensitive => 0, - loop_context_vars => 0, - global_vars => 0, - tagstyle => '-asp -comment', - default_escape => $default_escape, - cache => 0, - utf8 => 1, - ); - }else{ - $html_template = HTML::Template::Compiled->new( - filename => $filename, - die_on_bad_params => 0, - case_sensitive => 1, - loop_context_vars => 0, - global_vars => 0, - tagstyle => '-asp -comment', - default_escape => 'XML', - plugin => [qw(HTML::Template::Compiled::Plugin::XMLEscape)], - utf8 => 1 - ); - } - - #$params= - setRelativeUrls($params,0) unless (defined $params->{extern}) && ($params->{extern} eq '1'); - -# HTML::Template::Compiled->preload($cache_dir); - $html_template->param($params); - if((defined $_[0]) && ($_[0]eq'print')){ - print $html_template->output; - }else{ - $_[0]=$html_template->output; - } + $html_template->param($params); + my $out = $html_template->output(); + my $version = "?v=".substr(md5_hex(join("",(stat "js",stat "css",stat "image"))),0,8); + $out =~ s{(src="js/.*\.js)"}{$1$version"}g; + $out =~ s{(href="css/.*\.css)"}{$1$version"}g; + $out =~ s{(src="image/.*\.svg)"}{$1$version"}g; + if ( ( defined $_[1] ) && ( $_[1] eq 'print' ) ) { + print $out; + } else { + $_[1] = $out; + } +} + +sub initTemplate($) { + my ($filename) = @_; + + my $default_escape = 'none'; + $default_escape = 'js' if ( $filename =~ /\.js$/ ); + $default_escape = 'js' if ( $filename =~ /\.json$/ ); + $default_escape = 'html_all' if ( $filename =~ /\.html$/ ); + + if ( $filename =~ /\.xml$/ ) { + return HTML::Template::Compiled->new( + filename => $filename, + die_on_bad_params => 1, + case_sensitive => 1, + loop_context_vars => 0, + global_vars => 0, + tagstyle => '-asp -comment --comment --tt', + default_escape => 'XML', + cache => 1, + utf8 => 1, + plugin => [qw(HTML::Template::Compiled::Plugin::XMLEscape)], + ); + } + + return HTML::Template::Compiled->new( + filename => $filename, + die_on_bad_params => 1, + case_sensitive => 1, + loop_context_vars => 0, + global_vars => 0, + tagstyle => '-asp -comment --comment --tt', + default_escape => $default_escape, + cache => 1, + utf8 => 1, + ); } # set relative urls in nested params structure -sub setRelativeUrls{ - my $params=shift; - my $depth=shift || 0; - - #print STDERR "setRelativeUrls depth:$depth ".ref($params)."\n"; - +sub setRelativeUrls; + +sub setRelativeUrls { + my $params = shift; + my $depth = shift || 0; + return unless defined $params; - - if ($depth>10){ + + if ( $depth > 10 ) { print STDERR "prevent deep recursion in template::setRelativeUrls()\n"; - return ; + return; } # set recursive for hash - if (ref($params) eq 'HASH'){ - for my $key (keys %$params){ + if ( ref($params) eq 'HASH' ) { + for my $key ( keys %$params ) { + #next unless ($key eq 'icon') || ($key eq 'thumb'); - my $val=$params->{$key}; + my $val = $params->{$key}; next unless defined $val; - if (ref($val) eq ''){ + if ( ref($val) eq '' ) { + # make link relative - $params->{$key} =~s/^https?\:(\/\/[^\/]+)/$1/; - }elsif ( (ref($val) eq 'HASH') || (ref($val) eq 'ARRAY') ){ - setRelativeUrls($params->{$key}, $depth+1); + $params->{$key} =~ s/^https?\:(\/\/[^\/]+)/$1/; + } elsif ( ( ref($val) eq 'HASH' ) || ( ref($val) eq 'ARRAY' ) ) { + setRelativeUrls( $params->{$key}, $depth + 1 ); } } return $params; } # set recursive for arrays - if (ref($params) eq 'ARRAY'){ - for my $i (0..@$params){ - my $val=$params->[$i]; + if ( ref($params) eq 'ARRAY' ) { + for my $i ( 0 .. @$params ) { + my $val = $params->[$i]; next unless defined $val; - if ( (ref($val) eq 'HASH') || (ref($val) eq 'ARRAY') ){ - setRelativeUrls($params->[$i], $depth+1); + if ( ( ref($val) eq 'HASH' ) || ( ref($val) eq 'ARRAY' ) ) { + setRelativeUrls( $params->[$i], $depth + 1 ); } } return $params; } - + return $params; } -#requires read config -sub check{ - my $template=shift||''; - my $default=shift; +sub check($;$$) { + my $config = shift; + my $template = shift || ''; + my $default = shift; - if($template =~/json\-p/){ - $template=~s/[^a-zA-Z0-9\-\_\.]//g; - $template=~s/\.{2,99}/\./g; - return $template; - } - - my $config=$config::config; - if ($template eq''){ - $template=$default; - }else{ - $template=~s/^\.\///gi; - #template does use ';' in filename - log::error($config, 'invalid template!') if ($template=~/;/); - #template does use '..' in filename - log::error($config, 'invalid template!') if ($template=~/\.\./); - } - #print STDERR $config::config->{cache}->{compress}."<.compres default:$template\n"; - $template=(split(/\//,$template))[-1]; - my $cwd=getcwd(); + if ( $template =~ /json\-p/ ) { + $template =~ s/[^a-zA-Z0-9\-\_\.]//g; + $template =~ s/\.{2,99}/\./g; + return $template; + } - $template.='.html' unless ($template=~/\./); - if (($config::config->{cache}->{compress}eq'1') && (-e $cwd.'/templates/compressed/'.$template)){ - $template=$cwd.'/templates/compressed/'.$template; - }elsif (-e $cwd.'/templates/'.$template){ - $template=$cwd.'/templates/'.$template; - }else{ - log::error($config, "template not found: '$cwd/$template'"); - - } + if ( $template eq '' ) { + $template = $default; + } else { + $template =~ s/^\.\///gi; - log::error($config, "missing permission to read template '$template'") unless (-r $template); - return $template; + #template does use ';' in filename + log::error( $config, 'invalid template!' ) if ( $template =~ /;/ ); + + #template does use '..' in filename + log::error( $config, 'invalid template!' ) if ( $template =~ /\.\./ ); + } + + $template = ( split( /\//, $template ) )[-1]; + $template .= '.html' unless ( $template =~ /\./ ); + my $dir = "templates"; + my $cwd = Cwd::getcwd(); + my $theme = $config->{locations}->{theme} //= 'default'; + $dir .= "/$theme" if $cwd =~ m{/agenda$} && $theme; + log::error( $config, "template not found: '$dir'" ) + unless -e "$cwd/$dir/$template"; + $template = "$cwd/$dir/$template"; + + return $template; } #deprecated (for old admin only) -sub exit_on_missing_permission{ - my $permission=shift; - my $user_permissions=roles::get_user_permissions(); - if ($user_permissions->{$permission} ne '1'){ - print STDERR "missing permission to $permission\n"; - template::process('print', template::check('default.html'), {error => 'sorry, missing permission!'}); - die(); - #exit; - } -} +sub exit_on_missing_permission($$) { + my $config = shift; + my $permission = shift; -sub clear_cache{ - HTML::Template::Compiled->clear_cache(); -# return; -# my $html_template = HTML::Template::Compiled->new(); -# $html_template->clear_cache(); + my $user_permissions = roles::get_user_permissions($config); + if ( $user_permissions->{$permission} ne '1' ) { + print STDERR "missing permission to $permission\n"; + template::process( + $config, 'print', + template::check( $config, 'default.html' ), + { error => 'sorry, missing permission!' } + ); + die(); + } } #do not delete last line! diff --git a/lib/calcms/time.pm b/lib/calcms/time.pm index 0a5a118..4c77d49 100644 --- a/lib/calcms/time.pm +++ b/lib/calcms/time.pm @@ -1,581 +1,628 @@ -use warnings "all"; -use strict; -use Time::Local; -use DateTime; -use Date::Calc; -use Date::Manip; -use POSIX qw(strftime); -use config; +package time; -package time; -use Data::Dumper; +use strict; +use warnings; +no warnings 'redefine'; use utf8; -require Exporter; -our @ISA = qw(Exporter); +use Time::Local(); +use DateTime(); +use Date::Calc(); +use Date::Manip(); +use POSIX qw(strftime); +use Data::Dumper; + +use config(); + +#use base 'Exporter'; our @EXPORT_OK = qw( - format_datetime format_time - date_format time_format - datetime_to_time time_to_datetime time_to_date - datetime_to_date - add_days_to_datetime add_hours_to_datetime add_minutes_to_datetime - add_days_to_date - datetime_to_array date_to_array array_to_date array_to_datetime array_to_time array_to_time_hm - date_cond time_cond check_date check_time check_datetime check_year_month - datetime_to_rfc822 get_datetime datetime_to_utc datetime_to_utc_datetime - get_duration get_duration_seconds - get_durations get_names get_all_names get_weekdays weekday_index - $names + format_datetime format_time + date_format time_format + datetime_to_time time_to_datetime time_to_date + datetime_to_date + add_days_to_datetime add_hours_to_datetime add_minutes_to_datetime + add_days_to_date + datetime_to_array date_to_array array_to_date array_to_datetime array_to_time array_to_time_hm + date_cond time_cond check_date check_time check_datetime check_year_month + datetime_to_rfc822 get_datetime datetime_to_utc datetime_to_utc_datetime + get_duration get_duration_seconds + getDurations getWeekdayIndex getWeekdayNames getWeekdayNamesShort getMonthNames getMonthNamesShort ); -our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ] ); - -our $names={ - 'de' =>{ - months =>['Januar','Februar','März','April','Mai','Juni','Juli','August','September','Oktober','November','Dezember'], - months_abbr =>['Jan','Feb','Mär','Apr','Mai','Jun','Jul','Aug','Sep','Okt','Nov','Dez'], - weekdays =>['Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag','Sonntag'], - weekdays_abbr =>['Mo','Di','Mi','Do','Fr','Sa','So'], +my $NAMES = { + 'de' => { + months => + [ 'Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember' ], + months_abbr => [ 'Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez' ], + weekdays => [ 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag', 'Sonntag' ], + weekdays_abbr => [ 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So' ], }, - 'en' =>{ - months =>['January','February','March','April','May','June','Jule','August','September','October','November','December'], - months_abbr =>['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'], - weekdays =>['Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday'], - weekdays_abbr =>['Mo','Tu','We','Th','Fr','Sa','Su'], + 'en' => { + months => + [ 'January', 'February', 'March', 'April', 'May', 'June', 'Jule', 'August', 'September', 'October', 'November', 'December' ], + months_abbr => [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ], + weekdays => [ 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday' ], + weekdays_abbr => [ 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su' ], }, }; -our $durations=[ - 0, 5,10,15,20,30,40,45,50,60,70,75,80,90,100,105,110,115,120,135,150,165,180,195,210,225,240,300,360,420,480,540,600,660,720,1440 + +# map starting with monday=0 +my $WEEKDAY_INDEX = { + '0' => 0, + '1' => 1, + '2' => 2, + '3' => 3, + '4' => 4, + '5' => 5, + '6' => 6, + 'Mo' => 0, + 'Tu' => 1, + 'Di' => 1, + 'We' => 2, + 'Mi' => 2, + 'Th' => 3, + 'Do' => 3, + 'Fr' => 4, + 'Sa' => 5, + 'Su' => 6, + 'So' => 6 +}; + +my $DURATIONS = [ + 0, 5, 10, 15, 20, 30, 40, 45, 50, 60, 70, 75, 80, 90, 100, 105, 110, 115, + 120, 135, 150, 165, 180, 195, 210, 225, 240, 300, 360, 420, 480, 540, 600, 660, 720, 1440 ]; -sub get_names{ - my $language=shift||'en'; - return $time::names->{$language}; +sub getDurations() { + return $DURATIONS; } -sub get_all_names{ - return $time::names; +sub getWeekdayNames(;$) { + my $language = shift || 'en'; + return $NAMES->{$language}->{weekdays}; } -sub get_durations{ - return $time::durations; +sub getWeekdayNamesShort(;$) { + my $language = shift || 'en'; + return $NAMES->{$language}->{weekdays_abbr}; } -#TODO: build from datenames -our $weekday_index={ - '0' => 0, - '1' => 1, - '2' => 2, - '3' => 3, - '4' => 4, - '5' => 5, - '6' => 6, - 'Mo'=> 0, - 'Tu'=> 1, - 'Di'=> 1, - 'We'=> 2, - 'Mi'=> 2, - 'Th'=> 3, - 'Do'=> 3, - 'Fr'=> 4, - 'Sa'=> 5, - 'Su'=> 6, - 'So'=> 6 -}; +sub getMonthNames(;$) { + my $language = shift || 'en'; + return $NAMES->{$language}->{months}; +} -sub get_weekdays{ - return{ - 0 => 0, - 1 => 1, - 2 => 2, - 3 => 3, - 4 => 4, - 5 => 5, - 6 => 6, - 'Mo'=>0, - 'Tu'=>1, - 'Di'=>1, - 'We'=>2, - 'Mi'=>2, - 'Th'=>3, - 'Do'=>3, - 'Fr'=>4, - 'Sa'=>5, - 'Su'=>6, - 'So'=>6 +sub getMonthNamesShort(;$) { + my $language = shift || 'en'; + return $NAMES->{$language}->{months_abbr}; +} + + +sub getWeekdayIndex(;$) { + my $weekday = shift || ''; + return $WEEKDAY_INDEX->{$weekday}; +} + +# map starting with monday=1 +sub getWeekdays { + return { + 1 => 1, + 2 => 2, + 3 => 3, + 4 => 4, + 5 => 5, + 6 => 6, + 7 => 7, + 'Mo' => 1, + 'Tu' => 2, + 'Di' => 2, + 'We' => 3, + 'Mi' => 3, + 'Th' => 4, + 'Do' => 4, + 'Fr' => 5, + 'Sa' => 6, + 'Su' => 7, + 'So' => 7 }; } - #deprecated, for wordpress sync -sub format_datetime{ - my $datetime=shift; - return $datetime if ($datetime eq ''); - return add_hours_to_datetime($datetime,0); -}; +sub format_datetime(;$) { + my $datetime = shift; + return $datetime if ( $datetime eq '' ); + return add_hours_to_datetime( $datetime, 0 ); +} #deprecated -sub format_time{ - my $t=$_[0]; +sub format_time($) { + my $t = $_[0]; - my $year =$t->[5]+1900; - my $month =$t->[4]+1; - $month ='0'.$month if(length($month)==1); + my $year = $t->[5] + 1900; + my $month = $t->[4] + 1; + $month = '0' . $month if ( length($month) == 1 ); - my $day =$t->[3]; - $day ='0'.$day if(length($day)==1); + my $day = $t->[3]; + $day = '0' . $day if ( length($day) == 1 ); + my $hour = $t->[2]; + $hour = '0' . $hour if ( length($hour) == 1 ); - my $hour =$t->[2]; - $hour ='0'.$hour if(length($hour)==1); - - my $minute =$t->[1]; - $minute ='0'.$minute if(length($minute)==1); - - return [$day,$month,$year,$hour,$minute]; -}; + my $minute = $t->[1]; + $minute = '0' . $minute if ( length($minute) == 1 ); + return [ $day, $month, $year, $hour, $minute ]; +} # convert datetime to unix time -sub datetime_to_time{ - my $datetime=$_[0]; -# print $datetime."\n"; - if ($datetime=~/(\d\d\d\d)\-(\d+)\-(\d+)[T\s](\d+)\:(\d+)(\:(\d+))?/){ - my $year=$1; - my $month=$2-1; - my $day=$3; - my $hour=$4; - my $minute=$5; - my $second=$8||0; - return Time::Local::timelocal($second,$minute,$hour,$day,$month,$year); - - }else{ - print STDERR "datetime_to_time: no valid date time found! ($datetime )\n"; - return -1; - } -}; +sub datetime_to_time ($){ + my $datetime = $_[0]; + + # print $datetime."\n"; + if ( $datetime =~ /(\d\d\d\d)\-(\d+)\-(\d+)[T\s](\d+)\:(\d+)(\:(\d+))?/ ) { + my $year = $1; + my $month = $2 - 1; + my $day = $3; + my $hour = $4; + my $minute = $5; + my $second = $8 || 0; + return Time::Local::timelocal( $second, $minute, $hour, $day, $month, $year ) || print STDERR "datetime_to_time: no valid date time found! ($datetime)\n"; + + } else { + print STDERR "datetime_to_time: no valid date time found! ($datetime)\n"; + return -1; + } +} #get rfc822 datetime string from datetime string -sub datetime_to_rfc822{ - my $datetime=$_[0]; - my $time=datetime_to_time($datetime); - return POSIX::strftime("%a, %d %b %Y %H:%M:%S %z", localtime($time)); +sub datetime_to_rfc822($) { + my $datetime = $_[0]; + my $time = datetime_to_time($datetime); + return POSIX::strftime( "%a, %d %b %Y %H:%M:%S %z", localtime($time) ); } #get seconds from epoch -sub datetime_to_utc{ - my $datetime=shift; - my $time_zone=shift; - $datetime=get_datetime($datetime, $time_zone); - return $datetime->epoch(); +sub datetime_to_utc($$) { + my $datetime = shift; + my $time_zone = shift; + $datetime = get_datetime( $datetime, $time_zone ); + return $datetime->epoch(); } # get full utc datetime including timezone offset -sub datetime_to_utc_datetime{ - my $datetime=shift; - my $time_zone=shift; - $datetime=get_datetime($datetime, $time_zone); - return $datetime->format_cldr("yyyy-MM-ddTHH:mm:ssZZZZZ"); +sub datetime_to_utc_datetime($$) { + my $datetime = shift; + my $time_zone = shift; + $datetime = get_datetime( $datetime, $time_zone ); + return $datetime->format_cldr("yyyy-MM-ddTHH:mm:ssZZZZZ"); } - - #add hours to datetime string -sub add_hours_to_datetime{ - my $datetime=shift; - my $hours=shift; - return time_to_datetime(datetime_to_time($datetime)+(3600*$hours)); -}; - -#add minutes to datetime string -sub add_minutes_to_datetime{ - my $datetime=shift; - my $minutes=shift; - return time_to_datetime(datetime_to_time($datetime)+(60*$minutes)); -}; - -#add days to datetime string -sub add_days_to_datetime{ - my $datetime=shift; - my $days=shift; - my $time=datetime_to_array($datetime); - #print STDERR Dumper($time); - ($time->[0], $time->[1], $time->[2]) =Date::Calc::Add_Delta_Days($time->[0]+0, $time->[1]+0, $time->[2]+0, $days); - return array_to_datetime($time); +sub add_hours_to_datetime($;$) { + my $datetime = shift; + my $hours = shift; + $hours = 0 unless defined $hours; + return time_to_datetime( datetime_to_time($datetime) + ( 3600 * $hours ) ); } -sub add_days_to_date{ - my $datetime=shift; - my $days=shift; - my $date=date_to_array($datetime); - ($date->[0], $date->[1], $date->[2]) =Date::Calc::Add_Delta_Days($date->[0]+0, $date->[1]+0, $date->[2]+0, $days); - return array_to_date($date); +#add minutes to datetime string +sub add_minutes_to_datetime($;$) { + my $datetime = shift; + my $minutes = shift; + $minutes = 0 unless defined $minutes; + return time_to_datetime( datetime_to_time($datetime) + ( 60 * $minutes ) ); +} + +#add days to datetime string +sub add_days_to_datetime($;$) { + my $datetime = shift; + my $days = shift; + $days = 0 unless defined $days; + my $time = datetime_to_array($datetime); + + ( $time->[0], $time->[1], $time->[2] ) = Date::Calc::Add_Delta_Days( $time->[0] + 0, $time->[1] + 0, $time->[2] + 0, $days ); + return array_to_datetime($time); +} + +sub add_days_to_date($;$) { + my $datetime = shift; + my $days = shift; + $days = 0 unless defined $days; + my $date = date_to_array($datetime); + ( $date->[0], $date->[1], $date->[2] ) = Date::Calc::Add_Delta_Days( $date->[0] + 0, $date->[1] + 0, $date->[2] + 0, $days ); + return array_to_date($date); } # convert unix time to datetime format -sub time_to_datetime{ - my $time=shift; - $time=time() unless((defined $time) && ($time ne'')); - my @t=localtime($time); - return sprintf('%04d-%02d-%02d %02d:%02d:%02d', $t[5]+1900, $t[4]+1, $t[3], $t[2], $t[1], $t[0]); -}; +sub time_to_datetime(;$) { + my $time = shift; + $time = time() unless ( defined $time ) && ( $time ne '' ); + my @t = localtime($time); + return sprintf( '%04d-%02d-%02d %02d:%02d:%02d', $t[5] + 1900, $t[4] + 1, $t[3], $t[2], $t[1], $t[0] ); +} # convert unix time to date format -sub time_to_date{ - my $time=shift; - $time=time() unless((defined $time) && ($time ne'')); - my @t=localtime($time); - return sprintf('%04d-%02d-%02d', $t[5]+1900, $t[4]+1, $t[3]); -}; +sub time_to_date(;$) { + my $time = shift; + $time = time() unless ( defined $time ) && ( $time ne '' ); + my @t = localtime($time); + return sprintf( '%04d-%02d-%02d', $t[5] + 1900, $t[4] + 1, $t[3] ); +} # convert datetime to a array of date/time values -sub datetime_to_array{ - my $datetime=$_[0]||''; - if ($datetime=~/(\d\d\d\d)\-(\d+)\-(\d+)([T\s]+(\d+)\:(\d+)(\:(\d+))?)?/){ - my $year=$1; - my $month=$2; - my $day=$3; - my $hour=$5||'00'; - my $minute=$6||'00'; - my $second=$8||'00'; - return [$year,$month,$day,$hour,$minute,$second]; - } - return undef; -}; +sub datetime_to_array(;$) { + my $datetime = $_[0] || ''; + if ( $datetime =~ /(\d\d\d\d)\-(\d+)\-(\d+)([T\s]+(\d+)\:(\d+)(\:(\d+))?)?/ ) { + my $year = $1; + my $month = $2; + my $day = $3; + my $hour = $5 || '00'; + my $minute = $6 || '00'; + my $second = $8 || '00'; + return [ $year, $month, $day, $hour, $minute, $second ]; + } + return undef; +} # convert datetime to date -sub datetime_to_date{ - my $datetime=$_[0]||''; - if ($datetime=~/(\d\d\d\d)\-(\d+)\-(\d+)/){ - my $year=$1; - my $month=$2; - my $day=$3; - return sprintf("%04d-%02d-%02d",$year,$month,$day); - } - return undef; -}; +sub datetime_to_date(;$) { + my $datetime = $_[0] || ''; + if ( $datetime =~ /(\d\d\d\d)\-(\d+)\-(\d+)/ ) { + my $year = $1; + my $month = $2; + my $day = $3; + return sprintf( "%04d-%02d-%02d", $year, $month, $day ); + } + return undef; +} #convert datetime array or single value to datetime string -sub array_to_datetime{ - my $date =shift; - if(ref($date)eq'ARRAY'){ - return sprintf("%04d-%02d-%02d %02d:%02d:%02d", $date->[0], $date->[1], $date->[2], $date->[3], $date->[4], $date->[5]); - } - my $month =shift; - my $day =shift; - my $hour =shift||'0'; - my $minute =shift||'0'; - my $second =shift||'0'; - return sprintf("%04d-%02d-%02d %02d:%02d:%02d", $date, $month, $day, $hour, $minute, $second); +sub array_to_datetime(;$) { + my $date = shift; + if ( ref($date) eq 'ARRAY' ) { + return sprintf( "%04d-%02d-%02d %02d:%02d:%02d", $date->[0], $date->[1], $date->[2], $date->[3], $date->[4], $date->[5] ); + } + my $month = shift; + my $day = shift; + my $hour = shift || '0'; + my $minute = shift || '0'; + my $second = shift || '0'; + return sprintf( "%04d-%02d-%02d %02d:%02d:%02d", $date, $month, $day, $hour, $minute, $second ); } #convert date array or single values to date string -sub array_to_date{ - my $date =shift; - if(ref($date)eq'ARRAY'){ - return sprintf("%04d-%02d-%02d", $date->[0], $date->[1], $date->[2]); - } - my $month=shift; - my $day =shift; - return sprintf("%04d-%02d-%02d", $date, $month, $day); +sub array_to_date($;$$) { + my $date = shift; + if ( ref($date) eq 'ARRAY' ) { + return sprintf( "%04d-%02d-%02d", $date->[0], $date->[1], $date->[2] ); + } + my $month = shift; + my $day = shift; + return sprintf( "%04d-%02d-%02d", $date, $month, $day ); } -sub array_to_time{ - my $date =shift; - if(ref($date)eq'ARRAY'){ - return sprintf("%02d:%02d:%02d", $date->[3], $date->[4], $date->[5]); - } - my $minute = shift||0; - my $second = shift||0; - return sprintf("%02d:%02d:%02d", $date, $minute, $second); +sub array_to_time(;$) { + my $date = shift; + if ( ref($date) eq 'ARRAY' ) { + return sprintf( "%02d:%02d:%02d", $date->[3], $date->[4], $date->[5] ); + } + my $minute = shift || 0; + my $second = shift || 0; + return sprintf( "%02d:%02d:%02d", $date, $minute, $second ); } -sub array_to_time_hm{ - my $date =shift; - if(ref($date)eq'ARRAY'){ - return sprintf("%02d:%02d", $date->[3], $date->[4]); - } - my $minute = shift||0; - return sprintf("%02d:%02d", $date, $minute); +sub array_to_time_hm(;$) { + my $date = shift; + if ( ref($date) eq 'ARRAY' ) { + return sprintf( "%02d:%02d", $date->[3], $date->[4] ); + } + my $minute = shift || 0; + return sprintf( "%02d:%02d", $date, $minute ); } - # get number of days between two days -sub days_between{ - my $today=$_[0]; - my $date=$_[1]; - my $delta_days=eval{Date::Calc::Delta_Days( - $today->[0],$today->[1],$today->[2], - $date->[0], $date->[1], $date->[2] - )}; - return $delta_days; +sub days_between($$) { + my $today = $_[0]; + my $date = $_[1]; + my $delta_days = eval { Date::Calc::Delta_Days( $today->[0], $today->[1], $today->[2], $date->[0], $date->[1], $date->[2] ) }; + return $delta_days; } -sub dayOfYear{ - my $datetime=$_[0]; - if ($datetime=~/(\d\d\d\d)\-(\d+)\-(\d+)/){ - my $year = $1; - my $month = $2; - my $day = $3; - return Date::Calc::Day_of_Year($year,$month,$day); - } - return undef; +sub dayOfYear($) { + my $datetime = $_[0]; + if ( $datetime =~ /(\d\d\d\d)\-(\d+)\-(\d+)/ ) { + my $year = $1; + my $month = $2; + my $day = $3; + return Date::Calc::Day_of_Year( $year, $month, $day ); + } + return undef; } # get duration in minutes -sub get_duration{ - my $start = shift; - my $end = shift; - my $timezone= shift; - $start=time::get_datetime($start, $timezone); - $end =time::get_datetime($end, $timezone); - my $duration=$end->epoch()-$start->epoch(); - return $duration/60; +sub get_duration($$$) { + my $start = shift; + my $end = shift; + my $timezone = shift; + $start = time::get_datetime( $start, $timezone ); + $end = time::get_datetime( $end, $timezone ); + my $duration = $end->epoch() - $start->epoch(); + return $duration / 60; } # get duration in seconds -sub get_duration_seconds{ - my $start = shift; - my $end = shift; - my $timezone= shift||'UTC'; - $start=time::get_datetime($start, $timezone); - $end =time::get_datetime($end, $timezone); - my $duration=$end->epoch()-$start->epoch(); - return $duration; +sub get_duration_seconds($$;$) { + my $start = shift; + my $end = shift; + my $timezone = shift || 'UTC'; + + unless ( defined $start ) { + print STDERR "time::get_duration_seconds(): start is missing\n"; + return 0; + } + unless ( defined $end ) { + print STDERR "time::get_duration_seconds(): end is missing\n"; + return 0; + } + + $start = time::get_datetime( $start, $timezone ); + $end = time::get_datetime( $end, $timezone ); + unless ( defined $start ) { + print STDERR "time::get_duration_seconds(): invalid start\n"; + return 0; + } + unless ( defined $end ) { + print STDERR "time::get_duration_seconds(): invalid end\n"; + return 0; + } + my $duration = $end->epoch() - $start->epoch(); + return $duration; } # convert date string to a array of date values -sub date_to_array{ - my $datetime=$_[0]; - if ($datetime=~/(\d\d\d\d)\-(\d+)\-(\d+)/){ - my $year = $1; - my $month = $2; - my $day = $3; - return [$year,$month,$day]; - } - return undef; -}; +sub date_to_array($) { + my $datetime = $_[0]; + if ( $datetime =~ /(\d\d\d\d)\-(\d+)\-(\d+)/ ) { + my $year = $1; + my $month = $2; + my $day = $3; + return [ $year, $month, $day ]; + } + return undef; +} -# parse date string and return date string +# parse date string and return date string # pass 'today', return '' on parse error -sub date_cond{ - my $date=shift; +sub date_cond($) { + my $date = shift; - return '' if ($date eq''); - if ($date=~/(\d\d\d\d)\-(\d\d?)\-(\d\d?)/){ - my $year = $1; - my $month = $2; - my $day = $3; - return sprintf("%04d-%02d-%02d", $year, $month, $day); - } - return 'today' if ($date eq 'today'); - return ''; -}; + return '' if ( $date eq '' ); + if ( $date =~ /(\d\d\d\d)\-(\d\d?)\-(\d\d?)/ ) { + my $year = $1; + my $month = $2; + my $day = $3; + return sprintf( "%04d-%02d-%02d", $year, $month, $day ); + } + return 'today' if ( $date eq 'today' ); + return ''; +} #parse time and return time string hh:mm:ss #return hh:00 if time is 'now' -sub time_cond{ - my $time = shift; +sub time_cond($) { + my $time = shift; - return '' if ($time eq''); - if ($time=~/(\d\d?)\:(\d\d?)(\:(\d\d))?/){ - my $hour=$1; - my $minute=$2; - my $second=$4||'00'; - return sprintf("%02d:%02d:%02d", $hour, $minute, $second); - } - if ($time eq 'now'){ - my $date=datetime_to_array(time_to_datetime(time())); - my $hour=$date->[3]-2; - $hour=0 if ($hour<0); - $time=sprintf("%02d:00",$hour); - return $time; - } - return ''; -}; - -#parse date and time string and return yyyy-mm-ddThh:mm:ss -sub datetime_cond{ - my $datetime = shift; - - return '' if ($datetime eq''); - (my $date,my $time)=split /[ T]/,$datetime; - $date=time::date_cond($date); - return '' if ($date eq''); - $time=time::time_cond($time); - return '' if ($time eq''); - - return $date.'T'.$time; + return '' if ( $time eq '' ); + if ( $time =~ /(\d\d?)\:(\d\d?)(\:(\d\d))?/ ) { + my $hour = $1; + my $minute = $2; + my $second = $4 || '00'; + return sprintf( "%02d:%02d:%02d", $hour, $minute, $second ); + } + if ( $time eq 'now' ) { + my $date = datetime_to_array( time_to_datetime( time() ) ); + my $hour = $date->[3] - 2; + $hour = 0 if ( $hour < 0 ); + $time = sprintf( "%02d:00", $hour ); + return $time; + } + return ''; } -sub check_date{ - my $date=shift; +#parse date and time string and return yyyy-mm-ddThh:mm:ss +sub datetime_cond($) { + my $datetime = shift; - return "" if((!defined $date) || ($date eq '')); - if($date=~/(\d\d\d\d)\-(\d\d?)\-(\d\d?)/){ - return $1.'-'.$2.'-'.$3; - }elsif($date=~/(\d\d?)\.(\d\d?)\.(\d\d\d\d)/){ - return $3.'-'.$2.'-'.$1; - } - return $date if ($date eq'today' || $date eq'tomorrow' || $date eq'yesterday'); - return -1; - #error("no valid date format given!"); -}; + return '' if ( $datetime eq '' ); + ( my $date, my $time ) = split /[ T]/, $datetime; + $date = time::date_cond($date); + return '' if ( $date eq '' ); + $time = time::time_cond($time); + return '' if ( $time eq '' ); -sub check_time{ - my $time=shift; - return "" if((!defined $time) || ($time eq '')); - return $time if(($time eq 'now') || ($time eq 'future')); - if($time=~/(\d\d?)\:(\d\d?)/){ - return $1.':'.$2 - } - return -1; -}; + return $date . 'T' . $time; +} -sub check_datetime{ - my $date=shift; +sub check_date($) { + my $date = shift; - return "" if((!defined $date) || ($date eq '')); - if($date=~/(\d\d\d\d)\-(\d\d?)\-(\d\d?)[T ](\d\d?)\:(\d\d?)/){ - return sprintf("%04d-%02d-%02dT%02d:%02d",$1,$2,$3,$4,$5); - } - return -1; -}; + return "" if ( !defined $date ) || ( $date eq '' ); + if ( $date =~ /(\d\d\d\d)\-(\d\d?)\-(\d\d?)/ ) { + return $1 . '-' . $2 . '-' . $3; + } elsif ( $date =~ /(\d\d?)\.(\d\d?)\.(\d\d\d\d)/ ) { + return $3 . '-' . $2 . '-' . $1; + } + return $date if ( $date eq 'today' || $date eq 'tomorrow' || $date eq 'yesterday' ); + return -1; -sub check_year_month{ - my $date=shift; - return -1 unless(defined $date); - return $date if($date eq ''); - if($date=~/(\d\d\d\d)\-(\d\d?)/){ - return $1.'-'.$2.'-'.$3; - } - return -1; -}; + #error("no valid date format given!"); +} + +sub check_time($) { + my $time = shift; + return "" if ( !defined $time ) || ( $time eq '' ); + return $time if ( $time eq 'now' ) || ( $time eq 'future' ); + if ( $time =~ /(\d\d?)\:(\d\d?)/ ) { + return $1 . ':' . $2; + } + return -1; +} + +sub check_datetime($) { + my $date = shift; + + return "" if ( !defined $date ) || ( $date eq '' ); + if ( $date =~ /(\d\d\d\d)\-(\d\d?)\-(\d\d?)[T ](\d\d?)\:(\d\d?)/ ) { + return sprintf( "%04d-%02d-%02dT%02d:%02d", $1, $2, $3, $4, $5 ); + } + return -1; +} + +sub check_year_month($) { + my $date = shift; + return -1 unless defined $date; + return $date if ( $date eq '' ); + if ( $date =~ /(\d\d\d\d)\-(\d\d?)/ ) { + return $1 . '-' . $2 . '-' . $3; + } + return -1; +} #TODO: remove config dependency -sub date_time_format{ - my $datetime=shift; - my $language=shift || $config::config->{date}->{language} || 'en'; - if (defined $datetime && $datetime=~/(\d\d\d\d)\-(\d\d?)\-(\d\d?)[\sT](\d\d?\:\d\d?)/){ - my $time=$4; - my $day=$3; - my $month=$2; - my $year=$1; - - $month=$time::names->{$language}->{months_abbr}->[$month-1]||''; - return "$day. $month $year $time"; - } - return $datetime; +sub date_time_format($$;$) { + my $config = shift; + my $datetime = shift; + my $language = shift || $config->{date}->{language} || 'en'; + if ( defined $datetime && $datetime =~ /(\d\d\d\d)\-(\d\d?)\-(\d\d?)[\sT](\d\d?\:\d\d?)/ ) { + my $time = $4; + my $day = $3; + my $month = $2; + my $year = $1; + + $month = time::getMonthNamesShort($language)->[ $month - 1 ] || ''; + return "$day. $month $year $time"; + } + return $datetime; } #format datetime to date string #TODO: remove config dependency -sub date_format{ - my $datetime=shift; - my $language=shift || $config::config->{date}->{language} || 'en'; +sub date_format($$;$) { + my $config = shift; + my $datetime = shift; + my $language = shift || $config->{date}->{language} || 'en'; - if (defined $datetime && $datetime=~/(\d\d\d\d)\-(\d\d?)\-(\d\d?)/){ - my $day=$3; - my $month=$2; - my $year=$1; - $month=$time::names->{$language}->{months_abbr}->[$month-1]||''; - return "$day. $month $year"; - } - return $datetime; -}; + if ( defined $datetime && $datetime =~ /(\d\d\d\d)\-(\d\d?)\-(\d\d?)/ ) { + my $day = $3; + my $month = $2; + my $year = $1; + $month = time::getMonthNamesShort($language)->[ $month - 1 ] || ''; + return "$day. $month $year"; + } + return $datetime; +} #format datetime to time string -sub time_format{ - my $datetime=shift; - if (defined $datetime && $datetime=~/(\d\d?\:\d\d?)/){ - return $1; - } - return $datetime; -}; +sub time_format($) { + my $datetime = shift; + if ( defined $datetime && $datetime =~ /(\d\d?\:\d\d?)/ ) { + return $1; + } + return $datetime; +} #get offset from given time_zone -sub utc_offset{ - my $time_zone=shift; +sub utc_offset($) { + my $time_zone = shift; - $a=DateTime->now(); - $a->set_time_zone($time_zone); - return $a->strftime("%z"); + my $datetime = DateTime->now(); + $datetime->set_time_zone($time_zone); + return $datetime->strftime("%z"); } #get weekday from (yyyy,mm,dd) -sub weekday{ - my ($year,$month,$day)=@_; - my $time = Time::Local::timelocal(0,0,0,$day,$month-1,$year); - return (localtime($time))[6]; +sub weekday($$$) { + my ( $year, $month, $day ) = @_; + my $time = Time::Local::timelocal( 0, 0, 0, $day, $month - 1, $year ); + return ( localtime($time) )[6]; } #get current date, related to starting day_starting_hour #TODO: remove config dependency -sub get_event_date{ - my $config=shift; - $config=$config::config unless defined $config; +sub get_event_date($) { + my $config = shift; - my $datetime=time::time_to_datetime(time()); - my $hour=(time::datetime_to_array($datetime))->[3]; - #today: between 0:00 and starting_hour show last day - if ($hour < $config->{date}->{day_starting_hour}){ - my $date=time::datetime_to_array(time::add_hours_to_datetime($datetime,-24)); - return $date->[0].'-'.$date->[1].'-'.$date->[2]; - }else{ - #today: between starting_hour and end of day show current day - my $date=time::datetime_to_array(time::time_to_datetime(time())); - return $date->[0]."-".$date->[1]."-".$date->[2]; - } + my $datetime = time::time_to_datetime( time() ); + my $hour = ( time::datetime_to_array($datetime) )->[3]; + + #print STDERR "datetime=$datetime hour=$hour\n"; + #today: between 0:00 and starting_hour show last day + if ( $hour < $config->{date}->{day_starting_hour} ) { + my $date = time::datetime_to_array( time::add_days_to_datetime( $datetime, -1 ) ); + return join( '-', ( $date->[0], $date->[1], $date->[2] ) ); + } else { + + #today: between starting_hour and end of day show current day + my $date = time::datetime_to_array( time::time_to_datetime( time() ) ); + return join( '-', ( $date->[0], $date->[1], $date->[2] ) ); + } } #get datetime object from datetime string -sub get_datetime{ - my $datetime=shift; - my $timezone=shift; +sub get_datetime(;$$) { + my $datetime = shift; + my $timezone = shift; return unless defined $datetime; - return if $datetime eq ''; - my @l = @{time::datetime_to_array($datetime)}; - return undef if scalar(@l)==0; + return if $datetime eq ''; + my @l = @{ time::datetime_to_array($datetime) }; + return undef if scalar(@l) == 0; # catch invalid datees - $datetime=undef; - eval{ - $datetime=DateTime->new( - year =>$l[0], - month =>$l[1], - day =>$l[2], - hour =>$l[3], - minute =>$l[4], - second =>$l[5], - time_zone=> $timezone - ); - }; - return undef unless defined $datetime; + $datetime = undef; + eval { + $datetime = DateTime->new( + year => $l[0], + month => $l[1], + day => $l[2], + hour => $l[3], + minute => $l[4], + second => $l[5], + time_zone => $timezone + ); + }; + return undef unless defined $datetime; $datetime->set_locale('de_DE'); - return $datetime; + return $datetime; } #get list of nth weekday in month from start to end -sub get_nth_weekday_in_month{ - my $start=shift; # datetime string - my $end=shift; # datetime string - my $nth=shift; # every nth week of month - my $weekday=shift; # weekday [0..6,'Mo'-'Su','Mo'-'Fr'] +sub get_nth_weekday_in_month(;$$$$) { + my $start = shift; # datetime string + my $end = shift; # datetime string + my $nth = shift; # every nth week of month + my $weekday = shift; # weekday [1..7,'Mo'-'Su','Mo'-'Fr'] - my $weekdays=time::get_weekdays(); - $weekday=$weekdays->{$weekday+1}; - - my $dates=[]; - if ($start=~/(\d\d\d\d)-(\d\d)-(\d\d)[ T](\d\d)\:(\d\d)/){ - my $hour=int($4); - my $min=int($5); - my $sec=0; - my @date = Date::Manip::ParseRecur("0:1*$nth:$weekday:$hour:$min:$sec", "", $start, $end); - for my $date (@date){ - if ($date=~/(\d\d\d\d)(\d\d)(\d\d)(\d\d)\:(\d\d)\:(\d\d)/){ - push @$dates,"$1-$2-$3 $4:$5:$6"; + return [] unless defined $start; + return [] unless defined $end; + return [] unless defined $nth; + return [] unless defined $weekday; + + my $weekdays = time::getWeekdays(); + return [] unless defined $weekdays->{$weekday}; + $weekday = $weekdays->{$weekday}; + + my $dates = []; + + if ( $start =~ /(\d\d\d\d)-(\d\d)-(\d\d)[ T](\d\d)\:(\d\d)/ ) { + my $hour = int($4); + my $min = int($5); + my $sec = 0; + my @date = Date::Manip::ParseRecur( "0:1*$nth:$weekday:$hour:$min:$sec", "", $start, $end ); + for my $date (@date) { + if ( $date =~ /(\d\d\d\d)(\d\d)(\d\d)(\d\d)\:(\d\d)\:(\d\d)/ ) { + push @$dates, "$1-$2-$3 $4:$5:$6"; } } } diff --git a/lib/calcms/uac.pm b/lib/calcms/uac.pm index 9b312d3..9dc1f06 100644 --- a/lib/calcms/uac.pm +++ b/lib/calcms/uac.pm @@ -1,450 +1,459 @@ -#!/bin/perl +package uac; -use CGI; -#use CGI::Carp qw(warningsToBrowser fatalsToBrowser); -use CGI::Session qw(-ip-match); -use CGI::Cookie; -#$CGI::Session::IP_MATCH=1; - -package uac; -use warnings "all"; use strict; +use warnings; +no warnings 'redefine'; + +use CGI::Session qw(-ip-match); +use CGI::Cookie(); use Data::Dumper; -use auth; -use db; -use template; -use project; -use studios; -#use series; +use auth(); +use db(); +use template(); +use project(); +use studios(); +use user_settings(); +use user_default_studios(); -require Exporter; -our @ISA = qw(Exporter); +#use base 'Exporter'; our @EXPORT_OK = qw( - get_user get_users update_user insert_user delete_user - get_roles insert_role update_role get_role_columns - get_studios_by_user get_users_by_studio - get_projects_by_user - get_user_role get_studio_roles - assign_user_role remove_user_role - get_user_permissions get_user_presets - prepare_request set_template_permissions - permission_denied + get_user get_users update_user insert_user delete_user + get_roles insert_role update_role get_role_columns + get_studios_by_user get_users_by_studio + get_projects_by_user + get_user_role get_studio_roles + assign_user_role remove_user_role + get_user_permissions get_user_presets + prepare_request set_template_permissions + permission_denied ); -our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ] ); - -sub debug; # get user by name -sub get_user{ - my $config=shift; - my $user=shift; +sub get_user($$) { + my $config = shift; + my $user = shift; - my $query=qq{ + my $query = qq{ select id, name, full_name, email, disabled, modified_at, created_at from calcms_users where name=? }; - my $bind_values=[$user]; + my $bind_values = [$user]; - my $dbh=db::connect($config); - my $users=db::get($dbh, $query,$bind_values); - if (@$users!=1){ - print STDERR "cannot find user '$user'\n"; - return undef; - } - return $users->[0]; + my $dbh = db::connect($config); + my $users = db::get( $dbh, $query, $bind_values ); + if ( scalar @$users != 1 ) { + print STDERR "cannot find user '$user'\n"; + return undef; + } + return $users->[0]; } # get all users -sub get_users{ - my $config=shift; +sub get_users($;$) { + my $config = shift; + my $condition = shift; - my $query=qq{ + my @conditions = (); + my @bind_values = (); + + for my $key ( 'name', 'email' ) { + my $value = $condition->{$key}; + next unless defined $value; + next if $value eq ''; + push @conditions, $key . '=?'; + push @bind_values, $value; + } + + my $conditions = ''; + $conditions = " where " . join( " and ", @conditions ) if ( scalar @conditions > 0 ); + + my $query = qq{ select id, name, full_name, email, disabled, modified_at, created_at from calcms_users + $conditions }; - my $dbh=db::connect($config); - my $users=db::get($dbh, $query); - return $users; + my $dbh = db::connect($config); + my $users = db::get( $dbh, $query, \@bind_values ); + return $users; } #TODO: get_users_by_project # get all users of a given studio id # used at series (previously named get_studio_users) -sub get_users_by_studio{ - my $config=shift; - my $condition=shift; +sub get_users_by_studio ($$) { + my $config = shift; + my $condition = shift; - return unless (defined $condition->{studio_id}); + return unless defined $condition->{studio_id}; - my @conditions=(); - my @bind_values=(); + my @conditions = (); + my @bind_values = (); - if ((defined $condition->{project_id}) && ($condition->{project_id} ne '')){ - push @conditions, 'ur.project_id=?'; - push @bind_values, $condition->{project_id}; - } + if ( ( defined $condition->{project_id} ) && ( $condition->{project_id} ne '' ) ) { + push @conditions, 'ur.project_id=?'; + push @bind_values, $condition->{project_id}; + } - if ((defined $condition->{studio_id}) && ($condition->{studio_id} ne '')){ - push @conditions, 'ur.studio_id=?'; - push @bind_values, $condition->{studio_id}; - } + if ( ( defined $condition->{studio_id} ) && ( $condition->{studio_id} ne '' ) ) { + push @conditions, 'ur.studio_id=?'; + push @bind_values, $condition->{studio_id}; + } - my $conditions=''; - $conditions=" and ".join(" and ",@conditions) if (@conditions>0); + my $conditions = ''; + $conditions = " and " . join( " and ", @conditions ) if ( scalar @conditions > 0 ); - my $query=qq{ + my $query = qq{ select distinct(u.id), u.name, u.full_name from calcms_user_roles ur, calcms_users u where ur.user_id=u.id $conditions }; - my $dbh=db::connect($config); - my $users=db::get($dbh, $query, \@bind_values); - return $users; + my $dbh = db::connect($config); + my $users = db::get( $dbh, $query, \@bind_values ); + return $users; } # get projects a user is assigned by name -sub get_projects_by_user{ - my $config=shift; - my $condition=shift; +sub get_projects_by_user ($$) { + my $config = shift; + my $condition = shift; - my @conditions=(); - my @bind_values=(); + my @conditions = (); + my @bind_values = (); - if ((defined $condition->{project_id}) && ($condition->{project_id} ne '')){ - push @conditions, 'ur.project_id=?'; - push @bind_values, $condition->{project_id}; - } + if ( ( defined $condition->{project_id} ) && ( $condition->{project_id} ne '' ) ) { + push @conditions, 'ur.project_id=?'; + push @bind_values, $condition->{project_id}; + } - if ((defined $condition->{studio_id}) && ($condition->{studio_id} ne '')){ - push @conditions, 'ur.studio_id=?'; - push @bind_values, $condition->{studio_id}; - } + if ( ( defined $condition->{studio_id} ) && ( $condition->{studio_id} ne '' ) ) { + push @conditions, 'ur.studio_id=?'; + push @bind_values, $condition->{studio_id}; + } - if ((defined $condition->{user}) && ($condition->{user} ne '')){ - push @conditions, 'u.name=?'; - push @bind_values, $condition->{user}; - } + if ( ( defined $condition->{user} ) && ( $condition->{user} ne '' ) ) { + push @conditions, 'u.name=?'; + push @bind_values, $condition->{user}; + } - my $conditions=''; - $conditions=" and ".join(" and ",@conditions) if (@conditions>0); + my $conditions = ''; + $conditions = " and " . join( " and ", @conditions ) if ( @conditions > 0 ); - my $query=qq{ + my $query = qq{ select distinct p.*, ur.project_id project_id from calcms_user_roles ur, calcms_users u, calcms_projects p where ur.user_id=u.id and p.project_id=ur.project_id $conditions }; - my $dbh=db::connect($config); - my $users=db::get($dbh, $query, \@bind_values); - return $users; + my $dbh = db::connect($config); + my $users = db::get( $dbh, $query, \@bind_values ); + return $users; } # get all studios a user is assigned to by role # used at series (previously named get_user_studios) -sub get_studios_by_user{ - my $config=shift; - my $condition=shift; +sub get_studios_by_user ($$) { + my $config = shift; + my $condition = shift; - my @conditions=(); - my @bind_values=(); + my @conditions = (); + my @bind_values = (); - if ((defined $condition->{project_id}) && ($condition->{project_id} ne '')){ - push @conditions, 'ur.project_id=?'; - push @bind_values, $condition->{project_id}; - } + if ( ( defined $condition->{project_id} ) && ( $condition->{project_id} ne '' ) ) { + push @conditions, 'ur.project_id=?'; + push @bind_values, $condition->{project_id}; + } - if ((defined $condition->{studio_id}) && ($condition->{studio_id} ne '')){ - push @conditions, 'ur.studio_id=?'; - push @bind_values, $condition->{studio_id}; - } + if ( ( defined $condition->{studio_id} ) && ( $condition->{studio_id} ne '' ) ) { + push @conditions, 'ur.studio_id=?'; + push @bind_values, $condition->{studio_id}; + } - if ((defined $condition->{user}) && ($condition->{user} ne '')){ - push @conditions, 'u.name=?'; - push @bind_values, $condition->{user}; - } + if ( ( defined $condition->{user} ) && ( $condition->{user} ne '' ) ) { + push @conditions, 'u.name=?'; + push @bind_values, $condition->{user}; + } - my $conditions=''; - $conditions=" and ".join(" and ",@conditions) if (@conditions>0); + my $conditions = ''; + $conditions = " and " . join( " and ", @conditions ) if ( @conditions > 0 ); - my $query=qq{ + my $query = qq{ select distinct s.*, ur.project_id project_id from calcms_user_roles ur, calcms_users u, calcms_studios s where ur.user_id=u.id and s.id=ur.studio_id $conditions }; - my $dbh=db::connect($config); - my $users=db::get($dbh, $query, \@bind_values); - return $users; + my $dbh = db::connect($config); + my $users = db::get( $dbh, $query, \@bind_values ); + return $users; } -sub insert_user{ - my $config=shift; - my $entry=shift; +sub insert_user($$) { + my $config = shift; + my $entry = shift; - $entry->{created_at} = time::time_to_datetime(time()); - $entry->{modified_at}= time::time_to_datetime(time()); + $entry->{created_at} = time::time_to_datetime( time() ); + $entry->{modified_at} = time::time_to_datetime( time() ); - my $dbh=db::connect($config); - db::insert($dbh, 'calcms_users', $entry); + my $dbh = db::connect($config); + db::insert( $dbh, 'calcms_users', $entry ); } -sub update_user{ - my $config=shift; - my $entry=shift; +sub update_user($$) { + my $config = shift; + my $entry = shift; - $entry->{modified_at}= time::time_to_datetime(time()); + $entry->{modified_at} = time::time_to_datetime( time() ); - my $values =join(",", map {$_.'=?'} (keys %$entry)); - my @bind_values =map {$entry->{$_}} (keys %$entry); - push @bind_values,$entry->{id}; + my @keys = sort keys %$entry; + my $values = join( ",", map { $_ . '=?' } @keys ); + my @bind_values = map { $entry->{$_} } @keys; + push @bind_values, $entry->{id}; - my $query=qq{ + my $query = qq{ update calcms_users set $values where id=? }; - my $dbh =db::connect($config); - db::put($dbh, $query, \@bind_values); + my $dbh = db::connect($config); + db::put( $dbh, $query, \@bind_values ); } -sub delete_user{ - my $config=shift; - my $id=shift; - return unless (defined $id && ($id=~/^\d+$/)); +sub delete_user($$) { + my $config = shift; + my $id = shift; + return unless ( defined $id && ( $id =~ /^\d+$/ ) ); - my $query=qq{ + my $query = qq{ delete from calcms_users where id=? }; - my $dbh =db::connect($config); - db::put($dbh, $query, [$id]); + my $dbh = db::connect($config); + db::put( $dbh, $query, [$id] ); } - # get all roles used by all users of a studio # available conditions: project_id, studio_id -sub get_studio_roles{ - my $config=shift; - my $condition=shift; +sub get_studio_roles($$) { + my $config = shift; + my $condition = shift; - return [] if ($condition->{studio_id} eq ''); + return [] if ( $condition->{studio_id} eq '' ); - my @conditions=(); - my @bind_values=(); + my @conditions = (); + my @bind_values = (); - if ((defined $condition->{project_id}) && ($condition->{project_id} ne '')){ - push @conditions, 'ur.project_id=?'; - push @bind_values, $condition->{project_id}; - } + if ( ( defined $condition->{project_id} ) && ( $condition->{project_id} ne '' ) ) { + push @conditions, 'ur.project_id=?'; + push @bind_values, $condition->{project_id}; + } - if ((defined $condition->{studio_id}) && ($condition->{studio_id} ne '')){ - push @conditions, 'ur.studio_id=?'; - push @bind_values, $condition->{studio_id}; - } + if ( ( defined $condition->{studio_id} ) && ( $condition->{studio_id} ne '' ) ) { + push @conditions, 'ur.studio_id=?'; + push @bind_values, $condition->{studio_id}; + } - my $conditions=''; - $conditions=" and ".join(" and ",@conditions) if (@conditions>0); + my $conditions = ''; + $conditions = " and " . join( " and ", @conditions ) if ( @conditions > 0 ); - my $query=qq{ + my $query = qq{ select r.*, ur.studio_id, ur.project_id from calcms_roles r, calcms_user_roles ur where r.id=ur.role_id $conditions }; - my $dbh=db::connect($config); - my $roles=db::get($dbh, $query, \@bind_values); - return $roles; + my $dbh = db::connect($config); + my $roles = db::get( $dbh, $query, \@bind_values ); + return $roles; } # get role columns (for external use only) -sub get_role_columns{ - my $config=shift; - my $dbh=db::connect($config); - my $columns=db::get_columns_hash($dbh, 'calcms_roles'); - return $columns +sub get_role_columns($) { + my $config = shift; + my $dbh = db::connect($config); + my $columns = db::get_columns_hash( $dbh, 'calcms_roles' ); + return $columns; } # get roles # filter: studio_id project_id -sub get_roles{ - my $config=shift; - my $condition=shift; +sub get_roles($$) { + my $config = shift; + my $condition = shift; - my @conditions=(); - my @bind_values=(); + my @conditions = (); + my @bind_values = (); - my $dbh=db::connect($config); - my $columns=db::get_columns_hash($dbh, 'calcms_roles'); + my $dbh = db::connect($config); + my $columns = db::get_columns_hash( $dbh, 'calcms_roles' ); - for my $column (keys %$columns){ - if (defined $condition->{$column}){ - push @conditions, $column.'=?'; - push @bind_values, $condition->{$column}; + for my $column ( sort keys %$columns ) { + if ( defined $condition->{$column} ) { + push @conditions, $column . '=?'; + push @bind_values, $condition->{$column}; } - } - my $conditions=''; - $conditions=' where '.join(' and ',@conditions) if(@conditions>0); + } + my $conditions = ''; + $conditions = ' where ' . join( ' and ', @conditions ) if ( @conditions > 0 ); - my $query=qq{ + my $query = qq{ select r.* from calcms_roles r $conditions }; - my $roles=db::get($dbh, $query, \@bind_values); + my $roles = db::get( $dbh, $query, \@bind_values ); - return $roles; + return $roles; } #insert role to database, set created_at and modified_at -sub insert_role{ - my $config=shift; - my $entry=shift; +sub insert_role ($$) { + my $config = shift; + my $entry = shift; - $entry->{created_at} = time::time_to_datetime(time()); - $entry->{modified_at}= time::time_to_datetime(time()); + $entry->{created_at} = time::time_to_datetime( time() ); + $entry->{modified_at} = time::time_to_datetime( time() ); - my $dbh=db::connect($config); - my $columns=db::get_columns_hash($dbh, 'calcms_roles'); -; - my $role={}; - for my $column (keys %$columns){ - $role->{$column}=$entry->{$column} if defined $entry->{$column}; + my $dbh = db::connect($config); + my $columns = db::get_columns_hash( $dbh, 'calcms_roles' ); + my $role = {}; + for my $column ( keys %$columns ) { + $role->{$column} = $entry->{$column} if defined $entry->{$column}; } - db::insert($dbh, 'calcms_roles', $role); + db::insert( $dbh, 'calcms_roles', $role ); } #update role, set modified_at -sub update_role{ - my $config=shift; - my $entry=shift; +sub update_role($$) { + my $config = shift; + my $entry = shift; - $entry->{modified_at}= time::time_to_datetime(time()); + $entry->{modified_at} = time::time_to_datetime( time() ); - my $dbh =db::connect($config); - my $columns=db::get_columns_hash($dbh, 'calcms_roles'); - my $values =join(",", map {$_.'=?'} (keys %$columns)); - my @bind_values =map {$entry->{$_}} (keys %$columns); - push @bind_values,$entry->{id}; + my $dbh = db::connect($config); + my $columns = db::get_columns_hash( $dbh, 'calcms_roles' ); + my @keys = sort keys %$columns; + my $values = join( ",", map { $_ . '=?' } @keys ); + my @bind_values = map { $entry->{$_} } @keys; + push @bind_values, $entry->{id}; - my $query=qq{ + my $query = qq{ update calcms_roles set $values where id=? }; -# print $query."<br>\n".Dumper(\@bind_values)."<br>\ņ"; - db::put($dbh, $query, \@bind_values); + db::put( $dbh, $query, \@bind_values ); } # delete role from database -sub delete_role{ - my $config=shift; - my $id=shift; +sub delete_role($$) { + my $config = shift; + my $id = shift; - return unless (defined $id && ($id=~/^\d+$/)); + return unless ( defined $id && ( $id =~ /^\d+$/ ) ); - my $query=qq{ + my $query = qq{ delete from calcms_roles where id=? }; - my $dbh =db::connect($config); - db::put($dbh, $query, [$id]); + my $dbh = db::connect($config); + db::put( $dbh, $query, [$id] ); } # get all roles for given conditions: project_id, studio_id, user_id, name # includes global admin user role -sub get_user_roles{ - my $config=shift; - my $condition=shift; +sub get_user_roles($$) { + my $config = shift; + my $condition = shift; - my @conditions=(); - my @bind_values=(); + my @conditions = (); + my @bind_values = (); - if (defined $condition->{user}){ - push @conditions, 'u.name=?'; - push @bind_values, $condition->{user}; - } - if (defined $condition->{user_id}){ - push @conditions, 'ur.user_id=?'; - push @bind_values, $condition->{user_id}; - } - if (defined $condition->{studio_id}){ - push @conditions, 'ur.studio_id=?'; - push @bind_values, $condition->{studio_id}; - } - if (defined $condition->{project_id}){ - push @conditions, 'ur.project_id=?'; - push @bind_values, $condition->{project_id}; - } + if ( defined $condition->{user} ) { + push @conditions, 'u.name=?'; + push @bind_values, $condition->{user}; + } + if ( defined $condition->{user_id} ) { + push @conditions, 'ur.user_id=?'; + push @bind_values, $condition->{user_id}; + } + if ( defined $condition->{studio_id} ) { + push @conditions, 'ur.studio_id=?'; + push @bind_values, $condition->{studio_id}; + } + if ( defined $condition->{project_id} ) { + push @conditions, 'ur.project_id=?'; + push @bind_values, $condition->{project_id}; + } - my $conditions=''; - $conditions= " and ".join(" and ",@conditions) if (@conditions>0); + my $conditions = ''; + $conditions = " and " . join( " and ", @conditions ) if ( @conditions > 0 ); - my $query=qq{ + my $query = qq{ select distinct r.* from calcms_users u, calcms_user_roles ur, calcms_roles r where ur.user_id=u.id and ur.role_id=r.id $conditions }; - my $dbh=db::connect($config); - my $user_roles=db::get($dbh, $query, \@bind_values); + my $dbh = db::connect($config); + my $user_roles = db::get( $dbh, $query, \@bind_values ); - #return roles, if the contain an admin role - for my $role(@$user_roles){ - return $user_roles if $role->{role}eq'Admin'; - } + #return roles, if the contain an admin role + for my $role (@$user_roles) { + return $user_roles if $role->{role} eq 'Admin'; + } #get all admin roles delete $condition->{studio_id} if defined $condition->{studio_id}; delete $condition->{project_id} if defined $condition->{project_id}; - my $admin_roles=get_admin_user_roles($config, $condition); + my $admin_roles = get_admin_user_roles( $config, $condition ); - #add admin roles to user roles - my @user_roles=(@$admin_roles, @$user_roles); - $user_roles=\@user_roles; + #add admin roles to user roles + my @user_roles = ( @$admin_roles, @$user_roles ); + $user_roles = \@user_roles; - return $user_roles; + return $user_roles; } #return admin user roles for given conditions: project_id, studio_id, user, user_id -sub get_admin_user_roles{ - my $config=shift; - my $condition=shift; +sub get_admin_user_roles ($$) { + my $config = shift; + my $condition = shift; - my @conditions=(); - my @bind_values=(); + my @conditions = (); + my @bind_values = (); - if ((defined $condition->{user}) && ($condition->{user} ne '')){ - push @conditions, 'u.name=?'; - push @bind_values, $condition->{user}; - } - if ((defined $condition->{user_id}) && ($condition->{user_id} ne '')){ - push @conditions, 'ur.user_id=?'; - push @bind_values, $condition->{user_id}; - } - if ((defined $condition->{studio_id}) && ($condition->{studio_id} ne '')){ - push @conditions, 'ur.studio_id=?'; - push @bind_values, $condition->{studio_id}; - } - if ((defined $condition->{project_id}) && ($condition->{project_id} ne '')){ - push @conditions, 'ur.project_id=?'; - push @bind_values, $condition->{project_id}; - } + if ( ( defined $condition->{user} ) && ( $condition->{user} ne '' ) ) { + push @conditions, 'u.name=?'; + push @bind_values, $condition->{user}; + } + if ( ( defined $condition->{user_id} ) && ( $condition->{user_id} ne '' ) ) { + push @conditions, 'ur.user_id=?'; + push @bind_values, $condition->{user_id}; + } + if ( ( defined $condition->{studio_id} ) && ( $condition->{studio_id} ne '' ) ) { + push @conditions, 'ur.studio_id=?'; + push @bind_values, $condition->{studio_id}; + } + if ( ( defined $condition->{project_id} ) && ( $condition->{project_id} ne '' ) ) { + push @conditions, 'ur.project_id=?'; + push @bind_values, $condition->{project_id}; + } - my $conditions=''; - $conditions=" and ".join(" and ",@conditions) if (@conditions>0); + my $conditions = ''; + $conditions = " and " . join( " and ", @conditions ) if ( @conditions > 0 ); - my $query=qq{ + my $query = qq{ select distinct r.*, ur.studio_id, ur.project_id from calcms_users u, calcms_user_roles ur, calcms_roles r where ur.user_id=u.id and ur.role_id=r.id and r.role='Admin' @@ -452,366 +461,400 @@ sub get_admin_user_roles{ limit 1 }; - my $dbh=db::connect($config); - my $user_roles=db::get($dbh, $query, \@bind_values); - return $user_roles; + my $dbh = db::connect($config); + my $user_roles = db::get( $dbh, $query, \@bind_values ); + return $user_roles; } # read permissions for given conditions and add to user_permissions # return user_permissions # studio_id, user_id, name -sub get_user_permissions{ - my $config=shift; - my $conditions=shift; - my $user_permissions=shift; +sub get_user_permissions ($$;$) { + my $config = shift; + my $conditions = shift; + my $user_permissions = shift; - my $user_roles = get_user_roles($config, $conditions); - my $admin_roles = get_admin_user_roles($config, $conditions); - my @user_roles=(@$admin_roles,@$user_roles); + my $user_roles = get_user_roles( $config, $conditions ); + my $admin_roles = get_admin_user_roles( $config, $conditions ); + my @user_roles = ( @$admin_roles, @$user_roles ); - #set default permissions - $user_permissions={} unless(defined $user_permissions); - $user_permissions->{is_admin}=1 if(scalar @$admin_roles>0); + #set default permissions + $user_permissions = {} unless defined $user_permissions; + $user_permissions->{is_admin} = 1 if scalar @$admin_roles > 0; + + my $max_level = 0; - my $max_level=0; # aggregate max permissions # should be limited by project and studio - for my $user_role (@user_roles){ - if ($user_role->{level}>$max_level){ - $user_permissions->{level} = $user_role->{level}; - $user_permissions->{id} = $user_role->{id}; - $user_permissions->{role} = $user_role->{role}; - $user_permissions->{studio_id} = $user_role->{studio_id}; - $user_permissions->{project_id}= $user_role->{project_id}; - $max_level = $user_role->{level}; - } - for my $permission (keys %$user_role){ - if (($permission ne 'level') && ($permission ne 'id') && ($permission ne 'role') && ($permission ne 'studio_id') && ($permission ne 'project_id')){ - $user_permissions->{$permission}=1 if ((defined $user_role->{$permission}) && ($user_role->{$permission} ne '0')); - } - } - } - return $user_permissions; + for my $user_role (@user_roles) { + if ( $user_role->{level} > $max_level ) { + $user_permissions->{level} = $user_role->{level}; + $user_permissions->{id} = $user_role->{id}; + $user_permissions->{role} = $user_role->{role}; + $user_permissions->{studio_id} = $user_role->{studio_id}; + $user_permissions->{project_id} = $user_role->{project_id}; + $max_level = $user_role->{level}; + } + for my $permission ( keys %$user_role ) { + if ( ( $permission ne 'level' ) + && ( $permission ne 'id' ) + && ( $permission ne 'role' ) + && ( $permission ne 'studio_id' ) + && ( $permission ne 'project_id' ) ) + { + $user_permissions->{$permission} = 1 + if ( defined $user_role->{$permission} ) && ( $user_role->{$permission} ne '0' ); + } + } + } + return $user_permissions; } #get user id by user name -sub get_user_id{ - my $config=shift; - my $user=shift; +sub get_user_id ($$) { + my $config = shift; + my $user = shift; - return undef unless (defined $user); + return undef unless defined $user; - my $query=qq{ + my $query = qq{ select id from calcms_users where binary name=? }; - my $dbh=db::connect($config); - my $users=db::get($dbh, $query, [$user]); - return undef if (@$users==0); - return $users->[0]->{id}; + my $dbh = db::connect($config); + my $users = db::get( $dbh, $query, [$user] ); + return undef if scalar @$users == 0; + return $users->[0]->{id}; } #get role id by role name -sub get_role_id{ - my $config=shift; - my $role=shift; +sub get_role_id ($$) { + my $config = shift; + my $role = shift; - return undef unless (defined $role); + return undef unless defined $role; - my $query=qq{ + my $query = qq{ select id from calcms_roles where role=? }; - my $dbh=db::connect($config); - my $roles=db::get($dbh, $query, [$role]); - return undef if (@$roles==0); - return $roles->[0]->{id}; + my $dbh = db::connect($config); + my $roles = db::get( $dbh, $query, [$role] ); + return undef if scalar @$roles == 0; + return $roles->[0]->{id}; } # assign a role to an user (for a studio) -sub assign_user_role{ - my $config=shift; - my $options=shift; - - #print STDERR Dumper($options); - return undef unless defined $options->{project_id}; - return undef unless defined $options->{studio_id}; - return undef unless defined $options->{user_id}; - return undef unless defined $options->{role_id}; +sub assign_user_role($$) { + my $config = shift; + my $options = shift; - #return if already exists - my $query=qq{ + return undef unless defined $options->{project_id}; + return undef unless defined $options->{studio_id}; + return undef unless defined $options->{user_id}; + return undef unless defined $options->{role_id}; + + #return if already exists + my $query = qq{ select * from calcms_user_roles where project_id=? and studio_id=? and user_id=? and role_id=? }; - my $dbh=db::connect($config); - my $user_roles=db::get($dbh, $query, [$options->{project_id}, $options->{studio_id}, $options->{user_id}, $options->{role_id}]); - return undef if (@$user_roles>0); + my $dbh = db::connect($config); + my $user_roles = db::get( $dbh, $query, + [ $options->{project_id}, $options->{studio_id}, $options->{user_id}, $options->{role_id} ] ); + return undef if scalar @$user_roles > 0; - #insert entry - my $entry={ - project_id => $options->{project_id}, - studio_id => $options->{studio_id}, - user_id => $options->{user_id}, - role_id => $options->{role_id}, - created_at => time::time_to_datetime(time()) - }; + #insert entry + my $entry = { + project_id => $options->{project_id}, + studio_id => $options->{studio_id}, + user_id => $options->{user_id}, + role_id => $options->{role_id}, + created_at => time::time_to_datetime( time() ) + }; - return db::insert($dbh, 'calcms_user_roles', $entry); + return db::insert( $dbh, 'calcms_user_roles', $entry ); } # unassign a user from a role of (for a studio) -sub remove_user_role{ - my $config=shift; - my $options=shift; - - return undef unless defined $options->{project_id}; - return undef unless defined $options->{studio_id}; - return undef unless defined $options->{user_id}; - return undef unless defined $options->{role_id}; +sub remove_user_role($$) { + my $config = shift; + my $options = shift; - my $query=qq{ + return undef unless defined $options->{project_id}; + return undef unless defined $options->{studio_id}; + return undef unless defined $options->{user_id}; + return undef unless defined $options->{role_id}; + + my $query = qq{ delete from calcms_user_roles where project_id=? and studio_id=? and user_id=? and role_id=? }; - my $bind_values=[ $options->{project_id}, $options->{studio_id}, $options->{user_id}, $options->{role_id} ]; - #print STDERR Dumper($query).Dumper($bind_values); - my $dbh=db::connect($config); - my $result=db::put($dbh, $query, $bind_values); + my $bind_values = [ $options->{project_id}, $options->{studio_id}, $options->{user_id}, $options->{role_id} ]; + + my $dbh = db::connect($config); + my $result = db::put( $dbh, $query, $bind_values ); # successfully return even if no entry exists return 1; } #checks -sub is_user_assigned_to_studio{ - my $request=shift; - my $options=shift; +sub is_user_assigned_to_studio ($$) { + my $request = shift; + my $options = shift; - my $config = $request->{config}; + my $config = $request->{config}; return 0 unless defined $request->{user}; return 0 unless defined $options->{studio_id}; return 0 unless defined $options->{project_id}; - my $options2={ - user => $request->{user}, + my $options2 = { + user => $request->{user}, studio_id => $options->{studio_id}, project_id => $options->{project_id} }; - my $user_studios=uac::get_studios_by_user($config, $options2); - return 1 if(@$user_studios==1); - return 0; + my $user_studios = uac::get_studios_by_user( $config, $options2 ); + return 1 if scalar @$user_studios == 1; + return 0; } # print errors at get_user_presets and check for project id and studio id # call after header is printed -sub check{ - my $config=shift; - my $params=shift; - my $user_presets=shift; +sub check($$$) { + my $config = shift; + my $params = shift; + my $user_presets = shift; - if (defined $user_presets->{error}){ - uac::print_error($user_presets->{error}); - return undef; + if ( defined $user_presets->{error} ) { + uac::print_error( $user_presets->{error} ); + return 0; } - my $project_check=project::check($config, { project_id => $params->{project_id} } ); - if($project_check ne '1'){ + my $project_check = project::check( $config, { project_id => $params->{project_id} } ); + if ( $project_check ne '1' ) { uac::print_error($project_check); - return undef; + return 0; } - my $studio_check=studios::check($config, { studio_id => $params->{studio_id} } ); - if($studio_check ne '1'){ + my $studio_check = studios::check( $config, { studio_id => $params->{studio_id} } ); + if ( $studio_check ne '1' ) { uac::print_error($studio_check); - return undef; + return 0; } return 1; } # get user, projects and studios user is assigned to for selected values from params # set permissions for selected project and studio -# return request -sub get_user_presets{ - my $config = shift; - my $options = shift; +# return request +sub get_user_presets($$) { + my $config = shift; + my $options = shift; - my $user = $options->{user}||''; - my $error = undef; - return {error=>"no user selected"} if ($user eq''); - - my $project_id = $options->{project_id}||''; - my $studio_id = $options->{studio_id}||''; - $config->{access}->{write}=0; + my $user = $options->{user} || ''; + my $error = undef; + return { error => "no user selected" } if ( $user eq '' ); - #get - my $admin_roles = get_admin_user_roles($config, {user=>$user}); + my $project_id = $options->{project_id} || ''; + my $studio_id = $options->{studio_id} || ''; + $config->{access}->{write} = 0; + + my $user_settings = user_settings::get( $config, { user => $user } ); + $project_id = $user_settings->{project_id} // '' if $project_id eq ''; + my $defaults = user_default_studios::get( $config, { user => $user, project_id => $project_id } ); + $studio_id = $defaults->{studio_id} // $user_settings->{studio_id} // '' if $studio_id eq ''; + + #get + my $admin_roles = get_admin_user_roles( $config, { user => $user } ); #get all projects by user - my $projects = uac::get_projects_by_user($config, {user=>$user}); - return {error=>"no project is assigned to user"} if(@$projects==0); + my $projects = uac::get_projects_by_user( $config, { user => $user } ); + return { error => "no project is assigned to user" } if scalar @$projects == 0; - $projects=project::get($config) if(@$admin_roles>0); - my @projects=reverse sort {$a->{end_date} cmp $b->{end_date}} (@$projects); - $projects=\@projects; + $projects = project::get($config) if ( @$admin_roles > 0 ); + my @projects = reverse sort { $a->{end_date} cmp $b->{end_date} } (@$projects); + $projects = \@projects; - if ($project_id ne'' && $project_id ne'-1'){ - my $projectFound=0; - for my $project(@$projects){ - if ($project->{project_id} eq $project_id){ - $projectFound=1; + if ( $project_id ne '' && $project_id ne '-1' ) { + my $projectFound = 0; + for my $project (@$projects) { + if ( $project->{project_id} eq $project_id ) { + $projectFound = 1; last; - }; + } } - return {error=>"project is not assigned to user"} if($projectFound==0); - }else{ - $project_id=$projects->[0]->{project_id}; + return { error => "project is not assigned to user" } if ( $projectFound == 0 ); + } else { + $project_id = $projects->[0]->{project_id}; } - #print STDERR "project:$project_id\n"; #check if studios are assigned to project - my $studios = project::get_studios($config, {project_id => $project_id}); - $error="no studio is assigned to project" if (@$studios==0); + my $studios = project::get_studios( $config, { project_id => $project_id } ); + $error = "no studio is assigned to project" if scalar @$studios == 0; + + if ( scalar @$admin_roles == 0 ) { - if(@$admin_roles==0){ #get all studios by user - $studios=uac::get_studios_by_user($config, {user=>$user, project_id=>$project_id}); - $error="no studio is assigned to user" if (@$studios==0); - if (($studio_id ne '')&&($studio_id ne '-1')){ - my $studioFound=0; - for my $studio(@$studios){ - if ($studio->{id} eq $studio_id){ - $studioFound=1; + $studios = uac::get_studios_by_user( $config, { user => $user, project_id => $project_id } ); + $error = "no studio is assigned to user" if scalar @$studios == 0; + if ( ( $studio_id ne '' ) && ( $studio_id ne '-1' ) ) { + my $studioFound = 0; + for my $studio (@$studios) { + if ( $studio->{id} eq $studio_id ) { + $studioFound = 1; last; - }; + } } - $error="studio is not assigned to user" if($studioFound==0); - }else{ - $studio_id =$studios->[0]->{id}; - } - }else{ + $error = "studio is not assigned to user" if ( $studioFound == 0 ); + } else { + $studio_id = $studios->[0]->{id} unless defined $studio_id; + } + } else { + #for admin get studios by project - $studios = studios::get($config, {project_id => $project_id}); - if (($studio_id ne '')&&($studio_id ne '-1')){ - my $studioFound=0; - for my $studio(@$studios){ - if ($studio->{id} eq $studio_id){ - $studioFound=1; + $studios = studios::get( $config, { project_id => $project_id } ); + if ( ( $studio_id ne '' ) && ( $studio_id ne '-1' ) ) { + my $studioFound = 0; + for my $studio (@$studios) { + if ( $studio->{id} eq $studio_id ) { + $studioFound = 1; last; - }; + } } - $error="studio is not assigned to project" if($studioFound==0); - }else{ - $studio_id =$studios->[0]->{id}; - } + $error = "studio is not assigned to project" if ( $studioFound == 0 ); + } else { + $studio_id = $studios->[0]->{id} unless defined $studio_id; + } } - my $permissions=uac::get_user_permissions($config, {user=>$user, project_id=>$project_id, studio_id=>$studio_id}); + my $permissions = + uac::get_user_permissions( $config, { user => $user, project_id => $project_id, studio_id => $studio_id } ); #only admin is allowed to select all projects -# if($permissions->{is_admin}==1){ -# $projects=project::get($config); -# } + # if($permissions->{is_admin}==1){ + # $projects=project::get($config); + # } - #set studios and projects as selected, TODO:do in JS - my $selectedProject={}; - for my $project(@$projects){ - if ($project_id eq $project->{project_id}){ - $project->{selected}='selected="selected"'; - $selectedProject=$project; - last; - }; - } + #set studios and projects as selected, TODO:do in JS + my $selectedProject = {}; + for my $project (@$projects) { + if ( $project_id eq $project->{project_id} ) { + $project->{selected} = 'selected="selected"'; + $selectedProject = $project; + last; + } + } - my $selectedStudio={}; - for my $studio(@$studios){ - if ($studio_id eq $studio->{id}){ - $studio->{selected}='selected="selected"'; - $selectedStudio=$studio; - last; - }; - } + my $selectedStudio = {}; + for my $studio (@$studios) { + if ( $studio_id eq $studio->{id} ) { + $studio->{selected} = 'selected="selected"'; + $selectedStudio = $studio; + last; + } + } - my $logout_url=(split(/\//, $0))[-1]; + my $logout_url = ( split( /\//, $0 ) )[-1]; - #print STDERR "ok\n"; - my $result={ - user => $user, - logout_url => $logout_url, + my $result = { + user => $user, + logout_url => $logout_url, - project_id => $project_id, # from parameter or default - projects => $projects, - project => $selectedProject, + project_id => $project_id, # from parameter or default + projects => $projects, + project => $selectedProject, - studio_id => $studio_id, # from parameter or default - studios => $studios, - studio => $selectedStudio, + studio_id => $studio_id, # from parameter or default + studios => $studios, + studio => $selectedStudio, - permissions => $permissions, # from parameter or default - config => $config - }; - $result->{error}=$error if defined $error; - return $result; + permissions => $permissions, # from parameter or default + config => $config + }; + $result->{error} = $error if defined $error; + return $result; +} + +sub setDefaultProject ($$) { + my $params = shift; + my $user_presets = shift; + + $params->{project_id} = $user_presets->{project_id} + if ( !defined $params->{authAction} ) || ( $params->{authAction} eq '' ) || ( $params->{authAction} eq 'login' ); + return $params; +} + +sub setDefaultStudio($$) { + my $params = shift; + my $user_presets = shift; + + $params->{studio_id} = $user_presets->{studio_id} + if ( !defined $params->{authAction} ) || ( $params->{authAction} eq '' ) || ( $params->{authAction} eq 'login' ); + return $params; } #set user preset properties to request -sub prepare_request{ - my $request=shift; - my $user_presets=shift; +sub prepare_request ($$) { + my $request = shift; + my $user_presets = shift; - for my $key (keys %$user_presets){ - $request->{$key}=$user_presets->{$key}; - } - #enrich menu parameters - for my $key ('studio_id', 'project_id', 'studio', 'project', 'studios', 'projects', 'user', 'logout_url'){ - $request->{params}->{checked}->{presets}->{$key}=$user_presets->{$key}; - } - return $request; + for my $key ( keys %$user_presets ) { + $request->{$key} = $user_presets->{$key}; + } + + #enrich menu parameters + for my $key ( 'studio_id', 'project_id', 'studio', 'project', 'studios', 'projects', 'user', 'logout_url' ) { + $request->{params}->{checked}->{presets}->{$key} = $user_presets->{$key}; + } + return $request; } #TODO: shift to permissions sub entry -sub set_template_permissions{ - my $permissions = shift; - my $params = shift; +sub set_template_permissions ($$) { + my $permissions = shift; + my $params = shift; - for my $usecase (keys %$permissions){ - $params->{'allow'}->{$usecase}=1 if ($permissions->{$usecase}eq'1'); - } - return $params; + for my $usecase ( keys %$permissions ) { + $params->{'allow'}->{$usecase} = 1 if ( $permissions->{$usecase} eq '1' ); + } + return $params; } #print error message -sub permissions_denied{ - my $message=shift; - $message=~s/_/ /g; - print '<div class="error">Sorry! Missing permissions to '.$message.'</div>'."\n"; - print STDERR 'Sorry! Missing permissions to '.$message."\n"; +sub permissions_denied($) { + my $message = shift; + $message =~ s/_/ /g; + print '<div class="error">Sorry! Missing permissions to ' . $message . '</div>' . "\n"; + print STDERR 'Sorry! Missing permissions to ' . $message . "\n"; } -sub print_info{ +sub print_info($) { print '<div class="ok head">' - .'<span class="ui-icon ui-icon-check" style="float:left"></span> ' - .$_[0] - .'</div>'."\n"; + . '<span class="ui-icon ui-icon-check" style="float:left"></span> ' + . $_[0] + . '</div>' . "\n"; } -sub print_warn{ +sub print_warn($) { print '<div class="warn head">' - .'<span class="ui-icon ui-icon-info" style="float:left"></span> ' - .$_[0] - .'</div>'."\n"; + . '<span class="ui-icon ui-icon-info" style="float:left"></span> ' + . $_[0] + . '</div>' . "\n"; } -sub print_error{ +sub print_error ($) { + my $message = shift; + print STDERR "ERROR:" . $message . "\n"; print '<div class="error" head>' - .'<span class="ui-icon ui-icon-alert" style="float:left"></span> ' - .$_[0]. - '</div>'."\n"; + . '<span class="ui-icon ui-icon-alert" style="float:left"></span> ' + . $message + . '</div>' . "\n"; } #do not delete last line! diff --git a/lib/calcms/user_day_start.pm b/lib/calcms/user_day_start.pm new file mode 100644 index 0000000..9fce22e --- /dev/null +++ b/lib/calcms/user_day_start.pm @@ -0,0 +1,126 @@ +package user_day_start; + +use strict; +use warnings; +no warnings 'redefine'; + +use Data::Dumper; + +# table: calcms_user_day_start +# columns: user, project_id, studio_id, series_id, day_start + +sub get_columns($) { + my $config = shift; + + my $dbh = db::connect($config); + return db::get_columns_hash( $dbh, 'calcms_user_day_start' ); +} + +sub get ($$) { + my $config = shift; + my $condition = shift; + + my @conditions = (); + my @bind_values = (); + + return unless defined $condition->{user}; + return unless defined $condition->{project_id}; + return unless defined $condition->{studio_id}; + + for my $field ('user', 'project_id', 'studio_id'){ + if ( ( defined $condition->{$field} ) && ( $condition->{$field} ne '' ) ) { + push @conditions, $field.'=?'; + push @bind_values, $condition->{$field}; + } + } + + my $conditions = ''; + $conditions = " where " . join( " and ", @conditions ) if scalar(@conditions) > 0; + + my $query = qq{ + select * + from calcms_user_day_start + $conditions + }; + + my $dbh = db::connect($config); + my $entries = db::get( $dbh, $query, \@bind_values ); + return $entries->[0] || undef; +} + +sub insert_or_update($$){ + my $config = shift; + my $entry = shift; + print STDERR Dumper $entry; + if ( get($config, $entry) ){ + update ($config, $entry); + } else { + insert ($config, $entry); + } +} + +sub insert ($$) { + my $config = shift; + my $entry = shift; + + return unless defined $entry->{user}; + return unless defined $entry->{project_id}; + return unless defined $entry->{studio_id}; + return unless defined $entry->{day_start}; + + my $dbh = db::connect($config); + print STDERR "insert".Dumper($entry ); + return db::insert( $dbh, 'calcms_user_day_start', $entry ); +} + +sub update($$) { + my $config = shift; + my $entry = shift; + + my $fields = [ 'user', 'project_id', 'studio_id' ]; + for (@$fields){ + return unless defined $entry->{$_} + }; + + my @keys = sort keys %$entry; + my $values = join( ",", map { $_ . '=?' } @keys ); + my @bind_values = map { $entry->{$_} } ( @keys, @$fields ); + my $conditions = join (' and ', map { $_.'=?' } @$fields ); + + my $query = qq{ + update calcms_user_day_start + set $values + where $conditions + }; + + print STDERR "update".Dumper($query ).Dumper(\@bind_values); + my $dbh = db::connect($config); + return db::put( $dbh, $query, \@bind_values ); +} + +sub delete ($$) { + my $config = shift; + my $entry = shift; + + return unless defined $entry->{user}; + return unless defined $entry->{project_id}; + return unless defined $entry->{studio_id}; + + my $query = qq{ + delete + from calcms_user_day_start + where user=? and project_id=? and studio_id=? + }; + my $bind_values = [ $entry->{user}, $entry->{project_id}, $entry->{studio_id} ]; + + my $dbh = db::connect($config); + return db::put( $dbh, $query, $bind_values ); +} + +sub error ($) { + my $msg = shift; + print "ERROR: $msg<br/>\n"; +} + +#do not delete last line! +1; diff --git a/lib/calcms/user_default_studios.pm b/lib/calcms/user_default_studios.pm new file mode 100644 index 0000000..4d2e619 --- /dev/null +++ b/lib/calcms/user_default_studios.pm @@ -0,0 +1,109 @@ +package user_default_studios; + +use strict; +use warnings; +no warnings 'redefine'; + +use Data::Dumper; + +# table: calcms_user_default_studios +# columns: user, project_id, studio_id + +sub get_columns($) { + my $config = shift; + + my $dbh = db::connect($config); + return db::get_columns_hash( $dbh, 'calcms_user_default_studios' ); +} + +sub get ($$) { + my $config = shift; + my $condition = shift; + + my @conditions = (); + my @bind_values = (); + + if ( ( defined $condition->{user} ) && ( $condition->{user} ne '' ) ) { + push @conditions, 'user=?'; + push @bind_values, $condition->{user}; + } + if ( ( defined $condition->{project_id} ) && ( $condition->{project_id} ne '' ) ) { + push @conditions, 'project_id=?'; + push @bind_values, $condition->{project_id}; + } + if ( ( defined $condition->{studio_id} ) && ( $condition->{studio_id} ne '' ) ) { + push @conditions, 'studio_id=?'; + push @bind_values, $condition->{studio_id}; + } + + my $conditions = ''; + $conditions = " where " . join( " and ", @conditions ) if scalar(@conditions) > 0; + + my $query = qq{ + select * + from calcms_user_default_studios + $conditions + }; + + my $dbh = db::connect($config); + my $entries = db::get( $dbh, $query, \@bind_values ); + return $entries->[0] || undef; +} + +sub insert ($$) { + my $config = shift; + my $entry = shift; + + return unless defined $entry->{user}; + + my $dbh = db::connect($config); + return db::insert( $dbh, 'calcms_user_default_studios', $entry ); +} + +sub update($$) { + my $config = shift; + my $entry = shift; + + return unless defined $entry->{user}; + + my @keys = sort keys %$entry; + my $values = join( ",", map { $_ . '=?' } @keys ); + my @bind_values = map { $entry->{$_} } @keys; + + push @bind_values, $entry->{user}; + push @bind_values, $entry->{project_id}; + + my $query = qq{ + update calcms_user_default_studios + set $values + where user=? and project_id=? + }; + + my $dbh = db::connect($config); + return db::put( $dbh, $query, \@bind_values ); +} + +sub delete ($$) { + my $config = shift; + my $entry = shift; + + return unless defined $entry->{user}; + + my $query = qq{ + delete + from calcms_user_default_studios + where user=? + }; + my $bind_values = [ $entry->{user} ]; + + my $dbh = db::connect($config); + return db::put( $dbh, $query, $bind_values ); +} + +sub error ($) { + my $msg = shift; + print "ERROR: $msg<br/>\n"; +} + +#do not delete last line! +1; diff --git a/lib/calcms/user_selected_events.pm b/lib/calcms/user_selected_events.pm new file mode 100644 index 0000000..052def5 --- /dev/null +++ b/lib/calcms/user_selected_events.pm @@ -0,0 +1,125 @@ +package user_selected_events; + +use strict; +use warnings; +no warnings 'redefine'; + +use Data::Dumper; + +# table: calcms_user_selected_events +# columns: user, project_id, studio_id, series_id, <- selection +# project_studio_filter, series_filter <- optional filter params +# selected_project, selected_studio, selected_series, selected_event <-result + +sub get_columns($) { + my $config = shift; + + my $dbh = db::connect($config); + return db::get_columns_hash( $dbh, 'calcms_user_selected_events' ); +} + +sub get ($$) { + my $config = shift; + my $condition = shift; + + my @conditions = (); + my @bind_values = (); + + return unless defined $condition->{user}; + return unless defined $condition->{project_id}; + return unless defined $condition->{studio_id}; + return unless defined $condition->{series_id}; + + for my $field ('user', 'project_id', 'studio_id', 'series_id', + 'filter_project_studio', 'filter_series' + ){ + if ( ( defined $condition->{$field} ) && ( $condition->{$field} ne '' ) ) { + push @conditions, $field.'=?'; + push @bind_values, $condition->{$field}; + } + } + + my $conditions = ''; + $conditions = " where " . join( " and ", @conditions ) if scalar(@conditions) > 0; + + my $query = qq{ + select * + from calcms_user_selected_events + $conditions + }; + + my $dbh = db::connect($config); + my $entries = db::get( $dbh, $query, \@bind_values ); + return $entries->[0] || undef; +} + +sub insert ($$) { + my $config = shift; + my $entry = shift; + + return unless defined $entry->{user}; + return unless defined $entry->{project_id}; + return unless defined $entry->{studio_id}; + return unless defined $entry->{series_id}; + return unless defined $entry->{selected_event}; + + my $dbh = db::connect($config); + print STDERR "insert".Dumper($entry ); + return db::insert( $dbh, 'calcms_user_selected_events', $entry ); +} + +sub update($$) { + my $config = shift; + my $entry = shift; + + my $fields = [ + 'user', 'project_id', 'studio_id', 'series_id', + 'filter_project_studio', 'filter_series' + ]; + for (@$fields){ + return unless defined $entry->{$_} + }; + + my @keys = sort keys %$entry; + my $values = join( ",", map { $_ . '=?' } @keys ); + my @bind_values = map { $entry->{$_} } ( @keys, @$fields ); + my $conditions = join (' and ', map { $_.'=?' } @$fields ); + + my $query = qq{ + update calcms_user_selected_events + set $values + where $conditions + }; + + print STDERR "update".Dumper($query ).Dumper(\@bind_values); + my $dbh = db::connect($config); + return db::put( $dbh, $query, \@bind_values ); +} + +sub delete ($$) { + my $config = shift; + my $entry = shift; + + return unless defined $entry->{user}; + return unless defined $entry->{project_id}; + return unless defined $entry->{studio_id}; + return unless defined $entry->{series_id}; + + my $query = qq{ + delete + from calcms_user_selected_events + where user=? and project_id=? and studio_id=? and series_id=? + }; + my $bind_values = [ $entry->{user}, $entry->{project_id}, $entry->{studio_id}, $entry->{series_id} ]; + + my $dbh = db::connect($config); + return db::put( $dbh, $query, $bind_values ); +} + +sub error ($) { + my $msg = shift; + print "ERROR: $msg<br/>\n"; +} + +#do not delete last line! +1; diff --git a/lib/calcms/user_sessions.pm b/lib/calcms/user_sessions.pm new file mode 100644 index 0000000..ef3917a --- /dev/null +++ b/lib/calcms/user_sessions.pm @@ -0,0 +1,225 @@ +package user_sessions; + +use strict; +use warnings; +no warnings 'redefine'; + +use Digest::MD5(); + +use time; + +# access user name by session id + +# table: calcms_user_sessions +# columns: id, +# user, +# timeout, +# pid, +# start (timestamp), +# end (timestamp), + +#use base 'Exporter'; +our @EXPORT_OK = qw(get_columns get insert update delete); + +sub get_columns($) { + my $config = shift; + + my $dbh = db::connect($config); + return db::get_columns_hash( $dbh, 'calcms_user_sessions' ); +} + +#map schedule id to id +sub get($$) { + my $config = shift; + my $condition = shift; + + my $dbh = db::connect($config); + + my @conditions = (); + my @bind_values = (); + + if ( ( defined $condition->{id} ) && ( $condition->{id} ne '' ) ) { + push @conditions, 'id=?'; + push @bind_values, $condition->{id}; + } + + if ( ( defined $condition->{user} ) && ( $condition->{user} ne '' ) ) { + push @conditions, 'user=?'; + push @bind_values, $condition->{user}; + } + + if ( ( defined $condition->{session_id} ) && ( $condition->{session_id} ne '' ) ) { + push @conditions, 'session_id=?'; + push @bind_values, $condition->{session_id}; + } + + if ( ( defined $condition->{start} ) && ( $condition->{start} ne '' ) ) { + push @conditions, 'start>?'; + push @bind_values, $condition->{start}; + } + + my $conditions = ''; + $conditions = " where " . join( " and ", @conditions ) if @conditions; + + my $query = qq{ + select * + from calcms_user_sessions + $conditions + order by start + }; + + my $entries = db::get( $dbh, $query, \@bind_values ); + return $entries; +} + +# insert entry and return database id +sub insert ($$) { + my $config = shift; + my $entry = shift; + + return undef unless defined $entry->{user}; + return undef unless defined $entry->{timeout}; + + unless ( defined $entry->{session_id} ) { + my $md5 = Digest::MD5->new(); + $md5->add( $$, time(), rand(time) ); + $entry->{session_id} = $md5->hexdigest(); + } + + $entry->{pid} = $$; + $entry->{expires_at} = time::time_to_datetime( time() + $entry->{timeout} ); + + my $dbh = db::connect($config); + return db::insert( $dbh, 'calcms_user_sessions', $entry ); +} + +# start session and return generated session id +sub start($$) { + my $config = shift; + my $entry = shift; + + return undef unless defined $entry->{user}; + return undef unless defined $entry->{timeout}; + + my $id = insert( + $config, + { + user => $entry->{user}, + timeout => $entry->{timeout}, + } + ); + return undef unless defined $id; + + my $sessions = get( $config, { id => $id } ); + return undef unless defined $sessions; + + my $session = $sessions->[0]; + return undef unless defined $session; + + return $session->{session_id}; +} + +# expand session by timeout +sub keep_alive ($$) { + my $config = shift; + my $entry = shift; + + return undef unless defined $entry; + + $entry->{pid} = $$; + $entry->{expires_at} = time::time_to_datetime( time() + $entry->{timeout} ); + + my $dbh = db::connect($config); + return update( $config, $entry ); +} + +# get session by session id and expand session if valid +sub check($$) { + my $config = shift; + my $entry = shift; + + return undef unless defined $entry; + my $entries = get( $config, { session_id => $entry->{session_id} } ); + return undef unless defined $entry; + + $entry = $entries->[0]; + return undef unless defined $entry; + + my $now = time::time_to_datetime( time() ); + return undef unless defined $entry->{expires_at}; + return undef unless defined $entry->{user}; + + return undef if $entry->{expires_at} le $now; + return undef if $entry->{end} && ( $entry->{end} le $now ); + + keep_alive( $config, $entry ); + return $entry; +} + +# stop session +sub stop ($$) { + my $config = shift; + my $entry = shift; + + return undef unless defined $entry; + + my $entries = get( $config, { session_id => $entry->{session_id} } ); + return undef unless defined $entries; + + $entry = $entries->[0]; + return undef unless defined $entry; + + $entry->{end} = time::time_to_datetime( time() ); + + my $dbh = db::connect($config); + return update( $config, $entry ); +} + +#schedule id to id +sub update ($$) { + my $config = shift; + my $entry = shift; + + return undef unless defined $entry->{session_id}; + + my $dbh = db::connect($config); + my @keys = sort keys %$entry; + my $values = join( ",", map { $_ . '=?' } @keys ); + my @bind_values = map { $entry->{$_} } @keys; + + push @bind_values, $entry->{session_id}; + + my $query = qq{ + update calcms_user_sessions + set $values + where session_id=? + }; + return db::put( $dbh, $query, \@bind_values ); +} + +#map schedule id to id +sub delete($$) { + my $config = shift; + my $entry = shift; + + return undef unless defined $entry->{session_id}; + + my $dbh = db::connect($config); + + my $query = qq{ + delete + from calcms_user_sessions + where session_id=? + }; + my $bind_values = [ $entry->{session_id} ]; + + return db::put( $dbh, $query, $bind_values ); +} + +sub error($) { + my $msg = shift; + print "ERROR: $msg<br/>\n"; +} + +#do not delete last line! +1; diff --git a/lib/calcms/user_settings.pm b/lib/calcms/user_settings.pm index a142885..6ca6da8 100644 --- a/lib/calcms/user_settings.pm +++ b/lib/calcms/user_settings.pm @@ -1,217 +1,223 @@ -package user_settings; -use warnings "all"; +package user_settings; + use strict; +use warnings; +no warnings 'redefine'; + use Data::Dumper; -use series_dates; +use series_dates(); # table: calcms_user_settings # columns: user, colors -require Exporter; -our @ISA = qw(Exporter); +#use base 'Exporter'; our @EXPORT_OK = qw(getColors getColorCss get insert update delete get_columns defaultColors); -our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ] ); -sub debug; - -our $defaultColors=[ +our $defaultColors = [ { name => 'color_event', css => '#content .event', color => '#c5e1a5' - },{ + }, + { name => 'color_draft', css => '#content .draft', color => '#eeeeee', - },{ + }, + { name => 'color_schedule', css => '#content .schedule', color => '#dde4e6', - },{ + }, + { name => 'color_published', css => '#content .event.published', color => '#a5d6a7', - },{ + }, + { name => 'color_no_series', css => '#content .event.no_series', color => '#fff59d', - },{ + }, + { name => 'color_marked', css => '#content .event.marked', color => '#81d4fa', - },{ + }, + { name => 'color_event_error', css => '#content.conflicts .event.error', color => '#ffab91', - },{ + }, + { name => 'color_schedule_error', css => '#content.conflicts .schedule.error', color => '#ffcc80' - },{ + }, + { name => 'color_work', css => '#content .work', color => '#b39ddb' - },{ + }, + { name => 'color_playout', css => '#content .play', color => '#90caf9' } ]; -sub getColors{ - my $config=shift; - my $conditions=shift; +sub getColors($$) { + my $config = shift; + my $conditions = shift; + return unless defined $conditions->{user}; - my $user=$conditions->{user}; + my $user = $conditions->{user}; #get defaultColors - my $colors=[]; - my $colorMap={}; - for my $defaultColor (@$defaultColors){ - my $color= { + my $colors = []; + my $colorMap = {}; + for my $defaultColor (@$defaultColors) { + my $color = { name => $defaultColor->{name}, css => $defaultColor->{css}, color => $defaultColor->{color}, }; - push @$colors,$color; - $colorMap->{$color->{css}}=$color; - } + push @$colors, $color; + $colorMap->{ $color->{css} } = $color; + } + + my $settings = user_settings::get( $config, { user => $user } ); + $settings->{colors} |= ''; - my $settings = user_settings::get($config, {user => $user }); - $settings->{colors} |=''; #overwrite colors from user settings - for my $line (split(/\n+/, $settings->{colors})){ - my ($key,$value)=split(/\=/,$line); - $key=~s/^\s+//; - $key=~s/\s+$//; - $value=~s/^\s+//; - $value=~s/\s+$//; - $colorMap->{$key}->{color}=$value if (($key ne '')&&($value ne '')&&(defined $colorMap->{$key})); + for my $line ( split( /\n+/, $settings->{colors} ) ) { + my ( $key, $value ) = split( /\=/, $line ); + $key =~ s/^\s+//; + $key =~ s/\s+$//; + $value =~ s/^\s+//; + $value =~ s/\s+$//; + $colorMap->{$key}->{color} = $value if ( $key ne '' ) && ( $value ne '' ) && ( defined $colorMap->{$key} ); } return $colors; } -sub getColorCss{ - my $config=shift; - my $conditions=shift; +sub getColorCss ($$) { + my $config = shift; + my $conditions = shift; return unless defined $conditions->{user}; - - my $shift=20; - my $limit=220; - - my $colors=getColors($config, $conditions); - my $style="<style>\n"; - for my $color (@$colors){ - $style.= $color->{css}."{\n\tbackground-color:".$color->{color}.";\n}\n"; - my $c=$color->{color}; - if ($c=~/#([a-fA-F0-9][a-fA-F0-9])([a-fA-F0-9][a-fA-F0-9])([a-fA-F0-9][a-fA-F0-9])/){ - my $r=hex($1); - my $g=hex($2); - my $b=hex($3); - if ($r>$limit){$r-=$shift;}else{$r+=$shift;} - if ($g>$limit){$g-=$shift;}else{$g+=$shift;} - if ($b>$limit){$b-=$shift;}else{$b+=$shift;} - $c=sprintf("#%x%x%x",$r,$g,$b); - $style.= $color->{css}.":hover{\n\tbackground-color:".$c.";\n}\n"; + + my $shift = 20; + my $limit = 220; + + my $colors = getColors( $config, $conditions ); + my $style = "<style>\n"; + for my $color (@$colors) { + $style .= $color->{css} . "{\n\tbackground-color:" . $color->{color} . ";\n}\n"; + my $c = $color->{color}; + if ( $c =~ /#([a-fA-F0-9][a-fA-F0-9])([a-fA-F0-9][a-fA-F0-9])([a-fA-F0-9][a-fA-F0-9])/ ) { + my $r = hex($1); + my $g = hex($2); + my $b = hex($3); + if ( $r > $limit ) { $r -= $shift; } + else { $r += $shift; } + if ( $g > $limit ) { $g -= $shift; } + else { $g += $shift; } + if ( $b > $limit ) { $b -= $shift; } + else { $b += $shift; } + $c = sprintf( "#%x%x%x", $r, $g, $b ); + $style .= $color->{css} . ":hover{\n\tbackground-color:" . $c . ";\n}\n"; } } - $style.="</style>\n"; + $style .= "</style>\n"; return $style; } +sub get_columns($) { + my $config = shift; -sub get_columns{ - my $config=shift; - - my $dbh=db::connect($config); - my $cols=db::get_columns($dbh, 'calcms_user_settings'); - my $columns={}; - for my $col (@$cols){ - $columns->{$col}=1; - } - return $columns; + my $dbh = db::connect($config); + return db::get_columns_hash( $dbh, 'calcms_user_settings' ); } -sub get{ - my $config=shift; - my $condition=shift; +sub get ($$) { + my $config = shift; + my $condition = shift; - my $dbh=db::connect($config); + my $dbh = db::connect($config); - my @conditions=(); - my @bind_values=(); + my @conditions = (); + my @bind_values = (); - if ((defined $condition->{user}) && ($condition->{user} ne '')){ - push @conditions, 'user=?'; - push @bind_values, $condition->{user}; - } + if ( ( defined $condition->{user} ) && ( $condition->{user} ne '' ) ) { + push @conditions, 'user=?'; + push @bind_values, $condition->{user}; + } - my $conditions=''; - $conditions=" where ".join(" and ",@conditions) if (@conditions>0); + my $conditions = ''; + $conditions = " where " . join( " and ", @conditions ) if ( @conditions > 0 ); - my $query=qq{ + my $query = qq{ select * from calcms_user_settings $conditions }; - #print $query."\n"; - #print Dumper(\@bind_values); - my $entries=db::get($dbh, $query, \@bind_values); - return $entries->[0]||undef; + my $entries = db::get( $dbh, $query, \@bind_values ); + return $entries->[0] || undef; } -sub insert{ - my $config=shift; - my $entry=shift; +sub insert ($$) { + my $config = shift; + my $entry = shift; - return unless(defined $entry->{user}); - return unless(defined $entry->{colors}); - my $dbh=db::connect($config); - return db::insert($dbh, 'calcms_user_settings', $entry); + return unless defined $entry->{user}; + + my $dbh = db::connect($config); + return db::insert( $dbh, 'calcms_user_settings', $entry ); } -sub update{ - my $config=shift; - my $entry=shift; +sub update($$) { + my $config = shift; + my $entry = shift; - return unless(defined $entry->{user}); - return unless(defined $entry->{colors}); + return unless ( defined $entry->{user} ); - my $dbh=db::connect($config); - my $values =join(",", map {$_.'=?'} (keys %$entry)); - my @bind_values =map {$entry->{$_}} (keys %$entry); - push @bind_values,$entry->{user}; + my $dbh = db::connect($config); + my @keys = sort keys %$entry; + my $values = join( ",", map { $_ . '=?' } @keys ); + my @bind_values = map { $entry->{$_} } @keys; + push @bind_values, $entry->{user}; - my $query=qq{ + my $query = qq{ update calcms_user_settings set $values where user=? }; - db::put($dbh, $query, \@bind_values); - print "done\n"; + + db::put( $dbh, $query, \@bind_values ); + print "done\n"; } -sub delete{ - my $config=shift; - my $entry=shift; - - return unless(defined $entry->{user}); +sub delete ($$) { + my $config = shift; + my $entry = shift; - my $dbh=db::connect($config); + return unless ( defined $entry->{user} ); - my $query=qq{ + my $dbh = db::connect($config); + + my $query = qq{ delete from calcms_user_settings where user=? }; - my $bind_values=[$entry->{user}]; - #print '<pre>$query'.$query.Dumper($bind_values).'</pre>'; - db::put($dbh, $query, $bind_values); + my $bind_values = [ $entry->{user} ]; + + db::put( $dbh, $query, $bind_values ); } -sub error{ - my $msg=shift; - print "ERROR: $msg<br/>\n"; +sub error ($) { + my $msg = shift; + print "ERROR: $msg<br/>\n"; } #do not delete last line! diff --git a/lib/calcms/user_stats.pm b/lib/calcms/user_stats.pm index aa537e4..afd50af 100644 --- a/lib/calcms/user_stats.pm +++ b/lib/calcms/user_stats.pm @@ -1,117 +1,107 @@ -#!/bin/perl - -package user_stats; -use warnings "all"; +package user_stats; + use strict; +use warnings; +no warnings 'redefine'; use Data::Dumper; -require Exporter; -our @ISA = qw(Exporter); +#use base 'Exporter'; our @EXPORT_OK = qw(get_columns get update insert get_stats increase); -our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ] ); -sub debug; +sub get_columns($) { + my $config = shift; -sub get_columns{ - my $config=shift; - - my $dbh=db::connect($config); - my $cols=db::get_columns($dbh, 'calcms_user_stats'); - my $columns={}; - for my $col (@$cols){ - $columns->{$col}=1; - } - return $columns; + my $dbh = db::connect($config); + return db::get_columns_hash( $dbh, 'calcms_user_stats' ); } -sub get{ - my $config=shift; - my $condition=shift; +sub get ($$) { + my $config = shift; + my $condition = shift; - my $dbh=db::connect($config); + my $dbh = db::connect($config); - my @conditions=(); - my @bind_values=(); + my @conditions = (); + my @bind_values = (); - if ((defined $condition->{project_id}) && ($condition->{project_id} ne '')){ - push @conditions, 'project_id=?'; - push @bind_values, $condition->{project_id}; - } - - if ((defined $condition->{studio_id}) && ($condition->{studio_id} ne '')){ - push @conditions, 'studio_id=?'; - push @bind_values, $condition->{studio_id}; - } - - if ((defined $condition->{series_id}) && ($condition->{series_id} ne '')){ - push @conditions, 'series_id=?'; - push @bind_values, $condition->{series_id}; - } - - if ((defined $condition->{user}) && ($condition->{user} ne '')){ - push @conditions, 'user=?'; - push @bind_values, $condition->{user}; - } - - my $limit=''; - if ((defined $condition->{limit}) && ($condition->{limit} ne '')){ - $limit= 'limit '.$condition->{limit}; + if ( ( defined $condition->{project_id} ) && ( $condition->{project_id} ne '' ) ) { + push @conditions, 'project_id=?'; + push @bind_values, $condition->{project_id}; } - my $conditions=''; - $conditions=" where ".join(" and ",@conditions) if (@conditions>0); + if ( ( defined $condition->{studio_id} ) && ( $condition->{studio_id} ne '' ) ) { + push @conditions, 'studio_id=?'; + push @bind_values, $condition->{studio_id}; + } - my $query=qq{ + if ( ( defined $condition->{series_id} ) && ( $condition->{series_id} ne '' ) ) { + push @conditions, 'series_id=?'; + push @bind_values, $condition->{series_id}; + } + + if ( ( defined $condition->{user} ) && ( $condition->{user} ne '' ) ) { + push @conditions, 'user=?'; + push @bind_values, $condition->{user}; + } + + my $limit = ''; + if ( ( defined $condition->{limit} ) && ( $condition->{limit} ne '' ) ) { + $limit = 'limit ' . $condition->{limit}; + } + + my $conditions = ''; + $conditions = " where " . join( " and ", @conditions ) if ( @conditions > 0 ); + + my $query = qq{ select * from calcms_user_stats $conditions order by modified_at desc $limit }; - #print STDERR Dumper($query).Dumper(\@bind_values); - my $results=db::get($dbh, $query, \@bind_values); - return $results; + my $results = db::get( $dbh, $query, \@bind_values ); + return $results; } -sub get_stats{ - my $config=shift; - my $condition=shift; +sub get_stats($$) { + my $config = shift; + my $condition = shift; - my $dbh=db::connect($config); + my $dbh = db::connect($config); - my @conditions=(); - my @bind_values=(); + my @conditions = (); + my @bind_values = (); - if ((defined $condition->{project_id}) && ($condition->{project_id} ne '')){ - push @conditions, 'project_id=?'; - push @bind_values, $condition->{project_id}; - } - - if ((defined $condition->{studio_id}) && ($condition->{studio_id} ne '')){ - push @conditions, 'studio_id=?'; - push @bind_values, $condition->{studio_id}; - } - - if ((defined $condition->{series_id}) && ($condition->{series_id} ne '')){ - push @conditions, 'series_id=?'; - push @bind_values, $condition->{series_id}; - } - - if ((defined $condition->{user}) && ($condition->{user} ne '')){ - push @conditions, 'user=?'; - push @bind_values, $condition->{user}; - } - - my $limit=''; - if ((defined $condition->{limit}) && ($condition->{limit} ne '')){ - $limit= 'limit '.$condition->{limit}; + if ( ( defined $condition->{project_id} ) && ( $condition->{project_id} ne '' ) ) { + push @conditions, 'project_id=?'; + push @bind_values, $condition->{project_id}; } - my $conditions=''; - $conditions=" where ".join(" and ",@conditions) if (@conditions>0); + if ( ( defined $condition->{studio_id} ) && ( $condition->{studio_id} ne '' ) ) { + push @conditions, 'studio_id=?'; + push @bind_values, $condition->{studio_id}; + } - my $query=qq{ + if ( ( defined $condition->{series_id} ) && ( $condition->{series_id} ne '' ) ) { + push @conditions, 'series_id=?'; + push @bind_values, $condition->{series_id}; + } + + if ( ( defined $condition->{user} ) && ( $condition->{user} ne '' ) ) { + push @conditions, 'user=?'; + push @bind_values, $condition->{user}; + } + + my $limit = ''; + if ( ( defined $condition->{limit} ) && ( $condition->{limit} ne '' ) ) { + $limit = 'limit ' . $condition->{limit}; + } + + my $conditions = ''; + $conditions = " where " . join( " and ", @conditions ) if ( @conditions > 0 ); + + my $query = qq{ select user, project_id, studio_id, max(modified_at) modified_at, sum(create_events) create_events, @@ -125,22 +115,23 @@ sub get_stats{ group by user, project_id, studio_id $limit }; - #print STDERR Dumper($query).Dumper(\@bind_values); - my $results=db::get($dbh, $query, \@bind_values); - for my $result (@$results){ - $result->{score}=0; - for my $column ('create_events','update_events','delete_events','create_series','update_series','delete_series'){ - $result->{score}+=$result->{$column}; - } - } - my @results=reverse sort {$a->{score} <=> $b->{score}} @$results; - return \@results; + my $results = db::get( $dbh, $query, \@bind_values ); + for my $result (@$results) { + $result->{score} = 0; + for my $column ( 'create_events', 'update_events', 'delete_events', 'create_series', 'update_series', + 'delete_series' ) + { + $result->{score} += $result->{$column}; + } + } + my @results = reverse sort { $a->{score} <=> $b->{score} } @$results; + return \@results; } -sub insert{ - my $config=shift; - my $stats=shift; +sub insert($$) { + my $config = shift; + my $stats = shift; return undef unless defined $stats->{project_id}; return undef unless defined $stats->{studio_id}; @@ -148,58 +139,57 @@ sub insert{ return undef unless defined $stats->{user}; #TODO:filter for existing attributes - my $columns=get_columns($config); - my $entry={}; - for my $column (keys %$columns){ - $entry->{$column}=$stats->{$column} if defined $stats->{$column}; + my $columns = get_columns($config); + my $entry = {}; + for my $column ( keys %$columns ) { + $entry->{$column} = $stats->{$column} if defined $stats->{$column}; } - $entry->{modified_at}= time::time_to_datetime(time()); - - my $dbh=db::connect($config); - my $id=db::insert($dbh, 'calcms_user_stats', $entry); + $entry->{modified_at} = time::time_to_datetime( time() ); + + my $dbh = db::connect($config); + my $id = db::insert( $dbh, 'calcms_user_stats', $entry ); return $id; } # update project -sub update{ - my $config=shift; - my $stats=shift; +sub update ($$) { + my $config = shift; + my $stats = shift; return undef unless defined $stats->{project_id}; return undef unless defined $stats->{studio_id}; return undef unless defined $stats->{series_id}; return undef unless defined $stats->{user}; - my $columns=get_columns($config); - my $entry={}; - for my $column (keys %$columns){ - $entry->{$column}=$stats->{$column} if defined $stats->{$column}; + my $columns = get_columns($config); + my $entry = {}; + for my $column ( keys %$columns ) { + $entry->{$column} = $stats->{$column} if defined $stats->{$column}; } - $entry->{modified_at}= time::time_to_datetime(time()); - - my $values =join(",", map {$_.'=?'} (keys %$entry)); - my @bind_values =map {$entry->{$_}} (keys %$entry); - push @bind_values, $entry->{user}; - push @bind_values, $entry->{project_id}; - push @bind_values, $entry->{studio_id}; - push @bind_values, $entry->{series_id}; + $entry->{modified_at} = time::time_to_datetime( time() ); - my $query=qq{ + my @keys = sort keys %$entry; + my $values = join( ",", map { $_ . '=?' } @keys ); + my @bind_values = map { $entry->{$_} } @keys; + push @bind_values, $entry->{user}; + push @bind_values, $entry->{project_id}; + push @bind_values, $entry->{studio_id}; + push @bind_values, $entry->{series_id}; + + my $query = qq{ update calcms_user_stats set $values where user=? and project_id=? and studio_id=? and series_id=? }; - #print STDERR Dumper($query).Dumper(\@bind_values); - my $dbh=db::connect($config); - return db::put($dbh, $query, \@bind_values); + + my $dbh = db::connect($config); + return db::put( $dbh, $query, \@bind_values ); } -sub increase{ - my $config=shift; - my $usecase=shift; - my $options=shift; - - #print STDERR Dumper($usecase)." ".Dumper($options); +sub increase ($$$) { + my $config = shift; + my $usecase = shift; + my $options = shift; return undef unless defined $usecase; return undef unless defined $options->{project_id}; @@ -207,40 +197,53 @@ sub increase{ return undef unless defined $options->{series_id}; return undef unless defined $options->{user}; - #print STDERR "ok\n"; + my $columns = get_columns($config); + return undef unless exists $columns->{$usecase}; - my $columns=get_columns($config); - #print STDERR "columns:".Dumper($columns); - return undef unless defined $columns->{$usecase}; - - my $entries= get($config,$options); - #print STDERR "exist:".Dumper($columns); - - if (@$entries==0){ - my $entry={ + my $entries = get( $config, $options ); + if ( scalar @$entries == 0 ) { + my $entry = { project_id => $options->{project_id}, studio_id => $options->{studio_id}, series_id => $options->{series_id}, user => $options->{user}, $usecase => 1, }; - #print STDERR "user_stats::insert\n"; - return insert($config, $entry); - }elsif (@$entries==1){ - my $entry=$entries->[0]; - $entry->{$usecase}++ if defined - #print STDERR "user_stats::update\n"; - return update($config, $entry); - }else{ - print STDERR "user_stats: to few options given: $usecase,".Dumper($options)."\n"; + + return insert( $config, $entry ); + } elsif ( scalar @$entries == 1 ) { + my $entry = $entries->[0]; + $entry->{$usecase}++ if defined + return update( $config, $entry ); + } else { + print STDERR "user_stats: to few options given: $usecase," . Dumper($options) . "\n"; } } +sub get_active_users{ + my $config = shift; -sub error{ - my $msg=shift; - print "ERROR: $msg<br/>\n"; + my $dbh = db::connect($config); + + my $query=qq{ + select u.name login, u.full_name, + s.last_login, s.login_count, + u.disabled, u.created_at, u.created_by + from calcms_users u left join ( + SELECT user , max(start) last_login, count(user) login_count + FROM calcms_user_sessions + group by user + ) s on s.user=u.name + order by u.disabled, s.last_login desc, u.created_at desc + }; + my $results = db::get( $dbh, $query, [] ); + return $results; +} + +sub error ($) { + my $msg = shift; + print "ERROR: $msg<br/>\n"; } #do not delete last line! diff --git a/lib/calcms/work_dates.pm b/lib/calcms/work_dates.pm index c945ad5..4cb361d 100644 --- a/lib/calcms/work_dates.pm +++ b/lib/calcms/work_dates.pm @@ -1,101 +1,95 @@ -package work_dates; +package work_dates; -use warnings "all"; use strict; +use warnings; +no warnings 'redefine'; + use Data::Dumper; -use Date::Calc; -use time; -use db; -use log; -use studio_timeslot_dates; -use work_schedule; +use Date::Calc(); +use time(); +use db(); +use log(); +use studio_timeslot_dates(); +use work_schedule(); # schedule dates for work_schedule # table: calcms_work_dates # columns: id, studio_id, schedule_id, start(datetime), end(datetime) # TODO: delete column schedule_id -require Exporter; -our @ISA = qw(Exporter); +#use base 'Exporter'; our @EXPORT_OK = qw(get_columns get insert update delete get_dates); -our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ] ); -sub debug; +sub get_columns($) { + my $config = shift; -sub get_columns{ - my $config=shift; - - my $dbh=db::connect($config); - my $cols=db::get_columns($dbh, 'calcms_work_dates'); - my $columns={}; - for my $col (@$cols){ - $columns->{$col}=1; - } - return $columns; + my $dbh = db::connect($config); + return db::get_columns_hash( $dbh, 'calcms_work_dates' ); } # get all work_dates for studio_id and schedule_id within given time range # calculate start_date, end_date, weeday, day from start and end(datetime) -sub get{ - my $config=shift; - my $condition=shift; +sub get ($$) { + my $config = shift; + my $condition = shift; - my $date_range_include=0; - $date_range_include=1 if $condition->{date_range_include}==1; + my $date_range_include = 0; + $date_range_include = 1 + if ( defined $condition->{date_range_include} ) && ( $condition->{date_range_include} == 1 ); - my $dbh=db::connect($config); + my $dbh = db::connect($config); - my @conditions=(); - my @bind_values=(); + my @conditions = (); + my @bind_values = (); - if ((defined $condition->{project_id}) && ($condition->{project_id} ne '')){ - push @conditions, 'project_id=?'; - push @bind_values, $condition->{project_id}; - } + if ( ( defined $condition->{project_id} ) && ( $condition->{project_id} ne '' ) ) { + push @conditions, 'project_id=?'; + push @bind_values, $condition->{project_id}; + } - if ((defined $condition->{studio_id}) && ($condition->{studio_id} ne '')){ - push @conditions, 'studio_id=?'; - push @bind_values, $condition->{studio_id}; - } + if ( ( defined $condition->{studio_id} ) && ( $condition->{studio_id} ne '' ) ) { + push @conditions, 'studio_id=?'; + push @bind_values, $condition->{studio_id}; + } - if ((defined $condition->{schedule_id}) && ($condition->{schedule_id} ne '')){ - push @conditions, 'schedule_id=?'; - push @bind_values, $condition->{schedule_id}; - } + if ( ( defined $condition->{schedule_id} ) && ( $condition->{schedule_id} ne '' ) ) { + push @conditions, 'schedule_id=?'; + push @bind_values, $condition->{schedule_id}; + } - if ((defined $condition->{start_at}) && ($condition->{start_at} ne '')){ - push @conditions, 'start=?'; - push @bind_values, $condition->{start_at}; - } + if ( ( defined $condition->{start_at} ) && ( $condition->{start_at} ne '' ) ) { + push @conditions, 'start=?'; + push @bind_values, $condition->{start_at}; + } - if ((defined $condition->{from}) && ($condition->{from} ne '')){ - if ($date_range_include==1){ - push @conditions, 'end_date>=?'; - push @bind_values, $condition->{from}; - }else{ - push @conditions, 'start_date>=?'; - push @bind_values, $condition->{from}; + if ( ( defined $condition->{from} ) && ( $condition->{from} ne '' ) ) { + if ( $date_range_include == 1 ) { + push @conditions, 'end_date>=?'; + push @bind_values, $condition->{from}; + } else { + push @conditions, 'start_date>=?'; + push @bind_values, $condition->{from}; } - } + } - if ((defined $condition->{till}) && ($condition->{till} ne '')){ - if ($date_range_include==1){ - push @conditions, 'start_date<=?'; - push @bind_values, $condition->{till}; - }else{ - push @conditions, 'end_date<=?'; - push @bind_values, $condition->{till}; + if ( ( defined $condition->{till} ) && ( $condition->{till} ne '' ) ) { + if ( $date_range_include == 1 ) { + push @conditions, 'start_date<=?'; + push @bind_values, $condition->{till}; + } else { + push @conditions, 'end_date<=?'; + push @bind_values, $condition->{till}; } - } + } - if ((defined $condition->{exclude}) && ($condition->{exclude} ne '')){ - push @conditions, 'exclude=?'; - push @bind_values, $condition->{exclude}; - } + if ( ( defined $condition->{exclude} ) && ( $condition->{exclude} ne '' ) ) { + push @conditions, 'exclude=?'; + push @bind_values, $condition->{exclude}; + } - my $conditions=''; - $conditions=" where ".join(" and ",@conditions) if (@conditions>0); + my $conditions = ''; + $conditions = " where " . join( " and ", @conditions ) if ( @conditions > 0 ); - my $query=qq{ + my $query = qq{ select date(start) start_date ,date(end) end_date ,dayname(start) weekday @@ -113,272 +107,268 @@ sub get{ $conditions order by start }; - #print STDERR $query."\n"; - #print STDERR Dumper(\@bind_values); - my $entries=db::get($dbh, $query, \@bind_values); - for my $entry (@$entries){ - $entry->{weekday}=substr($entry->{weekday},0,2); - } - - return $entries; + my $entries = db::get( $dbh, $query, \@bind_values ); + for my $entry (@$entries) { + $entry->{weekday} = substr( $entry->{weekday}, 0, 2 ); + } + + return $entries; } - #update work dates for all schedules of a work and studio_id -sub update{ - my $config=shift; - my $entry=shift; +sub update($$) { + my $config = shift; + my $entry = shift; - return undef unless defined $entry->{project_id} ; - return undef unless defined $entry->{studio_id} ; - return undef unless defined $entry->{schedule_id} ; + return undef unless defined $entry->{project_id}; + return undef unless defined $entry->{studio_id}; + return undef unless defined $entry->{schedule_id}; - my $dbh=db::connect($config); + my $dbh = db::connect($config); - #delete all existing work dates (by project, studio and schedule id) - work_dates::delete($config, $entry); + #delete all existing work dates (by project, studio and schedule id) + work_dates::delete( $config, $entry ); - my $day_start=$config->{date}->{day_starting_hour}; + my $day_start = $config->{date}->{day_starting_hour}; - #get all schedules for schedule id ordered by exclude, date - my $schedules=work_schedule::get($config, { - project_id => $entry->{project_id}, - studio_id => $entry->{studio_id}, - schedule_id => $entry->{schedule_id}, - }); - - #add scheduled work dates and remove exluded dates - my $work_dates={}; + #get all schedules for schedule id ordered by exclude, date + my $schedules = work_schedule::get( + $config, + { + project_id => $entry->{project_id}, + studio_id => $entry->{studio_id}, + schedule_id => $entry->{schedule_id}, + } + ); + + #add scheduled work dates and remove exluded dates + my $work_dates = {}; #TODO:set schedules exclude to 0 if not 1 #insert all normal dates (not excludes) - for my $schedule (@$schedules){ - my $dates=get_schedule_dates($schedule, {exclude => 0}); - for my $date (@$dates){ - $date->{exclude}=0; - $work_dates->{$date->{start}}=$date; - #print STDERR Dumper($date)."\n" if ($date->{start} eq'2014-02-05 19:00:00'); - } - } - - #insert / overwrite all exlude dates - for my $schedule (@$schedules){ - my $dates=get_schedule_dates($schedule, {exclude => 1}); - for my $date (@$dates){ - $date->{exclude}=1; - $work_dates->{$date->{start}}=$date; - #print STDERR Dumper($date)."\n" if ($date->{start} eq'2014-02-05 19:00:00'); - } - } - - #print STDERR Dumper($work_dates->{'2014-02-05 19:00:00'}); - - my $request={ - config => $config - }; - - my $i=0; - my $j=0; - for my $date (keys %$work_dates){ - my $work_date=$work_dates->{$date}; - #insert date - my $entry={ - project_id => $entry->{project_id}, - studio_id => $entry->{studio_id}, - schedule_id => $entry->{schedule_id}, - title => $entry->{title}, - type => $entry->{type}, - schedule_id => $entry->{schedule_id}, - start => $work_date->{start}, - end => $work_date->{end}, - exclude => $work_date->{exclude} - }; - if(studio_timeslot_dates::can_studio_edit_events($config, $entry)==1){ # by studio_id, start, end - $entry->{start_date}= time::add_hours_to_datetime($entry->{start}, -$day_start); - $entry->{end_date}= time::add_hours_to_datetime($entry->{end}, -$day_start); - db::insert($dbh, 'calcms_work_dates', $entry); - #print STDERR "$entry->{start_date}\n"; - $i++; - }else{ - $j++; - #print STDERR Dumper($entry); + for my $schedule (@$schedules) { + my $dates = get_schedule_dates( $schedule, { exclude => 0 } ); + for my $date (@$dates) { + $date->{exclude} = 0; + $work_dates->{ $date->{start} } = $date; } } + + #insert / overwrite all exlude dates + for my $schedule (@$schedules) { + my $dates = get_schedule_dates( $schedule, { exclude => 1 } ); + for my $date (@$dates) { + $date->{exclude} = 1; + $work_dates->{ $date->{start} } = $date; + } + } + + my $request = { config => $config }; + my $i = 0; + my $j = 0; + for my $date ( keys %$work_dates ) { + my $work_date = $work_dates->{$date}; + + #insert date + my $entry = { + project_id => $entry->{project_id}, + studio_id => $entry->{studio_id}, + schedule_id => $entry->{schedule_id}, + title => $entry->{title}, + type => $entry->{type}, + schedule_id => $entry->{schedule_id}, + start => $work_date->{start}, + end => $work_date->{end}, + exclude => $work_date->{exclude} + }; + if ( studio_timeslot_dates::can_studio_edit_events( $config, $entry ) == 1 ) { # by studio_id, start, end + $entry->{start_date} = time::add_hours_to_datetime( $entry->{start}, -$day_start ); + $entry->{end_date} = time::add_hours_to_datetime( $entry->{end}, -$day_start ); + db::insert( $dbh, 'calcms_work_dates', $entry ); + + #print STDERR "$entry->{start_date}\n"; + $i++; + } else { + $j++; + } + } + #print STDERR "$i work_dates updates\n"; - return $j." dates out of studio times, ".$i; + return $j . " dates out of studio times, " . $i; } -sub get_schedule_dates{ - my $schedule=shift; - my $options=shift; +sub get_schedule_dates($$) { + my $schedule = shift; + my $options = shift; - my $is_exclude=$options->{exclude}||0; - my $dates=[]; - return $dates if (($is_exclude eq'1') && ($schedule->{exclude}ne'1')); - return $dates if (($is_exclude eq'0') && ($schedule->{exclude}eq'1')); + my $is_exclude = $options->{exclude} || 0; + my $dates = []; + return $dates if ( $is_exclude eq '1' ) && ( $schedule->{exclude} ne '1' ); + return $dates if ( $is_exclude eq '0' ) && ( $schedule->{exclude} eq '1' ); - if ($schedule->{period_type}eq'single'){ - $dates=get_single_date($schedule->{start}, $schedule->{duration}) ; - }elsif($schedule->{period_type}eq'days'){ - $dates=get_dates($schedule->{start}, $schedule->{end}, $schedule->{duration}, $schedule->{frequency}) ; - }elsif($schedule->{period_type}eq'week_of_month'){ - $dates=get_week_of_month_dates($schedule->{start}, $schedule->{end}, $schedule->{duration}, $schedule->{week_of_month}, $schedule->{weekday}, $schedule->{month}); - }else{ + if ( $schedule->{period_type} eq 'single' ) { + $dates = get_single_date( $schedule->{start}, $schedule->{duration} ); + } elsif ( $schedule->{period_type} eq 'days' ) { + $dates = get_dates( $schedule->{start}, $schedule->{end}, $schedule->{duration}, $schedule->{frequency} ); + } elsif ( $schedule->{period_type} eq 'week_of_month' ) { + $dates = get_week_of_month_dates( + $schedule->{start}, $schedule->{end}, $schedule->{duration}, + $schedule->{week_of_month}, $schedule->{weekday}, $schedule->{month} + ); + } else { print STDERR "unknown schedule period_type\n"; } return $dates; } +sub get_week_of_month_dates($$$$$$) { + my $start = shift; # datetime string + my $end = shift; # datetime string + my $duration = shift; # in minutes + my $week = shift; # every nth week of month + my $weekday = shift; # weekday [1..7] + my $frequency = shift; # every 1st,2nd,3th time -sub get_week_of_month_dates{ - my $start =shift; # datetime string - my $end =shift; # datetime string - my $duration =shift; # in minutes - my $week =shift; # every nth week of month - my $weekday =shift; # weekday [1..7] - my $frequency =shift; # every 1st,2nd,3th time + return undef if $start eq ''; + return undef if $end eq ''; + return undef if $duration eq ''; + return undef if $week eq ''; + return undef if $weekday eq ''; + return undef if $frequency eq ''; + return undef if $frequency == 0; - return undef if $start eq''; - return undef if $end eq''; - return undef if $duration eq''; - return undef if $week eq''; - return undef if $weekday eq''; - return undef if $frequency eq''; - return undef if $frequency==0; + my $start_dates = time::get_nth_weekday_in_month( $start, $end, $week, $weekday ); - my $start_dates=time::get_nth_weekday_in_month($start, $end, $week, $weekday-1); + my $results = []; - my $results=[]; - - my $c=-1; - for my $start_datetime (@$start_dates){ + my $c = -1; + for my $start_datetime (@$start_dates) { $c++; - my @start = @{time::datetime_to_array($start_datetime)}; - next unless @start>=6; - next if (($c % $frequency)!=0); + my @start = @{ time::datetime_to_array($start_datetime) }; + next unless @start >= 6; + next if ( $c % $frequency ) != 0; - my @end_datetime = Date::Calc::Add_Delta_DHMS( - $start[0], $start[1], $start[2], # start date - $start[3], $start[4], $start[5], # start time - 0, 0, $duration, 0 # delta days, hours, minutes, seconds - ); - my $end_datetime=time::array_to_datetime(\@end_datetime); + my @end_datetime = Date::Calc::Add_Delta_DHMS( + $start[0], $start[1], $start[2], # start date + $start[3], $start[4], $start[5], # start time + 0, 0, $duration, 0 # delta days, hours, minutes, seconds + ); + my $end_datetime = time::array_to_datetime( \@end_datetime ); - push @$results, { + push @$results, + { start => $start_datetime, end => $end_datetime - }; + }; } return $results; } #add duration to a single date -sub get_single_date{ - my $start_datetime = shift; +sub get_single_date($$) { + my $start_datetime = shift; my $duration = shift; - my @start = @{time::datetime_to_array($start_datetime)}; - return unless @start>=6; + my @start = @{ time::datetime_to_array($start_datetime) }; + return unless @start >= 6; - my @end_datetime = Date::Calc::Add_Delta_DHMS( - $start[0], $start[1], $start[2], # start date - $start[3], $start[4], $start[5], # start time - 0, 0, $duration, 0 # delta days, hours, minutes, seconds - ); - my $date={ + my @end_datetime = Date::Calc::Add_Delta_DHMS( + $start[0], $start[1], $start[2], # start date + $start[3], $start[4], $start[5], # start time + 0, 0, $duration, 0 # delta days, hours, minutes, seconds + ); + my $date = { start => $start_datetime, - end => time::array_to_datetime(\@end_datetime) + end => time::array_to_datetime( \@end_datetime ) }; - return [$date]; + return [$date]; } #calculate all dates between start_datetime and end_date with duration(minutes) and frequency(days) -sub get_dates{ - my $start_datetime = shift; - my $end_date = shift; - my $duration = shift; # in minutes - my $frequency = shift; # in days - #print "start_datetime:$start_datetime end_date:$end_date duration:$duration frequency:$frequency\n"; +sub get_dates($$$$) { + my $start_datetime = shift; + my $end_date = shift; + my $duration = shift; # in minutes + my $frequency = shift; # in days + #print "start_datetime:$start_datetime end_date:$end_date duration:$duration frequency:$frequency\n"; - my @start = @{time::datetime_to_array($start_datetime)}; - return unless @start>=6; - my @start_date = ($start[0], $start[1], $start[2]); - my $start_time = sprintf('%02d:%02d:%02d', $start[3], $start[4], $start[5]); + my @start = @{ time::datetime_to_array($start_datetime) }; + return unless @start >= 6; + my @start_date = ( $start[0], $start[1], $start[2] ); + my $start_time = sprintf( '%02d:%02d:%02d', $start[3], $start[4], $start[5] ); #print STDERR "$start_datetime,$end_date,$duration,$frequency\n"; #return on single date - my $date={}; - $date->{start}= sprintf("%04d-%02d-%02d",@start_date).' '.$start_time; - return undef if $duration eq ''; + my $date = {}; + $date->{start} = sprintf( "%04d-%02d-%02d", @start_date ) . ' ' . $start_time; + return undef if $duration eq ''; - return undef if (($frequency eq '')||($end_date eq'')); + return undef if ( $frequency eq '' ) || ( $end_date eq '' ); #continue on recurring date - my @end = @{time::datetime_to_array($end_date)}; - return unless @end>=3; - my @end_date = ($end[0], $end[1], $end[2]); + my @end = @{ time::datetime_to_array($end_date) }; + return unless @end >= 3; + my @end_date = ( $end[0], $end[1], $end[2] ); - my $today=time::time_to_date(); - my ($year, $month, $day)=split(/\-/,$today); + my $today = time::time_to_date(); + my ( $year, $month, $day ) = split( /\-/, $today ); #do not show dates one month back - my $not_before= sprintf("%04d-%02d-%02d", Date::Calc::Add_Delta_Days($year, $month, $day, -30)); + my $not_before = sprintf( "%04d-%02d-%02d", Date::Calc::Add_Delta_Days( $year, $month, $day, -30 ) ); - my $dates=[]; - return $dates if ($end_date lt $today); - return $dates if ($frequency<1); + my $dates = []; + return $dates if ( $end_date lt $today ); + return $dates if ( $frequency < 1 ); - my $j = Date::Calc::Delta_Days(@start_date, @end_date); - my $c=0; - for (my $i = 0; $i <= $j; $i+=$frequency ){ - my @date = Date::Calc::Add_Delta_Days($start[0], $start[1], $start[2], $i); - my $date={}; - $date->{start}=sprintf("%04d-%02d-%02d",@date).' '.$start_time; - - my @end_datetime = Date::Calc::Add_Delta_DHMS( - $date[0], $date[1], $date[2], # start date - $start[3], $start[4], $start[5], # start time - 0, 0, $duration, 0 # delta days, hours, minutes, seconds - ); - $date->{end}=time::array_to_datetime(\@end_datetime); + my $j = Date::Calc::Delta_Days( @start_date, @end_date ); + my $c = 0; + for ( my $i = 0 ; $i <= $j ; $i += $frequency ) { + my @date = Date::Calc::Add_Delta_Days( $start[0], $start[1], $start[2], $i ); + my $date = {}; + $date->{start} = sprintf( "%04d-%02d-%02d", @date ) . ' ' . $start_time; - last if ($c>200); - $c++; + my @end_datetime = Date::Calc::Add_Delta_DHMS( + $date[0], $date[1], $date[2], # start date + $start[3], $start[4], $start[5], # start time + 0, 0, $duration, 0 # delta days, hours, minutes, seconds + ); + $date->{end} = time::array_to_datetime( \@end_datetime ); + + last if ( $c > 200 ); + $c++; next if $date->{end} lt $not_before; - push @$dates,$date; + push @$dates, $date; - } - return $dates; + } + return $dates; } #remove all work_dates for studio_id and schedule_id -sub delete{ - my $config=shift; - my $entry=shift; - - return undef unless defined $entry->{project_id}; - return undef unless defined $entry->{studio_id}; - return undef unless defined $entry->{schedule_id}; +sub delete($$) { + my $config = shift; + my $entry = shift; - my $dbh=db::connect($config); + return undef unless defined $entry->{project_id}; + return undef unless defined $entry->{studio_id}; + return undef unless defined $entry->{schedule_id}; - my $query=qq{ + my $dbh = db::connect($config); + + my $query = qq{ delete from calcms_work_dates where project_id=? and studio_id=? and schedule_id=? }; - my $bind_values=[$entry->{project_id}, $entry->{studio_id}, $entry->{schedule_id}]; - #print '<pre>$query'.$query.Dumper($bind_values).'</pre>'; - return db::put($dbh, $query, $bind_values); + my $bind_values = [ $entry->{project_id}, $entry->{studio_id}, $entry->{schedule_id} ]; + return db::put( $dbh, $query, $bind_values ); } - -sub error{ - my $msg=shift; - print "ERROR: $msg<br/>\n"; +sub error($) { + my $msg = shift; + print "ERROR: $msg<br/>\n"; } #do not delete last line! diff --git a/lib/calcms/work_schedule.pm b/lib/calcms/work_schedule.pm index 253ebb7..56bff79 100644 --- a/lib/calcms/work_schedule.pm +++ b/lib/calcms/work_schedule.pm @@ -1,155 +1,149 @@ -package work_schedule; -use warnings "all"; +package work_schedule; + use strict; +use warnings; +no warnings 'redefine'; + use Data::Dumper; -use series_dates; +use series_dates(); # table: calcms_work_schedule -# columns: id, studio_id, series_id, - # start (datetime), - # duration (minutes), - # frequency (days), - # end (date), - # weekday (1..7) - # week_of_month (1..5) - # month +# columns: id, studio_id, series_id, +# start (datetime), +# duration (minutes), +# frequency (days), +# end (date), +# weekday (1..7) +# week_of_month (1..5) +# month -require Exporter; -our @ISA = qw(Exporter); +#use base 'Exporter'; our @EXPORT_OK = qw(get_columns get insert update delete); -our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ] ); -sub debug; +sub get_columns($) { + my $config = shift; -sub get_columns{ - my $config=shift; - - my $dbh=db::connect($config); - my $cols=db::get_columns($dbh, 'calcms_work_schedule'); - my $columns={}; - for my $col (@$cols){ - $columns->{$col}=1; - } - return $columns; + my $dbh = db::connect($config); + return db::get_columns_hash( $dbh, 'calcms_work_schedule' ); } #map schedule id to id -sub get{ - my $config=shift; - my $condition=shift; +sub get($$) { + my $config = shift; + my $condition = shift; - my $dbh=db::connect($config); + my $dbh = db::connect($config); - my @conditions=(); - my @bind_values=(); + my @conditions = (); + my @bind_values = (); - if ((defined $condition->{project_id}) && ($condition->{project_id} ne '')){ - push @conditions, 'project_id=?'; - push @bind_values, $condition->{project_id}; - } + if ( ( defined $condition->{project_id} ) && ( $condition->{project_id} ne '' ) ) { + push @conditions, 'project_id=?'; + push @bind_values, $condition->{project_id}; + } - if ((defined $condition->{studio_id}) && ($condition->{studio_id} ne '')){ - push @conditions, 'studio_id=?'; - push @bind_values, $condition->{studio_id}; - } + if ( ( defined $condition->{studio_id} ) && ( $condition->{studio_id} ne '' ) ) { + push @conditions, 'studio_id=?'; + push @bind_values, $condition->{studio_id}; + } - if ((defined $condition->{schedule_id}) && ($condition->{schedule_id} ne '')){ - push @conditions, 'schedule_id=?'; - push @bind_values, $condition->{schedule_id}; - } + if ( ( defined $condition->{schedule_id} ) && ( $condition->{schedule_id} ne '' ) ) { + push @conditions, 'schedule_id=?'; + push @bind_values, $condition->{schedule_id}; + } - if ((defined $condition->{start}) && ($condition->{start} ne '')){ - push @conditions, 'start=?'; - push @bind_values, $condition->{start}; - } + if ( ( defined $condition->{start} ) && ( $condition->{start} ne '' ) ) { + push @conditions, 'start=?'; + push @bind_values, $condition->{start}; + } - if ((defined $condition->{exclude}) && ($condition->{exclude} ne '')){ - push @conditions, 'exclude=?'; - push @bind_values, $condition->{exclude}; - } + if ( ( defined $condition->{exclude} ) && ( $condition->{exclude} ne '' ) ) { + push @conditions, 'exclude=?'; + push @bind_values, $condition->{exclude}; + } - if ((defined $condition->{period_type}) && ($condition->{period_type} ne '')){ - push @conditions, 'period_type=?'; - push @bind_values, $condition->{period_type}; - } + if ( ( defined $condition->{period_type} ) && ( $condition->{period_type} ne '' ) ) { + push @conditions, 'period_type=?'; + push @bind_values, $condition->{period_type}; + } - my $conditions=''; - $conditions=" where ".join(" and ",@conditions) if (@conditions>0); + my $conditions = ''; + $conditions = " where " . join( " and ", @conditions ) if ( @conditions > 0 ); - my $query=qq{ + my $query = qq{ select * from calcms_work_schedule $conditions order by exclude, start }; - #print STDERR $query."\n".Dumper(\@bind_values); - my $entries=db::get($dbh, $query, \@bind_values); - return $entries; + my $entries = db::get( $dbh, $query, \@bind_values ); + return $entries; } -sub insert{ - my $config=shift; - my $entry=shift; +sub insert ($$) { + my $config = shift; + my $entry = shift; - return undef unless defined $entry->{project_id}; - return undef unless defined $entry->{studio_id}; - return undef unless defined $entry->{start}; - my $dbh=db::connect($config); - return db::insert($dbh, 'calcms_work_schedule', $entry); + return undef unless defined $entry->{project_id}; + return undef unless defined $entry->{studio_id}; + return undef unless defined $entry->{start}; + my $dbh = db::connect($config); + return db::insert( $dbh, 'calcms_work_schedule', $entry ); } #schedule id to id -sub update{ - my $config=shift; - my $entry=shift; +sub update ($$) { + my $config = shift; + my $entry = shift; - return undef unless defined $entry->{project_id}; - return undef unless defined $entry->{studio_id}; - return undef unless defined $entry->{schedule_id}; - return undef unless defined $entry->{start}; + return undef unless defined $entry->{project_id}; + return undef unless defined $entry->{studio_id}; + return undef unless defined $entry->{schedule_id}; + return undef unless defined $entry->{start}; - my $dbh=db::connect($config); - my $values =join(",", map {$_.'=?'} (keys %$entry)); - my @bind_values =map {$entry->{$_}} (keys %$entry); + my $dbh = db::connect($config); + my @keys = sort keys %$entry; + my $values = join( ",", map { $_ . '=?' } @keys); + my @bind_values = map { $entry->{$_} } @keys; - push @bind_values,$entry->{project_id}; - push @bind_values,$entry->{studio_id}; - push @bind_values,$entry->{schedule_id}; + push @bind_values, $entry->{project_id}; + push @bind_values, $entry->{studio_id}; + push @bind_values, $entry->{schedule_id}; - my $query=qq{ + my $query = qq{ update calcms_work_schedule set $values where project_id=? and studio_id=? and schedule_id=? }; - return db::put($dbh, $query, \@bind_values); - print "done\n"; + return db::put( $dbh, $query, \@bind_values ); + print "done\n"; } #map schedule id to id -sub delete{ - my $config=shift; - my $entry=shift; - - return undef unless defined $entry->{project_id}; - return undef unless defined $entry->{studio_id}; - return undef unless defined $entry->{schedule_id}; +sub delete($$) { + my $config = shift; + my $entry = shift; - my $dbh=db::connect($config); + return undef unless defined $entry->{project_id}; + return undef unless defined $entry->{studio_id}; + return undef unless defined $entry->{schedule_id}; - my $query=qq{ + my $dbh = db::connect($config); + + my $query = qq{ delete from calcms_work_schedule where project_id=? and studio_id=? and schedule_id=? }; - my $bind_values=[$entry->{project_id}, $entry->{studio_id}, $entry->{schedule_id}]; - #print '<pre>$query'.$query.Dumper($bind_values).'</pre>'; - return db::put($dbh, $query, $bind_values); + my $bind_values = [ $entry->{project_id}, $entry->{studio_id}, $entry->{schedule_id} ]; + + return db::put( $dbh, $query, $bind_values ); } -sub error{ - my $msg=shift; - print "ERROR: $msg<br/>\n"; +sub error($) { + my $msg = shift; + print "ERROR: $msg<br/>\n"; } #do not delete last line! diff --git a/tools/compress_templates.cgi b/tools/compress_templates.cgi deleted file mode 100755 index 026de15..0000000 --- a/tools/compress_templates.cgi +++ /dev/null @@ -1,125 +0,0 @@ -#! /usr/bin/perl -w - -BEGIN{ - my $dir=$ENV{SCRIPT_FILENAME}||''; - $dir=~s/(.*\/)[^\/]+/$1/; - $dir=$ENV{PWD} if ($dir eq''); - $dir=`pwd` if ($dir eq''); - - #if located below extern CMS go on more down - #$dir.='../'; - - #local perl installation libs - unshift(@INC,$dir.'/../../perl/lib/'); - unshift(@INC,$dir.'/../../calcms/calcms/'); -} - -use warnings "all"; -use strict; -use Data::Dumper; - -use File::stat; -use Time::localtime; -use CGI qw(header param Vars escapeHTML uploadInfo cgi_error); -use time; -use config; -use log; -use projects; -use markup; -use template; - -my $config =config::get('../config/config.cgi'); - -my $debug =$config->{system}->{debug}; -my $base_dir =$config->{locations}->{base_dir}; -my $local_base_url =$config->{locations}->{local_base_url}; - -$CGI::POST_MAX = 1024*10; -my $cgi=new CGI(); -my %params=$cgi->Vars(); -#print $cgi->header(); -#print STDERR Dumper($config); - -#print "a\n"; -template::exit_on_missing_permission('access_system'); -#print "b\n"; - -my $request={ - url => $ENV{QUERY_STRING}||'', - params => { - original => \%params, - checked => check_params(\%params), - }, - config => $config -}; -my $params=$request->{params}->{checked}; - -log::init($request); -log::mem('pic_manager init')if($debug>2); - -my $errors=''; -my $action_result=''; - -log::error("base_dir '$base_dir' does not exist")unless(-e $base_dir); - -my $template_dirs=[ - $base_dir.'/templates/', - $base_dir.'/admin/templates/', - $base_dir.'/planung/templates/', -]; -my @results=(); -#print "<pre>\n"; - -for my $template_dir(@$template_dirs){ - my $dest_dir=$template_dir.'compressed/'; - log::error('template directory "'.$dest_dir.'" does not exist') unless(-e $dest_dir); - log::error('cannot write into template directory "'.$dest_dir.'"') unless(-w $dest_dir); - - #compress only: html, xml - my @files=glob("$template_dir*.*ml"); - for my $file (@files){ - $file=~s/[\n\r]+$//g; - next if ($file=~/\~$/); - next if ($file=~/compressed/); - next if ($file=~/\.old$/); - push @results,$file; - - my $content=log::load_file($file); -# print "$file\n"; - markup::compress($content); - - my $filename=(split(/\//,$file))[-1]; - my $dest_file=$template_dir.'compressed/'.$filename; - log::error("cannot write '$dest_file'") if((-e $dest_file) && (!(-w $dest_file))); - log::save_file($dest_file,$content); - } -} - -my $out=''; -template::process('print',$params->{template},{ - 'error' => $errors, - 'projects' => projects::get({all=>0}), - - } -); - -print '<pre>'; -for my $result(@results){ - $result=~s/$base_dir//g; - print $local_base_url.$result."\n"; -} -print '</pre>'; -log::mem('pic_manager init')if($debug>1); - - -sub check_params{ - my $params=shift; - - my $result={}; - - #avoid checking templates - $result->{template}='templates/default.html'; - - return $result; -} - diff --git a/tools/sync_cms/INSTALL b/tools/sync_cms/INSTALL deleted file mode 100755 index ce7bea7..0000000 --- a/tools/sync_cms/INSTALL +++ /dev/null @@ -1,90 +0,0 @@ -#install libxml2, libxml2-dev (for headers) to use XML::Atom (required by Net::Google::Calendar) -#install perl modules: DateTime, DateTime::TimeZone, XML::Atom, XML::Atom::Feed, Net::Google::Calendar -#if reading calendar fails, patch Entry line 184, from -# if ($elem->hasAttribute($key)) { -# to -# if (defined $elem && $elem->hasAttribute($key)) { -# -#patch Entry before line 184, insert -# return unless ($tmp); - - -#patch Entry line 176, modify - $val =~ s!^http://schemas.google.com/g/2005#event\.!! if (defined $val); - -#admin,admin - - #all available google calendar definitions, replace in url 'basic' by 'full' to get calendar entries!!! (basic covers feed content only, but no calendar data...) -# google_calendars => { -# programm => 'http://www.google.com/calendar/feeds/58ei894fakpf84hj0u7o6el4sc%40group.calendar.google.com/public/full', -# programm_intern => 'http://www.google.com/calendar/feeds/lin4mscfdld2eiv22qda82t478%40group.calendar.google.com/public/full', -# planung => 'http://www.google.com/calendar/feeds/0is4ruq5thsb6ndsqr5gicff2k%40group.calendar.google.com/public/full', -# termine_intern => 'http://www.google.com/calendar/feeds/1n762hqutnsocd46h6nji3i2l4%40group.calendar.google.com/public/full', -# termine => 'http://www.google.com/calendar/feeds/f29rqfutlkub911i8u0eerusb0%40group.calendar.google.com/public/full' -# }, - -GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, FILE, INDEX, ALTER ON * . * TO 'root'@'localhost' IDENTIFIED BY 'calcms' WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0; - -Query OK, 0 rows affected (0.02 sec) - -flush previleges -https://www.google.com/calendar/dav/peter_retep@gmx.de/events - - -create database calcms-herbstradio; -mysql calcms_herbstradio -u root -p < calcms/calcms.sql - - -GRANT SELECT ON * . * TO 'root'@'localhost' IDENTIFIED BY 'calcms-agenda' WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0; - - -flush previleges - - -CREATE USER 'milan'@'localhost' IDENTIFIED BY 'eeGei3Yo'; -GRANT SELECT ON calcms_agenda.* TO 'calcms'@'localhost'; - -chmod 777 cache - -GRANT SELECT ON calcms_herbstradio.* TO 'calcms_agenda'@'localhost' IDENTIFIED BY 'eeGei3Yo' -GRANT SELECT, INSERT, UPDATE ON calcms_herbstradio.* TO 'calcms'@'localhost' IDENTIFIED BY 'CheiBai8' - - -ERROR: Can't create '/usr/local/lib/perl5/5.8.6/man/man3' -Do not have write permissions on '/usr/local/lib/perl5/5.8.6/man/man3' -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - at /home/milan/perl/lib/Module/Build/Base.pm line 2975 - SIMONW/Net-Google-Calendar-0.97.tar.gz - ./Build install -- NOT OK ----- - You may have to su to root to install the package - (Or you may want to run something like - o conf make_install_make_command 'sudo make' - to raise your permissions.Failed during this command: - DROLSKY/DateTime-Locale-0.43.tar.gz : install NO - DROLSKY/DateTime-TimeZone-0.91.tar.gz : install NO - DROLSKY/DateTime-0.50.tar.gz : make_test NO - SIMONW/Net-Google-AuthSub-0.5.tar.gz : install NO - GRANTM/XML-SAX-0.96.tar.gz : make_test NO - SIMONW/Net-Google-Calendar-0.97.tar.gz : install NO - -See perldoc ExtUtils::MakeMaker for full details. For Module::Build -modules, you need to create a ~/.modulebuildrc file containing -bindoc=~/man/man1 libdoc=~/man/man3 - -o conf makepl_arg "PREFIX=/home/milan/perl/ LIB=/home/milan/perl/lib INST_LIB=/home/milan/perl/lib INSTALLSITELIB=/home/milan/perl/lib INSTALLMAN1DIR=/home/milan/perl/man/man1 INSTALLSITEMAN1DIR=/home/milan/perl/man/man1 INSTALLMAN3DIR=~/home/milan/perl/man/man3 INSTALLSITEMAN3DIR=/home/milan/perl/man/man3 INSTALLDIRS=/home/milan/perl/ SITEPREFIX=/home/milan/perl/ VENDORPREFIX=/home/milan/perl/" - -LIB=$PREFIX/lib INST_LIB=$PREFIX/lib PREFIX=$PREFIX SITEPREFIX=$PREFIX VENDORPREFIX=$PREFIX - - - - -o conf make_arg -I/home/twiki/lib/CPAN -o conf make_install_arg -I/home/twiki/lib/CPAN -o conf makepl_arg "install_base=/home/twiki/lib/CPAN LIB=/home/twiki/lib/CPAN/lib INSTALLPRIVLIB=/home/twiki/lib/CPAN/lib INSTALLARCHLIB=/home/twiki/lib/CPAN/lib/arch INSTALLSITEARCH=/home/twiki/lib/CPAN/lib/arch INSTALLSITELIB=/home/twiki/lib/CPAN/lib INSTALLSCRIPT=/home/twiki/lib/CPAN/bin INSTALLBIN=/home/twiki/lib/CPAN/bin INSTALLSITEBIN=/home/twiki/lib/CPAN/bin INSTALLMAN1DIR=/home/twiki/lib/CPAN/man/man1 INSTALLSITEMAN1DIR=/home/twiki/lib/CPAN/man/man1 INSTALLMAN3DIR=/home/twiki/lib/CPAN/man/man3 INSTALLSITEMAN3DIR=/home/twiki/lib/CPAN/man/man3 " -o conf commit -q - - - - diff --git a/tools/sync_cms/config/jobs.config b/tools/sync_cms/config/jobs.config new file mode 100644 index 0000000..110b3c5 --- /dev/null +++ b/tools/sync_cms/config/jobs.config @@ -0,0 +1,18 @@ +<config> + +start_dir /home/calcms/agenda/admin/jobs/start/ +log_dir /home/calcms/agenda/admin/jobs/logs/ + +<job> + title potsdam : sender berlin -> 88vier.de + name potsdam_to_88vier.de + command /home/radio/calcms/sync_cms/sync_jobs/calcms_to_google.sh -7 31 potsdam +</job> + +<job> + title frb : sender berlin -> 88vier.de + name frb_to_88vier.de + command /home/radio/calcms/sync_cms/sync_jobs/calcms_to_google.sh -7 31 frb +</job> + +</config> diff --git a/tools/sync_cms/config/source/calcms_ansage.cfg b/tools/sync_cms/config/source/calcms_ansage.cfg index a404f68..3083ea4 100644 --- a/tools/sync_cms/config/source/calcms_ansage.cfg +++ b/tools/sync_cms/config/source/calcms_ansage.cfg @@ -1,12 +1,10 @@ <source> - type calcms_i - <access> hostname localhost port 3306 - database calcms_herbstradio - username calcms - password CheiBai8 + database calcms + username calcms_read + password password </access> <date> @@ -19,7 +17,7 @@ name 88vier title 88vier Studio Ansage start_date 2010-05-01 - end_date 2016-06-01 + end_date 2020-06-01 </88vier> </projects> location ansage diff --git a/tools/sync_cms/config/source/calcms_colabo.cfg b/tools/sync_cms/config/source/calcms_colabo.cfg index 06e2018..4be6dcd 100644 --- a/tools/sync_cms/config/source/calcms_colabo.cfg +++ b/tools/sync_cms/config/source/calcms_colabo.cfg @@ -1,12 +1,10 @@ <source> - type calcms_i - <access> hostname localhost port 3306 - database calcms_herbstradio - username calcms - password CheiBai8 + database calcms + username calcms_read + password password </access> <date> @@ -19,7 +17,7 @@ name 88vier title 88vier Colaboradio start_date 2010-05-01 - end_date 2016-06-01 + end_date 2020-06-01 </88vier> </projects> location colabo diff --git a/tools/sync_cms/config/source/calcms.cfg b/tools/sync_cms/config/source/calcms_frb.cfg similarity index 54% rename from tools/sync_cms/config/source/calcms.cfg rename to tools/sync_cms/config/source/calcms_frb.cfg index 2540478..5d89ead 100644 --- a/tools/sync_cms/config/source/calcms.cfg +++ b/tools/sync_cms/config/source/calcms_frb.cfg @@ -1,12 +1,10 @@ <source> - type calcms_i - <access> hostname localhost port 3306 - database calcms_herbstradio - username calcms - password CheiBai8 + database calcms + username calcms_read + password password </access> <date> @@ -17,15 +15,15 @@ <projects> <88vier> name 88vier - title 88vier PI-Radio 2010 + title 88vier FRB start_date 2010-05-01 - end_date 2013-08-31 + end_date 2020-06-01 </88vier> </projects> - location piradio + location frb <mapping> - event_details_url http://piradio.de/programm/sendung/<TMPL_VAR event_id>.html + event_details_url http://senderberlin.org/programm/sendung/<TMPL_VAR event_id>.html </mapping> <system> diff --git a/tools/sync_cms/config/source/calcms_piradio.cfg b/tools/sync_cms/config/source/calcms_piradio.cfg index 7a391c5..1f689ed 100644 --- a/tools/sync_cms/config/source/calcms_piradio.cfg +++ b/tools/sync_cms/config/source/calcms_piradio.cfg @@ -1,12 +1,10 @@ <source> - type calcms_i - <access> hostname localhost port 3306 - database calcms_herbstradio - username calcms - password CheiBai8 + database calcms + username calcms_read + password password </access> <date> @@ -19,7 +17,7 @@ name 88vier title 88vier PI-Radio start_date 2010-05-01 - end_date 2016-06-01 + end_date 2020-06-01 </88vier> </projects> location piradio diff --git a/tools/sync_cms/config/source/calcms_potsdam.cfg b/tools/sync_cms/config/source/calcms_potsdam.cfg index d2452c4..28d49c1 100644 --- a/tools/sync_cms/config/source/calcms_potsdam.cfg +++ b/tools/sync_cms/config/source/calcms_potsdam.cfg @@ -1,12 +1,10 @@ <source> - type calcms_i - <access> hostname localhost port 3306 - database calcms_herbstradio - username calcms - password CheiBai8 + database calcms + username calcms_read + password password </access> <date> @@ -19,7 +17,7 @@ name 88vier title 88vier Frrapo start_date 2010-05-01 - end_date 2016-06-01 + end_date 2020-06-01 </88vier> </projects> location potsdam diff --git a/tools/sync_cms/config/target/88vier_ansage.cfg b/tools/sync_cms/config/target/88vier_ansage.cfg index 67be6dc..bb7991e 100644 --- a/tools/sync_cms/config/target/88vier_ansage.cfg +++ b/tools/sync_cms/config/target/88vier_ansage.cfg @@ -1,10 +1,8 @@ <target> - type google_calendar2 - <access> - calendarId info@studioansage.de - serviceAccount 433089473368-bv26eveq03b7nhb9p62nu3ts7htgb4g3@developer.gserviceaccount.com - serviceAccountKeyFile /home/radio/googleApi.key + calendarId your-id + serviceAccount your-accounr@developer.gserviceaccount.com + serviceAccountKeyFile googleApi.key </access> <date> diff --git a/tools/sync_cms/config/target/88vier_colabo.cfg b/tools/sync_cms/config/target/88vier_colabo.cfg index 42df591..fbd2c13 100644 --- a/tools/sync_cms/config/target/88vier_colabo.cfg +++ b/tools/sync_cms/config/target/88vier_colabo.cfg @@ -1,10 +1,8 @@ <target> - type google_calendar2 - <access> - calendarId colaboradio@gmail.com - serviceAccount 433089473368-bv26eveq03b7nhb9p62nu3ts7htgb4g3@developer.gserviceaccount.com - serviceAccountKeyFile /home/radio/googleApi.key + calendarId your-calendar-id + serviceAccount your-account@developer.gserviceaccount.com + serviceAccountKeyFile googleApi.key </access> <date> diff --git a/tools/sync_cms/config/target/88vier_frb.cfg b/tools/sync_cms/config/target/88vier_frb.cfg new file mode 100644 index 0000000..a02aa9d --- /dev/null +++ b/tools/sync_cms/config/target/88vier_frb.cfg @@ -0,0 +1,21 @@ +<target> + <access> + calendarId your-id@group.calendar.google.com + serviceAccount your-account@developer.gserviceaccount.com + serviceAccountKeyFile googleApi.key + </access> + + <date> + time_zone Europe/Berlin + </date> + + <mapping> + title <TMPL_VAR location> : <TMPL_VAR series_name> - <TMPL_VAR title> + content <TMPL_VAR excerpt> <a href="<TMPL_VAR event_details_url>">mehr zur Sendung</a> + </mapping> + + <system> + debug 1 + </system> +</target> + diff --git a/tools/sync_cms/config/target/88vier_piradio.cfg b/tools/sync_cms/config/target/88vier_piradio.cfg index 7cc1aa7..8359efb 100644 --- a/tools/sync_cms/config/target/88vier_piradio.cfg +++ b/tools/sync_cms/config/target/88vier_piradio.cfg @@ -1,10 +1,8 @@ <target> - type google_calendar2 - <access> - calendarId li6if8drs373kf9ttot7er6suc@group.calendar.google.com - serviceAccount 433089473368-bv26eveq03b7nhb9p62nu3ts7htgb4g3@developer.gserviceaccount.com - serviceAccountKeyFile /home/radio/googleApi.key + calendarId your-id@group.calendar.google.com + serviceAccount your-account@developer.gserviceaccount.com + serviceAccountKeyFile googleApi.key </access> <date> diff --git a/tools/sync_cms/export_db.pl b/tools/sync_cms/export_db.pl deleted file mode 100644 index 79c3016..0000000 --- a/tools/sync_cms/export_db.pl +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/perl - -use strict; -use warnings; -use lib "../calcms"; -use utf8; - -use Data::Dumper; -use Config::General; -use Storable qw(nstore); - -use db; -use config; - -our $default={ - configFile => '/home/radio/piradio.de/agenda/config/config.cgi', - timezone => 'Europe/Berlin', - local_media_url => 'http://piradio.de/agenda_files/media/', - project => '88vier', - location => 'piradio', -}; - -my $config = config::get($default->{configFile}); -print Dumper($config); - -my $dbh=db::connect($config); -my $query=q{ - select * from calcms_events - order by start -}; - -my $events=db::get($dbh, $query); -nstore($events, 'event_export.dat'); diff --git a/tools/sync_cms/ical_html_to_ical_creole.pl b/tools/sync_cms/ical_html_to_ical_creole.pl deleted file mode 100644 index a512d49..0000000 --- a/tools/sync_cms/ical_html_to_ical_creole.pl +++ /dev/null @@ -1,17 +0,0 @@ -require '../lib/text_markup.pl'; - -open FILE,"<$ARGV[0]"; -while (<FILE>){ - my $line=$_; - if ($line=~/^DESCRIPTION:/){ - my $description=substr($line,length('DESCRIPTION:')); - my $html=markup::ical_to_plain($description); - my $creole=markup::html_to_creole($html); - my $ical=markup::plain_to_ical($creole); - $line= 'DESCRIPTION:'.$ical."\n"; - } - print $line; -} -close FILE; - - diff --git a/tools/sync_cms/import_ical.pl b/tools/sync_cms/import_ical.pl deleted file mode 100755 index ec25c76..0000000 --- a/tools/sync_cms/import_ical.pl +++ /dev/null @@ -1,162 +0,0 @@ -#!/usr/bin/perl - -use strict; -use warnings; -use lib "../calcms"; -use utf8; - -use DateTime; -use Net::Google::Calendar; -use DateTime::Format::ICal; -use Data::Dumper; -use Config::General; - -use db; -use config; -use creole_wiki; -use markup; -use events; - -my $filename=$ARGV[0]; -die("USAGE: $0 filename") unless defined $filename; -die("cannot read from '$filename'") unless -e $filename; - -our $default={ - configFile => '/home/radio/piradio.de/agenda/config/config.cgi', - timezone => 'Europe/Berlin', - local_media_url => 'http://piradio.de/agenda_files/media/', - project => '88vier', - location => 'piradio', -}; - -my $config = config::get($default->{configFile}); -print Dumper($config); - -parseICalFile($config, $filename); -our $active=0; -sub parseICalFile{ - my $config=shift; - my $filename=shift; - - print "open $filename\n"; - open my $file, "<:encoding(UTF-8)", $filename; - my $parse=0; - my $event=undef; - my $lastKey=undef; - - while (<$file>){ - my $line=$_; - #print $parse." ".$line; - if ($line=~/^BEGIN\:VEVENT/){ - $event={}; - $parse=1; - #print "start event\n"; - next; - } - if ($line=~/^END\:VEVENT/){ - $parse=0; - processEvent($config, $event) if defined $event; - #print "end event\n"; - next; - } - if ($line=~/^\s/){ - my $key = $lastKey; - my $value = substr($line, 1); - $value=~s/[\r\n]+$//; - $event->{$key}.=$value; - $lastKey=$key; - next; - }else{ - my ($key,$value)=split(/\:/,$line,2); - $value=~s/[\r\n]+$//; - $event->{$key}=$value; - $lastKey=$key; - } - - } - close $file; -} - -sub processEvent{ - my $config=shift; - my $source=shift; - - my $event={}; - - $event->{title} = $source->{SUMMARY}; - $event->{content} = $source->{DESCRIPTION}; - $event->{title} = markup::ical_to_plain($event->{title}); - $event->{content} = markup::ical_to_plain($event->{content}); - - unless (defined $source->{DTSTART}){ - print STDERR "missing DTSTART in ".Dumper($source); - return; - } - unless (defined $source->{DTEND}){ - print STDERR "missing DTEND in ".Dumper($source); - return; - } - my $start = DateTime::Format::ICal->parse_datetime($source->{DTSTART}); - $start=$start->set_time_zone($default->{timezone}); - $event->{start} = $start->datetime(); - - my $end = DateTime::Format::ICal->parse_datetime($source->{DTEND}); - $end = $end->set_time_zone($default->{timezone}); - $event->{end} = $end->datetime(); - - my $params={ - title => $event->{title}, - content => $event->{content}, - local_media_url => $default->{local_media_url} - }; - - #$params->{content}=~s/\x0A\x20/\n/g; - $event=creole_wiki::extractEventFromWikiText($params, $event); - - $event->{project} = $default->{project}; - $event->{location} = $default->{location}; - - return unless ($event->{start} ge '2015-09-01'); - - $active=1 if ($event->{series_name}=~/Brainwashed/); - print "$active $event->{start} $event->{series_name} - $event->{title}\n"; - #saveEvent($config, $event); - #exit; -} - -sub saveEvent{ - my $config = shift; - my $event = shift; - - $config->{access}->{write}=1; - my $dbh=db::connect($config); - - $event->{'html_content'}=markup::creole_to_html($event->{'content'}); - - # set start date - my $day_start=$config->{date}->{day_starting_hour}; - $event->{start_date} = time::add_hours_to_datetime($event->{start}, -$day_start); - $event->{start_date} = time::datetime_to_date($event->{start_date}); - - # set end date - $event->{end_date} = time::add_hours_to_datetime($event->{end}, -$day_start); - $event->{end_date} = time::datetime_to_date($event->{end_date}); - - delete $event->{categories} if defined $event->{categories}; - - # set time of day - my $day_times=$config->{date}->{time_of_day}; - my $event_hour=int((split(/[\-\:\sT]/,$event->{start}))[3]); - for my $hour(sort {$a <=> $b} (keys %$day_times)){ - if ($event_hour >= $hour){ - $event->{time_of_day}=$day_times->{$hour}; - }else{ - last; - }; - } - $event->{published}=0; - $event->{modified_by}='sync_cms'; - print Dumper($event); - #db::insert($dbh,'calcms_events', $event); -} - diff --git a/tools/sync_cms/lib/CalcmsEvents.pm b/tools/sync_cms/lib/CalcmsEvents.pm new file mode 100644 index 0000000..9f9d45e --- /dev/null +++ b/tools/sync_cms/lib/CalcmsEvents.pm @@ -0,0 +1,135 @@ +package CalcmsEvents; + +use strict; +use warnings; + +use Common ('info','error'); +use DateTime; +use Data::Dumper; + +use creole_wiki; +use events; +use time; +#use config; + +my $settings = {}; + +sub init($) { + $settings = shift || {}; +} + +sub set($$) { + my $key = shift; + my $value = shift; + $settings->{$key} = $value; +} + +sub get($) { + my $key = shift; + return $settings->{$key}; +} + +# return a list of start_min, start_max request parameters. +sub splitRequest($$$) { + my $from = shift; + my $till = shift; + my $timeZone = shift; + + return undef unless defined $from; + return undef unless defined $till; + return undef if $from eq ''; + return undef if $till eq ''; + + my $dates = []; + + my $start = time::get_datetime( $from, $timeZone ); + my $end = time::get_datetime( $till, $timeZone ); + + #build a list of dates + my $date = $start; + my @dates = (); + while ( $date < $end ) { + push @dates, $date; + $date = $date->clone->add( days => 7 ); + } + my $duration = $end - $date; + + push @dates, $end->clone if $duration->delta_seconds <= 0; + + #build a list of parameters from dates + $start = shift @dates; + for my $end (@dates) { + push @$dates, + { + from => $start, + till => $end + }; + $start = $end; + } + + return $dates; + +} + +#get a hash with per-day-lists days of a google calendar, given by its url defined at $calendar_name +sub getEvents($$) { + my $from = shift; + my $till = shift; + + my $last_update = get('last_update'); + info "getEvents from $from till $till"; + + my $request_parameters = { + from_date => $from, + till_date => $till, + project => get('project'), + archive => 'all', + template => 'no' + }; + my $location = get('location') || ''; + $request_parameters->{location} = $location if $location ne ''; + + my $config = $settings; + my %params = (); + my $request = { + url => $ENV{QUERY_STRING}, + params => { + original => \%params, + checked => events::check_params( $config, $request_parameters, $settings ), + }, + }; + + my $sourceEvents = events::get( $config, $request, $settings ); + + #return events by date + my $eventsByDate = {}; + for my $source (@$sourceEvents) { + $source->{calcms_start} = $source->{start}; + my $key = substr( $source->{start}, 0, 10 ); + push @{ $eventsByDate->{$key} }, $source; + } + return $eventsByDate; +} + +sub mapToSchema { + my $event = shift; + + #override settings by source map filter + for my $key ( keys %{ get('mapping') } ) { + $event->{$key} = get('mapping')->{$key}; + } + + #resolve variables set in mapped values + for my $mkey ( keys %{ get('mapping') } ) { + for my $key ( keys %{$event} ) { + my $val = $event->{$key}; + $val = $event->{$key} if ( $mkey eq $key ); + $event->{$mkey} =~ s/<TMPL_VAR $key>/$val/g; + } + } + + return $event; +} + +#do not delete last line +1; diff --git a/tools/sync_cms/lib/Common.pm b/tools/sync_cms/lib/Common.pm new file mode 100644 index 0000000..90b78ca --- /dev/null +++ b/tools/sync_cms/lib/Common.pm @@ -0,0 +1,75 @@ +package Common; +use warnings; +use strict; + +use Fcntl ':flock'; + +use base 'Exporter'; +our @EXPORT_OK = ( 'info', 'error' ); + +sub checkSingleInstance() { + open my $self, '<', $0 or die "Couldn't open self: $!"; + flock $self, LOCK_EX | LOCK_NB or die "This script $0 is already running"; +} + +sub loadFile($) { + my $filename = shift; + + my $content = ''; + open my $file, '<', $filename || die("cannot load $filename"); + while (<$file>) { + $content .= $_; + } + close $file; + return $content; +} + +sub saveFile($$) { + my $filename = shift; + my $content = shift; + open my $file, ">:utf8", $filename || die("cannot write $filename"); + print $file $content; + close $file; + +} + +sub getModifiedAt { + my $file = shift; + my @stats = stat $file; + return 0 if scalar @stats == 0; + my $modifiedAt = $stats[9]; + return $modifiedAt; +} + +sub execute($) { + my $command = shift; + print "EXEC:\t$command\n"; + my $result = `$command`; + my $exitCode = ( $? >> 8 ); + print "ERROR! exitCode=$?\n" if $exitCode > 0; + return ( $exitCode, $result ); +} + +my $debug = 0; + +sub debug($$) { + my $level = shift; + my $message = shift; + print $message. "\n" if $debug > $level; +} + +sub error ($) { + print "\nERROR: $_[0]\nsee $0 --help for help"; + exit 1; +} + +sub info ($) { + my $message = shift; + if ( $message =~ /^\n/ ) { + $message =~ s/^\n//g; + print "\n"; + } + print "INFO:\t$message\n"; +} + +return 1; diff --git a/tools/sync_cms/lib/GoogleCalendar.pm b/tools/sync_cms/lib/GoogleCalendar.pm new file mode 100644 index 0000000..57df031 --- /dev/null +++ b/tools/sync_cms/lib/GoogleCalendar.pm @@ -0,0 +1,197 @@ +package GoogleCalendar; + +use strict; +use warnings; + +use Data::Dumper; + +use lib '../calcms/'; +use Common ( 'info', 'error' ); +use GoogleCalendarApi(); +use time(); + +my $settings = {}; +my $cal = undef; +my $debug = 1; + +sub set($$) { + my $key = shift; + my $value = shift; + $settings->{$key} = $value; +} + +sub get($) { + my $key = shift; + return $settings->{$key}; +} + +sub init($) { + $settings = shift || {}; + + my $access = get('access'); + + # 1. create service account at https://console.developers.google.com/ + # 2. enable Calendar API + # 3. share calendar with service account for update permissions + + # see http://search.cpan.org/~shigeta/Google-API-Client-0.13/lib/Google/API/Client.pm + + my $serviceAccount = $access->{serviceAccount}; + my $serviceAccountKeyFile = $access->{serviceAccountKeyFile}; + my $calendarId = $access->{calendarId}; + + my $serviceAccountKey = Common::loadFile($serviceAccountKeyFile); + my $calendar = GoogleCalendarApi->new( + { + 'serviceAccount' => $serviceAccount, + 'privateKey' => $serviceAccountKey, + 'calendarId' => $calendarId, + 'debug' => 0 + } + ); + + $cal = $calendar; +} + +#map event schema to target schema +sub mapToSchema { + my $event = shift; + + #clone event + my $targetEvent = {}; + for my $key ( keys %{$event} ) { + $targetEvent->{$key} = $event->{$key}; + } + + if ( defined $event->{recurrence} && ref( $event->{recurrence} ) eq 'HASH' ) { + $targetEvent->{reference} .= '[' . $event->{recurrence}->{number} . ']' if ( $event->{recurrence}->{number} > 0 ); + $targetEvent->{recurrence} = $event->{recurrence}->{number} + 0; + } + $targetEvent->{rating} = 0; + $targetEvent->{visibility} = 0; + + #set project by project's date range + my $projects = get('projects'); + if ( ref($projects) eq 'HASH' ) { + for my $projectName ( keys %$projects ) { + my $project = get('projects')->{$projectName}; + my $start = substr( $event->{start}, 0, 10 ); + if ( $start ge $project->{start_date} && $start le $project->{end_date} ) { + $targetEvent->{project} = $project->{name}; + } + } + } + + #override settings by target map filter + for my $key ( keys %{ get('mapping') } ) { + $targetEvent->{$key} = get('mapping')->{$key}; + } + + #resolve variables set in mapped values + for my $mkey ( keys %{ get('mapping') } ) { + for my $key ( sort keys %{$targetEvent} ) { + my $val = $targetEvent->{$key}; + $val = $event->{$key} if $mkey eq $key; + $targetEvent->{$mkey} =~ s/<TMPL_VAR $key>/$val/g; + } + } + $targetEvent->{title} =~ s/\s+$//g; + $targetEvent->{title} =~ s/\s*\#$//g; + $targetEvent->{title} =~ s/\s*\-\s*$//g; + + my $schema = { event => $targetEvent }; + + return $schema; +} + +#this is done before sync and allows to delete old events before adding new +sub getEvents { + my $event = shift; + + return undef if get('date')->{'time_zone'} eq ''; + return undef if $event->{start} eq ''; + return undef if $event->{end} eq ''; + + #delete a span of dates + my $timeZone = get('date')->{'time_zone'}; + my $start = time::get_datetime( $event->{start}, $timeZone ); + my $end = time::get_datetime( $event->{end}, $timeZone ); + + info( "search target for events from " . $start . " to " . $end ); + + #search datetime with same timezone + my $events = $cal->getEvents( + { + timeMin => $cal->getDateTime( $start->datetime, $timeZone ), + timeMax => $cal->getDateTime( $end->datetime, $timeZone ), + maxResults => 50, + singleEvents => 'true', + orderBy => 'startTime' + } + ); + + return $events; +} + +# insert a new event +sub insertEvent { + my $event = shift; + my $entity = $event->{event}; + + $entity->{'html_content'} = markup::creole_to_html( $entity->{'content'} ); + + my $timeZone = get('date')->{'time_zone'}; + + my $start = $cal->getDateTime( $entity->{start}, $timeZone ); + my $end = $cal->getDateTime( $entity->{end}, $timeZone ); + + #info "insert event\t$start\t$entity->{title}"; + my $entry = { + start => $start, + end => $end, + summary => $entity->{title}, + description => $entity->{content}, + location => $entity->{location}, + transparency => 'transparent', + status => 'confirmed' + }; + + my $result = $cal->insertEvent($entry); + my $id = $result->{id}; +} + +sub deleteEvent { + my $event = shift; + + #info "delete event"; + $cal->deleteEvent( $event->{id} ); +} + +sub fixFields { + my $event = shift; + + #lower case for upper case titles longer than 4 characters + for my $attr ( 'series_name', 'title' ) { + my $val = $event->{$attr}; + my $c = 0; + while ( $val =~ /\b([A-Z]{5,99})\b/ && $c < 10 ) { + my $word = $1; + my $lower = lc $word; + $lower =~ s/^([a-z])/\u$1/gi; + $val =~ s/$word/$lower/g; + $c++; + } + $event->{$attr} = $val if $event->{$attr} ne $val; + } + + for my $attr ( 'series_name', 'title', 'excerpt', 'content' ) { + my $val = $event->{$attr}; + $val =~ s/^\s*(.*?)\s*$/$1/g; + $val =~ s/^[ \t]/ /g; + $event->{$attr} = $val if $event->{$attr} ne $val; + } + return $event; +} + +#do not delete last line +1; diff --git a/tools/sync_cms/lib/GoogleCalendarApi.pm b/tools/sync_cms/lib/GoogleCalendarApi.pm index aec1490..4d690c0 100644 --- a/tools/sync_cms/lib/GoogleCalendarApi.pm +++ b/tools/sync_cms/lib/GoogleCalendarApi.pm @@ -2,6 +2,7 @@ package GoogleCalendarApi; use strict; use warnings; + use JSON; use JSON::WebToken; use LWP::UserAgent; @@ -9,34 +10,38 @@ use HTML::Entities; use URI::Escape; use Data::Dumper; use DateTime; +use Time::HiRes qw(sleep); +use Common ( 'info', 'error' ); sub new { my $class = shift; my $params = shift; - - my $self={}; - for my $attr ('calendarId','debug'){ - $self->{$attr}=$params->{$attr} if defined $params->{$attr}; + + #print Dumper($class); + my $self = {}; + for my $attr ( 'calendarId', 'debug' ) { + $self->{$attr} = $params->{$attr} if defined $params->{$attr}; } - - my $instance=bless $self, $class; - if ((defined $params->{serviceAccount}) && (defined $params->{privateKey})){ - $instance->login($params->{serviceAccount}, $params->{privateKey}); + $self->{debug} = 1; + + my $instance = bless $self, $class; + if ( ( defined $params->{serviceAccount} ) && ( defined $params->{privateKey} ) ) { + $instance->login( $params->{serviceAccount}, $params->{privateKey} ); } - + return $instance; } -sub setCalendar{ - my $self=shift; - my $calendarId=shift; - $self->{calendarId}=$calendarId; +sub setCalendar { + my $self = shift; + my $calendarId = shift; + $self->{calendarId} = $calendarId; } -sub getBasicUrl{ - my $self=shift; - return 'https://www.googleapis.com/calendar/v3/calendars/'.encode_entities($self->{calendarId}); +sub getBasicUrl { + my $self = shift; + return 'https://www.googleapis.com/calendar/v3/calendars/' . encode_entities( $self->{calendarId} ); } #https://developers.google.com/google-apps/calendar/v3/reference/events/list @@ -52,149 +57,161 @@ sub getBasicUrl{ # 'updated' => '2014-11-12T19:46:22.086Z', # 'items' => [...] # } -sub getEvents{ - my $self=shift; - my $params=shift; +sub getEvents { + my $self = shift; + my $params = shift; - my $url='/events?'; - for my $param ('iCalUID','alwaysIncludeEmail','maxAttendees','maxResults','orderBy','pageToken','privateExtendedProperty', - 'q','sharedExtendedProperty','showDeleted','showHiddenInvitations','singleEvents','syncToken','timeZone' - ){ - $url.='&'.$param.'='.uri_escape($params->{$param}) if defined $params->{$param}; + my $url = '/events?'; + for my $param ( + 'iCalUID', 'alwaysIncludeEmail', 'maxAttendees', 'maxResults', + 'orderBy', 'pageToken', 'privateExtendedProperty', 'q', + 'sharedExtendedProperty', 'showDeleted', 'showHiddenInvitations', 'singleEvents', + 'syncToken', 'timeZone' + ) + { + $url .= '&' . $param . '=' . uri_escape( $params->{$param} ) if defined $params->{$param}; } - for my $param ('timeMin','timeMax','updatedMin'){ - $url.='&'.$param.'='.uri_escape($self->formatDateTime($params->{$param})) if defined $params->{$param}; + for my $param ( 'timeMin', 'timeMax', 'updatedMin' ) { + $url .= '&' . $param . '=' . uri_escape( $self->formatDateTime( $params->{$param} ) ) if defined $params->{$param}; } - my $result=$self->httpRequest('GET', $url); + my $result = $self->httpRequest( 'GET', $url ); return $result; } # sleep 0.25 seconds to prevent hitting the 5.0 requests/second/user rate -sub sleep{ - my $this=shift; - my $duration=shift || 0.25; - select(undef, undef, undef, $duration); -} +#sub sleep{ +# my $this=shift; +# my $duration=shift; +# $duration=1 unless defined $duration; +# select(undef, undef, undef, $duration); +#} #https://developers.google.com/google-apps/calendar/v3/reference/events/delete -sub deleteEvent{ - my $self=shift; - my $eventId=shift; - my $url='/events/'.$eventId; +sub deleteEvent { + my $self = shift; + my $eventId = shift; + my $url = '/events/' . $eventId; + #DELETE https://www.googleapis.com/calendar/v3/calendars/calendarId/events/eventId - my $result=$self->httpRequest('DELETE', $url); - $self->sleep(); + my $result = $self->httpRequest( 'DELETE', $url ); + + #$self->sleep(); return $result; } #https://developers.google.com/google-apps/calendar/v3/reference/events/insert -sub insertEvent{ - my $self=shift; - my $params=shift; +sub insertEvent { + my $self = shift; + my $params = shift; - my $event={ + my $event = { start => { - dateTime => $self->formatDateTime($params->{start}) + dateTime => $self->formatDateTime( $params->{start} ) }, - end => { - dateTime => $self->formatDateTime($params->{end}) + end => { + dateTime => $self->formatDateTime( $params->{end} ) }, - summary => $params->{summary}||'', - description => $params->{description}||'', - location => $params->{location}||'', - status => $params->{confirmed}||'confirmed' + summary => $params->{summary} || '', + description => $params->{description} || '', + location => $params->{location} || '', + status => $params->{confirmed} || 'confirmed' }; - $event= encode_json $event; + $event = encode_json $event; #POST https://www.googleapis.com/calendar/v3/calendars/calendarId/events - my $url='/events'; - my $result=$self->httpRequest('POST', $url, $event); - $self->sleep(); + my $url = '/events'; + my $result = $self->httpRequest( 'POST', $url, $event ); + + #$self->sleep(); return $result; } # send a HTTP request -sub httpRequest{ - my $self=shift; - my $method=shift; - my $url=shift; - my $content=shift||''; - - print STDERR "$method ".$url."\n" if $self->{debug}; +sub httpRequest { + my $self = shift; + my $method = shift; + my $url = shift; + my $content = shift || ''; - die ("missing url") unless defined $url; - die ("calendarId not set") unless defined $self->{calendarId}; - die ("not logged in ") unless defined $self->{api}; + sleep 0.3; + print STDERR "$method " . $url . "\n" if $self->{debug}; - #prepend basic url including calendar id - $url=$self->getBasicUrl().$url; - print STDERR "$method ".$url."\n" if $self->{debug}; + die("missing url") unless defined $url; + die("calendarId not set") unless defined $self->{calendarId}; + die("not logged in ") unless defined $self->{api}; - my $response=undef; - if($method eq 'GET'){ + #prepend basic url including calendar id + $url = $self->getBasicUrl() . $url; + print STDERR "$method " . $url . "\n" if $self->{debug}; + + my $response = undef; + if ( $method eq 'GET' ) { $response = $self->{api}->get($url); - }elsif(($method eq 'POST')||($method eq 'PUT')){ - print STDERR $content."\n" if $self->{debug}; + } elsif ( ( $method eq 'POST' ) || ( $method eq 'PUT' ) ) { + #return; + print STDERR $content . "\n" if $self->{debug}; my $request = HTTP::Request->new( $method, $url ); $request->header( 'Content-Type' => 'application/json' ); - $request->content( $content ); - $response=$self->{api}->request( $request ); - }elsif($method eq 'DELETE'){ + $request->content($content); + $response = $self->{api}->request($request); + } elsif ( $method eq 'DELETE' ) { + #return; $response = $self->{api}->delete($url); } - if($response->is_success) { + if ( $response->is_success ) { my $content = $response->content; return {} if $content eq ''; return decode_json($content); } else { print "ERROR:\n"; - print "Code: ".$response->code."\n"; - print "Message: ".$response->message."\n"; - print $response->content."\n"; + print "Code: " . $response->code . "\n"; + print "Message: " . $response->message . "\n"; + print $response->content . "\n"; die; } } # write datetime object to string -sub formatDateTime{ - my $self=shift; - my $dt=shift; +sub formatDateTime { + my $self = shift; + my $dt = shift; - my $datetime= $dt->format_cldr("yyyy-MM-ddTHH:mm:ssZZZZZ"); + my $datetime = $dt->format_cldr("yyyy-MM-ddTHH:mm:ssZZZZZ"); print STDERR "$dt -> $datetime\n" if $self->{debug}; return $datetime; } # parse datetime from string to object -sub getDateTime{ - my $self=shift; - my $datetime=shift; - my $timezone=shift; +sub getDateTime { + my $self = shift; + my $datetime = shift; + my $timezone = shift; - return if((!defined $datetime) or ($datetime eq '')); - my @l=split /[\-\;T\s\:\+\.]/,$datetime; + return if ( !defined $datetime ) or ( $datetime eq '' ); + my @l = split /[\-\;T\s\:\+\.]/, $datetime; - $datetime=DateTime->new( - year => $l[0], - month => $l[1], - day => $l[2], - hour => $l[3], - minute => $l[4], - second => $l[5], - time_zone => $timezone - ); - return $datetime; + $datetime = DateTime->new( + year => $l[0], + month => $l[1], + day => $l[2], + hour => $l[3], + minute => $l[4], + second => $l[5], + time_zone => $timezone + ); + return $datetime; } # login with serviceAccount and webToken (from privateKey) -sub login{ - my $self=shift; - my $serviceAccount=shift; - my $privateKey=shift; +sub login { + my $self = shift; + my $serviceAccount = shift; + my $privateKey = shift; # https://developers.google.com/accounts/docs/OAuth2ServiceAccount my $time = time; + #create JSON Web Token my $jwt = JSON::WebToken->encode( { @@ -203,10 +220,10 @@ sub login{ aud => 'https://accounts.google.com/o/oauth2/token', exp => $time + 3600, iat => $time, - }, - $privateKey, - 'RS256', - {typ => 'JWT'} + }, + $privateKey, + 'RS256', + { typ => 'JWT' } ); #send JSON web token to authentication service @@ -215,16 +232,16 @@ sub login{ 'https://accounts.google.com/o/oauth2/token', { grant_type => encode_entities('urn:ietf:params:oauth:grant-type:jwt-bearer'), - assertion => $jwt + assertion => $jwt } ); - - die($response->code, "\n", $response->content, "\n") unless $response->is_success(); - my $data= decode_json($response->content); - + + die( $response->code, "\n", $response->content, "\n" ) unless $response->is_success(); + my $data = decode_json( $response->content ); + #create a new user agent and set token to bearer $self->{api} = LWP::UserAgent->new(); - $self->{api}->default_header(Authorization => 'Bearer ' . $data->{access_token}); + $self->{api}->default_header( Authorization => 'Bearer ' . $data->{access_token} ); print STDERR "login successful\n" if $self->{debug}; return $data; diff --git a/tools/sync_cms/lib/source/calcms_i.pl b/tools/sync_cms/lib/source/calcms_i.pl deleted file mode 100644 index 962c25d..0000000 --- a/tools/sync_cms/lib/source/calcms_i.pl +++ /dev/null @@ -1,133 +0,0 @@ -#use markup; -use creole_wiki; -use DateTime; -use events; -use time; -use config; -#use DateTime::Format::ICal; - -package source; -use Data::Dumper; - -my $settings={}; - -sub init{ - $source::settings=shift; - #print STDERR Dumper($source::settings); -} - -#return a list of start_min, start_max request parameters. list is defined as timespan given by start_min and start_max in source_options -sub split_request{ - - return undef if ( - (!(defined $source::settings->{start_min})) || ($source::settings->{start_min} eq'') - ||(!(defined $source::settings->{start_max})) || ($source::settings->{start_max} eq'') - ); - - #print Dumper($source_options); - my $dates=[]; - - my $start =time::get_datetime($source::settings->{start_min},$source::settings->{date}->{time_zone}); - my $end =time::get_datetime($source::settings->{start_max},$source::settings->{date}->{time_zone}); - my $date =$start; - - #build a list of dates - my @dates=(); - while ($date < $end){ - push @dates,$date; - $date=$date->clone->add(days=>7); - } - my $duration=$end-$date; -# print "sec:".($duration->delta_seconds/(60*60))."\n"; - if ($duration->delta_seconds <= 0){ -# pop @dates; - push @dates,$end->clone; - } - - #build a list of parameters from dates - my $start=shift @dates; - for my $end (@dates){ - push @$dates,{ - start_min => $start, - start_max => $end - }; - $start=$end; - } - -# for $day(@$dates){print "$day->{start_min} - $day->{start_max}\n";} - return $dates; - -} - -#get a hash with per-day-lists days of a google calendar, given by its url defined at $calendar_name -sub get_events{ - my $block_number =$source::settings->{block_number}; - my $block_size =$source::settings->{block_size}; - my $last_update =$source::settings->{last_update}; - - #print Dumper($request); - - my $request_parameters={ - from_date => $source::settings->{start_min}, - till_date => $source::settings->{start_max}, - archive => 'all', - project => $source::settings->{project}, - template => 'no' - }; - $request_parameters->{location}=$source::settings->{location} if ($source::settings->{location}ne''); - - my $config = $source::settings; - my $request={ - url => $ENV{QUERY_STRING}, - params => { - original => \%params, - checked => events::check_params($config, - $request_parameters, - $source::settings - ), - }, - }; - #print Dumper($request); - - my $source_events=events::get($config, $request, $source::settings); - #print Dumper($source_events); - - #return events by date - my $sources_by_date={}; - my $old_start=''; - for my $source (@$source_events){ - $source->{calcms_start}=$source->{start}; - my $key=substr($source->{start},0,10); - push @{$sources_by_date->{$key}},$source; - } - return $sources_by_date; -} - -sub get_event_attributes{ - my $source=shift; - return $source; -} - -sub map_to_schema{ - my $event=shift; -# print Dumper($source_options); -# exit; - - #override settings by source map filter - for my $key (keys %{$source::settings->{mapping}}){ - $event->{$key}=$source::settings->{mapping}->{$key}; - } - - #resolve variables set in mapped values - for my $mkey (keys %{$source::settings->{mapping}}){ - for my $key (keys %{$event}){ - my $val=$event->{$key}; - $val=$event->{$key} if($mkey eq $key); - $event->{$mkey}=~s/<TMPL_VAR $key>/$val/g; - } - } - - return $event; -} - -eof; diff --git a/tools/sync_cms/lib/source/google_calendar.pl b/tools/sync_cms/lib/source/google_calendar.pl deleted file mode 100755 index 4ce739a..0000000 --- a/tools/sync_cms/lib/source/google_calendar.pl +++ /dev/null @@ -1,339 +0,0 @@ -#use markup; -use creole_wiki; -use DateTime; -use Net::Google::Calendar; -use DateTime::Format::ICal; - -package source; -#do 'time.pl'; -use Data::Dumper; - -my $settings={}; - -sub init{ - $source::settings=shift; -} - -#return a list of start_min, start_max request parameters. -#list is defined as timespan given by start_min and start_max in source::settings -sub split_request{ - - return undef if ( - (!(defined $source::settings->{start_min})) || ($source::settings->{start_min} eq'') - ||(!(defined $source::settings->{start_max})) || ($source::settings->{start_max} eq'') - ); - - my $dates=[]; - - my $start =get_datetime($source::settings->{start_min},$source::settings->{date}->{time_zone}); - my $end =get_datetime($source::settings->{start_max},$source::settings->{date}->{time_zone}); - my $date =$start; - - #build a list of dates - my @dates=(); - while ($date < $end){ - push @dates,$date; - $date=$date->clone->add(days=>7); - } - my $duration=$end-$date; -# print "sec:".($duration->delta_seconds/(60*60))."\n"; - if ($duration->delta_seconds <= 0){ -# pop @dates; - push @dates,$end->clone; - } - - #build a list of parameters from dates - my $start=shift @dates; - for my $end (@dates){ - push @$dates,{ - start_min => $start, - start_max => $end - }; - $start=$end; - } - -# for $day(@$dates){print "$day->{start_min} - $day->{start_max}\n";} - return $dates; - -} - -#get a hash with per-day-lists days of a google calendar, given by its url defined at $calendar_name -sub get_events{ - -# print Dumper($source::settings); - my $url =$source::settings->{access}->{url}; - my $email =$source::settings->{access}->{email}; - my $password =$source::settings->{access}->{password}; - - my $block_number =$source::settings->{block_number}; - my $block_size =$source::settings->{block_size}; - my $last_update =$source::settings->{last_update}; - - my $parameters={}; - my $start_index=undef; - my $stop_index=undef; - if ($source::settings->{read_blocks}==1){ - my $start_index=$block_number*$block_size+1 ; - my $stop_index=$start_index+$block_size-1; - $parameters->{"start-index"} = $start_index; - $parameters->{"max-results"} = $block_size; - $source::settings->{start_index}=$start_index; - $source::settings->{stop_index}=$stop_index; - }else{ - $parameters->{"max-results"} = 10000; - } - - #see http://code.google.com/intl/de/apis/calendar/data/2.0/reference.html - $parameters->{singleevents}='true'; - $parameters->{orderby}='lastmodified'; - - my $more='modified' if (defined $last_update && $source::settings->{modified_events}==1); - main::print_info("read $more events from google calendar: '".substr($url,0,40)."...".substr($url,length($url)-8)."'"); - - # print "\nblock '$block_number' (events ".$start_index."..".$stop_index.") \n" if (defined $block_number || defined $start_index || defined $stop_index); - - # http://search.cpan.org/~simonw/Net-Google-Calendar-0.97/lib/Net/Google/Calendar.pm#get_events_[_%opts_] - - my $cal = Net::Google::Calendar->new( url => $url ); - #main::print_info("new\n"); - if ($email ne'' && $password ne''){ - $cal->login($email, $password) ; - # $cal->auth($email, $password) if ($email ne'' && $password ne''); - # main::print_info("login $email $password"); - } - #print Dumper($cal); - - #set UTF-8 - $XML::Atom::ForceUnicode = 1; - $XML::Atom::DefaultVersion = "1.0"; - -# my $xml=$cal->get_xml(); -# $xml=~s/<content/\n<content/gi; -# print $xml."\n"; -# exit; - - #set updated-min (using UTC) - if ((defined $last_update) && ($source::settings->{modified_events}==1)){ - my $datetime=$last_update; - $datetime=source::get_datetime($datetime,$source::settings->{date}->{time_zone}) if (ref($datetime)eq''); - $datetime->set_time_zone('UTC'); - $parameters->{"updated-min"} = $datetime->datetime; - #print "last update\n"; - } - #set start min (using UTC) - if ((defined $source::settings->{start_min}) && ($source::settings->{start_min}ne'')){ - my $datetime=$source::settings->{start_min}; - $datetime=source::get_datetime($datetime,$source::settings->{date}->{time_zone}) if (ref($datetime)eq''); - $datetime->set_time_zone('UTC'); - $parameters->{"start-min"} = $datetime->datetime; - $parameters->{"recurrence-expansion-start"}= $datetime->datetime; - } - #set start max (using UTC) - if ((defined $source::settings->{start_max})&&($source::settings->{start_max} ne'')){ - my $datetime=$source::settings->{start_max}; - $datetime=source::get_datetime($datetime,$source::settings->{date}->{time_zone}) if (ref($datetime)eq''); - $datetime->set_time_zone('UTC'); - $parameters->{"start-max"} = $datetime->datetime; - $parameters->{"recurrence-expansion-end"}= $datetime->datetime; - } - - -# print Dumper($parameters); - my @events=(); - my @source_events=$cal->get_events(%$parameters); - main::print_info("found ".@source_events." events"); - -# print Dumper($parameters); -# print Dumper($source::settings); -# exit; - - for my $source(@source_events) { - (my $start,my $end)=$source->when; - $start= $start->set_time_zone($source::settings->{date}->{time_zone})->datetime if (defined $start); - $end= $end->set_time_zone ($source::settings->{date}->{time_zone})->datetime if (defined $end); - $source->{calcms_start} = $start; - $source->{calcms_end} = $end; - $source->{status} = $source->status; - } - - #return events by date - my $sources_by_date={}; - my $old_start=''; -# for my $source (sort{$a->{calcms_start} cmp $b->{calcms_start} }@source_events){ - for my $source (@source_events){ -# if ($source->{status}eq'confirmed'){ - my $key=substr($source->{calcms_start},0,10); -# if ($old_start eq $source->{calcms_start}){ -# my $source=pop (@{$sources_by_date->{$key}}); -# print STDERR "WARNING: ignore canceled entry in google calendar: ".$source->{calcms_start}."\t".$source->{title}."\t".$source->{id}."\n"; -# } -# - push @{$sources_by_date->{$key}},$source; -# -# $old_start=$source->{calcms_start}; -# } - } - return $sources_by_date; -} - -sub map_to_schema{ - my $event=shift; - - my $params={ - title => $event->{title}, - content => $event->{content}, - local_media_url => '<TMPL_VAR local_media_url>' - }; - $params->{content}=~s/\x0A\x20/\n/g; - #print Dumper($params); - #open FILE,">/tmp/test"; - #print FILE Dumper($params); - #close FILE; - - #decode event - $event=creole_wiki::extractEventFromWikiText($params, $event); - #exit; - - #override settings by source map filter - for my $key (keys %{$source::settings->{mapping}}){ - $event->{$key}=$source::settings->{mapping}->{$key}; - } - - #resolve variables set in mapped values - for my $mkey (keys %{$source::settings->{mapping}}){ - for my $key (keys %{$event}){ - my $val=$event->{$key}; - $val=$event->{$key} if($mkey eq $key); - $event->{$mkey}=~s/<TMPL_VAR $key>/$val/g; - } - } - #print Dumper($event); - - return $event; -} - -sub get_event_attributes{ - my $source=shift; - - #print @source_events." ".Dumper($source)."\n"; - #use Data::Dumper;print Dumper($source->when); - - #create an hash with calendar event settings - my $event={ - start => $source->{calcms_start}, - end => $source->{calcms_end}, - status => $source->{status}, -# recurrence => $source->{recurrence}, - reference => $source->id, -# program => $program, -# series_name => $series_name, - title => $source->title, - content => $source->content->body, - author_name => $source->author->name, - author_uri => $source->author->uri, - author_email => $source->author->email, - transparency => $source->transparency, - visibility => $source->visibility, - location => $source->location, -# podcast_url => $podcast_url, -# media_url => $media_url, -# comments => $source->comments -# who_name => $source->who->name, -# who_email => $source->who->email, -# who_attendee_status => $source->who->attendee_status, - }; - #print Dumper($event); - -# if ($source->recurrence){ -# $event->{recurrence}=get_event_recurrence($source,$event); -# } - - return $event; -} - -sub get_event_recurrence{ - my $source=shift; - my $event=shift; - #print Dumper(); - - my $event_recurrence=$source->recurrence; - my $properties = $event_recurrence->properties; -# print Dumper($properties); - - my $dtstart = $properties->{dtstart}->[0]->{value}; - my $timezone = $properties->{dtstart}->[0]->{_parameters}->{TZID}; - my $dtend = $properties->{dtend}->[0]->{value}; - my $rrule = $properties->{rrule}->[0]->{value}; -# print $rrule."\n"; - - #convert timezone from "until=<datetime>" to same datetime as in dtstart - if ($rrule=~/UNTIL=([\dT]+Z?)/){ - my $ical=$1; - - #convert timezone at ical format - my $datetime= DateTime::Format::ICal->parse_datetime($ical); - $datetime=$datetime->set_time_zone($timezone); - $ical=DateTime::Format::ICal->format_datetime($datetime); - - #remove TZID=... from ical, since not implemented at format_datetime - $ical=~s/[^\:]+\://; - $rrule=~s/(UNTIL\=)([\dT]+Z?)/$1$ical/g; -# print $datetime->datetime." --> $ical --> $rrule\n"; - } - - $dtstart = DateTime::Format::ICal->parse_datetime($dtstart); - $dtend = DateTime::Format::ICal->parse_datetime($dtend);#->add(seconds=>3600)->set_time_zone('UTC'); - - my $recurrence={ - dtstart => $dtstart, - dtend => $dtend, - rrule => $rrule - }; - - #calc duration of the event - my $duration=$dtend-$dtstart; - my $duration_min=$duration->delta_minutes; - -# print Dumper($duration_min); - #print Dumper($recurrence); - my $recurrence_start = DateTime::Format::ICal->parse_recurrence( - recurrence =>$rrule, - dtstart =>$dtstart - ); - - #step through recurrent events and mark if event matchs - my $start_iter = $recurrence_start->iterator; - $c=1; - while (my $start = $start_iter->next ){ -# print "$start eq $event->{start}, $end\n"; - $recurrence->{number}=$c if ($start eq $event->{start}); -# push @dates,{ -# start => $start->set_time_zone($source::settings->{time_zone})->datetime, -# end => $start->set_time_zone($source::settings->{time_zone})->add(minutes=>$duration_min)->datetime -# }; - $c++; - } - $event->{recurrence}=$recurrence; - #print Dumper($event->{recurrence}); - -} - -sub get_datetime{ - my $datetime=shift; - my $timezone=shift; - - return if((!defined $datetime) or ($datetime eq '')); - my @l=@{time::datetime_to_array($datetime)}; - $datetime=DateTime->new( - year =>$l[0], - month =>$l[1], - day =>$l[2], - hour =>$l[3], - minute =>$l[4], - second =>$l[5], - time_zone=> $timezone - ); - return $datetime; -} - -eof; diff --git a/tools/sync_cms/lib/target/google_calendar.pl b/tools/sync_cms/lib/target/google_calendar.pl deleted file mode 100644 index 84b705d..0000000 --- a/tools/sync_cms/lib/target/google_calendar.pl +++ /dev/null @@ -1,233 +0,0 @@ -#require 'db.pl'; -#use db; -#use markup; - -package target; -use Data::Dumper; -use Net::Google::Calendar; -use time; - -my $settings={}; -my $cal = undef; -#my $op_count=0; - -sub init{ - $target::settings=shift; - my $access=$target::settings->{access}; - $target::cal = Net::Google::Calendar->new( url => $access->{url} ); - #main::print_info("init\n"); - #main::print_info("new\n"); - #print Dumper($access); - - my $email=$access->{email}; - my $password=$access->{password}; - if ($email ne'' && $password ne''){ - $target::cal->login($email, $password) ; - # $target::cal->auth($email, $password) if ($email ne'' && $password ne''); - main::print_info("loged in"); - } - #print Dumper($target::cal); - -# for my $c($target::cal->get_calendars) { -# print "'".$c->title."'\n"; -# print $c->id."\n\n"; -# if ($c->title eq 'petra poss'){ -# $target::cal->set_calendar($c); -# main::print_info("found matching calendar!"); -# } -# } -# exit; - - #set UTF-8 - $XML::Atom::ForceUnicode = 1; - $XML::Atom::DefaultVersion = "1.0"; - -} - -#map event schema to target schema -sub map_to_schema{ - my $event=shift; - - #clone event - my $target_event={}; - for my $key (keys %{$event}){ - $target_event->{$key}=$event->{$key}; - } - - $target_event->{reference}.='['.$event->{recurrence}->{number}.']' if ($event->{recurrence}->{number}>0); - $target_event->{recurrence} => $event->{recurrence}->{number}+0; - $target_event->{rating} => 0; - $target_event->{visibility} => 0; -# $target_event->{transparency} => $event->{transparency}; - - #set project by project's date range - for my $project_name (keys %{$target::settings->{projects}}){ - my $project=$target::settings->{projects}->{$project_name}; - my $start=substr($event->{start},0,10); - if ($start ge $project->{start_date} && $start le $project->{end_date}){ - $target_event->{project}=$project->{name}; - } -# print "$event->{start} gt $project->{start_date} $target_event->{project}\n"; - } - - #override settings by target map filter - for my $key (keys %{$target::settings->{mapping}}){ - $target_event->{$key}=$target::settings->{mapping}->{$key}; - } - #use Data::Dumper;print Dumper($target_event); - - #resolve variables set in mapped values - for my $mkey (keys %{$target::settings->{mapping}}){ - my $mval=$target_event->{$mkey}; - for my $key (sort keys %{$target_event}){ - my $val=$target_event->{$key}; - $val=$event->{$key} if($mkey eq $key); - #print $target_event->{$mkey}."\t".$key."-> $val\n"; - $target_event->{$mkey}=~s/<TMPL_VAR $key>/$val/g; - } - } - #use Data::Dumper;print Dumper($target_event);#exit; - - #$schema->{event}=fix_fields($schema->{event}); - - my $schema={ - event => $target_event - }; - - return $schema; -} - -# get a event by an existing google id, e.g. to check if the event exists in target -sub get_event_by_reference_id{ - return undef; -} - -#try to find a event, matching to $event from google calendar -sub find_event{ - my $event=shift; - return undef; - -} - -sub pre_sync{ - my $event=shift; - - $debug=1; - return undef if(($target::settings->{date}->{'time_zone'} eq '') || ($event->{start} eq '' ) || ($event->{end} eq '')); - - #delete a span of dates - print "\n" if ($debug eq '1'); - my $time_zone=$target::settings->{date}->{'time_zone'}; - my $start=time::get_datetime($event->{start},$time_zone); - $start->set_time_zone('UTC'); - $parameters->{"start-min"} = $start->datetime; - #$parameters->{"recurrence-expansion-start"}= $start->datetime; - - my $end=time::get_datetime($event->{end},$time_zone); - $end->set_time_zone('UTC'); - $parameters->{"start-max"} = $end->datetime; - #$parameters->{"recurrence-expansion-end"}= $end->datetime; - - main::print_info("search target for events from ".$start." to ".$end) if ($debug eq '1'); - - my @events=$target::cal->get_events(%$parameters); - - for my $event(@events){ - main::print_info("delete ".$event->title) if ($debug eq '1'); - $target::cal->delete_entry($event); - }; -} - - -# insert a new event -sub insert_event{ - my $event=shift; - my $entity=$event->{event}; - - $entity->{'html_content'}=markup::creole_to_html($entity->{'content'}); - - my $time_zone =$target::settings->{date}->{'time_zone'}; - my $start =time::get_datetime($entity->{start},$time_zone); - my $end =time::get_datetime($entity->{end},$time_zone); - #print Dumper($start)."\n"; - #print Dumper($end)."\n"; - print "\n" if ($debug eq '1'); - - main::print_info("insert event") if ($debug eq '1'); - my $entry = Net::Google::Calendar::Entry->new(); - - #print Dumper($entity); - $entry->title($entity->{title}); - $entry->content($entity->{content}); - $entry->location($entity->{location}); - $entry->transparency('transparent'); - $entry->status('confirmed'); - $entry->when($start, $end); - #print Dumper($entry); - - $target::cal->add_entry($entry); - #exit; -} - - -# update an existing event -sub update_event{ - return; -} -### end of interface implementation ### - - -sub print_event{ - my $header=shift; - my $event=shift; - - if ($header eq'google'){ - print "\n===== $header ====="; - }else{ - print "$header\n" if $header ne ''; - } -# print qq!$event->{start} $event->{program} : $event->{series_name} - $event->{title}!."\n"; - #content: >$event->{content}< -}; - -sub delete_event{ - return; - -} - -sub fix_fields{ - my $event=shift; - #lower case for upper case titles longer than 4 characters - for my $attr qw(program series_name title){ - my $val=$event->{$attr}; - my $c=0; - while ($val=~/\b([A-Z]{5,99})\b/ && $c<10){ - my $word=$1; - my $lower=lc $word; - $lower=~s/^([a-z])/\u$1/gi; - $val=~s/$word/$lower/g; - $c++; - } - if ($event->{$attr} ne $val){ - $event->{$attr}=$val; -# print Dumper($event->{$attr}).'<>'.Dumper($val)."\n" ; - } - } - - for my $attr qw(program series_name title excerpt content ){ - my $val=$event->{$attr}; - $val=~s/^\s*(.*?)\s*$/$1/g; - $val=~s/^[ \t]/ /g; - if ($event->{$attr} ne $val){ - $event->{$attr}=$val; -# print Dumper($event->{$attr}).'<>'.Dumper($val)."\n" ; - } - } - return $event; -} - -sub clean_up{ - return; -} - -1; diff --git a/tools/sync_cms/lib/target/google_calendar2.pl b/tools/sync_cms/lib/target/google_calendar2.pl deleted file mode 100644 index ada99a8..0000000 --- a/tools/sync_cms/lib/target/google_calendar2.pl +++ /dev/null @@ -1,254 +0,0 @@ -#require 'db.pl'; -#use db; -#use markup; - -package target; -use lib '/home/radio/calcms/sync_cms/lib/'; -use Data::Dumper; -#use Net::Google::Calendar; -use GoogleCalendarApi; -use time; - -my $settings={}; -my $cal = undef; -#my $op_count=0; - -sub init{ - $target::settings=shift; - my $access=$target::settings->{access}; - - # 1. create service account at https://console.developers.google.com/ - # 2. enable Calendar API - # 3. share calendar with service account for update permissions - - # see http://search.cpan.org/~shigeta/Google-API-Client-0.13/lib/Google/API/Client.pm - - my $serviceAccount = $access->{serviceAccount}; - my $serviceAccountKeyFile = $access->{serviceAccountKeyFile}; - my $calendarId = $access->{calendarId}; - - my $serviceAccountKey = loadFile($serviceAccountKeyFile); - - #print "connect...\n"; - my $calendar = new GoogleCalendarApi({ - 'serviceAccount' => $serviceAccount, - 'privateKey' => $serviceAccountKey, - 'calendarId' => $calendarId, - 'debug' => 0 - }); - #print Dumper($calendar); - $target::cal = $calendar; - -} - -#map event schema to target schema -sub map_to_schema{ - my $event=shift; - - #clone event - my $target_event={}; - for my $key (keys %{$event}){ - $target_event->{$key}=$event->{$key}; - } - - $target_event->{reference}.='['.$event->{recurrence}->{number}.']' if ($event->{recurrence}->{number}>0); - $target_event->{recurrence} => $event->{recurrence}->{number}+0; - $target_event->{rating} => 0; - $target_event->{visibility} => 0; -# $target_event->{transparency} => $event->{transparency}; - - #set project by project's date range - for my $project_name (keys %{$target::settings->{projects}}){ - my $project=$target::settings->{projects}->{$project_name}; - my $start=substr($event->{start},0,10); - if ($start ge $project->{start_date} && $start le $project->{end_date}){ - $target_event->{project}=$project->{name}; - } -# print "$event->{start} gt $project->{start_date} $target_event->{project}\n"; - } - - #override settings by target map filter - for my $key (keys %{$target::settings->{mapping}}){ - $target_event->{$key}=$target::settings->{mapping}->{$key}; - } - #use Data::Dumper;print Dumper($target_event); - - #resolve variables set in mapped values - for my $mkey (keys %{$target::settings->{mapping}}){ - my $mval=$target_event->{$mkey}; - for my $key (sort keys %{$target_event}){ - my $val=$target_event->{$key}; - $val=$event->{$key} if($mkey eq $key); - #print $target_event->{$mkey}."\t".$key."-> $val\n"; - $target_event->{$mkey}=~s/<TMPL_VAR $key>/$val/g; - } - } - #use Data::Dumper;print Dumper($target_event);#exit; - - #$schema->{event}=fix_fields($schema->{event}); - - my $schema={ - event => $target_event - }; - - return $schema; -} - -# get a event by an existing google id, e.g. to check if the event exists in target -sub get_event_by_reference_id{ - return undef; -} - -#try to find a event, matching to $event from google calendar -sub find_event{ - my $event=shift; - return undef; - -} - -#this is done before sync and allows to delete old events before adding new -sub pre_sync{ - my $event=shift; - - $debug=1; - return undef if(($target::settings->{date}->{'time_zone'} eq '') || ($event->{start} eq '' ) || ($event->{end} eq '')); - - #delete a span of dates - print "\n" if ($debug eq '1'); - - my $timeZone=$target::settings->{date}->{'time_zone'}; - - #get datetime in timezone - my $start = time::get_datetime($event->{start}, $timeZone); - my $end = time::get_datetime($event->{end}, $timeZone); - - main::print_info("search target for events from ".$start." to ".$end) if ($debug eq '1'); - - my $events=$target::cal->getEvents({ - #search datetime with same timezone - timeMin => $target::cal->getDateTime($start->datetime, $timeZone), - timeMax => $target::cal->getDateTime($end->datetime, $timeZone), - maxResults => 50, - singleEvents => 'true', - orderBy => 'startTime' - }); - - my $now=DateTime->now()->set_time_zone('UTC')->epoch(); - #print Dumper($now->datetime); - #exit; - - for my $event(@{$events->{items}}){ - main::print_info("delete\t$event->{start}->{dateTime}\t".$event->{summary}) if ($debug eq '1'); - #my $updated = $target::cal->getDateTime($event->{updated},'UTC')->epoch(); - #my $delta = $now-$updated; - #print $delta." seconds old\n"; - $target::cal->deleteEvent($event->{id}) - }; - #exit; -} - - -# insert a new event -sub insert_event{ - my $event=shift; - my $entity=$event->{event}; - - $entity->{'html_content'}=markup::creole_to_html($entity->{'content'}); - - my $timeZone = $target::settings->{date}->{'time_zone'}; - #print Dumper($timeZone); - #print Dumper($entity); - my $start = $target::cal->getDateTime($entity->{start}, $timeZone); - my $end = $target::cal->getDateTime($entity->{end}, $timeZone); - print "\n" if ($debug eq '1'); - #exit; - main::print_info("insert event\t$start\t$entity->{title}") if ($debug eq '1'); - my $entry = { - start => $start, - end => $end, - summary => $entity->{title}, - description => $entity->{content}, - location => $entity->{location}, - transparency => 'transparent', - status => 'confirmed' - }; - - my $result=$target::cal->insertEvent($entry); - my $id=$result->{id}; - - #exit; -} - -sub loadFile{ - my $filename=shift; - my $content=''; - - open my $file, '<', $filename || die("cannot load $filename"); - while(<$file>){ - $content.=$_; - } - close $file; - return $content; -} - -# update an existing event -sub update_event{ - return; -} -### end of interface implementation ### - - -sub print_event{ - my $header=shift; - my $event=shift; - - if ($header eq'google'){ - print "\n===== $header ====="; - }else{ - print "$header\n" if $header ne ''; - } -# print qq!$event->{start} $event->{program} : $event->{series_name} - $event->{title}!."\n"; - #content: >$event->{content}< -}; - -sub delete_event{ - return; - -} - -sub fix_fields{ - my $event=shift; - #lower case for upper case titles longer than 4 characters - for my $attr qw(program series_name title){ - my $val=$event->{$attr}; - my $c=0; - while ($val=~/\b([A-Z]{5,99})\b/ && $c<10){ - my $word=$1; - my $lower=lc $word; - $lower=~s/^([a-z])/\u$1/gi; - $val=~s/$word/$lower/g; - $c++; - } - if ($event->{$attr} ne $val){ - $event->{$attr}=$val; -# print Dumper($event->{$attr}).'<>'.Dumper($val)."\n" ; - } - } - - for my $attr qw(program series_name title excerpt content ){ - my $val=$event->{$attr}; - $val=~s/^\s*(.*?)\s*$/$1/g; - $val=~s/^[ \t]/ /g; - if ($event->{$attr} ne $val){ - $event->{$attr}=$val; -# print Dumper($event->{$attr}).'<>'.Dumper($val)."\n" ; - } - } - return $event; -} - -sub clean_up{ - return; -} - -1; diff --git a/tools/sync_cms/lib/target/playlist_csv.pl b/tools/sync_cms/lib/target/playlist_csv.pl deleted file mode 100644 index 2456688..0000000 --- a/tools/sync_cms/lib/target/playlist_csv.pl +++ /dev/null @@ -1,195 +0,0 @@ -package target; -use Data::Dumper; -use time; -use warnings; -use strict; - -my $settings={}; -my $cal = undef; - -sub init{ - $target::settings=shift; - my $access=$target::settings->{access}; - $cal = []; -} - -#map event schema to target schema -sub map_to_schema{ - my $event=shift; - #clone event - my $target_event={}; - for my $key (keys %{$event}){ - $target_event->{$key}=$event->{$key}; - } - - $event->{recurrence}->{number}=0 unless (defined $event->{recurrence} || defined $event->{recurrence}->{number}); - $target_event->{reference}.='['.$event->{recurrence}->{number}.']' if ($event->{recurrence}->{number}>0); - $target_event->{recurrence} => $event->{recurrence}->{number}; - $target_event->{rating} => 0; - $target_event->{visibility} => 0; -# $target_event->{transparency} => $event->{transparency}; - - #set project by project's date range - for my $project_name (keys %{$target::settings->{projects}}){ - my $project=$target::settings->{projects}->{$project_name}; - my $start=substr($event->{start},0,10); - if ($start ge $project->{start_date} && $start le $project->{end_date}){ - $target_event->{project}=$project->{name}; - } - } - - #override settings by target map filter - for my $key (keys %{$target::settings->{mapping}}){ - $target_event->{$key}=$target::settings->{mapping}->{$key}; - } - - #resolve variables set in mapped values - for my $mkey (keys %{$target::settings->{mapping}}){ - my $mval=$target_event->{$mkey}; - for my $key (keys %{$target_event}){ - my $val=$target_event->{$key}; - $val=$event->{$key} if($mkey eq $key); - $target_event->{$mkey}=~s/<TMPL_VAR $key>/$val/g; - } - } - - my $schema={ - event => $target_event - }; - - return $schema; -} - -# get a event by an existing reference id, e.g. to check if the event exists in target -sub get_event_by_reference_id{ - my $event_id=shift; - my $event={}; - return undef; -} - -#try to find a event -sub find_event{ - my $event=shift; - return undef; -} - -# insert a new event -sub insert_event{ - my $event=shift; - my $entity=$event->{event}; - - my $time_zone =$target::settings->{date}->{'time_zone'}; - my $start =time::get_datetime($entity->{start},$time_zone); - my $end =time::get_datetime($entity->{end},$time_zone); - print "\n" if ($main::debug eq '1'); - - main::print_info("insert event") if ($main::debug eq '1'); - push @$cal,{ - start => $start, - end => $end, - title => $entity->{title} - } - #exit; -} - - -# update an existing event -sub update_event{ - my $event=shift; - my $entity=shift; -} -### end of interface implementation ### - - -sub print_event{ - my $header=shift; - my $event=shift; - - if ($header eq'google'){ - print "\n===== $header ====="; - }else{ - print "$header\n" if $header ne ''; - } -# print qq!$event->{start} $event->{program} : $event->{series_name} - $event->{title}!."\n"; - #content: >$event->{content}< -}; - -sub delete_event{ - my $event_id=shift; - -} - -sub fix_fields{ - my $event=shift; - - for my $attr qw(title){ - my $val=$event->{$attr}; - $val=~s/^\s*(.*?)\s*$/$1/g; - $val=~s/^[ \t]/ /g; - if ($event->{$attr} ne $val){ - $event->{$attr}=$val; -# print Dumper($event->{$attr}).'<>'.Dumper($val)."\n" ; - } - } - return $event; -} - -sub pre_sync{ -} - -sub clean_up{ - my $content=''; - - my @cal=sort {$a->{start} cmp $b->{end}} @$cal; - my @cal2=(); - #print Dumper(\@cal); - #fill in default - if (defined $target::settings->{date}->{default_entry}){ - my $from=$main::from; - if ($from=~/^\d\d\d\d\-\d\d\-\d\dT\d\d$/){ - $from.=':00'; - } - my $till=$main::till; - if ($till=~/^\d\d\d\d\-\d\d\-\d\dT\d\d$/){ - $till.=':59'; - } - - my $default=$target::settings->{date}->{default_entry}; - if ($cal[0]->{start} gt $from){ - unshift @cal,{ - start => $from, - end => $cal[0]->{start}, - title => $default - } - } - if ($cal[-1]->{end} lt $till){ - push @cal,{ - start => $cal[-1]->{end}, - end => $till, - title => $default - } - } - my $old_event={end=>$from}; - for my $event (@cal){ - if ($event->{start} gt $old_event->{end}){ - push @cal2,{ - start => $old_event->{end}, - end => $event->{start}, - title => $default - } - } - push @cal2,$event; - $old_event=$event; - - } - } - - - for my $event(@cal2){ - $content.= $event->{start}.";\t".$event->{end}.";\t".$event->{title}."\n"; - } - log::save_file($target::settings->{access}->{file},$content); - return; -} - -1; diff --git a/tools/sync_cms/run_jobs.pl b/tools/sync_cms/run_jobs.pl new file mode 100755 index 0000000..b61df03 --- /dev/null +++ b/tools/sync_cms/run_jobs.pl @@ -0,0 +1,81 @@ +#! /usr/bin/perl + +use strict; +use warnings; + +use Data::Dumper; +use FindBin; +use lib "$FindBin::Bin/lib"; +use lib "$FindBin::Bin/../calcms"; + +use Common ( 'info', 'error' ); + +use config(); +use time(); +use log(); + +$| = 1; + +sub runJobs { + my $jobs = shift; + my $startDir = shift; + my $logDir = shift; + + for my $job (@$jobs) { + + my $startFile = $startDir . '/' . $job->{name} . '.start.txt'; + my $startAge = Common::getModifiedAt($startFile); + next if $startAge == 0; + + my $logFile = $logDir . '/' . $job->{name} . '.log'; + my $logAge = Common::getModifiedAt($logFile); + next if $startAge < $logAge; + + # read parameters form start file + my $content = log::load_file($startFile); + + #execute command + my $command = $job->{command} . ' 2>&1 > ' . $logFile; + my ( $exitCode, $result ) = Common::execute($command); + error "exitCode=$exitCode on $command" if $exitCode != 0; + } +} + +sub check() { + my $configFile = shift @ARGV; + error qq{cannot read $configFile "$configFile"} unless -e $configFile; + + my $config = config::get($configFile); + + my $startDir = $config->{start_dir} || ''; + error 'missing configuration of jobs/start_dir!' if $startDir eq ''; + error "job dir does not exist '$startDir'" unless -e $startDir; + error "cannot read from job dir '$startDir'. Please check permissions!" unless -w $startDir; + + my $logDir = $config->{log_dir} || ''; + error 'missing configuration of jobs/log_dir' if $logDir eq ''; + error "job log dir does not exist '$logDir'" unless -e $logDir; + error "cannot read from job log dir '$logDir'. Please check permissions!" unless -r $logDir; + error "cannot write to job log dir '$logDir'. Please check permissions!" unless -w $logDir; + + my $jobs = $config->{job}; + error "no jobs defined!" if scalar @$jobs == 0; + + return ( $jobs, $startDir, $logDir ); +} + +sub main() { + + info "INIT\t" . time::time_to_datetime(); + Common::checkSingleInstance(); + my ( $jobs, $startDir, $logDir ) = check(); + + #exit after a at most 10 minute timeout in case of hanging process + local $SIG{ALRM} = sub { die "ERROR: exit due to synchronization hangs\n" }; + alarm 10 * 60; + + runJobs( $jobs, $startDir, $logDir ); + info "DONE\t" . time::time_to_datetime(); +} + +main(); diff --git a/tools/sync_cms/sync_cms.pl b/tools/sync_cms/sync_cms.pl index 981a025..a5fa3aa 100755 --- a/tools/sync_cms/sync_cms.pl +++ b/tools/sync_cms/sync_cms.pl @@ -1,438 +1,236 @@ #!/usr/bin/perl -BEGIN{ - my $dir=''; - $ENV{SCRIPT_FILENAME}||'' if ($dir eq''); - $dir=~s/(.*\/)[^\/]+/$1/ if ($dir ne ''); - $dir=$ENV{PWD} if ($dir eq''); - $dir=`pwd` if ($dir eq''); - - #add calcms libs - unshift(@INC,$dir.'/../calcms/'); -} +use strict; +use warnings; use Data::Dumper; use Getopt::Long; use Config::General; -use time; use DateTime; use DateTime::Duration; -use strict; -use warnings; +use IO::Socket::INET; +use Fcntl ':flock'; -check_running_processes(); +use FindBin; +use lib "$FindBin::Bin/lib"; +use lib "$FindBin::Bin/../../calcms"; -my $read_mode=''; -my $update_mode=''; -my $all_events=''; -my $modified_events=''; -my $source_config_file=''; -my $target_config_file=''; -my $block_number=0; -my $block_size=2000; -our $from=''; -our $till=''; -my $read_only=0; -our $output_type='text'; -our $debug=0; +use Common ( 'info', 'error' ); +use GoogleCalendar; +use CalcmsEvents; -GetOptions( - "read" => \$read_mode, - "update" => \$update_mode, - "all" => \$all_events, - "modified" => \$modified_events, - "from=s" => \$from, - "till=s" => \$till, - "source=s" => \$source_config_file, - "target=s" => \$target_config_file, - "block_number:i" => \$block_number, - "block_size:i" => \$block_size, - "output_type=s" => \$output_type, -); - -$|=1; +Common::checkSingleInstance(); BEGIN { - our $utf8dbi=1; - $ENV{LANG}="en_US.UTF-8"; + $ENV{LANG} = "en_US.UTF-8"; } +$| = 1; + +my $sourceConfigFile = ''; +my $targetConfigFile = ''; +my $debug = 1; + +my $from = undef; +my $till = undef; +GetOptions( + "from=s" => \$from, + "till=s" => \$till, + "source=s" => \$sourceConfigFile, + "target=s" => \$targetConfigFile, +); + #source and taget settings are loaded from config files -our $settings={ -}; +my $settings = {}; -#user interface -our $ask_before_insert=0; -our $ask_before_update=0; - -# end of configuration - -if ($update_mode){ - $db::write=1; -# print_info("enter update mode"); -}elsif($read_mode){ - #default - $db::write=0; -# print_info("enter read-only mode"); -}else{ - print_error("set parameter >read< or >update<"); -} - -unless ($modified_events || $all_events || $from || $till){ - print_error("set one of folling parameters: --modified, --from, --till"); -} +error "set one of folling parameters: --from, --till" unless $from || $till; init(); sync(); -print_info("$0 done."); +info "$0 done."; exit 0; #sync all events, splitting multi-day-requests into multiple 1-day-requests to avoid large result sets -sub sync{ - #prepare target - print_info("$0 inited"); - print_info("last update: $settings->{source}->{last_update}"); +sub sync { + my $timeZone = CalcmsEvents::get('date')->{time_zone}; + my $from = CalcmsEvents::get('start_min'); + my $till = CalcmsEvents::get('start_max'); - if (my $days=source::split_request()){ - #set 1-day start-min and start-max parameters, requires --from and --till values - for my $date (@$days){ - for my $key(keys %$date){ - $settings->{source}->{$key}=$date->{$key}; - } - #print "\nrequest ".$settings->{source}->{"start_min"}." to ".$settings->{source}->{"start_max"}."\n"; - sync_timespan(); - } - }else{ - #update without time span (e.g. --modified) - sync_timespan(); - } + info "sync from $from till $till at $timeZone"; - print_info("\nclean up old database entries..."); - target::clean_up(); + #prepare target + info "last update: " . ( CalcmsEvents::get('last_update') || '' ); - print_info("\nset last-update time: $settings->{event}->{update_start}"); - set_last_update_time($source_config_file,$target_config_file,$settings->{event}->{update_start}); + if ( my $days = CalcmsEvents::splitRequest( $from, $till, $timeZone ) ) { + for my $date (@$days) { + syncTimespan( $date->{from}, $date->{till} ); + } + } else { + syncTimespan( $from, $till ); + } + + info "\nset last-update time: $settings->{event}->{update_start}"; + setLastUpdateTime( $sourceConfigFile, $targetConfigFile, $settings->{event}->{update_start} ); } #sync all events of a given source timespan -sub sync_timespan{ - #get a list of all days and their events - #print Dumper($settings->{source}); - my $source_events=source::get_events($settings->{source},$settings->{target}); - my @dates=(keys %$source_events); +sub syncTimespan { + my $from = shift; + my $till = shift; - #print "2\n"; - if (@dates==0){ - my $more=''; - if ((defined $settings->{source}->{block_number}) && ($settings->{source}->{block_number} ne '0')){ - $more='more '; - }elsif ($modified_events){ - $more.='modified '; - } - print_info("\n".'no '.$more."entries found."); - }else{ - print "<table>" if ($output_type eq 'html'); - #sort lists of date and time (same time events should be preserved) - for my $date(sort {$a cmp $b} @dates){ -# for my $date(@dates){ -# print "\n$date:\n"; - sync_events($source_events->{$date}, $settings); - } - print "</table>" if ($output_type eq 'html'); - } + #get a list of all days and their events + my $sourceEvents = CalcmsEvents::getEvents( $from, $till ); + + my @dates = keys %$sourceEvents; + if ( scalar @dates == 0 ) { + info "\nno entries found."; + return; + } + + #sort lists of date and time (same time events should be preserved) + for my $date ( sort { $a cmp $b } @dates ) { + syncEvents( $sourceEvents->{$date} ); + } } #syncronize a list of source events to target events -sub sync_events{ - my $source_events=shift; - my $settings=shift; +sub syncEvents($) { + my $sourceEvents = shift; -# my $source_settings =$settings->{source}; -# my $target_settings =$settings->{target}; - my $event_settings =$settings->{event}; + my @sourceEvents = sort { $a->{calcms_start} cmp $b->{calcms_start} } @$sourceEvents; + $sourceEvents = \@sourceEvents; + my $start = $sourceEvents->[0]->{start}; + my $end = $sourceEvents->[-1]->{end}; - my $c=0; - $c=$source::settings->{start_index}+0 if (defined $source::settings->{start_index}); - -# print "<events>\n"; - print html_table_header() if ($output_type eq 'html'); - #order processing by start time (TODO: order by last-modified date) - for my $event (sort{$a->{calcms_start} cmp $b->{calcms_start}} @$source_events){ - target::pre_sync({ - start =>$source_events->[0]->{start}, - end =>$source_events->[-1]->{end} - }); + my $targetEvents = GoogleCalendar::getEvents( + { + start => $start, + end => $end + } + ); + $targetEvents = $targetEvents->{items}; + info "google:" . scalar(@$targetEvents) . " vs " . scalar(@$sourceEvents); - print "<tr><td>"if ($output_type eq 'html'); + # mark all known target events + my $targetEventsByKey = {}; + for my $event (@$targetEvents) { + #print Dumper($event); + next if $event->{status} eq 'canceled'; + my $key = getGoogleEventToString($event); + $targetEventsByKey->{$key} = $event; + } - #read event - $event=source::get_event_attributes($event); + # mark all knwon source events + my $sourceEventsByKey = {}; + for my $event (@$sourceEvents) { + $event = CalcmsEvents::mapToSchema($event); + $event = GoogleCalendar::mapToSchema($event); + my $key = getCalcmsEventToString($event); + $sourceEventsByKey->{$key} = $event; + } - #convert to calcms schema - $event=source::map_to_schema($event); + # delete target entries without matching source entries + for my $key ( keys %$targetEventsByKey ) { + next if defined $sourceEventsByKey->{$key}; + my $event = $targetEventsByKey->{$key}; + info "delete $key "; + print Dumper($event); + GoogleCalendar::deleteEvent($event); + } - #map event to target schema - $event=target::map_to_schema($event); - - #deprecated: override defined attributes by configuration - if ((defined $source::settings->{override}) && (ref($source::settings->{override})eq 'HASH')){ - for my $key (keys %{$source::settings->{override}}){ - my $value=$source::settings->{override}->{$key}; - if ($source::settings->{override} ne ''){ - print_info("override '$key'='$value'"); - $event->{event}->{$key}=$value; - } - } - } - - if ($output_type eq'html'){ - print_event_html("[".($c+1)."]",$event); - }else{ - print_event_text("[".($c+1)."]",$event); - } - - if ($event->{event}->{start} eq '' || $event->{event}->{end} eq ''){ - print ('WARNING: Cannot read start or end of event'); - print "\n"; - }else{ -# print Dumper($event); - sync_event($event); - } - - # last; - $event=undef; - $c++; - print "</td></tr>"if ($output_type eq 'html'); - } -# print "\n</events>\n"; + # insert source entries without matching target entries + for my $key ( keys %$sourceEventsByKey ) { + if ( defined $targetEventsByKey->{$key} ) { + info "$key is up to date"; + next; + } + my $event = $sourceEventsByKey->{$key}; + info "insert $key"; + GoogleCalendar::insertEvent($event); + } } -#syncronize a single source event with target -sub sync_event{ - my $event=shift; +sub getGoogleEventToString { + my $event = shift; + my $result = "\n"; + $result .= "start: " . substr( $event->{start}->{dateTime}, 0, 19 ) . "\n"; + $result .= "end : " . substr( $event->{end}->{dateTime}, 0, 19 ) . "\n"; + $result .= "title: $event->{summary}\n"; + $result .= "desc : $event->{description}\n"; + return $result; +} - #look if target_event exists by reference id incl. recurrence counter - #print Dumper($event); - my $target_event=target::get_event_by_reference_id($event->{event}->{reference}); - - #if target_event exists - if (defined $target_event){ - #delete canceled events - if ($event->{event}->{status}eq'canceled'){ - print cell("delete canceled event:".qq{$target_event}); -# target::delete($target_event->{id}); - return; - } - - $event->{event_id}=$target_event->{id}; - - target::update_event($event,$target_event); - print cell("(ref. update)"); - - }else{ - #find by date, time and title - $target_event=target::find_event($event); - - if (defined $target_event){ - target::update_event($event,$target_event); - #print Dumper($event); - $event->{event_id}=$target_event->{id}; - print cell("(update)"); - }else{ - target::insert_event($event); - #print Dumper($event); - $target_event=target::get_event_by_reference_id($event->{event}->{reference}); - #print Dumper($target_event); - $event->{event_id}=$target_event->{id}; - print cell("(new)"); - } - } - print "\n"; - - for my $category (@{$event->{categories}}){ - target::assign_category_to_event($category,$event); - } - - for my $meta (@{$event->{meta}}){ - target::assign_meta_to_event($meta,$event); - } -# print Dumper($event); +sub getCalcmsEventToString { + my $event = shift; + my $result = "\n"; + $result .= "start: " . substr( $event->{event}->{start_datetime}, 0, 19 ) . "\n"; + $result .= "end : " . substr( $event->{event}->{end_datetime}, 0, 19 ) . "\n"; + $result .= "title: $event->{event}->{title}\n"; + $result .= "desc : $event->{event}->{content}\n"; + return $result; } #import requested source and target libs -sub init{ - binmode STDOUT, ":utf8"; +sub init { + binmode STDOUT, ":utf8"; - #require source config file - print_error ("missing source parameter!") unless ($source_config_file=~/\S/); - print_error ("source file: '$source_config_file' does not exist") unless (-e $source_config_file); - print_error ("cannot read source file: '$source_config_file'") unless (-r $source_config_file); - #$settings->{source}=require $source_config_file; - my $configuration = new Config::General($source_config_file); - $settings->{source}=$configuration->{DefaultConfig}->{source}; + { + #require target config file + error "missing target parameter!" unless $targetConfigFile =~ /\S/; + error "target file: '$targetConfigFile' does not exist" unless -e $targetConfigFile; + error "cannot read target file: '$targetConfigFile'" unless -r $targetConfigFile; + my $config = new Config::General($targetConfigFile); + $config = $config->{DefaultConfig}->{target}; + GoogleCalendar::init($config); - #require source import lib from config file - my $source_import_lib='lib/source/'.$settings->{source}->{type}.'.pl'; - print_error ("missing 'type' in 'source' config ") unless ($settings->{source}->{type}=~/\S/); - print_error ("cannot read source type import lib: '$source_import_lib'")unless (-r $source_import_lib); - require $source_import_lib; - - #require target config file - print_error ("missing target parameter!") unless ($target_config_file=~/\S/); - print_error ("target file: '$target_config_file' does not exist") unless (-e $target_config_file); - print_error ("cannot read target file: '$target_config_file'") unless (-r $target_config_file); - $configuration = new Config::General($target_config_file); - $settings->{target}=$configuration->{DefaultConfig}->{target}; - #$settings->{target}=require $target_config_file; - - #require target import lib from config file - my $target_import_lib='lib/target/'.$settings->{target}->{type}.'.pl'; - print_error ("missing 'type' in 'target' config ") unless ($settings->{target}->{type}=~/\S/); - print_error ("cannot read target type import lib: '$target_import_lib'")unless (-r $target_import_lib); - require $target_import_lib; - - #print Dumper($settings); - if ((defined $settings->{source}->{read_blocks}) && ($settings->{source}->{read_blocks}==1)){ - $settings->{source}->{block_number} =$block_number; - $settings->{source}->{block_size} =$block_size; - } - $settings->{source}->{last_update} =get_last_update_time($source_config_file,$target_config_file); - $settings->{source}->{modified_events} =$modified_events; - - if ($from=~/^\d\d\d\d\-\d\d\-\d\d$/){ - $from.='T00:00'; -# print "from:$from\t"; - } - - if ($till=~/^\d\d\d\d\-\d\d\-\d\d$/){ - $till.='T23:59'; -# print "till:$till\t"; - } - - if ($from=~/^([-+]?\d+$)/){ - my $days=$1; - my $duration=new DateTime::Duration(days=>$days); - $from=DateTime->today->add_duration($duration); -# print "from:$from\t"; - } - if ($till=~/^([-+]?\d+$)/){ - my $days=$1+1; - my $duration=new DateTime::Duration(days=>$days); - $till=DateTime->today->add_duration($duration); -# print "till:$till\t"; - - } - - $settings->{source}->{start_min} =$from if defined ($from); - $settings->{source}->{start_max} =$till if defined ($till); - - my $gmt_difference =0;#*=3600; - my $now =time(); - my $now_gmt =$now-$gmt_difference; - $now =time::time_to_datetime($now); - $now_gmt =time::time_to_datetime($now_gmt); - - $settings->{event}={ - update_start => time::time_to_datetime(time()), - modified_at => $now, - modified_at_gmt => $now_gmt - }; - - source::init($settings->{source}); - target::init($settings->{target}); - -} - -# print date/time, title and excerpt of an calendar event -# TODO: replace by output filter (text, html) -sub print_event_text{ - my $header=shift; - my $event=shift; - - my $s=$header; - $s=$s." "x (8-length($s)); - - my $start=$event->{event}->{start}||''; - $start=~s/T/ /g; - $start=~s/\:00$//g; - - if (defined $event->{event}->{program}){ - $s.="$start $event->{event}->{program}"; - $s=$s." "x (45-length($s)); } - if (defined $event->{event}->{series_name}){ - $s.=" : $event->{event}->{series_name}"; - $s=$s." "x (75-length($s)); + { + #require source config file + error "missing source parameter!" unless $sourceConfigFile =~ /\S/; + error "source file: '$sourceConfigFile' does not exist" unless -e $sourceConfigFile; + error "cannot read source file: '$sourceConfigFile'" unless -r $sourceConfigFile; + my $config = new Config::General($sourceConfigFile); + $config = $config->{DefaultConfig}->{source}; + $config->{last_update} = getLastUpdateTime( $sourceConfigFile, $targetConfigFile ); + CalcmsEvents::init($config); } - if (defined $event->{event}->{title}){ - $s.=" - $event->{event}->{title}"; - $s=$s." "x (110-length($s)); + $from .= 'T00:00' if $from =~ /^\d\d\d\d\-\d\d\-\d\d$/; + $till .= 'T23:59' if $till =~ /^\d\d\d\d\-\d\d\-\d\d$/; + + if ( $from =~ /^([-+]?\d+$)/ ) { + my $days = $1; + my $duration = new DateTime::Duration( days => $days ); + $from = DateTime->today->add_duration($duration); } - if ($event->{categories}){ - $s.= "(".join(", ",(@{$event->{categories}})).")"; - } - $s=$s." "x (135-length($s)); + if ( $till =~ /^([-+]?\d+$)/ ) { + my $days = $1 + 1; + my $duration = new DateTime::Duration( days => $days ); + $till = DateTime->today->add_duration($duration); + } - my $status=$event->{event}->{status}; - $s.=$status.' ' if (defined $status); - $s=$s." "x (140-length($s)); + CalcmsEvents::set( 'start_min', $from ) if defined $from; + CalcmsEvents::set( 'start_max', $till ) if defined $till; - my $reference=$event->{event}->{reference}; - $s.=substr($reference,length($reference)-25) if (defined $reference); + my $now = time(); + $now = time::time_to_datetime($now); + $settings->{event} = { + update_start => time::time_to_datetime( time() ), + modified_at => $now, + }; - print $s; -} - -sub print_event_html{ - my $header=shift; - my $event=shift; - - #close error block - my $s='</td>'; - - my $start=$event->{event}->{start}||''; - $start=~s/T/ /g; - $start=~s/\:00$//g; - $s.=cell($start); - $s.=cell($event->{event}->{program}); - $s.=cell($event->{event}->{series_name}); - $s.=cell($event->{event}->{title}); - - if ($event->{categories}){ - $s.=cell( join(", " , ( @{$event->{categories}} ) ) ); - } - - my $status=$event->{event}->{status}; - $s.=cell($status) if (defined $status); - - my $reference=$event->{event}->{reference}; - $reference=substr($reference,length($reference)-25) if (defined $reference); - $s.=cell($reference); - - $s.="<td>"; - - print $s; -} - -sub cell{ - if ($output_type eq 'html'){ - return "<td>$_[0]</td>"; - }else{ - return "\t".$_[0]; - }; } #output usage on error or --help parameter -sub print_usage{ - print qq{ +sub usage { + print qq{ update all/modified events from source at target. -USAGE: sync_cms.pl [--read,--update] [--modified,--all] --source s --target t [--block_number b] [--block_size s] +USAGE: sync_cms.pl [--read,--update] [--modified,--all] --source s --target t on using --from and --till requests will be processed as multiple single-day-requests. @@ -440,128 +238,55 @@ parameters: --read show all events without updating database --update update target database with source events - --modified process only modified events. - --all' process all events - --source source configuration file --target target configuration file --from start of date range: datetime (YYYY-MM-DDTHH:MM::SS) or days from today (e.g. -1 for yesterday, +1 for tomorrow) --till end of date range: datetime (YYYY-MM-DDTHH:MM::SS) or days from today (e.g. -1 for yesterday, +1 for tomorrow) - --output_type log output format [text,html] - - --block_number which block is to be syncronized [0..n]. To split up processing into multiple blocks (for machines with small memory resources). - --block_size size of a block, default=20 events examples: update modified - perl sync_cms.pl --update --modified --source=config/source/program.cfg --target=config/target/calcms.cfg + perl sync_cms.pl --update --source=config/source/program.cfg --target=config/target/calcms.cfg update a given time range perl sync_cms.pl --update --all --from=2009-09-01T00:00:00 --till=2009-11-22T23:59:59 --source=config/source/program.cfg --target=config/target/calcms.cfg update from last 2 days until next 3 days - perl sync_cms.pl --update --all --from=-2 --till=+3 --source=config/source/program.cfg --target=config/target/calcms.cfg + perl sync_cms.pl --update --from=-2 --till=+3 --source=config/source/program.cfg --target=config/target/calcms.cfg }; - exit 1; -}; - -#default error handling -sub print_error{ - print "\nERROR: $_[0]\n" ; - print_usage(); + exit 1; } -sub print_info{ - my $message=shift; - if ($message=~/^\n/){ - $message=~s/^\n//g; - print "\n"; - } - if ($output_type eq 'html'){ - print "$message<br/>"; - }else{ - print "INFO:\t$message\n"; - } -} -sub html_table_header{ - return qq{ -<tr> - <th> </th> - <th>start date</th> - <th>project</th> - <th>series</th> - <th>title</th> - <th>category</th> - <th>status</th> - <th>id</th> - <th> </th> - <th>action</th> -</tr> - }; -}; - - #load last update time out of sync.data -sub get_last_update_time{ - my $source=shift; - my $target=shift; +sub getLastUpdateTime { + my $source = shift; + my $target = shift; - my $date=undef; - return undef unless(-r "sync.data"); - - open my $DATA, "<:utf8","sync.data" || die ('cannot read update timestamp'); - while (<$DATA>){ - my $line=$_; - if ($line=~/$source\s+\->\s+$target\s+:\s+(\d{4}\-\d{2}\-\d{2} \d{2}:\d{2}:\d{2})/){ - $date=$1; - last; - } - } - close $DATA; - return $date; + my $date = undef; + return undef unless -r "sync.data"; + my $content = Common::loadFile("sync.data"); + if ( $content =~ /$source\s+\->\s+$target\s+:\s+(\d{4}\-\d{2}\-\d{2} \d{2}:\d{2}:\d{2})/ ) { + $date = $1; + } + return $date; } #save last update time to sync.data -sub set_last_update_time{ - my $source =shift; - my $target =shift; - my $date =shift; +sub setLastUpdateTime { + my $source = shift; + my $target = shift; + my $date = shift; - my $data=''; - if (-r "sync.data"){ - open my $DATA, "<:utf8","sync.data"; - $data=join("\n",(<$DATA>)); - close $DATA; - } + my $data = ''; + if ( -r "sync.data" ) { + $data = Common::loadFile("sync.data"); + } - if ($data=~/$source\s+\->\s+$target\s+:\s+(\d{4}\-\d{2}\-\d{2} \d{2}:\d{2}:\d{2})/){ - $data=~s/($source\s+\->\s+$target\s+:)\s+\d{4}\-\d{2}\-\d{2} \d{2}:\d{2}:\d{2}/$1\t$date/gi; - }else{ - $data.="$source\t\->\t$target\t:\t$date\n"; - } + if ( $data =~ /$source\s+\->\s+$target\s+:\s+(\d{4}\-\d{2}\-\d{2} \d{2}:\d{2}:\d{2})/ ) { + $data =~ s/($source\s+\->\s+$target\s+:)\s+\d{4}\-\d{2}\-\d{2} \d{2}:\d{2}:\d{2}/$1\t$date/gi; + } else { + $data .= "$source\t\->\t$target\t:\t$date\n"; + } - $data=~s/[\r\n]+/\n/g; - - open my $DATA2, ">:utf8","sync.data" || die ('cannot write update timestamp'); - print $DATA2 $data; - close $DATA2; - -# print $data; + $data =~ s/[\r\n]+/\n/g; + Common::saveFile( "sync.data", $data ); } -#avoid to run more than one sync process in parallel -sub check_running_processes{ - my $cmd="ps -afex 2>/dev/null | grep sync_cms.pl | grep -v nice | grep -v grep "; - my $ps=`$cmd`; -# print "$ps"; - my @lines=(split(/\n/,$ps)); - if (@lines>1){ - print "ERROR: another ".@lines." synchronization processes 'sync_cms.pl' instances are running!".qq{ - -$cmd -$ps --> program will exit -}; - exit; - } - -} diff --git a/tools/sync_cms/sync_days.pl b/tools/sync_cms/sync_days.pl deleted file mode 100644 index 1f2ea48..0000000 --- a/tools/sync_cms/sync_days.pl +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/perl -I ../lib #-w - -BEGIN{ - my $dir=''; - $ENV{SCRIPT_FILENAME} if ($dir eq''); - $dir=~s/(.*\/)[^\/]+/$1/; - $dir=$ENV{PWD} if ($dir eq''); - $dir=`pwd` if ($dir eq''); - - #local perl installation libs - unshift(@INC,$dir.'/../../perl/lib/'); - - #calcms libs + configuration - unshift(@INC,$dir.'/../calcms/'); -} - -#use utf8; -use warnings "all"; -use strict; -use Data::Dumper; - -#use CGI; -#use HTML::Template; -use Date::Calc; -#use calendar; -#use time; -#use log; - -if(@ARGV<2){ - print qq{ERROR: $0 yyyy-mm-dd yyyy-mm-dd -syncronize from given start date to end date, day by day -}; - exit 1; -} - -my $start =$ARGV[0]; -my $end =$ARGV[1]; - -(my $start_year,my $start_month,my $start_day)=split(/\-/,$start); -my $last_day=Date::Calc::Days_in_Month($start_year,$start_month); -$start_day = 1 if ($start_day<1); -$start_day = $last_day if ($start_day gt $last_day); - -(my $end_year,my $end_month,my $end_day)=split(/\-/,$end); -$last_day=Date::Calc::Days_in_Month($end_year,$end_month); -$end_day = 1 if ($end_day<1); -$end_day = $last_day if ($end_day gt $last_day); - - - -for my $year($start_year..$end_year){ - my $m1=1; - my $m2=12; - $m1=$start_month if($year eq $start_year); - $m2=$end_month if($year eq $end_year); - - for my $month($m1..$m2){ - $month='0'.$month if (length($month)==1); - my $d1=1; - my $d2=Date::Calc::Days_in_Month($year,$month); - $d1=$start_day if($month eq $start_month); - $d2=$end_day if($month eq $end_month); - - for my $day($d1..$d2){ - $day='0'.$day if (length($day)==1); - my $date=join('-',($year,$month,$day)); - my $cmd="perl sync_cms.pl --update --all --source config/source/program.cfg --target config/target/calcms.cfg --from ".$date."T00:00:00 --till ".$date."T23:59:59"; - #print "$cmd\n"; - print `nice -n 10 $cmd`; - } - } - -} - diff --git a/tools/sync_cms/sync_jobs/calcms_to_google.sh b/tools/sync_cms/sync_jobs/calcms_to_google.sh new file mode 100755 index 0000000..70c0d40 --- /dev/null +++ b/tools/sync_cms/sync_jobs/calcms_to_google.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +from=$1 +till=$2 +project=$3 + +export LC_ALL="de_DE.utf8" +export LANGUAGE="de_DE.utf8" + +set -x +cd /home/radio/calcms/sync_cms +nice -n 10 perl sync_cms.pl --from=$from --till=$till --source=config/source/calcms_$project.cfg --target=config/target/88vier_$project.cfg 2>&1 + diff --git a/tools/sync_cms/sync_jobs/sync.sh b/tools/sync_cms/sync_jobs/sync.sh new file mode 100755 index 0000000..43b3cf0 --- /dev/null +++ b/tools/sync_cms/sync_jobs/sync.sh @@ -0,0 +1,7 @@ +#/bin/sh + +./sync_project.sh "$1" "$2" piradio +./sync_project.sh "$1" "$2" potsdam +./sync_project.sh "$1" "$2" ansage +./sync_project.sh "$1" "$2" collabo +./sync_project.sh "$1" "$2" frb diff --git a/tools/sync_cms/sync_jobs/update_ansage.sh b/tools/sync_cms/sync_jobs/update_ansage.sh new file mode 100755 index 0000000..fe37ceb --- /dev/null +++ b/tools/sync_cms/sync_jobs/update_ansage.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +file=/home/radio/piradio.de/agenda/admin/jobs/start/ansage_to_88vier.de.start.txt +touch $file +chown radio:www-data $file + diff --git a/tools/sync_cms/sync_jobs/update_colabo.sh b/tools/sync_cms/sync_jobs/update_colabo.sh new file mode 100755 index 0000000..904b5e1 --- /dev/null +++ b/tools/sync_cms/sync_jobs/update_colabo.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +file=/home/radio/piradio.de/agenda/admin/jobs/start/colabo_to_88vier.de.start.txt +touch $file +chown radio:www-data $file + diff --git a/tools/sync_cms/sync_jobs/update_frb.sh b/tools/sync_cms/sync_jobs/update_frb.sh new file mode 100755 index 0000000..0139861 --- /dev/null +++ b/tools/sync_cms/sync_jobs/update_frb.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +file=/home/radio/piradio.de/agenda/admin/jobs/start/frb_to_88vier.de.start.txt +touch $file +chown radio:www-data $file + diff --git a/tools/sync_cms/sync_jobs/update_piradio.sh b/tools/sync_cms/sync_jobs/update_piradio.sh new file mode 100755 index 0000000..ad7c170 --- /dev/null +++ b/tools/sync_cms/sync_jobs/update_piradio.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +file=/home/radio/piradio.de/agenda/admin/jobs/start/piradio_to_88vier.de.start.txt +touch $file +chown radio:www-data $file + diff --git a/tools/sync_cms/sync_jobs/update_potsdam.sh b/tools/sync_cms/sync_jobs/update_potsdam.sh new file mode 100755 index 0000000..86d30d8 --- /dev/null +++ b/tools/sync_cms/sync_jobs/update_potsdam.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +file=/home/radio/piradio.de/agenda/admin/jobs/start/potsdam_to_88vier.de.start.txt +touch $file +chown radio:www-data $file + diff --git a/tools/sync_cms/time_gate.pl b/tools/sync_cms/time_gate.pl deleted file mode 100644 index b83bc2b..0000000 --- a/tools/sync_cms/time_gate.pl +++ /dev/null @@ -1,487 +0,0 @@ -#!/usr/bin/perl -I ../lib #-w - -BEGIN{ - my $dir=''; - $ENV{SCRIPT_FILENAME}||'' if ($dir eq''); - $dir=~s/(.*\/)[^\/]+/$1/ if ($dir ne ''); - $dir=$ENV{PWD} if ($dir eq''); - $dir=`pwd` if ($dir eq''); - - #local perl installation libs - unshift(@INC,$dir.'/../../perl/lib/'); - - #calcms libs + configuration - unshift(@INC,$dir.'/../calcms/'); -} - -#use utf8; -use Data::Dumper; -#require 'time.pl'; -use Getopt::Long; -use time; -use DateTime; -use DateTime::Duration; -use strict; -use warnings; - -check_running_processes(); - - -my $read_mode=''; -my $update_mode=''; -my $all_events=''; -my $modified_events=''; -my $source_config_file=''; -my $target_config_file=''; -my $block_number=0; -my $block_size=2000; -my $from=''; -my $till=''; -my $read_only=0; -my $project=''; - -GetOptions( - "read" => \$read_mode, - "update" => \$update_mode, - "all" => \$all_events, - "modified" => \$modified_events, - "from=s" => \$from, - "till=s" => \$till, - "source=s" => \$source_config_file, - "target=s" => \$target_config_file, - "project=s" => \$project, - "block_number:i" => \$block_number, - "block_size:i" => \$block_size -); - -$|=1; - -BEGIN { - our $utf8dbi=1; - $ENV{LANG}="en_US.UTF-8"; -# print Dumper(\%ENV); -} - -#source and taget settings are loaded from config files -our $settings={ -}; - -#user interface -our $ask_before_insert=0; -our $ask_before_update=0; - -# end of configuration - -if ($update_mode){ - $db::write=1; -# print "enter update mode\n"; -}elsif($read_mode){ - #default - $db::write=0; -# print "enter read-only mode\n"; -}else{ - print_error("set parameter >read< or >update<"); -} - -unless ($modified_events || $all_events || $from || $till){ - print_error("set one of folling parameters: --modified, --from, --till"); -} - -init(); -my $project_target=$source::settings->{sources}->{$project}; -unless (defined $project){ - print_error("missing parameter --project") unless(defined $project_target); - print_error("cant find project configuration '$project_target'") unless (-f $project_target); - print_error("cant read project configuration '$project_target'") unless (-r $project_target); -} - -my $events=[]; -print "TIME_GATE: READ ALL CALENDARS\n"; -sync(); -$events=compress_events($events); -my $c=0; -if ($project eq ''){ - for my $event (@$events){ - print_event("[".($c+1)."]",$event); - print "\n"; - $c++; - } -}else{ - my $source=$source::settings->{sources}->{$project}; - my $target='config/target/calcms.cfg'; - - for my $event (@$events){ - my $from=$event->{start}; - #print Dumper($event->{end}); - #remove a second - my $till=source::get_datetime($event->{end}, $source::settings->{date}->{time_zone})->add(seconds=>-1)->datetime(); - print_event("STATION TIMESLOT [".($c+1)."]\t",$event); - print "\n"; - $c++; - my $command="perl sync_cms.pl --update --all --from=$from --till=$till --source $source --target $target "; - print_info($command); - print `$command`; - #exit; - } - -} -print "\ndone.\n"; -exit 0; - -sub compress_events{ - my $events=shift; - - my @results=(); - my $old_event={end=>'', start=>'', title=>''}; - for my $event(sort {$a->{start} gt $b->{start}} @$events){ -# print "$event->{start}\t$event->{end}\t$event->{title}\n"; - if ( -# (defined $event) && (defined $event->{start}) && (defined $event->{end}) && (defined $event->{title}) - ( #station continues - ($event->{start} eq $old_event->{end}) - || (#multiple entries for same event - ($event->{start} ge $old_event->{start}) - && ($event->{end} eq $old_event->{end}) - ) - ) - && ($event->{title} eq $old_event->{title}) - && (@results>0) - ){ - $results[-1]->{end}=$event->{end}; -# print @results."\tmerge \n"; - }else{ - push @results,{ - start => $event->{start}, - end => $event->{end}, - title => $event->{title}, - }; -# print @results."\tinsert \n"; - } - $old_event=$results[-1]; - } -# print Dumper(\@results); - - return \@results; -} - -#sync all events, splitting multi-day-requests into multiple 1-day-requests to avoid large result sets -sub sync{ - #prepare target - target::init($settings->{target}); - print_info("last update: $settings->{source}->{last_update}"); - - if (my $days=source::split_request($settings->{source})){ - #set 1-day start-min and start-max parameters, requires --from and --till values - for my $date (@$days){ - for my $key(keys %$date){ - $settings->{source}->{$key}=$date->{$key}; - } - print "\nrequest ".$settings->{source}->{"start_min"}." to ".$settings->{source}->{"start_max"}."\n"; - sync_timespan(); - } - }else{ - #update without time span (e.g. --modified) - sync_timespan(); - } - - print_info("\nset last-update time: $settings->{event}->{update_start}"); - set_last_update_time($source_config_file,$target_config_file,$settings->{event}->{update_start}); -} - -#sync all events of a given source timespan -sub sync_timespan{ - #get a list of all days and their events - #print Dumper($settings->{source}); - my $source_events=source::get_events($settings->{source},$settings->{target}); - #print Dumper($source_events); - my @dates=(keys %$source_events); - - if (@dates==0){ - my $more=''; - if ((defined $settings->{source}->{block_number}) && ($settings->{source}->{block_number} ne '0')){ - $more='more '; - }elsif ($modified_events){ - $more.='modified '; - } - print_info("\n".'no '.$more."entries found."); - }else{ - #sort lists of date and time (same time events should be preserved) - for my $date(sort {$a cmp $b} @dates){ -# for my $date(@dates){ -# print "\n$date:\n"; - sync_events($source_events->{$date}, $settings); - } - } - -} - -#syncronize a list of source events to target events -sub sync_events{ - my $source_events=shift; - my $settings=shift; - - my $c=0; - $c=$source::settings->{start_index}+0 if (defined $source::settings->{start_index}); - -# print "<events>\n"; - - #order processing by start time (TODO: order by last-modified date) - for my $event (sort{$a->{calcms_start} cmp $b->{calcms_start}} @$source_events){ - #read event attributes - $event=source::get_event_attributes($event); - - $event->{title}=~s/\s//g; - - $event->{event}={ - title => $event->{title}, - start => $event->{start}, - end => $event->{end}, - status => $event->{status}, - }; - -# print "\n"; - #print_event("[".($c+1)."]",$event); - #print "\n".$event->{event}->{title}." ".$project."\n"; - - if ($event->{event}->{status}eq'canceled'){ - print "canceled event:".qq{$event}; - }elsif ($event->{event}->{start} eq ''){ - print ('WARNING: Cannot read start of event'."\n"); - }elsif ($event->{event}->{end} eq ''){ - print ('WARNING: Cannot read start of end'."\n"); - }elsif ($event->{event}->{title} eq ''){ - print ('WARNING: Cannot read start of title'."\n"); - }elsif ($project ne ''){ - if ($event->{event}->{title} eq $project){ - push @$events, $event->{event}; - } - }else{ - push @$events, $event->{event}; - } - $event=undef; - $c++; - } -} - - -#import requested source and target libs -sub init{ - binmode STDOUT, ":utf8"; - - #require source config file - print_error ("missing source parameter!") unless ($source_config_file=~/\S/); - print_error ("source file: '$source_config_file' does not exist") unless (-e $source_config_file); - print_error ("cannot read source file: '$source_config_file'") unless (-r $source_config_file); - #$settings->{source}=require $source_config_file; - my $configuration = new Config::General($source_config_file); - $settings->{source}=$configuration->{DefaultConfig}->{source}; - - #require source import lib from config file - my $source_import_lib='lib/source/'.$settings->{source}->{type}.'.pl'; - print_error ("missing 'type' in 'source' config ") unless ($settings->{source}->{type}=~/\S/); - print_error ("cannot read source type import lib: '$source_import_lib'")unless (-r $source_import_lib); - require $source_import_lib; - - #require target config file - print_error ("missing target parameter!") unless ($target_config_file=~/\S/); - print_error ("target file: '$target_config_file' does not exist") unless (-e $target_config_file); - print_error ("cannot read target file: '$target_config_file'") unless (-r $target_config_file); - #$settings->{target}=require $target_config_file; - $configuration = new Config::General($target_config_file); - $settings->{target}=$configuration->{DefaultConfig}->{target}; - - #require target import lib from config file - my $target_import_lib='lib/target/'.$settings->{target}->{type}.'.pl'; - print_error ("missing 'type' in 'target' config ") unless ($settings->{target}->{type}=~/\S/); - print_error ("cannot read target type import lib: '$target_import_lib'")unless (-r $target_import_lib); - require $target_import_lib; - - #print Dumper($settings); - if ((defined $settings->{source}->{read_blocks}) && ($settings->{source}->{read_blocks}==1)){ - $settings->{source}->{block_number} =$block_number; - $settings->{source}->{block_size} =$block_size; - } - $settings->{source}->{last_update} =get_last_update_time($source_config_file,$target_config_file); - $settings->{source}->{modified_events} =$modified_events; - - if ($from=~/^\d\d\d\d\-\d\d\-\d\d$/){ - $from.='T00:00'; - } - - if ($till=~/^\d\d\d\d\-\d\d\-\d\d$/){ - $till.='T23:59'; - } - - if ($from=~/^([-+]?\d+$)/){ - my $days=$1; - my $duration=new DateTime::Duration(days=>$days); - $from=DateTime->today->add_duration($duration); -# print "from:$from\t"; - } - if ($till=~/^([-+]?\d+$)/){ - my $days=$1+1; - my $duration=new DateTime::Duration(days=>$days); - $till=DateTime->today->add_duration($duration); -# print "till:$till\t"; - - } - - - $settings->{source}->{start_min} =$from if defined ($from); - $settings->{source}->{start_max} =$till if defined ($till); - - my $gmt_difference =0;#*=3600; - my $now =time(); - my $now_gmt =$now-$gmt_difference; - $now =time::time_to_datetime($now); - $now_gmt =time::time_to_datetime($now_gmt); - - $settings->{event}={ - update_start => time::time_to_datetime(time()), - modified_at => $now, - modified_at_gmt => $now_gmt - }; - source::init($settings->{source}); - -} - -# print date/time, title and excerpt of an calendar event -# TODO: replace by output filter (text, html) -sub print_event{ - my $header=shift; - my $event=shift; - - my $s=$header; - $s=$s." "x (8-length($s)); - -# print Dumper($event); - my $start=$event->{start}||''; - $start=~s/T/ /g; - $start=~s/\:00$//g; - - my $end=$event->{end}||''; - $end=~s/T/ /g; - $end=~s/\:00$//g; - - $s.="$start\t$end\t'$event->{title}'"; - -# print Dumper($event->{event}); - print $s; -#excerpt: >$event->{excerpt}< -#content: >$event->{content}< -#content: >$event->{content}< - -} - -#output usage on error or --help parameter -sub print_usage{ - print qq{ -update all/modified events from source at target. - -USAGE: $0 [--read,--update] [--modified,--all] --source s --target t [--block_number b] [--block_size s] - -on using --from and --till requests will be processed as multiple single-day-requests. - -parameters: - --read show all events without updating database - --update update target database with source events - - --modified process only modified events. - --all' process all events - - --source source configuration file - --target target configuration file - - --from start of date range: datetime (YYYY-MM-DDTHH:MM::SS) or days from today (e.g. -1 for yesterday, +1 for tomorrow) - --till end of date range: datetime (YYYY-MM-DDTHH:MM::SS) or days from today (e.g. -1 for yesterday, +1 for tomorrow) - - --block_number which block is to be syncronized [0..n]. To split up processing into multiple blocks (for machines with small memory resources). - --block_size size of a block, default=20 events - -examples: - perl $0 --update --modified --source=config/source/einheit.cfg --target=config/target/calcms.cfg - perl $0 --update --all --from=2009-09-01T00:00:00 --till=2009-11-22T23:59:59 --source=config/source/einheit.cfg --target=config/target/calcms.cfg -}; - exit 1; -}; - -#load last update time out of sync.data -sub get_last_update_time{ - my $source=shift; - my $target=shift; - - my $date=undef; - return undef unless(-r "sync.data"); - - open my $DATA, "<:utf8","sync.data" || die ('cannot read update timestamp'); - while (<$DATA>){ - my $line=$_; - if ($line=~/$source\s+\->\s+$target\s+:\s+(\d{4}\-\d{2}\-\d{2} \d{2}:\d{2}:\d{2})/){ - $date=$1; - last; - } - } - close $DATA; - return $date; -} - -#save last update time to sync.data -sub set_last_update_time{ - my $source =shift; - my $target =shift; - my $date =shift; - - my $data=''; - if (-r "sync.data"){ - open my $DATA, "<:utf8","sync.data"; - $data=join("\n",(<$DATA>)); - close $DATA; - } - - if ($data=~/$source\s+\->\s+$target\s+:\s+(\d{4}\-\d{2}\-\d{2} \d{2}:\d{2}:\d{2})/){ - $data=~s/($source\s+\->\s+$target\s+:)\s+\d{4}\-\d{2}\-\d{2} \d{2}:\d{2}:\d{2}/$1\t$date/gi; - }else{ - $data.="$source\t\->\t$target\t:\t$date\n"; - } - - $data=~s/[\r\n]+/\n/g; - - open my $DATA2, ">:utf8","sync.data" || die ('cannot write update timestamp'); - print $DATA2 $data; - close $DATA2; - -# print $data; -} - -#default error handling -sub print_error{ - print "\nERROR:\t$_[0]\n" ; - print_usage(); -} - -sub print_info{ - my $message=shift; - if ($message=~/^\n/){ - $message=~s/^\n//g; - print "\n"; - } - print "INFO:\t$message\n"; -} - -#avoid to run more than one sync process simultaniously -sub check_running_processes{ - my $cmd="ps -afex 2>/dev/null | grep $0.pl | grep -v nice | grep -v grep "; - my $ps=`$cmd`; -# print "$ps"; - my @lines=(split(/\n/,$ps)); - if (@lines>1){ - print "ERROR:\tanother ".@lines." synchronization processes '$0.pl' instances are running!".qq{ - -$cmd -$ps --> program will exit -}; - exit; - } - -} diff --git a/tools/update_page.sh b/tools/update_page.sh index 525ff38..728eac3 100755 --- a/tools/update_page.sh +++ b/tools/update_page.sh @@ -1,28 +1,4 @@ #!/bin/sh perl -I /home/calcms/lib/calcms update_program.pl - -exit; - -##clear cache -##echo "cd /home/radio/radio/agenda/admin;perl clear_cache.cgi online=0" -#cd /home/radio/radio/agenda/admin -#perl clear_cache.cgi online=0 - -##get current layout -##cd /home/radio/calcms -##perl preload_agenda.pl read /home/radio/radio/agenda/index.html - -##cd /home/radio/calcms/ -##perl preload_agenda.pl replace /home/radio/radio/sites/default/files/programm.html; -##perl preload_agenda.pl replace /home/radio/radio/programm.html; -# -##update cache (important for night hours!) -##echo "cd /home/radio/radio/agenda;perl aggregate.cgi date=today 2>/dev/null > /home/radio/radio/agenda/programm.html " -#cd /home/radio/radio/agenda; #perl -I /home/radio/calcms/calcms aggregate.cgi date=today 2>/dev/null > /home/radio/radio/agenda/programm.html -# -#find /home/radio/radio/agenda/cache/ -type f -exec chmod 664 {} \; 2>/dev/null -#find /home/radio/radio/agenda/cache/ -type f -exec chgrp www-data {} \; 2>/dev/null -# - diff --git a/tools/update_program.pl b/tools/update_program.pl index 91927c0..cf390d4 100755 --- a/tools/update_program.pl +++ b/tools/update_program.pl @@ -7,7 +7,6 @@ use Data::Dumper; use Date::Calc; use config; use template; -use projects; my $perlPath='-I /home/calcms/lib/calcms'; my $configPath=$ARGV[0]||'/home/calcms/website/agenda/config/config.cgi'; @@ -19,19 +18,12 @@ clean_up_cache(); sub clean_up_cache{ my $base_dir =$config::config->{locations}->{base_dir}||''; - my $cache =$config::config->{cache}->{cache_dir}||''; - my $cache_dir=$base_dir.'/'.$cache.'/'; print_error("'base_dir' directory not configured! Please check config!") if($base_dir eq''); print_error("invalid 'base_dir' directory '$base_dir'! Please check config!") unless ($base_dir=~/[a-zA-Z]\/[a-zA-Z]/); print_error("'base_dir' directory '$base_dir' does not exist! Please check config!") unless (-e $base_dir); print_error("cannot read 'base_dir' directory '$base_dir'! Please check permissions!") unless (-r $base_dir); - print_error("'cache_dir' directory $cache_dir not configured! Please check config!") if ($cache_dir eq '/'); - print_error("invalid 'cache_dir' directory '$cache_dir'! Please check config!") unless ($cache_dir=~/[a-zA-Z]\/[a-zA-Z]/); - print_error("'cache_dir' directory '$cache_dir' does not exist! Please check filesystem!") unless (-e $cache_dir); - print_error("cannot write to 'cache_dir' directory '$cache_dir'! Please check filesystem!") unless (-w $cache_dir); - # update basic layout print_header("update basic layout"); @@ -44,14 +36,6 @@ sub clean_up_cache{ execute($cmd); } - # clear all files from cache - print_header("clear cache"); - - for my $controller (qw(sendung sendungen kalender kommentare)){ - clear($cache_dir.'/'.$controller.'/*'); - clear($cache_dir.'/programm/'.$controller.'/*'); - } - # update start page print_header("update agenda start page"); $file="$base_dir/programm.html"; @@ -63,22 +47,6 @@ sub clean_up_cache{ } } -sub clear{ - my $path=shift; - - print_error("invalid path '$path' to delete!") unless ($path=~/cache/); - return if ($path=~/\.htaccess$/); - - print_info("clear $path:"); - - for my $file (glob($path) ){ - if (-f $file){ - print_info($file); - unlink $file; - } - } -} - sub print_header{ print "\n# $_[0]\n"; } @@ -100,5 +68,4 @@ sub print_error{ exit 1; } - 1; diff --git a/website/agenda/.htaccess b/website/agenda/.htaccess index a8a5c56..833f9ae 100644 --- a/website/agenda/.htaccess +++ b/website/agenda/.htaccess @@ -15,7 +15,7 @@ RewriteRule ^feed_kommentare/(.*)$ comments.cgi?template=comments.xml&limit RewriteRule ^kommentar_neu/(.*)$ add_comment.cgi?$1 [L] RewriteRule ^sendung/(\d+)/[^&]*(&.*)?$ events.cgi?template=event_details.html&event_id=$1&$2 [L] -RewriteRule ^sendung/(.*)$ events.cgi?$1 [L] +RewriteRule ^sendung/(.*)$ events.cgi?$1 [L] RewriteRule ^sendungen/(\d{4}-\d{2}-\d{2})/(\d{4}-\d{2}-\d{2})/(\d)/(.*)$ events.cgi?template=event_list_2.html&from_date=$1&till_date=$2&weekday=$3&$4 [L] RewriteRule ^sendungen/(\d{4}-\d{2}-\d{2})/(\d{4}-\d{2}-\d{2})/(.*)$ events.cgi?template=event_list_2.html&from_date=$1&till_date=$2&$3 [L] @@ -25,15 +25,14 @@ RewriteRule ^sendungen/(.*)$ events.cgi?$1 [L] RewriteRule ^menu/(\d{4}-\d{2}-\d{2})/(\d{4}-\d{2}-\d{2})/(\d)/(.*)$ events.cgi?template=event_menu.html&from_date=$1&till_date=$2&weekday=$3&$4 [L] RewriteRule ^menu/(\d{4}-\d{2}-\d{2})/(\d{4}-\d{2}-\d{2})/(.*)$ events.cgi?template=event_menu.html&from_date=$1&till_date=$2&$3 [L] -RewriteRule ^menu/(\d{4}-\d{2}-\d{2})/(.*)$ events.cgi?template=event_menu.html&date=$1&$2 [L] -RewriteRule ^menu/heute/(.*)$ events.cgi?template=event_menu.html&date=today&$1 [L] -RewriteRule ^menu/(.*)$ events.cgi?$1 [L] +RewriteRule ^menu/(\d{4}-\d{2}-\d{2})/(.*)$ events.cgi?template=event_menu.html&date=$1&$2 [L] +RewriteRule ^menu/heute/(.*)$ events.cgi?template=event_menu.html&date=today&$1 [L] +RewriteRule ^menu/(.*)$ events.cgi?$1 [L] RewriteRule ^kalender/(\d{4}-\d{2}-\d{2})/$ cal.cgi?date=$1&template=calendar_colo.html&open_end=1 [L] RewriteRule ^kalender/(\d{4}-\d{2}-\d{2})/(\d{4}-\d{2}-\d{2})/$ cal.cgi?from_date=$1&till_date=$2&template=calendar_colo.html&open_end=1 [L] RewriteRule ^kalender/(.*)$ cal.cgi?$1&template=calendar_colo.html&open_end=1 [L] -RewriteRule ^kategorien/(.*)$ category.cgi?$1 [L] RewriteRule ^sendereihen/(.*)$ series_names.cgi?$1 [L] RewriteRule ^playlist/(.*)$ events.cgi?template=event_playlist.html&time=future&limit=5&$1 [L] @@ -48,6 +47,8 @@ RewriteRule ^atom/(.*)$ events.cgi?template=event.atom.xml&time=future&limit= RewriteRule ^atom.xml[\?]?(.*)$ events.cgi?template=event.atom.xml&time=future&limit=100&$1 [L] RewriteRule ^rss/(.*)$ events.cgi?template=event.rss.xml&time=future&limit=100&$1 [L] RewriteRule ^rss.xml[\?]?(.*)$ events.cgi?template=event.rss.xml&time=future&limit=100&$1 [L] +RewriteRule ^rss-media/(.*)$ events.cgi?last_days=7&only_recordings=1&template=event_media.rss.xml&$1 [L] + RewriteRule ^ical/(\d{4}-\d{2}-\d{2})/(\d{4}-\d{2}-\d{2})/(\d)/(.*)$ events.cgi?template=event.ics&from_date=$1&till_date=$2&weekday=$3&$4 [L] RewriteRule ^ical/(\d{4}-\d{2}-\d{2})/(\d{4}-\d{2}-\d{2})/(.*)$ events.cgi?template=event.ics&from_date=$1&till_date=$2&$3 [L] @@ -63,27 +64,24 @@ RewriteRule ^suche/(.*?)/(.*?)/vergangene/(.*)$ events.cgi?template=event_list.h RewriteRule ^suche/(.*?)/(.*?)/(.*)$ events.cgi?template=event_list.html&project=$1&search=$2&$3 [L] RewriteRule ^suche/(.*?)/(.*)$ events.cgi?template=event_list.html&search=$1&$2 [L] -RewriteRule ^kategorie/(.*?)/(.*?)/kommende/(.*)$ events.cgi?template=event_list.html&project=$1&category=$2&archive=coming&$3 [L] -RewriteRule ^kategorie/(.*?)/(.*?)/vergangene/(.*)$ events.cgi?template=event_list.html&project=$1&category=$2&archive=gone&$3 [L] -RewriteRule ^kategorie/(.*?)/(.*?)/(.*)$ events.cgi?template=event_list.html&project=$1&category=$2&$3 [L] -RewriteRule ^kategorie/(.*?)/(.*)$ events.cgi?template=event_list.html&category=$1&$2 [L] - RewriteRule ^rds/(.*)$ events.cgi?template=event_playlist.txt&time=now&limit=1&$1 [L] RewriteRule ^playlist_show/(.*)$ events.cgi?template=event_playlist_show.html&time=future&limit=3&$1 [L] RewriteRule ^json/(.*)$ events.cgi?template=event.json&time=now&limit=15&$1 [L] +RewriteRule ^dashboard/sendung/(\d+)/[^&]*(&.*)?$ events.cgi?template=event_dashboard_details.html&event_id=$1&$2 [L] +RewriteRule ^dashboard/date/(\d{4}-\d{2}-\d{2})/ events.cgi?template=event_dashboard.html.js&date=$1&$2 [L] +RewriteRule ^dashboard/(.*)$ events.cgi?template=event_dashboard.html.js&time=now&limit=1&$1 [L] + RewriteRule ^sendereihe/(.*?)/(.*?)/kommende/(.*)$ events.cgi?template=event_list.html&project=$1&series_name=$2&archive=coming&$3 [L] RewriteRule ^sendereihe/(.*?)/(.*?)/vergangene/(.*)$ events.cgi?template=event_list.html&project=$1&series_name=$2&archive=gone&$3 [L] +RewriteRule ^sendereihe/(.*?)/(.*?)/show/$ events.cgi?template=event_redirect.html&project=$1&series_name=$2&limit=1&$3 [L] RewriteRule ^sendereihe/(.*?)/(.*?)/(.*)$ events.cgi?template=event_list.html&project=$1&series_name=$2&$3 [L] RewriteRule ^sendereihe/(.*?)/(.*)$ events.cgi?template=event_list.html&series_name=$1&$2 [L] RewriteRule ^freefm.xml$ events.cgi?template=event_freefm.xml&location=piradio&limit=40 -RewriteRule ^future$ events.cgi?template=event_list_image.html&limit=20 -RewriteRule ^dt64-festival.html$ events.cgi?location=dt64&template=event_dt64&archive=all RewriteRule ^frrapo-programm.html$ events.cgi?location=potsdam&template=event_frrapo RewriteRule ^upload_playout_piradio$ upload_playout.cgi?project_id=1&studio_id=1 - </IfModule> # MOD_PERL @@ -104,18 +102,4 @@ Options -Indexes +FollowSymLinks +MultiViews +ExecCGI AddHandler cgi-script .cgi .pl </IfModule> -#Order allow,deny -#allow from all Require all granted - -## compress -<IfModule mod_headers.c> -# SetOutputFilter DEFLATE -# SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|zip|mp3)$ no-gzip dont-vary -# Header append Vary User-Agent env=!dont-vary - -# <FilesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|js|css|swf)$"> -# Header set Cache-Control "max-age=600, public" -# </FilesMatch> -</IfModule> - diff --git a/website/agenda/add_comment.cgi b/website/agenda/add_comment.cgi index 70c5d09..9112906 100755 --- a/website/agenda/add_comment.cgi +++ b/website/agenda/add_comment.cgi @@ -1,99 +1,95 @@ -#! /usr/bin/perl -w +#!/usr/bin/perl -use warnings "all"; -use diagnostics; use strict; +use warnings; +no warnings 'redefine'; + use Data::Dumper; -use CGI qw(header param Vars escapeHTML uploadInfo cgi_error); -$CGI::POST_MAX=1024 * 100; - -use params; -use config; -use db; -use markup; -use cache; -use comments; -use template; -use log; -use time; +use params(); +use config(); +use db(); +use markup(); +use comments(); +use template(); +use log(); +use time(); binmode STDOUT, ":utf8"; -my $r=shift; -(my $cgi, my $params, my $error)=params::get($r); +my $r = shift; +( my $cgi, my $params, my $error ) = params::get($r); -my $config = config::get('./config/config.cgi'); -my $debug = $config->{system}->{debug}; - -$cache::debug=$debug; - -my $request={ - url => $ENV{QUERY_STRING}, - params => { - original => $params, - checked => check_params($config, $params), - }, - config => $config, +my $config = config::getFromScriptLocation(); +my $request = { + url => $ENV{QUERY_STRING}, + params => { + original => $params, + checked => check_params( $config, $params ), + }, + config => $config, }; -$params=$request->{params}->{checked}; -log::init($request); +$params = $request->{params}->{checked}; -print $cgi->header('text/plain')."\n"; +print "Content-Type:text/plain\n\n"; -print STDERR "add comment: ".Dumper($params); -my $comment =$params->{comment}; +print STDERR "add comment: " . Dumper($params); +my $comment = $params->{comment}; -$config->{access}->{write}=1; -my $dbh=db::connect($config,undef); +$config->{access}->{write} = 1; +my $dbh = db::connect( $config, undef ); print "ok\n"; -$comment->{content}=~s/(^|\s)((https?\:\/\/)(.*?))(\s|$|\<)/$1\<a href\=\"$2\"\>$2\<\/a\>$5/g; -$comment->{content}=~s/(^|\s)((https?\:\/\/)(.*?))(\s|$|\<)/$1\<a href\=\"$2\"\>$2\<\/a\>$5/g; -$comment->{content}=~s/(^|\s)((www\.)(.*?))(\s|$|\<)/$1\<a href\=\"http\:\/\/$2\"\>$2\<\/a\>$5/g; #" -$comment->{content}=~s/(^|\s)((www\.)(.*?))(\s|$|\<)/$1\<a href\=\"http\:\/\/$2\"\>$2\<\/a\>$5/g; #" +$comment->{content} =~ s/(^|\s)((https?\:\/\/)(.*?))(\s|$|\<)/$1\<a href\=\"$2\"\>$2\<\/a\>$5/g; +$comment->{content} =~ s/(^|\s)((https?\:\/\/)(.*?))(\s|$|\<)/$1\<a href\=\"$2\"\>$2\<\/a\>$5/g; +$comment->{content} =~ s/(^|\s)((www\.)(.*?))(\s|$|\<)/$1\<a href\=\"http\:\/\/$2\"\>$2\<\/a\>$5/g; #" +$comment->{content} =~ s/(^|\s)((www\.)(.*?))(\s|$|\<)/$1\<a href\=\"http\:\/\/$2\"\>$2\<\/a\>$5/g; #" -if (comments::check($dbh, $config, $comment)){ - my $nslookup=nslookup(); +if ( comments::check( $dbh, $config, $comment ) ) { + my $nslookup = nslookup(); - #if (is_blocked($nslookup)==1){ - # send_mail($comment, $nslookup, 'blocked'); - # return; - #}; - $comment->{comment_id}=comments::insert($dbh, $config, $comment); - if($comment->{comment_id}>0){ - comments::update_comment_count($dbh, $config, $comment); - delete_cache($config); - send_mail($comment, $nslookup, 'new'); + if (is_blocked($nslookup)==1){ + send_mail($comment, $nslookup, 'blocked'); + return; + }; + + $comment->{comment_id} = comments::insert( $dbh, $config, $comment ); + if ( $comment->{comment_id} > 0 ) { + comments::update_comment_count( $dbh, $config, $comment ); + send_mail( $config, $comment, $nslookup, 'new' ); } } -sub is_blocked{ - my $nslookup=shift; +sub is_blocked { + my $nslookup = shift; - my $user_agent=$ENV{HTTP_USER_AGENT}; + my $user_agent = $ENV{HTTP_USER_AGENT}; - my $block=0; - $block = 1 - if ( ( $user_agent eq 'Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:35.0) Gecko/20100101 Firefox/35.0' ) - && ( $nslookup =~ /alicedsl/ ) ); - return $block; + # add lock settings here + # return 1 if + # ( $user_agent eq 'Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:35.0) Gecko/20100101 Firefox/35.0' ) + # && ( $nslookup =~ /alicedsl/ ); + + return 0; } -sub send_mail{ +sub send_mail { + my $config = shift; my $comment = shift; my $nslookup = shift; my $status = shift || 'new'; - my $ip = $ENV{REMOTE_ADDR}||''; - my $user_agent = $ENV{HTTP_USER_AGENT}||''; - my $cookie = $ENV{HTTP_COOKIE}||''; + my $ip = $ENV{REMOTE_ADDR} || ''; + my $user_agent = $ENV{HTTP_USER_AGENT} || ''; + my $cookie = $ENV{HTTP_COOKIE} || ''; - my $from = 'no-reply@'; - my $to = 'info@'; - my $subject = "$status comment from '$comment->{author}': $comment->{content}"; - my $content = "$status comment + my $locations = $config->{locations}; + my $base_domain = $locations->{base_domain}; + my $from = $locations->{email}; + my $to = $locations->{email}; + my $subject = "$status comment from '$comment->{author}': $comment->{content}"; + my $content = qq!$status comment FROM: '$comment->{author}' EMAIL: $comment->{email} @@ -101,20 +97,20 @@ EMAIL: $comment->{email} CONTENT: '$comment->{content}' view event -https://programm.coloradio.org/programm/sendung/$comment->{event_id}.html#comments -"; +$base_domain/programm/sendung/$comment->{event_id}.html#comments +!; -if ($status eq 'new'){ - $content.=" + if ( $status eq 'new' ) { + $content .= qq! manage comments: -https://programm.coloradio.org/agenda/planung/comment.cgi?project_id=1&studio_id=1 +$base_domain/agenda/planung/comment.cgi?project_id=1&studio_id=1 lock this comment -https://programm.coloradio.org/agenda/planung/comment.cgi?event_id=$comment->{event_id}&comment_id=$comment->{comment_id}&set_lock_status=blocked -"; -} +$base_domain/agenda/planung/comment.cgi?event_id=$comment->{event_id}&comment_id=$comment->{comment_id}&set_lock_status=blocked +!; + } -$content.=qq{ + $content .= qq{ ----------------------------------------------------------- SENDER IP: $ip ($comment->{ip}) @@ -130,126 +126,101 @@ $nslookup To => $to, Subject => $subject, Data => $content - #.Dumper($comment) ); $msg->send; } -sub nslookup{ - my $ip =$ENV{REMOTE_ADDR}; - my $nslookup=''; - if($ip=~/^([\d\.]+)$/){ - $ip=$1; +sub nslookup { + my $ip = $ENV{REMOTE_ADDR}; + my $nslookup = ''; + if ( $ip =~ /^([\d\.]+)$/ ) { + $ip = $1; return `nslookup '$ip'`; } return ''; } -sub delete_cache{ - my $config=shift; +sub check_params { + my $config = shift; + my $params = shift; - unless($config->{locations}->{base_dir}=~/a-zA-Z/){ - print STDERR "add_comment.cgi: base_dir is not configured\n"; - return; - } - unless($config->{cache}->{cache_dir}=~/a-zA-Z/){ - print STDERR "add_comment.cgi: cache_dir is not configured\n"; - return; - } - unless($config->{controllers}->{comments}=~/a-zA-Z/){ - print STDERR "add_comment.cgi: contoller 'comments' is not configured\n"; - return; + my $template = template::check( $config, $params->{'template'}, 'comments.html' ); + + my $comment = {}; + + my $event_start = $params->{'event_start'} || ''; + if ( $event_start =~ /^(\d\d\d\d\-\d\d\-\d\d[ T]\d\d\:\d\d)(\:\d\d)?$/ ) { + $comment->{event_start} = $1; + } else { + log::error( $config, 'add_comment.cgi: invalid date "' . $event_start . '"' ); } - my $cache_dir=$config->{locations}->{base_dir}.'/'.$config->{cache}->{cache_dir}.'/'; + my $event_id = $params->{'event_id'} || ''; + if ( $event_id =~ /^(\d+)$/ ) { + $comment->{event_id} = $1; + } else { + log::error( $config, 'add_comment.cgi: invalid id' ); + } - my $widget_cache=$cache_dir.'/'.$config->{controllers}->{comments}; - `rm -f $widget_cache/*` if (-d $widget_cache); + my $parent_id = $params->{'parent_id'} || ''; + if ( $parent_id =~ /^(\d+)$/ ) { + $comment->{parent_id} = $1; + } else { + $comment->{parent_id} = 0; + } - my $aggregator_dir=$cache_dir.'/programm/'.$config->{controllers}->{comments}; - `rm -f $aggregator_dir/*` if (-d $aggregator_dir); + $comment->{content} = $params->{'content'} || ''; + $comment->{content} = escape_text( $comment->{content} ); + $comment->{content} = substr( $comment->{content}, 0, 1000 ); + log::error( $config, 'add_comment.cgi: missing body' ) if $comment->{content} eq ''; + + $comment->{author} = $params->{'author'} || ''; + $comment->{author} = escape_text( $comment->{author} ); + $comment->{author} = substr( $comment->{author}, 0, 40 ); + log::error( $config, 'add_comment.cgi: missing name' ) if $comment->{author} eq ''; + + $comment->{email} = $params->{'email'} || ''; + $comment->{email} = escape_text( $comment->{email} ); + $comment->{email} = substr( $comment->{email}, 0, 40 ); + + $comment->{title} = $params->{'title'} || ''; + $comment->{title} = escape_text( $comment->{title} ); + $comment->{title} = substr( $comment->{title}, 0, 80 ); + + $comment->{ip} = $ENV{REMOTE_ADDR} || ''; + log::error( $config, 'missing ip' ) if $comment->{ip} eq ''; + $comment->{ip} = Digest::MD5::md5_base64( $comment->{ip} ); + + my $today = time::datetime_to_array( time::time_to_datetime() ); + my $date = time::datetime_to_array( $comment->{event_start} ); + my $delta_days = time::days_between( $today, $date ); + + log::error( $config, 'add_comment.cgi: no comments allowed, yet' ) + if $delta_days > $config->{permissions}->{no_new_comments_before}; + + log::error( $config, 'add_comment.cgi: no comments allowed anymore' ) + if $delta_days < -1 * $config->{permissions}->{no_new_comments_after}; + + return { + template => $template, + comment => $comment + }; } -sub check_params{ - my $config=shift; - my $params=shift; +sub escape_text { + my $s = shift; + $s =~ s/^\s+//g; + $s =~ s/\s+$//g; - my $template=template::check($params->{'template'}, 'comments.html'); - - my $comment={}; + #remove broken HTML + $s =~ s/<[a-z\!\?\[\/][^\>]+?\>//gi; + $s =~ s/<[a-z\!\?\[\/]\>//gi; - my $event_start=$params->{'event_start'}||''; - if ($event_start=~/^(\d\d\d\d\-\d\d\-\d\d[ T]\d\d\:\d\d)(\:\d\d)?$/){ - $comment->{event_start}=$1; - }else{ - log::error($config, 'add_comment.cgi: invalid date "'.$event_start.'"'); - } - - my $event_id=$params->{'event_id'}||''; - if ($event_id=~/^(\d+)$/){ - $comment->{event_id}=$1; - }else{ - log::error($config, 'add_comment.cgi: invalid id'); - } - - my $parent_id=$params->{'parent_id'}||''; - if ($parent_id=~/^(\d+)$/){ - $comment->{parent_id}=$1; - }else{ - $comment->{parent_id}=0; - } - - $comment->{content}=$params->{'content'}||''; - $comment->{content}=escape_text($comment->{content}); - $comment->{content}=substr($comment->{content},0,1000); - log::error($config, 'add_comment.cgi: missing body') if ($comment->{content}eq''); - - $comment->{author}=$params->{'author'}||''; - $comment->{author}=escape_text($comment->{author}); - $comment->{author}=substr($comment->{author},0,40); - log::error($config, 'add_comment.cgi: missing name') if ($comment->{author}eq''); - - $comment->{email}=$params->{'email'}||''; - $comment->{email}=escape_text($comment->{email}); - $comment->{email}=substr($comment->{email},0,40); - - $comment->{title}=$params->{'title'}||''; - $comment->{title}=escape_text($comment->{title}); - $comment->{title}=substr($comment->{title},0,80); - - $comment->{ip}=$ENV{REMOTE_ADDR}||''; - log::error($config, 'missing ip') if ($comment->{ip}eq''); - $comment->{ip}=Digest::MD5::md5_base64($comment->{ip}); - - my $today=time::datetime_to_array(time::time_to_datetime()); - my $date =time::datetime_to_array($comment->{event_start}); - my $delta_days=time::days_between($today,$date); - log::error( $config, 'add_comment.cgi: no comments allowed, yet' ) - if ( $delta_days > $config->{permissions}->{no_new_comments_before} ); - log::error( $config, 'add_comment.cgi: no comments allowed anymore' ) - if ( $delta_days < -1 * $config->{permissions}->{no_new_comments_after} ); - - return { - template =>$template, - comment =>$comment - }; + $s = markup::escapeHtml($s); + $s =~ s/[\n\r]+/\<br \/\>/g; + $s =~ s/\<br \/\>/\<br \/\>\n/g; + $s =~ s/\<br \/\>\s*$//g; + return $s; } -sub escape_text{ - my $s=shift; - $s=~s/^\s+//g; - $s=~s/\s+$//g; - - #remove broken HTML - $s=~s/<[a-z\!\?\[\/][^\>]+?\>//gi; - $s=~s/<[a-z\!\?\[\/]\>//gi; - - $s=CGI::escapeHTML($s); - $s=~s/[\n\r]+/\<br \/\>/g; - $s=~s/\<br \/\>/\<br \/\>\n/g; - $s=~s/\<br \/\>\s*$//g; - return $s; -} - - diff --git a/website/agenda/aggregate.cgi b/website/agenda/aggregate.cgi index 8b609bd..b78d49a 100755 --- a/website/agenda/aggregate.cgi +++ b/website/agenda/aggregate.cgi @@ -1,180 +1,140 @@ -#! /usr/bin/perl -w +#!/usr/bin/perl -use warnings "all"; use strict; +use warnings; +no warnings 'redefine'; +use utf8; +use feature 'state'; -#use Data::Dumper; - -#use DBI; -use CGI qw(header param Vars); - -#use Time::Local qw(timelocal); -#use Benchmark; -#use Devel::Profiler; - -use db; -use events; -use time; -use aggregator; -use markup; -use log; -use config; - -#use params; -#my $r=shift; +use config(); +use params(); +use db(); +use events(); +use time(); +use aggregator(); +use markup(); +use log(); if ( $0 =~ /aggregate.*?\.cgi$/ ) { - binmode STDOUT, ":encoding(UTF-8)"; + binmode STDOUT, ":encoding(UTF-8)"; - #(my $cgi, my $params, my $error)=params::get($r); - my $cgi = new CGI(); - my %params = $cgi->Vars(); - my $params = \%params; + my $params = {}; + my $r = shift; + if ( ref($r) eq '' ) { + unshift @ARGV, $r; + for my $arg (@ARGV) { + my ( $key, $value ) = split( /\=/, $arg, 2 ); + $params->{$key} = $value; + } + } else { + ( my $cgi, $params, my $error ) = params::get($r); + } - #print STDERR Dumper($params); + my $config = config::getFromScriptLocation(); - my $config = config::get('config/config.cgi'); - my $debug = $config->{system}->{debug}; - my $mem_debug = $config->{system}->{debug_memory}; - my $base_dir = $config->{locations}->{base_dir}; + my $debug = $config->{system}->{debug}; + my $base_dir = $config->{locations}->{base_dir}; - #my $cgi=new CGI(); - my $output_header = ''; - if ( exists $ENV{REQUEST_URI} && $ENV{REQUEST_URI} ne '' ) { - $output_header .= "Content-type:text/html; charset=UTF-8;\n\n"; - } + my $output_header = ''; + if ( exists $ENV{REQUEST_URI} && $ENV{REQUEST_URI} ne '' ) { + $output_header .= "Content-type:text/html; charset=UTF-8;\n\n"; + } - # $output_header.='<!DOCTYPE html>'."\n"; + $params->{exclude_locations} = 1; + $params->{exclude_projects} = 1; + $params->{exclude_event_images} = 1; + $params->{ro} = 1; + $params->{recordings} = 1; - my $request = { - url => $ENV{QUERY_STRING}, - params => { - original => $params, - checked => aggregator::check_params( $config, $params ), - }, - }; - $params = $request->{params}->{checked}; + my $request = { + url => $ENV{QUERY_STRING}, + params => { + original => $params, + checked => aggregator::check_params( $config, $params ), + }, + }; + $params = $request->{params}->{checked}; - my $mem = 0; - log::init($request); + my $content = load_file( $base_dir . './index.html' ); - #get result from cache - my $cache = aggregator::get_cache( $config, $request ); + #replace HTML escaped calcms_title span by unescaped one + $content =~ +s/\<\;span id\="\;calcms_title"\;\>\;[^\&]*\<\;\/span\>\;/\<span id=\"calcms_title\" \>\<\/span\>/g; - if ( ( defined $cache->{content} ) && ( $cache->{content} ne '' ) ) { - my $content = $cache->{content}; - print $output_header; - print $content; - return; - } + my $list = aggregator::get_list( $config, $request ); - my $content = load_file( $base_dir . './index.html' ); - $content = $$content || ''; + my $menu = { content => '' }; - #replace HTML escaped calcms_title span by unescaped one - $content =~ s/\<\;span id\="\;calcms_title"\;\>\;[^\&]*\<\;\/span\>\;/\<span id=\"calcms_title\" \>\<\/span\>/g; - - # print $content; - - my $list = aggregator::get_list( $config, $request ); - - my $menu = { content => '' }; - - $list->{day} = '' unless defined $list->{day}; - $list->{day} = $params->{date} if (defined $params->{date}) && ($params->{date} ne ''); - $list->{day} = $params->{from_date} if (defined $params->{from_date}) && ($params->{from_date} ne ''); + $list->{day} = '' unless defined $list->{day}; + $list->{day} = $params->{date} if ( defined $params->{date} ) && ( $params->{date} ne '' ); + $list->{day} = $params->{from_date} if ( defined $params->{from_date} ) && ( $params->{from_date} ne '' ); $list->{day} = 'today' if $list->{day} eq ''; - $menu = aggregator::get_menu( $config, $request, $list->{day}, $list->{results} ); + $params->{recordings} = 0; + $menu = aggregator::get_menu( $config, $request, $list->{day}, $list->{results} ); - my $calendar = aggregator::get_calendar( $config, $request, $list->{day} ); - my $newest_comments = aggregator::get_newest_comments( $config, $request ); + my $calendar = aggregator::get_calendar( $config, $request, $list->{day} ); + my $newest_comments = aggregator::get_newest_comments( $config, $request ); - #my $newest_comments={}; - #db::disconnect($request) if (defined $request && defined $request->{connection}); - #print STDERR "$list->{project_title}\n"; + #build results list + my $output = {}; + $output->{calcms_menu} = \$menu->{content}; + $output->{calcms_list} = \$list->{content}; + $output->{calcms_calendar} = \$calendar->{content}; + $output->{calcms_newest_comments} = \$newest_comments->{content}; - #build results list - my $output = {}; - $output->{calcms_menu} = \$menu->{content}; - $output->{calcms_list} = \$list->{content}; - $output->{calcms_calendar} = \$calendar->{content}; - $output->{calcms_newest_comments} = \$newest_comments->{content}; - - # $output->{calcms_categories} = load_file($base_dir.'/cache/categories.html'); - # $output->{calcms_series_names} = load_file($base_dir.'/cache/series_names.html'); - # $output->{calcms_programs} = load_file($base_dir.'/cache/programs.html'); - - my $url = $list->{url}; - my $js = qq{ + my $url = $list->{url}; + my $js = qq{ set('preloaded','1'); set('last_list_url','$url'); }; - $content =~ s/\/\/\s*(calcms_)?preload/$js/; + $content =~ s/\/\/\s*(calcms_)?preload/$js/; - #insert results into page - for my $key ( keys %$output ) { - my $val = ${ $output->{$key} }; - my $start = index( $val, "<body>" ); - if ( $start != -1 ) { - $val = substr( $val, $start + length('<body>') ); - } - my $end = index( $val, "</body>" ); - if ( $end != -1 ) { - $val = substr( $val, 0, $end ); - } - $content =~ s/(<(div|span)\s+id="$key".*?>).*?(<\/(div|span)>)/$1$val$3/g; - } + #insert results into page + for my $key ( keys %$output ) { + my $val = ${ $output->{$key} }; + my $start = index( $val, "<body>" ); + if ( $start != -1 ) { + $val = substr( $val, $start + length('<body>') ); + } + my $end = index( $val, "</body>" ); + if ( $end != -1 ) { + $val = substr( $val, 0, $end ); + } + $content =~ s/(<(div|span)\s+id="$key".*?>).*?(<\/(div|span)>)/$1$val$3/g; + } - #replace whole element span with id="calcms_title" by value - $list->{project_title} = '' unless ( defined $list->{project_title} ); - $content =~ s/(<(div|span)\s+id="calcms_title".*?>).*?(<\/(div|span)>)/$list->{project_title}/g; + #replace whole element span with id="calcms_title" by value + $list->{project_title} = '' unless defined $list->{project_title}; + $content =~ s/(<(div|span)\s+id="calcms_title".*?>).*?(<\/(div|span)>)/$list->{project_title}/g; - my $title = $list->{program} || ''; - $title .= ' - ' . $list->{series_name} if ( ( defined $list->{series_name} ) && ( $list->{series_name} ne '' ) ); - $title .= ' - ' . $list->{title} if ( ( defined $list->{title} ) && ( $list->{title} ne '' ) ); - $title = ' | ' . $title if ( $title ne '' ); - $title .= 'Programmplan'; - $title .= ' | ' . $list->{project_title} if $list->{project_title} ne ''; + my $title = join ' - ', grep {defined $_ and $_ ne ''} ( + $list->{'series_name'}, $list->{'title'}, + $list->{'location'}, 'Programm ' . $list->{project_title} + ); + $content =~ s/(<title>)(.*?)(<\/title>)/$1$title$3/; - #$content=~s/(<title>)(.*?)(<\/title>)/$1$title$3/; + $js = ''; + if ( ( defined $list->{event_id} ) && ( $list->{event_id} ne '' ) ) { + $js .= qq{showCommentsByEventIdOrEventStart('$list->{event_id}','$list->{start_datetime}')}; + } - $js = ''; - if ( ( defined $list->{event_id} ) && ( $list->{event_id} ne '' ) ) { - $js .= qq{showCommentsByEventIdOrEventStart('$list->{event_id}','$list->{start_datetime}')}; - } - - $content =~ s/startCalcms\(\)\;/$js/gi; - - #replace link to uncompressed or compressed drupal (first link in <head>) - my @parts = split( /<\/head>/, $content ); - $parts[0] =~ s|/misc/jquery.js|/agenda_files/js/jquery.js|; - $parts[0] =~ s|/sites/default/files/js/[a-z0-9\_]+\.js|/agenda_files/js/jquery.js|; - $content = join( '</head>', @parts ); - - print $output_header; - print $content; - - # $r->print("done"); - - if ( $config->{cache}->{use_cache} eq '1' ) { - $cache->{content} = $content; - log::write( $config, 'cache_file', $cache->{filename} ) if ($debug); - cache::save($cache); - } - - # $config=undef; - $content = undef; - $cache = undef; - log::mem( $config, 'aggregate done', $mem ) if ( $mem_debug > 0 ); + $content =~ s/startCalcms\(\)\;/$js/gi; + print $output_header; + print $content; + $content = undef; } sub load_file { - my $filename = shift; - my $content = "cannot load '$filename'"; - open my $FILE, '<:utf8', $filename or return \$content; - $content = join( "", (<$FILE>) ); - close $FILE; - return \$content; + my ($filename) = @_; + state $cache; + my $cached = $cache->{$filename}; + return $cached->{content} if defined $cached and $cached->{updated} > time - 60; + open my $fh, '<:utf8', $filename or return qq{cannot load '$filename'}; + local $/ = undef; + my $content = <$fh>; + close $fh or return qq{cannot load '$filename'}; + $cache->{$filename} = {updated => time, content => $content}; + return $content; } diff --git a/website/agenda/all-events.cgi b/website/agenda/all-events.cgi new file mode 100644 index 0000000..46d0cd3 --- /dev/null +++ b/website/agenda/all-events.cgi @@ -0,0 +1,34 @@ +#!/usr/bin/perl + +use strict; +use warnings; +no warnings 'redefine'; + +use params(); +use config(); +use events(); + +binmode STDOUT, ":encoding(UTF-8)"; + +my $r = shift; +( my $cgi, my $params, my $error ) = params::get($r); +if ( $0 =~ /all-events.*?\.cgi$/ ) { + + my $config = config::getFromScriptLocation(); + + $params->{template} = '' unless defined $params->{template}; + $params->{recordings} = 1 if $params->{template} =~ /events_playout/; + $params->{exclude_event_images} = 1; + + my $request = { + url => $ENV{QUERY_STRING}, + params => { + original => $params, + checked => events::check_params( $config, $params ), + }, + }; + + events::get_cached_or_render( 'print', $config, $request ); +} + +1; diff --git a/website/agenda/cal.cgi b/website/agenda/cal.cgi index 91967d8..37c83a4 100755 --- a/website/agenda/cal.cgi +++ b/website/agenda/cal.cgi @@ -1,44 +1,38 @@ -#! /usr/bin/perl -w +#!/usr/bin/perl -#use utf8; -use warnings "all"; use strict; - -use CGI qw(header param Vars); -$CGI::POST_MAX = 1000; -$CGI::DISABLE_UPLOADS = 1; +use warnings; +no warnings 'redefine'; use Data::Dumper; -use params; -use config; -use log; -use calendar; +use params(); +use config(); +use log(); +use calendar(); -my $r=shift; +my $r = shift; #binmode STDOUT, ":utf8"; binmode STDOUT, ":encoding(UTF-8)"; -if ($0=~/cal.*?\.cgi$/){ - (my $cgi, my $params, my $error)=params::get($r); +if ( $0 =~ /cal.*?\.cgi$/ ) { + ( my $cgi, my $params, my $error ) = params::get($r); - my $config=config::get('config/config.cgi'); - my $debug=$config->{system}->{debug}; + my $config = config::getFromScriptLocation(); + my $debug = $config->{system}->{debug}; - my $request={ - url => $ENV{QUERY_STRING}, - params => { - original => $params, - checked => calendar::check_params($config, $params), - }, - }; - $params=$request->{params}->{checked}; + my $request = { + url => $ENV{QUERY_STRING}, + params => { + original => $params, + checked => calendar::check_params( $config, $params ), + }, + }; + $params = $request->{params}->{checked}; - log::init($request); - - my $out=''; - calendar::get_cached_or_render($out, $config, $request); - print $out."\n"; + my $out = ''; + calendar::get_cached_or_render( $out, $config, $request ); + print $out. "\n"; } 1; diff --git a/website/agenda/category.cgi b/website/agenda/category.cgi deleted file mode 100755 index ff91cf5..0000000 --- a/website/agenda/category.cgi +++ /dev/null @@ -1,146 +0,0 @@ -#! /usr/bin/perl -w - -use strict; -use warnings; - -use Data::Dumper; -use CGI qw(header param Vars); -$CGI::POST_MAX = 1000; -$CGI::DISABLE_UPLOADS = 1; - -use params; -use db; -use markup; -use cache; -use log; -use config; -use template; -use project; - -binmode STDOUT, ":utf8"; - -my $r = shift; -( my $cgi, my $params, my $error ) = params::get($r); - -my $config = config::get('config/config.cgi'); - -my $debug = $config->{system}->{debug}; - -my $request = { - url => $ENV{QUERY_STRING}, - params => { - original => $params, - checked => check_params( $config, $params ), - }, -}; - -log::init($request); - -$params = $request->{params}->{checked}; - -my $cache = {}; -if ( $config->{cache}->{use_cache} eq '1' ) { - cache::configure('categories.html'); - $cache = cache::load( $config, $params ); - if ( defined $cache->{content} ) { - print $cache->{content}; - return; - } -} - -my $dbh = db::connect($config); - -my $template_parameters = {}; -$template_parameters->{projects} = getProjects( $dbh, $config ); - -#$template_parameters->{categories} = get_categories($dbh,$params->{project}); -$template_parameters->{debug} = $config->{system}->{debug}; -$template_parameters->{server_cache} = $config->{cache}->{server_cache} if ( $config->{cache}->{server_cache} ); -$template_parameters->{use_client_cache} = $config->{cache}->{use_client_cache} if ( $config->{cache}->{use_client_cache} ); - -my $template = $params->{template}; -my $out = ''; -template::process( $out, $params->{template}, $template_parameters ); -print $out; - -#write to cache -if ( $config->{cache}->{use_cache} eq '1' ) { - $cache->{content} = $out; - cache::save($cache); -} - -sub getProjects { - my $dbh = shift; - my $config = shift; - - my $excludedProjects = {}; - if ( defined $config->{filter}->{exclude_projects} ) { - for my $project ( split( /\,/, $config->{filter}->{exclude_projects} ) ) { - $project =~ s/^\s+//g; - $project =~ s/\s+$//g; - $excludedProjects->{$project} = 1; - } - } - - my $projects = project::get_sorted($config); - my $results = []; - for my $project (@$projects) { - next if defined $excludedProjects->{ $project->{name} }; - my $categories = getCategories( $dbh, $config, $project->{name} ); - $project->{isEmpty} = 1 if scalar(@$categories) == 0; - $project->{categories} = $categories; - - $project->{js_name} = $project->{name}; - $project->{js_name} =~ s/[^a-zA-Z\_0-9]/\_/g; - $project->{js_name} =~ s/\_+/\_/g; - push @$results, $project; - } - return $results; -} - -sub getCategories { - my $dbh = shift; - my $config = shift; - my $project = shift; - - my $cond = ''; - my $bind_values = []; - if ( ( $project ne '' ) && ( $project ne 'all' ) ) { - $cond = 'where project=?'; - $bind_values = [$project]; - } - - my $query = qq{ - select name, count(name) sum - from calcms_categories - $cond - group by name - order by sum desc, name - }; - my $categories = db::get( $dbh, $query, $bind_values ); - - my $results = []; - for my $category (@$categories) { - push @$results, $category if $category->{sum} > 1; - } - - return $results; -} - -sub check_params { - my $config = $_[0]; - my $params = $_[1]; - - my $template = template::check( $params->{template}, 'categories.html' ); - - my $debug = $params->{debug} || ''; - if ( $debug =~ /([a-z\_\,]+)/ ) { - $debug = $1; - } - - return { - template => $template, - debug => $debug - }; -} - diff --git a/website/agenda/checkip.cgi b/website/agenda/checkip.cgi new file mode 100755 index 0000000..b86e9d9 --- /dev/null +++ b/website/agenda/checkip.cgi @@ -0,0 +1,4 @@ +#!/bin/perl + +print "Content-type:text/plain\n\nCurrent IP Address:".$ENV{REMOTE_ADDR}."\n"; + diff --git a/website/agenda/comments.cgi b/website/agenda/comments.cgi index df32af9..ff19394 100755 --- a/website/agenda/comments.cgi +++ b/website/agenda/comments.cgi @@ -1,43 +1,38 @@ -#! /usr/bin/perl -w +#!/usr/bin/perl -use warnings "all"; use strict; - -use CGI qw(header param Vars); -$CGI::POST_MAX = 1000; -$CGI::DISABLE_UPLOADS = 1; +use warnings; +no warnings 'redefine'; use Data::Dumper; -use params; -use config; -use comments; -use db; -use markup; -use time; -use cache; -use log; -my $r=shift; -(my $cgi, my $params, my $error)=params::get($r); +use params(); +use config(); +use comments(); +use db(); +use markup(); +use time(); +use log(); +my $r = shift; +( my $cgi, my $params, my $error ) = params::get($r); binmode STDOUT, ":encoding(UTF-8)"; -if ($0=~/comments.*?\.cgi$/){ - my $config=config::get('config/config.cgi'); - my $debug=$config->{system}->{debug}; +if ( $0 =~ /comments.*?\.cgi$/ ) { + my $config = config::get('config/config.cgi'); + my $debug = $config->{system}->{debug}; - my $request={ - url => $ENV{QUERY_STRING}, - params => { - original => $params, - checked => comments::check_params($config, $params), - }, - }; - log::init($request); - - my $output=''; - comments::get_cached_or_render($output, $config, $request, 'filter_locked'); - print $output; + my $request = { + url => $ENV{QUERY_STRING}, + params => { + original => $params, + checked => comments::check_params( $config, $params ), + }, + }; + + my $output = ''; + comments::get_cached_or_render( $output, $config, $request, 'filter_locked' ); + print $output; } #do not delete last line diff --git a/website/agenda/config/.htaccess b/website/agenda/config/.htaccess index b2f8f32..b66e808 100644 --- a/website/agenda/config/.htaccess +++ b/website/agenda/config/.htaccess @@ -1,3 +1 @@ -Order deny,allow -deny from all -Require all granted +Require all denied diff --git a/website/agenda/config/config.cgi.off b/website/agenda/config/config.cgi.off index 9a2ed6f..3058341 100755 --- a/website/agenda/config/config.cgi.off +++ b/website/agenda/config/config.cgi.off @@ -1,109 +1,102 @@ #!/usr/bin/perl -use CGI qw(header param Vars); -$CGI::POST_MAX = 0;$CGI::DISABLE_UPLOADS = 1;$cgi=new CGI();print $cgi->header();return;exit; +print "Content-type:text/plain\n\nAccess denies."; +exit; __END__ <config> -# TODO: replace with projects from database -project Corax +Define DOMAIN localhost +Define BASE_DIR /home/calcms/racalmas/website + +# default project from database +project my-project +domain ${DOMAIN} + +<filter> +# projects_to_exclude project1 +# locations_to_exclude location1,location2 +</filter> -# widget support <controllers> # controller base directory - domain /agenda/ + domain /agenda/ # customize controller URLs - calendar kalender - event sendung - events sendungen - comments kommentare - ical ical - atom atom - rss rss + calendar kalender + event sendung + events sendungen + comments kommentare + ical ical + atom atom + rss rss </controllers> -# widget support -<templates> - events event_menu.html - events event_list.html - events event_details.html - events event_playlist.html - events event_playlist.txt - events event.ics - events event.atom.xml - events event.rss.xml - events event.json - - comments comments.html - comments comments_newest.html - comments comments.xml - aggregator -</templates> - - <system> - config_file /home/calcms/website/agenda/config/config.cgi + config_file ${BASE_DIR}/agenda/config/config.cgi - log_file /var/www/vhosts/system/yourdomain.org/logs/error_log - log_debug_file /home/calcms/log/calcms.log - log_debug_memory_file /home/calcms/log/calcms-mem.log - job_log /home/calcms/log/jobs.log + log_file /var/www/vhosts/${DOMAIN}/logs/error_log + log_debug_file ${LOG_DIR}/${DOMAIN}/calcms.log + log_debug_memory_file ${LOG_DIR}/${DOMAIN}/calcms-mem.log debug_memory 0 debug 0 </system> - + <cache> - use_cache 0 - use_client_cache 0 - compress 0 - cache_dir cache/ base_url /programm </cache> <locations> - # URLs of the program page the agenda should be injected into (done by preload_agenda.pl) - # this is the page containing calcms_menu, and other ids - source_url_http http://www.yourdomain.org/programm.html - source_url_https https://www.yourdomain.org/programm.html + temp_dir ${BASE_DIR}/temp/ + + # source website to inject calcms widgets into + source_url_http http://${DOMAIN}/programm.html + source_url_https https://${DOMAIN}/programm.html # feed base url - source_base_url http://yourdomain.org/ + source_base_url https://${DOMAIN}/ local_base_url /agenda/ + editor_base_url /agenda/planung/ # ajax - base_domain http://yourdomain.org/ + base_domain https://${DOMAIN}/ base_url /agenda/? - base_dir /home/calcms/website/agenda/ + base_dir ${BASE_DIR}/agenda/ static_files_url /agenda/ # images - local_media_dir /home/calcms/website/agenda_files/media/ - local_media_url /agenda_files/media/ + local_media_dir ${BASE_DIR}/media/ + local_media_url /media/ + thumbs_url /thumbs/ + icons_url /icons/ # archives local_archive_dir /home/calcms/archive/ local_archive_url /archive/ - local_audio_recordings_dir /home/calcms/recordings/ + # listen + listen_dir /home/calcms/${DOMAIN}/ + listen_url https://${DOMAIN}/listen/ + + # upload + local_audio_recordings_dir ${BASE_DIR}/recordings/recordings/ local_audio_recordings_url /recordings/ - # synchronization - sync_cms_dir /home/calcms/sync_cms/ - # multi language support - admin_pot_dir /home/calcms/website/agenda/planung/pot/ + admin_pot_dir ${BASE_DIR}/agenda/planung/pot/ + email info@${DOMAIN} + theme default </locations> - <permissions> result_limit 500 # limit creating comments in days before and after start of event - no_new_comments_before 10 + no_new_comments_before 10 no_new_comments_after 60 + + hide_event_images 0 </permissions> <access> @@ -112,10 +105,10 @@ project Corax database calcms username calcms_read - password xxx + password calread000 username_write calcms_write - password_write xxx + password_write calwrite000 </access> <date> @@ -124,5 +117,8 @@ project Corax day_starting_hour 6 </date> -</config> +no_result_message Radio ${DOMAIN} +events_title Radio ${DOMAIN} +events_description Hört mehr Radio +</config> diff --git a/website/agenda/css/agenda.css b/website/agenda/css/agenda.css index 5804f98..e7d5dbd 100644 --- a/website/agenda/css/agenda.css +++ b/website/agenda/css/agenda.css @@ -3,249 +3,303 @@ */ /* main structure */ -/* - body { +#nav { + text-align: center; + margin: 0; + height: 3em; + z-index: 3; + text-align: left; + background: white; + width: 100%; + font-size: 10px; +} - font-size:12px - } -*/ - #nav { - text-align:center; - margin:0; - height:3em; - z-index:3; - text-align:left; - background:white; - width:100%; - font-size:10px; - } - - #calcms_body { -/* - font-size:10px; -*/ - overflow:auto; - background:white; - padding-top:3px;padding-right:5px; - margin:bottom:1px; - text-align:left; - padding:3px; - } - - pre { - text-align:left; -/* - font-size:0.7em; -*/ - font-family:Courier; - padding:1em;margin:1em; - border:1px solid black; - background-color:#eee; - } +#calcms_body { + overflow: auto; + background: white; + padding-top: 3px; + padding-right: 5px; + margin: bottom:1px; + text-align: left; + padding: 3px; +} +pre { + text-align: left; + font-family: Courier; + padding: 1em; + margin: 1em; + border: 1px solid black; + background-color: #eee; +} /* end of main structure */ - /* search field */ +#nav form { + float: left; +} - #nav form {float:left;} - #nav form input { -/* - font-size:12px; -*/ - padding:0;margin:1;border:1px solid gray - } +#nav form input { + padding: 0; + margin: 1; + border: 1px solid gray +} - #nav form select { -/* - font-size:12px; -*/ - padding:0;margin:1;border:1px solid gray;width:130px; - } +#nav form select { + padding: 0; + margin: 1; + border: 1px solid gray; + width: 130px; +} - #nav form option { -/* - font-size:12px; -*/ - padding:0;margin:0 - } +#nav form option { + padding: 0; + margin: 0 +} /* end of search field */ - /* event fields */ +.calcms_date { + background: #ccccff; + padding: 6px; + margin: 0px; + font-weight: bold; + margin-top: 1em; + -moz-border-radius-topleft: 6px; + -moz-border-radius-topright: 6px; + -webkit-border-top-right-radius: 6px; + -webkit-border-top-left-radius: 6px; + text-align: left +} +.calcms_title { + padding: 3px; + margin: 0px; + font-weight: bold; + text-align: left; +} - .calcms_date { - background: #ccccff; - padding:6px;margin:0px; - font-weight:bold; - margin-top:1em; - -moz-border-radius-topleft:6px; - -moz-border-radius-topright:6px; - -webkit-border-top-right-radius: 6px; - -webkit-border-top-left-radius: 6px; - text-align:left - } +.calcms_excerpt { + padding: 3px; + margin: 0px; + background-color: #eee; +} - .calcms_title {padding:3px;margin:0px;font-weight:bold;text-align:left;} - .calcms_excerpt {padding:3px;margin:0px;background-color:#eee;} - .calcms_content {padding:3px;margin:0px;clear:left;margin:0} - .calcms_content p {margin-top:10px} - .calcms_content h1 {text-align:left;font-size:1.5em;clear:left;margin-top:16px} - .calcms_content h2 {text-align:left;font-size:1.5em;clear:left;margin-top:16px} - .calcms_content h3 {text-align:left;font-size:1.5em;clear:left;margin-top:16px} - .calcms_content h4 {text-align:left;font-size:1.5em;clear:left;margin-top:16px} - .calcms_content li {clear:left;} - .calcms_content img {text-align:left;font-size:1.5em;float:left;margin-right:10px;}/*width:50;height:50px;*/ - .calcms_event {text-align:left} - .calcms_day {padding:1px;margin:0px;clear:left;text-align:left} - - /* hide microformats */ - .dtstart {display:none;visibility:hidden;} - .dtend {display:none;visibility:hidden;} +.calcms_content { + padding: 3px; + margin: 0px; + clear: left; + margin: 0 +} + +.calcms_content p { + margin-top: 10px +} + +.calcms_content h1 { + text-align: left; + font-size: 1.5em; + clear: left; + margin-top: 16px +} + +.calcms_content h2 { + text-align: left; + font-size: 1.5em; + clear: left; + margin-top: 16px +} + +.calcms_content h3 { + text-align: left; + font-size: 1.5em; + clear: left; + margin-top: 16px +} + +.calcms_content h4 { + text-align: left; + font-size: 1.5em; + clear: left; + margin-top: 16px +} + +.calcms_content li { + clear: left; +} + +.calcms_content img { + text-align: left; + font-size: 1.5em; + float: left; + margin-right: 10px; +} /*width:50;height:50px;*/ + +.calcms_event { + text-align: left +} + +.calcms_day { + padding: 1px; + margin: 0px; + clear: left; + text-align: left +} + +/* hide microformats */ +.dtstart { + display: none; + visibility: hidden; +} + +.dtend { + display: none; + visibility: hidden; +} /* end of event fields */ - - /* navigation bar */ +table#nav { + padding: 0; + margin: 0; + width: 100%; + border-left: 1px solid #88f; + border-top: 1px solid #88f; + text-align: left; +} - table#nav{ - padding:0;margin:0;width:100%; - border-left:1px solid #88f; - border-top: 1px solid #88f; - text-align:left; - } - table#nav table{ - padding:0;margin:0; - border-left:0;border-top:0; - text-align:left;width:100% - } - table#nav table td{ - margin:0;text-align:center; - border-bottom:1px solid #88f; - border-right: 1px solid #88f; - } - table#nav table td, - table#nav table a{ - padding:1px; -/* - font-size:10px; +table#nav table { + padding: 0; + margin: 0; + border-left: 0; + border-top: 0; + text-align: left; + width: 100% +} + +table#nav table td { + margin: 0; + text-align: center; + border-bottom: 1px solid #88f; + border-right: 1px solid #88f; +} + +table#nav table td, table#nav table a { + padding: 1px; + /* + font-size:10px; */ - } +} +/* hover effects */ +table#nav table td:hover { + border-bottom: 1px solid #88f; + border-right: 1px solid #88f; + background-color: #f0f0f0; +} - /* hover effects */ +table#nav table td.selected:hover { + background-color: #eee; + border-bottom: 1px solid #88f; + border-right: 1px solid #88f; +} - table#nav table td:hover{ - border-bottom:1px solid #88f; - border-right :1px solid #88f; - background-color:#f0f0f0; - } +table#nav table a:hover { + +} - table#nav table td.selected:hover{ - background-color:#eee; - border-bottom:1px solid #88f; - border-right: 1px solid #88f; - } +/* not selectable columns */ +table#nav table td.row_type:hover { + border-bottom: 1px solid #88f; + border-right: 1px solid #88f; + background-color: #ffffff; +} - table#nav table a:hover{ - } - - - /* not selectable columns */ - - table#nav table td.row_type:hover{ - border-bottom:1px solid #88f; - border-right: 1px solid #88f; - background-color:#ffffff; - } - - .row_type{ - width:100px - } - - - /* selected fields */ - #nav .selected, .night, .morning, .noon, .afternoon, .evening{ - background:#ddd; - border-bottom:1px solid #88f; - border-right: 1px solid #88f; - -moz-border-radius-topleft:5px; - -moz-border-radius-topright:5px; - -webkit-border-top-right-radius: 5px; - -webkit-border-top-left-radius: 5px; - } +.row_type { + width: 100px +} +/* selected fields */ +#nav .selected, .night, .morning, .noon, .afternoon, .evening { + background: #ddd; + border-bottom: 1px solid #88f; + border-right: 1px solid #88f; + -moz-border-radius-topleft: 5px; + -moz-border-radius-topright: 5px; + -webkit-border-top-right-radius: 5px; + -webkit-border-top-left-radius: 5px; +} /* end of navigation bar */ /* calendar weeks */ - - #nav td.week_1, - #nav td.week_2, - #nav td.week_3, - #nav td.week_4, - #nav td.week_5 { - border-right:1px solid #88f ; - } +#nav td.week_1, #nav td.week_2, #nav td.week_3, #nav td.week_4, #nav td.week_5 + { + border-right: 1px solid #88f; +} /* end of calendar weeks */ - /* calendar days */ - /* replaces the original wp css*/ +/* replaces the original wp css*/ +#wp-calendar { + +} - #wp-calendar {} - #wp-calendar a {padding:2px} - #wp-calendar table {padding:2px} +#wp-calendar a { + padding: 2px +} - #wp-calendar td { -/* - font-size:8px; +#wp-calendar table { + padding: 2px +} + +#wp-calendar td { + /* + font-size:8px; */ - text-align:center; - background-color:#fefeff; - } - #wp-calendar td a { - padding:2px; -/* - font-size:8px; + text-align: center; + background-color: #fefeff; +} + +#wp-calendar td a { + padding: 2px; + /* + font-size:8px; */ - font-weight:normal; - } + font-weight: normal; +} - #wp-calendar a:hover { - background:#eeeeff; - } +#wp-calendar a:hover { + background: #eeeeff; +} +/* additional css to mark today and all dates matching to the request */ +#wp-calendar .calcms_today { + padding: 2px; + margin: 0px; + background: #eeeeee; +} - /* additional css to mark today and all dates matching to the request */ +#wp-calendar td.calcms_match { + background: #ccffcc; +} - #wp-calendar .calcms_today { - padding:2px;margin:0px;background:#eeeeee; - } - - #wp-calendar td.calcms_match { - background:#ccffcc; - } - #wp-calendar td .selected .calcms_match { - background:#ddeedd; - } +#wp-calendar td .selected .calcms_match { + background: #ddeedd; +} /* end of calendar days */ +div.update { + position: absolute; + bottom: 0px; +} - div.update { - position:absolute; - bottom:0px; - } - - div.update , div.update a{ - text-align:left; - font-size:6px; - color:#bbb; - } - - +div.update, div.update a { + text-align: left; + font-size: 6px; + color: #bbb; +} diff --git a/website/agenda/css/calcms.css b/website/agenda/css/calcms.css index 7bed1a4..4974cfa 100644 --- a/website/agenda/css/calcms.css +++ b/website/agenda/css/calcms.css @@ -1,117 +1,184 @@ -/* -include in your web page: -<link rel="stylesheet" type="text/css" media="screen" href="/agenda_files/css/calcms.css" /> -*/ - -/* fix drupal */ -input{ - max-width:20em; +* { + border-radius:4px; } -a{ - text-decoration:none; - box-shadow:none !important; +/* roboto-regular - latin_latin-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + src: url('../fonts/roboto-v18-latin_latin-ext-regular.eot'); /* IE9 Compat Modes */ + src: local('Roboto'), local('Roboto-Regular'), + url('../fonts/roboto-v18-latin_latin-ext-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ + url('../fonts/roboto-v18-latin_latin-ext-regular.woff2') format('woff2'), /* Super Modern Browsers */ + url('../fonts/roboto-v18-latin_latin-ext-regular.woff') format('woff'), /* Modern Browsers */ + url('../fonts/roboto-v18-latin_latin-ext-regular.ttf') format('truetype'), /* Safari, Android, iOS */ + url('../fonts/roboto-v18-latin_latin-ext-regular.svg#Roboto') format('svg'); /* Legacy iOS */ +} + +/* open-sans-regular - latin_latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: url('../fonts/open-sans-v15-latin_latin-ext-regular.eot'); /* IE9 Compat Modes */ + src: local('Open Sans Regular'), local('OpenSans-Regular'), + url('../fonts/open-sans-v15-latin_latin-ext-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ + url('../fonts/open-sans-v15-latin_latin-ext-regular.woff2') format('woff2'), /* Super Modern Browsers */ + url('../fonts/open-sans-v15-latin_latin-ext-regular.woff') format('woff'), /* Modern Browsers */ + url('../fonts/open-sans-v15-latin_latin-ext-regular.ttf') format('truetype'), /* Safari, Android, iOS */ + url('../fonts/open-sans-v15-latin_latin-ext-regular.svg#OpenSans') format('svg'); /* Legacy iOS */ +} + +@media (prefers-color-scheme: dark) { + html, + *, + .entry-title a, + #calcms_calendar table thead a:hover, + #calcms_calendar table thead a:link, + .main-navigation a:hover, + .main-navigation a:focus + { + color:white !important; + background:black !important; + } + + #calcms_list h1.summary{ + background: none !important; + } + + a.load-prev, a.load-next{ + color:#999 !important; + background:#333 !important; + } + + img.custom-logo{ + filter: invert(1); + } +} + +#page * { + font-family: Roboto, serif !important; +} + +#page p { + font-family: Open Sans, serif !important; +} + +a { + text-decoration: none; + box-shadow: none !important; } /* hide microformats */ .vevent .dtstart, .vevent .dtend, -.vevent .location{ - display:none; - visibility:hidden; +.vevent .location { + display: none; + visibility: hidden; } -.vevent a{ - font-weight:normal; +.vevent a { + font-weight: normal; } /* end of common */ - /* menu */ -#calcms_menu{ - clear:both; - text-align:left; +#calcms_menu { + clear: both; + text-align: left; } -#calcms_menu .date{ - margin:0.5em; - font-weight:bold; +#calcms_menu .date { + margin: 0.5em; + font-weight: bold; } -#calcms_menu div.event{ - padding:0.5em; +#calcms_menu div.event { + padding: 0.5em; } -#calcms_menu div.icon{ - width:25px; - margin-right:1em; - float:left; +#calcms_menu div.icon { + width: 25px; + margin-right: 1em; + float: left; } -#calcms_menu img{ - border:1px solid #ccc; - width:25px; - height:25px; +#calcms_menu img { + border: 1px solid #ccc; + width: 25px; + height: 25px; } -#calcms_menu .title{ - padding:0; - margin:0; - line-height:120%; +#calcms_menu .title { + padding: 0; + margin: 0; + line-height: 120%; } -#calcms_menu .event.running{ - font-weight:bold; +#calcms_menu .event.running { + font-weight: bold; } -#calcms_menu a:hover{ - text-decoration:none; +#calcms_menu a:hover { + text-decoration: none; } #calcms_menu .event { transition: all .1s ease-in-out; } +.event .excerpt { + transition: all .2s ease-in-out; +} + +a.load-prev, a.load-next{ + text-align:center; + cursor:pointer; + display:block ruby; + background:#eee; + padding:0.5rem; +} + #calcms_menu .event:hover { background: #e6e6e6; } - /* coming events*/ -#calcms_playlist{ - clear:both; - text-align:left; +#calcms_playlist { + clear: both; + text-align: left; } -#calcms_playlist div.event{ - padding:0.5em; +#calcms_playlist div.event { + padding: 0.5em; } -#calcms_playlist div.icon{ - width:25px; - margin-right:1em; - float:left; +#calcms_playlist div.icon { + width: 25px; + margin-right: 1em; + float: left; } -#calcms_playlist img{ - width:25px; - height:25px; - border:1px solid #ccc; +#calcms_playlist img { + width: 25px; + height: 25px; + border: 1px solid #ccc; } -#calcms_playlist .title{ - padding:0; - margin:0; - text-align:left; - line-height:120%; +#calcms_playlist .title { + padding: 0; + margin: 0; + text-align: left; + line-height: 120%; } -#calcms_playlist a:hover{ - text-decoration:none; +#calcms_playlist a:hover { + text-decoration: none; } -#calcms_playlist .event{ +#calcms_playlist .event { transition: all .1s ease-in-out; } @@ -119,582 +186,710 @@ a{ background: #e6e6e6; } - /* calcms list */ - -#calcms_list{ - hyphens:auto; +#calcms_list { + hyphens: auto; } -#content div a img{ - margin:6px; +#content div a img { + margin: 6px; } -#content li{ - margin-left:1.7rem; +#content li { + margin-left: 1.7rem; } -#calcms_list .date{ - font-weight:bold; -} - -#calcms_list .excerpt{ - margin-left:3rem; - margin-top:6px; - max-height:5em; - overflow: hidden; - text-overflow: ellipsis; -} - -#calcms_list .event.running, -#calcms_list .event.running a{ - color:#fff; - background:#aaa; -} - -#calcms_list .comments.submitted{ - font-weight:bold; -} - -#calcms_list .submitted{ - margin-left:3.2rem; -} - -#calcms_list .title{ - margin-bottom:1em; - font-weight:bold; -} - -#calcms_list .content img{ - text-align:left; - font-size:1.5em; - margin-bottom:20px; - border:0; - float: right; - margin-left: 1em; -} - -#calcms_list .event{ - padding:1rem; - padding-right:0.5rem; - border-bottom:1rem solid #fff; +#calcms_list .event { + display: flex; + flex-direction: row; + width: 100%; + justify-content: space-between; hyphens: none; - cursor:pointer; - background:#eee; - color:#666; - max-height:8rem; - overflow:hidden; - text-overflow: ellipsis; + cursor: pointer; + overflow: hidden; + text-overflow: ellipsis; + transition: all .1s ease-in-out; } +#calcms_list .event:hover { + background: rgba(200, 200, 200, 0.2); +} -#calcms_list hr{ - margin:1em 0; +#calcms_list h1, +#calcms_list h2, +#calcms_list h3, +#calcms_list h4 { + display: inline; +} +#calcms_list a:hover, +#calcms_list a:focus, +#calcms_list a:active { + color:none; +} + +#calcms_list .date { + font-weight: bold; +} + +#calcms_list .icon { + width:20%; + padding: 1rem; + text-align: center; + text-align:left; +} + +#calcms_list .time { + width: 5%; + min-width: 5rem; + padding: 1rem; + padding-left: 0.5rem; + padding-right: 0; + text-align: center; + font-size: 1.1rem; + text-align:left; +} + +#calcms_list .summary { + width: 80%; + padding: 1rem; + padding-left: 0; + padding-right: 0; + hyphens: auto; +} + +#calcms_list .title { + font-weight: bold; + hyphens: auto; +} + +#calcms_list .title a { + font-weight: bold; +} + +#calcms_list .time{ + font-size: 1.2rem; +} +#calcms_list .summary a, +#calcms_list .time { + line-height: 1.8rem; +} + +#calcms_list .location { + width: 15%; + padding: 1rem; + font-weight: 100; + text-align: center; + font-size: 1.0rem; + opacity:0.5; + display:inline-flex; + align-items:center; +} + +#calcms_list .excerpt { + opacity:0.7; +} + +@media all and (max-width: 959px) { + #calcms_list .summary { + width: 90%; + } + #calcms_list .location { + width: 0; + display: none; + } +} + +@media all and (max-width: 800px) { + #calcms_list .excerpt { + width: 0; + display: none; + } + #calcms_list .location { + width: 0; + display: none; + } +} +@media all and (max-width: 600px) { + #calcms_list .excerpt { + width: 0; + display: none; + } + #calcms_list .location { + width: 0; + display: none; + } + #calcms_list .subtitle { + width: 0; + display: none; + } + #calcms_list .icon { + width: 0; + display: none; + } +} + +#calcms_list .event.running:hover { + opacity: 0.9; +} + +#calcms_list .event.running, +#calcms_list .event.running .excerpt, +#calcms_list .event.running .location, +#calcms_list .event.running a { + color: #fff; + background: #007acc; +} + +#calcms_list .comments.submitted { + font-weight: bold; +} + +#calcms_list h2 { + clear: none !important; +} + +#calcms_list .content img { + border: 0; +} + +#calcms_list .icon img { + width:100%; + height:auto; +} + +#calcms_list .content figure { + float: right; + margin: 3vw; + width:33%; + display:inline-block; +} + +#calcms_list .content figcaption { + font-size: 12px; + margin-left: 1em; + max-width: 12em; +} + +#calcms_list hr { + margin: 1em 0; background: #ccc; } -#calcms_list tbody{ - border:0; +#calcms_list tbody { + border: 0; } -#icon_bar{ - text-align:right; - padding:1 em; +#icon_bar { + text-align: right; + padding: 1 em; } #icon_bar a { - padding:1em; - float:left; + padding: 1em; + float: left; } /* slider */ -#coming_shows{ - white-space:nowrap; - height:120px; +#coming_shows { + white-space: nowrap; + height: 120px; } -#calcms_list #playlist_container{ - overflow:hidden; - height:120px; - padding:10px; +#calcms_list #playlist_container { + overflow: hidden; + height: 120px; + padding: 10px; } -#calcms_list #playlist_container .event{ - padding:0; - margin:0; - overflow:hidden; +#calcms_list #playlist_container .event { + padding: 0; + margin: 0; + overflow: hidden; } -#calcms_list #playlist_container a{ - padding:0; - margin:0; - overflow:hidden; - width:100px; - height:100px; - box-sizing:border-box; +#calcms_list #playlist_container a { + padding: 0; + margin: 0; + overflow: hidden; + width: 100px; + height: 100px; + box-sizing: border-box; } -#playlist_container .event div.bottom{ - max-height:70px; - font-size:12px; - padding:6px; - white-space:wrap; - text-overflow: ellipsis; +#playlist_container .event div.bottom { + max-height: 70px; + font-size: 12px; + padding: 6px; + white-space: wrap; + text-overflow: ellipsis; } #coming_shows .eventContainer { - display:inline-block; - vertical-align:top; - text-align:center; - cursor:pointer; - width:100px; - height:100px; -} -#coming_shows .eventContainer:hover { - background:#eeeeee; -} -#coming_shows a:hover { - text-decoration:none; + display: inline-block; + vertical-align: top; + text-align: center; + cursor: pointer; + width: 100px; + height: 100px; } -#coming_shows div.event{ - position:relative; - width:100px; - height:100px; +#coming_shows .eventContainer:hover { + background: #eeeeee; +} + +#coming_shows a:hover { + text-decoration: none; +} + +#coming_shows div.event { + position: relative; + width: 100px; + height: 100px; background-repeat: no-repeat; background-position: center center; - background-size: cover; + background-size: cover; } -#coming_shows div.event .top, -#coming_shows div.event .bottom{ - position:absolute; - background:#222; - color:#fff; - opacity:0.8; - width:100%; + +#coming_shows div.event .top, +#coming_shows div.event .bottom { + position: absolute; + background: #222; + color: #fff; + opacity: 0.8; + width: 100%; } + #coming_shows div.event .top:hover, -#coming_shows div.event .bottom:hover{ - opacity:1; +#coming_shows div.event .bottom:hover + { + opacity: 1; } -#coming_shows div.event .top{ - top:0; +#coming_shows div.event .top { + top: 0; } -#coming_shows div.event .bottom{ - bottom:0; +#coming_shows div.event .bottom { + bottom: 0; } -#coming_shows div.event{ +#coming_shows div.event { transition: all .2s ease-in-out; } -#coming_shows div.event:hover{ +#coming_shows div.event:hover { transform: scale(1.05); } - /* calcms comments */ -#calcms_comments{ - clear:both; +#calcms_comments { + clear: both; } - -#calcms_comments .author{ - color:#666; - font-weight:bold; - float:left; +#calcms_comments .author { + color: #666; + font-weight: bold; + float: left; } -#calcms_comments .date{ - color:#888; - font-weight:normal; - margin:0; - padding:0; +#calcms_comments .date { + color: #888; + font-weight: normal; + margin: 0; + padding: 0; } -#calcms_comments .content{ - font-weight:normal; +#calcms_comments .content { + font-weight: normal; } -#calcms_comments .comment{ +#calcms_comments .comment { + } -#calcms_comments .level0{ - margin-left:00px; -} -#calcms_comments .level1{ - margin-left:20px; -} -#calcms_comments .level2{ - margin-left:40px; -} -#calcms_comments .level3{ - margin-left:60px; -} -#calcms_comments .level4{ - margin-left:80px; -} -#calcms_comments .level5{ - margin-left:100px; -} -#calcms_comments .level6{ - margin-left:120px; -} -#calcms_comments .level7{ - margin-left:140px; -} -#calcms_comments .level8{ - margin-left:160px; -} -#calcms_comments .level9{ - margin-left:180px; -} -#calcms_comments .level10{ - margin-left:200px; +#calcms_comments .level0 { + margin-left: 00px; } -#calcms_add_comment{ - visibility:hidden; - display:none; +#calcms_comments .level1 { + margin-left: 20px; +} + +#calcms_comments .level2 { + margin-left: 40px; +} + +#calcms_comments .level3 { + margin-left: 60px; +} + +#calcms_comments .level4 { + margin-left: 80px; +} + +#calcms_comments .level5 { + margin-left: 100px; +} + +#calcms_comments .level6 { + margin-left: 120px; +} + +#calcms_comments .level7 { + margin-left: 140px; +} + +#calcms_comments .level8 { + margin-left: 160px; +} + +#calcms_comments .level9 { + margin-left: 180px; +} + +#calcms_comments .level10 { + margin-left: 200px; +} + +#calcms_add_comment { + visibility: hidden; + display: none; } /* calcms add comment */ #calcms_comments input, -#calcms_comments textarea{ +#calcms_comments textarea { appearance: none; -moz-appearance: none; -webkit-appearance: none; - box-sizing:border-box; - width:80%; - padding:6px; - margin:6px; - margin-left:0; - border-radius:3px; - border:1px solid #ccc; - box-shadow: 2px 2px 2px rgba(0,0,0,0.1); + box-sizing: border-box; + width: 80%; + padding: 6px; + margin: 6px; + margin-left: 0; + border-radius: 3px; + border: 1px solid #ccc; + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.1); } -#calcms_comments input{ - max-width:20em; - height:32px; +#calcms_comments input { + max-width: 40rem; + height: 32px; } -#calcms_comments input[type=submit]{ - max-width:10em; - background:#ddd; +#calcms_comments input[type=submit] { + max-width: 10rem; + background: #ddd; } -#calcms_comments input[type="submit"]:hover{ - cursor:pointer; - background:#eee; - border:1px solid #aaa; +#calcms_comments input[type="submit"]:hover { + cursor: pointer; + background: #eee; + border: 1px solid #aaa; } -#calcms_comments textarea{ - height:10em; - width:40em; +#calcms_comments textarea { + height: 10em; + width: 40em; } /* calcms comment list */ -#calcms_newest_comments .author{ - font-weight:bold; +#calcms_newest_comments .author { + font-weight: bold; } -#calcms_newest_comments div{ - padding-left:1em; - padding-bottom:1em; +#calcms_newest_comments div { + padding-left: 1rem; + padding-bottom: 0.5rem; + padding-top: 0.5rem; } -#calcms_newest_comments a:hover{ - text-decoration:none; +#calcms_newest_comments a:hover { + text-decoration: none; } -#calcms_newest_comments span.content{ - text-overflow: ellipsis; +#calcms_newest_comments span.content { + text-overflow: ellipsis; } -#calcms_newest_comments .comments{ +#calcms_newest_comments .comments { transition: all .1s ease-in-out; } -#calcms_newest_comments .comments:hover{ +#calcms_newest_comments .comments:hover { background: #e6e6e6; } /* end of calcms comments*/ /* calcms_search */ -#calcms_search{ - margin:0; - padding:0; - z-index:3; - text-align:left; - clear:both; - text-align:center; +#calcms_search { + margin: 0; + padding: 0; + z-index: 3; + text-align: left; + clear: both; + text-align: center; } #calcms_search input, -#calcms_search select{ +#calcms_search select { appearance: none; -moz-appearance: none; -webkit-appearance: none; - box-sizing:border-box; - width:80%; - padding:6px; - margin:6px; - margin-left:0; - border-radius:3px; - border:1px solid #ccc; - box-shadow: 2px 2px 2px rgba(0,0,0,0.1); - height:32px; + box-sizing: border-box; + width: 80%; + padding: 6px; + margin: 6px; + margin-left: 0; + border-radius: 3px; + border: 1px solid #ccc; + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.1); + height: 32px; } -#calcms_search select{ +#calcms_search select { background: white; background-image: url("/agenda/image/select.png"); background-position: right center; background-repeat: no-repeat; } -#calcms_search input[type="checkbox"]{ +#calcms_search input[type="checkbox"] { background: none; - width:1em; - height:1em; - border:1px solid #ccc; - display:inline-block; - box-shadow:0 1px 1px 0 rgba(0, 0, 0, 0.1) inset; + width: 1rem; + height: 1rem; + border: 1px solid #ccc; + display: inline-block; + box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1) inset; content: " "; - margin-right:1em; + margin-right: 1rem; } -#calcms_search input[type="button"]{ - background: none; - width:50%; +#calcms_search input[type="button"] { + background: #1987d1; + width: 50%; } -#calcms_search input[type="button"]:hover{ - cursor:pointer; - background:#eee; - border:1px solid #aaa; +#calcms_search input[type="button"]:hover { + cursor: pointer; + background: #eee; + border: 1px solid #aaa; } - -#calcms_search input{} -#calcms_search input#calcms_search_field{} -#calcms_search a#calcms_search_show_details{ - padding-left:1em; - display:block; +#calcms_search a#calcms_search_show_details { + padding-left: 1rem; + display: block; } -a#calcms_search_show_details #plus{ - font-size:16px; +a#calcms_search_show_details #plus { + font-size: 16px; } /* end of calcms_search */ - /* calcms_calendar */ -#calcms_calendar{ - overflow:hidden; - text-align:center; - padding:0; - margin:0; - vertical-align:top; - clear:both; +#calcms_calendar { + overflow: hidden; + text-align: center; + padding: 0; + margin: 0; + vertical-align: top; + clear: both; } -#calcms_calendar table{ - padding:0; - margin:0; - background:#fff; - border:0px solid #ddd; - border-collapse:collapse; - text-align:center; +#calcms_calendar table { + padding: 0; + margin: 0; + background: #fff; + border: 0px solid #ddd; + border-collapse: collapse; + text-align: center; } #calcms_calendar table thead a:hover, #calcms_calendar table thead a:link, -#calcms_calendar table thead a:visited{ - color:#333; - padding:0; - text-decoration:none; - font-weight:normal; -} - +#calcms_calendar table thead a:visited, #calcms_calendar table tbody a:hover, #calcms_calendar table tbody a:link, -#calcms_calendar table tbody a:visited{ - color:#333; - padding:5px; - padding-top:2px; - padding-bottom:3px; - text-decoration:none; - font-weight:normal; +#calcms_calendar table tbody a:visited { + color: #333; + padding: 5px; + text-decoration: none; + font-weight: normal; + display:block; } #calcms_calendar table td, -#calcms_calendar table th{ - padding:0; - margin:0; - border:0; - text-align:center; - font-weight:normal; - border-bottom:1px solid #ddd; +#calcms_calendar table th { + padding: 0; + margin: 0; + border: 0; + text-align: center; + font-weight: normal; + border-bottom: 1px solid #ddd; transition: all .1s ease-in-out; - padding-top:2%; - padding-bottom:2%; } #calcms_calendar table thead td:hover, #calcms_calendar table thead th:hover{ - background-color:#ddd; + background-color: #1987d1; } /* header */ #calcms_calendar table th.first, -#calcms_calendar table th.last{ - font-size:large; +#calcms_calendar table th.last { + font-size: large; } /* month selector */ -#calcms_calendar table thead tr:first-child a{ - padding:6px; +#calcms_calendar table thead tr:first-child a { + padding: 6px; + color: white; } -#calcms_calendar table thead tr:first-child{ - background:#ccc; +#calcms_calendar table thead tr:first-child { + background: #007acc; } /* weekdays */ #calcms_calendar table thead tr:nth-child(2) { - background:#eee; + background: #eee; } /* week numbers */ #calcms_calendar table tbody tr:first-child th:first-child, -#calcms_calendar table tbody tr th:first-child a{ - color:#aaa; +#calcms_calendar table tbody tr th:first-child a { + color: #aaa; } #calcms_calendar table tbody td:hover, -#calcms_calendar table tbody th:hover{ - background-color:#f0f0f0; +#calcms_calendar table tbody th:hover { + background-color: #4f7acc; } -#calcms_calendar table td.selected{ - background:#eee; - font-weight:bold; +#calcms_calendar table tbody td.calcms_today, +#calcms_calendar table tbody td.calcms_today a { + background: #007acc; + color: white; } -#calcms_calendar table td.selected:hover{ - background-color:#ddd; +#calcms_calendar table td.selected { + background: #eee; + font-weight: bold; } -#calcms_calendar table td.other_month a{ - opacity:0.3; +#calcms_calendar table td.selected:hover { + background-color: #ddd; } +#calcms_calendar table td.other_month a { + opacity: 0.3; +} +#player { + border: 0; + padding: 0; + height: 5rem; +} -/* player */ -#player{ - border:0; - padding:0; - height:26px; - width:180px; - overflow:hidden; +#player:hover { + opacity: 0.9; } /* mobile menu */ - -#mobileMenuButton{ - display:block; - position:fixed; - z-index:99; - right:6px; - top:3px; - font-size:1.5em; - padding:1em; - line-height:1em; - background:#ddd; - color:#000; - font-weight:bold; +#mobileMenuButton { + display: block; + position: fixed; + z-index: 99; + right: 6px; + top: 3px; + font-size: 1.5rem; + padding: 1rem; + line-height: 1rem; + background: #ddd; + color: #000; + font-weight: bold; cursor: pointer; - background:#ccc; - background:linear-gradient(to bottom, #333 0%, #333 20%, #bbb 20%, #bbb 40%, #333 40%, #333 60%, #bbb 60%, #bbb 80%, #333 80%, #333 100%); - border:0.4em solid #bbb; - border-radius:6px; - transition:all 0.2s ease-in-out 0s; + background: #ccc; + background: linear-gradient(to bottom, #333 0%, #333 20%, #bbb 20%, #bbb 40%, #333 + 40%, #333 60%, #bbb 60%, #bbb 80%, #333 80%, #333 100%); + border: 0.4rem solid #bbb; + border-radius: 6px; + transition: all 0.2s ease-in-out 0s; } -#mobileMenuButton:hover{ + +#mobileMenuButton:hover { transform: scale(1.05); } -ul.mobileMenu{ - position:fixed; - top:0px; - background:#333!important; - width:100%; +ul.mobileMenu { + position: fixed; + top: 0px; + background: #333 !important; + width: 100%; } -ul.mobileMenu li, -ul.mobileMenu li a{ - float:none!important; - background:#444!important; - display:block; - text-align:center; - font-size:1.3em; - padding:0.5em!important; - line-height:1em; - z-index:99; - margin-bottom:1px; - width:80%; +ul.mobileMenu li, +ul.mobileMenu li a { + float: none !important; + background: #444 !important; + display: block; + text-align: center; + font-size: 1.3em; + padding: 0.5em !important; + line-height: 1em; + z-index: 99; + margin-bottom: 1px; + width: 80%; } -ul.mobileMenu a, -ul.mobileMenu a:link, -ul.mobileMenu a:hover, -ul.mobileMenu a:visited{ - background-image:url()!important; - background:#444!important; - width:80%; +ul.mobileMenu a, +ul.mobileMenu a:link, +ul.mobileMenu a:hover, +ul.mobileMenu a:visited { + background-image: url() !important; + background: #444 !important; + width: 80%; } -ul.mobileMenu li:hover, -ul.mobileMenu li:hover a{ - background:#999!important; - transition:all 0.2s ease; - +ul.mobileMenu li:hover, +ul.mobileMenu li:hover a { + background: #999 !important; + transition: all 0.2s ease; } -ul.mobileMenu li a:hover{ - text-decoration:none!important; +ul.mobileMenu li a:hover { + text-decoration: none !important; } -#footer .content a{ - padding:0.5em; - line-height:2em; +#footer .content a { + padding: 0.5em; + line-height: 2em; } -/* -pre{ - text-align:left; - font-family:Courier; - padding:1em; - margin:1em; - border:1px solid black; +#listen_radio { + width: 100%; + text-align: left; } -div.update{ - position:absolute; - bottom:0px; +#listen_radio iframe { + margin-top: 1em; + max-width: none; } -div.update, div.update a{ - text-align:left; - font-size:6px; - color:#bbb; +#listen_radio td { + border: 0; +} + +div#content header h1.entry-title { + margin-bottom: 0; +} + +@media screen and (min-width: 61.5625em) { + .site-header { + padding: 3rem; + padding-top: 1rem; + padding-bottom: 0rem; + } } -*/ diff --git a/website/agenda/css/calcms_drupal.css b/website/agenda/css/calcms_drupal.css deleted file mode 100644 index ea46d40..0000000 --- a/website/agenda/css/calcms_drupal.css +++ /dev/null @@ -1,42 +0,0 @@ -/* - - This css is to be included at drupal's programm page type only. - It disables drupal's search block, since calcms needs to use its own. - -*/ - -#search-theme-form { - display: none; - visibility:hidden; -} - -.content ul li, -.content ul.menu li, -.content .item-list ul li, -.content li.leaf{ - margin:-0.15em 0 -0.15em -0.4em - } - -.content ul li{ - clear:both; -} - - -.content ul ul { - margin-left:20px; -} - -.content ul ul ul { - margin-left:40px; -} - -.content ul ul ul ul { - margin-left:60px; -} - - - -#calcms_menu a:hover, -#calcms_calendar a:hover{ - text-decoration:underline; -} diff --git a/website/agenda/css/jquery-ui.css b/website/agenda/css/jquery-ui.css deleted file mode 100644 index 334bea3..0000000 --- a/website/agenda/css/jquery-ui.css +++ /dev/null @@ -1,1225 +0,0 @@ -/*! jQuery UI - v1.11.4 - 2015-10-09 -* http://jqueryui.com -* Includes: core.css, draggable.css, resizable.css, selectable.css, sortable.css, accordion.css, autocomplete.css, button.css, datepicker.css, dialog.css, menu.css, progressbar.css, selectmenu.css, slider.css, spinner.css, tabs.css, tooltip.css, theme.css -* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2CArial%2Csans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=highlight_soft&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=flat&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=glass&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=glass&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px -* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */ - -/* Layout helpers -----------------------------------*/ -.ui-helper-hidden { - display: none; -} -.ui-helper-hidden-accessible { - border: 0; - clip: rect(0 0 0 0); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - width: 1px; -} -.ui-helper-reset { - margin: 0; - padding: 0; - border: 0; - outline: 0; - line-height: 1.3; - text-decoration: none; - font-size: 100%; - list-style: none; -} -.ui-helper-clearfix:before, -.ui-helper-clearfix:after { - content: ""; - display: table; - border-collapse: collapse; -} -.ui-helper-clearfix:after { - clear: both; -} -.ui-helper-clearfix { - min-height: 0; /* support: IE7 */ -} -.ui-helper-zfix { - width: 100%; - height: 100%; - top: 0; - left: 0; - position: absolute; - opacity: 0; - filter:Alpha(Opacity=0); /* support: IE8 */ -} - -.ui-front { - z-index: 100; -} - - -/* Interaction Cues -----------------------------------*/ -.ui-state-disabled { - cursor: default !important; -} - - -/* Icons -----------------------------------*/ - -/* states and images */ -.ui-icon { - display: block; - text-indent: -99999px; - overflow: hidden; - background-repeat: no-repeat; -} - - -/* Misc visuals -----------------------------------*/ - -/* Overlays */ -.ui-widget-overlay { - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; -} -.ui-draggable-handle { - -ms-touch-action: none; - touch-action: none; -} -.ui-resizable { - position: relative; -} -.ui-resizable-handle { - position: absolute; - font-size: 0.1px; - display: block; - -ms-touch-action: none; - touch-action: none; -} -.ui-resizable-disabled .ui-resizable-handle, -.ui-resizable-autohide .ui-resizable-handle { - display: none; -} -.ui-resizable-n { - cursor: n-resize; - height: 7px; - width: 100%; - top: -5px; - left: 0; -} -.ui-resizable-s { - cursor: s-resize; - height: 7px; - width: 100%; - bottom: -5px; - left: 0; -} -.ui-resizable-e { - cursor: e-resize; - width: 7px; - right: -5px; - top: 0; - height: 100%; -} -.ui-resizable-w { - cursor: w-resize; - width: 7px; - left: -5px; - top: 0; - height: 100%; -} -.ui-resizable-se { - cursor: se-resize; - width: 12px; - height: 12px; - right: 1px; - bottom: 1px; -} -.ui-resizable-sw { - cursor: sw-resize; - width: 9px; - height: 9px; - left: -5px; - bottom: -5px; -} -.ui-resizable-nw { - cursor: nw-resize; - width: 9px; - height: 9px; - left: -5px; - top: -5px; -} -.ui-resizable-ne { - cursor: ne-resize; - width: 9px; - height: 9px; - right: -5px; - top: -5px; -} -.ui-selectable { - -ms-touch-action: none; - touch-action: none; -} -.ui-selectable-helper { - position: absolute; - z-index: 100; - border: 1px dotted black; -} -.ui-sortable-handle { - -ms-touch-action: none; - touch-action: none; -} -.ui-accordion .ui-accordion-header { - display: block; - cursor: pointer; - position: relative; - margin: 2px 0 0 0; - padding: .5em .5em .5em .7em; - min-height: 0; /* support: IE7 */ - font-size: 100%; -} -.ui-accordion .ui-accordion-icons { - padding-left: 2.2em; -} -.ui-accordion .ui-accordion-icons .ui-accordion-icons { - padding-left: 2.2em; -} -.ui-accordion .ui-accordion-header .ui-accordion-header-icon { - position: absolute; - left: .5em; - top: 50%; - margin-top: -8px; -} -.ui-accordion .ui-accordion-content { - padding: 1em 2.2em; - border-top: 0; - overflow: auto; -} -.ui-autocomplete { - position: absolute; - top: 0; - left: 0; - cursor: default; -} -.ui-button { - display: inline-block; - position: relative; - padding: 0; - line-height: normal; - margin-right: .1em; - cursor: pointer; - vertical-align: middle; - text-align: center; - overflow: visible; /* removes extra width in IE */ -} -.ui-button, -.ui-button:link, -.ui-button:visited, -.ui-button:hover, -.ui-button:active { - text-decoration: none; -} -/* to make room for the icon, a width needs to be set here */ -.ui-button-icon-only { - width: 2.2em; -} -/* button elements seem to need a little more width */ -button.ui-button-icon-only { - width: 2.4em; -} -.ui-button-icons-only { - width: 3.4em; -} -button.ui-button-icons-only { - width: 3.7em; -} - -/* button text element */ -.ui-button .ui-button-text { - display: block; - line-height: normal; -} -.ui-button-text-only .ui-button-text { - padding: .4em 1em; -} -.ui-button-icon-only .ui-button-text, -.ui-button-icons-only .ui-button-text { - padding: .4em; - text-indent: -9999999px; -} -.ui-button-text-icon-primary .ui-button-text, -.ui-button-text-icons .ui-button-text { - padding: .4em 1em .4em 2.1em; -} -.ui-button-text-icon-secondary .ui-button-text, -.ui-button-text-icons .ui-button-text { - padding: .4em 2.1em .4em 1em; -} -.ui-button-text-icons .ui-button-text { - padding-left: 2.1em; - padding-right: 2.1em; -} -/* no icon support for input elements, provide padding by default */ -input.ui-button { - padding: .4em 1em; -} - -/* button icon element(s) */ -.ui-button-icon-only .ui-icon, -.ui-button-text-icon-primary .ui-icon, -.ui-button-text-icon-secondary .ui-icon, -.ui-button-text-icons .ui-icon, -.ui-button-icons-only .ui-icon { - position: absolute; - top: 50%; - margin-top: -8px; -} -.ui-button-icon-only .ui-icon { - left: 50%; - margin-left: -8px; -} -.ui-button-text-icon-primary .ui-button-icon-primary, -.ui-button-text-icons .ui-button-icon-primary, -.ui-button-icons-only .ui-button-icon-primary { - left: .5em; -} -.ui-button-text-icon-secondary .ui-button-icon-secondary, -.ui-button-text-icons .ui-button-icon-secondary, -.ui-button-icons-only .ui-button-icon-secondary { - right: .5em; -} - -/* button sets */ -.ui-buttonset { - margin-right: 7px; -} -.ui-buttonset .ui-button { - margin-left: 0; - margin-right: -.3em; -} - -/* workarounds */ -/* reset extra padding in Firefox, see h5bp.com/l */ -input.ui-button::-moz-focus-inner, -button.ui-button::-moz-focus-inner { - border: 0; - padding: 0; -} -.ui-datepicker { - width: 17em; - padding: .2em .2em 0; - display: none; -} -.ui-datepicker .ui-datepicker-header { - position: relative; - padding: .2em 0; -} -.ui-datepicker .ui-datepicker-prev, -.ui-datepicker .ui-datepicker-next { - position: absolute; - top: 2px; - width: 1.8em; - height: 1.8em; -} -.ui-datepicker .ui-datepicker-prev-hover, -.ui-datepicker .ui-datepicker-next-hover { - top: 1px; -} -.ui-datepicker .ui-datepicker-prev { - left: 2px; -} -.ui-datepicker .ui-datepicker-next { - right: 2px; -} -.ui-datepicker .ui-datepicker-prev-hover { - left: 1px; -} -.ui-datepicker .ui-datepicker-next-hover { - right: 1px; -} -.ui-datepicker .ui-datepicker-prev span, -.ui-datepicker .ui-datepicker-next span { - display: block; - position: absolute; - left: 50%; - margin-left: -8px; - top: 50%; - margin-top: -8px; -} -.ui-datepicker .ui-datepicker-title { - margin: 0 2.3em; - line-height: 1.8em; - text-align: center; -} -.ui-datepicker .ui-datepicker-title select { - font-size: 1em; - margin: 1px 0; -} -.ui-datepicker select.ui-datepicker-month, -.ui-datepicker select.ui-datepicker-year { - width: 45%; -} -.ui-datepicker table { - width: 100%; - font-size: .9em; - border-collapse: collapse; - margin: 0 0 .4em; -} -.ui-datepicker th { - padding: .7em .3em; - text-align: center; - font-weight: bold; - border: 0; -} -.ui-datepicker td { - border: 0; - padding: 1px; -} -.ui-datepicker td span, -.ui-datepicker td a { - display: block; - padding: .2em; - text-align: right; - text-decoration: none; -} -.ui-datepicker .ui-datepicker-buttonpane { - background-image: none; - margin: .7em 0 0 0; - padding: 0 .2em; - border-left: 0; - border-right: 0; - border-bottom: 0; -} -.ui-datepicker .ui-datepicker-buttonpane button { - float: right; - margin: .5em .2em .4em; - cursor: pointer; - padding: .2em .6em .3em .6em; - width: auto; - overflow: visible; -} -.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { - float: left; -} - -/* with multiple calendars */ -.ui-datepicker.ui-datepicker-multi { - width: auto; -} -.ui-datepicker-multi .ui-datepicker-group { - float: left; -} -.ui-datepicker-multi .ui-datepicker-group table { - width: 95%; - margin: 0 auto .4em; -} -.ui-datepicker-multi-2 .ui-datepicker-group { - width: 50%; -} -.ui-datepicker-multi-3 .ui-datepicker-group { - width: 33.3%; -} -.ui-datepicker-multi-4 .ui-datepicker-group { - width: 25%; -} -.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header, -.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { - border-left-width: 0; -} -.ui-datepicker-multi .ui-datepicker-buttonpane { - clear: left; -} -.ui-datepicker-row-break { - clear: both; - width: 100%; - font-size: 0; -} - -/* RTL support */ -.ui-datepicker-rtl { - direction: rtl; -} -.ui-datepicker-rtl .ui-datepicker-prev { - right: 2px; - left: auto; -} -.ui-datepicker-rtl .ui-datepicker-next { - left: 2px; - right: auto; -} -.ui-datepicker-rtl .ui-datepicker-prev:hover { - right: 1px; - left: auto; -} -.ui-datepicker-rtl .ui-datepicker-next:hover { - left: 1px; - right: auto; -} -.ui-datepicker-rtl .ui-datepicker-buttonpane { - clear: right; -} -.ui-datepicker-rtl .ui-datepicker-buttonpane button { - float: left; -} -.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current, -.ui-datepicker-rtl .ui-datepicker-group { - float: right; -} -.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header, -.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { - border-right-width: 0; - border-left-width: 1px; -} -.ui-dialog { - overflow: hidden; - position: absolute; - top: 0; - left: 0; - padding: .2em; - outline: 0; -} -.ui-dialog .ui-dialog-titlebar { - padding: .4em 1em; - position: relative; -} -.ui-dialog .ui-dialog-title { - float: left; - margin: .1em 0; - white-space: nowrap; - width: 90%; - overflow: hidden; - text-overflow: ellipsis; -} -.ui-dialog .ui-dialog-titlebar-close { - position: absolute; - right: .3em; - top: 50%; - width: 20px; - margin: -10px 0 0 0; - padding: 1px; - height: 20px; -} -.ui-dialog .ui-dialog-content { - position: relative; - border: 0; - padding: .5em 1em; - background: none; - overflow: auto; -} -.ui-dialog .ui-dialog-buttonpane { - text-align: left; - border-width: 1px 0 0 0; - background-image: none; - margin-top: .5em; - padding: .3em 1em .5em .4em; -} -.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { - float: right; -} -.ui-dialog .ui-dialog-buttonpane button { - margin: .5em .4em .5em 0; - cursor: pointer; -} -.ui-dialog .ui-resizable-se { - width: 12px; - height: 12px; - right: -5px; - bottom: -5px; - background-position: 16px 16px; -} -.ui-draggable .ui-dialog-titlebar { - cursor: move; -} -.ui-menu { - list-style: none; - padding: 0; - margin: 0; - display: block; - outline: none; -} -.ui-menu .ui-menu { - position: absolute; -} -.ui-menu .ui-menu-item { - position: relative; - margin: 0; - padding: 3px 1em 3px .4em; - cursor: pointer; - min-height: 0; /* support: IE7 */ - /* support: IE10, see #8844 */ - list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"); -} -.ui-menu .ui-menu-divider { - margin: 5px 0; - height: 0; - font-size: 0; - line-height: 0; - border-width: 1px 0 0 0; -} -.ui-menu .ui-state-focus, -.ui-menu .ui-state-active { - margin: -1px; -} - -/* icon support */ -.ui-menu-icons { - position: relative; -} -.ui-menu-icons .ui-menu-item { - padding-left: 2em; -} - -/* left-aligned */ -.ui-menu .ui-icon { - position: absolute; - top: 0; - bottom: 0; - left: .2em; - margin: auto 0; -} - -/* right-aligned */ -.ui-menu .ui-menu-icon { - left: auto; - right: 0; -} -.ui-progressbar { - height: 2em; - text-align: left; - overflow: hidden; -} -.ui-progressbar .ui-progressbar-value { - margin: -1px; - height: 100%; -} -.ui-progressbar .ui-progressbar-overlay { - background: url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw=="); - height: 100%; - filter: alpha(opacity=25); /* support: IE8 */ - opacity: 0.25; -} -.ui-progressbar-indeterminate .ui-progressbar-value { - background-image: none; -} -.ui-selectmenu-menu { - padding: 0; - margin: 0; - position: absolute; - top: 0; - left: 0; - display: none; -} -.ui-selectmenu-menu .ui-menu { - overflow: auto; - /* Support: IE7 */ - overflow-x: hidden; - padding-bottom: 1px; -} -.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup { - font-size: 1em; - font-weight: bold; - line-height: 1.5; - padding: 2px 0.4em; - margin: 0.5em 0 0 0; - height: auto; - border: 0; -} -.ui-selectmenu-open { - display: block; -} -.ui-selectmenu-button { - display: inline-block; - overflow: hidden; - position: relative; - text-decoration: none; - cursor: pointer; -} -.ui-selectmenu-button span.ui-icon { - right: 0.5em; - left: auto; - margin-top: -8px; - position: absolute; - top: 50%; -} -.ui-selectmenu-button span.ui-selectmenu-text { - text-align: left; - padding: 0.4em 2.1em 0.4em 1em; - display: block; - line-height: 1.4; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} -.ui-slider { - position: relative; - text-align: left; -} -.ui-slider .ui-slider-handle { - position: absolute; - z-index: 2; - width: 1.2em; - height: 1.2em; - cursor: default; - -ms-touch-action: none; - touch-action: none; -} -.ui-slider .ui-slider-range { - position: absolute; - z-index: 1; - font-size: .7em; - display: block; - border: 0; - background-position: 0 0; -} - -/* support: IE8 - See #6727 */ -.ui-slider.ui-state-disabled .ui-slider-handle, -.ui-slider.ui-state-disabled .ui-slider-range { - filter: inherit; -} - -.ui-slider-horizontal { - height: .8em; -} -.ui-slider-horizontal .ui-slider-handle { - top: -.3em; - margin-left: -.6em; -} -.ui-slider-horizontal .ui-slider-range { - top: 0; - height: 100%; -} -.ui-slider-horizontal .ui-slider-range-min { - left: 0; -} -.ui-slider-horizontal .ui-slider-range-max { - right: 0; -} - -.ui-slider-vertical { - width: .8em; - height: 100px; -} -.ui-slider-vertical .ui-slider-handle { - left: -.3em; - margin-left: 0; - margin-bottom: -.6em; -} -.ui-slider-vertical .ui-slider-range { - left: 0; - width: 100%; -} -.ui-slider-vertical .ui-slider-range-min { - bottom: 0; -} -.ui-slider-vertical .ui-slider-range-max { - top: 0; -} -.ui-spinner { - position: relative; - display: inline-block; - overflow: hidden; - padding: 0; - vertical-align: middle; -} -.ui-spinner-input { - border: none; - background: none; - color: inherit; - padding: 0; - margin: .2em 0; - vertical-align: middle; - margin-left: .4em; - margin-right: 22px; -} -.ui-spinner-button { - width: 16px; - height: 50%; - font-size: .5em; - padding: 0; - margin: 0; - text-align: center; - position: absolute; - cursor: default; - display: block; - overflow: hidden; - right: 0; -} -/* more specificity required here to override default borders */ -.ui-spinner a.ui-spinner-button { - border-top: none; - border-bottom: none; - border-right: none; -} -/* vertically center icon */ -.ui-spinner .ui-icon { - position: absolute; - margin-top: -8px; - top: 50%; - left: 0; -} -.ui-spinner-up { - top: 0; -} -.ui-spinner-down { - bottom: 0; -} - -/* TR overrides */ -.ui-spinner .ui-icon-triangle-1-s { - /* need to fix icons sprite */ - background-position: -65px -16px; -} -.ui-tabs { - position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ - padding: .2em; -} -.ui-tabs .ui-tabs-nav { - margin: 0; - padding: .2em .2em 0; -} -.ui-tabs .ui-tabs-nav li { - list-style: none; - float: left; - position: relative; - top: 0; - margin: 1px .2em 0 0; - border-bottom-width: 0; - padding: 0; - white-space: nowrap; -} -.ui-tabs .ui-tabs-nav .ui-tabs-anchor { - float: left; - padding: .5em 1em; - text-decoration: none; -} -.ui-tabs .ui-tabs-nav li.ui-tabs-active { - margin-bottom: -1px; - padding-bottom: 1px; -} -.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor, -.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor, -.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor { - cursor: text; -} -.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor { - cursor: pointer; -} -.ui-tabs .ui-tabs-panel { - display: block; - border-width: 0; - padding: 1em 1.4em; - background: none; -} -.ui-tooltip { - padding: 8px; - position: absolute; - z-index: 9999; - max-width: 300px; - -webkit-box-shadow: 0 0 5px #aaa; - box-shadow: 0 0 5px #aaa; -} -body .ui-tooltip { - border-width: 2px; -} - -/* Component containers -----------------------------------*/ -.ui-widget { - font-family: Verdana,Arial,sans-serif; - font-size: 1.1em; -} -.ui-widget .ui-widget { - font-size: 1em; -} -.ui-widget input, -.ui-widget select, -.ui-widget textarea, -.ui-widget button { - font-family: Verdana,Arial,sans-serif; - font-size: 1em; -} -.ui-widget-content { - border: 1px solid #aaaaaa; - background: #ffffff url("images/ui-bg_flat_75_ffffff_40x100.png") 50% 50% repeat-x; - color: #222222; -} -.ui-widget-content a { - color: #222222; -} -.ui-widget-header { - border: 1px solid #aaaaaa; - background: #cccccc url("images/ui-bg_highlight-soft_75_cccccc_1x100.png") 50% 50% repeat-x; - color: #222222; - font-weight: bold; -} -.ui-widget-header a { - color: #222222; -} - -/* Interaction states -----------------------------------*/ -.ui-state-default, -.ui-widget-content .ui-state-default, -.ui-widget-header .ui-state-default { - border: 1px solid #d3d3d3; - background: #e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x; - font-weight: normal; - color: #555555; -} -.ui-state-default a, -.ui-state-default a:link, -.ui-state-default a:visited { - color: #555555; - text-decoration: none; -} -.ui-state-hover, -.ui-widget-content .ui-state-hover, -.ui-widget-header .ui-state-hover, -.ui-state-focus, -.ui-widget-content .ui-state-focus, -.ui-widget-header .ui-state-focus { - border: 1px solid #999999; - background: #dadada url("images/ui-bg_glass_75_dadada_1x400.png") 50% 50% repeat-x; - font-weight: normal; - color: #212121; -} -.ui-state-hover a, -.ui-state-hover a:hover, -.ui-state-hover a:link, -.ui-state-hover a:visited, -.ui-state-focus a, -.ui-state-focus a:hover, -.ui-state-focus a:link, -.ui-state-focus a:visited { - color: #212121; - text-decoration: none; -} -.ui-state-active, -.ui-widget-content .ui-state-active, -.ui-widget-header .ui-state-active { - border: 1px solid #aaaaaa; - background: #ffffff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x; - font-weight: normal; - color: #212121; -} -.ui-state-active a, -.ui-state-active a:link, -.ui-state-active a:visited { - color: #212121; - text-decoration: none; -} - -/* Interaction Cues -----------------------------------*/ -.ui-state-highlight, -.ui-widget-content .ui-state-highlight, -.ui-widget-header .ui-state-highlight { - border: 1px solid #fcefa1; - background: #fbf9ee url("images/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x; - color: #363636; -} -.ui-state-highlight a, -.ui-widget-content .ui-state-highlight a, -.ui-widget-header .ui-state-highlight a { - color: #363636; -} -.ui-state-error, -.ui-widget-content .ui-state-error, -.ui-widget-header .ui-state-error { - border: 1px solid #cd0a0a; - background: #fef1ec url("images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x; - color: #cd0a0a; -} -.ui-state-error a, -.ui-widget-content .ui-state-error a, -.ui-widget-header .ui-state-error a { - color: #cd0a0a; -} -.ui-state-error-text, -.ui-widget-content .ui-state-error-text, -.ui-widget-header .ui-state-error-text { - color: #cd0a0a; -} -.ui-priority-primary, -.ui-widget-content .ui-priority-primary, -.ui-widget-header .ui-priority-primary { - font-weight: bold; -} -.ui-priority-secondary, -.ui-widget-content .ui-priority-secondary, -.ui-widget-header .ui-priority-secondary { - opacity: .7; - filter:Alpha(Opacity=70); /* support: IE8 */ - font-weight: normal; -} -.ui-state-disabled, -.ui-widget-content .ui-state-disabled, -.ui-widget-header .ui-state-disabled { - opacity: .35; - filter:Alpha(Opacity=35); /* support: IE8 */ - background-image: none; -} -.ui-state-disabled .ui-icon { - filter:Alpha(Opacity=35); /* support: IE8 - See #6059 */ -} - -/* Icons -----------------------------------*/ - -/* states and images */ -.ui-icon { - width: 16px; - height: 16px; -} -.ui-icon, -.ui-widget-content .ui-icon { - background-image: url("images/ui-icons_222222_256x240.png"); -} -.ui-widget-header .ui-icon { - background-image: url("images/ui-icons_222222_256x240.png"); -} -.ui-state-default .ui-icon { - background-image: url("images/ui-icons_888888_256x240.png"); -} -.ui-state-hover .ui-icon, -.ui-state-focus .ui-icon { - background-image: url("images/ui-icons_454545_256x240.png"); -} -.ui-state-active .ui-icon { - background-image: url("images/ui-icons_454545_256x240.png"); -} -.ui-state-highlight .ui-icon { - background-image: url("images/ui-icons_2e83ff_256x240.png"); -} -.ui-state-error .ui-icon, -.ui-state-error-text .ui-icon { - background-image: url("images/ui-icons_cd0a0a_256x240.png"); -} - -/* positioning */ -.ui-icon-blank { background-position: 16px 16px; } -.ui-icon-carat-1-n { background-position: 0 0; } -.ui-icon-carat-1-ne { background-position: -16px 0; } -.ui-icon-carat-1-e { background-position: -32px 0; } -.ui-icon-carat-1-se { background-position: -48px 0; } -.ui-icon-carat-1-s { background-position: -64px 0; } -.ui-icon-carat-1-sw { background-position: -80px 0; } -.ui-icon-carat-1-w { background-position: -96px 0; } -.ui-icon-carat-1-nw { background-position: -112px 0; } -.ui-icon-carat-2-n-s { background-position: -128px 0; } -.ui-icon-carat-2-e-w { background-position: -144px 0; } -.ui-icon-triangle-1-n { background-position: 0 -16px; } -.ui-icon-triangle-1-ne { background-position: -16px -16px; } -.ui-icon-triangle-1-e { background-position: -32px -16px; } -.ui-icon-triangle-1-se { background-position: -48px -16px; } -.ui-icon-triangle-1-s { background-position: -64px -16px; } -.ui-icon-triangle-1-sw { background-position: -80px -16px; } -.ui-icon-triangle-1-w { background-position: -96px -16px; } -.ui-icon-triangle-1-nw { background-position: -112px -16px; } -.ui-icon-triangle-2-n-s { background-position: -128px -16px; } -.ui-icon-triangle-2-e-w { background-position: -144px -16px; } -.ui-icon-arrow-1-n { background-position: 0 -32px; } -.ui-icon-arrow-1-ne { background-position: -16px -32px; } -.ui-icon-arrow-1-e { background-position: -32px -32px; } -.ui-icon-arrow-1-se { background-position: -48px -32px; } -.ui-icon-arrow-1-s { background-position: -64px -32px; } -.ui-icon-arrow-1-sw { background-position: -80px -32px; } -.ui-icon-arrow-1-w { background-position: -96px -32px; } -.ui-icon-arrow-1-nw { background-position: -112px -32px; } -.ui-icon-arrow-2-n-s { background-position: -128px -32px; } -.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } -.ui-icon-arrow-2-e-w { background-position: -160px -32px; } -.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } -.ui-icon-arrowstop-1-n { background-position: -192px -32px; } -.ui-icon-arrowstop-1-e { background-position: -208px -32px; } -.ui-icon-arrowstop-1-s { background-position: -224px -32px; } -.ui-icon-arrowstop-1-w { background-position: -240px -32px; } -.ui-icon-arrowthick-1-n { background-position: 0 -48px; } -.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } -.ui-icon-arrowthick-1-e { background-position: -32px -48px; } -.ui-icon-arrowthick-1-se { background-position: -48px -48px; } -.ui-icon-arrowthick-1-s { background-position: -64px -48px; } -.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } -.ui-icon-arrowthick-1-w { background-position: -96px -48px; } -.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } -.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } -.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } -.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } -.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } -.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } -.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } -.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } -.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } -.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } -.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } -.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } -.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } -.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } -.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } -.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } -.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } -.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } -.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } -.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } -.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } -.ui-icon-arrow-4 { background-position: 0 -80px; } -.ui-icon-arrow-4-diag { background-position: -16px -80px; } -.ui-icon-extlink { background-position: -32px -80px; } -.ui-icon-newwin { background-position: -48px -80px; } -.ui-icon-refresh { background-position: -64px -80px; } -.ui-icon-shuffle { background-position: -80px -80px; } -.ui-icon-transfer-e-w { background-position: -96px -80px; } -.ui-icon-transferthick-e-w { background-position: -112px -80px; } -.ui-icon-folder-collapsed { background-position: 0 -96px; } -.ui-icon-folder-open { background-position: -16px -96px; } -.ui-icon-document { background-position: -32px -96px; } -.ui-icon-document-b { background-position: -48px -96px; } -.ui-icon-note { background-position: -64px -96px; } -.ui-icon-mail-closed { background-position: -80px -96px; } -.ui-icon-mail-open { background-position: -96px -96px; } -.ui-icon-suitcase { background-position: -112px -96px; } -.ui-icon-comment { background-position: -128px -96px; } -.ui-icon-person { background-position: -144px -96px; } -.ui-icon-print { background-position: -160px -96px; } -.ui-icon-trash { background-position: -176px -96px; } -.ui-icon-locked { background-position: -192px -96px; } -.ui-icon-unlocked { background-position: -208px -96px; } -.ui-icon-bookmark { background-position: -224px -96px; } -.ui-icon-tag { background-position: -240px -96px; } -.ui-icon-home { background-position: 0 -112px; } -.ui-icon-flag { background-position: -16px -112px; } -.ui-icon-calendar { background-position: -32px -112px; } -.ui-icon-cart { background-position: -48px -112px; } -.ui-icon-pencil { background-position: -64px -112px; } -.ui-icon-clock { background-position: -80px -112px; } -.ui-icon-disk { background-position: -96px -112px; } -.ui-icon-calculator { background-position: -112px -112px; } -.ui-icon-zoomin { background-position: -128px -112px; } -.ui-icon-zoomout { background-position: -144px -112px; } -.ui-icon-search { background-position: -160px -112px; } -.ui-icon-wrench { background-position: -176px -112px; } -.ui-icon-gear { background-position: -192px -112px; } -.ui-icon-heart { background-position: -208px -112px; } -.ui-icon-star { background-position: -224px -112px; } -.ui-icon-link { background-position: -240px -112px; } -.ui-icon-cancel { background-position: 0 -128px; } -.ui-icon-plus { background-position: -16px -128px; } -.ui-icon-plusthick { background-position: -32px -128px; } -.ui-icon-minus { background-position: -48px -128px; } -.ui-icon-minusthick { background-position: -64px -128px; } -.ui-icon-close { background-position: -80px -128px; } -.ui-icon-closethick { background-position: -96px -128px; } -.ui-icon-key { background-position: -112px -128px; } -.ui-icon-lightbulb { background-position: -128px -128px; } -.ui-icon-scissors { background-position: -144px -128px; } -.ui-icon-clipboard { background-position: -160px -128px; } -.ui-icon-copy { background-position: -176px -128px; } -.ui-icon-contact { background-position: -192px -128px; } -.ui-icon-image { background-position: -208px -128px; } -.ui-icon-video { background-position: -224px -128px; } -.ui-icon-script { background-position: -240px -128px; } -.ui-icon-alert { background-position: 0 -144px; } -.ui-icon-info { background-position: -16px -144px; } -.ui-icon-notice { background-position: -32px -144px; } -.ui-icon-help { background-position: -48px -144px; } -.ui-icon-check { background-position: -64px -144px; } -.ui-icon-bullet { background-position: -80px -144px; } -.ui-icon-radio-on { background-position: -96px -144px; } -.ui-icon-radio-off { background-position: -112px -144px; } -.ui-icon-pin-w { background-position: -128px -144px; } -.ui-icon-pin-s { background-position: -144px -144px; } -.ui-icon-play { background-position: 0 -160px; } -.ui-icon-pause { background-position: -16px -160px; } -.ui-icon-seek-next { background-position: -32px -160px; } -.ui-icon-seek-prev { background-position: -48px -160px; } -.ui-icon-seek-end { background-position: -64px -160px; } -.ui-icon-seek-start { background-position: -80px -160px; } -/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ -.ui-icon-seek-first { background-position: -80px -160px; } -.ui-icon-stop { background-position: -96px -160px; } -.ui-icon-eject { background-position: -112px -160px; } -.ui-icon-volume-off { background-position: -128px -160px; } -.ui-icon-volume-on { background-position: -144px -160px; } -.ui-icon-power { background-position: 0 -176px; } -.ui-icon-signal-diag { background-position: -16px -176px; } -.ui-icon-signal { background-position: -32px -176px; } -.ui-icon-battery-0 { background-position: -48px -176px; } -.ui-icon-battery-1 { background-position: -64px -176px; } -.ui-icon-battery-2 { background-position: -80px -176px; } -.ui-icon-battery-3 { background-position: -96px -176px; } -.ui-icon-circle-plus { background-position: 0 -192px; } -.ui-icon-circle-minus { background-position: -16px -192px; } -.ui-icon-circle-close { background-position: -32px -192px; } -.ui-icon-circle-triangle-e { background-position: -48px -192px; } -.ui-icon-circle-triangle-s { background-position: -64px -192px; } -.ui-icon-circle-triangle-w { background-position: -80px -192px; } -.ui-icon-circle-triangle-n { background-position: -96px -192px; } -.ui-icon-circle-arrow-e { background-position: -112px -192px; } -.ui-icon-circle-arrow-s { background-position: -128px -192px; } -.ui-icon-circle-arrow-w { background-position: -144px -192px; } -.ui-icon-circle-arrow-n { background-position: -160px -192px; } -.ui-icon-circle-zoomin { background-position: -176px -192px; } -.ui-icon-circle-zoomout { background-position: -192px -192px; } -.ui-icon-circle-check { background-position: -208px -192px; } -.ui-icon-circlesmall-plus { background-position: 0 -208px; } -.ui-icon-circlesmall-minus { background-position: -16px -208px; } -.ui-icon-circlesmall-close { background-position: -32px -208px; } -.ui-icon-squaresmall-plus { background-position: -48px -208px; } -.ui-icon-squaresmall-minus { background-position: -64px -208px; } -.ui-icon-squaresmall-close { background-position: -80px -208px; } -.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } -.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } -.ui-icon-grip-solid-vertical { background-position: -32px -224px; } -.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } -.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } -.ui-icon-grip-diagonal-se { background-position: -80px -224px; } - - -/* Misc visuals -----------------------------------*/ - -/* Corner radius */ -.ui-corner-all, -.ui-corner-top, -.ui-corner-left, -.ui-corner-tl { - border-top-left-radius: 4px; -} -.ui-corner-all, -.ui-corner-top, -.ui-corner-right, -.ui-corner-tr { - border-top-right-radius: 4px; -} -.ui-corner-all, -.ui-corner-bottom, -.ui-corner-left, -.ui-corner-bl { - border-bottom-left-radius: 4px; -} -.ui-corner-all, -.ui-corner-bottom, -.ui-corner-right, -.ui-corner-br { - border-bottom-right-radius: 4px; -} - -/* Overlays */ -.ui-widget-overlay { - background: #aaaaaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x; - opacity: .3; - filter: Alpha(Opacity=30); /* support: IE8 */ -} -.ui-widget-shadow { - margin: -8px 0 0 -8px; - padding: 8px; - background: #aaaaaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x; - opacity: .3; - filter: Alpha(Opacity=30); /* support: IE8 */ - border-radius: 8px; -} diff --git a/website/agenda/css/jquery-ui.structure.css b/website/agenda/css/jquery-ui.structure.css deleted file mode 100644 index 8184e15..0000000 --- a/website/agenda/css/jquery-ui.structure.css +++ /dev/null @@ -1,833 +0,0 @@ -/*! - * jQuery UI CSS Framework 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/category/theming/ - */ - -/* Layout helpers -----------------------------------*/ -.ui-helper-hidden { - display: none; -} -.ui-helper-hidden-accessible { - border: 0; - clip: rect(0 0 0 0); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - width: 1px; -} -.ui-helper-reset { - margin: 0; - padding: 0; - border: 0; - outline: 0; - line-height: 1.3; - text-decoration: none; - font-size: 100%; - list-style: none; -} -.ui-helper-clearfix:before, -.ui-helper-clearfix:after { - content: ""; - display: table; - border-collapse: collapse; -} -.ui-helper-clearfix:after { - clear: both; -} -.ui-helper-clearfix { - min-height: 0; /* support: IE7 */ -} -.ui-helper-zfix { - width: 100%; - height: 100%; - top: 0; - left: 0; - position: absolute; - opacity: 0; - filter:Alpha(Opacity=0); /* support: IE8 */ -} - -.ui-front { - z-index: 100; -} - - -/* Interaction Cues -----------------------------------*/ -.ui-state-disabled { - cursor: default !important; -} - - -/* Icons -----------------------------------*/ - -/* states and images */ -.ui-icon { - display: block; - text-indent: -99999px; - overflow: hidden; - background-repeat: no-repeat; -} - - -/* Misc visuals -----------------------------------*/ - -/* Overlays */ -.ui-widget-overlay { - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; -} -.ui-draggable-handle { - -ms-touch-action: none; - touch-action: none; -} -.ui-resizable { - position: relative; -} -.ui-resizable-handle { - position: absolute; - font-size: 0.1px; - display: block; - -ms-touch-action: none; - touch-action: none; -} -.ui-resizable-disabled .ui-resizable-handle, -.ui-resizable-autohide .ui-resizable-handle { - display: none; -} -.ui-resizable-n { - cursor: n-resize; - height: 7px; - width: 100%; - top: -5px; - left: 0; -} -.ui-resizable-s { - cursor: s-resize; - height: 7px; - width: 100%; - bottom: -5px; - left: 0; -} -.ui-resizable-e { - cursor: e-resize; - width: 7px; - right: -5px; - top: 0; - height: 100%; -} -.ui-resizable-w { - cursor: w-resize; - width: 7px; - left: -5px; - top: 0; - height: 100%; -} -.ui-resizable-se { - cursor: se-resize; - width: 12px; - height: 12px; - right: 1px; - bottom: 1px; -} -.ui-resizable-sw { - cursor: sw-resize; - width: 9px; - height: 9px; - left: -5px; - bottom: -5px; -} -.ui-resizable-nw { - cursor: nw-resize; - width: 9px; - height: 9px; - left: -5px; - top: -5px; -} -.ui-resizable-ne { - cursor: ne-resize; - width: 9px; - height: 9px; - right: -5px; - top: -5px; -} -.ui-selectable { - -ms-touch-action: none; - touch-action: none; -} -.ui-selectable-helper { - position: absolute; - z-index: 100; - border: 1px dotted black; -} -.ui-sortable-handle { - -ms-touch-action: none; - touch-action: none; -} -.ui-accordion .ui-accordion-header { - display: block; - cursor: pointer; - position: relative; - margin: 2px 0 0 0; - padding: .5em .5em .5em .7em; - min-height: 0; /* support: IE7 */ - font-size: 100%; -} -.ui-accordion .ui-accordion-icons { - padding-left: 2.2em; -} -.ui-accordion .ui-accordion-icons .ui-accordion-icons { - padding-left: 2.2em; -} -.ui-accordion .ui-accordion-header .ui-accordion-header-icon { - position: absolute; - left: .5em; - top: 50%; - margin-top: -8px; -} -.ui-accordion .ui-accordion-content { - padding: 1em 2.2em; - border-top: 0; - overflow: auto; -} -.ui-autocomplete { - position: absolute; - top: 0; - left: 0; - cursor: default; -} -.ui-button { - display: inline-block; - position: relative; - padding: 0; - line-height: normal; - margin-right: .1em; - cursor: pointer; - vertical-align: middle; - text-align: center; - overflow: visible; /* removes extra width in IE */ -} -.ui-button, -.ui-button:link, -.ui-button:visited, -.ui-button:hover, -.ui-button:active { - text-decoration: none; -} -/* to make room for the icon, a width needs to be set here */ -.ui-button-icon-only { - width: 2.2em; -} -/* button elements seem to need a little more width */ -button.ui-button-icon-only { - width: 2.4em; -} -.ui-button-icons-only { - width: 3.4em; -} -button.ui-button-icons-only { - width: 3.7em; -} - -/* button text element */ -.ui-button .ui-button-text { - display: block; - line-height: normal; -} -.ui-button-text-only .ui-button-text { - padding: .4em 1em; -} -.ui-button-icon-only .ui-button-text, -.ui-button-icons-only .ui-button-text { - padding: .4em; - text-indent: -9999999px; -} -.ui-button-text-icon-primary .ui-button-text, -.ui-button-text-icons .ui-button-text { - padding: .4em 1em .4em 2.1em; -} -.ui-button-text-icon-secondary .ui-button-text, -.ui-button-text-icons .ui-button-text { - padding: .4em 2.1em .4em 1em; -} -.ui-button-text-icons .ui-button-text { - padding-left: 2.1em; - padding-right: 2.1em; -} -/* no icon support for input elements, provide padding by default */ -input.ui-button { - padding: .4em 1em; -} - -/* button icon element(s) */ -.ui-button-icon-only .ui-icon, -.ui-button-text-icon-primary .ui-icon, -.ui-button-text-icon-secondary .ui-icon, -.ui-button-text-icons .ui-icon, -.ui-button-icons-only .ui-icon { - position: absolute; - top: 50%; - margin-top: -8px; -} -.ui-button-icon-only .ui-icon { - left: 50%; - margin-left: -8px; -} -.ui-button-text-icon-primary .ui-button-icon-primary, -.ui-button-text-icons .ui-button-icon-primary, -.ui-button-icons-only .ui-button-icon-primary { - left: .5em; -} -.ui-button-text-icon-secondary .ui-button-icon-secondary, -.ui-button-text-icons .ui-button-icon-secondary, -.ui-button-icons-only .ui-button-icon-secondary { - right: .5em; -} - -/* button sets */ -.ui-buttonset { - margin-right: 7px; -} -.ui-buttonset .ui-button { - margin-left: 0; - margin-right: -.3em; -} - -/* workarounds */ -/* reset extra padding in Firefox, see h5bp.com/l */ -input.ui-button::-moz-focus-inner, -button.ui-button::-moz-focus-inner { - border: 0; - padding: 0; -} -.ui-datepicker { - width: 17em; - padding: .2em .2em 0; - display: none; -} -.ui-datepicker .ui-datepicker-header { - position: relative; - padding: .2em 0; -} -.ui-datepicker .ui-datepicker-prev, -.ui-datepicker .ui-datepicker-next { - position: absolute; - top: 2px; - width: 1.8em; - height: 1.8em; -} -.ui-datepicker .ui-datepicker-prev-hover, -.ui-datepicker .ui-datepicker-next-hover { - top: 1px; -} -.ui-datepicker .ui-datepicker-prev { - left: 2px; -} -.ui-datepicker .ui-datepicker-next { - right: 2px; -} -.ui-datepicker .ui-datepicker-prev-hover { - left: 1px; -} -.ui-datepicker .ui-datepicker-next-hover { - right: 1px; -} -.ui-datepicker .ui-datepicker-prev span, -.ui-datepicker .ui-datepicker-next span { - display: block; - position: absolute; - left: 50%; - margin-left: -8px; - top: 50%; - margin-top: -8px; -} -.ui-datepicker .ui-datepicker-title { - margin: 0 2.3em; - line-height: 1.8em; - text-align: center; -} -.ui-datepicker .ui-datepicker-title select { - font-size: 1em; - margin: 1px 0; -} -.ui-datepicker select.ui-datepicker-month, -.ui-datepicker select.ui-datepicker-year { - width: 45%; -} -.ui-datepicker table { - width: 100%; - font-size: .9em; - border-collapse: collapse; - margin: 0 0 .4em; -} -.ui-datepicker th { - padding: .7em .3em; - text-align: center; - font-weight: bold; - border: 0; -} -.ui-datepicker td { - border: 0; - padding: 1px; -} -.ui-datepicker td span, -.ui-datepicker td a { - display: block; - padding: .2em; - text-align: right; - text-decoration: none; -} -.ui-datepicker .ui-datepicker-buttonpane { - background-image: none; - margin: .7em 0 0 0; - padding: 0 .2em; - border-left: 0; - border-right: 0; - border-bottom: 0; -} -.ui-datepicker .ui-datepicker-buttonpane button { - float: right; - margin: .5em .2em .4em; - cursor: pointer; - padding: .2em .6em .3em .6em; - width: auto; - overflow: visible; -} -.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { - float: left; -} - -/* with multiple calendars */ -.ui-datepicker.ui-datepicker-multi { - width: auto; -} -.ui-datepicker-multi .ui-datepicker-group { - float: left; -} -.ui-datepicker-multi .ui-datepicker-group table { - width: 95%; - margin: 0 auto .4em; -} -.ui-datepicker-multi-2 .ui-datepicker-group { - width: 50%; -} -.ui-datepicker-multi-3 .ui-datepicker-group { - width: 33.3%; -} -.ui-datepicker-multi-4 .ui-datepicker-group { - width: 25%; -} -.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header, -.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { - border-left-width: 0; -} -.ui-datepicker-multi .ui-datepicker-buttonpane { - clear: left; -} -.ui-datepicker-row-break { - clear: both; - width: 100%; - font-size: 0; -} - -/* RTL support */ -.ui-datepicker-rtl { - direction: rtl; -} -.ui-datepicker-rtl .ui-datepicker-prev { - right: 2px; - left: auto; -} -.ui-datepicker-rtl .ui-datepicker-next { - left: 2px; - right: auto; -} -.ui-datepicker-rtl .ui-datepicker-prev:hover { - right: 1px; - left: auto; -} -.ui-datepicker-rtl .ui-datepicker-next:hover { - left: 1px; - right: auto; -} -.ui-datepicker-rtl .ui-datepicker-buttonpane { - clear: right; -} -.ui-datepicker-rtl .ui-datepicker-buttonpane button { - float: left; -} -.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current, -.ui-datepicker-rtl .ui-datepicker-group { - float: right; -} -.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header, -.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { - border-right-width: 0; - border-left-width: 1px; -} -.ui-dialog { - overflow: hidden; - position: absolute; - top: 0; - left: 0; - padding: .2em; - outline: 0; -} -.ui-dialog .ui-dialog-titlebar { - padding: .4em 1em; - position: relative; -} -.ui-dialog .ui-dialog-title { - float: left; - margin: .1em 0; - white-space: nowrap; - width: 90%; - overflow: hidden; - text-overflow: ellipsis; -} -.ui-dialog .ui-dialog-titlebar-close { - position: absolute; - right: .3em; - top: 50%; - width: 20px; - margin: -10px 0 0 0; - padding: 1px; - height: 20px; -} -.ui-dialog .ui-dialog-content { - position: relative; - border: 0; - padding: .5em 1em; - background: none; - overflow: auto; -} -.ui-dialog .ui-dialog-buttonpane { - text-align: left; - border-width: 1px 0 0 0; - background-image: none; - margin-top: .5em; - padding: .3em 1em .5em .4em; -} -.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { - float: right; -} -.ui-dialog .ui-dialog-buttonpane button { - margin: .5em .4em .5em 0; - cursor: pointer; -} -.ui-dialog .ui-resizable-se { - width: 12px; - height: 12px; - right: -5px; - bottom: -5px; - background-position: 16px 16px; -} -.ui-draggable .ui-dialog-titlebar { - cursor: move; -} -.ui-menu { - list-style: none; - padding: 0; - margin: 0; - display: block; - outline: none; -} -.ui-menu .ui-menu { - position: absolute; -} -.ui-menu .ui-menu-item { - position: relative; - margin: 0; - padding: 3px 1em 3px .4em; - cursor: pointer; - min-height: 0; /* support: IE7 */ - /* support: IE10, see #8844 */ - list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"); -} -.ui-menu .ui-menu-divider { - margin: 5px 0; - height: 0; - font-size: 0; - line-height: 0; - border-width: 1px 0 0 0; -} -.ui-menu .ui-state-focus, -.ui-menu .ui-state-active { - margin: -1px; -} - -/* icon support */ -.ui-menu-icons { - position: relative; -} -.ui-menu-icons .ui-menu-item { - padding-left: 2em; -} - -/* left-aligned */ -.ui-menu .ui-icon { - position: absolute; - top: 0; - bottom: 0; - left: .2em; - margin: auto 0; -} - -/* right-aligned */ -.ui-menu .ui-menu-icon { - left: auto; - right: 0; -} -.ui-progressbar { - height: 2em; - text-align: left; - overflow: hidden; -} -.ui-progressbar .ui-progressbar-value { - margin: -1px; - height: 100%; -} -.ui-progressbar .ui-progressbar-overlay { - background: url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw=="); - height: 100%; - filter: alpha(opacity=25); /* support: IE8 */ - opacity: 0.25; -} -.ui-progressbar-indeterminate .ui-progressbar-value { - background-image: none; -} -.ui-selectmenu-menu { - padding: 0; - margin: 0; - position: absolute; - top: 0; - left: 0; - display: none; -} -.ui-selectmenu-menu .ui-menu { - overflow: auto; - /* Support: IE7 */ - overflow-x: hidden; - padding-bottom: 1px; -} -.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup { - font-size: 1em; - font-weight: bold; - line-height: 1.5; - padding: 2px 0.4em; - margin: 0.5em 0 0 0; - height: auto; - border: 0; -} -.ui-selectmenu-open { - display: block; -} -.ui-selectmenu-button { - display: inline-block; - overflow: hidden; - position: relative; - text-decoration: none; - cursor: pointer; -} -.ui-selectmenu-button span.ui-icon { - right: 0.5em; - left: auto; - margin-top: -8px; - position: absolute; - top: 50%; -} -.ui-selectmenu-button span.ui-selectmenu-text { - text-align: left; - padding: 0.4em 2.1em 0.4em 1em; - display: block; - line-height: 1.4; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} -.ui-slider { - position: relative; - text-align: left; -} -.ui-slider .ui-slider-handle { - position: absolute; - z-index: 2; - width: 1.2em; - height: 1.2em; - cursor: default; - -ms-touch-action: none; - touch-action: none; -} -.ui-slider .ui-slider-range { - position: absolute; - z-index: 1; - font-size: .7em; - display: block; - border: 0; - background-position: 0 0; -} - -/* support: IE8 - See #6727 */ -.ui-slider.ui-state-disabled .ui-slider-handle, -.ui-slider.ui-state-disabled .ui-slider-range { - filter: inherit; -} - -.ui-slider-horizontal { - height: .8em; -} -.ui-slider-horizontal .ui-slider-handle { - top: -.3em; - margin-left: -.6em; -} -.ui-slider-horizontal .ui-slider-range { - top: 0; - height: 100%; -} -.ui-slider-horizontal .ui-slider-range-min { - left: 0; -} -.ui-slider-horizontal .ui-slider-range-max { - right: 0; -} - -.ui-slider-vertical { - width: .8em; - height: 100px; -} -.ui-slider-vertical .ui-slider-handle { - left: -.3em; - margin-left: 0; - margin-bottom: -.6em; -} -.ui-slider-vertical .ui-slider-range { - left: 0; - width: 100%; -} -.ui-slider-vertical .ui-slider-range-min { - bottom: 0; -} -.ui-slider-vertical .ui-slider-range-max { - top: 0; -} -.ui-spinner { - position: relative; - display: inline-block; - overflow: hidden; - padding: 0; - vertical-align: middle; -} -.ui-spinner-input { - border: none; - background: none; - color: inherit; - padding: 0; - margin: .2em 0; - vertical-align: middle; - margin-left: .4em; - margin-right: 22px; -} -.ui-spinner-button { - width: 16px; - height: 50%; - font-size: .5em; - padding: 0; - margin: 0; - text-align: center; - position: absolute; - cursor: default; - display: block; - overflow: hidden; - right: 0; -} -/* more specificity required here to override default borders */ -.ui-spinner a.ui-spinner-button { - border-top: none; - border-bottom: none; - border-right: none; -} -/* vertically center icon */ -.ui-spinner .ui-icon { - position: absolute; - margin-top: -8px; - top: 50%; - left: 0; -} -.ui-spinner-up { - top: 0; -} -.ui-spinner-down { - bottom: 0; -} - -/* TR overrides */ -.ui-spinner .ui-icon-triangle-1-s { - /* need to fix icons sprite */ - background-position: -65px -16px; -} -.ui-tabs { - position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ - padding: .2em; -} -.ui-tabs .ui-tabs-nav { - margin: 0; - padding: .2em .2em 0; -} -.ui-tabs .ui-tabs-nav li { - list-style: none; - float: left; - position: relative; - top: 0; - margin: 1px .2em 0 0; - border-bottom-width: 0; - padding: 0; - white-space: nowrap; -} -.ui-tabs .ui-tabs-nav .ui-tabs-anchor { - float: left; - padding: .5em 1em; - text-decoration: none; -} -.ui-tabs .ui-tabs-nav li.ui-tabs-active { - margin-bottom: -1px; - padding-bottom: 1px; -} -.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor, -.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor, -.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor { - cursor: text; -} -.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor { - cursor: pointer; -} -.ui-tabs .ui-tabs-panel { - display: block; - border-width: 0; - padding: 1em 1.4em; - background: none; -} -.ui-tooltip { - padding: 8px; - position: absolute; - z-index: 9999; - max-width: 300px; - -webkit-box-shadow: 0 0 5px #aaa; - box-shadow: 0 0 5px #aaa; -} -body .ui-tooltip { - border-width: 2px; -} diff --git a/website/agenda/css/jquery-ui.structure.min.css b/website/agenda/css/jquery-ui.structure.min.css deleted file mode 100644 index fc03225..0000000 --- a/website/agenda/css/jquery-ui.structure.min.css +++ /dev/null @@ -1,5 +0,0 @@ -/*! jQuery UI - v1.11.4 - 2015-10-04 -* http://jqueryui.com -* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */ - -.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-draggable-handle{-ms-touch-action:none;touch-action:none}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display:block;-ms-touch-action:none;touch-action:none}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-selectable{-ms-touch-action:none;touch-action:none}.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted black}.ui-sortable-handle{-ms-touch-action:none;touch-action:none}.ui-accordion .ui-accordion-header{display:block;cursor:pointer;position:relative;margin:2px 0 0 0;padding:.5em .5em .5em .7em;min-height:0;font-size:100%}.ui-accordion .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-icons .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-header .ui-accordion-header-icon{position:absolute;left:.5em;top:50%;margin-top:-8px}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;overflow:auto}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-button{display:inline-block;position:relative;padding:0;line-height:normal;margin-right:.1em;cursor:pointer;vertical-align:middle;text-align:center;overflow:visible}.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none}.ui-button-icon-only{width:2.2em}button.ui-button-icon-only{width:2.4em}.ui-button-icons-only{width:3.4em}button.ui-button-icons-only{width:3.7em}.ui-button .ui-button-text{display:block;line-height:normal}.ui-button-text-only .ui-button-text{padding:.4em 1em}.ui-button-icon-only .ui-button-text,.ui-button-icons-only .ui-button-text{padding:.4em;text-indent:-9999999px}.ui-button-text-icon-primary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 1em .4em 2.1em}.ui-button-text-icon-secondary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 2.1em .4em 1em}.ui-button-text-icons .ui-button-text{padding-left:2.1em;padding-right:2.1em}input.ui-button{padding:.4em 1em}.ui-button-icon-only .ui-icon,.ui-button-text-icon-primary .ui-icon,.ui-button-text-icon-secondary .ui-icon,.ui-button-text-icons .ui-icon,.ui-button-icons-only .ui-icon{position:absolute;top:50%;margin-top:-8px}.ui-button-icon-only .ui-icon{left:50%;margin-left:-8px}.ui-button-text-icon-primary .ui-button-icon-primary,.ui-button-text-icons .ui-button-icon-primary,.ui-button-icons-only .ui-button-icon-primary{left:.5em}.ui-button-text-icon-secondary .ui-button-icon-secondary,.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em}.ui-buttonset{margin-right:7px}.ui-buttonset .ui-button{margin-left:0;margin-right:-.3em}input.ui-button::-moz-focus-inner,button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:45%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:bold;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-dialog{overflow:hidden;position:absolute;top:0;left:0;padding:.2em;outline:0}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 0;white-space:nowrap;width:90%;overflow:hidden;text-overflow:ellipsis}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:20px;margin:-10px 0 0 0;padding:1px;height:20px}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:none;overflow:auto}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0 0;background-image:none;margin-top:.5em;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-se{width:12px;height:12px;right:-5px;bottom:-5px;background-position:16px 16px}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-menu{list-style:none;padding:0;margin:0;display:block;outline:none}.ui-menu .ui-menu{position:absolute}.ui-menu .ui-menu-item{position:relative;margin:0;padding:3px 1em 3px .4em;cursor:pointer;min-height:0;list-style-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7")}.ui-menu .ui-menu-divider{margin:5px 0;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-state-focus,.ui-menu .ui-state-active{margin:-1px}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item{padding-left:2em}.ui-menu .ui-icon{position:absolute;top:0;bottom:0;left:.2em;margin:auto 0}.ui-menu .ui-menu-icon{left:auto;right:0}.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.ui-progressbar .ui-progressbar-overlay{background:url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==");height:100%;filter:alpha(opacity=25);opacity:0.25}.ui-progressbar-indeterminate .ui-progressbar-value{background-image:none}.ui-selectmenu-menu{padding:0;margin:0;position:absolute;top:0;left:0;display:none}.ui-selectmenu-menu .ui-menu{overflow:auto;overflow-x:hidden;padding-bottom:1px}.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup{font-size:1em;font-weight:bold;line-height:1.5;padding:2px 0.4em;margin:0.5em 0 0 0;height:auto;border:0}.ui-selectmenu-open{display:block}.ui-selectmenu-button{display:inline-block;overflow:hidden;position:relative;text-decoration:none;cursor:pointer}.ui-selectmenu-button span.ui-icon{right:0.5em;left:auto;margin-top:-8px;position:absolute;top:50%}.ui-selectmenu-button span.ui-selectmenu-text{text-align:left;padding:0.4em 2.1em 0.4em 1em;display:block;line-height:1.4;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default;-ms-touch-action:none;touch-action:none}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider.ui-state-disabled .ui-slider-handle,.ui-slider.ui-state-disabled .ui-slider-range{filter:inherit}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle}.ui-spinner-input{border:none;background:none;color:inherit;padding:0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:22px}.ui-spinner-button{width:16px;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0}.ui-spinner a.ui-spinner-button{border-top:none;border-bottom:none;border-right:none}.ui-spinner .ui-icon{position:absolute;margin-top:-8px;top:50%;left:0}.ui-spinner-up{top:0}.ui-spinner-down{bottom:0}.ui-spinner .ui-icon-triangle-1-s{background-position:-65px -16px}.ui-tabs{position:relative;padding:.2em}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom-width:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav .ui-tabs-anchor{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor{cursor:text}.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:none}.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px;-webkit-box-shadow:0 0 5px #aaa;box-shadow:0 0 5px #aaa}body .ui-tooltip{border-width:2px} \ No newline at end of file diff --git a/website/agenda/css/jquery-ui.theme.css b/website/agenda/css/jquery-ui.theme.css deleted file mode 100644 index 47cb233..0000000 --- a/website/agenda/css/jquery-ui.theme.css +++ /dev/null @@ -1,410 +0,0 @@ -/*! - * jQuery UI CSS Framework 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/category/theming/ - * - * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2CArial%2Csans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=highlight_soft&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=flat&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=glass&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=glass&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px - */ - - -/* Component containers -----------------------------------*/ -.ui-widget { - font-family: Verdana,Arial,sans-serif; - font-size: 1.1em; -} -.ui-widget .ui-widget { - font-size: 1em; -} -.ui-widget input, -.ui-widget select, -.ui-widget textarea, -.ui-widget button { - font-family: Verdana,Arial,sans-serif; - font-size: 1em; -} -.ui-widget-content { - border: 1px solid #aaaaaa; - background: #ffffff url("images/ui-bg_flat_75_ffffff_40x100.png") 50% 50% repeat-x; - color: #222222; -} -.ui-widget-content a { - color: #222222; -} -.ui-widget-header { - border: 1px solid #aaaaaa; - background: #cccccc url("images/ui-bg_highlight-soft_75_cccccc_1x100.png") 50% 50% repeat-x; - color: #222222; - font-weight: bold; -} -.ui-widget-header a { - color: #222222; -} - -/* Interaction states -----------------------------------*/ -.ui-state-default, -.ui-widget-content .ui-state-default, -.ui-widget-header .ui-state-default { - border: 1px solid #d3d3d3; - background: #e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x; - font-weight: normal; - color: #555555; -} -.ui-state-default a, -.ui-state-default a:link, -.ui-state-default a:visited { - color: #555555; - text-decoration: none; -} -.ui-state-hover, -.ui-widget-content .ui-state-hover, -.ui-widget-header .ui-state-hover, -.ui-state-focus, -.ui-widget-content .ui-state-focus, -.ui-widget-header .ui-state-focus { - border: 1px solid #999999; - background: #dadada url("images/ui-bg_glass_75_dadada_1x400.png") 50% 50% repeat-x; - font-weight: normal; - color: #212121; -} -.ui-state-hover a, -.ui-state-hover a:hover, -.ui-state-hover a:link, -.ui-state-hover a:visited, -.ui-state-focus a, -.ui-state-focus a:hover, -.ui-state-focus a:link, -.ui-state-focus a:visited { - color: #212121; - text-decoration: none; -} -.ui-state-active, -.ui-widget-content .ui-state-active, -.ui-widget-header .ui-state-active { - border: 1px solid #aaaaaa; - background: #ffffff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x; - font-weight: normal; - color: #212121; -} -.ui-state-active a, -.ui-state-active a:link, -.ui-state-active a:visited { - color: #212121; - text-decoration: none; -} - -/* Interaction Cues -----------------------------------*/ -.ui-state-highlight, -.ui-widget-content .ui-state-highlight, -.ui-widget-header .ui-state-highlight { - border: 1px solid #fcefa1; - background: #fbf9ee url("images/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x; - color: #363636; -} -.ui-state-highlight a, -.ui-widget-content .ui-state-highlight a, -.ui-widget-header .ui-state-highlight a { - color: #363636; -} -.ui-state-error, -.ui-widget-content .ui-state-error, -.ui-widget-header .ui-state-error { - border: 1px solid #cd0a0a; - background: #fef1ec url("images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x; - color: #cd0a0a; -} -.ui-state-error a, -.ui-widget-content .ui-state-error a, -.ui-widget-header .ui-state-error a { - color: #cd0a0a; -} -.ui-state-error-text, -.ui-widget-content .ui-state-error-text, -.ui-widget-header .ui-state-error-text { - color: #cd0a0a; -} -.ui-priority-primary, -.ui-widget-content .ui-priority-primary, -.ui-widget-header .ui-priority-primary { - font-weight: bold; -} -.ui-priority-secondary, -.ui-widget-content .ui-priority-secondary, -.ui-widget-header .ui-priority-secondary { - opacity: .7; - filter:Alpha(Opacity=70); /* support: IE8 */ - font-weight: normal; -} -.ui-state-disabled, -.ui-widget-content .ui-state-disabled, -.ui-widget-header .ui-state-disabled { - opacity: .35; - filter:Alpha(Opacity=35); /* support: IE8 */ - background-image: none; -} -.ui-state-disabled .ui-icon { - filter:Alpha(Opacity=35); /* support: IE8 - See #6059 */ -} - -/* Icons -----------------------------------*/ - -/* states and images */ -.ui-icon { - width: 16px; - height: 16px; -} -.ui-icon, -.ui-widget-content .ui-icon { - background-image: url("images/ui-icons_222222_256x240.png"); -} -.ui-widget-header .ui-icon { - background-image: url("images/ui-icons_222222_256x240.png"); -} -.ui-state-default .ui-icon { - background-image: url("images/ui-icons_888888_256x240.png"); -} -.ui-state-hover .ui-icon, -.ui-state-focus .ui-icon { - background-image: url("images/ui-icons_454545_256x240.png"); -} -.ui-state-active .ui-icon { - background-image: url("images/ui-icons_454545_256x240.png"); -} -.ui-state-highlight .ui-icon { - background-image: url("images/ui-icons_2e83ff_256x240.png"); -} -.ui-state-error .ui-icon, -.ui-state-error-text .ui-icon { - background-image: url("images/ui-icons_cd0a0a_256x240.png"); -} - -/* positioning */ -.ui-icon-blank { background-position: 16px 16px; } -.ui-icon-carat-1-n { background-position: 0 0; } -.ui-icon-carat-1-ne { background-position: -16px 0; } -.ui-icon-carat-1-e { background-position: -32px 0; } -.ui-icon-carat-1-se { background-position: -48px 0; } -.ui-icon-carat-1-s { background-position: -64px 0; } -.ui-icon-carat-1-sw { background-position: -80px 0; } -.ui-icon-carat-1-w { background-position: -96px 0; } -.ui-icon-carat-1-nw { background-position: -112px 0; } -.ui-icon-carat-2-n-s { background-position: -128px 0; } -.ui-icon-carat-2-e-w { background-position: -144px 0; } -.ui-icon-triangle-1-n { background-position: 0 -16px; } -.ui-icon-triangle-1-ne { background-position: -16px -16px; } -.ui-icon-triangle-1-e { background-position: -32px -16px; } -.ui-icon-triangle-1-se { background-position: -48px -16px; } -.ui-icon-triangle-1-s { background-position: -64px -16px; } -.ui-icon-triangle-1-sw { background-position: -80px -16px; } -.ui-icon-triangle-1-w { background-position: -96px -16px; } -.ui-icon-triangle-1-nw { background-position: -112px -16px; } -.ui-icon-triangle-2-n-s { background-position: -128px -16px; } -.ui-icon-triangle-2-e-w { background-position: -144px -16px; } -.ui-icon-arrow-1-n { background-position: 0 -32px; } -.ui-icon-arrow-1-ne { background-position: -16px -32px; } -.ui-icon-arrow-1-e { background-position: -32px -32px; } -.ui-icon-arrow-1-se { background-position: -48px -32px; } -.ui-icon-arrow-1-s { background-position: -64px -32px; } -.ui-icon-arrow-1-sw { background-position: -80px -32px; } -.ui-icon-arrow-1-w { background-position: -96px -32px; } -.ui-icon-arrow-1-nw { background-position: -112px -32px; } -.ui-icon-arrow-2-n-s { background-position: -128px -32px; } -.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } -.ui-icon-arrow-2-e-w { background-position: -160px -32px; } -.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } -.ui-icon-arrowstop-1-n { background-position: -192px -32px; } -.ui-icon-arrowstop-1-e { background-position: -208px -32px; } -.ui-icon-arrowstop-1-s { background-position: -224px -32px; } -.ui-icon-arrowstop-1-w { background-position: -240px -32px; } -.ui-icon-arrowthick-1-n { background-position: 0 -48px; } -.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } -.ui-icon-arrowthick-1-e { background-position: -32px -48px; } -.ui-icon-arrowthick-1-se { background-position: -48px -48px; } -.ui-icon-arrowthick-1-s { background-position: -64px -48px; } -.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } -.ui-icon-arrowthick-1-w { background-position: -96px -48px; } -.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } -.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } -.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } -.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } -.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } -.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } -.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } -.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } -.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } -.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } -.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } -.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } -.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } -.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } -.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } -.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } -.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } -.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } -.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } -.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } -.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } -.ui-icon-arrow-4 { background-position: 0 -80px; } -.ui-icon-arrow-4-diag { background-position: -16px -80px; } -.ui-icon-extlink { background-position: -32px -80px; } -.ui-icon-newwin { background-position: -48px -80px; } -.ui-icon-refresh { background-position: -64px -80px; } -.ui-icon-shuffle { background-position: -80px -80px; } -.ui-icon-transfer-e-w { background-position: -96px -80px; } -.ui-icon-transferthick-e-w { background-position: -112px -80px; } -.ui-icon-folder-collapsed { background-position: 0 -96px; } -.ui-icon-folder-open { background-position: -16px -96px; } -.ui-icon-document { background-position: -32px -96px; } -.ui-icon-document-b { background-position: -48px -96px; } -.ui-icon-note { background-position: -64px -96px; } -.ui-icon-mail-closed { background-position: -80px -96px; } -.ui-icon-mail-open { background-position: -96px -96px; } -.ui-icon-suitcase { background-position: -112px -96px; } -.ui-icon-comment { background-position: -128px -96px; } -.ui-icon-person { background-position: -144px -96px; } -.ui-icon-print { background-position: -160px -96px; } -.ui-icon-trash { background-position: -176px -96px; } -.ui-icon-locked { background-position: -192px -96px; } -.ui-icon-unlocked { background-position: -208px -96px; } -.ui-icon-bookmark { background-position: -224px -96px; } -.ui-icon-tag { background-position: -240px -96px; } -.ui-icon-home { background-position: 0 -112px; } -.ui-icon-flag { background-position: -16px -112px; } -.ui-icon-calendar { background-position: -32px -112px; } -.ui-icon-cart { background-position: -48px -112px; } -.ui-icon-pencil { background-position: -64px -112px; } -.ui-icon-clock { background-position: -80px -112px; } -.ui-icon-disk { background-position: -96px -112px; } -.ui-icon-calculator { background-position: -112px -112px; } -.ui-icon-zoomin { background-position: -128px -112px; } -.ui-icon-zoomout { background-position: -144px -112px; } -.ui-icon-search { background-position: -160px -112px; } -.ui-icon-wrench { background-position: -176px -112px; } -.ui-icon-gear { background-position: -192px -112px; } -.ui-icon-heart { background-position: -208px -112px; } -.ui-icon-star { background-position: -224px -112px; } -.ui-icon-link { background-position: -240px -112px; } -.ui-icon-cancel { background-position: 0 -128px; } -.ui-icon-plus { background-position: -16px -128px; } -.ui-icon-plusthick { background-position: -32px -128px; } -.ui-icon-minus { background-position: -48px -128px; } -.ui-icon-minusthick { background-position: -64px -128px; } -.ui-icon-close { background-position: -80px -128px; } -.ui-icon-closethick { background-position: -96px -128px; } -.ui-icon-key { background-position: -112px -128px; } -.ui-icon-lightbulb { background-position: -128px -128px; } -.ui-icon-scissors { background-position: -144px -128px; } -.ui-icon-clipboard { background-position: -160px -128px; } -.ui-icon-copy { background-position: -176px -128px; } -.ui-icon-contact { background-position: -192px -128px; } -.ui-icon-image { background-position: -208px -128px; } -.ui-icon-video { background-position: -224px -128px; } -.ui-icon-script { background-position: -240px -128px; } -.ui-icon-alert { background-position: 0 -144px; } -.ui-icon-info { background-position: -16px -144px; } -.ui-icon-notice { background-position: -32px -144px; } -.ui-icon-help { background-position: -48px -144px; } -.ui-icon-check { background-position: -64px -144px; } -.ui-icon-bullet { background-position: -80px -144px; } -.ui-icon-radio-on { background-position: -96px -144px; } -.ui-icon-radio-off { background-position: -112px -144px; } -.ui-icon-pin-w { background-position: -128px -144px; } -.ui-icon-pin-s { background-position: -144px -144px; } -.ui-icon-play { background-position: 0 -160px; } -.ui-icon-pause { background-position: -16px -160px; } -.ui-icon-seek-next { background-position: -32px -160px; } -.ui-icon-seek-prev { background-position: -48px -160px; } -.ui-icon-seek-end { background-position: -64px -160px; } -.ui-icon-seek-start { background-position: -80px -160px; } -/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ -.ui-icon-seek-first { background-position: -80px -160px; } -.ui-icon-stop { background-position: -96px -160px; } -.ui-icon-eject { background-position: -112px -160px; } -.ui-icon-volume-off { background-position: -128px -160px; } -.ui-icon-volume-on { background-position: -144px -160px; } -.ui-icon-power { background-position: 0 -176px; } -.ui-icon-signal-diag { background-position: -16px -176px; } -.ui-icon-signal { background-position: -32px -176px; } -.ui-icon-battery-0 { background-position: -48px -176px; } -.ui-icon-battery-1 { background-position: -64px -176px; } -.ui-icon-battery-2 { background-position: -80px -176px; } -.ui-icon-battery-3 { background-position: -96px -176px; } -.ui-icon-circle-plus { background-position: 0 -192px; } -.ui-icon-circle-minus { background-position: -16px -192px; } -.ui-icon-circle-close { background-position: -32px -192px; } -.ui-icon-circle-triangle-e { background-position: -48px -192px; } -.ui-icon-circle-triangle-s { background-position: -64px -192px; } -.ui-icon-circle-triangle-w { background-position: -80px -192px; } -.ui-icon-circle-triangle-n { background-position: -96px -192px; } -.ui-icon-circle-arrow-e { background-position: -112px -192px; } -.ui-icon-circle-arrow-s { background-position: -128px -192px; } -.ui-icon-circle-arrow-w { background-position: -144px -192px; } -.ui-icon-circle-arrow-n { background-position: -160px -192px; } -.ui-icon-circle-zoomin { background-position: -176px -192px; } -.ui-icon-circle-zoomout { background-position: -192px -192px; } -.ui-icon-circle-check { background-position: -208px -192px; } -.ui-icon-circlesmall-plus { background-position: 0 -208px; } -.ui-icon-circlesmall-minus { background-position: -16px -208px; } -.ui-icon-circlesmall-close { background-position: -32px -208px; } -.ui-icon-squaresmall-plus { background-position: -48px -208px; } -.ui-icon-squaresmall-minus { background-position: -64px -208px; } -.ui-icon-squaresmall-close { background-position: -80px -208px; } -.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } -.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } -.ui-icon-grip-solid-vertical { background-position: -32px -224px; } -.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } -.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } -.ui-icon-grip-diagonal-se { background-position: -80px -224px; } - - -/* Misc visuals -----------------------------------*/ - -/* Corner radius */ -.ui-corner-all, -.ui-corner-top, -.ui-corner-left, -.ui-corner-tl { - border-top-left-radius: 4px; -} -.ui-corner-all, -.ui-corner-top, -.ui-corner-right, -.ui-corner-tr { - border-top-right-radius: 4px; -} -.ui-corner-all, -.ui-corner-bottom, -.ui-corner-left, -.ui-corner-bl { - border-bottom-left-radius: 4px; -} -.ui-corner-all, -.ui-corner-bottom, -.ui-corner-right, -.ui-corner-br { - border-bottom-right-radius: 4px; -} - -/* Overlays */ -.ui-widget-overlay { - background: #aaaaaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x; - opacity: .3; - filter: Alpha(Opacity=30); /* support: IE8 */ -} -.ui-widget-shadow { - margin: -8px 0 0 -8px; - padding: 8px; - background: #aaaaaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x; - opacity: .3; - filter: Alpha(Opacity=30); /* support: IE8 */ - border-radius: 8px; -} diff --git a/website/agenda/css/jquery-ui.theme.min.css b/website/agenda/css/jquery-ui.theme.min.css deleted file mode 100644 index c7b45bf..0000000 --- a/website/agenda/css/jquery-ui.theme.min.css +++ /dev/null @@ -1,5 +0,0 @@ -/*! jQuery UI - v1.11.4 - 2015-10-09 -* http://jqueryui.com -* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */ - -.ui-widget{font-family:Verdana,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Verdana,Arial,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #aaa;background:#fff url("images/ui-bg_flat_75_ffffff_40x100.png") 50% 50% repeat-x;color:#222}.ui-widget-content a{color:#222}.ui-widget-header{border:1px solid #aaa;background:#ccc url("images/ui-bg_highlight-soft_75_cccccc_1x100.png") 50% 50% repeat-x;color:#222;font-weight:bold}.ui-widget-header a{color:#222}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #d3d3d3;background:#e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x;font-weight:normal;color:#555}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#555;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #999;background:#dadada url("images/ui-bg_glass_75_dadada_1x400.png") 50% 50% repeat-x;font-weight:normal;color:#212121}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited{color:#212121;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #aaa;background:#fff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x;font-weight:normal;color:#212121}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#212121;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fcefa1;background:#fbf9ee url("images/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x;color:#363636}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#fef1ec url("images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x;color:#cd0a0a}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#cd0a0a}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#cd0a0a}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url("images/ui-icons_222222_256x240.png")}.ui-widget-header .ui-icon{background-image:url("images/ui-icons_222222_256x240.png")}.ui-state-default .ui-icon{background-image:url("images/ui-icons_888888_256x240.png")}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url("images/ui-icons_454545_256x240.png")}.ui-state-active .ui-icon{background-image:url("images/ui-icons_454545_256x240.png")}.ui-state-highlight .ui-icon{background-image:url("images/ui-icons_2e83ff_256x240.png")}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url("images/ui-icons_cd0a0a_256x240.png")}.ui-icon-blank{background-position:16px 16px}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:4px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:4px}.ui-widget-overlay{background:#aaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30)}.ui-widget-shadow{margin:-8px 0 0 -8px;padding:8px;background:#aaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30);border-radius:8px} \ No newline at end of file diff --git a/website/agenda/css/mobile.css b/website/agenda/css/mobile.css deleted file mode 100644 index 77a4d6e..0000000 --- a/website/agenda/css/mobile.css +++ /dev/null @@ -1,650 +0,0 @@ - -/* -include in your web page: -<link rel="stylesheet" type="text/css" media="screen" href="http://piradio.de/agenda_files/css/calcms.css" /> -*/ - -/* calcms - common */ - - body{ - text-align:left; - font: 1em/1.2em Ubuntu,"Lucida Grande",Verdana,Helvetica,Arial,sans-serif; - } - - a{ - text-decoration:none; - color:black; - } - - a:visited{ - color:black; - - } - - @media only screen and (max-device-width: 480px) { - #content{ - width:480px; - } - } - @media only screen and (max-device-width: 800px) { - #content{ - width:800px; - } - } - - #content{ - width:460px; - padding:10px; - } - - pre{ - text-align:left; - font-family:Courier; - padding:1em; - margin:1em; - border:1px solid black; - } - - /* hide microformats */ - .dtstart{ - display:none; - visibility:hidden; - } - - .dtend{ - display:none; - visibility:hidden; - } - -/* end of common */ - - -/* menu */ - #calcms_menu{ - padding-top:3px;padding-right:5px; - margin-bottom:1px; - text-align:left; - clear:both; - line-height:120%; - /*padding:3px;*/ - /*font-family:Verdana,Arial,sans-serif;*/ - /*overflow:auto;*/ - } - - #calcms_menu li.leaf{ - list-style-type:none; - list-style-image:url(); - background:none; - padding:0; - } - -/* - #calcms_menu a{ - text-decoration:none; - } -*/ - #calcms_menu a:hover, - #calcms_calendar a:hover{ - text-decoration:underline; - } - - #calcms_menu .date{ - margin:0px; - font-weight:bold; - margin-top:1em; - margin-bottom:6px; - -moz-border-radius-topleft:12px; - -moz-border-radius-topright:12px; - -webkit-border-top-right-radius: 12px; - -webkit-border-top-left-radius: 12px; - } - - #calcms_menu .title{ - padding:0px; - margin:0px; - text-align:left; - } - -/* - div:first-line #calcms_menu .title { - margin-left:0px; - } -*/ - #calcms_menu .excerpt{ - padding:3px; - margin:0px; - } - #calcms_menu .content{ - padding:3px; - margin:0px; - clear:left; - margin:0 - } - #calcms_menu .content p{ - margin-top:10px - } - #calcms_menu .content h1{ - text-align:left; - font-size:1.5em; - clear:left; - margin-top:16px - } - #calcms_menu .content h2{ - text-align:left; - font-size:1.5em; - clear:left; - margin-top:16px - } - #calcms_menu .content h3{ - text-align:left; - font-size:1.5em; - clear:left; - margin-top:16px - } - #calcms_menu .content h4{ - text-align:left; - font-size:1.5em; - clear:left; - margin-top:16px - } - - #calcms_menu li{ - clear:left; - line-height:1.2em; - } - - #calcms_menu .date{ - margin-top:12px; - margin-left:3em; - clear:both; - } - - #calcms_list .summary .title{ - font-weight:bold; - } - - #calcms_list .title{ - margin-bottom:1em; - } - - #calcms_list hr{ - /*margin-bottom:2em;*/ - background-color:#ddd; - } - - #calcms_list .content img{ - text-align:left; - font-size:1.5em; - margin-bottom:20px; - border:0; - /* - clear:both; - float:left; - margin-right:30px; - */ - float: right; - margin-left: 1em; - } - - #calcms_list li{ -/* - list-style-type:none; - list-style-image:url(); - background:none; - padding:0; -*/ - } - - - #calcms_playlist{ - padding:1px; - margin:0px; - clear:both; - /*text-align:center;*/ - } - - #calcms_playlist div{ - vertical-align:middle; - clear:both; - } - - #calcms_playlist img{ - width:2em; - height:2em; - margin:6px; - float:left; - opacity:0.9; - } - - #calcms_playlist img:hover{ - opacity:1.0; - } - - #calcms_menu div{ - vertical-align:middle; - clear:both; - } - - #calcms_menu .event{ - opacity:0.8; - } - -/* - #calcms_menu .event:hover{ - opacity:1.0; - } -*/ - #calcms_menu img{ - width:2em; - height:2em; - margin-right:6px; - margin-bottom:12px; - float:left; - } - - #calcms_menu img:hover{ - } - - #calcms_playlist a{ - clear:both; - float:none; - } - - #calcms_menu .event{ - padding:1px; - margin:0px; - clear:both; - text-align:left; - } - - #calcms_menu .event.running{ - font-weight:bold; - } - -/* end of menu */ - - - -/* calcms_list */ - div#calcms_list{ - } - - #content div a img, - #icon_bar a img, - { - margin:6px; - } - - #calcms_list .date{ - /*padding:6px;*/ - /*margin:0px;*/ - font-weight:bold; - margin-top:1em; - /* - -moz-border-radius-topleft:12px; - -moz-border-radius-topright:12px; - -webkit-border-top-right-radius: 12px; - -webkit-border-top-left-radius: 12px; - */ - } - - #calcms_list .excerpt{ - margin-left:40px; - margin-top:6px; - /*margin-bottom:10px;*/ - /* color:#eee; */ - } - - #calcms_list .event.running{ - /*padding:6px;*/ - /*background: white;*/ - /*border:1px solid #bbb;*/ - color:#000; - } - - #calcms_list .submitted{ - position:absolute; - right:0px; - } - - -/* end of calcms_list */ - -/* calcms comments */ - - #calcms_comments .author{ - color:#666; - font-weight:bold; - float:left; - } - - #calcms_comments .date{ - color:#888; - font-weight:normal; - margin:0; - padding:0; - } - - #calcms_comments .content{ - /* color:#ccc; */ - font-weight:normal; - } - - #calcms_comments .comment{ - margin:0; - padding:0; - } - - #calcms_comments .level0{ - padding-top:1.5em; - margin-left:00px; - } - #calcms_comments .level1{ - margin-left:20px; - } - #calcms_comments .level2{ - margin-left:40px; - } - #calcms_comments .level3{ - margin-left:60px; - } - #calcms_comments .level4{ - margin-left:80px; - } - #calcms_comments .level5{ - margin-left:100px; - } - #calcms_comments .level6{ - margin-left:120px; - } - #calcms_comments .level7{ - margin-left:140px; - } - #calcms_comments .level8{ - margin-left:160px; - } - #calcms_comments .level9{ - margin-left:180px; - } - #calcms_comments .level10{ - margin-left:200px; - } - - #calcms_add_comment{ - visibility:hidden; - display:none; - } - - #calcms_newest_comments .author{ - font-weight:bold; - } - - #calcms_newest_comments li, - #calcms_newest_comments li.leaf{ - list-style-type:none; - list-style-image:url(); - background:none; - } - - #calcms_newest_comments span.content{ - text-overflow: ellipsis; - -o-text-overflow: ellipsis; - -icab-text-overflow: ellipsis; - -khtml-text-overflow: ellipsis; - -moz-text-overflow: ellipsis; - -webkit-text-overflow: ellipsis; - } - - #calcms_newest_comments li.leaf a, - #calcms_newest_comments li.leaf span{ - line-height:1.2em; - } - - #calcms_newest_comments li.leaf a:hover{ - text-decoration:none; - } - -/* end of calcms comments*/ - -/* calcms_search */ - #calcms_search{ - margin:0; - z-index:3; - text-align:left; - font-size:10px; - clear:both; - } - - #calcms_search input{ - width:80px; - } - - table#calcms_search{ - padding:0; - margin:0; - text-align:left; - } - - table#calcms_search td a{ - padding:1px; - } - - #calcms_search input#calcms_search_field, - #calcms_search select{ - width:100px; - } - - #calcms_search input#calcms_search_field{ - float:left; - } - - #calcms_search form{ - float:left; - } -/* end of calcms_search */ - - -/* calcms_calendar */ - #calcms_calendar{ - overflow:auto; - text-align:center; - padding:0px; - margin:0px; - vertical-align:top; - clear:both; - width:100%; - } - - #calcms_calendar .week_1, - #calcms_calendar .week_2, - #calcms_calendar .week_3, - #calcms_calendar .week_4, - #calcms_calendar .week_5{ - } - - #calcms_calendar th{ - margin:0px; - font-weight:normal; - margin-top:1em; - } - - #calcms_calendar th a{ - /* color:#AEB1B3; */ - } - - /* selected fields */ - #calcms_calendar .selected, .night, .morning, .noon, .afternoon, .evening{ - background:#eee; - font-size:bold; - font-weight:bold; - } - - #calcms_calendar table{ - text-align:center; - padding:0px; - margin:0px; - } - - /* hover effects */ - - #calcms_calendar table td:hover{ - background-color:#f0f0f0; - } - - #calcms_calendar table td{ - border-bottom:1px solid #D1C7CA; - opacity:0.8; - /*border-right:1px solid #D1C7CA;*/ - } - - #calcms_calendar table td.selected{ - /*opacity:1.0;*/ - } - - #calcms_calendar table td.selected:hover{ - background-color:#f0f0f0; - border-top: 1px solid #D1C7CA; - border-bottom:1px solid #D1C7CA; - } - - #calcms_calendar table a{ - text-decoration:none; - font-weight:normal; - } - - #calcms_calendar table td.selected a{ - font-weight:bold; - } - - #calcms_calendar td, - #calcms_calendar th{ - padding:0px; - padding-left:1em; - padding-right:1em; - padding-bottom:1em; - margin:0; - text-align:center; - } - - #calcms_calendar th.first, - #calcms_calendar th.last{ - font-size:large; - } - /* not selectable columns */ - - #calcms_calendar table td.row_type:hover{ - border-bottom:1px solid #D1C7CA; - border-right: 1px solid #D1C7CA; - background-color:#ffffff; - } - - #calcms_calendar .row_type{ -/* width:100px -*/ - } - - .calcms_today{ - font-weight:bold; - } - -/* end of calcms_calendar */ - - - .blnfm, .multicultfm, .ohrfunk, .twenfm, .offenerkanalberlin, .klubradio, .piradio, - .studioansage, .studiolottumstrasse, .studiorebootfm - - { -/* - border-radius: 12px; - -moz-border-radius: 12px; - -webkit-border-radius: 12px; -*/ - padding:6px; - margin:6px; - } - - .blnfm{ - background-color:white; - } - - .multicultfm{ - background-color:white; - } - - .ohrfunk{ - background-color:white; - } - - .twenfm{ - background-color:white; - } - - .offenerkanalberlin{ - background-color:white; - } - - .klubradio{ - background-color:white; - } - - .piradio{ - background-color:white; - } - - /*Einheitsradio */ - .studiolottumstrasse{ - background-color:white; - /* background-color:#ffddff; */ - } - .studioansage{ - background-color:white; - /* background-color:#ddffdd; */ - } - .studiorebootfm{ - background-color:white; - /* background-color:#ffff00; */ - } - - .feed-icon{ - float:left; - } - - #icon_bar{ - padding-bottom:6px; - } - - #icon_bar .feed-icon{ - height:24px; - } - - #icon_bar .feed-icon img{ - margin:6px; - text-align:right; - } - - input{ - width:200px; - } - - .vevent a{ - font-weight:normal; - } - - - div#jp_player_1{ - text-decoration:none; - height:24px; - padding-left:30px; - color:black; - background-repeat:no-repeat; - background-image:url("/agenda/image/player4.play.png"); - border:1px solid black; - } - - div#jp_equalizer_1{ - width:0px; - height:2px; - background:#ccc; - border:1px solid gray; - } - diff --git a/website/agenda/events.cgi b/website/agenda/events.cgi index 9204a53..c780b4e 100755 --- a/website/agenda/events.cgi +++ b/website/agenda/events.cgi @@ -1,51 +1,37 @@ -#! /usr/bin/perl -w +#!/usr/bin/perl -use warnings "all"; - -#no warnings 'redefine'; -#use diagnostics; use strict; -use Data::Dumper; +use warnings; +no warnings 'redefine'; -#use utf8; -use DBI; -use CGI qw(header param Vars); -$CGI::POST_MAX = 1000; -$CGI::DISABLE_UPLOADS = 1; +use params(); +use config(); +use events(); -use params; -use config; -use log; -use events; -use time; - -#binmode STDOUT, ":utf8"; binmode STDOUT, ":encoding(UTF-8)"; my $r = shift; ( my $cgi, my $params, my $error ) = params::get($r); - if ( $0 =~ /events.*?\.cgi$/ ) { - #my $cgi=new CGI(); - #my %params=$cgi->Vars(); - our $config = config::get('config/config.cgi'); + my $config = config::getFromScriptLocation(); - $params->{recordings} = 1 if $params->{template} =~ /events_playout/; - my $request = { - url => $ENV{QUERY_STRING}, - params => { - original => $params, - checked => events::check_params( $config, $params ), - }, - }; + $params->{template} = '' unless defined $params->{template}; + $params->{recordings} = 1 if $params->{template} =~ /events_playout/; - #events::init($request); - log::init($request); + $params->{exclude_locations} = 1; + $params->{exclude_projects} = 1; + $params->{exclude_event_images} = 1; + $params->{ro} = 1; - my $output = ''; - events::get_cached_or_render( $output, $config, $request ); - print $output. "\n"; + my $request = { + url => $ENV{QUERY_STRING}, + params => { + original => $params, + checked => events::check_params( $config, $params ), + }, + }; + events::get_cached_or_render( 'print', $config, $request ); } 1; diff --git a/website/agenda/fonts/open-sans-v15-latin_latin-ext-regular.eot b/website/agenda/fonts/open-sans-v15-latin_latin-ext-regular.eot new file mode 100644 index 0000000..f25146f Binary files /dev/null and b/website/agenda/fonts/open-sans-v15-latin_latin-ext-regular.eot differ diff --git a/website/agenda/fonts/open-sans-v15-latin_latin-ext-regular.svg b/website/agenda/fonts/open-sans-v15-latin_latin-ext-regular.svg new file mode 100644 index 0000000..78eb653 --- /dev/null +++ b/website/agenda/fonts/open-sans-v15-latin_latin-ext-regular.svg @@ -0,0 +1,336 @@ +<?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"> +<defs > +<font id="OpenSans" horiz-adv-x="1206" ><font-face + font-family="Open Sans" + units-per-em="2048" + panose-1="2 11 6 6 3 5 4 2 2 4" + ascent="2189" + descent="-600" + alphabetic="0" /> +<glyph unicode=" " glyph-name="space" horiz-adv-x="532" /> +<glyph unicode="!" glyph-name="exclam" horiz-adv-x="547" d="M326 403H221L170 1462H377L326 403ZM152 106Q152 242 272 242Q330 242 361 207T393 106Q393 42 361 7T272 -29Q220 -29 186 2T152 106Z" /> +<glyph unicode=""" glyph-name="quotedbl" horiz-adv-x="821" d="M319 1462L279 934H174L133 1462H319ZM688 1462L647 934H543L502 1462H688Z" /> +<glyph unicode="#" glyph-name="numbersign" horiz-adv-x="1323" d="M981 899L915 559H1198V430H891L807 0H670L754 430H451L369 0H233L313 430H51V559H338L406 899H129V1026H428L510 1462H649L567 1026H872L956 1462H1090L1006 1026H1270V899H981ZM475 559H778L844 +899H541L475 559Z" /> +<glyph unicode="$" glyph-name="dollar" horiz-adv-x="1171" d="M1036 449Q1036 313 934 225T649 113V-119H520V104Q408 104 303 121T131 170V326Q214 289 322 266T520 242V682Q315 747 233 833T150 1055Q150 1186 251 1270T520 1372V1554H649V1374Q833 1369 1004 +1300L952 1169Q803 1228 649 1239V805Q806 755 884 708T999 599T1036 449ZM866 436Q866 508 822 552T649 641V252Q866 282 866 436ZM319 1057Q319 981 364 935T520 848V1235Q421 1219 370 1173T319 1057Z" /> +<glyph unicode="%" glyph-name="percent" horiz-adv-x="1686" d="M242 1026Q242 856 279 771T399 686Q563 686 563 1026Q563 1364 399 1364Q316 1364 279 1280T242 1026ZM700 1026Q700 798 624 682T399 565Q259 565 182 684T104 1026Q104 1253 178 1368T399 1483Q544 +1483 622 1364T700 1026ZM1122 440Q1122 269 1159 185T1280 100Q1364 100 1404 183T1444 440Q1444 611 1404 693T1280 776Q1196 776 1159 694T1122 440ZM1581 440Q1581 213 1505 97T1280 -20Q1138 -20 1062 99T985 440Q985 667 1059 782T1280 897Q1422 897 1501 +780T1581 440ZM1323 1462L512 0H365L1176 1462H1323Z" /> +<glyph unicode="&" glyph-name="ampersand" horiz-adv-x="1495" d="M414 1171Q414 1102 450 1040T573 889Q702 964 752 1027T803 1174Q803 1251 752 1299T614 1348Q525 1348 470 1300T414 1171ZM569 129Q810 129 969 283L532 707Q421 639 375 595T307 499T285 +383Q285 266 362 198T569 129ZM113 379Q113 509 182 609T432 811Q347 906 317 955T268 1057T250 1167Q250 1317 348 1401T621 1485Q783 1485 876 1402T969 1169Q969 1062 901 972T676 788L1083 397Q1139 459 1172 542T1229 725H1397Q1329 439 1192 291L1491 0H1262L1077 +178Q959 72 837 26T565 -20Q350 -20 232 86T113 379Z" /> +<glyph unicode="'" glyph-name="quotesingle" horiz-adv-x="453" d="M319 1462L279 934H174L133 1462H319Z" /> +<glyph unicode="(" glyph-name="parenleft" horiz-adv-x="606" d="M82 561Q82 826 159 1057T383 1462H545Q401 1269 329 1038T256 563Q256 323 330 94T543 -324H383Q236 -154 159 73T82 561Z" /> +<glyph unicode=")" glyph-name="parenright" horiz-adv-x="606" d="M524 561Q524 298 447 71T223 -324H63Q202 -136 276 93T350 563Q350 807 278 1038T61 1462H223Q370 1287 447 1056T524 561Z" /> +<glyph unicode="*" glyph-name="asterisk" horiz-adv-x="1130" d="M657 1556L614 1161L1012 1272L1038 1090L657 1059L905 733L733 639L557 1001L397 639L221 733L463 1059L86 1090L115 1272L506 1161L463 1556H657Z" /> +<glyph unicode="+" glyph-name="plus" horiz-adv-x="1171" d="M653 791H1065V653H653V227H514V653H104V791H514V1219H653V791Z" /> +<glyph unicode="," glyph-name="comma" horiz-adv-x="502" d="M350 238L365 215Q339 115 290 -17T188 -264H63Q90 -160 122 -7T168 238H350Z" /> +<glyph unicode="-" glyph-name="hyphen" horiz-adv-x="659" d="M84 473V625H575V473H84Z" /> +<glyph unicode="." glyph-name="period" horiz-adv-x="545" d="M152 106Q152 173 182 207T270 242Q328 242 360 208T393 106Q393 41 360 6T270 -29Q219 -29 186 2T152 106Z" /> +<glyph unicode="/" glyph-name="slash" horiz-adv-x="752" d="M731 1462L186 0H20L565 1462H731Z" /> +<glyph unicode="0" glyph-name="zero" horiz-adv-x="1171" d="M1069 733Q1069 354 950 167T584 -20Q348 -20 225 171T102 733Q102 1115 221 1300T584 1485Q822 1485 945 1292T1069 733ZM270 733Q270 414 345 269T584 123Q750 123 824 270T899 733Q899 1048 825 +1194T584 1341Q420 1341 345 1197T270 733Z" /> +<glyph unicode="1" glyph-name="one" horiz-adv-x="1171" d="M715 0H553V1042Q553 1172 561 1288Q540 1267 514 1244T276 1049L188 1163L575 1462H715V0Z" /> +<glyph unicode="2" glyph-name="two" horiz-adv-x="1171" d="M1061 0H100V143L485 530Q661 708 717 784T801 932T829 1087Q829 1204 758 1272T561 1341Q470 1341 389 1311T207 1202L119 1315Q321 1483 559 1483Q765 1483 882 1378T999 1094Q999 955 921 819T629 +475L309 162V154H1061V0Z" /> +<glyph unicode="3" glyph-name="three" horiz-adv-x="1171" d="M1006 1118Q1006 978 928 889T705 770V762Q881 740 966 650T1051 414Q1051 205 906 93T494 -20Q378 -20 282 -3T94 59V217Q189 170 296 146T500 121Q879 121 879 418Q879 684 461 684H317V827H463Q634 +827 734 902T834 1112Q834 1219 761 1280T561 1341Q465 1341 380 1315T186 1219L102 1331Q192 1402 309 1442T557 1483Q770 1483 888 1386T1006 1118Z" /> +<glyph unicode="4" glyph-name="four" horiz-adv-x="1171" d="M1130 336H913V0H754V336H43V481L737 1470H913V487H1130V336ZM754 487V973Q754 1116 764 1296H756Q708 1200 666 1137L209 487H754Z" /> +<glyph unicode="5" glyph-name="five" horiz-adv-x="1171" d="M557 893Q788 893 920 779T1053 465Q1053 238 909 109T510 -20Q263 -20 133 59V219Q203 174 307 149T512 123Q688 123 785 206T883 446Q883 752 508 752Q413 752 254 723L168 778L223 1462H950V1309H365L328 +870Q443 893 557 893Z" /> +<glyph unicode="6" glyph-name="six" horiz-adv-x="1171" d="M117 625Q117 1056 284 1269T780 1483Q893 1483 958 1464V1321Q881 1346 782 1346Q547 1346 423 1200T287 739H299Q409 911 647 911Q844 911 957 792T1071 469Q1071 241 947 111T610 -20Q383 -20 250 +150T117 625ZM608 121Q750 121 828 210T907 469Q907 614 834 697T616 780Q526 780 451 743T332 641T287 506Q287 403 327 314T440 173T608 121Z" /> +<glyph unicode="7" glyph-name="seven" horiz-adv-x="1171" d="M285 0L891 1309H94V1462H1067V1329L469 0H285Z" /> +<glyph unicode="8" glyph-name="eight" horiz-adv-x="1171" d="M584 1483Q784 1483 901 1390T1018 1133Q1018 1025 951 936T737 774Q915 689 990 596T1065 379Q1065 197 938 89T590 -20Q356 -20 230 82T104 373Q104 624 410 764Q272 842 212 932T152 1135Q152 +1294 269 1388T584 1483ZM268 369Q268 249 351 182T586 115Q735 115 818 185T901 377Q901 474 823 549T551 696Q402 632 335 555T268 369ZM582 1348Q457 1348 386 1288T315 1128Q315 1036 374 970T592 838Q735 898 794 967T854 1128Q854 1229 782 1288T582 1348Z" +/> +<glyph unicode="9" glyph-name="nine" horiz-adv-x="1171" d="M1061 838Q1061 -20 397 -20Q281 -20 213 0V143Q293 117 395 117Q635 117 757 265T891 721H879Q824 638 733 595T528 551Q334 551 220 667T106 991Q106 1219 233 1351T569 1483Q718 1483 829 1407T1001 +1184T1061 838ZM569 1341Q426 1341 348 1249T270 993Q270 849 342 767T561 684Q652 684 728 721T849 822T893 956Q893 1061 852 1150T738 1290T569 1341Z" /> +<glyph unicode=":" glyph-name="colon" horiz-adv-x="545" d="M152 106Q152 173 182 207T270 242Q328 242 360 208T393 106Q393 41 360 6T270 -29Q219 -29 186 2T152 106ZM152 989Q152 1124 270 1124Q393 1124 393 989Q393 924 360 889T270 854Q219 854 186 885T152 989Z" /> +<glyph unicode=";" glyph-name="semicolon" horiz-adv-x="545" d="M350 238L365 215Q339 115 290 -17T188 -264H63Q90 -160 122 -7T168 238H350ZM147 989Q147 1124 266 1124Q389 1124 389 989Q389 924 356 889T266 854Q208 854 178 889T147 989Z" /> +<glyph unicode="<" glyph-name="less" horiz-adv-x="1171" d="M1065 242L104 664V762L1065 1241V1092L283 721L1065 393V242Z" /> +<glyph unicode="=" glyph-name="equal" horiz-adv-x="1171" d="M119 858V995H1049V858H119ZM119 449V586H1049V449H119Z" /> +<glyph unicode=">" glyph-name="greater" horiz-adv-x="1171" d="M104 393L887 719L104 1092V1241L1065 762V664L104 242V393Z" /> +<glyph unicode="?" glyph-name="question" horiz-adv-x="879" d="M289 403V457Q289 574 325 649T459 809Q595 924 630 982T666 1122Q666 1224 601 1279T412 1335Q333 1335 258 1317T86 1249L27 1384Q216 1483 422 1483Q613 1483 719 1389T825 1124Q825 1051 806 +996T748 891T584 731Q483 645 451 588T418 436V403H289ZM240 106Q240 242 360 242Q418 242 449 207T481 106Q481 42 449 7T360 -29Q308 -29 274 2T240 106Z" /> +<glyph unicode="@" glyph-name="at" horiz-adv-x="1841" d="M1720 729Q1720 587 1676 469T1552 286T1368 221Q1282 221 1223 273T1153 406H1145Q1105 319 1031 270T854 221Q704 221 620 323T535 602Q535 806 653 933T963 1061Q1031 1061 1117 1049T1272 1014L1247 +544V522Q1247 344 1380 344Q1471 344 1528 451T1585 731Q1585 912 1511 1048T1301 1257T987 1331Q764 1331 599 1239T347 975T260 578Q260 273 421 109T885 -55Q1095 -55 1321 31V-102Q1129 -186 885 -186Q522 -186 322 13T121 571Q121 831 228 1034T533 1348T987 +1460Q1202 1460 1369 1370T1628 1113T1720 729ZM686 598Q686 344 881 344Q1088 344 1106 657L1120 918Q1048 938 963 938Q833 938 760 848T686 598Z" /> +<glyph unicode="A" glyph-name="A" horiz-adv-x="1296" d="M1120 0L938 465H352L172 0H0L578 1468H721L1296 0H1120ZM885 618L715 1071Q682 1157 647 1282Q625 1186 584 1071L412 618H885Z" /> +<glyph unicode="B" glyph-name="B" horiz-adv-x="1327" d="M201 1462H614Q905 1462 1035 1375T1165 1100Q1165 970 1093 886T881 776V766Q1214 709 1214 416Q1214 220 1082 110T711 0H201V1462ZM371 836H651Q831 836 910 892T989 1083Q989 1206 901 1260T621 1315H371V836ZM371 +692V145H676Q853 145 942 213T1032 428Q1032 564 941 628T662 692H371Z" /> +<glyph unicode="C" glyph-name="C" horiz-adv-x="1292" d="M827 1331Q586 1331 447 1171T307 731Q307 444 441 288T825 131Q978 131 1174 186V37Q1022 -20 799 -20Q476 -20 301 176T125 733Q125 959 209 1129T453 1391T829 1483Q1059 1483 1231 1399L1159 1253Q993 +1331 827 1331Z" /> +<glyph unicode="D" glyph-name="D" horiz-adv-x="1493" d="M1368 745Q1368 383 1172 192T606 0H201V1462H649Q990 1462 1179 1273T1368 745ZM1188 739Q1188 1025 1045 1170T618 1315H371V147H578Q882 147 1035 296T1188 739Z" /> +<glyph unicode="E" glyph-name="E" horiz-adv-x="1139" d="M1016 0H201V1462H1016V1311H371V840H977V690H371V152H1016V0Z" /> +<glyph unicode="F" glyph-name="F" horiz-adv-x="1057" d="M371 0H201V1462H1016V1311H371V776H977V625H371V0Z" /> +<glyph unicode="G" glyph-name="G" horiz-adv-x="1491" d="M844 766H1341V55Q1225 18 1105 -1T827 -20Q495 -20 310 177T125 731Q125 959 216 1130T480 1392T883 1483Q1117 1483 1319 1397L1253 1247Q1055 1331 872 1331Q605 1331 455 1172T305 731Q305 435 449 +282T874 129Q1026 129 1171 164V614H844V766Z" /> +<glyph unicode="H" glyph-name="H" horiz-adv-x="1511" d="M1311 0H1141V688H371V0H201V1462H371V840H1141V1462H1311V0Z" /> +<glyph unicode="I" glyph-name="I" horiz-adv-x="571" d="M201 0V1462H371V0H201Z" /> +<glyph unicode="J" glyph-name="J" horiz-adv-x="547" d="M-12 -385Q-106 -385 -160 -358V-213Q-89 -233 -12 -233Q87 -233 138 -173T190 0V1462H360V14Q360 -176 264 -280T-12 -385Z" /> +<glyph unicode="K" glyph-name="K" horiz-adv-x="1257" d="M1257 0H1057L524 709L371 573V0H201V1462H371V737L1034 1462H1235L647 827L1257 0Z" /> +<glyph unicode="L" glyph-name="L" horiz-adv-x="1063" d="M201 0V1462H371V154H1016V0H201Z" /> +<glyph unicode="M" glyph-name="M" horiz-adv-x="1849" d="M848 0L352 1296H344Q358 1142 358 930V0H201V1462H457L920 256H928L1395 1462H1649V0H1479V942Q1479 1104 1493 1294H1485L985 0H848Z" /> +<glyph unicode="N" glyph-name="N" horiz-adv-x="1544" d="M1343 0H1149L350 1227H342Q358 1011 358 831V0H201V1462H393L1190 240H1198Q1196 267 1189 413T1184 623V1462H1343V0Z" /> +<glyph unicode="O" glyph-name="O" horiz-adv-x="1595" d="M1470 733Q1470 382 1293 181T799 -20Q476 -20 301 177T125 735Q125 1092 301 1288T801 1485Q1116 1485 1293 1285T1470 733ZM305 733Q305 436 431 283T799 129Q1042 129 1166 282T1290 733Q1290 1028 +1167 1180T801 1333Q558 1333 432 1180T305 733Z" /> +<glyph unicode="P" glyph-name="P" horiz-adv-x="1233" d="M1128 1036Q1128 814 977 695T543 575H371V0H201V1462H580Q1128 1462 1128 1036ZM371 721H524Q750 721 851 794T952 1028Q952 1173 857 1244T561 1315H371V721Z" /> +<glyph unicode="Q" glyph-name="Q" horiz-adv-x="1595" d="M1470 733Q1470 452 1357 266T1038 14L1386 -348H1139L854 -18L799 -20Q476 -20 301 177T125 735Q125 1092 301 1288T801 1485Q1116 1485 1293 1285T1470 733ZM305 733Q305 436 431 283T799 129Q1042 +129 1166 282T1290 733Q1290 1028 1167 1180T801 1333Q558 1333 432 1180T305 733Z" /> +<glyph unicode="R" glyph-name="R" horiz-adv-x="1266" d="M371 608V0H201V1462H602Q871 1462 999 1359T1128 1049Q1128 759 834 657L1231 0H1030L676 608H371ZM371 754H604Q784 754 868 825T952 1040Q952 1185 867 1249T592 1313H371V754Z" /> +<glyph unicode="S" glyph-name="S" horiz-adv-x="1124" d="M1026 389Q1026 196 886 88T506 -20Q246 -20 106 47V211Q196 173 302 151T512 129Q682 129 768 193T854 373Q854 449 824 497T722 587T504 680Q300 753 213 853T125 1114Q125 1283 252 1383T588 1483Q806 +1483 989 1403L936 1255Q755 1331 584 1331Q449 1331 373 1273T297 1112Q297 1036 325 988T419 899T623 809Q853 727 939 633T1026 389Z" /> +<glyph unicode="T" glyph-name="T" horiz-adv-x="1133" d="M651 0H481V1311H18V1462H1114V1311H651V0Z" /> +<glyph unicode="U" glyph-name="U" horiz-adv-x="1491" d="M1305 1462V516Q1305 266 1154 123T739 -20Q475 -20 331 124T186 520V1462H356V508Q356 325 456 227T750 129Q935 129 1035 227T1135 510V1462H1305Z" /> +<glyph unicode="V" glyph-name="V" horiz-adv-x="1219" d="M1036 1462H1219L692 0H524L0 1462H180L516 516Q574 353 608 199Q644 361 702 522L1036 1462Z" /> +<glyph unicode="W" glyph-name="W" horiz-adv-x="1896" d="M1477 0H1309L1014 979Q993 1044 967 1143T940 1262Q918 1130 870 973L584 0H416L27 1462H207L438 559Q486 369 508 215Q535 398 588 573L850 1462H1030L1305 565Q1353 410 1386 215Q1405 357 1458 561L1688 +1462H1868L1477 0Z" /> +<glyph unicode="X" glyph-name="X" horiz-adv-x="1182" d="M1174 0H981L588 643L188 0H8L494 764L41 1462H229L592 883L958 1462H1139L686 770L1174 0Z" /> +<glyph unicode="Y" glyph-name="Y" horiz-adv-x="1147" d="M573 731L963 1462H1147L659 567V0H487V559L0 1462H186L573 731Z" /> +<glyph unicode="Z" glyph-name="Z" horiz-adv-x="1169" d="M1087 0H82V133L858 1309H106V1462H1065V1329L289 154H1087V0Z" /> +<glyph unicode="[" glyph-name="bracketleft" horiz-adv-x="674" d="M623 -324H166V1462H623V1321H334V-182H623V-324Z" /> +<glyph unicode="\" glyph-name="backslash" horiz-adv-x="752" d="M186 1462L733 0H567L23 1462H186Z" /> +<glyph unicode="]" glyph-name="bracketright" horiz-adv-x="674" d="M51 -182H340V1321H51V1462H508V-324H51V-182Z" /> +<glyph unicode="^" glyph-name="asciicircum" horiz-adv-x="1110" d="M49 551L483 1473H582L1059 551H907L535 1296L201 551H49Z" /> +<glyph unicode="_" glyph-name="underscore" horiz-adv-x="918" d="M922 -315H-4V-184H922V-315Z" /> +<glyph unicode="`" glyph-name="grave" horiz-adv-x="1182" d="M786 1241H676Q611 1293 522 1389T393 1548V1569H596Q628 1500 685 1410T786 1266V1241Z" /> +<glyph unicode="a" glyph-name="a" horiz-adv-x="1139" d="M850 0L817 156H809Q727 53 646 17T442 -20Q279 -20 187 64T94 303Q94 635 625 651L811 657V725Q811 854 756 915T578 977Q441 977 268 893L217 1020Q298 1064 394 1089T588 1114Q784 1114 878 1027T973 +748V0H850ZM475 117Q630 117 718 202T807 440V539L641 532Q443 525 356 471T268 301Q268 211 322 164T475 117Z" /> +<glyph unicode="b" glyph-name="b" horiz-adv-x="1255" d="M686 1114Q902 1114 1021 967T1141 549Q1141 279 1021 130T686 -20Q579 -20 491 19T342 141H330L295 0H176V1556H342V1178Q342 1051 334 950H342Q458 1114 686 1114ZM662 975Q492 975 417 878T342 549Q342 +318 419 219T666 119Q819 119 894 230T969 551Q969 765 894 870T662 975Z" /> +<glyph unicode="c" glyph-name="c" horiz-adv-x="975" d="M614 -20Q376 -20 246 126T115 541Q115 816 247 966T625 1116Q704 1116 783 1099T907 1059L856 918Q801 940 736 954T621 969Q287 969 287 543Q287 341 368 233T610 125Q747 125 891 184V37Q781 -20 614 -20Z" /> +<glyph unicode="d" glyph-name="d" horiz-adv-x="1255" d="M922 147H913Q798 -20 569 -20Q354 -20 235 127T115 545Q115 816 235 966T569 1116Q792 1116 911 954H924L917 1033L913 1110V1556H1079V0H944L922 147ZM590 119Q760 119 836 211T913 510V545Q913 778 +836 877T588 977Q442 977 365 864T287 543Q287 333 364 226T590 119Z" /> +<glyph unicode="e" glyph-name="e" horiz-adv-x="1149" d="M639 -20Q396 -20 256 128T115 539Q115 804 245 960T596 1116Q802 1116 922 981T1042 623V518H287Q292 325 384 225T645 125Q822 125 995 199V51Q907 13 829 -3T639 -20ZM594 977Q462 977 384 891T291 +653H864Q864 810 794 893T594 977Z" /> +<glyph unicode="f" glyph-name="f" horiz-adv-x="694" d="M670 967H391V0H225V967H29V1042L225 1102V1163Q225 1567 578 1567Q665 1567 782 1532L739 1399Q643 1430 575 1430Q481 1430 436 1368T391 1167V1096H670V967Z" /> +<glyph unicode="g" glyph-name="g" horiz-adv-x="1122" d="M1073 1096V991L870 967Q898 932 920 876T942 748Q942 587 832 491T530 395Q481 395 438 403Q332 347 332 262Q332 217 369 196T496 174H690Q868 174 963 99T1059 -119Q1059 -301 913 -396T487 -492Q272 +-492 156 -412T39 -186Q39 -86 103 -13T283 86Q241 105 213 145T184 238Q184 298 216 343T317 430Q232 465 179 549T125 741Q125 921 233 1018T539 1116Q625 1116 694 1096H1073ZM199 -184Q199 -273 274 -319T489 -365Q698 -365 798 -303T899 -133Q899 -44 844 +-10T637 25H438Q325 25 262 -29T199 -184ZM289 745Q289 630 354 571T535 512Q778 512 778 748Q778 995 532 995Q415 995 352 932T289 745Z" /> +<glyph unicode="h" glyph-name="h" horiz-adv-x="1257" d="M926 0V709Q926 843 865 909T674 975Q501 975 422 881T342 573V0H176V1556H342V1085Q342 1000 334 944H344Q393 1023 483 1068T690 1114Q891 1114 991 1019T1092 715V0H926Z" /> +<glyph unicode="i" glyph-name="i" horiz-adv-x="518" d="M342 0H176V1096H342V0ZM162 1393Q162 1450 190 1476T260 1503Q300 1503 329 1476T358 1393Q358 1337 329 1310T260 1282Q218 1282 190 1309T162 1393Z" /> +<glyph unicode="j" glyph-name="j" horiz-adv-x="518" d="M43 -492Q-52 -492 -111 -467V-332Q-42 -352 25 -352Q103 -352 139 -310T176 -180V1096H342V-168Q342 -492 43 -492ZM162 1393Q162 1450 190 1476T260 1503Q300 1503 329 1476T358 1393Q358 1337 329 1310T260 +1282Q218 1282 190 1309T162 1393Z" /> +<glyph unicode="k" glyph-name="k" horiz-adv-x="1075" d="M340 561Q383 622 471 721L825 1096H1022L578 629L1053 0H852L465 518L340 410V0H176V1556H340V731Q340 676 332 561H340Z" /> +<glyph unicode="l" glyph-name="l" horiz-adv-x="518" d="M342 0H176V1556H342V0Z" /> +<glyph unicode="m" glyph-name="m" horiz-adv-x="1905" d="M1573 0V713Q1573 844 1517 909T1343 975Q1188 975 1114 886T1040 612V0H874V713Q874 844 818 909T643 975Q487 975 415 882T342 575V0H176V1096H311L338 946H346Q393 1026 478 1071T670 1116Q927 1116 +1006 930H1014Q1063 1016 1156 1066T1368 1116Q1554 1116 1646 1021T1739 715V0H1573Z" /> +<glyph unicode="n" glyph-name="n" horiz-adv-x="1257" d="M926 0V709Q926 843 865 909T674 975Q502 975 422 882T342 575V0H176V1096H311L338 946H346Q397 1027 489 1071T694 1116Q892 1116 992 1021T1092 715V0H926Z" /> +<glyph unicode="o" glyph-name="o" horiz-adv-x="1237" d="M1122 549Q1122 281 987 131T614 -20Q467 -20 353 49T177 247T115 549Q115 817 249 966T621 1116Q851 1116 986 963T1122 549ZM287 549Q287 339 371 229T618 119Q781 119 865 228T950 549Q950 758 866 +866T616 975Q453 975 370 868T287 549Z" /> +<glyph unicode="p" glyph-name="p" horiz-adv-x="1255" d="M686 -20Q579 -20 491 19T342 141H330Q342 45 342 -41V-492H176V1096H311L334 946H342Q406 1036 491 1076T686 1116Q904 1116 1022 967T1141 549Q1141 279 1021 130T686 -20ZM662 975Q494 975 419 882T342 +586V549Q342 318 419 219T666 119Q808 119 888 234T969 551Q969 756 889 865T662 975Z" /> +<glyph unicode="q" glyph-name="q" horiz-adv-x="1255" d="M590 119Q756 119 832 208T913 508V545Q913 775 835 876T588 977Q442 977 365 864T287 543Q287 336 363 228T590 119ZM565 -20Q353 -20 234 129T115 545Q115 814 235 965T569 1116Q794 1116 915 946H924L948 +1096H1079V-492H913V-23Q913 77 924 147H911Q796 -20 565 -20Z" /> +<glyph unicode="r" glyph-name="r" horiz-adv-x="836" d="M676 1116Q749 1116 807 1104L784 950Q716 965 664 965Q531 965 437 857T342 588V0H176V1096H313L332 893H340Q401 1000 487 1058T676 1116Z" /> +<glyph unicode="s" glyph-name="s" horiz-adv-x="977" d="M883 299Q883 146 769 63T449 -20Q231 -20 109 49V203Q188 163 278 140T453 117Q583 117 653 158T723 285Q723 349 668 394T451 502Q298 559 234 601T138 698T106 827Q106 961 215 1038T514 1116Q691 1116 +860 1044L801 909Q636 977 502 977Q384 977 324 940T264 838Q264 794 286 763T359 704T551 623Q746 552 814 480T883 299Z" /> +<glyph unicode="t" glyph-name="t" horiz-adv-x="723" d="M530 117Q574 117 615 123T680 137V10Q653 -3 601 -11T506 -20Q188 -20 188 315V967H31V1047L188 1116L258 1350H354V1096H672V967H354V322Q354 223 401 170T530 117Z" /> +<glyph unicode="u" glyph-name="u" horiz-adv-x="1257" d="M332 1096V385Q332 251 393 185T584 119Q756 119 835 213T915 520V1096H1081V0H944L920 147H911Q860 66 770 23T563 -20Q363 -20 264 75T164 379V1096H332Z" /> +<glyph unicode="v" glyph-name="v" horiz-adv-x="1026" d="M416 0L0 1096H178L414 446Q494 218 508 150H516Q527 203 585 369T848 1096H1026L610 0H416Z" /> +<glyph unicode="w" glyph-name="w" horiz-adv-x="1593" d="M1071 0L870 643Q851 702 799 911H791Q751 736 721 641L514 0H322L23 1096H197Q303 683 358 467T422 176H430Q441 233 465 323T508 467L709 1096H889L1085 467Q1141 295 1161 178H1169Q1173 214 1190 +289T1399 1096H1571L1268 0H1071Z" /> +<glyph unicode="x" glyph-name="x" horiz-adv-x="1073" d="M440 561L59 1096H248L537 676L825 1096H1012L631 561L1032 0H844L537 444L227 0H39L440 561Z" /> +<glyph unicode="y" glyph-name="y" horiz-adv-x="1032" d="M2 1096H180L420 471Q499 257 518 162H526Q539 213 580 336T852 1096H1030L559 -152Q489 -337 396 -414T166 -492Q90 -492 16 -475V-342Q71 -354 139 -354Q310 -354 383 -162L444 -6L2 1096Z" /> +<glyph unicode="z" glyph-name="z" horiz-adv-x="958" d="M877 0H82V113L680 967H119V1096H862V967L272 129H877V0Z" /> +<glyph unicode="{" glyph-name="braceleft" horiz-adv-x="776" d="M475 12Q475 -90 533 -136T705 -184V-324Q515 -322 411 -237T307 2V305Q307 409 244 453T61 498V639Q191 641 249 687T307 829V1135Q307 1290 415 1376T705 1462V1323Q475 1317 475 1124V829Q475 +614 252 575V563Q475 524 475 309V12Z" /> +<glyph unicode="|" glyph-name="bar" horiz-adv-x="1128" d="M494 1556H635V-496H494V1556Z" /> +<glyph unicode="}" glyph-name="braceright" horiz-adv-x="776" d="M522 575Q299 614 299 829V1124Q299 1317 72 1323V1462Q256 1462 361 1375T467 1135V829Q467 732 526 687T715 639V498Q593 498 530 454T467 305V2Q467 -151 365 -236T72 -324V-184Q183 -182 +241 -136T299 12V309Q299 423 354 483T522 563V575Z" /> +<glyph unicode="~" glyph-name="asciitilde" horiz-adv-x="1171" d="M338 713Q285 713 222 680T104 592V743Q204 852 348 852Q416 852 472 838T618 786Q684 758 733 745T829 731Q883 731 947 763T1065 852V702Q963 592 821 592Q749 592 686 608T551 657Q476 689 +431 701T338 713Z" /> +<glyph unicode=" " glyph-name="nbspace" horiz-adv-x="532" /> +<glyph unicode="¡" glyph-name="exclamdown" horiz-adv-x="547" d="M219 684H324L375 -373H168L219 684ZM393 983Q393 848 272 848Q212 848 182 883T152 983Q152 1046 183 1082T272 1118Q323 1118 358 1086T393 983Z" /> +<glyph unicode="¢" glyph-name="cent" horiz-adv-x="1171" d="M971 240Q866 186 719 180V-20H586V186Q383 218 287 354T190 741Q190 1249 586 1311V1483H721V1319Q796 1316 867 1300T987 1260L938 1120Q805 1171 696 1171Q524 1171 443 1066T362 743Q362 +531 441 430T688 328Q829 328 971 387V240Z" /> +<glyph unicode="£" glyph-name="sterling" horiz-adv-x="1171" d="M682 1481Q872 1481 1042 1397L981 1264Q827 1341 684 1341Q561 1341 499 1279T436 1077V782H858V655H436V434Q436 334 404 266T297 154H1092V0H63V141Q268 188 268 432V655H70V782H268V1098Q268 +1276 380 1378T682 1481Z" /> +<glyph unicode="¤" glyph-name="currency" horiz-adv-x="1171" d="M184 723Q184 845 258 952L123 1092L217 1184L352 1051Q456 1124 586 1124Q713 1124 815 1051L952 1184L1047 1092L913 954Q987 841 987 723Q987 592 913 489L1044 354L952 262L815 395Q713 +324 586 324Q452 324 352 397L217 264L125 356L258 492Q184 599 184 723ZM313 723Q313 611 391 531T586 451Q702 451 781 530T860 723Q860 837 780 918T586 999Q470 999 392 917T313 723Z" /> +<glyph unicode="¥" glyph-name="yen" horiz-adv-x="1171" d="M584 735L963 1462H1137L721 692H983V565H666V395H983V268H666V0H502V268H186V395H502V565H186V692H442L31 1462H209L584 735Z" /> +<glyph unicode="¦" glyph-name="brokenbar" horiz-adv-x="1128" d="M494 1556H635V780H494V1556ZM494 281H635V-496H494V281Z" /> +<glyph unicode="§" glyph-name="section" horiz-adv-x="1057" d="M139 809Q139 895 182 963T303 1069Q229 1109 187 1164T145 1305Q145 1426 248 1495T549 1565Q643 1565 722 1551T899 1497L846 1366Q748 1405 681 1418T537 1432Q421 1432 363 1403T305 1309Q305 +1249 366 1207T582 1110Q768 1042 843 967T918 784Q918 694 877 624T762 512Q915 431 915 285Q915 145 798 69T469 -8Q251 -8 123 57V205Q201 168 298 146T477 123Q611 123 681 161T752 270Q752 316 728 345T650 403T481 475Q339 527 272 572T172 674T139 809ZM285 +829Q285 752 351 700T584 586L633 567Q770 647 770 758Q770 841 697 897T438 1010Q370 991 328 941T285 829Z" /> +<glyph unicode="¨" glyph-name="dieresis" horiz-adv-x="1182" d="M309 1393Q309 1445 335 1468T399 1491Q437 1491 464 1468T492 1393Q492 1343 465 1319T399 1294Q362 1294 336 1318T309 1393ZM690 1393Q690 1445 716 1468T780 1491Q817 1491 844 1468T872 +1393Q872 1343 845 1319T780 1294Q743 1294 717 1318T690 1393Z" /> +<glyph unicode="©" glyph-name="copyright" horiz-adv-x="1704" d="M893 1059Q768 1059 701 972T633 731Q633 563 696 482T891 401Q977 401 1102 446V322Q1054 302 1004 288T883 274Q689 274 585 394T481 731Q481 940 591 1063T893 1186Q1021 1186 1139 1126L1081 +1008Q973 1059 893 1059ZM100 731Q100 931 200 1106T475 1382T852 1483Q1052 1483 1227 1383T1503 1108T1604 731Q1604 534 1507 361T1235 84T852 -20Q645 -20 470 83T198 360T100 731ZM205 731Q205 558 292 408T529 171T852 84Q1026 84 1175 171T1411 406T1499 +731Q1499 905 1412 1054T1177 1290T852 1378Q678 1378 529 1291T293 1056T205 731Z" /> +<glyph unicode="ª" glyph-name="ordfeminine" horiz-adv-x="725" d="M532 801L508 885Q416 788 276 788Q181 788 126 837T70 989Q70 1091 147 1143T389 1202L506 1206V1245Q506 1378 358 1378Q258 1378 154 1327L111 1423Q225 1479 358 1479Q488 1479 556 +1427T625 1253V801H532ZM193 989Q193 889 305 889Q506 889 506 1069V1118L408 1114Q296 1110 245 1082T193 989Z" /> +<glyph unicode="«" glyph-name="guillemotleft" horiz-adv-x="1018" d="M82 551L424 958L543 889L254 539L543 188L424 117L82 524V551ZM477 551L821 958L938 889L651 539L938 188L821 117L477 524V551Z" /> +<glyph unicode="¬" glyph-name="logicalnot" horiz-adv-x="1171" d="M1065 791V264H928V653H104V791H1065Z" /> +<glyph unicode="­" glyph-name="uni00AD" horiz-adv-x="659" d="M84 473V625H575V473H84Z" /> +<glyph unicode="®" glyph-name="registered" horiz-adv-x="1704" d="M723 762H831Q911 762 959 803T1008 909Q1008 984 965 1016T829 1049H723V762ZM1157 913Q1157 833 1115 772T995 680L1233 285H1065L858 639H723V285H575V1176H836Q1002 1176 1079 1111T1157 +913ZM100 731Q100 931 200 1106T475 1382T852 1483Q1052 1483 1227 1383T1503 1108T1604 731Q1604 534 1507 361T1235 84T852 -20Q645 -20 470 83T198 360T100 731ZM205 731Q205 558 292 408T529 171T852 84Q1026 84 1175 171T1411 406T1499 731Q1499 905 1412 +1054T1177 1290T852 1378Q678 1378 529 1291T293 1056T205 731Z" /> +<glyph unicode="¯" glyph-name="overscore" horiz-adv-x="1024" d="M1030 1556H-6V1683H1030V1556Z" /> +<glyph unicode="°" glyph-name="degree" horiz-adv-x="877" d="M127 1171Q127 1301 217 1392T438 1483Q568 1483 659 1393T750 1171Q750 1087 709 1016T595 902T438 860Q308 860 218 950T127 1171ZM242 1171Q242 1089 300 1032T440 975Q520 975 577 1031T635 +1171Q635 1255 579 1311T440 1368Q357 1368 300 1311T242 1171Z" /> +<glyph unicode="±" glyph-name="plusminus" horiz-adv-x="1171" d="M653 791H1065V653H653V227H514V653H104V791H514V1219H653V791ZM104 1V139H1065V1H104Z" /> +<glyph unicode="²" glyph-name="twosuperior" horiz-adv-x="711" d="M653 586H49V690L285 920Q374 1006 415 1054T472 1141T489 1233Q489 1301 449 1335T346 1370Q294 1370 245 1351T127 1282L61 1370Q192 1481 344 1481Q476 1481 549 1416T623 1239Q623 +1159 579 1084T387 870L213 705H653V586Z" /> +<glyph unicode="³" glyph-name="threesuperior" horiz-adv-x="711" d="M627 1255Q627 1175 586 1124T477 1049Q653 1002 653 840Q653 712 561 641T301 569Q149 569 33 625V748Q180 680 303 680Q514 680 514 842Q514 987 283 987H166V1094H285Q388 1094 437 +1133T487 1241Q487 1302 447 1336T340 1370Q274 1370 218 1349T106 1292L37 1382Q100 1427 170 1454T334 1481Q470 1481 548 1422T627 1255Z" /> +<glyph unicode="´" glyph-name="acute" horiz-adv-x="1182" d="M393 1266Q441 1328 496 1416T584 1569H786V1548Q742 1483 655 1388T504 1241H393V1266Z" /> +<glyph unicode="µ" glyph-name="mu" horiz-adv-x="1268" d="M342 381Q342 119 596 119Q767 119 846 213T926 520V1096H1092V0H956L930 147H920Q809 -20 580 -20Q430 -20 342 72H332Q342 -12 342 -172V-492H176V1096H342V381Z" /> +<glyph unicode="¶" glyph-name="paragraph" horiz-adv-x="1341" d="M1120 -260H1006V1452H793V-260H678V559Q616 541 532 541Q316 541 215 666T113 1042Q113 1302 222 1429T563 1556H1120V-260Z" /> +<glyph unicode="·" glyph-name="middot" horiz-adv-x="545" d="M152 723Q152 789 183 823T270 858Q328 858 360 824T393 723Q393 658 360 623T270 588Q219 588 186 619T152 723Z" /> +<glyph unicode="¸" glyph-name="cedilla" horiz-adv-x="465" d="M436 -289Q436 -386 360 -439T133 -492Q82 -492 37 -483V-377Q82 -385 141 -385Q220 -385 260 -365T301 -291Q301 -248 262 -222T113 -178L201 0H311L256 -115Q436 -154 436 -289Z" /> +<glyph unicode="¹" glyph-name="onesuperior" horiz-adv-x="711" d="M338 1462H481V586H348V1165Q348 1256 354 1346Q332 1324 305 1302T143 1184L76 1280L338 1462Z" /> +<glyph unicode="º" glyph-name="ordmasculine" horiz-adv-x="768" d="M702 1135Q702 971 617 880T381 788Q235 788 151 881T66 1135Q66 1298 150 1388T385 1479Q537 1479 619 1388T702 1135ZM188 1135Q188 1013 233 952T383 891Q488 891 534 952T580 1135Q580 +1258 534 1317T383 1376Q280 1376 234 1317T188 1135Z" /> +<glyph unicode="»" glyph-name="guillemotright" horiz-adv-x="1018" d="M936 524L592 117L475 188L762 539L475 889L592 958L936 551V524ZM541 524L197 117L80 188L367 539L80 889L197 958L541 551V524Z" /> +<glyph unicode="¼" glyph-name="onequarter" horiz-adv-x="1597" d="M1298 1462L395 0H252L1155 1462H1298ZM593 1462H736V586H603V1165Q603 1256 609 1346Q587 1324 560 1302T398 1184L331 1280L593 1462ZM1489 203H1364V1H1219V203H817V304L1225 883H1364V320H1489V203ZM1219 +320V515Q1219 649 1225 724Q1220 712 1208 693T1181 651T1151 606T1125 566L957 320H1219Z" /> +<glyph unicode="½" glyph-name="onehalf" horiz-adv-x="1597" d="M1230 1462L327 0H184L1087 1462H1230ZM564 1462H707V586H574V1165Q574 1256 580 1346Q558 1324 531 1302T369 1184L302 1280L564 1462ZM1499 1H895V105L1131 335Q1220 421 1261 469T1318 +556T1335 648Q1335 716 1295 750T1192 785Q1140 785 1091 766T973 697L907 785Q1038 896 1190 896Q1322 896 1395 831T1469 654Q1469 574 1425 499T1233 285L1059 120H1499V1Z" /> +<glyph unicode="¾" glyph-name="threequarters" horiz-adv-x="1597" d="M876 1255Q876 1175 835 1124T726 1049Q902 1002 902 840Q902 712 810 641T550 569Q398 569 282 625V748Q429 680 552 680Q763 680 763 842Q763 987 532 987H415V1094H534Q637 1094 +686 1133T736 1241Q736 1302 696 1336T589 1370Q523 1370 467 1349T355 1292L286 1382Q349 1427 419 1454T583 1481Q719 1481 797 1422T876 1255ZM1390 1462L487 0H344L1247 1462H1390ZM1569 203H1444V1H1299V203H897V304L1305 883H1444V320H1569V203ZM1299 320V515Q1299 +649 1305 724Q1300 712 1288 693T1261 651T1231 606T1205 566L1037 320H1299Z" /> +<glyph unicode="¿" glyph-name="questiondown" horiz-adv-x="879" d="M590 684V633Q590 511 553 437T418 279Q297 173 267 136T224 60T211 -35Q211 -135 277 -191T465 -248Q545 -248 620 -229T793 -162L852 -297Q655 -393 457 -393Q267 -393 159 -300T51 +-37Q51 33 68 85T118 182T194 268T293 356Q394 444 426 502T459 653V684H590ZM639 983Q639 848 518 848Q459 848 428 882T397 983Q397 1047 430 1082T518 1118Q569 1118 604 1086T639 983Z" /> +<glyph unicode="À" glyph-name="Agrave" horiz-adv-x="1296" d="M1120 0L938 465H352L172 0H0L578 1468H721L1296 0H1120ZM885 618L715 1071Q682 1157 647 1282Q625 1186 584 1071L412 618H885ZM724 1579H614Q549 1631 460 1727T331 1886V1907H534Q566 1838 +623 1748T724 1604V1579Z" /> +<glyph unicode="Á" glyph-name="Aacute" horiz-adv-x="1296" d="M1120 0L938 465H352L172 0H0L578 1468H721L1296 0H1120ZM885 618L715 1071Q682 1157 647 1282Q625 1186 584 1071L412 618H885ZM526 1604Q574 1666 629 1754T717 1907H919V1886Q875 1821 788 +1726T637 1579H526V1604Z" /> +<glyph unicode="Â" glyph-name="Acircumflex" horiz-adv-x="1296" d="M1120 0L938 465H352L172 0H0L578 1468H721L1296 0H1120ZM885 618L715 1071Q682 1157 647 1282Q625 1186 584 1071L412 618H885ZM303 1602Q430 1738 481 1802T555 1907H721Q743 1865 797 +1799T977 1602V1579H858Q770 1634 637 1765Q501 1631 418 1579H303V1602Z" /> +<glyph unicode="Ã" glyph-name="Atilde" horiz-adv-x="1296" d="M1120 0L938 465H352L172 0H0L578 1468H721L1296 0H1120ZM885 618L715 1071Q682 1157 647 1282Q625 1186 584 1071L412 618H885ZM792 1581Q749 1581 708 1599T628 1640T552 1681T481 1700Q431 +1700 406 1670T366 1579H268Q281 1700 338 1768T487 1837Q533 1837 576 1819T658 1778T733 1737T801 1718Q850 1718 874 1747T913 1839H1012Q999 1718 943 1650T792 1581Z" /> +<glyph unicode="Ä" glyph-name="Adieresis" horiz-adv-x="1296" d="M1120 0L938 465H352L172 0H0L578 1468H721L1296 0H1120ZM885 618L715 1071Q682 1157 647 1282Q625 1186 584 1071L412 618H885ZM364 1731Q364 1783 390 1806T454 1829Q492 1829 519 1806T547 +1731Q547 1681 520 1657T454 1632Q417 1632 391 1656T364 1731ZM745 1731Q745 1783 771 1806T835 1829Q872 1829 899 1806T927 1731Q927 1681 900 1657T835 1632Q798 1632 772 1656T745 1731Z" /> +<glyph unicode="Å" glyph-name="Aring" horiz-adv-x="1296" d="M1120 0L938 465H352L172 0H0L578 1468H721L1296 0H1120ZM885 618L715 1071Q682 1157 647 1282Q625 1186 584 1071L412 618H885ZM870 1587Q870 1489 809 1430T645 1370Q544 1370 484 1428T424 +1585Q424 1683 484 1740T645 1798Q746 1798 808 1739T870 1587ZM762 1585Q762 1641 729 1671T645 1702Q594 1702 561 1672T528 1585Q528 1529 558 1499T645 1468Q697 1468 729 1498T762 1585Z" /> +<glyph unicode="Æ" glyph-name="AE" horiz-adv-x="1788" d="M1665 0H915V465H401L174 0H-2L696 1462H1665V1311H1085V840H1626V690H1085V152H1665V0ZM469 618H915V1311H797L469 618Z" /> +<glyph unicode="Ç" glyph-name="Ccedilla" horiz-adv-x="1292" d="M827 1331Q586 1331 447 1171T307 731Q307 444 441 288T825 131Q978 131 1174 186V37Q1022 -20 799 -20Q476 -20 301 176T125 733Q125 959 209 1129T453 1391T829 1483Q1059 1483 1231 1399L1159 +1253Q993 1331 827 1331ZM950 -289Q950 -386 874 -439T647 -492Q596 -492 551 -483V-377Q596 -385 655 -385Q734 -385 774 -365T815 -291Q815 -248 776 -222T627 -178L715 0H825L770 -115Q950 -154 950 -289Z" /> +<glyph unicode="È" glyph-name="Egrave" horiz-adv-x="1139" d="M1016 0H201V1462H1016V1311H371V840H977V690H371V152H1016V0ZM713 1579H603Q538 1631 449 1727T320 1886V1907H523Q555 1838 612 1748T713 1604V1579Z" /> +<glyph unicode="É" glyph-name="Eacute" horiz-adv-x="1139" d="M1016 0H201V1462H1016V1311H371V840H977V690H371V152H1016V0ZM456 1604Q504 1666 559 1754T647 1907H849V1886Q805 1821 718 1726T567 1579H456V1604Z" /> +<glyph unicode="Ê" glyph-name="Ecircumflex" horiz-adv-x="1139" d="M1016 0H201V1462H1016V1311H371V840H977V690H371V152H1016V0ZM263 1602Q390 1738 441 1802T515 1907H681Q703 1865 757 1799T937 1602V1579H818Q730 1634 597 1765Q461 1631 378 1579H263V1602Z" /> +<glyph unicode="Ë" glyph-name="Edieresis" horiz-adv-x="1139" d="M1016 0H201V1462H1016V1311H371V840H977V690H371V152H1016V0ZM327 1731Q327 1783 353 1806T417 1829Q455 1829 482 1806T510 1731Q510 1681 483 1657T417 1632Q380 1632 354 1656T327 1731ZM708 +1731Q708 1783 734 1806T798 1829Q835 1829 862 1806T890 1731Q890 1681 863 1657T798 1632Q761 1632 735 1656T708 1731Z" /> +<glyph unicode="Ì" glyph-name="Igrave" horiz-adv-x="571" d="M201 0V1462H371V0H201ZM398 1579H288Q223 1631 134 1727T5 1886V1907H208Q240 1838 297 1748T398 1604V1579Z" /> +<glyph unicode="Í" glyph-name="Iacute" horiz-adv-x="571" d="M201 0V1462H371V0H201ZM179 1604Q227 1666 282 1754T370 1907H572V1886Q528 1821 441 1726T290 1579H179V1604Z" /> +<glyph unicode="Î" glyph-name="Icircumflex" horiz-adv-x="571" d="M201 0V1462H371V0H201ZM-57 1602Q70 1738 121 1802T195 1907H361Q383 1865 437 1799T617 1602V1579H498Q410 1634 277 1765Q141 1631 58 1579H-57V1602Z" /> +<glyph unicode="Ï" glyph-name="Idieresis" horiz-adv-x="571" d="M201 0V1462H371V0H201ZM5 1731Q5 1783 31 1806T95 1829Q133 1829 160 1806T188 1731Q188 1681 161 1657T95 1632Q58 1632 32 1656T5 1731ZM386 1731Q386 1783 412 1806T476 1829Q513 1829 +540 1806T568 1731Q568 1681 541 1657T476 1632Q439 1632 413 1656T386 1731Z" /> +<glyph unicode="Ð" glyph-name="Eth" horiz-adv-x="1479" d="M1352 745Q1352 383 1156 192T590 0H201V649H47V799H201V1462H635Q972 1462 1162 1275T1352 745ZM1171 739Q1171 1315 602 1315H371V799H750V649H371V147H561Q1171 147 1171 739Z" /> +<glyph unicode="Ñ" glyph-name="Ntilde" horiz-adv-x="1544" d="M1343 0H1149L350 1227H342Q358 1011 358 831V0H201V1462H393L1190 240H1198Q1196 267 1189 413T1184 623V1462H1343V0ZM935 1581Q892 1581 851 1599T771 1640T695 1681T624 1700Q574 1700 +549 1670T509 1579H411Q424 1700 481 1768T630 1837Q676 1837 719 1819T801 1778T876 1737T944 1718Q993 1718 1017 1747T1056 1839H1155Q1142 1718 1086 1650T935 1581Z" /> +<glyph unicode="Ò" glyph-name="Ograve" horiz-adv-x="1595" d="M1470 733Q1470 382 1293 181T799 -20Q476 -20 301 177T125 735Q125 1092 301 1288T801 1485Q1116 1485 1293 1285T1470 733ZM305 733Q305 436 431 283T799 129Q1042 129 1166 282T1290 733Q1290 +1028 1167 1180T801 1333Q558 1333 432 1180T305 733ZM907 1579H797Q732 1631 643 1727T514 1886V1907H717Q749 1838 806 1748T907 1604V1579Z" /> +<glyph unicode="Ó" glyph-name="Oacute" horiz-adv-x="1595" d="M1470 733Q1470 382 1293 181T799 -20Q476 -20 301 177T125 735Q125 1092 301 1288T801 1485Q1116 1485 1293 1285T1470 733ZM305 733Q305 436 431 283T799 129Q1042 129 1166 282T1290 733Q1290 +1028 1167 1180T801 1333Q558 1333 432 1180T305 733ZM659 1604Q707 1666 762 1754T850 1907H1052V1886Q1008 1821 921 1726T770 1579H659V1604Z" /> +<glyph unicode="Ô" glyph-name="Ocircumflex" horiz-adv-x="1595" d="M1470 733Q1470 382 1293 181T799 -20Q476 -20 301 177T125 735Q125 1092 301 1288T801 1485Q1116 1485 1293 1285T1470 733ZM305 733Q305 436 431 283T799 129Q1042 129 1166 282T1290 +733Q1290 1028 1167 1180T801 1333Q558 1333 432 1180T305 733ZM448 1602Q575 1738 626 1802T700 1907H866Q888 1865 942 1799T1122 1602V1579H1003Q915 1634 782 1765Q646 1631 563 1579H448V1602Z" /> +<glyph unicode="Õ" glyph-name="Otilde" horiz-adv-x="1595" d="M1470 733Q1470 382 1293 181T799 -20Q476 -20 301 177T125 735Q125 1092 301 1288T801 1485Q1116 1485 1293 1285T1470 733ZM305 733Q305 436 431 283T799 129Q1042 129 1166 282T1290 733Q1290 +1028 1167 1180T801 1333Q558 1333 432 1180T305 733ZM942 1581Q899 1581 858 1599T778 1640T702 1681T631 1700Q581 1700 556 1670T516 1579H418Q431 1700 488 1768T637 1837Q683 1837 726 1819T808 1778T883 1737T951 1718Q1000 1718 1024 1747T1063 1839H1162Q1149 +1718 1093 1650T942 1581Z" /> +<glyph unicode="Ö" glyph-name="Odieresis" horiz-adv-x="1595" d="M1470 733Q1470 382 1293 181T799 -20Q476 -20 301 177T125 735Q125 1092 301 1288T801 1485Q1116 1485 1293 1285T1470 733ZM305 733Q305 436 431 283T799 129Q1042 129 1166 282T1290 +733Q1290 1028 1167 1180T801 1333Q558 1333 432 1180T305 733ZM522 1731Q522 1783 548 1806T612 1829Q650 1829 677 1806T705 1731Q705 1681 678 1657T612 1632Q575 1632 549 1656T522 1731ZM903 1731Q903 1783 929 1806T993 1829Q1030 1829 1057 1806T1085 1731Q1085 +1681 1058 1657T993 1632Q956 1632 930 1656T903 1731Z" /> +<glyph unicode="×" glyph-name="multiply" horiz-adv-x="1171" d="M940 1176L1036 1077L684 723L1034 371L938 272L584 623L236 272L135 371L485 723L133 1075L233 1176L586 821L940 1176Z" /> +<glyph unicode="Ø" glyph-name="Oslash" horiz-adv-x="1595" d="M1470 733Q1470 382 1293 181T799 -20Q564 -20 416 80L315 -61L195 18L303 172Q125 370 125 735Q125 1092 301 1288T801 1485Q1010 1485 1167 1391L1264 1526L1384 1446L1278 1298Q1470 1096 +1470 733ZM1290 733Q1290 1005 1180 1159L508 211Q623 129 799 129Q1042 129 1166 282T1290 733ZM305 733Q305 471 406 317L1075 1260Q969 1333 801 1333Q558 1333 432 1180T305 733Z" /> +<glyph unicode="Ù" glyph-name="Ugrave" horiz-adv-x="1491" d="M1305 1462V516Q1305 266 1154 123T739 -20Q475 -20 331 124T186 520V1462H356V508Q356 325 456 227T750 129Q935 129 1035 227T1135 510V1462H1305ZM856 1579H746Q681 1631 592 1727T463 1886V1907H666Q698 +1838 755 1748T856 1604V1579Z" /> +<glyph unicode="Ú" glyph-name="Uacute" horiz-adv-x="1491" d="M1305 1462V516Q1305 266 1154 123T739 -20Q475 -20 331 124T186 520V1462H356V508Q356 325 456 227T750 129Q935 129 1035 227T1135 510V1462H1305ZM600 1604Q648 1666 703 1754T791 1907H993V1886Q949 +1821 862 1726T711 1579H600V1604Z" /> +<glyph unicode="Û" glyph-name="Ucircumflex" horiz-adv-x="1491" d="M1305 1462V516Q1305 266 1154 123T739 -20Q475 -20 331 124T186 520V1462H356V508Q356 325 456 227T750 129Q935 129 1035 227T1135 510V1462H1305ZM393 1602Q520 1738 571 1802T645 +1907H811Q833 1865 887 1799T1067 1602V1579H948Q860 1634 727 1765Q591 1631 508 1579H393V1602Z" /> +<glyph unicode="Ü" glyph-name="Udieresis" horiz-adv-x="1491" d="M1305 1462V516Q1305 266 1154 123T739 -20Q475 -20 331 124T186 520V1462H356V508Q356 325 456 227T750 129Q935 129 1035 227T1135 510V1462H1305ZM461 1731Q461 1783 487 1806T551 1829Q589 +1829 616 1806T644 1731Q644 1681 617 1657T551 1632Q514 1632 488 1656T461 1731ZM842 1731Q842 1783 868 1806T932 1829Q969 1829 996 1806T1024 1731Q1024 1681 997 1657T932 1632Q895 1632 869 1656T842 1731Z" /> +<glyph unicode="Ý" glyph-name="Yacute" horiz-adv-x="1147" d="M573 731L963 1462H1147L659 567V0H487V559L0 1462H186L573 731ZM442 1604Q490 1666 545 1754T633 1907H835V1886Q791 1821 704 1726T553 1579H442V1604Z" /> +<glyph unicode="Þ" glyph-name="Thorn" horiz-adv-x="1251" d="M1145 784Q1145 557 994 438T555 319H371V0H201V1462H371V1206H586Q867 1206 1006 1103T1145 784ZM371 465H539Q765 465 866 536T967 772Q967 921 872 990T575 1059H371V465Z" /> +<glyph unicode="ß" glyph-name="germandbls" horiz-adv-x="1274" d="M1049 1266Q1049 1131 906 1016Q818 946 790 913T762 846Q762 814 775 793T824 744T938 664Q1078 569 1129 491T1180 311Q1180 151 1083 66T807 -20Q619 -20 512 49V203Q575 164 653 141T803 +117Q1018 117 1018 299Q1018 374 977 427T825 551Q698 633 650 694T602 840Q602 903 636 956T742 1062Q817 1119 849 1164T881 1262Q881 1342 813 1384T618 1427Q342 1427 342 1204V0H176V1202Q176 1380 286 1473T618 1567Q824 1567 936 1489T1049 1266Z" /> +<glyph unicode="à" glyph-name="agrave" horiz-adv-x="1139" d="M850 0L817 156H809Q727 53 646 17T442 -20Q279 -20 187 64T94 303Q94 635 625 651L811 657V725Q811 854 756 915T578 977Q441 977 268 893L217 1020Q298 1064 394 1089T588 1114Q784 1114 +878 1027T973 748V0H850ZM475 117Q630 117 718 202T807 440V539L641 532Q443 525 356 471T268 301Q268 211 322 164T475 117ZM928 1241H818Q753 1293 664 1389T535 1548V1569H738Q770 1500 827 1410T928 1266V1241Z" /> +<glyph unicode="á" glyph-name="aacute" horiz-adv-x="1139" d="M850 0L817 156H809Q727 53 646 17T442 -20Q279 -20 187 64T94 303Q94 635 625 651L811 657V725Q811 854 756 915T578 977Q441 977 268 893L217 1020Q298 1064 394 1089T588 1114Q784 1114 +878 1027T973 748V0H850ZM475 117Q630 117 718 202T807 440V539L641 532Q443 525 356 471T268 301Q268 211 322 164T475 117ZM436 1266Q484 1328 539 1416T627 1569H829V1548Q785 1483 698 1388T547 1241H436V1266Z" /> +<glyph unicode="â" glyph-name="acircumflex" horiz-adv-x="1139" d="M850 0L817 156H809Q727 53 646 17T442 -20Q279 -20 187 64T94 303Q94 635 625 651L811 657V725Q811 854 756 915T578 977Q441 977 268 893L217 1020Q298 1064 394 1089T588 1114Q784 +1114 878 1027T973 748V0H850ZM475 117Q630 117 718 202T807 440V539L641 532Q443 525 356 471T268 301Q268 211 322 164T475 117ZM484 1264Q611 1400 662 1464T736 1569H902Q924 1527 978 1461T1158 1264V1241H1039Q951 1296 818 1427Q682 1293 599 1241H484V1264Z" +/> +<glyph unicode="ã" glyph-name="atilde" horiz-adv-x="1139" d="M850 0L817 156H809Q727 53 646 17T442 -20Q279 -20 187 64T94 303Q94 635 625 651L811 657V725Q811 854 756 915T578 977Q441 977 268 893L217 1020Q298 1064 394 1089T588 1114Q784 1114 +878 1027T973 748V0H850ZM475 117Q630 117 718 202T807 440V539L641 532Q443 525 356 471T268 301Q268 211 322 164T475 117ZM977 1243Q934 1243 893 1261T813 1302T737 1343T666 1362Q616 1362 591 1332T551 1241H453Q466 1362 523 1430T672 1499Q718 1499 761 +1481T843 1440T918 1399T986 1380Q1035 1380 1059 1409T1098 1501H1197Q1184 1380 1128 1312T977 1243Z" /> +<glyph unicode="ä" glyph-name="adieresis" horiz-adv-x="1139" d="M850 0L817 156H809Q727 53 646 17T442 -20Q279 -20 187 64T94 303Q94 635 625 651L811 657V725Q811 854 756 915T578 977Q441 977 268 893L217 1020Q298 1064 394 1089T588 1114Q784 1114 +878 1027T973 748V0H850ZM475 117Q630 117 718 202T807 440V539L641 532Q443 525 356 471T268 301Q268 211 322 164T475 117ZM535 1393Q535 1445 561 1468T625 1491Q663 1491 690 1468T718 1393Q718 1343 691 1319T625 1294Q588 1294 562 1318T535 1393ZM916 1393Q916 +1445 942 1468T1006 1491Q1043 1491 1070 1468T1098 1393Q1098 1343 1071 1319T1006 1294Q969 1294 943 1318T916 1393Z" /> +<glyph unicode="å" glyph-name="aring" horiz-adv-x="1139" d="M850 0L817 156H809Q727 53 646 17T442 -20Q279 -20 187 64T94 303Q94 635 625 651L811 657V725Q811 854 756 915T578 977Q441 977 268 893L217 1020Q298 1064 394 1089T588 1114Q784 1114 878 +1027T973 748V0H850ZM475 117Q630 117 718 202T807 440V539L641 532Q443 525 356 471T268 301Q268 211 322 164T475 117ZM1060 1458Q1060 1360 999 1301T835 1241Q734 1241 674 1299T614 1456Q614 1554 674 1611T835 1669Q936 1669 998 1610T1060 1458ZM952 1456Q952 +1512 919 1542T835 1573Q784 1573 751 1543T718 1456Q718 1400 748 1370T835 1339Q887 1339 919 1369T952 1456Z" /> +<glyph unicode="æ" glyph-name="ae" horiz-adv-x="1757" d="M94 303Q94 464 218 553T596 651L780 657V725Q780 854 722 915T545 977Q401 977 238 893L186 1020Q260 1061 359 1087T557 1114Q687 1114 769 1071T893 932Q946 1020 1031 1068T1227 1116Q1419 +1116 1535 983T1651 627V520H950Q958 125 1272 125Q1363 125 1441 142T1604 199V51Q1518 13 1444 -3T1268 -20Q979 -20 854 213Q773 86 675 33T442 -20Q279 -20 187 65T94 303ZM268 301Q268 206 321 162T463 117Q608 117 692 201T776 440V539L618 532Q432 524 350 +470T268 301ZM1225 977Q1104 977 1035 894T954 653H1473Q1473 809 1409 893T1225 977Z" /> +<glyph unicode="ç" glyph-name="ccedilla" horiz-adv-x="975" d="M614 -20Q376 -20 246 126T115 541Q115 816 247 966T625 1116Q704 1116 783 1099T907 1059L856 918Q801 940 736 954T621 969Q287 969 287 543Q287 341 368 233T610 125Q747 125 891 184V37Q781 +-20 614 -20ZM762 -289Q762 -386 686 -439T459 -492Q408 -492 363 -483V-377Q408 -385 467 -385Q546 -385 586 -365T627 -291Q627 -248 588 -222T439 -178L527 0H637L582 -115Q762 -154 762 -289Z" /> +<glyph unicode="è" glyph-name="egrave" horiz-adv-x="1149" d="M639 -20Q396 -20 256 128T115 539Q115 804 245 960T596 1116Q802 1116 922 981T1042 623V518H287Q292 325 384 225T645 125Q822 125 995 199V51Q907 13 829 -3T639 -20ZM594 977Q462 977 384 +891T291 653H864Q864 810 794 893T594 977ZM967 1241H857Q792 1293 703 1389T574 1548V1569H777Q809 1500 866 1410T967 1266V1241Z" /> +<glyph unicode="é" glyph-name="eacute" horiz-adv-x="1149" d="M639 -20Q396 -20 256 128T115 539Q115 804 245 960T596 1116Q802 1116 922 981T1042 623V518H287Q292 325 384 225T645 125Q822 125 995 199V51Q907 13 829 -3T639 -20ZM594 977Q462 977 384 +891T291 653H864Q864 810 794 893T594 977ZM471 1266Q519 1328 574 1416T662 1569H864V1548Q820 1483 733 1388T582 1241H471V1266Z" /> +<glyph unicode="ê" glyph-name="ecircumflex" horiz-adv-x="1149" d="M639 -20Q396 -20 256 128T115 539Q115 804 245 960T596 1116Q802 1116 922 981T1042 623V518H287Q292 325 384 225T645 125Q822 125 995 199V51Q907 13 829 -3T639 -20ZM594 977Q462 +977 384 891T291 653H864Q864 810 794 893T594 977ZM515 1264Q642 1400 693 1464T767 1569H933Q955 1527 1009 1461T1189 1264V1241H1070Q982 1296 849 1427Q713 1293 630 1241H515V1264Z" /> +<glyph unicode="ë" glyph-name="edieresis" horiz-adv-x="1149" d="M639 -20Q396 -20 256 128T115 539Q115 804 245 960T596 1116Q802 1116 922 981T1042 623V518H287Q292 325 384 225T645 125Q822 125 995 199V51Q907 13 829 -3T639 -20ZM594 977Q462 977 +384 891T291 653H864Q864 810 794 893T594 977ZM319 1393Q319 1445 345 1468T409 1491Q447 1491 474 1468T502 1393Q502 1343 475 1319T409 1294Q372 1294 346 1318T319 1393ZM700 1393Q700 1445 726 1468T790 1491Q827 1491 854 1468T882 1393Q882 1343 855 1319T790 +1294Q753 1294 727 1318T700 1393Z" /> +<glyph unicode="ì" glyph-name="igrave" horiz-adv-x="518" d="M342 0H176V1096H342V0ZM355 1241H245Q180 1293 91 1389T-38 1548V1569H165Q197 1500 254 1410T355 1266V1241Z" /> +<glyph unicode="í" glyph-name="iacute" horiz-adv-x="518" d="M342 0H176V1096H342V0ZM169 1266Q217 1328 272 1416T360 1569H562V1548Q518 1483 431 1388T280 1241H169V1266Z" /> +<glyph unicode="î" glyph-name="icircumflex" horiz-adv-x="518" d="M342 0H176V1096H342V0ZM-77 1264Q50 1400 101 1464T175 1569H341Q363 1527 417 1461T597 1264V1241H478Q390 1296 257 1427Q121 1293 38 1241H-77V1264Z" /> +<glyph unicode="ï" glyph-name="idieresis" horiz-adv-x="518" d="M342 0H176V1096H342V0ZM-20 1393Q-20 1445 6 1468T70 1491Q108 1491 135 1468T163 1393Q163 1343 136 1319T70 1294Q33 1294 7 1318T-20 1393ZM361 1393Q361 1445 387 1468T451 1491Q488 +1491 515 1468T543 1393Q543 1343 516 1319T451 1294Q414 1294 388 1318T361 1393Z" /> +<glyph unicode="ð" glyph-name="eth" horiz-adv-x="1221" d="M1122 563Q1122 282 992 131T614 -20Q392 -20 253 114T113 475Q113 705 244 836T596 967Q822 967 922 846L930 850Q873 1064 668 1255L397 1100L324 1208L557 1341Q465 1403 371 1452L440 1569Q596 +1496 698 1421L936 1559L1012 1452L805 1333Q957 1190 1039 991T1122 563ZM954 512Q954 659 864 744T618 829Q281 829 281 469Q281 302 368 211T618 119Q793 119 873 219T954 512Z" /> +<glyph unicode="ñ" glyph-name="ntilde" horiz-adv-x="1257" d="M926 0V709Q926 843 865 909T674 975Q502 975 422 882T342 575V0H176V1096H311L338 946H346Q397 1027 489 1071T694 1116Q892 1116 992 1021T1092 715V0H926ZM802 1243Q759 1243 718 1261T638 +1302T562 1343T491 1362Q441 1362 416 1332T376 1241H278Q291 1362 348 1430T497 1499Q543 1499 586 1481T668 1440T743 1399T811 1380Q860 1380 884 1409T923 1501H1022Q1009 1380 953 1312T802 1243Z" /> +<glyph unicode="ò" glyph-name="ograve" horiz-adv-x="1237" d="M1122 549Q1122 281 987 131T614 -20Q467 -20 353 49T177 247T115 549Q115 817 249 966T621 1116Q851 1116 986 963T1122 549ZM287 549Q287 339 371 229T618 119Q781 119 865 228T950 549Q950 +758 866 866T616 975Q453 975 370 868T287 549ZM998 1241H888Q823 1293 734 1389T605 1548V1569H808Q840 1500 897 1410T998 1266V1241Z" /> +<glyph unicode="ó" glyph-name="oacute" horiz-adv-x="1237" d="M1122 549Q1122 281 987 131T614 -20Q467 -20 353 49T177 247T115 549Q115 817 249 966T621 1116Q851 1116 986 963T1122 549ZM287 549Q287 339 371 229T618 119Q781 119 865 228T950 549Q950 +758 866 866T616 975Q453 975 370 868T287 549ZM479 1266Q527 1328 582 1416T670 1569H872V1548Q828 1483 741 1388T590 1241H479V1266Z" /> +<glyph unicode="ô" glyph-name="ocircumflex" horiz-adv-x="1237" d="M1122 549Q1122 281 987 131T614 -20Q467 -20 353 49T177 247T115 549Q115 817 249 966T621 1116Q851 1116 986 963T1122 549ZM287 549Q287 339 371 229T618 119Q781 119 865 228T950 +549Q950 758 866 866T616 975Q453 975 370 868T287 549ZM282 1264Q409 1400 460 1464T534 1569H700Q722 1527 776 1461T956 1264V1241H837Q749 1296 616 1427Q480 1293 397 1241H282V1264Z" /> +<glyph unicode="õ" glyph-name="otilde" horiz-adv-x="1237" d="M1122 549Q1122 281 987 131T614 -20Q467 -20 353 49T177 247T115 549Q115 817 249 966T621 1116Q851 1116 986 963T1122 549ZM287 549Q287 339 371 229T618 119Q781 119 865 228T950 549Q950 +758 866 866T616 975Q453 975 370 868T287 549ZM1029 1243Q986 1243 945 1261T865 1302T789 1343T718 1362Q668 1362 643 1332T603 1241H505Q518 1362 575 1430T724 1499Q770 1499 813 1481T895 1440T970 1399T1038 1380Q1087 1380 1111 1409T1150 1501H1249Q1236 +1380 1180 1312T1029 1243Z" /> +<glyph unicode="ö" glyph-name="odieresis" horiz-adv-x="1237" d="M1122 549Q1122 281 987 131T614 -20Q467 -20 353 49T177 247T115 549Q115 817 249 966T621 1116Q851 1116 986 963T1122 549ZM287 549Q287 339 371 229T618 119Q781 119 865 228T950 549Q950 +758 866 866T616 975Q453 975 370 868T287 549ZM336 1393Q336 1445 362 1468T426 1491Q464 1491 491 1468T519 1393Q519 1343 492 1319T426 1294Q389 1294 363 1318T336 1393ZM717 1393Q717 1445 743 1468T807 1491Q844 1491 871 1468T899 1393Q899 1343 872 1319T807 +1294Q770 1294 744 1318T717 1393Z" /> +<glyph unicode="÷" glyph-name="divide" horiz-adv-x="1171" d="M104 653V791H1065V653H104ZM471 373Q471 433 500 463T584 494Q636 494 665 463T694 373Q694 316 665 284T584 252Q532 252 502 283T471 373ZM471 1071Q471 1131 500 1161T584 1192Q636 1192 +665 1161T694 1071Q694 1014 665 982T584 950Q532 950 502 981T471 1071Z" /> +<glyph unicode="ø" glyph-name="oslash" horiz-adv-x="1237" d="M1122 549Q1122 281 987 131T614 -20Q460 -20 348 49L264 -68L150 10L244 141Q115 293 115 549Q115 817 249 966T621 1116Q775 1116 891 1040L975 1159L1092 1083L995 950Q1122 798 1122 549ZM287 +549Q287 378 340 276L805 922Q730 975 616 975Q453 975 370 868T287 549ZM950 549Q950 713 899 813L434 170Q505 119 618 119Q781 119 865 228T950 549Z" /> +<glyph unicode="ù" glyph-name="ugrave" horiz-adv-x="1257" d="M332 1096V385Q332 251 393 185T584 119Q756 119 835 213T915 520V1096H1081V0H944L920 147H911Q860 66 770 23T563 -20Q363 -20 264 75T164 379V1096H332ZM982 1241H872Q807 1293 718 1389T589 +1548V1569H792Q824 1500 881 1410T982 1266V1241Z" /> +<glyph unicode="ú" glyph-name="uacute" horiz-adv-x="1257" d="M332 1096V385Q332 251 393 185T584 119Q756 119 835 213T915 520V1096H1081V0H944L920 147H911Q860 66 770 23T563 -20Q363 -20 264 75T164 379V1096H332ZM506 1266Q554 1328 609 1416T697 +1569H899V1548Q855 1483 768 1388T617 1241H506V1266Z" /> +<glyph unicode="û" glyph-name="ucircumflex" horiz-adv-x="1257" d="M332 1096V385Q332 251 393 185T584 119Q756 119 835 213T915 520V1096H1081V0H944L920 147H911Q860 66 770 23T563 -20Q363 -20 264 75T164 379V1096H332ZM286 1264Q413 1400 464 1464T538 +1569H704Q726 1527 780 1461T960 1264V1241H841Q753 1296 620 1427Q484 1293 401 1241H286V1264Z" /> +<glyph unicode="ü" glyph-name="udieresis" horiz-adv-x="1257" d="M332 1096V385Q332 251 393 185T584 119Q756 119 835 213T915 520V1096H1081V0H944L920 147H911Q860 66 770 23T563 -20Q363 -20 264 75T164 379V1096H332ZM342 1393Q342 1445 368 1468T432 +1491Q470 1491 497 1468T525 1393Q525 1343 498 1319T432 1294Q395 1294 369 1318T342 1393ZM723 1393Q723 1445 749 1468T813 1491Q850 1491 877 1468T905 1393Q905 1343 878 1319T813 1294Q776 1294 750 1318T723 1393Z" /> +<glyph unicode="ý" glyph-name="yacute" horiz-adv-x="1032" d="M2 1096H180L420 471Q499 257 518 162H526Q539 213 580 336T852 1096H1030L559 -152Q489 -337 396 -414T166 -492Q90 -492 16 -475V-342Q71 -354 139 -354Q310 -354 383 -162L444 -6L2 1096ZM411 +1266Q459 1328 514 1416T602 1569H804V1548Q760 1483 673 1388T522 1241H411V1266Z" /> +<glyph unicode="þ" glyph-name="thorn" horiz-adv-x="1255" d="M344 948Q410 1037 495 1076T686 1116Q901 1116 1021 966T1141 549Q1141 281 1021 131T686 -20Q464 -20 342 141H330L334 107Q342 30 342 -33V-492H176V1556H342V1090Q342 1038 336 948H344ZM664 +975Q496 975 420 883T342 590V549Q342 318 419 219T666 119Q969 119 969 551Q969 766 895 870T664 975Z" /> +<glyph unicode="ÿ" glyph-name="ydieresis" horiz-adv-x="1032" d="M2 1096H180L420 471Q499 257 518 162H526Q539 213 580 336T852 1096H1030L559 -152Q489 -337 396 -414T166 -492Q90 -492 16 -475V-342Q71 -354 139 -354Q310 -354 383 -162L444 -6L2 1096ZM490 +1393Q490 1445 516 1468T580 1491Q618 1491 645 1468T673 1393Q673 1343 646 1319T580 1294Q543 1294 517 1318T490 1393ZM871 1393Q871 1445 897 1468T961 1491Q998 1491 1025 1468T1053 1393Q1053 1343 1026 1319T961 1294Q924 1294 898 1318T871 1393Z" /> +<glyph unicode="–" glyph-name="endash" horiz-adv-x="1024" d="M82 473V625H942V473H82Z" /> +<glyph unicode="—" glyph-name="emdash" horiz-adv-x="2048" d="M82 473V625H1966V473H82Z" /> +<glyph unicode="‘" glyph-name="quoteleft" horiz-adv-x="348" d="M37 961L25 983Q47 1073 96 1207T201 1462H324Q258 1208 221 961H37Z" /> +<glyph unicode="’" glyph-name="quoteright" horiz-adv-x="348" d="M309 1462L324 1440Q298 1340 249 1208T147 961H25Q95 1246 127 1462H309Z" /> +<glyph unicode="‚" glyph-name="quotesinglbase" horiz-adv-x="502" d="M350 238L365 215Q339 115 290 -17T188 -264H63Q90 -160 122 -7T168 238H350Z" /> +<glyph unicode="“" glyph-name="quotedblleft" horiz-adv-x="717" d="M406 961L391 983Q447 1198 569 1462H692Q662 1347 633 1203T590 961H406ZM37 961L25 983Q47 1073 96 1207T201 1462H324Q258 1208 221 961H37Z" /> +<glyph unicode="”" glyph-name="quotedblright" horiz-adv-x="717" d="M309 1462L324 1440Q298 1340 249 1208T147 961H25Q95 1246 127 1462H309ZM678 1462L692 1440Q668 1349 620 1216T516 961H391Q417 1061 450 1215T496 1462H678Z" /> +<glyph unicode="„" glyph-name="quotedblbase" horiz-adv-x="829" d="M309 238L324 216Q298 116 249 -16T147 -263H25Q95 22 127 238H309ZM678 238L692 216Q668 125 620 -8T516 -263H391Q417 -163 450 -9T496 238H678Z" /> +<glyph unicode="•" glyph-name="bullet" horiz-adv-x="770" d="M164 748Q164 869 220 932T385 995Q490 995 548 933T606 748Q606 629 549 565T385 500Q278 500 221 565T164 748Z" /> +<glyph unicode="‹" glyph-name="guilsinglleft" horiz-adv-x="623" d="M82 551L424 958L543 889L254 539L543 188L424 117L82 524V551Z" /> +<glyph unicode="›" glyph-name="guilsinglright" horiz-adv-x="623" d="M541 524L197 117L80 188L367 539L80 889L197 958L541 551V524Z" /> +</font> +</defs> +</svg> diff --git a/website/agenda/fonts/open-sans-v15-latin_latin-ext-regular.ttf b/website/agenda/fonts/open-sans-v15-latin_latin-ext-regular.ttf new file mode 100644 index 0000000..65a04f1 Binary files /dev/null and b/website/agenda/fonts/open-sans-v15-latin_latin-ext-regular.ttf differ diff --git a/website/agenda/fonts/open-sans-v15-latin_latin-ext-regular.woff b/website/agenda/fonts/open-sans-v15-latin_latin-ext-regular.woff new file mode 100644 index 0000000..6ca02c4 Binary files /dev/null and b/website/agenda/fonts/open-sans-v15-latin_latin-ext-regular.woff differ diff --git a/website/agenda/fonts/open-sans-v15-latin_latin-ext-regular.woff2 b/website/agenda/fonts/open-sans-v15-latin_latin-ext-regular.woff2 new file mode 100644 index 0000000..a337154 Binary files /dev/null and b/website/agenda/fonts/open-sans-v15-latin_latin-ext-regular.woff2 differ diff --git a/website/agenda/fonts/roboto-v18-latin_latin-ext-regular.eot b/website/agenda/fonts/roboto-v18-latin_latin-ext-regular.eot new file mode 100644 index 0000000..748c0e6 Binary files /dev/null and b/website/agenda/fonts/roboto-v18-latin_latin-ext-regular.eot differ diff --git a/website/agenda/fonts/roboto-v18-latin_latin-ext-regular.svg b/website/agenda/fonts/roboto-v18-latin_latin-ext-regular.svg new file mode 100644 index 0000000..627f5a3 --- /dev/null +++ b/website/agenda/fonts/roboto-v18-latin_latin-ext-regular.svg @@ -0,0 +1,308 @@ +<?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"> +<defs > +<font id="Roboto" horiz-adv-x="1158" ><font-face + font-family="Roboto" + units-per-em="2048" + panose-1="2 0 0 0 0 0 0 0 0 0" + ascent="1900" + descent="-500" + alphabetic="0" /> +<glyph unicode=" " horiz-adv-x="507" /> +<glyph unicode="!" horiz-adv-x="527" d="M347 411H180L167 1456H361L347 411ZM160 93Q160 138 187 168T269 199T351 169T379 93T351 19T269 -11T188 18T160 93Z" /> +<glyph unicode=""" horiz-adv-x="655" d="M277 1400L247 1042H136L137 1536H277V1400ZM547 1400L517 1042H406L407 1536H547V1400Z" /> +<glyph unicode="#" horiz-adv-x="1261" d="M765 410H501L421 0H278L358 410H119V547H384L453 901H195V1040H480L562 1456H705L623 1040H887L969 1456H1113L1031 1040H1235V901H1004L935 547H1160V410H909L829 0H685L765 410ZM527 547H791L860 901H596L527 547Z" /> +<glyph unicode="$" horiz-adv-x="1150" d="M856 375Q856 467 792 530T574 644Q361 709 264 813T166 1079Q166 1243 261 1348T524 1473V1692H673V1472Q841 1449 934 1331T1028 1008H844Q844 1149 777 1232T596 1315Q477 1315 414 1254T351 1082Q351 980 417 920T636 +810T874 701T1000 562T1041 377Q1041 208 940 105T655 -17V-208H507V-17Q321 0 216 115T110 429H295Q295 290 368 215T575 140Q706 140 781 203T856 375Z" /> +<glyph unicode="%" horiz-adv-x="1500" d="M105 1176Q105 1307 188 1392T403 1477Q536 1477 618 1392T701 1170V1099Q701 967 618 884T405 800Q275 800 190 883T105 1106V1176ZM243 1099Q243 1021 287 971T405 920Q476 920 519 969T563 1103V1176Q563 1254 520 +1305T403 1356T286 1305T243 1172V1099ZM814 357Q814 488 897 572T1112 657T1327 573T1411 350V279Q1411 148 1328 64T1114 -21T899 62T814 285V357ZM952 279Q952 200 996 150T1114 99Q1186 99 1229 148T1272 283V357Q1272 436 1229 486T1112 536Q1041 536 997 +487T952 353V279ZM447 110L342 176L1053 1314L1158 1248L447 110Z" /> +<glyph unicode="&" horiz-adv-x="1273" d="M101 391Q101 496 159 584T383 789Q286 907 253 979T220 1122Q220 1288 318 1382T584 1476Q734 1476 832 1389T930 1168Q930 1080 886 1006T730 849L623 770L947 383Q1015 513 1015 672H1182Q1182 417 1059 249L1267 +0H1045L948 115Q874 49 775 15T572 -20Q359 -20 230 93T101 391ZM572 131Q719 131 841 243L486 668L453 644Q286 521 286 391Q286 273 362 202T572 131ZM405 1128Q405 1032 523 888L641 971Q709 1019 734 1062T759 1168Q759 1235 709 1279T583 1324Q501 1324 453 +1269T405 1128Z" /> +<glyph unicode="'" horiz-adv-x="357" d="M253 1425L232 1057H103L104 1536H253V1425Z" /> +<glyph unicode="(" horiz-adv-x="700" d="M133 591Q133 817 193 1025T374 1403T623 1643L661 1521Q515 1409 422 1179T319 664L318 579Q318 193 459 -91Q544 -261 661 -357L623 -470Q490 -396 369 -222Q133 118 133 591Z" /> +<glyph unicode=")" horiz-adv-x="712" d="M567 581Q567 358 509 154T330 -224T77 -470L38 -357Q192 -239 285 9T381 561V593Q381 803 337 983T215 1307T38 1530L77 1643Q209 1570 328 1399T507 1022T567 581Z" /> +<glyph unicode="*" horiz-adv-x="882" d="M330 983L28 1073L74 1224L376 1112L367 1456H520L510 1107L807 1217L853 1065L546 974L744 703L620 609L434 897L254 616L129 707L330 983Z" /> +<glyph unicode="+" horiz-adv-x="1161" d="M670 781H1076V606H670V146H484V606H78V781H484V1206H670V781Z" /> +<glyph unicode="," horiz-adv-x="402" d="M134 -290L29 -218Q123 -87 127 52V219H308V74Q308 -27 259 -128T134 -290Z" /> +<glyph unicode="-" horiz-adv-x="565" d="M525 543H37V694H525V543Z" /> +<glyph unicode="." horiz-adv-x="539" d="M144 97Q144 145 172 177T258 209T344 177T374 97Q374 51 345 20T258 -11T173 20T144 97Z" /> +<glyph unicode="/" horiz-adv-x="844" d="M177 -125H18L626 1456H784L177 -125Z" /> +<glyph unicode="0" horiz-adv-x="1150" d="M1034 621Q1034 296 923 138T576 -20Q343 -20 231 134T115 596V843Q115 1164 226 1320T574 1476Q809 1476 920 1326T1034 861V621ZM849 874Q849 1109 783 1216T574 1324Q432 1324 367 1217T300 888V592Q300 356 368 244T576 +131Q713 131 779 237T849 571V874Z" /> +<glyph unicode="1" horiz-adv-x="1150" d="M729 0H543V1233L170 1096V1264L700 1463H729V0Z" /> +<glyph unicode="2" horiz-adv-x="1150" d="M1075 0H121V133L625 693Q737 820 779 899T822 1064Q822 1178 753 1251T569 1324Q431 1324 355 1246T278 1027H93Q93 1228 222 1352T569 1476Q772 1476 890 1370T1008 1086Q1008 871 734 574L344 151H1075V0Z" /> +<glyph unicode="3" horiz-adv-x="1150" d="M390 818H529Q660 820 735 887T810 1068Q810 1324 555 1324Q435 1324 364 1256T292 1074H107Q107 1247 233 1361T555 1476Q761 1476 878 1367T995 1064Q995 969 934 880T766 747Q886 709 951 621T1017 406Q1017 210 889 +95T556 -20T223 91T94 384H280Q280 269 355 200T556 131Q690 131 761 201T832 402Q832 529 754 597T529 667H390V818Z" /> +<glyph unicode="4" horiz-adv-x="1150" d="M902 489H1104V338H902V0H716V338H53V447L705 1456H902V489ZM263 489H716V1203L694 1163L263 489Z" /> +<glyph unicode="5" horiz-adv-x="1150" d="M206 730L280 1456H1026V1285H437L393 888Q500 951 636 951Q835 951 952 820T1069 464Q1069 239 948 110T608 -20Q415 -20 293 87T154 383H329Q346 258 418 195T608 131Q737 131 810 219T884 462Q884 608 805 696T593 +785Q472 785 403 732L354 692L206 730Z" /> +<glyph unicode="6" horiz-adv-x="1150" d="M847 1457V1300H813Q597 1296 469 1172T321 823Q436 955 635 955Q825 955 938 821T1052 475Q1052 250 930 115T601 -20Q392 -20 262 140T132 554V625Q132 1027 303 1239T814 1457H847ZM604 801Q509 801 429 744T318 601V533Q318 +353 399 243T601 133Q726 133 797 225T869 466Q869 616 797 708T604 801Z" /> +<glyph unicode="7" horiz-adv-x="1150" d="M1061 1352L458 0H264L865 1304H77V1456H1061V1352Z" /> +<glyph unicode="8" horiz-adv-x="1150" d="M1004 1076Q1004 967 947 882T791 749Q905 700 971 606T1038 393Q1038 204 911 92T575 -20Q365 -20 239 92T112 393Q112 511 176 606T355 750Q258 798 202 883T146 1076Q146 1260 264 1368T575 1476Q767 1476 885 1368T1004 +1076ZM853 397Q853 519 776 596T573 673T373 597T297 397T370 202T575 131Q705 131 779 202T853 397ZM575 1324Q466 1324 399 1257T331 1073Q331 962 397 894T575 825T752 893T819 1073T750 1254T575 1324Z" /> +<glyph unicode="9" horiz-adv-x="1150" d="M830 640Q772 571 692 529T515 487Q389 487 296 549T151 723T100 972Q100 1118 155 1235T313 1414T551 1476Q767 1476 891 1315T1016 874V820Q1016 395 848 200T341 -1H305V155H344Q573 159 696 274T830 640ZM545 640Q638 +640 716 697T831 838V912Q831 1094 752 1208T552 1322Q430 1322 356 1229T282 982Q282 833 353 737T545 640Z" /> +<glyph unicode=":" horiz-adv-x="496" d="M390 97Q390 145 418 177T504 209T590 177T620 97Q620 51 591 20T504 -11T419 20T390 97ZM135 980Q135 1028 163 1060T249 1092T335 1060T365 980Q365 934 336 903T249 872T164 903T135 980Z" /> +<glyph unicode=";" horiz-adv-x="433" d="M111 980Q111 1028 139 1060T225 1092T311 1060T341 980Q341 934 312 903T225 872T140 903T111 980ZM146 -290L41 -218Q135 -87 139 52V219H320V74Q320 -27 271 -128T146 -290Z" /> +<glyph unicode="<" horiz-adv-x="1041" d="M264 644L890 391V195L72 574V720L890 1098V902L264 644Z" /> +<glyph unicode="=" horiz-adv-x="1124" d="M986 814H152V975H986V814ZM986 399H152V559H986V399Z" /> +<glyph unicode=">" horiz-adv-x="1070" d="M795 650L134 909V1099L988 721V575L134 196V388L795 650Z" /> +<glyph unicode="?" horiz-adv-x="967" d="M357 410Q359 529 384 598T486 751L617 886Q701 981 701 1090Q701 1195 646 1254T486 1314Q384 1314 322 1260T260 1115H75Q77 1277 190 1376T486 1476Q675 1476 780 1375T886 1096Q886 921 724 751L615 643Q542 562 542 +410H357ZM349 93Q349 138 376 168T458 199T540 169T568 93T540 19T458 -11T377 18T349 93Z" /> +<glyph unicode="@" horiz-adv-x="1839" d="M1738 502Q1726 260 1618 120T1329 -20Q1142 -20 1089 148Q1035 63 966 22T822 -20Q680 -20 607 96T553 417Q568 582 628 711T784 915T985 989Q1066 989 1130 968T1274 883L1222 329Q1203 98 1350 98Q1463 98 1533 210T1609 +502Q1628 891 1465 1095T967 1299Q766 1299 610 1200T364 912T263 478Q251 230 323 48T542 -231T899 -328Q989 -328 1079 -306T1230 -249L1267 -364Q1205 -403 1103 -428T895 -453Q645 -453 465 -341T196 -17T118 478Q130 753 241 972T542 1311T971 1431Q1220 1431 +1398 1319T1663 996T1738 502ZM712 417Q698 275 738 199T867 123Q927 123 982 174T1074 320L1075 329L1121 832Q1065 861 1001 861Q884 861 808 742T712 417Z" /> +<glyph unicode="A" horiz-adv-x="1336" d="M973 380H363L226 0H28L584 1456H752L1309 0H1112L973 380ZM421 538H916L668 1219L421 538Z" /> +<glyph unicode="B" horiz-adv-x="1275" d="M169 0V1456H645Q882 1456 1001 1358T1121 1068Q1121 966 1063 888T905 766Q1023 733 1091 641T1160 420Q1160 224 1033 112T674 0H169ZM361 681V157H678Q812 157 889 226T967 418Q967 681 681 681H361ZM361 835H651Q777 +835 852 898T928 1069Q928 1189 858 1243T645 1298H361V835Z" /> +<glyph unicode="C" horiz-adv-x="1333" d="M1240 462Q1213 231 1070 106T688 -20Q430 -20 275 165T119 660V800Q119 1003 191 1157T397 1393T705 1476Q937 1476 1077 1347T1240 988H1047Q1022 1162 939 1240T705 1318Q521 1318 417 1182T312 795V654Q312 417 411 +277T688 137Q848 137 933 209T1047 462H1240Z" /> +<glyph unicode="D" horiz-adv-x="1343" d="M169 0V1456H580Q770 1456 916 1372T1141 1133T1222 777V684Q1222 478 1143 323T916 85T572 0H169ZM361 1298V157H563Q785 157 908 295T1032 688V773Q1032 1021 916 1158T585 1298H361Z" /> +<glyph unicode="E" horiz-adv-x="1164" d="M992 673H361V157H1094V0H169V1456H1084V1298H361V830H992V673Z" /> +<glyph unicode="F" horiz-adv-x="1132" d="M972 643H361V0H169V1456H1071V1298H361V800H972V643Z" /> +<glyph unicode="G" horiz-adv-x="1395" d="M1244 191Q1170 85 1038 33T729 -20Q551 -20 413 63T200 301T122 658V785Q122 1114 275 1295T707 1476Q935 1476 1074 1360T1244 1029H1052Q998 1318 708 1318Q515 1318 416 1183T315 790V671Q315 426 427 282T730 137Q838 +137 919 161T1053 242V569H716V725H1244V191Z" /> +<glyph unicode="H" horiz-adv-x="1460" d="M1288 0H1095V673H361V0H169V1456H361V830H1095V1456H1288V0Z" /> +<glyph unicode="I" horiz-adv-x="557" d="M375 0H183V1456H375V0Z" /> +<glyph unicode="J" horiz-adv-x="1130" d="M779 1456H972V425Q972 216 847 98T512 -20Q295 -20 174 91T53 402H245Q245 277 313 207T512 137Q631 137 704 212T779 422V1456Z" /> +<glyph unicode="K" horiz-adv-x="1284" d="M539 677L361 492V0H169V1456H361V736L1008 1456H1240L667 813L1285 0H1055L539 677Z" /> +<glyph unicode="L" horiz-adv-x="1102" d="M362 157H1052V0H169V1456H362V157Z" /> +<glyph unicode="M" horiz-adv-x="1788" d="M417 1456L893 268L1369 1456H1618V0H1426V567L1444 1179L966 0H819L342 1176L361 567V0H169V1456H417Z" /> +<glyph unicode="N" horiz-adv-x="1460" d="M1288 0H1095L362 1122V0H169V1456H362L1097 329V1456H1288V0Z" /> +<glyph unicode="O" horiz-adv-x="1408" d="M1289 681Q1289 467 1217 308T1013 64T705 -20Q533 -20 400 64T194 305T118 668V773Q118 983 191 1144T397 1390T703 1476Q878 1476 1011 1392T1217 1147T1289 773V681ZM1098 775Q1098 1034 994 1172T703 1311Q521 1311 +417 1173T309 788V681Q309 430 414 287T705 143Q891 143 993 278T1098 667V775Z" /> +<glyph unicode="P" horiz-adv-x="1292" d="M361 570V0H169V1456H706Q945 1456 1080 1334T1216 1011Q1216 799 1084 685T704 570H361ZM361 727H706Q860 727 942 799T1024 1009Q1024 1139 942 1217T717 1298H361V727Z" /> +<glyph unicode="Q" horiz-adv-x="1408" d="M1281 681Q1281 470 1214 318T1026 79L1286 -125L1155 -246L848 -2Q776 -20 696 -20Q524 -20 391 64T185 305T109 668V773Q109 983 182 1144T388 1390T694 1476Q870 1476 1003 1391T1209 1147T1281 774V681ZM1089 775Q1089 +1032 987 1171T694 1311Q513 1311 409 1173T301 788V681Q301 431 405 287T696 143T984 278T1089 667V775Z" /> +<glyph unicode="R" horiz-adv-x="1261" d="M703 589H361V0H168V1456H650Q896 1456 1028 1344T1161 1018Q1161 882 1088 781T883 630L1225 12V0H1019L703 589ZM361 746H656Q799 746 883 820T968 1018Q968 1153 888 1225T655 1298H361V746Z" /> +<glyph unicode="S" horiz-adv-x="1215" d="M598 649Q351 720 239 823T126 1079Q126 1251 263 1363T621 1476Q771 1476 888 1418T1070 1258T1135 1035H942Q942 1167 858 1242T621 1318Q479 1318 400 1256T320 1082Q320 993 395 932T652 819T936 707T1088 563T1138 +370Q1138 193 1000 87T631 -20Q481 -20 351 37T151 195T80 422H273Q273 290 370 214T631 137Q783 137 864 199T945 368T870 533T598 649Z" /> +<glyph unicode="T" horiz-adv-x="1222" d="M1175 1298H707V0H516V1298H49V1456H1175V1298Z" /> +<glyph unicode="U" horiz-adv-x="1328" d="M1194 1456V466Q1193 260 1065 129T716 -18L665 -20Q426 -20 284 109T140 464V1456H330V470Q330 312 417 225T665 137Q828 137 914 224T1001 469V1456H1194Z" /> +<glyph unicode="V" horiz-adv-x="1303" d="M651 255L1067 1456H1277L737 0H567L28 1456H237L651 255Z" /> +<glyph unicode="W" horiz-adv-x="1817" d="M483 459L511 267L552 440L840 1456H1002L1283 440L1323 264L1354 460L1580 1456H1773L1420 0H1245L945 1061L922 1172L899 1061L588 0H413L61 1456H253L483 459Z" /> +<glyph unicode="X" horiz-adv-x="1284" d="M644 898L993 1456H1219L759 734L1230 0H1002L644 568L284 0H57L529 734L68 1456H293L644 898Z" /> +<glyph unicode="Y" horiz-adv-x="1230" d="M613 725L993 1456H1211L709 543V0H517V543L15 1456H235L613 725Z" /> +<glyph unicode="Z" horiz-adv-x="1226" d="M313 157H1146V0H86V144L884 1298H99V1456H1114V1315L313 157Z" /> +<glyph unicode="[" horiz-adv-x="543" d="M523 1512H332V-160H523V-312H146V1664H523V1512Z" /> +<glyph unicode="\" horiz-adv-x="840" d="M40 1456H216L824 -125H648L40 1456Z" /> +<glyph unicode="]" horiz-adv-x="543" d="M9 1664H387V-312H9V-160H202V1512H9V1664Z" /> +<glyph unicode="^" horiz-adv-x="856" d="M426 1211L236 729H64L363 1456H490L788 729H617L426 1211Z" /> +<glyph unicode="_" horiz-adv-x="924" d="M920 -151H4V0H920V-151Z" /> +<glyph unicode="`" horiz-adv-x="633" d="M474 1242H315L57 1536H280L474 1242Z" /> +<glyph unicode="a" horiz-adv-x="1114" d="M808 0Q792 32 782 114Q653 -20 474 -20Q314 -20 212 70T109 300Q109 469 237 562T599 656H779V741Q779 838 721 895T550 953Q451 953 384 903T317 782H131Q131 863 188 938T344 1058T561 1102Q748 1102 854 1009T964 +751V253Q964 104 1002 16V0H808ZM501 141Q588 141 666 186T779 303V525H634Q294 525 294 326Q294 239 352 190T501 141Z" /> +<glyph unicode="b" horiz-adv-x="1149" d="M1056 529Q1056 281 942 131T636 -20Q431 -20 319 125L310 0H140V1536H325V963Q437 1102 634 1102T943 953T1056 545V529ZM871 550Q871 739 798 842T588 945Q405 945 325 775V307Q410 137 590 137Q723 137 797 240T871 550Z" /> +<glyph unicode="c" horiz-adv-x="1072" d="M574 131Q673 131 747 191T829 341H1004Q999 248 940 164T783 30T574 -20Q353 -20 223 127T92 531V562Q92 720 150 843T316 1034T573 1102Q755 1102 875 993T1004 710H829Q821 815 750 882T573 950Q432 950 355 849T277 +555V520Q277 333 354 232T574 131Z" /> +<glyph unicode="d" horiz-adv-x="1155" d="M95 550Q95 799 213 950T522 1102Q712 1102 823 972V1536H1008V0H838L829 116Q718 -20 520 -20Q332 -20 214 134T95 536V550ZM280 529Q280 345 356 241T566 137Q742 137 823 295V792Q740 945 568 945Q432 945 356 840T280 529Z" /> +<glyph unicode="e" horiz-adv-x="1085" d="M589 -20Q369 -20 231 124T93 511V545Q93 706 154 832T326 1030T566 1102Q777 1102 894 963T1011 565V488H278Q282 328 371 230T599 131Q697 131 765 171T884 277L997 189Q861 -20 589 -20ZM566 950Q454 950 378 869T284 +640H826V654Q818 795 750 872T566 950Z" /> +<glyph unicode="f" horiz-adv-x="711" d="M231 0V939H60V1082H231V1193Q231 1367 324 1462T587 1557Q651 1557 714 1540L704 1390Q657 1399 604 1399Q514 1399 465 1347T416 1196V1082H647V939H416V0H231Z" /> +<glyph unicode="g" horiz-adv-x="1149" d="M96 550Q96 803 213 952T523 1102Q721 1102 832 962L841 1082H1010V26Q1010 -184 886 -305T551 -426Q434 -426 322 -376T151 -239L247 -128Q366 -275 538 -275Q673 -275 748 -199T824 15V108Q713 -20 521 -20Q331 -20 +214 133T96 550ZM282 529Q282 346 357 242T567 137Q742 137 824 296V790Q739 945 569 945Q434 945 358 840T282 529Z" /> +<glyph unicode="h" horiz-adv-x="1128" d="M325 951Q448 1102 645 1102Q988 1102 991 715V0H806V716Q805 833 753 889T589 945Q499 945 431 897T325 771V0H140V1536H325V951Z" /> +<glyph unicode="i" horiz-adv-x="497" d="M341 0H156V1082H341V0ZM141 1369Q141 1414 168 1445T250 1476T332 1445T360 1369T332 1294T250 1264T169 1294T141 1369Z" /> +<glyph unicode="j" horiz-adv-x="489" d="M331 1082V-125Q331 -437 48 -437Q-13 -437 -65 -419V-271Q-33 -279 19 -279Q81 -279 113 -246T146 -129V1082H331ZM127 1369Q127 1413 154 1444T235 1476Q289 1476 317 1445T345 1369T317 1294T235 1264T154 1294T127 1369Z" /> +<glyph unicode="k" horiz-adv-x="1038" d="M442 501L326 380V0H141V1536H326V607L425 726L762 1082H987L566 630L1036 0H819L442 501Z" /> +<glyph unicode="l" horiz-adv-x="497" d="M341 0H156V1536H341V0Z" /> +<glyph unicode="m" horiz-adv-x="1795" d="M314 1082L319 962Q438 1102 640 1102Q867 1102 949 928Q1003 1006 1089 1054T1294 1102Q1650 1102 1656 725V0H1471V714Q1471 830 1418 887T1240 945Q1137 945 1069 884T990 718V0H804V709Q804 945 573 945Q391 945 +324 790V0H139V1082H314Z" /> +<glyph unicode="n" horiz-adv-x="1130" d="M315 1082L321 946Q445 1102 645 1102Q988 1102 991 715V0H806V716Q805 833 753 889T589 945Q499 945 431 897T325 771V0H140V1082H315Z" /> +<glyph unicode="o" horiz-adv-x="1168" d="M91 551Q91 710 153 837T327 1033T582 1102Q803 1102 939 949T1076 542V529Q1076 371 1016 246T843 50T584 -20Q364 -20 228 133T91 538V551ZM277 529Q277 349 360 240T584 131Q725 131 808 241T891 551Q891 729 807 +839T582 950Q445 950 361 841T277 529Z" /> +<glyph unicode="p" horiz-adv-x="1149" d="M1054 529Q1054 282 941 131T635 -20Q438 -20 325 105V-416H140V1082H309L318 962Q431 1102 632 1102Q827 1102 940 955T1054 546V529ZM869 550Q869 733 791 839T577 945Q409 945 325 796V279Q408 131 579 131Q712 131 +790 236T869 550Z" /> +<glyph unicode="q" horiz-adv-x="1164" d="M95 550Q95 805 212 953T526 1102Q718 1102 829 973L837 1082H1007V-416H822V100Q710 -20 524 -20Q328 -20 212 132T95 537V550ZM280 529Q280 343 358 237T570 131Q735 131 822 277V807Q734 950 572 950Q438 950 359 +844T280 529Z" /> +<glyph unicode="r" horiz-adv-x="693" d="M663 916Q621 923 572 923Q390 923 325 768V0H140V1082H320L323 957Q414 1102 581 1102Q635 1102 663 1088V916Z" /> +<glyph unicode="s" horiz-adv-x="1056" d="M770 287Q770 362 714 403T517 475T294 547T172 647T132 785Q132 918 244 1010T532 1102Q716 1102 830 1007T945 764H759Q759 840 695 895T532 950Q431 950 374 906T317 791Q317 724 370 690T561 625T786 551T913 448T955 +300Q955 155 839 68T538 -20Q408 -20 308 26T152 154T95 333H280Q285 240 354 186T538 131Q643 131 706 173T770 287Z" /> +<glyph unicode="t" horiz-adv-x="669" d="M391 1344V1082H593V939H391V268Q391 203 418 171T510 138Q542 138 598 150V0Q525 -20 456 -20Q332 -20 269 55T206 268V939H9V1082H206V1344H391Z" /> +<glyph unicode="u" horiz-adv-x="1129" d="M808 107Q700 -20 491 -20Q318 -20 228 80T136 378V1082H321V383Q321 137 521 137Q733 137 803 295V1082H988V0H812L808 107Z" /> +<glyph unicode="v" horiz-adv-x="992" d="M497 251L765 1082H954L566 0H425L33 1082H222L497 251Z" /> +<glyph unicode="w" horiz-adv-x="1539" d="M1098 255L1306 1082H1491L1176 0H1026L763 820L507 0H357L43 1082H227L440 272L692 1082H841L1098 255Z" /> +<glyph unicode="x" horiz-adv-x="1015" d="M503 687L743 1082H959L605 547L970 0H756L506 405L256 0H41L406 547L52 1082H266L503 687Z" /> +<glyph unicode="y" horiz-adv-x="969" d="M494 271L746 1082H944L509 -167Q408 -437 188 -437L153 -434L84 -421V-271L134 -275Q228 -275 280 -237T367 -98L408 12L22 1082H224L494 271Z" /> +<glyph unicode="z" horiz-adv-x="1015" d="M314 151H947V0H88V136L685 929H97V1082H917V951L314 151Z" /> +<glyph unicode="{" horiz-adv-x="693" d="M632 -366Q455 -316 366 -202T276 101V300Q276 543 64 543V688Q276 688 276 930V1138Q278 1321 365 1433T632 1597L670 1482Q461 1415 461 1133V931Q461 704 294 615Q461 525 461 296V90Q464 -185 670 -251L632 -366Z" /> +<glyph unicode="|" horiz-adv-x="499" d="M324 -270H175V1456H324V-270Z" /> +<glyph unicode="}" horiz-adv-x="693" d="M19 -251Q222 -186 229 80V300Q229 531 410 615Q229 697 229 930V1133Q229 1415 20 1482L58 1597Q235 1547 324 1435T414 1137V927Q414 688 626 688V543Q414 543 414 300V98Q414 -90 324 -203T58 -366L19 -251Z" /> +<glyph unicode="~" horiz-adv-x="1393" d="M1263 777Q1263 619 1170 511T939 402Q867 402 803 428T655 529T533 621T454 639Q376 639 334 586T292 438L131 436Q131 596 223 699T454 802Q530 802 600 770T758 658T910 567L939 565Q1015 565 1062 623T1110 776L1263 777Z" /> +<glyph unicode=" " horiz-adv-x="507" /> +<glyph unicode="¡" horiz-adv-x="499" d="M170 684H338L351 -360H157L170 684ZM358 996Q358 951 331 920T249 889T167 920T139 996T167 1071T249 1101T330 1071T358 996Z" /> +<glyph unicode="¢" horiz-adv-x="1120" d="M586 131Q686 131 760 191T842 341H1017Q1011 215 912 115T669 -12V-245H484V-11Q305 23 205 165T105 527V562Q105 774 206 916T484 1092V1318H669V1095Q819 1072 915 966T1017 710H842Q834 815 763 882T586 950Q445 +950 368 849T290 555V520Q290 333 367 232T586 131Z" /> +<glyph unicode="£" horiz-adv-x="1190" d="M449 622L457 402Q457 248 395 157H1128L1127 0H95V157H172Q212 166 237 231T264 393V401L256 622H91V779H251L242 1039Q242 1238 364 1357T687 1476Q877 1476 988 1370T1099 1087H908Q908 1194 845 1256T670 1318Q565 +1318 500 1241T435 1039L444 779H763V622H449Z" /> +<glyph unicode="¤" horiz-adv-x="1460" d="M1103 112Q944 -20 735 -20Q528 -20 369 110L235 -26L105 109L244 250Q140 406 140 608Q140 814 252 977L105 1128L235 1264L382 1114Q540 1234 735 1234Q931 1234 1090 1113L1239 1265L1371 1128L1220 974Q1330 +811 1330 608Q1330 412 1228 253L1371 109L1239 -27L1103 112ZM311 608Q311 485 368 379T524 212T735 151T946 212T1100 379T1157 608Q1157 730 1101 835T946 1001T735 1062Q622 1062 524 1002T369 836T311 608Z" /> +<glyph unicode="¥" horiz-adv-x="1075" d="M539 793L847 1456H1060L693 736H954V611H630V446H954V322H630V0H437V322H119V446H437V611H119V736H382L15 1456H231L539 793Z" /> +<glyph unicode="¦" horiz-adv-x="491" d="M147 -270V521H333V-270H147ZM333 698H147V1456H333V698Z" /> +<glyph unicode="§" horiz-adv-x="1256" d="M1145 431Q1145 242 959 157Q1028 108 1064 40T1100 -128Q1100 -296 970 -395T612 -495Q500 -495 400 -467T229 -382Q90 -269 90 -64L276 -62Q276 -192 366 -267T612 -343Q748 -343 831 -285T914 -130Q914 -41 843 +11T563 126Q381 174 285 229T143 362T96 551Q96 737 278 825Q212 874 177 942T141 1110Q141 1276 274 1376T630 1476Q862 1476 992 1363T1122 1045H937Q937 1170 853 1247T630 1325Q488 1325 408 1268T327 1112Q327 1043 355 1003T450 931T661 858T889 782T1030 +698T1116 585T1145 431ZM602 691Q512 715 437 742Q357 723 320 673T282 553Q282 483 309 443T402 370T611 296T797 238Q875 258 917 308T959 428Q959 516 890 570T602 691Z" /> +<glyph unicode="¨" horiz-adv-x="856" d="M101 1371Q101 1416 128 1446T210 1477T292 1447T320 1371T292 1296T210 1266T129 1296T101 1371ZM531 1369Q531 1414 558 1445T640 1476T722 1445T750 1369T722 1294T640 1264T559 1294T531 1369Z" /> +<glyph unicode="©" horiz-adv-x="1609" d="M1119 597Q1119 444 1033 364T788 283Q631 283 537 388T442 676V786Q442 962 537 1067T788 1173Q948 1173 1034 1091T1120 860H974Q974 959 927 1001T788 1044Q694 1044 640 975T586 783V670Q586 550 640 481T788 +412Q880 412 926 454T973 597H1119ZM206 729Q206 557 286 411T503 181T801 98T1098 181T1315 410T1395 729Q1395 899 1316 1044T1100 1272T801 1356Q641 1356 503 1274T286 1045T206 729ZM91 729Q91 931 184 1104T443 1376T801 1476T1158 1377T1416 1104T1510 729Q1510 +532 1420 360T1165 84T801 -21Q604 -21 439 82T182 358T91 729Z" /> +<glyph unicode="ª" horiz-adv-x="915" d="M618 705Q606 739 600 777Q524 691 396 691Q277 691 212 753T147 918Q147 1029 230 1089T486 1149H594V1201Q594 1336 470 1336Q401 1336 362 1309T322 1231L161 1243Q161 1346 247 1411T470 1476Q603 1476 680 1405T757 +1199V883Q757 786 783 705H618ZM435 828Q478 828 522 848T594 895V1037H482Q399 1036 355 1005T310 922Q310 828 435 828Z" /> +<glyph unicode="«" horiz-adv-x="961" d="M536 804L794 407H653L358 795V814L653 1203H794L536 804ZM610 548L868 151H727L432 539V558L727 947H868L610 548Z" /> +<glyph unicode="¬" horiz-adv-x="1134" d="M958 375H772V639H127V800H958V375Z" /> +<glyph unicode="­" horiz-adv-x="565" d="M525 543H37V694H525V543Z" /> +<glyph unicode="®" horiz-adv-x="1610" d="M90 729Q90 931 183 1104T442 1376T800 1476T1157 1377T1415 1104T1509 729Q1509 532 1419 360T1164 84T800 -21Q603 -21 438 82T181 358T90 729ZM205 729Q205 557 285 411T502 181T800 98Q961 98 1099 182T1315 +412T1394 729Q1394 900 1316 1044T1099 1272T800 1356Q640 1356 502 1274T285 1045T205 729ZM653 654V316H512V1165H788Q941 1165 1025 1100T1110 909Q1110 786 982 721Q1104 671 1105 517V456Q1105 370 1122 332V316H977Q963 352 963 444T960 554Q944 650 829 +654H653ZM653 782H809Q881 784 925 817T969 904Q969 977 930 1007T791 1038H653V782Z" /> +<glyph unicode="¯" horiz-adv-x="938" d="M814 1302H142V1445H814V1302Z" /> +<glyph unicode="°" horiz-adv-x="765" d="M130 1216Q130 1320 204 1398T385 1476Q489 1476 562 1399T636 1216Q636 1110 563 1035T385 960Q280 960 205 1035T130 1216ZM385 1088Q439 1088 476 1123T513 1216Q513 1274 476 1311T385 1349Q330 1349 293 1310T255 +1216T292 1125T385 1088Z" /> +<glyph unicode="±" horiz-adv-x="1094" d="M649 854H1013V703H649V289H482V703H97V854H482V1267H649V854ZM970 0H135V152H970V0Z" /> +<glyph unicode="²" horiz-adv-x="751" d="M683 667H84V775L384 1057Q493 1159 493 1228Q493 1277 461 1307T369 1338Q294 1338 259 1300T223 1205H66Q66 1319 149 1393T365 1467T574 1404T651 1230Q651 1126 544 1019L460 940L284 795H683V667Z" /> +<glyph unicode="³" horiz-adv-x="751" d="M265 1126H349Q423 1126 459 1156T495 1235Q495 1280 464 1309T362 1338Q305 1338 268 1313T230 1246H73Q73 1344 154 1405T360 1467Q497 1467 575 1407T653 1242Q653 1187 618 1142T517 1071Q666 1030 666 887Q666 +781 581 719T360 656Q228 656 145 719T62 889H220Q220 844 259 814T366 784Q436 784 472 814T509 895Q509 1008 353 1010H265V1126Z" /> +<glyph unicode="´" horiz-adv-x="642" d="M316 1536H540L272 1242H123L316 1536Z" /> +<glyph unicode="µ" horiz-adv-x="1160" d="M339 1082V449Q340 286 391 208T559 130Q758 130 820 282V1082H1006V0H839L830 115Q737 -20 567 -20Q420 -20 339 53V-416H154V1082H339Z" /> +<glyph unicode="¶" horiz-adv-x="1001" d="M646 0V520H562Q332 520 200 647T67 988Q67 1201 200 1328T563 1456H832V0H646Z" /> +<glyph unicode="·" horiz-adv-x="534" d="M147 729Q147 777 175 809T261 841T347 809T377 729Q377 682 348 651T261 619T176 650T147 729Z" /> +<glyph unicode="¸" horiz-adv-x="507" d="M285 0L273 -52Q426 -79 426 -225Q426 -322 346 -378T123 -435L116 -328Q195 -328 238 -302T282 -229Q282 -185 250 -164T120 -134L152 0H285Z" /> +<glyph unicode="¹" horiz-adv-x="751" d="M495 667H338V1268L122 1211V1339L477 1456H495V667Z" /> +<glyph unicode="º" horiz-adv-x="931" d="M122 1123Q122 1281 216 1378T464 1476Q619 1476 713 1380T807 1117V1043Q807 884 714 787T466 690T217 787T122 1049V1123ZM285 1043Q285 943 333 886T466 829Q549 829 596 886T644 1045V1123Q644 1222 596 1279T464 +1336Q383 1336 335 1281T285 1129V1043Z" /> +<glyph unicode="»" horiz-adv-x="960" d="M244 949L539 560V541L244 152H102L360 550L102 949H244ZM593 949L888 560V541L593 152H451L709 550L451 949H593Z" /> +<glyph unicode="¼" horiz-adv-x="1500" d="M458 664H301V1265L85 1208V1336L440 1453H458V664ZM443 118L339 184L1050 1322L1154 1256L443 118ZM1318 299H1425V169H1318V0H1161V169H786L780 271L1157 789H1318V299ZM938 299H1161V588L1144 560L938 299Z" /> +<glyph unicode="½" horiz-adv-x="1589" d="M399 118L295 184L1006 1322L1110 1256L399 118ZM453 664H296V1265L80 1208V1336L435 1453H453V664ZM1481 0H882V108L1182 390Q1291 492 1291 561Q1291 610 1259 640T1167 671Q1092 671 1057 633T1021 538H864Q864 +652 947 726T1163 800T1372 737T1449 563Q1449 459 1342 352L1258 273L1082 128H1481V0Z" /> +<glyph unicode="¾" horiz-adv-x="1593" d="M570 118L466 184L1177 1322L1281 1256L570 118ZM1410 299H1517V169H1410V0H1253V169H878L872 271L1249 789H1410V299ZM1030 299H1253V588L1236 560L1030 299ZM314 1126H398Q472 1126 508 1156T544 1235Q544 1280 +513 1309T411 1338Q354 1338 317 1313T279 1246H122Q122 1344 203 1405T409 1467Q546 1467 624 1407T702 1242Q702 1187 667 1142T566 1071Q715 1030 715 887Q715 781 630 719T409 656Q277 656 194 719T111 889H269Q269 844 308 814T415 784Q485 784 521 814T558 +895Q558 1008 402 1010H314V1126Z" /> +<glyph unicode="¿" horiz-adv-x="969" d="M588 680Q587 574 567 511T498 388T358 233T255 37L253 0Q253 -109 311 -166T478 -224Q578 -224 640 -168T703 -20H888Q886 -181 774 -283T478 -385Q282 -385 175 -285T68 -5Q68 168 228 343L337 456Q403 534 403 +680H588ZM596 997Q596 952 569 921T487 890T405 921T377 997Q377 1041 405 1071T487 1101T568 1071T596 997Z" /> +<glyph unicode="À" horiz-adv-x="1336" d="M973 380H363L226 0H28L584 1456H752L1309 0H1112L973 380ZM421 538H916L668 1219L421 538ZM778 1552H619L361 1846H584L778 1552Z" /> +<glyph unicode="Á" horiz-adv-x="1336" d="M973 380H363L226 0H28L584 1456H752L1309 0H1112L973 380ZM421 538H916L668 1219L421 538ZM763 1846H987L719 1552H570L763 1846Z" /> +<glyph unicode="Â" horiz-adv-x="1336" d="M973 380H363L226 0H28L584 1456H752L1309 0H1112L973 380ZM421 538H916L668 1219L421 538ZM975 1572V1562H822L672 1732L523 1562H370V1574L616 1846H728L975 1572Z" /> +<glyph unicode="Ã" horiz-adv-x="1336" d="M973 380H363L226 0H28L584 1456H752L1309 0H1112L973 380ZM421 538H916L668 1219L421 538ZM1027 1814Q1027 1706 966 1639T812 1572Q771 1572 741 1582T663 1623T593 1660T543 1667Q502 1667 473 1636T444 1555L320 +1562Q320 1669 380 1739T534 1809Q569 1809 597 1799T673 1760T746 1722T803 1713Q846 1713 874 1747T903 1826L1027 1814Z" /> +<glyph unicode="Ä" horiz-adv-x="1336" d="M973 380H363L226 0H28L584 1456H752L1309 0H1112L973 380ZM421 538H916L668 1219L421 538ZM350 1681Q350 1726 377 1756T459 1787T541 1757T569 1681T541 1606T459 1576T378 1606T350 1681ZM780 1679Q780 1724 +807 1755T889 1786T971 1755T999 1679T971 1604T889 1574T808 1604T780 1679Z" /> +<glyph unicode="Å" horiz-adv-x="1336" d="M973 380H363L226 0H28L584 1456H752L1309 0H1112L973 380ZM421 538H916L668 1219L421 538ZM887 1729Q887 1642 825 1584T672 1525Q580 1525 519 1584T457 1729T518 1876T672 1937T825 1876T887 1729ZM556 1729Q556 +1682 589 1648T672 1614Q720 1614 754 1647T788 1729T755 1812T672 1847Q622 1847 589 1812T556 1729Z" /> +<glyph unicode="Æ" horiz-adv-x="1914" d="M1879 0H996L981 353H417L212 0H-14L866 1456H1817V1304H1126L1146 833H1736V682H1152L1174 151H1879V0ZM518 527H974L943 1260L518 527Z" /> +<glyph unicode="Ç" horiz-adv-x="1333" d="M1240 462Q1213 231 1070 106T688 -20Q430 -20 275 165T119 660V800Q119 1003 191 1157T397 1393T705 1476Q937 1476 1077 1347T1240 988H1047Q1022 1162 939 1240T705 1318Q521 1318 417 1182T312 795V654Q312 +417 411 277T688 137Q848 137 933 209T1047 462H1240ZM751 -9L739 -61Q892 -88 892 -234Q892 -331 812 -387T589 -444L582 -337Q661 -337 704 -311T748 -238Q748 -194 716 -173T586 -143L618 -9H751Z" /> +<glyph unicode="È" horiz-adv-x="1164" d="M992 673H361V157H1094V0H169V1456H1084V1298H361V830H992V673ZM725 1564H566L308 1858H531L725 1564Z" /> +<glyph unicode="É" horiz-adv-x="1164" d="M992 673H361V157H1094V0H169V1456H1084V1298H361V830H992V673ZM710 1858H934L666 1564H517L710 1858Z" /> +<glyph unicode="Ê" horiz-adv-x="1164" d="M992 673H361V157H1094V0H169V1456H1084V1298H361V830H992V673ZM922 1584V1574H769L619 1744L470 1574H317V1586L563 1858H675L922 1584Z" /> +<glyph unicode="Ë" horiz-adv-x="1164" d="M992 673H361V157H1094V0H169V1456H1084V1298H361V830H992V673ZM297 1693Q297 1738 324 1768T406 1799T488 1769T516 1693T488 1618T406 1588T325 1618T297 1693ZM727 1691Q727 1736 754 1767T836 1798T918 1767T946 +1691T918 1616T836 1586T755 1616T727 1691Z" /> +<glyph unicode="Ì" horiz-adv-x="557" d="M375 0H183V1456H375V0ZM385 1564H226L-32 1858H191L385 1564Z" /> +<glyph unicode="Í" horiz-adv-x="557" d="M375 0H183V1456H375V0ZM369 1858H593L325 1564H176L369 1858Z" /> +<glyph unicode="Î" horiz-adv-x="557" d="M375 0H183V1456H375V0ZM582 1584V1574H429L279 1744L130 1574H-23V1586L223 1858H335L582 1584Z" /> +<glyph unicode="Ï" horiz-adv-x="557" d="M375 0H183V1456H375V0ZM-43 1693Q-43 1738 -16 1768T66 1799T148 1769T176 1693T148 1618T66 1588T-15 1618T-43 1693ZM387 1691Q387 1736 414 1767T496 1798T578 1767T606 1691T578 1616T496 1586T415 1616T387 1691Z" /> +<glyph unicode="Ð" horiz-adv-x="1373" d="M199 0V666H7V817H199V1456H610Q800 1456 946 1372T1171 1133T1252 777V684Q1252 478 1173 323T946 85T602 0H199ZM643 666H391V157H592Q814 157 937 294T1062 680V773Q1062 1021 946 1158T615 1298H391V817H643V666Z" /> +<glyph unicode="Ñ" horiz-adv-x="1460" d="M1288 0H1095L362 1122V0H169V1456H362L1097 329V1456H1288V0ZM1081 1814Q1081 1706 1020 1639T866 1572Q825 1572 795 1582T717 1623T647 1660T597 1667Q556 1667 527 1636T498 1555L374 1562Q374 1669 434 1739T588 +1809Q623 1809 651 1799T727 1760T800 1722T857 1713Q900 1713 928 1747T957 1826L1081 1814Z" /> +<glyph unicode="Ò" horiz-adv-x="1408" d="M1289 681Q1289 467 1217 308T1013 64T705 -20Q533 -20 400 64T194 305T118 668V773Q118 983 191 1144T397 1390T703 1476Q878 1476 1011 1392T1217 1147T1289 773V681ZM1098 775Q1098 1034 994 1172T703 1311Q521 +1311 417 1173T309 788V681Q309 430 414 287T705 143Q891 143 993 278T1098 667V775ZM812 1554H653L395 1848H618L812 1554Z" /> +<glyph unicode="Ó" horiz-adv-x="1408" d="M1289 681Q1289 467 1217 308T1013 64T705 -20Q533 -20 400 64T194 305T118 668V773Q118 983 191 1144T397 1390T703 1476Q878 1476 1011 1392T1217 1147T1289 773V681ZM1098 775Q1098 1034 994 1172T703 1311Q521 +1311 417 1173T309 788V681Q309 430 414 287T705 143Q891 143 993 278T1098 667V775ZM797 1848H1021L753 1554H604L797 1848Z" /> +<glyph unicode="Ô" horiz-adv-x="1408" d="M1289 681Q1289 467 1217 308T1013 64T705 -20Q533 -20 400 64T194 305T118 668V773Q118 983 191 1144T397 1390T703 1476Q878 1476 1011 1392T1217 1147T1289 773V681ZM1098 775Q1098 1034 994 1172T703 1311Q521 +1311 417 1173T309 788V681Q309 430 414 287T705 143Q891 143 993 278T1098 667V775ZM1009 1574V1564H856L706 1734L557 1564H404V1576L650 1848H762L1009 1574Z" /> +<glyph unicode="Õ" horiz-adv-x="1408" d="M1289 681Q1289 467 1217 308T1013 64T705 -20Q533 -20 400 64T194 305T118 668V773Q118 983 191 1144T397 1390T703 1476Q878 1476 1011 1392T1217 1147T1289 773V681ZM1098 775Q1098 1034 994 1172T703 1311Q521 +1311 417 1173T309 788V681Q309 430 414 287T705 143Q891 143 993 278T1098 667V775ZM1061 1816Q1061 1708 1000 1641T846 1574Q805 1574 775 1584T697 1625T627 1662T577 1669Q536 1669 507 1638T478 1557L354 1564Q354 1671 414 1741T568 1811Q603 1811 631 1801T707 +1762T780 1724T837 1715Q880 1715 908 1749T937 1828L1061 1816Z" /> +<glyph unicode="Ö" horiz-adv-x="1408" d="M1289 681Q1289 467 1217 308T1013 64T705 -20Q533 -20 400 64T194 305T118 668V773Q118 983 191 1144T397 1390T703 1476Q878 1476 1011 1392T1217 1147T1289 773V681ZM1098 775Q1098 1034 994 1172T703 1311Q521 +1311 417 1173T309 788V681Q309 430 414 287T705 143Q891 143 993 278T1098 667V775ZM384 1683Q384 1728 411 1758T493 1789T575 1759T603 1683T575 1608T493 1578T412 1608T384 1683ZM814 1681Q814 1726 841 1757T923 1788T1005 1757T1033 1681T1005 1606T923 +1576T842 1606T814 1681Z" /> +<glyph unicode="×" horiz-adv-x="1092" d="M89 329L419 665L91 1000L210 1123L539 788L868 1123L987 1000L659 665L989 329L870 206L539 543L208 206L89 329Z" /> +<glyph unicode="Ø" horiz-adv-x="1408" d="M1289 681Q1289 467 1217 308T1013 64T705 -20Q534 -20 403 62L306 -93H164L308 138Q118 330 118 690V773Q118 983 191 1144T397 1390T703 1476Q917 1476 1065 1351L1168 1516H1309L1150 1261Q1287 1074 1289 780V681ZM309 +681Q309 437 407 296L971 1200Q869 1311 703 1311Q521 1311 417 1173T309 788V681ZM1098 775Q1098 957 1042 1088L493 207Q584 143 705 143Q891 143 993 278T1098 667V775Z" /> +<glyph unicode="Ù" horiz-adv-x="1328" d="M1194 1456V466Q1193 260 1065 129T716 -18L665 -20Q426 -20 284 109T140 464V1456H330V470Q330 312 417 225T665 137Q828 137 914 224T1001 469V1456H1194ZM773 1552H614L356 1846H579L773 1552Z" /> +<glyph unicode="Ú" horiz-adv-x="1328" d="M1194 1456V466Q1193 260 1065 129T716 -18L665 -20Q426 -20 284 109T140 464V1456H330V470Q330 312 417 225T665 137Q828 137 914 224T1001 469V1456H1194ZM758 1846H982L714 1552H565L758 1846Z" /> +<glyph unicode="Û" horiz-adv-x="1328" d="M1194 1456V466Q1193 260 1065 129T716 -18L665 -20Q426 -20 284 109T140 464V1456H330V470Q330 312 417 225T665 137Q828 137 914 224T1001 469V1456H1194ZM970 1572V1562H817L667 1732L518 1562H365V1574L611 +1846H723L970 1572Z" /> +<glyph unicode="Ü" horiz-adv-x="1328" d="M1194 1456V466Q1193 260 1065 129T716 -18L665 -20Q426 -20 284 109T140 464V1456H330V470Q330 312 417 225T665 137Q828 137 914 224T1001 469V1456H1194ZM345 1681Q345 1726 372 1756T454 1787T536 1757T564 +1681T536 1606T454 1576T373 1606T345 1681ZM775 1679Q775 1724 802 1755T884 1786T966 1755T994 1679T966 1604T884 1574T803 1604T775 1679Z" /> +<glyph unicode="Ý" horiz-adv-x="1230" d="M613 725L993 1456H1211L709 543V0H517V543L15 1456H235L613 725ZM708 1846H932L664 1552H515L708 1846Z" /> +<glyph unicode="Þ" horiz-adv-x="1210" d="M352 1456V1163H631Q778 1163 888 1111T1057 961T1117 738Q1117 544 985 429T626 313H352V0H166V1456H352ZM352 1011V465H629Q771 465 851 540T931 736Q931 859 851 934T635 1011H352Z" /> +<glyph unicode="ß" horiz-adv-x="1218" d="M324 0H139V1111Q139 1319 242 1436T532 1554Q712 1554 810 1465T909 1216Q909 1091 845 990T781 819Q781 768 818 721T950 601T1087 461T1130 317Q1130 158 1029 69T745 -20Q664 -20 574 2T445 52L488 207Q537 +175 604 153T725 131Q832 131 888 178T945 307Q945 359 908 407T777 528T639 671T595 821Q595 910 664 1013T734 1201Q734 1295 682 1348T542 1402Q324 1402 324 1109V0Z" /> +<glyph unicode="à" horiz-adv-x="1114" d="M808 0Q792 32 782 114Q653 -20 474 -20Q314 -20 212 70T109 300Q109 469 237 562T599 656H779V741Q779 838 721 895T550 953Q451 953 384 903T317 782H131Q131 863 188 938T344 1058T561 1102Q748 1102 854 1009T964 +751V253Q964 104 1002 16V0H808ZM501 141Q588 141 666 186T779 303V525H634Q294 525 294 326Q294 239 352 190T501 141ZM687 1242H528L270 1536H493L687 1242Z" /> +<glyph unicode="á" horiz-adv-x="1114" d="M808 0Q792 32 782 114Q653 -20 474 -20Q314 -20 212 70T109 300Q109 469 237 562T599 656H779V741Q779 838 721 895T550 953Q451 953 384 903T317 782H131Q131 863 188 938T344 1058T561 1102Q748 1102 854 1009T964 +751V253Q964 104 1002 16V0H808ZM501 141Q588 141 666 186T779 303V525H634Q294 525 294 326Q294 239 352 190T501 141ZM672 1536H896L628 1242H479L672 1536Z" /> +<glyph unicode="â" horiz-adv-x="1114" d="M808 0Q792 32 782 114Q653 -20 474 -20Q314 -20 212 70T109 300Q109 469 237 562T599 656H779V741Q779 838 721 895T550 953Q451 953 384 903T317 782H131Q131 863 188 938T344 1058T561 1102Q748 1102 854 1009T964 +751V253Q964 104 1002 16V0H808ZM501 141Q588 141 666 186T779 303V525H634Q294 525 294 326Q294 239 352 190T501 141ZM884 1262V1252H731L581 1422L432 1252H279V1264L525 1536H637L884 1262Z" /> +<glyph unicode="ã" horiz-adv-x="1114" d="M808 0Q792 32 782 114Q653 -20 474 -20Q314 -20 212 70T109 300Q109 469 237 562T599 656H779V741Q779 838 721 895T550 953Q451 953 384 903T317 782H131Q131 863 188 938T344 1058T561 1102Q748 1102 854 1009T964 +751V253Q964 104 1002 16V0H808ZM501 141Q588 141 666 186T779 303V525H634Q294 525 294 326Q294 239 352 190T501 141ZM936 1504Q936 1396 875 1329T721 1262Q680 1262 650 1272T572 1313T502 1350T452 1357Q411 1357 382 1326T353 1245L229 1252Q229 1359 289 +1429T443 1499Q478 1499 506 1489T582 1450T655 1412T712 1403Q755 1403 783 1437T812 1516L936 1504Z" /> +<glyph unicode="ä" horiz-adv-x="1114" d="M808 0Q792 32 782 114Q653 -20 474 -20Q314 -20 212 70T109 300Q109 469 237 562T599 656H779V741Q779 838 721 895T550 953Q451 953 384 903T317 782H131Q131 863 188 938T344 1058T561 1102Q748 1102 854 1009T964 +751V253Q964 104 1002 16V0H808ZM501 141Q588 141 666 186T779 303V525H634Q294 525 294 326Q294 239 352 190T501 141ZM259 1371Q259 1416 286 1446T368 1477T450 1447T478 1371T450 1296T368 1266T287 1296T259 1371ZM689 1369Q689 1414 716 1445T798 1476T880 +1445T908 1369T880 1294T798 1264T717 1294T689 1369Z" /> +<glyph unicode="å" horiz-adv-x="1114" d="M808 0Q792 32 782 114Q653 -20 474 -20Q314 -20 212 70T109 300Q109 469 237 562T599 656H779V741Q779 838 721 895T550 953Q451 953 384 903T317 782H131Q131 863 188 938T344 1058T561 1102Q748 1102 854 1009T964 +751V253Q964 104 1002 16V0H808ZM501 141Q588 141 666 186T779 303V525H634Q294 525 294 326Q294 239 352 190T501 141ZM796 1419Q796 1332 734 1274T581 1215Q489 1215 428 1274T366 1419T427 1566T581 1627T734 1566T796 1419ZM465 1419Q465 1372 498 1338T581 +1304Q629 1304 663 1337T697 1419T664 1502T581 1537Q531 1537 498 1502T465 1419Z" /> +<glyph unicode="æ" horiz-adv-x="1729" d="M1262 -20Q1001 -20 865 160Q800 74 687 27T433 -20Q266 -20 172 66T78 304Q78 461 191 548T526 635H749V720Q749 827 694 888T535 950Q430 950 360 895T290 759L106 778Q106 921 227 1011T535 1102Q650 1102 738 +1061T876 936Q939 1015 1026 1058T1218 1102Q1428 1102 1544 974T1660 612V497H932Q939 321 1026 226T1262 130Q1410 130 1531 206L1578 237L1642 101Q1484 -20 1262 -20ZM469 130Q541 130 620 167T749 258V495H521Q404 493 334 438T264 300Q264 223 317 177T469 +130ZM1218 950Q1103 950 1029 865T937 640H1475V671Q1475 803 1408 876T1218 950Z" /> +<glyph unicode="ç" horiz-adv-x="1072" d="M574 131Q673 131 747 191T829 341H1004Q999 248 940 164T783 30T574 -20Q353 -20 223 127T92 531V562Q92 720 150 843T316 1034T573 1102Q755 1102 875 993T1004 710H829Q821 815 750 882T573 950Q432 950 355 +849T277 555V520Q277 333 354 232T574 131ZM604 -9L592 -61Q745 -88 745 -234Q745 -331 665 -387T442 -444L435 -337Q514 -337 557 -311T601 -238Q601 -194 569 -173T439 -143L471 -9H604Z" /> +<glyph unicode="è" horiz-adv-x="1085" d="M589 -20Q369 -20 231 124T93 511V545Q93 706 154 832T326 1030T566 1102Q777 1102 894 963T1011 565V488H278Q282 328 371 230T599 131Q697 131 765 171T884 277L997 189Q861 -20 589 -20ZM566 950Q454 950 378 +869T284 640H826V654Q818 795 750 872T566 950ZM671 1242H512L254 1536H477L671 1242Z" /> +<glyph unicode="é" horiz-adv-x="1085" d="M589 -20Q369 -20 231 124T93 511V545Q93 706 154 832T326 1030T566 1102Q777 1102 894 963T1011 565V488H278Q282 328 371 230T599 131Q697 131 765 171T884 277L997 189Q861 -20 589 -20ZM566 950Q454 950 378 +869T284 640H826V654Q818 795 750 872T566 950ZM656 1536H880L612 1242H463L656 1536Z" /> +<glyph unicode="ê" horiz-adv-x="1085" d="M589 -20Q369 -20 231 124T93 511V545Q93 706 154 832T326 1030T566 1102Q777 1102 894 963T1011 565V488H278Q282 328 371 230T599 131Q697 131 765 171T884 277L997 189Q861 -20 589 -20ZM566 950Q454 950 378 +869T284 640H826V654Q818 795 750 872T566 950ZM868 1262V1252H715L565 1422L416 1252H263V1264L509 1536H621L868 1262Z" /> +<glyph unicode="ë" horiz-adv-x="1085" d="M589 -20Q369 -20 231 124T93 511V545Q93 706 154 832T326 1030T566 1102Q777 1102 894 963T1011 565V488H278Q282 328 371 230T599 131Q697 131 765 171T884 277L997 189Q861 -20 589 -20ZM566 950Q454 950 378 +869T284 640H826V654Q818 795 750 872T566 950ZM243 1371Q243 1416 270 1446T352 1477T434 1447T462 1371T434 1296T352 1266T271 1296T243 1371ZM673 1369Q673 1414 700 1445T782 1476T864 1445T892 1369T864 1294T782 1264T701 1294T673 1369Z" /> +<glyph unicode="ì" horiz-adv-x="506" d="M341 0H155V1082H341V0ZM615 1497H456L198 1791H421L615 1497Z" /> +<glyph unicode="í" horiz-adv-x="506" d="M341 0H155V1082H341V0ZM343 1791H567L299 1497H150L343 1791Z" /> +<glyph unicode="î" horiz-adv-x="506" d="M341 0H155V1082H341V0ZM556 1261V1251H403L253 1421L104 1251H-49V1263L197 1535H309L556 1261Z" /> +<glyph unicode="ï" horiz-adv-x="506" d="M341 0H155V1082H341V0ZM-69 1370Q-69 1415 -42 1445T40 1476T122 1446T150 1370T122 1295T40 1265T-41 1295T-69 1370ZM361 1368Q361 1413 388 1444T470 1475T552 1444T580 1368T552 1293T470 1263T389 1293T361 1368Z" /> +<glyph unicode="ð" horiz-adv-x="1200" d="M820 1301Q1069 1037 1069 628V535Q1069 377 1011 251T844 52T602 -20Q467 -20 357 44T187 221T126 467Q126 614 182 730T341 912T574 977Q737 977 858 863Q810 1058 669 1199L451 1051L378 1150L570 1281Q438 1372 +255 1421L312 1580Q551 1526 726 1387L915 1516L988 1416L820 1301ZM884 635L882 691Q849 752 780 788T618 825Q473 825 392 730T311 467Q311 327 394 229T606 131Q731 131 807 244T884 541V635Z" /> +<glyph unicode="ñ" horiz-adv-x="1130" d="M315 1082L321 946Q445 1102 645 1102Q988 1102 991 715V0H806V716Q805 833 753 889T589 945Q499 945 431 897T325 771V0H140V1082H315ZM927 1504Q927 1396 866 1329T712 1262Q671 1262 641 1272T563 1313T493 1350T443 +1357Q402 1357 373 1326T344 1245L220 1252Q220 1359 280 1429T434 1499Q469 1499 497 1489T573 1450T646 1412T703 1403Q746 1403 774 1437T803 1516L927 1504Z" /> +<glyph unicode="ò" horiz-adv-x="1168" d="M91 551Q91 710 153 837T327 1033T582 1102Q803 1102 939 949T1076 542V529Q1076 371 1016 246T843 50T584 -20Q364 -20 228 133T91 538V551ZM277 529Q277 349 360 240T584 131Q725 131 808 241T891 551Q891 729 +807 839T582 950Q445 950 361 841T277 529ZM681 1242H522L264 1536H487L681 1242Z" /> +<glyph unicode="ó" horiz-adv-x="1168" d="M91 551Q91 710 153 837T327 1033T582 1102Q803 1102 939 949T1076 542V529Q1076 371 1016 246T843 50T584 -20Q364 -20 228 133T91 538V551ZM277 529Q277 349 360 240T584 131Q725 131 808 241T891 551Q891 729 +807 839T582 950Q445 950 361 841T277 529ZM666 1536H890L622 1242H473L666 1536Z" /> +<glyph unicode="ô" horiz-adv-x="1168" d="M91 551Q91 710 153 837T327 1033T582 1102Q803 1102 939 949T1076 542V529Q1076 371 1016 246T843 50T584 -20Q364 -20 228 133T91 538V551ZM277 529Q277 349 360 240T584 131Q725 131 808 241T891 551Q891 729 +807 839T582 950Q445 950 361 841T277 529ZM878 1262V1252H725L575 1422L426 1252H273V1264L519 1536H631L878 1262Z" /> +<glyph unicode="õ" horiz-adv-x="1168" d="M91 551Q91 710 153 837T327 1033T582 1102Q803 1102 939 949T1076 542V529Q1076 371 1016 246T843 50T584 -20Q364 -20 228 133T91 538V551ZM277 529Q277 349 360 240T584 131Q725 131 808 241T891 551Q891 729 +807 839T582 950Q445 950 361 841T277 529ZM930 1504Q930 1396 869 1329T715 1262Q674 1262 644 1272T566 1313T496 1350T446 1357Q405 1357 376 1326T347 1245L223 1252Q223 1359 283 1429T437 1499Q472 1499 500 1489T576 1450T649 1412T706 1403Q749 1403 777 +1437T806 1516L930 1504Z" /> +<glyph unicode="ö" horiz-adv-x="1168" d="M91 551Q91 710 153 837T327 1033T582 1102Q803 1102 939 949T1076 542V529Q1076 371 1016 246T843 50T584 -20Q364 -20 228 133T91 538V551ZM277 529Q277 349 360 240T584 131Q725 131 808 241T891 551Q891 729 +807 839T582 950Q445 950 361 841T277 529ZM253 1371Q253 1416 280 1446T362 1477T444 1447T472 1371T444 1296T362 1266T281 1296T253 1371ZM683 1369Q683 1414 710 1445T792 1476T874 1445T902 1369T874 1294T792 1264T711 1294T683 1369Z" /> +<glyph unicode="÷" horiz-adv-x="1169" d="M1069 600H71V784H1069V600ZM461 1098Q461 1146 489 1178T575 1210T661 1178T691 1098Q691 1051 662 1020T575 989T490 1020T461 1098ZM461 281Q461 329 489 361T575 393T661 361T691 281Q691 235 662 204T575 172T490 +203T461 281Z" /> +<glyph unicode="ø" horiz-adv-x="1160" d="M91 551Q91 710 152 836T326 1032T582 1102Q692 1102 786 1060L859 1208H983L881 1003Q1076 849 1076 529Q1076 371 1014 244T840 49T584 -20Q480 -20 394 15L320 -134H196L296 69Q91 218 91 551ZM276 529Q276 335 +373 224L716 918Q654 950 582 950Q444 950 360 841T276 529ZM890 551Q890 733 803 844L463 156Q518 131 584 131Q723 131 806 240T890 535V551Z" /> +<glyph unicode="ù" horiz-adv-x="1129" d="M808 107Q700 -20 491 -20Q318 -20 228 80T136 378V1082H321V383Q321 137 521 137Q733 137 803 295V1082H988V0H812L808 107ZM673 1242H514L256 1536H479L673 1242Z" /> +<glyph unicode="ú" horiz-adv-x="1129" d="M808 107Q700 -20 491 -20Q318 -20 228 80T136 378V1082H321V383Q321 137 521 137Q733 137 803 295V1082H988V0H812L808 107ZM658 1536H882L614 1242H465L658 1536Z" /> +<glyph unicode="û" horiz-adv-x="1129" d="M808 107Q700 -20 491 -20Q318 -20 228 80T136 378V1082H321V383Q321 137 521 137Q733 137 803 295V1082H988V0H812L808 107ZM870 1262V1252H717L567 1422L418 1252H265V1264L511 1536H623L870 1262Z" /> +<glyph unicode="ü" horiz-adv-x="1129" d="M808 107Q700 -20 491 -20Q318 -20 228 80T136 378V1082H321V383Q321 137 521 137Q733 137 803 295V1082H988V0H812L808 107ZM245 1371Q245 1416 272 1446T354 1477T436 1447T464 1371T436 1296T354 1266T273 1296T245 +1371ZM675 1369Q675 1414 702 1445T784 1476T866 1445T894 1369T866 1294T784 1264T703 1294T675 1369Z" /> +<glyph unicode="ý" horiz-adv-x="969" d="M494 271L746 1082H944L509 -167Q408 -437 188 -437L153 -434L84 -421V-271L134 -275Q228 -275 280 -237T367 -98L408 12L22 1082H224L494 271ZM599 1536H823L555 1242H406L599 1536Z" /> +<glyph unicode="þ" horiz-adv-x="1180" d="M1063 529Q1063 282 950 131T644 -20Q447 -20 334 105V-416H149V1536H334V970Q447 1102 641 1102Q836 1102 949 955T1063 546V529ZM878 550Q878 733 800 839T586 945Q418 945 334 796V279Q417 131 588 131Q721 131 +799 236T878 550Z" /> +<glyph unicode="ÿ" horiz-adv-x="969" d="M494 271L746 1082H944L509 -167Q408 -437 188 -437L153 -434L84 -421V-271L134 -275Q228 -275 280 -237T367 -98L408 12L22 1082H224L494 271ZM186 1371Q186 1416 213 1446T295 1477T377 1447T405 1371T377 1296T295 +1266T214 1296T186 1371ZM616 1369Q616 1414 643 1445T725 1476T807 1445T835 1369T807 1294T725 1264T644 1294T616 1369Z" /> +<glyph unicode="–" horiz-adv-x="1344" d="M1421 651H419V802H1421V651Z" /> +<glyph unicode="—" horiz-adv-x="1599" d="M1737 651H401V802H1737V651Z" /> +<glyph unicode="‘" horiz-adv-x="409" d="M270 1555L376 1483Q283 1356 280 1209V1073H96V1189Q96 1291 144 1391T270 1555Z" /> +<glyph unicode="’" horiz-adv-x="409" d="M153 1046L48 1118Q141 1248 144 1392V1536H327V1406Q326 1306 278 1207T153 1046Z" /> +<glyph unicode="‚" horiz-adv-x="407" d="M141 -283L36 -210Q127 -83 130 63V181H315V81Q315 -20 266 -121T141 -283Z" /> +<glyph unicode="“" horiz-adv-x="724" d="M278 1555L384 1483Q291 1356 288 1209V1073H104V1189Q104 1291 152 1391T278 1555ZM593 1555L699 1483Q606 1356 603 1209V1073H419V1189Q419 1291 467 1391T593 1555Z" /> +<glyph unicode="”" horiz-adv-x="731" d="M165 1046L60 1118Q153 1248 156 1392V1536H339V1406Q338 1306 290 1207T165 1046ZM472 1046L367 1118Q460 1248 463 1392V1536H646V1406Q645 1306 597 1207T472 1046Z" /> +<glyph unicode="„" horiz-adv-x="705" d="M141 -301L36 -229Q127 -92 130 61V246H315V82Q315 -26 266 -131T141 -301ZM437 -301L332 -229Q423 -92 426 61V246H612V82Q612 -25 564 -129T437 -301Z" /> +<glyph unicode="•" horiz-adv-x="690" d="M138 772Q138 859 193 915T341 971Q432 971 489 917T546 769V732Q546 645 491 590T342 535Q249 535 194 590T138 734V772Z" /> +<glyph unicode="‹" horiz-adv-x="614" d="M286 550L544 153H403L108 541V560L403 949H544L286 550Z" /> +<glyph unicode="›" horiz-adv-x="614" d="M231 949L526 560V541L231 152H89L347 550L89 949H231Z" /> +</font> +</defs> +</svg> diff --git a/website/agenda/fonts/roboto-v18-latin_latin-ext-regular.ttf b/website/agenda/fonts/roboto-v18-latin_latin-ext-regular.ttf new file mode 100644 index 0000000..5c3b764 Binary files /dev/null and b/website/agenda/fonts/roboto-v18-latin_latin-ext-regular.ttf differ diff --git a/website/agenda/fonts/roboto-v18-latin_latin-ext-regular.woff b/website/agenda/fonts/roboto-v18-latin_latin-ext-regular.woff new file mode 100644 index 0000000..0f128f1 Binary files /dev/null and b/website/agenda/fonts/roboto-v18-latin_latin-ext-regular.woff differ diff --git a/website/agenda/fonts/roboto-v18-latin_latin-ext-regular.woff2 b/website/agenda/fonts/roboto-v18-latin_latin-ext-regular.woff2 new file mode 100644 index 0000000..ab076be Binary files /dev/null and b/website/agenda/fonts/roboto-v18-latin_latin-ext-regular.woff2 differ diff --git a/website/agenda/image/favicon.ico b/website/agenda/image/favicon.ico deleted file mode 100644 index e4af50b..0000000 Binary files a/website/agenda/image/favicon.ico and /dev/null differ diff --git a/website/agenda/images/.htaccess b/website/agenda/images/.htaccess new file mode 100644 index 0000000..754e331 --- /dev/null +++ b/website/agenda/images/.htaccess @@ -0,0 +1,2 @@ +Options -Indexes +FollowSymLinks +MultiViews -ExecCGI +Require all granted diff --git a/website/agenda/image/event.icon.png b/website/agenda/images/event.icon.png similarity index 100% rename from website/agenda/image/event.icon.png rename to website/agenda/images/event.icon.png diff --git a/website/agenda/images/expand_less.svg b/website/agenda/images/expand_less.svg new file mode 100644 index 0000000..73f41f6 --- /dev/null +++ b/website/agenda/images/expand_less.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M12 8l-6 6 1.41 1.41L12 10.83l4.59 4.58L18 14l-6-6z"/></svg> \ No newline at end of file diff --git a/website/agenda/images/expand_more.svg b/website/agenda/images/expand_more.svg new file mode 100644 index 0000000..b615405 --- /dev/null +++ b/website/agenda/images/expand_more.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M24 24H0V0h24v24z" fill="none" opacity=".87"/><path d="M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6-1.41-1.41z"/></svg> \ No newline at end of file diff --git a/website/agenda/image/feed.png b/website/agenda/images/feed.png similarity index 100% rename from website/agenda/image/feed.png rename to website/agenda/images/feed.png diff --git a/website/agenda/image/ical.png b/website/agenda/images/ical.png similarity index 100% rename from website/agenda/image/ical.png rename to website/agenda/images/ical.png diff --git a/website/agenda/image/icals.png b/website/agenda/images/icals.png similarity index 100% rename from website/agenda/image/icals.png rename to website/agenda/images/icals.png diff --git a/website/agenda/image/logo.jpg b/website/agenda/images/logo.jpg similarity index 100% rename from website/agenda/image/logo.jpg rename to website/agenda/images/logo.jpg diff --git a/website/agenda/images/more_vert.svg b/website/agenda/images/more_vert.svg new file mode 100644 index 0000000..2145ccd --- /dev/null +++ b/website/agenda/images/more_vert.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/></svg> \ No newline at end of file diff --git a/website/agenda/image/select.png b/website/agenda/images/select.png similarity index 100% rename from website/agenda/image/select.png rename to website/agenda/images/select.png diff --git a/website/agenda/js/.htaccess b/website/agenda/js/.htaccess index 30178ec..754e331 100644 --- a/website/agenda/js/.htaccess +++ b/website/agenda/js/.htaccess @@ -1,3 +1,2 @@ Options -Indexes +FollowSymLinks +MultiViews -ExecCGI Require all granted - diff --git a/website/agenda/js/calcms.cust.js b/website/agenda/js/calcms.cust.js index a81eec7..6c08817 100644 --- a/website/agenda/js/calcms.cust.js +++ b/website/agenda/js/calcms.cust.js @@ -2,406 +2,170 @@ var calcms_settings = new Array(); (function($, calcms) { - // show current project - calcms.selectProject = function selectProject() { - var project = calcms.getProject(); - console.log("project=" + project) + // show current project + calcms.selectProject = function selectProject() { + var project = calcms.getProject(); + console.log("project=" + project) - calcms.clearOnChangeArchive(); - calcms.showProjectCategories(project); - calcms.showProjectSeriesNames(project); - calcms.selectFirstOption('#calcms_series_name_' - + calcms.getJsName(project)); - calcms.selectFirstOption('#calcms_category_' - + calcms.getJsName(project)); - } + calcms.clearOnChangeArchive(); + calcms.showProjectSeriesNames(project); + calcms.selectFirstOption('#calcms_series_name_' + + calcms.getJsName(project)); + } - // search events - calcms.selectSearchEventListener = function selectSearchEventListener() { - var project = calcms.getProject(); + // search events + calcms.selectSearchEventListener = function selectSearchEventListener() { + var project = calcms.getProject(); - calcms.showSearchResultsByProject(project, calcms.getSearchElement() - .val(), calcms.isArchive()); - calcms.selectFirstOption('#calcms_series_name_' - + calcms.getJsName(project)); - calcms.selectFirstOption('#calcms_category_' - + calcms.getJsName(project)); + calcms.showSearchResultsByProject(project, calcms.getSearchElement() + .val(), calcms.isArchive()); + calcms.selectFirstOption('#calcms_series_name_' + + calcms.getJsName(project)); - calcms.registerOnChangeArchive(function() { - calcms.showSearchResultsByProject(project, calcms - .getSearchElement().val(), calcms.isArchive()); - }); - } + calcms.registerOnChangeArchive(function() { + calcms.showSearchResultsByProject(project, calcms + .getSearchElement().val(), calcms.isArchive()); + }); + } - // show events for selected category of project - calcms.selectCategory = function selectCategory(project, category) { - calcms.showEventsByProjectAndCategory(project, category, calcms - .isArchive()); - calcms.selectFirstOption('#calcms_series_name_' - + calcms.getJsName(project)); - calcms.resetSearch(); + // show events for selected series of project + calcms.selectSeries = function selectSeries(project, seriesName) { + calcms.showEventsByProjectAndSeriesName(project, seriesName, calcms + .isArchive()); + calcms.resetSearch(); - calcms.registerOnChangeArchive(function() { - calcms.showEventsByProjectAndCategory(project, category, calcms - .isArchive()); - }); - } + calcms.registerOnChangeArchive(function() { + calcms.showEventsByProjectAndSeriesName(project, seriesName, calcms + .isArchive()); + }); + } - // show events for selected series of project - calcms.selectSeries = function selectSeries(project, seriesName) { - calcms.showEventsByProjectAndSeriesName(project, seriesName, calcms - .isArchive()); - calcms.selectFirstOption('#calcms_category_' - + calcms.getJsName(project)); - calcms.resetSearch(); + // calendar events + calcms.selectMonthEventListener = function selectMonthEventListener(month) { + calcms.showCalendarAndEventsByMonth(month); + } - calcms.registerOnChangeArchive(function() { - calcms.showEventsByProjectAndSeriesName(project, seriesName, calcms - .isArchive()); - }); - } + calcms.selectWeekdayEventListener = function selectWeekdayEventListener( + start_date, end_date, weekday) { + calcms.showEventsByWeekday(start_date, end_date, weekday); + } - // calendar events - calcms.selectMonthEventListener = function selectMonthEventListener(month) { - calcms.showCalendarAndEventsByMonth(month); - } + calcms.selectDateRangeEventListener = function selectDateRangeEventListener( + from, till) { + calcms.showEventsByDateRange(from, till); + } - calcms.selectWeekdayEventListener = function selectWeekdayEventListener( - start_date, end_date, weekday) { - calcms.showEventsByWeekday(start_date, end_date, weekday); - } + calcms.selectDateEventListener = function selectDateEventListener(date) { + calcms.showEventsByDate(date); + } - calcms.selectDateRangeEventListener = function selectDateRangeEventListener( - from, till) { - calcms.showEventsByDateRange(from, till); - } + // initial initialize + function initCalcms() { + calcms.set('base_url', ''); - calcms.selectDateEventListener = function selectDateEventListener(date) { - calcms.showEventsByDate(date); - } + calcms.set('calendar_url', '/agenda/kalender'); + calcms.set('menu_url', '/agenda/menu'); - // initial initialize - function initCalcms() { - calcms.set('base_url', ''); + calcms.set('events_url', '/agenda/sendungen'); + calcms.set('list_url', '/agenda/sendung'); + calcms.set('next_series_url', '/programm/sendung/serie_plus'); + calcms.set('prev_series_url', '/programm/sendung/serie_minus'); - calcms.set('calendar_url', '/agenda/kalender'); - calcms.set('menu_url', '/agenda/menu'); + calcms.set('ical_url', '/agenda/ical'); + calcms.set('feed_url', '/agenda/feed/'); + calcms.set('playlist_url', '/agenda/playlist/'); - calcms.set('events_url', '/agenda/sendungen'); - calcms.set('list_url', '/agenda/sendung'); - calcms.set('next_series_url', '/programm/sendung/serie_plus'); - calcms.set('prev_series_url', '/programm/sendung/serie_minus'); + calcms.set('search_url', '/agenda/suche/'); + calcms.set('search_series_name_url', '/agenda/sendereihe/'); - calcms.set('ical_url', '/agenda/ical'); - calcms.set('feed_url', '/agenda/feed/'); - calcms.set('playlist_url', '/agenda/playlist/'); + calcms.set('series_name_url', '/agenda/sendereihen/'); - calcms.set('search_url', '/agenda/suche/'); - calcms.set('search_category_url', '/agenda/kategorie/'); - calcms.set('search_series_name_url', '/agenda/sendereihe/'); + calcms.set('comments_url', '/agenda/kommentare/'); + calcms.set('add_comment_url', '/agenda/kommentar_neu/'); + calcms.set('newest_comments_url', '/agenda/neueste_kommentare/'); + return true; + } - calcms.set('category_url', '/agenda/kategorien/'); - calcms.set('series_name_url', '/agenda/sendereihen/'); + var loadedSearchComponents = 0; + // load projects, series and show search fields + // remove empty projects if series have been loaded + calcms.showAdvancedSearch = function showAdvancedSearch(id) { + searchReady = 0; + var element = $('#calcms_enhanced_search'); + if (element.length == 0) return; - calcms.set('comments_url', '/agenda/kommentare/'); - calcms.set('add_comment_url', '/agenda/kommentar_neu/'); - calcms.set('newest_comments_url', '/agenda/neueste_kommentare/'); + if (element.css('display') == 'none') { + url = calcms.get('series_name_url'); + calcms.updateContainer('calcms_series_names', url, function() { + calcms.selectProject(); + loadedSearchComponents++; + if (loadedSearchComponents == 2) { + calcms.removeEmptyProjects(); + } + }); + } else { + calcms.showProjectSeriesNames(calcms.getProject()); + } + calcms.toggle(document.querySelector('#' + id)); + } - return true; - } + calcms.insertDeskNextShows = function insertDeskNextShows(desk) { + var url = '/agenda/suche/all/' + desk + '/kommende/'; + calcms.updateContainer('showDesk', url); + return false; + } - var loadedSearchComponents = 0; - // load projects, series and categories and show search fields - // remove empty projects if both series and categories have been loaded - calcms.showAdvancedSearch = function showAdvancedSearch(id) { - searchReady = 0; - var element = $('#calcms_enhanced_search'); - if (element.length == 0) - return; + calcms.insertDeskPrevShows = function insertDeskPrevShows(desk) { + var url = '/agenda/suche/all/' + desk + '/vergangene/'; + calcms.updateContainer('showDesk', url); + return false; + } - if (element.css('display') == 'none') { - var url = calcms.get('category_url'); - calcms.updateContainer('calcms_categories', url, 1, function() { - calcms.selectProject(); - loadedSearchComponents++; - if (loadedSearchComponents == 2) { - calcms.removeEmptyProjects(); - } - }); + calcms.insertEditors = function insertEditors() { + var url = document.location.href; - url = calcms.get('series_name_url'); - calcms.updateContainer('calcms_series_names', url, 1, function() { - calcms.selectProject(); - loadedSearchComponents++; - if (loadedSearchComponents == 2) { - calcms.removeEmptyProjects(); - } - }); - } else { - calcms.showProjectCategories(calcms.getProject()); - calcms.showProjectSeriesNames(calcms.getProject()); - } + var mapping = { + "studio\-ansage" : "/agenda/redaktionen-studio-ansage", + "studio\-pi\-radio" : "/agenda/redaktionen-piradio", + "studio\-frb" : "/agenda/redaktionen-frb", + "studio\-colabo" : "/agenda/redaktionen-colabo-radio", + "studio\-frrapo" : "/agenda/redaktionen-frrapo" + }; - $("#" + id).slideToggle(); - } + for ( var key in mapping) { + var editorsUrl = mapping[key]; + var pattern = new RegExp(key); + var matchs = pattern.exec(url); + if ((matchs != null) && (matchs.length > 0)) { + console.log("matchs " + url) + $('div.entry-content').append('<div id="result"> </div>') + calcms.updateContainer("#result", editorsUrl); + } + } + } - calcms.insertDeskNextShows = function insertDeskNextShows(desk) { - var url = '/agenda/suche/all/' + desk + '/kommende/'; - calcms.updateContainer('showDesk', url, 1); - return false; - } + function initSearch() { + var base = $('#calcms_search_show_details'); + var elem = $('#calcms_search_show_details #plus'); + if (elem.length == 0) { + base.append('<span id="plus"> ▼ </span>'); + base.prepend('<span id="plus"></span>'); + } + } - calcms.insertDeskPrevShows = function insertDeskPrevShows(desk) { - var url = '/agenda/suche/all/' + desk + '/vergangene/'; - calcms.updateContainer('showDesk', url, 1); - return false; - } - - /* - function insertDeskDetails() { - var pattern = new RegExp(/redaktion\/(.*)$/); - var matchs = pattern.exec(document.location.href); - if ((matchs != null) && (matchs.length > 0) && (matchs[1] != '')) { - var desk = $('#center h2:first').text(); - desk = desk.replace('Redaktion: ', ''); - desk = escape(desk); - $('#center .content').append( - '<div>' + '<a onclick="insertDeskPrevShows(\'' + desk - + '\');return false;" href="#">«letzte«</a>' - + ' Sendungen ' - + '<a onclick="insertDeskNextShows(\'' + desk - + '\');return false;" href="#">»nächste»</a>' - + '<div id="showDesk" />' + '</div>'); - } - } - */ - - /* - function fixBlogEntries() { - if (document.location.href.match('/redaktionen/') - || document.location.href.match('/redaktionen?') - || document.location.href.match('/redaktionen$')) { - $('img.image-thumbnail').css('width', '3em'); - $('img.image-thumbnail').css('height', '3em'); - $('div.image-attach-teaser').css('width', '3em'); - $('div.node').css('padding', '0'); - $('div.node').css('margin', '0'); - $('#center .submitted').remove(); - $('#center .clear-block h2 a') - .each( - function(index) { - $(this) - .html( - $(this) - .text() - .replace('Redaktion: ', - '<font color="gray">Redaktion:</font> ')); - if ($(this).text().match(/Information:/)) - $(this).remove(); - }) - - } - } - */ - - /* - function setImageSize() { - var image = '#calcms_list div.content img'; - var size = $(window).width(); - size = Math.floor(size * 0.16); - $(image).css('width', size + 'px'); - $(image).css('height', size + 'px'); - if (size > 200) { - $(image).each(function(index) { - var url = $(this).attr('src'); - if (url != null) { - url = url.replace('/thumbs/', '/images/'); - console.log(url); - $(this).attr('src', url); - } - }); - } else { - $(image).each(function(index) { - var url = $(this).attr('src'); - if (url != null) { - url = url.replace('/images/', '/thumbs/'); - $(this).attr('src', url); - } - }); - } - } - */ - - function setThumbs() { - $('#calcms_playlist img').each(function(index) { - var url = $(this).attr('src'); - if (url != null) { - url = url.replace('/images/', '/thumbs/'); - $(this).attr('src', url); - } - }); - } - - /* - function addCommentsOnAgendaPages() { - if (calcms.contains(window.location.href, '/programm/') - || calcms.contains(window.location.href, '/agenda/')) { - $('#sidebar-right') - .append( - '<div id="block-block-2" class="clear-block block block-block"><h2>Kommentare</h2><div class="content">' - + '<div id="calcms_newest_comments">Bitte warten…</div>' - + '</div></div>'); - } - } - */ - - function scrollNextEvent() { - if ($('#calcms_running_event').length == 0) - return; - $('#playlist_container').scrollLeft(0); - setInterval(nextSlideEvent, 10000); - } - - var numberOfComingShows = 100; - var slideCount = 0; - var slideOffset = 1; - var slideEvents = 1; - - // slideEvents will be updated at onmouseenter/leave handler at - // playlist_long - function nextSlideEvent() { - if (slideEvents == 0) - return; - if ($('#coming_shows a').length == 0) - return; - if (slideCount == 0) { - numberOfComingShows = $('#coming_shows a').length; - $('#playlist_container').scrollLeft(0) - $('#playlist_container').css('overflow', 'auto'); - $('#playlist_container').css('-webkit-overflow-scrolling', 'touch'); - $('#playlist_container').css('height', '150'); - $('#coming_shows').css('white-space', 'nowrap'); - $('#coming_shows').css('overflow-x', 'hidden'); - $('#coming_shows').css('height', '150'); - } - - // console.log(slideCount+" "+slideOffset) - $('#playlist_container').animate({ - scrollLeft : slideCount * 115 + "px" - }, 5000); - - if (slideCount < 0) - slideOffset = 1 - if (slideCount > numberOfComingShows + 1 - $('#coming_shows').width() - / 100) - slideOffset = -1 - slideCount += slideOffset; - } - - function mobilise() { - if (!navigator.userAgent.match(/Mobi/)) - return; - - $('#wrapper #container #sidebar-left').before( - $('#wrapper #container #center')); - $('#wrapper #container #sidebar-left').before( - $('#wrapper #container #sidebar-right')); - - $('body.sidebars').css('min-width', '100%'); - $('body.sidebar-left').css('min-width', '100%'); - $('body.sidebar-right').css('min-width', '100%'); - - $('#wrapper #container .sidebar').css('width', '100%'); - $('#wrapper #container').css('width', '100%'); - $('#wrapper #container').css('max-width', '100%'); - $('#wrapper #container').css('margin', '0'); - $('#wrapper #container').css('padding', '0'); - - $('#center').css('margin', '0'); - $('#center #squeeze').css('margin', '0'); - $('#center *').css('margin-left', '0'); - $('#center *').css('margin-right', '0'); - $('#center .right-corner').css('position', 'static'); - $('#center .right-corner').css('left', '0'); - $('#center .right-corner').css('padding-left', '0'); - $('#center .right-corner').css('padding-right', '0'); - $('#center .right-corner').css('background-image', 'url()'); - $('#center .left-corner').css('position', 'static'); - $('#center .left-corner').css('padding-left', '0'); - $('#center .left-corner').css('padding-right', '0'); - $('#center .left-corner').css('background-image', 'url()'); - $('#center *').css('background-image', 'url()'); - - $('#wrapper #container #header').css('height', '100px'); - - var padding = '0.5em' - $('#center .left-corner').css('padding-left', padding); - $('#center .left-corner').css('padding-right', padding); - $('#wrapper #container #sidebar-left').css('padding-left', padding); - $('#wrapper #container #sidebar-left').css('padding-right', padding); - - // $('*').css('background','none'); - // $('#sidebar-left div.content').css('text-align','center'); - // $('#sidebar-left *').css('margin-left','0'); - // $('#sidebar-left *').css('margin-right','0'); - // $('#sidebar-right *').css('margin-left','0'); - // $('#sidebar-right *').css('margin-right','0'); - // $('#sidebar-left').css('width','90%'); - $('.node').css('padding-left', '0'); - $('.node').css('padding-right', '0'); - - $('#calcms_search input').css("padding", "1em"); - $('#calcms_search select').css("padding", "1em"); - - var menu = "ul.links.primary-links"; - $(menu).addClass('mobileMenu'); - $(menu).before('<div id="mobileMenuButton"></div>'); - $(menu).hide(); - - var menu2 = "ul.links.secondary-links"; - $(menu2).each(function() { - $(menu).append($(this).html()); - }) - $(menu2).remove(); - - $('#calcms_calendar table').css('width', '90%'); - - // move footer down - var footer = $('#wrapper #footer').html(); - $('body').append(footer); - $('#wrapper #footer').remove(); - - $("#mobileMenuButton").click(function() { - $(menu).slideToggle(); - return false; - }); - } - - function initSearch() { - var base = $('#calcms_search_show_details'); - var elem = $('#calcms_search_show_details #plus'); - if (elem.length == 0) { - base.append('<span id="plus"> ▼ </span>'); - base.prepend('<span id="plus"></span>'); - - } - } - - var isCalcms=false; - function initWordpress(){ - $('header.entry-header').each( function(){ - var elem=$(this); - $(this).find("h1").each( function(){ - if ( $(this).text() == "calcms" ){ - isCalcms=true; + var isCalcms = false; + function initWordpress() { + $('header.entry-header').each(function() { + $(this).find("h1").each(function() { + if ($(this).text() == "Programm") { + isCalcms = true; $(this).text("Programm"); } }); }); - $('div.site-info').remove(); - - if (isCalcms==false){ + + if (isCalcms == false) { $('#calcms_calendar').parent().parent().remove(); $('#calcms_menu').parent().parent().remove(); $('#calcms_search').parent().parent().remove(); @@ -410,27 +174,106 @@ var calcms_settings = new Array(); } } - function initAll() { - initCalcms(); - //initWordpress(); - //addCommentsOnAgendaPages(); - //calcms.showPlaylist(); - calcms.showNewestComments(); - // insertDeskDetails(); - // fixBlogEntries(); - calcms.removeCurrentPlayingHeader(); - // setImageSize(); - // setThumbs(); - scrollNextEvent(); - // initSlider(); - // mobilise(); - initSearch(); - console.log("calcms inited") - } + function formatDate(date) { + var d = new Date(date), + month = '' + (d.getMonth() + 1), + day = '' + d.getDate(), + year = d.getFullYear(); + if (month.length < 2) month = '0' + month; + if (day.length < 2) day = '0' + day; + return [year, month, day].join('-'); + } - $(document).ready(function() { - initAll(); - }); + function scrollTo(elem, offset, duration){ + if (elem==null) return; + if (offset==null) offset=0; + if (duration==null) duration=500; + try { $([document.documentElement, document.body]).scrollTop( elem.offset().top+offset ) } catch(e){}; + } + + function addPrevEvent(id){ + $('a.load-prev').remove(); + $('div.event-base').first().prepend('<a class="load-prev">davor</a>'); + $('a.load-prev').on( "click", function(){ + var url = "/programm/sendung/"+id+'.html'; + window.location.href=url; + }) + } + + function addPrevSection(till){ + $('a.load-prev').remove(); + $('div.events-base').first().prepend('<a class="load-prev">davor…</a>'); + $('a.load-prev').on( "click", function(){ + till.setDate(till.getDate()) + var from = new Date(till.getTime()); + from.setDate(from.getDate()-7); + var url = "/programm/events/"+formatDate(from)+'_'+formatDate(till)+'.html'; + fetch( url ) + .then( response => response.text()) + .then( text => { + var offset = $('a.load-prev').offset().top + $('div.events-base').first().before(text); + $('div.events-base').first().css("display","none").fadeIn("1s"); + scrollTo( $('a.load-prev'), -offset, 0 ); + addPrevSection(from); + }) + }); + } + + function addNextEvent(id){ + $('a.load-next').remove(); + $('div.event-base').last().append('<a class="load-next">danach</a>'); + $('a.load-next').on( "click", function(){ + var url = "/programm/sendung/"+id+'.html'; + window.location.href=url; + }); + } + + function addNextSection(from){ + $('a.load-next').remove(); + $('div.events-base').last().append('<a class="load-next">danach…</a>'); + $('a.load-next').on( "click", function(){ + from.setDate(from.getDate()+1) + var till = new Date(from.getTime()); + till.setDate(till.getDate()+7); + var url = "/programm/events/"+formatDate(from)+'_'+formatDate(till)+'.html'; + fetch( url ) + .then( response => response.text()) + .then( text => { + $('div.events-base').last().after(text); + $('div.events-base').last().css("display","none").fadeIn("1s"); + addNextSection(till); + }) + }); + } + + function initEventScroll(){ + var values = window.location.href.match(/programm/); + if (!values) return; + + var first_date = $('div.events-base').data('first-date'); + if (first_date) addPrevSection(new Date( first_date.split("-") ) ); + + var last_date = $('div.events-base').data('last-date'); + if (last_date) addNextSection(new Date( last_date.split("-") ) ); + + var prev = $('div.event-base').data('prev-event'); + if (prev) addPrevEvent(prev); + + var next = $('div.event-base').data('next-event'); + if (next) addNextEvent(next); + } + + $(document).ready(function() { + if (window.location.href.match(/\/programm\//)) scrollTo( $("h1"), -16,0 ); + initCalcms(); + initWordpress(); + calcms.showPlaylist(); + calcms.showNewestComments(); + calcms.insertEditors(); + initSearch(); + initEventScroll(); + console.log("calcms inited") + }); }(jQuery, calcms)); - diff --git a/website/agenda/js/calcms.jquery.min.js b/website/agenda/js/calcms.jquery.min.js deleted file mode 100644 index 5fd1339..0000000 --- a/website/agenda/js/calcms.jquery.min.js +++ /dev/null @@ -1,6 +0,0 @@ -/*! jQuery v1.12.4 | (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="1.12.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 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!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(n.isPlainObject(c)||(b=n.isArray(c)))?(b?(b=!1,f=a&&n.isArray(a)?a:[]):f=a&&n.isPlainObject(a)?a:{},g[d]=n.extend(j,f,c)):void 0!==c&&(g[d]=c));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||function(a){return"array"===n.type(a)},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},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;try{if(a.constructor&&!k.call(a,"constructor")&&!k.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(!l.ownFirst)for(b in a)return k.call(a,b);for(b in a);return void 0===b||k.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?i[j.call(a)]||"object":typeof a},globalEval:function(b){b&&n.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},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){var d;if(b){if(h)return h.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[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&&(f=a[b],b=a,a=f),n.isFunction(a)?(c=e.call(arguments,2),d=function(){return a.apply(b||this,c.concat(e.call(arguments)))},d.guid=a.guid=a.guid||n.guid++,d):void 0},now:function(){return+new Date},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 n.inArray(a,b)>-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=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;e>b;b++)if(n.contains(d[b],this))return!0}));for(b=0;e>b;b++)n.find(a,d[b],c);return c=this.pushStack(e>1?n.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},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.charAt(0)&&">"===a.charAt(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}if(f=d.getElementById(e[2]),f&&f.parentNode){if(f.id!==e[2])return A.find(a);this.length=1,this[0]=f}return this.context=d,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof 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,c=n(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(n.contains(this,c[b]))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?n.inArray(this[0],n(a)):n.inArray(a.jquery?a[0]:a,this):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){do a=a[b];while(a&&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 n.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document: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]||(e=n.uniqueSort(e)),D.test(a)&&(e=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=!0,c||j.disable(),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.addEventListener?(d.removeEventListener("DOMContentLoaded",K),a.removeEventListener("load",K)):(d.detachEvent("onreadystatechange",K),a.detachEvent("onload",K))}function K(){(d.addEventListener||"load"===a.event.type||"complete"===d.readyState)&&(J(),n.ready())}n.ready.promise=function(b){if(!I)if(I=n.Deferred(),"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll)a.setTimeout(n.ready);else if(d.addEventListener)d.addEventListener("DOMContentLoaded",K),a.addEventListener("load",K);else{d.attachEvent("onreadystatechange",K),a.attachEvent("onload",K);var c=!1;try{c=null==a.frameElement&&d.documentElement}catch(e){}c&&c.doScroll&&!function f(){if(!n.isReady){try{c.doScroll("left")}catch(b){return a.setTimeout(f,50)}J(),n.ready()}}()}return I.promise(b)},n.ready.promise();var L;for(L in n(l))break;l.ownFirst="0"===L,l.inlineBlockNeedsLayout=!1,n(function(){var a,b,c,e;c=d.getElementsByTagName("body")[0],c&&c.style&&(b=d.createElement("div"),e=d.createElement("div"),e.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(e).appendChild(b),"undefined"!=typeof b.style.zoom&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",l.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(e))}),function(){var a=d.createElement("div");l.deleteExpando=!0;try{delete a.test}catch(b){l.deleteExpando=!1}a=null}();var M=function(a){var b=n.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b},N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(O,"-$1").toLowerCase();if(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){}n.data(a,b,c)}else c=void 0; -}return c}function Q(a){var b;for(b in a)if(("data"!==b||!n.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function R(a,b,d,e){if(M(a)){var f,g,h=n.expando,i=a.nodeType,j=i?n.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||n.guid++:h),j[k]||(j[k]=i?{}:{toJSON:n.noop}),"object"!=typeof b&&"function"!=typeof b||(e?j[k]=n.extend(j[k],b):j[k].data=n.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[n.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[n.camelCase(b)])):f=g,f}}function S(a,b,c){if(M(a)){var d,e,f=a.nodeType,g=f?n.cache:a,h=f?a[n.expando]:n.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){n.isArray(b)?b=b.concat(n.map(b,n.camelCase)):b in d?b=[b]:(b=n.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!Q(d):!n.isEmptyObject(d))return}(c||(delete g[h].data,Q(g[h])))&&(f?n.cleanData([a],!0):l.deleteExpando||g!=g.window?delete g[h]:g[h]=void 0)}}}n.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?n.cache[a[n.expando]]:a[n.expando],!!a&&!Q(a)},data:function(a,b,c){return R(a,b,c)},removeData:function(a,b){return S(a,b)},_data:function(a,b,c){return R(a,b,c,!0)},_removeData:function(a,b){return S(a,b,!0)}}),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=n.data(f),1===f.nodeType&&!n._data(f,"parsedAttrs"))){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])));n._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){n.data(this,a)}):arguments.length>1?this.each(function(){n.data(this,a,b)}):f?P(f,a,n.data(f,a)):void 0},removeData:function(a){return this.each(function(){n.removeData(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=n._data(a,b),c&&(!d||n.isArray(c)?d=n._data(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._data(a,c)||n._data(a,c,{empty:n.Callbacks("once memory").add(function(){n._removeData(a,b+"queue"),n._removeData(a,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._data(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}}),function(){var a;l.shrinkWrapBlocks=function(){if(null!=a)return a;a=!1;var b,c,e;return c=d.getElementsByTagName("body")[0],c&&c.style?(b=d.createElement("div"),e=d.createElement("div"),e.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(e).appendChild(b),"undefined"!=typeof b.style.zoom&&(b.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:1px;width:1px;zoom:1",b.appendChild(d.createElement("div")).style.width="5px",a=3!==b.offsetWidth),c.removeChild(e),a):void 0}}();var T=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,U=new RegExp("^(?:([+-])=|)("+T+")([a-z%]*)$","i"),V=["Top","Right","Bottom","Left"],W=function(a,b){return a=b||a,"none"===n.css(a,"display")||!n.contains(a.ownerDocument,a)};function X(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)&&U.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 Y=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)Y(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},Z=/^(?:checkbox|radio)$/i,$=/<([\w:-]+)/,_=/^$|\/(?:java|ecma)script/i,aa=/^\s+/,ba="abbr|article|aside|audio|bdi|canvas|data|datalist|details|dialog|figcaption|figure|footer|header|hgroup|main|mark|meter|nav|output|picture|progress|section|summary|template|time|video";function ca(a){var b=ba.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}!function(){var a=d.createElement("div"),b=d.createDocumentFragment(),c=d.createElement("input");a.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",l.leadingWhitespace=3===a.firstChild.nodeType,l.tbody=!a.getElementsByTagName("tbody").length,l.htmlSerialize=!!a.getElementsByTagName("link").length,l.html5Clone="<:nav></:nav>"!==d.createElement("nav").cloneNode(!0).outerHTML,c.type="checkbox",c.checked=!0,b.appendChild(c),l.appendChecked=c.checked,a.innerHTML="<textarea>x</textarea>",l.noCloneChecked=!!a.cloneNode(!0).lastChild.defaultValue,b.appendChild(a),c=d.createElement("input"),c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),a.appendChild(c),l.checkClone=a.cloneNode(!0).cloneNode(!0).lastChild.checked,l.noCloneEvent=!!a.addEventListener,a[n.expando]=1,l.attributes=!a.getAttribute(n.expando)}();var da={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:l.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]};da.optgroup=da.option,da.tbody=da.tfoot=da.colgroup=da.caption=da.thead,da.th=da.td;function ea(a,b){var c,d,e=0,f="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||n.nodeName(d,b)?f.push(d):n.merge(f,ea(d,b));return void 0===b||b&&n.nodeName(a,b)?n.merge([a],f):f}function fa(a,b){for(var c,d=0;null!=(c=a[d]);d++)n._data(c,"globalEval",!b||n._data(b[d],"globalEval"))}var ga=/<|&#?\w+;/,ha=/<tbody/i;function ia(a){Z.test(a.type)&&(a.defaultChecked=a.checked)}function ja(a,b,c,d,e){for(var f,g,h,i,j,k,m,o=a.length,p=ca(b),q=[],r=0;o>r;r++)if(g=a[r],g||0===g)if("object"===n.type(g))n.merge(q,g.nodeType?[g]:g);else if(ga.test(g)){i=i||p.appendChild(b.createElement("div")),j=($.exec(g)||["",""])[1].toLowerCase(),m=da[j]||da._default,i.innerHTML=m[1]+n.htmlPrefilter(g)+m[2],f=m[0];while(f--)i=i.lastChild;if(!l.leadingWhitespace&&aa.test(g)&&q.push(b.createTextNode(aa.exec(g)[0])),!l.tbody){g="table"!==j||ha.test(g)?"<table>"!==m[1]||ha.test(g)?0:i:i.firstChild,f=g&&g.childNodes.length;while(f--)n.nodeName(k=g.childNodes[f],"tbody")&&!k.childNodes.length&&g.removeChild(k)}n.merge(q,i.childNodes),i.textContent="";while(i.firstChild)i.removeChild(i.firstChild);i=p.lastChild}else q.push(b.createTextNode(g));i&&p.removeChild(i),l.appendChecked||n.grep(ea(q,"input"),ia),r=0;while(g=q[r++])if(d&&n.inArray(g,d)>-1)e&&e.push(g);else if(h=n.contains(g.ownerDocument,g),i=ea(p.appendChild(g),"script"),h&&fa(i),c){f=0;while(g=i[f++])_.test(g.type||"")&&c.push(g)}return i=null,p}!function(){var b,c,e=d.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(l[b]=c in a)||(e.setAttribute(c,"t"),l[b]=e.attributes[c].expando===!1);e=null}();var ka=/^(?:input|select|textarea)$/i,la=/^key/,ma=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,na=/^(?:focusinfocus|focusoutblur)$/,oa=/^([^.]*)(?:\.(.+)|)/;function pa(){return!0}function qa(){return!1}function ra(){try{return d.activeElement}catch(a){}}function sa(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)sa(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=qa;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._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=n.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return"undefined"==typeof n||a&&n.event.triggered===a.type?void 0:n.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(G)||[""],h=b.length;while(h--)f=oa.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=n.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=n.event.special[o]||{},l=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(".")},i),(m=g[o])||(m=g[o]=[],m.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,l):m.push(l),n.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n.hasData(a)&&n._data(a);if(r&&(k=r.events)){b=(b||"").match(G)||[""],j=b.length;while(j--)if(h=oa.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=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=m.length;while(f--)g=m[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(m.splice(f,1),g.selector&&m.delegateCount--,l.remove&&l.remove.call(a,g));i&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(k)&&(delete r.handle,n._removeData(a,"events"))}},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(i=m=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!na.test(q+n.event.triggered)&&(q.indexOf(".")>-1&&(r=q.split("."),q=r.shift(),r.sort()),h=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]),l=n.event.special[q]||{},f||!l.trigger||l.trigger.apply(e,c)!==!1)){if(!f&&!l.noBubble&&!n.isWindow(e)){for(j=l.delegateType||q,na.test(j+q)||(i=i.parentNode);i;i=i.parentNode)p.push(i),m=i;m===(e.ownerDocument||d)&&p.push(m.defaultView||m.parentWindow||a)}o=0;while((i=p[o++])&&!b.isPropagationStopped())b.type=o>1?j:l.bindType||q,g=(n._data(i,"events")||{})[b.type]&&n._data(i,"handle"),g&&g.apply(i,c),g=h&&i[h],g&&g.apply&&M(i)&&(b.result=g.apply(i,c),b.result===!1&&b.preventDefault());if(b.type=q,!f&&!b.isDefaultPrevented()&&(!l._default||l._default.apply(p.pop(),c)===!1)&&M(e)&&h&&e[q]&&!n.isWindow(e)){m=e[h],m&&(e[h]=null),n.event.triggered=q;try{e[q]()}catch(s){}n.event.triggered=void 0,m&&(e[h]=m)}return b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,d,f,g,h=[],i=e.call(arguments),j=(n._data(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},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=ma.test(f)?this.mouseHooks:la.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=g.srcElement||d),3===a.target.nodeType&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,h.filter?h.filter(a,g):a},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 fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,e,f,g=b.button,h=b.fromElement;return null==a.pageX&&null!=b.clientX&&(e=a.target.ownerDocument||d,f=e.documentElement,c=e.body,a.pageX=b.clientX+(f&&f.scrollLeft||c&&c.scrollLeft||0)-(f&&f.clientLeft||c&&c.clientLeft||0),a.pageY=b.clientY+(f&&f.scrollTop||c&&c.scrollTop||0)-(f&&f.clientTop||c&&c.clientTop||0)),!a.relatedTarget&&h&&(a.relatedTarget=h===a.target?b.toElement:h),a.which||void 0===g||(a.which=1&g?1:2&g?3:4&g?2:0),a}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==ra()&&this.focus)try{return this.focus(),!1}catch(a){}},delegateType:"focusin"},blur:{trigger:function(){return this===ra()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return n.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(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){var d=n.extend(new n.Event,c,{type:a,isSimulated:!0});n.event.trigger(d,null,b),d.isDefaultPrevented()&&c.preventDefault()}},n.removeEvent=d.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c)}:function(a,b,c){var d="on"+b;a.detachEvent&&("undefined"==typeof a[d]&&(a[d]=null),a.detachEvent(d,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?pa:qa):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:qa,isPropagationStopped:qa,isImmediatePropagationStopped:qa,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=pa,a&&(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=pa,a&&!this.isSimulated&&(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=pa,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}}}),l.submit||(n.event.special.submit={setup:function(){return n.nodeName(this,"form")?!1:void n.event.add(this,"click._submit keypress._submit",function(a){var b=a.target,c=n.nodeName(b,"input")||n.nodeName(b,"button")?n.prop(b,"form"):void 0;c&&!n._data(c,"submit")&&(n.event.add(c,"submit._submit",function(a){a._submitBubble=!0}),n._data(c,"submit",!0))})},postDispatch:function(a){a._submitBubble&&(delete a._submitBubble,this.parentNode&&!a.isTrigger&&n.event.simulate("submit",this.parentNode,a))},teardown:function(){return n.nodeName(this,"form")?!1:void n.event.remove(this,"._submit")}}),l.change||(n.event.special.change={setup:function(){return ka.test(this.nodeName)?("checkbox"!==this.type&&"radio"!==this.type||(n.event.add(this,"propertychange._change",function(a){"checked"===a.originalEvent.propertyName&&(this._justChanged=!0)}),n.event.add(this,"click._change",function(a){this._justChanged&&!a.isTrigger&&(this._justChanged=!1),n.event.simulate("change",this,a)})),!1):void n.event.add(this,"beforeactivate._change",function(a){var b=a.target;ka.test(b.nodeName)&&!n._data(b,"change")&&(n.event.add(b,"change._change",function(a){!this.parentNode||a.isSimulated||a.isTrigger||n.event.simulate("change",this.parentNode,a)}),n._data(b,"change",!0))})},handle:function(a){var b=a.target;return this!==b||a.isSimulated||a.isTrigger||"radio"!==b.type&&"checkbox"!==b.type?a.handleObj.handler.apply(this,arguments):void 0},teardown:function(){return n.event.remove(this,"._change"),!ka.test(this.nodeName)}}),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._data(d,b);e||d.addEventListener(a,c,!0),n._data(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=n._data(d,b)-1;e?n._data(d,b,e):(d.removeEventListener(a,c,!0),n._removeData(d,b))}}}),n.fn.extend({on:function(a,b,c,d){return sa(this,a,b,c,d)},one:function(a,b,c,d){return sa(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=qa),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 ta=/ jQuery\d+="(?:null|\d+)"/g,ua=new RegExp("<(?:"+ba+")[\\s/>]","i"),va=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,wa=/<script|<style|<link/i,xa=/checked\s*(?:[^=]|=\s*.checked.)/i,ya=/^true\/(.*)/,za=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,Aa=ca(d),Ba=Aa.appendChild(d.createElement("div"));function Ca(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 Da(a){return a.type=(null!==n.find.attr(a,"type"))+"/"+a.type,a}function Ea(a){var b=ya.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Fa(a,b){if(1===b.nodeType&&n.hasData(a)){var c,d,e,f=n._data(a),g=n._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)n.event.add(b,c,h[c][d])}g.data&&(g.data=n.extend({},g.data))}}function Ga(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!l.noCloneEvent&&b[n.expando]){e=n._data(b);for(d in e.events)n.removeEvent(b,d,e.handle);b.removeAttribute(n.expando)}"script"===c&&b.text!==a.text?(Da(b).text=a.text,Ea(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),l.html5Clone&&a.innerHTML&&!n.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&Z.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:"input"!==c&&"textarea"!==c||(b.defaultValue=a.defaultValue)}}function Ha(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&&xa.test(q))return a.each(function(e){var f=a.eq(e);r&&(b[0]=q.call(this,e,f.html())),Ha(f,b,c,d)});if(o&&(k=ja(b,a[0].ownerDocument,!1,a,d),e=k.firstChild,1===k.childNodes.length&&(k=e),e||d)){for(i=n.map(ea(k,"script"),Da),h=i.length;o>m;m++)g=k,m!==p&&(g=n.clone(g,!0,!0),h&&n.merge(i,ea(g,"script"))),c.call(a[m],g,m);if(h)for(j=i[i.length-1].ownerDocument,n.map(i,Ea),m=0;h>m;m++)g=i[m],_.test(g.type||"")&&!n._data(g,"globalEval")&&n.contains(j,g)&&(g.src?n._evalUrl&&n._evalUrl(g.src):n.globalEval((g.text||g.textContent||g.innerHTML||"").replace(za,"")));k=e=null}return a}function Ia(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(ea(d)),d.parentNode&&(c&&n.contains(d.ownerDocument,d)&&fa(ea(d,"script")),d.parentNode.removeChild(d));return a}n.extend({htmlPrefilter:function(a){return a.replace(va,"<$1></$2>")},clone:function(a,b,c){var d,e,f,g,h,i=n.contains(a.ownerDocument,a);if(l.html5Clone||n.isXMLDoc(a)||!ua.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(Ba.innerHTML=a.outerHTML,Ba.removeChild(f=Ba.firstChild)),!(l.noCloneEvent&&l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(d=ea(f),h=ea(a),g=0;null!=(e=h[g]);++g)d[g]&&Ga(e,d[g]);if(b)if(c)for(h=h||ea(a),d=d||ea(f),g=0;null!=(e=h[g]);g++)Fa(e,d[g]);else Fa(a,f);return d=ea(f,"script"),d.length>0&&fa(d,!i&&ea(a,"script")),d=h=e=null,f},cleanData:function(a,b){for(var d,e,f,g,h=0,i=n.expando,j=n.cache,k=l.attributes,m=n.event.special;null!=(d=a[h]);h++)if((b||M(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)m[e]?n.event.remove(d,e):n.removeEvent(d,e,g.handle);j[f]&&(delete j[f],k||"undefined"==typeof d.removeAttribute?d[i]=void 0:d.removeAttribute(i),c.push(f))}}}),n.fn.extend({domManip:Ha,detach:function(a){return Ia(this,a,!0)},remove:function(a){return Ia(this,a)},text:function(a){return Y(this,function(a){return void 0===a?n.text(this):this.empty().append((this[0]&&this[0].ownerDocument||d).createTextNode(a))},null,a,arguments.length)},append:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.appendChild(a)}})},prepend:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ha(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(ea(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&n.nodeName(a,"select")&&(a.options.length=0)}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 Y(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(ta,""):void 0;if("string"==typeof a&&!wa.test(a)&&(l.htmlSerialize||!ua.test(a))&&(l.leadingWhitespace||!aa.test(a))&&!da[($.exec(a)||["",""])[1].toLowerCase()]){a=n.htmlPrefilter(a);try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ea(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return Ha(this,arguments,function(b){var c=this.parentNode;n.inArray(this,a)<0&&(n.cleanData(ea(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=0,e=[],f=n(a),h=f.length-1;h>=d;d++)c=d===h?this:this.clone(!0),n(f[d])[b](c),g.apply(e,c.get());return this.pushStack(e)}});var Ja,Ka={HTML:"block",BODY:"block"};function La(a,b){var c=n(b.createElement(a)).appendTo(b.body),d=n.css(c[0],"display");return c.detach(),d}function Ma(a){var b=d,c=Ka[a];return c||(c=La(a,b),"none"!==c&&c||(Ja=(Ja||n("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=(Ja[0].contentWindow||Ja[0].contentDocument).document,b.write(),b.close(),c=La(a,b),Ja.detach()),Ka[a]=c),c}var Na=/^margin/,Oa=new RegExp("^("+T+")(?!px)[a-z%]+$","i"),Pa=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},Qa=d.documentElement;!function(){var b,c,e,f,g,h,i=d.createElement("div"),j=d.createElement("div");if(j.style){j.style.cssText="float:left;opacity:.5",l.opacity="0.5"===j.style.opacity,l.cssFloat=!!j.style.cssFloat,j.style.backgroundClip="content-box",j.cloneNode(!0).style.backgroundClip="",l.clearCloneStyle="content-box"===j.style.backgroundClip,i=d.createElement("div"),i.style.cssText="border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute",j.innerHTML="",i.appendChild(j),l.boxSizing=""===j.style.boxSizing||""===j.style.MozBoxSizing||""===j.style.WebkitBoxSizing,n.extend(l,{reliableHiddenOffsets:function(){return null==b&&k(),f},boxSizingReliable:function(){return null==b&&k(),e},pixelMarginRight:function(){return null==b&&k(),c},pixelPosition:function(){return null==b&&k(),b},reliableMarginRight:function(){return null==b&&k(),g},reliableMarginLeft:function(){return null==b&&k(),h}});function k(){var k,l,m=d.documentElement;m.appendChild(i),j.style.cssText="-webkit-box-sizing:border-box;box-sizing:border-box;position:relative;display:block;margin:auto;border:1px;padding:1px;top:1%;width:50%",b=e=h=!1,c=g=!0,a.getComputedStyle&&(l=a.getComputedStyle(j),b="1%"!==(l||{}).top,h="2px"===(l||{}).marginLeft,e="4px"===(l||{width:"4px"}).width,j.style.marginRight="50%",c="4px"===(l||{marginRight:"4px"}).marginRight,k=j.appendChild(d.createElement("div")),k.style.cssText=j.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",k.style.marginRight=k.style.width="0",j.style.width="1px",g=!parseFloat((a.getComputedStyle(k)||{}).marginRight),j.removeChild(k)),j.style.display="none",f=0===j.getClientRects().length,f&&(j.style.display="",j.innerHTML="<table><tr><td></td><td>t</td></tr></table>",j.childNodes[0].style.borderCollapse="separate",k=j.getElementsByTagName("td"),k[0].style.cssText="margin:0;border:0;padding:0;display:none",f=0===k[0].offsetHeight,f&&(k[0].style.display="",k[1].style.display="none",f=0===k[0].offsetHeight)),m.removeChild(i)}}}();var Ra,Sa,Ta=/^(top|right|bottom|left)$/;a.getComputedStyle?(Ra=function(b){var c=b.ownerDocument.defaultView;return c&&c.opener||(c=a),c.getComputedStyle(b)},Sa=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ra(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()&&Oa.test(g)&&Na.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+""}):Qa.currentStyle&&(Ra=function(a){return a.currentStyle},Sa=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ra(a),g=c?c[b]:void 0,null==g&&h&&h[b]&&(g=h[b]),Oa.test(g)&&!Ta.test(b)&&(d=h.left,e=a.runtimeStyle,f=e&&e.left,f&&(e.left=a.currentStyle.left),h.left="fontSize"===b?"1em":g,g=h.pixelLeft+"px",h.left=d,f&&(e.left=f)),void 0===g?g:g+""||"auto"});function Ua(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}var Va=/alpha\([^)]*\)/i,Wa=/opacity\s*=\s*([^)]*)/i,Xa=/^(none|table(?!-c[ea]).+)/,Ya=new RegExp("^("+T+")(.*)$","i"),Za={position:"absolute",visibility:"hidden",display:"block"},$a={letterSpacing:"0",fontWeight:"400"},_a=["Webkit","O","Moz","ms"],ab=d.createElement("div").style;function bb(a){if(a in ab)return a;var b=a.charAt(0).toUpperCase()+a.slice(1),c=_a.length;while(c--)if(a=_a[c]+b,a in ab)return a}function cb(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=n._data(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&W(d)&&(f[g]=n._data(d,"olddisplay",Ma(d.nodeName)))):(e=W(d),(c&&"none"!==c||!e)&&n._data(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}function db(a,b,c){var d=Ya.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function eb(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+V[f],!0,e)),d?("content"===c&&(g-=n.css(a,"padding"+V[f],!0,e)),"margin"!==c&&(g-=n.css(a,"border"+V[f]+"Width",!0,e))):(g+=n.css(a,"padding"+V[f],!0,e),"padding"!==c&&(g+=n.css(a,"border"+V[f]+"Width",!0,e)));return g}function fb(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=Ra(a),g=l.boxSizing&&"border-box"===n.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=Sa(a,b,f),(0>e||null==e)&&(e=a.style[b]),Oa.test(e))return e;d=g&&(l.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+eb(a,b,c||(g?"border":"content"),d,f)+"px"}n.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Sa(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":l.cssFloat?"cssFloat":"styleFloat"},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;if(b=n.cssProps[h]||(n.cssProps[h]=bb(h)||h),g=n.cssHooks[b]||n.cssHooks[h],void 0===c)return g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b];if(f=typeof c,"string"===f&&(e=U.exec(c))&&e[1]&&(c=X(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)))))try{i[b]=c}catch(j){}}},css:function(a,b,c,d){var e,f,g,h=n.camelCase(b);return b=n.cssProps[h]||(n.cssProps[h]=bb(h)||h),g=n.cssHooks[b]||n.cssHooks[h],g&&"get"in g&&(f=g.get(a,!0,c)),void 0===f&&(f=Sa(a,b,d)),"normal"===f&&b in $a&&(f=$a[b]),""===c||c?(e=parseFloat(f),c===!0||isFinite(e)?e||0:f):f}}),n.each(["height","width"],function(a,b){n.cssHooks[b]={get:function(a,c,d){return c?Xa.test(n.css(a,"display"))&&0===a.offsetWidth?Pa(a,Za,function(){return fb(a,b,d)}):fb(a,b,d):void 0},set:function(a,c,d){var e=d&&Ra(a);return db(a,c,d?eb(a,b,d,l.boxSizing&&"border-box"===n.css(a,"boxSizing",!1,e),e):0)}}}),l.opacity||(n.cssHooks.opacity={get:function(a,b){return Wa.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=n.isNumeric(b)?"alpha(opacity="+100*b+")":"",f=d&&d.filter||c.filter||"";c.zoom=1,(b>=1||""===b)&&""===n.trim(f.replace(Va,""))&&c.removeAttribute&&(c.removeAttribute("filter"),""===b||d&&!d.filter)||(c.filter=Va.test(f)?f.replace(Va,e):f+" "+e)}}),n.cssHooks.marginRight=Ua(l.reliableMarginRight,function(a,b){return b?Pa(a,{display:"inline-block"},Sa,[a,"marginRight"]):void 0}),n.cssHooks.marginLeft=Ua(l.reliableMarginLeft,function(a,b){return b?(parseFloat(Sa(a,"marginLeft"))||(n.contains(a.ownerDocument,a)?a.getBoundingClientRect().left-Pa(a,{ -marginLeft:0},function(){return a.getBoundingClientRect().left}):0))+"px":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+V[d]+b]=f[d]||f[d-2]||f[0];return e}},Na.test(a)||(n.cssHooks[a+b].set=db)}),n.fn.extend({css:function(a,b){return Y(this,function(a,b,c){var d,e,f={},g=0;if(n.isArray(b)){for(d=Ra(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 cb(this,!0)},hide:function(){return cb(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){W(this)?n(this).show():n(this).hide()})}});function gb(a,b,c,d,e){return new gb.prototype.init(a,b,c,d,e)}n.Tween=gb,gb.prototype={constructor:gb,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=gb.propHooks[this.prop];return a&&a.get?a.get(this):gb.propHooks._default.get(this)},run:function(a){var b,c=gb.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):gb.propHooks._default.set(this),this}},gb.prototype.init.prototype=gb.prototype,gb.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)}}},gb.propHooks.scrollTop=gb.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=gb.prototype.init,n.fx.step={};var hb,ib,jb=/^(?:toggle|show|hide)$/,kb=/queueHooks$/;function lb(){return a.setTimeout(function(){hb=void 0}),hb=n.now()}function mb(a,b){var c,d={height:a},e=0;for(b=b?1:0;4>e;e+=2-b)c=V[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function nb(a,b,c){for(var d,e=(qb.tweeners[b]||[]).concat(qb.tweeners["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function ob(a,b,c){var d,e,f,g,h,i,j,k,m=this,o={},p=a.style,q=a.nodeType&&W(a),r=n._data(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++,m.always(function(){m.always(function(){h.unqueued--,n.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[p.overflow,p.overflowX,p.overflowY],j=n.css(a,"display"),k="none"===j?n._data(a,"olddisplay")||Ma(a.nodeName):j,"inline"===k&&"none"===n.css(a,"float")&&(l.inlineBlockNeedsLayout&&"inline"!==Ma(a.nodeName)?p.zoom=1:p.display="inline-block")),c.overflow&&(p.overflow="hidden",l.shrinkWrapBlocks()||m.always(function(){p.overflow=c.overflow[0],p.overflowX=c.overflow[1],p.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],jb.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(q?"hide":"show")){if("show"!==e||!r||void 0===r[d])continue;q=!0}o[d]=r&&r[d]||n.style(a,d)}else j=void 0;if(n.isEmptyObject(o))"inline"===("none"===j?Ma(a.nodeName):j)&&(p.display=j);else{r?"hidden"in r&&(q=r.hidden):r=n._data(a,"fxshow",{}),f&&(r.hidden=!q),q?n(a).show():m.done(function(){n(a).hide()}),m.done(function(){var b;n._removeData(a,"fxshow");for(b in o)n.style(a,b,o[b])});for(d in o)g=nb(q?r[d]:0,d,m),d in r||(r[d]=g.start,q&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function pb(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 qb(a,b,c){var d,e,f=0,g=qb.prefilters.length,h=n.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=hb||lb(),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:hb||lb(),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(pb(k,j.opts.specialEasing);g>f;f++)if(d=qb.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,nb,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(qb,{tweeners:{"*":[function(a,b){var c=this.createTween(a,b);return X(c.elem,a,U.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],qb.tweeners[c]=qb.tweeners[c]||[],qb.tweeners[c].unshift(b)},prefilters:[ob],prefilter:function(a,b){b?qb.prefilters.unshift(a):qb.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(W).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=qb(this,n.extend({},a),f);(e||n._data(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._data(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&kb.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._data(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(mb(b,!0),a,d,e)}}),n.each({slideDown:mb("show"),slideUp:mb("hide"),slideToggle:mb("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=n.timers,c=0;for(hb=n.now();c<b.length;c++)a=b[c],a()||b[c]!==a||b.splice(c--,1);b.length||n.fx.stop(),hb=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(){ib||(ib=a.setInterval(n.fx.tick,n.fx.interval))},n.fx.stop=function(){a.clearInterval(ib),ib=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,b=d.createElement("input"),c=d.createElement("div"),e=d.createElement("select"),f=e.appendChild(d.createElement("option"));c=d.createElement("div"),c.setAttribute("className","t"),c.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",a=c.getElementsByTagName("a")[0],b.setAttribute("type","checkbox"),c.appendChild(b),a=c.getElementsByTagName("a")[0],a.style.cssText="top:1px",l.getSetAttribute="t"!==c.className,l.style=/top/.test(a.getAttribute("style")),l.hrefNormalized="/a"===a.getAttribute("href"),l.checkOn=!!b.value,l.optSelected=f.selected,l.enctype=!!d.createElement("form").enctype,e.disabled=!0,l.optDisabled=!f.disabled,b=d.createElement("input"),b.setAttribute("value",""),l.input=""===b.getAttribute("value"),b.value="t",b.setAttribute("type","radio"),l.radioValue="t"===b.value}();var rb=/\r/g,sb=/[\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(rb,""):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(sb," ")}},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--)if(d=e[g],n.inArray(n.valHooks.option.get(d),f)>-1)try{d.selected=c=!0}catch(h){d.scrollHeight}else d.selected=!1;return c||(a.selectedIndex=-1),e}}}}),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 tb,ub,vb=n.expr.attrHandle,wb=/^(?:checked|selected)$/i,xb=l.getSetAttribute,yb=l.input;n.fn.extend({attr:function(a,b){return Y(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)?ub:tb)),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)?yb&&xb||!wb.test(c)?a[d]=!1:a[n.camelCase("default-"+c)]=a[d]=!1:n.attr(a,c,""),a.removeAttribute(xb?c:d)}}),ub={set:function(a,b,c){return b===!1?n.removeAttr(a,c):yb&&xb||!wb.test(c)?a.setAttribute(!xb&&n.propFix[c]||c,c):a[n.camelCase("default-"+c)]=a[c]=!0,c}},n.each(n.expr.match.bool.source.match(/\w+/g),function(a,b){var c=vb[b]||n.find.attr;yb&&xb||!wb.test(b)?vb[b]=function(a,b,d){var e,f;return d||(f=vb[b],vb[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,vb[b]=f),e}:vb[b]=function(a,b,c){return c?void 0:a[n.camelCase("default-"+b)]?b.toLowerCase():null}}),yb&&xb||(n.attrHooks.value={set:function(a,b,c){return n.nodeName(a,"input")?void(a.defaultValue=b):tb&&tb.set(a,b,c)}}),xb||(tb={set:function(a,b,c){var d=a.getAttributeNode(c);return d||a.setAttributeNode(d=a.ownerDocument.createAttribute(c)),d.value=b+="","value"===c||b===a.getAttribute(c)?b:void 0}},vb.id=vb.name=vb.coords=function(a,b,c){var d;return c?void 0:(d=a.getAttributeNode(b))&&""!==d.value?d.value:null},n.valHooks.button={get:function(a,b){var c=a.getAttributeNode(b);return c&&c.specified?c.value:void 0},set:tb.set},n.attrHooks.contenteditable={set:function(a,b,c){tb.set(a,""===b?!1:b,c)}},n.each(["width","height"],function(a,b){n.attrHooks[b]={set:function(a,c){return""===c?(a.setAttribute(b,"auto"),c):void 0}}})),l.style||(n.attrHooks.style={get:function(a){return a.style.cssText||void 0},set:function(a,b){return a.style.cssText=b+""}});var zb=/^(?:input|select|textarea|button|object)$/i,Ab=/^(?:a|area)$/i;n.fn.extend({prop:function(a,b){return Y(this,n.prop,a,b,arguments.length>1)},removeProp:function(a){return a=n.propFix[a]||a,this.each(function(){try{this[a]=void 0,delete this[a]}catch(b){}})}}),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):zb.test(a.nodeName)||Ab.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),l.hrefNormalized||n.each(["href","src"],function(a,b){n.propHooks[b]={get:function(a){return a.getAttribute(b,4)}}}),l.optSelected||(n.propHooks.selected={get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,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}),l.enctype||(n.propFix.enctype="encoding");var Bb=/[\t\r\n\f]/g;function Cb(a){return n.attr(a,"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,Cb(this)))});if("string"==typeof a&&a){b=a.match(G)||[];while(c=this[i++])if(e=Cb(c),d=1===c.nodeType&&(" "+e+" ").replace(Bb," ")){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=n.trim(d),e!==h&&n.attr(c,"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,Cb(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(G)||[];while(c=this[i++])if(e=Cb(c),d=1===c.nodeType&&(" "+e+" ").replace(Bb," ")){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=n.trim(d),e!==h&&n.attr(c,"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,Cb(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=Cb(this),b&&n._data(this,"__className__",b),n.attr(this,"class",b||a===!1?"":n._data(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+Cb(c)+" ").replace(Bb," ").indexOf(b)>-1)return!0;return!1}}),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)}});var Db=a.location,Eb=n.now(),Fb=/\?/,Gb=/(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;n.parseJSON=function(b){if(a.JSON&&a.JSON.parse)return a.JSON.parse(b+"");var c,d=null,e=n.trim(b+"");return e&&!n.trim(e.replace(Gb,function(a,b,e,f){return c&&b&&(d=0),0===d?a:(c=e||b,d+=!f-!e,"")}))?Function("return "+e)():n.error("Invalid JSON: "+b)},n.parseXML=function(b){var c,d;if(!b||"string"!=typeof b)return null;try{a.DOMParser?(d=new a.DOMParser,c=d.parseFromString(b,"text/xml")):(c=new a.ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b))}catch(e){c=void 0}return c&&c.documentElement&&!c.getElementsByTagName("parsererror").length||n.error("Invalid XML: "+b),c};var Hb=/#.*$/,Ib=/([?&])_=[^&]*/,Jb=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Kb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Lb=/^(?:GET|HEAD)$/,Mb=/^\/\//,Nb=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,Ob={},Pb={},Qb="*/".concat("*"),Rb=Db.href,Sb=Nb.exec(Rb.toLowerCase())||[];function Tb(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.charAt(0)?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Ub(a,b,c,d){var e={},f=a===Pb;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 Vb(a,b){var c,d,e=n.ajaxSettings.flatOptions||{};for(d in b)void 0!==b[d]&&((e[d]?a:c||(c={}))[d]=b[d]);return c&&n.extend(!0,a,c),a}function Wb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===e&&(e=a.mimeType||b.getResponseHeader("Content-Type"));if(e)for(g in h)if(h[g]&&h[g].test(e)){i.unshift(g);break}if(i[0]in c)f=i[0];else{for(g in c){if(!i[0]||a.converters[g+" "+i[0]]){f=g;break}d||(d=g)}f=f||d}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function Xb(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:Rb,type:"GET",isLocal:Kb.test(Sb[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Qb,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?Vb(Vb(a,n.ajaxSettings),b):Vb(n.ajaxSettings,a)},ajaxPrefilter:Tb(Ob),ajaxTransport:Tb(Pb),ajax:function(b,c){"object"==typeof b&&(c=b,b=void 0),c=c||{};var d,e,f,g,h,i,j,k,l=n.ajaxSetup({},c),m=l.context||l,o=l.context&&(m.nodeType||m.jquery)?n(m):n.event,p=n.Deferred(),q=n.Callbacks("once memory"),r=l.statusCode||{},s={},t={},u=0,v="canceled",w={readyState:0,getResponseHeader:function(a){var b;if(2===u){if(!k){k={};while(b=Jb.exec(g))k[b[1].toLowerCase()]=b[2]}b=k[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===u?g:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return u||(a=t[c]=t[c]||a,s[a]=b),this},overrideMimeType:function(a){return u||(l.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>u)for(b in a)r[b]=[r[b],a[b]];else w.always(a[w.status]);return this},abort:function(a){var b=a||v;return j&&j.abort(b),y(0,b),this}};if(p.promise(w).complete=q.add,w.success=w.done,w.error=w.fail,l.url=((b||l.url||Rb)+"").replace(Hb,"").replace(Mb,Sb[1]+"//"),l.type=c.method||c.type||l.method||l.type,l.dataTypes=n.trim(l.dataType||"*").toLowerCase().match(G)||[""],null==l.crossDomain&&(d=Nb.exec(l.url.toLowerCase()),l.crossDomain=!(!d||d[1]===Sb[1]&&d[2]===Sb[2]&&(d[3]||("http:"===d[1]?"80":"443"))===(Sb[3]||("http:"===Sb[1]?"80":"443")))),l.data&&l.processData&&"string"!=typeof l.data&&(l.data=n.param(l.data,l.traditional)),Ub(Ob,l,c,w),2===u)return w;i=n.event&&l.global,i&&0===n.active++&&n.event.trigger("ajaxStart"),l.type=l.type.toUpperCase(),l.hasContent=!Lb.test(l.type),f=l.url,l.hasContent||(l.data&&(f=l.url+=(Fb.test(f)?"&":"?")+l.data,delete l.data),l.cache===!1&&(l.url=Ib.test(f)?f.replace(Ib,"$1_="+Eb++):f+(Fb.test(f)?"&":"?")+"_="+Eb++)),l.ifModified&&(n.lastModified[f]&&w.setRequestHeader("If-Modified-Since",n.lastModified[f]),n.etag[f]&&w.setRequestHeader("If-None-Match",n.etag[f])),(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&w.setRequestHeader("Content-Type",l.contentType),w.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+("*"!==l.dataTypes[0]?", "+Qb+"; q=0.01":""):l.accepts["*"]);for(e in l.headers)w.setRequestHeader(e,l.headers[e]);if(l.beforeSend&&(l.beforeSend.call(m,w,l)===!1||2===u))return w.abort();v="abort";for(e in{success:1,error:1,complete:1})w[e](l[e]);if(j=Ub(Pb,l,c,w)){if(w.readyState=1,i&&o.trigger("ajaxSend",[w,l]),2===u)return w;l.async&&l.timeout>0&&(h=a.setTimeout(function(){w.abort("timeout")},l.timeout));try{u=1,j.send(s,y)}catch(x){if(!(2>u))throw x;y(-1,x)}}else y(-1,"No Transport");function y(b,c,d,e){var k,s,t,v,x,y=c;2!==u&&(u=2,h&&a.clearTimeout(h),j=void 0,g=e||"",w.readyState=b>0?4:0,k=b>=200&&300>b||304===b,d&&(v=Wb(l,w,d)),v=Xb(l,v,w,k),k?(l.ifModified&&(x=w.getResponseHeader("Last-Modified"),x&&(n.lastModified[f]=x),x=w.getResponseHeader("etag"),x&&(n.etag[f]=x)),204===b||"HEAD"===l.type?y="nocontent":304===b?y="notmodified":(y=v.state,s=v.data,t=v.error,k=!t)):(t=y,!b&&y||(y="error",0>b&&(b=0))),w.status=b,w.statusText=(c||y)+"",k?p.resolveWith(m,[s,y,w]):p.rejectWith(m,[w,y,t]),w.statusCode(r),r=void 0,i&&o.trigger(k?"ajaxSuccess":"ajaxError",[w,l,k?s:t]),q.fireWith(m,[w,y]),i&&(o.trigger("ajaxComplete",[w,l]),--n.active||n.event.trigger("ajaxStop")))}return w},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",cache:!0,async:!1,global:!1,"throws":!0})},n.fn.extend({wrapAll:function(a){if(n.isFunction(a))return this.each(function(b){n(this).wrapAll(a.call(this,b))});if(this[0]){var 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.firstChild&&1===a.firstChild.nodeType)a=a.firstChild;return a}).append(this)}return 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()}});function Yb(a){return a.style&&a.style.display||n.css(a,"display")}function Zb(a){if(!n.contains(a.ownerDocument||d,a))return!0;while(a&&1===a.nodeType){if("none"===Yb(a)||"hidden"===a.type)return!0;a=a.parentNode}return!1}n.expr.filters.hidden=function(a){return l.reliableHiddenOffsets()?a.offsetWidth<=0&&a.offsetHeight<=0&&!a.getClientRects().length:Zb(a)},n.expr.filters.visible=function(a){return!n.expr.filters.hidden(a)};var $b=/%20/g,_b=/\[\]$/,ac=/\r?\n/g,bc=/^(?:submit|button|image|reset|file)$/i,cc=/^(?:input|select|textarea|keygen)/i;function dc(a,b,c,d){var e;if(n.isArray(b))n.each(b,function(b,e){c||_b.test(a)?d(a,e):dc(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)dc(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)dc(c,a[c],b,e);return d.join("&").replace($b,"+")},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")&&cc.test(this.nodeName)&&!bc.test(a)&&(this.checked||!Z.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(ac,"\r\n")}}):{name:b.name,value:c.replace(ac,"\r\n")}}).get()}}),n.ajaxSettings.xhr=void 0!==a.ActiveXObject?function(){return this.isLocal?ic():d.documentMode>8?hc():/^(get|post|head|put|delete|options)$/i.test(this.type)&&hc()||ic()}:hc;var ec=0,fc={},gc=n.ajaxSettings.xhr();a.attachEvent&&a.attachEvent("onunload",function(){for(var a in fc)fc[a](void 0,!0)}),l.cors=!!gc&&"withCredentials"in gc,gc=l.ajax=!!gc,gc&&n.ajaxTransport(function(b){if(!b.crossDomain||l.cors){var c;return{send:function(d,e){var f,g=b.xhr(),h=++ec;if(g.open(b.type,b.url,b.async,b.username,b.password),b.xhrFields)for(f in b.xhrFields)g[f]=b.xhrFields[f];b.mimeType&&g.overrideMimeType&&g.overrideMimeType(b.mimeType),b.crossDomain||d["X-Requested-With"]||(d["X-Requested-With"]="XMLHttpRequest");for(f in d)void 0!==d[f]&&g.setRequestHeader(f,d[f]+"");g.send(b.hasContent&&b.data||null),c=function(a,d){var f,i,j;if(c&&(d||4===g.readyState))if(delete fc[h],c=void 0,g.onreadystatechange=n.noop,d)4!==g.readyState&&g.abort();else{j={},f=g.status,"string"==typeof g.responseText&&(j.text=g.responseText);try{i=g.statusText}catch(k){i=""}f||!b.isLocal||b.crossDomain?1223===f&&(f=204):f=j.text?200:404}j&&e(f,i,j,g.getAllResponseHeaders())},b.async?4===g.readyState?a.setTimeout(c):g.onreadystatechange=fc[h]=c:c()},abort:function(){c&&c(void 0,!0)}}}});function hc(){try{return new a.XMLHttpRequest}catch(b){}}function ic(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}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",a.global=!1)}),n.ajaxTransport("script",function(a){if(a.crossDomain){var b,c=d.head||n("head")[0]||d.documentElement;return{send:function(e,f){b=d.createElement("script"),b.async=!0,a.scriptCharset&&(b.charset=a.scriptCharset),b.src=a.url,b.onload=b.onreadystatechange=function(a,c){(c||!b.readyState||/loaded|complete/.test(b.readyState))&&(b.onload=b.onreadystatechange=null,b.parentNode&&b.parentNode.removeChild(b),b=null,c||f(200,"success"))},c.insertBefore(b,c.firstChild)},abort:function(){b&&b.onload(void 0,!0)}}}});var jc=[],kc=/(=)\?(?=&|$)|\?\?/;n.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=jc.pop()||n.expando+"_"+Eb++;return this[a]=!0,a}}),n.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(kc.test(b.url)?"url":"string"==typeof b.data&&0===(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&kc.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(kc,"$1"+e):b.jsonp!==!1&&(b.url+=(Fb.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,jc.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=ja([a],b,f),f&&f.length&&n(f).remove(),n.merge([],e.childNodes))};var lc=n.fn.load;n.fn.load=function(a,b,c){if("string"!=typeof a&&lc)return lc.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>-1&&(d=n.trim(a.slice(h,a.length)),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 mc(a){return n.isWindow(a)?a:9===a.nodeType?a.defaultView||a.parentWindow:!1}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)&&n.inArray("auto",[f,i])>-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={top:0,left:0},e=this[0],f=e&&e.ownerDocument;if(f)return b=f.documentElement,n.contains(b,e)?("undefined"!=typeof e.getBoundingClientRect&&(d=e.getBoundingClientRect()),c=mc(f),{top:d.top+(c.pageYOffset||b.scrollTop)-(b.clientTop||0),left:d.left+(c.pageXOffset||b.scrollLeft)-(b.clientLeft||0)}):d},position:function(){if(this[0]){var a,b,c={top:0,left:0},d=this[0];return"fixed"===n.css(d,"position")?b=d.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),n.nodeName(a[0],"html")||(c=a.offset()),c.top+=n.css(a[0],"borderTopWidth",!0),c.left+=n.css(a[0],"borderLeftWidth",!0)),{top:b.top-c.top-n.css(d,"marginTop",!0),left:b.left-c.left-n.css(d,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent;while(a&&!n.nodeName(a,"html")&&"static"===n.css(a,"position"))a=a.offsetParent;return a||Qa})}}),n.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c=/Y/.test(b);n.fn[a]=function(d){return Y(this,function(a,d,e){var f=mc(a);return void 0===e?f?b in f?f[b]:f.document.documentElement[d]:a[d]:void(f?f.scrollTo(c?n(f).scrollLeft():e,c?e:n(f).scrollTop()):a[d]=e)},a,d,arguments.length,null)}}),n.each(["top","left"],function(a,b){n.cssHooks[b]=Ua(l.pixelPosition,function(a,c){return c?(c=Sa(a,b),Oa.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 Y(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)}}),n.fn.size=function(){return this.length},n.fn.andSelf=n.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return n});var nc=a.jQuery,oc=a.$;return n.noConflict=function(b){return a.$===n&&(a.$=oc),b&&a.jQuery===n&&(a.jQuery=nc),n},b||(a.jQuery=a.$=n),n}); - diff --git a/website/agenda/js/calcms.js b/website/agenda/js/calcms.js index f7ee645..be71c1a 100644 --- a/website/agenda/js/calcms.js +++ b/website/agenda/js/calcms.js @@ -1,804 +1,560 @@ var calcms = (function($) { - // define this - var my = {}; - - // calcms base functions - // event handlers are customized at herbstradio.org - - my.updateContainer = function updateContainer(id, url, onLoading, callback) { - // alert(id+url); - if (id == null) - return; - if ($("#" + id).length == 0) - return; - // if (onLoading)document.getElementById(id).innerHTML="lade ..."; - $("#" + id).load(url, null, callback); - } - - my.load = function load(url) { - window.location.href = url; - // $(window).load(url); - // $('html').load(url); - } - - my.postContainer = function postContainer(url, parameters, callback) { - if (url != '') - $.post(url, parameters, callback); - } - - // get calcms setting - my.get = function get(name) { - if (calcms_settings[name] == null) - return ''; - return calcms_settings[name]; - } - - // set calcms setting - my.set = function set(name, value) { - calcms_settings[name] = value; - } - - // get select box value - my.selectValue = function selectValue(element) { - value = element.options[element.selectedIndex].value; - return value; - } - - my.selectFirstOption = function selectFirstOption(id) { - if ($(id) && $(id).length > 0) - $(id)[0].selectedIndex = 0; - } - - my.contains = function contains(s, t) { - if (s == false) - return false; - if (t == false) - return false; - return s.indexOf(t) != -1; - } - - my.getJsName = function getJsName(s) { - s = s.replace(/[^a-zA-Z\_0-9]/g, '_'); - s = s.replace(/_+/g, '_'); - return s; - } - - my.isArchive = function isArchive() { - if ($('#calcms_archive:checked').length == 0) - return 0; - return 1; - } - - my.getSearchElement = function getSearchElement() { - return $("#calcms_search input[name='search']"); - } - - my.resetSearch = function resetSearch() { - $("#calcms_search_field").val(''); - } - - // set calcms_settings to parameters from URL - my.evaluateParametersFromUrl = function evaluateParametersFromUrl() { - var location = new String(window.location); - - if (!location.match(my.get("base_url"))) - return; - - if (window.location.search != "") { - var parameters = window.location.search.split("?")[1].split("&"); - for (var i = 0; i < parameters.length; i++) { - var pair = parameters[i]; - var name_values = pair.split("="); - if (name_values != null) { - // alert(name_values[0]+"="+name_values[1]); - // set(name_values[0],name_values[1]); - var element = document.getElementById(name_values[0]); - if (element != null) - element.value = name_values[1]; - } - } - } - - var sendung = /\/sendung\/(\d+)\//; - sendung.exec(location); - - if (RegExp.$1 != null && RegExp.$1 != '') { - // alert(RegExp.$1); - set('event_id', RegExp.$1); - set('last_event_id', my.get('event_id')); - } else { - - var sendungen = /\/sendungen\/(\d{4}\-\d{2}\-\d{2})\/(\d{4}\-\d{2}\-\d{2})\/(\d)\//; - sendungen.exec(location); - if (RegExp.$1 != '' && RegExp.$2 != '' && RegExp.$3 != '') { - set('from_date', RegExp.$1); - set('till_date', RegExp.$2); - set('weekday', RegExp.$3); - } else { - - var sendungen = /\/sendungen\/(\d{4}\-\d{2}\-\d{2})\/(\d{4}\-\d{2}\-\d{2})\//; - sendungen.exec(location); - if (RegExp.$1 != '' && RegExp.$2 != '') { - set('from_date', RegExp.$1); - set('till_date', RegExp.$2); - } else { - var sendungen = /\/sendungen\/(\d{4}\-\d{2}\-\d{2})\//; - sendungen.exec(location); - if (RegExp.$1 != '') { - set('date', RegExp.$1); - } - } - - } - - var kalender = /\/kalender\/(\d{4}\-\d{2}\-\d{2})\/(\d{4}\-\d{2}\-\d{2})\//; - kalender.exec(location); - if (RegExp.$1 != '' && RegExp.$2 != '') { - set('from_date', RegExp.$1); - set('till_date', RegExp.$2); - } else { - var kalender = /\/kalender\/(\d{4}\-\d{2}\-\d{2})\//; - kalender.exec(location); - if (RegExp.$1 != '') { - set('date', RegExp.$1); - } - } - } - } - - // return URL from calcms_settings - // parameters can be overwritten by field and value - // This handles main controller interaction logics - my.setAndGetUrlParameters = function setAndGetUrlParameters(field, value) { - - // overwrite fields by field and value - if (field != null && value != null && field != '') { - // alert(target+" "+field+" "+value); - set(field, value); - } - - // read fields - var debug = my.get('debug'); - var from_date = my.get('from_date'); - var till_date = my.get('till_date'); - var date = my.get('date'); - var month = my.get('month'); - var weekday = my.get('weekday'); - var time = ''; - var program = my.get('program'); - var series_name = my.get('series_name'); - var category = my.get('category'); - var tag = my.get('tag'); - var search_field = my.get('search'); - - // delete filters by current action - if ((field == 'search' && search_field != '') - || (field == 'category' && category != '') - || (field == 'series_name' && series_name != '') - || (field == 'program' && program != '') || (field == 'tag') - && tag != '') { - weekday = ''; - date = ''; - from_date = ''; - till_date = ''; - } - - if (field == 'search') { - category = ''; - series_name = ''; - program = ''; - } - - if (field == 'category') { - search_field = ''; - series_name = ''; - program = ''; - } - - if (field == 'program') { - search_field = ''; - series_name = ''; - category = ''; - } - - if (field == 'series_name') { - search_field = ''; - program = ''; - category = ''; - } - - if (field == 'month') { - if (month != '') { - from_date = month; - till_date = month.substring(0, month.length - 2) + "31"; - } - weekday = ''; - date = ''; - category = ''; - program = ''; - series_name = ''; - tags = ''; - search_field = ''; - } - - if (field == 'week') { - weekday = ''; - date = ''; - category = ''; - program = ''; - series_name = ''; - tags = ''; - search_field = ''; - } - - if (field == 'weekday') { - /* - * if (month != ''){ from_date=month; - * till_date=month.substring(0,month.length-2)+"31" ; } - */ - category = ''; - program = ''; - series_name = ''; - tags = ''; - search_field = ''; - } - - if (field == 'date') { - weekday = ''; - from_date = ''; - till_date = ''; - category = ''; - program = ''; - series_name = ''; - tags = ''; - search_field = ''; - } - - if (field == 'time') { - if (time == 'null') { - return - - - - - - - - } else { - weekday = ''; - } - } - - if (field == 'month' || field == 'week' || field == 'weekday'){ - time = ''; - } - - // build target URL - var url = ''; - - if (field == 'month' || field == 'week') { - if (from_date != '') - url += '/' + from_date; - if (till_date != '') - url += '/' + till_date; - } else if (weekday != '') { - if (from_date != '') - url += '/' + from_date; - if (till_date != '') - url += '/' + till_date; - url += '/' + weekday; - } else if (date != '') { - if (date == 'today') { - url += '/heute/'; - } else { - url += '/' + date; - } - } - - if (search_field != '') { - url += "/suche/" + search_field; - } - - if (category != null && category != '') { - url += "/kategorie/" + category; - } - - if (series_name != null && series_name != '') { - url += "/sendereihe/" + series_name; - } - - if (url.substr(url.length - 1, url.length) != '/') { - url += '/'; - } else if (time != '' && time != 'null') { - url += "&" + time; - } - - if (tag != null && tag != '') { - url += "&tag=" + tag; - } - - if (program != null && program != '') { - url += "&program=" + program; - } - - if (field == 'print') { - url += "&print=1"; - } - - if (debug != '') { - url += '&debug=' + debug; - } - - return url; - } - - // show current project categories - my.showProjectCategories = function showProjectCategories(project) { - var projectJsName = calcms.getJsName(project); - $('#calcmsCategoryForm select').each(function() { - var id = $(this).attr('id'); - if (id == "calcms_category_" + projectJsName) { - if ($(this).css('display') == 'none') - $(this).show(); - } else { - if ($(this).css('display') != 'none') - $(this).hide(); - } - }); - } - - // show current series categories - my.showProjectSeriesNames = function showProjectSeriesNames(project) { - var projectJsName = calcms.getJsName(project); - $('#calcmsSeriesNamesForm select').each(function() { - var id = $(this).attr('id'); - if (id == "calcms_series_name_" + projectJsName) { - if ($(this).css('display') == 'none') - $(this).show(); - } else { - if ($(this).css('display') != 'none') - $(this).hide(); - } - }); - } - - // get current project - my.getProject = function getProject() { - var project = $('#calcms_project'); - if (project.length == 0) - return 'all'; - return project.val(); - } - - // remove projects from form without categories and series_names - my.removeEmptyProjects = function removeEmptyProjects() { - $('#calcms_project option').each( - function() { - var project = $(this).val(); - var hasCategories = $('#calcms_category_' - + calcms.getJsName(project)).length; - var hasSeries = $('#calcms_series_name_' - + calcms.getJsName(project)).length; - if ((hasCategories == 0) && (hasSeries == 0)) { - $(this).remove(); - } - }); - } - - my.clearOnChangeArchive = function clearOnChangeArchive() { - $('#calcms_archive').off(); - } - - // register action on changing archive - my.registerOnChangeArchive = function registerOnChangeArchive(action) { - my.clearOnChangeArchive(); - $('#calcms_archive').on('click', action); - } - - // show all events for a given project - my.showSearchResultsByProject = function showSearchResultsByProject( - project, value, archive) { - if (value != null && value != '') { - var url = my.get('search_url'); - if (project != '' && project != null) - url += escape(encodeURI(project)) + '/'; - else - url += 'all/'; - if (value != '' && value != null) - url += escape(encodeURI(value)) + '/'; - if (archive != null && archive == 0) - url += 'kommende/'; - if (archive != null && archive == 1) - url += 'vergangene/'; - my.updateContainer('sendungen', url, 1); - } - } - - // show all events for a given category - my.showEventsByCategory = function showEventsByCategory(value) { - if (value != '' && value != null) { - my.updateContainer('sendungen', my.get('search_category_url') - + escape(value) + '/', 1); - } - } - - // show all events for a given project and category - my.showEventsByProjectAndCategory = function showEventsByProjectAndCategory( - project, category, archive) { - if (category != '' && category != null) { - var url = my.get('search_category_url'); - if (project != '' && project != null) - url += escape(project) + '/'; - if (category != '' && category != null) - url += escape(category) + '/'; - if (archive != null && archive == 0) - url += 'kommende/'; - if (archive != null && archive == 1) - url += 'vergangene/'; - my.updateContainer('sendungen', url, 1); - } - } - - // show all events for a given project and series - my.showEventsByProjectAndSeriesName = function showEventsByProjectAndSeriesName( - project, seriesName, archive) { - if (seriesName != '' && seriesName != null) { - var url = my.get('search_series_name_url'); - if (project != '' && project != null) - { - project = project.replace(/'/g, ' '); - url += escape(project) + '/'; - } - - if (seriesName != '' && seriesName != null) - { - // send series name to url fragment - if(history.pushState) - { - history.pushState(null, 'Serie: '+seriesName, 'https://programm.coloradio.org/agenda/#seriesName+'+seriesName); - } - else - { - location.hash = '#seriesName+'+seriesName; - } - // escape apostrophe in show titles - seriesName = seriesName.replace(/'/g, ' ');; - url += encodeURI(escape(seriesName)) + '/'; - } - if (archive != null && archive == 0) - url += 'kommende/'; - if (archive != null && archive == 1) - url += 'vergangene/'; - /* alert (url); */ - my.updateContainer('sendungen', url, 1); - } - } - - // show all events for a given series - my.showEventsBySeriesName = function showEventsBySeriesName(value) { - if (value != '' && value != null) { - my.updateContainer('sendungen', my.get('search_series_name_url') - + escape(value) + '/', 1); - } - } - - // show all events for a given program - my.showEventsByProgram = function showEventsByProgram(value) { - var events_url = my.get('events_url'); - var url = my.setAndGetUrlParameters('program', value); - if (value != '' && value != null) { - // my.updateContainer('calcms_list', events_url+url, 1); - my.updateContainer('sendungen', url, 1); - } - } - - // show next event of a given series - my.showNextSeriesEvent = function showNextSeriesEvent(value) { - var events_url = my.get('next_series_url'); - my.load(events_url + '/' + value + '.html'); - } - - // show previous event of a given series - my.showPrevSeriesEvent = function showPrevSeriesEvent(value) { - var events_url = my.get('prev_series_url'); - my.load(events_url + '/' + value + '.html'); - } - - my.showMenuAndList = function showMenuAndList(target, field, value) { - - var events_url = my.get('events_url'); - var menu_url = my.get('menu_url'); - var event_id = my.get('event_id'); - - var url = my.setAndGetUrlParameters(field, value); - - if (target == 'window') { - window.location.href = events_url + url; - } else { - my.updateContainer('calcms_menu', menu_url + url, 1); - - if (event_id != '' && event_id != null && Number(event_id) != 'NaN') { - // load list selected by url - my.showEvents(event_id, ''); - my.set('event_id', ''); - } else { - // load event list - my.updateContainer('calcms_list', events_url + url, 1); - my.set('last_list_url', events_url + url); - } - - } - return false; - } - - // load given event details into list - my.showEvents = function showEvents(event_id, view) { - if (view == null || view == '') - view = 'list_url'; - if (event_id != '') { - var url = my.get(view) + '/' + event_id + '/'; - my.updateContainer('calcms_list', url, 1); - } else { - document.getElementById('calcms_list').innerHTML = 'keine Sendung gefunden...'; - } - } - - // load given event details into list - my.showEvent = function showEvent(event_id) { - var old_url = my.get('last_list_url'); - var url = my.get('list_url') + '/' + event_id + '/'; - if (url != old_url) { - my.set('last_event_id', event_id); - my - .updateContainer( - 'calcms_list', - url, - 1, - function(responseText, textStatus, XMLHttpRequest) { - var back_link = '<a href="#" onclick="updateContainer(\'calcms_list\',\'' - + old_url - + '\');return false;">zurück</a>'; - document.getElementById('calcms_list').innerHTML = back_link - + document - .getElementById('calcms_list').innerHTML - + '<p><hr/>' + back_link; - }); - } - } - - // Calendar actions - - // update menu and list by given date - my.showEventsByDate = function showEventsByDate(date) { - // my.set('date',date); - my.showMenuAndList('', 'date', date); - return false; - - }; - - // update menu and list by events from weekday at given date range - my.showEventsByWeekday = function showEventsByWeekday(from, till, weekday) { - my.set('from_date', from); - my.set('till_date', till); - my.set('weekday', weekday); - my.showMenuAndList('', 'weekday'); - return false; - - }; - - // update menu and list by events from given date range - my.showEventsByDateRange = function showEventsByDateRange(from, till) { - my.set('from_date', from); - my.set('till_date', till); - my.showMenuAndList('', 'week'); - return false; - }; - - // load calendar content - my.showCalendar = function showCalendar(target, field) { - var calendar_debug = my.get('calendar_debug'); - var calendar_url = my.get('calendar_url'); - var debug = my.get('debug'); - var date = my.get('month'); - - var url = calendar_url; - - console.log(calendar_url); - - if (field == 'month') { - url += '/' + date + '/'; - } - if (debug != '') { - url += '&debug=' + debug; - } - - if (target == 'window') { - window.location.href = events_url + url; - } else { - my.updateContainer('calcms_calendar', url); - } - - if (calendar_debug != null) { - calendar_debug.innerHTML = url; - } - return false; - } - - // update menu, list and calendar widget by entries of given month YYYY-MM - // (current day) - my.showTodaysCalendarAndEvents = function showTodaysCalendarAndEvents(month) { - my.set('month', month); - // my.set(date,'today'); - my.showMenuAndList('', 'date', 'today'); - my.showCalendar('', 'month'); - return false; - - }; - - // update menu, list and calendar widget by entries of given month YYYY-MM - my.showCalendarAndEventsByMonth = function showCalendarAndEventsByMonth( - month) { - my.set('month', month); - my.showMenuAndList('', 'month'); - my.showCalendar('', 'month'); - return false; - - }; - - // update menu, list and calendar widget by entries of given date YYYY-MM-DD - my.showCalendarAndEventsByDate = function showCalendarAndEventsByDate(date) { - my.set('date', date); - my.showMenuAndList('', 'date'); - - my.set('month', date); - my.showCalendar('', 'month'); - return false; - - }; - - // end of Calendar actions - - // show comment for given event id and start time - my.showCommentsByEventIdOrEventStart = function showCommentsByEventIdOrEventStart( - event_id, event_start) { - var url = my.get('comments_url'); - if (event_id == '' || event_start == '' || url == '') - return false; - - my.set('comments_event_start', event_start); - my.set('comments_event_id', event_id); - - url += event_id + '/' + event_start + '/'; - - my.updateContainer('calcms_comments', url); - } - - // add a comment to a event - my.addComment = function addComment(id, comment) { - var url = my.get('add_comment_url'); - if (url != '') - $.post(url, $("#" + id).serialize(), function(data) { - my.showCommentsByEventIdOrEventStart(my - .get('comments_event_id'), my - .get('comments_event_start')); - - }); - return false; - } - - // insert new comment form - my.showCommentForm = function showCommentForm(id, parent_id, event_id, - event_start) { - var response = '<div>'; - if (parent_id != '') - response += 'Deine Anwort:'; - document.getElementById(id).innerHTML = response - + '<form id="add_comment_' - + parent_id - + '" ' - + ' action="/agenda/kommentar_neu/?" method="post" ' - + ' onsubmit="calcms.addComment(\'add_comment_' - + parent_id - + '\',this);return false;" ' - + '>' - + ' Name: *<br /> ' - + ' <input name="author" maxlength="40" /><br /> ' - + ' Was ich sagen will, ist: *<br /> ' - + ' <textarea name="content" cols="60" rows="10" ' - + ' onkeyup="javascript:if (this.value.length>1000) this.value=this.value.substr(0,1000)" ' - + ' ></textarea><br />' - - + ' Email: (für Rückmeldungen, wird nicht angezeigt)<br /> ' - + ' <input name="email" maxlength="40" /><br /> ' - - + ' <input type="submit" value="abschicken!" /> ' - + ' <input name="event_id" value="' + event_id - + '" type="hidden" /> ' - + ' <input name="parent_id" value="' + parent_id - + '" type="hidden" /> ' - + ' <input name="event_start" value="' + event_start - + '" type="hidden" /> ' + '</form>' + '</div>'; - // $("#"+id).show("drop"); - my.show(id); - } - // end of Comment actions - - // used to embed playlist in external pages - my.showPlaylist = function showPlaylist() { - var url = my.get('playlist_url'); - my.updateContainer('calcms_playlist', url); - } - - // load comments into #calcms_newest_comments if not embedded yet - my.showNewestComments = function showNewestComments() { - if (my.get('preloaded') == '') { - var url = my.get('newest_comments_url'); - my.updateContainer('calcms_newest_comments', url); - } - return false; - } - - // export selected events to ical - my.exportSelectedToICal = function exportSelectedToICal() { - window.location = my.get('ical_url') + my.setAndGetUrlParameters(); - ; - return false; - } - - // init search interface: load search form content if not loaded yet - my.initSearch = function initSearch(target, field) { - if (my.get('preloaded') == '') { - var category_url = my.get('category_url'); - var program_url = my.get('program_url'); - var series_name_url = my.get('series_name_url'); - var debug = my.get('debug'); - - if (category_url != null && category_url != '') - my.updateContainer('calcms_categories', category_url, 1); - if (program_url != null && program_url != '') - my.updateContainer('calcms_programs', program_url, 1); - if (series_name_url != null && series_name_url != '') - my.updateContainer('calcms_series_names', series_name_url, 1); - } - return false; - } - - // wrapper to show an id - my.show = function show(id) { - $("#" + id).show("drop"); - document.getElementById(id).style.visibility = "visible"; - // document.getElementById(id).style.display="block"; - } - - // wrapper to hide an id - my.hide = function hide(id) { - $("#" + id).hide("drop"); - document.getElementById(id).style.visibility = "hidden"; - // document.getElementById(id).style.display="none"; - } - - // return max date - my.setDateIfBefore = function setDateIfBefore(date1, date2) { - if (date1 < date2) - return date2; - return date1; - } - - // return min date - my.setDateIfAfter = function setDateIfAfter(date1, date2) { - if (date1 > date2) - return date2; - return date1; - } - - // remove Drupal header for currently playing entry at topic overview page - my.removeCurrentPlayingHeader = function removeCurrentPlayingHeader() { - $("h2 a[href$='/testing']").each(function() { - $(this).css("display", "none"); - }); - } - - // return instance - return my; + // define this + var my = {}; + + // calcms base functions + my.updateContainer = function updateContainer(id, url, callback) { + if (id == null) return; + var elem = document.querySelector('#' + id); + if (elem == null) return; + fetch( url ) + .then( response => response.text()) + .then( text => { + elem.innerHTML = text; + if (callback != null) callback(); + }) + .catch( error => { + console.error('Error:', error); + }); + } + + my.load = function load(url) { + window.location.href = url; + } + + my.show = function (elem) { + elem.style.display = 'block'; + }; + + my.hide = function (elem) { + elem.style.display = 'none'; + }; + + my.toggle = function (elem) { + if (window.getComputedStyle(elem).display === 'block') { + my.hide(elem); + }else{ + my.show(elem); + } + }; + + // get calcms setting + my.get = function get(name) { + if (calcms_settings[name] == null) return ''; + return calcms_settings[name]; + } + + // set calcms setting + my.set = function set(name, value) { + calcms_settings[name] = value; + } + + // get select box value + my.selectValue = function selectValue(element) { + value = element.options[element.selectedIndex].value; + return value; + } + + my.selectFirstOption = function selectFirstOption(id) { + if ($(id) && $(id).length > 0) $(id)[0].selectedIndex = 0; + } + + my.contains = function contains(s, t) { + if (s == false) return false; + if (t == false) return false; + return s.indexOf(t) != -1; + } + + my.getJsName = function getJsName(s) { + s = s.replace(/[^a-zA-Z\_0-9]/g, '_'); + s = s.replace(/_+/g, '_'); + return s; + } + + my.isArchive = function isArchive() { + if ($('#calcms_archive:checked').length == 0) return 0; + return 1; + } + + my.getSearchElement = function getSearchElement() { + return $("#calcms_search input[name='search']"); + } + + my.resetSearch = function resetSearch() { + $("#calcms_search_field").val(''); + } + + // return URL from calcms_settings + // parameters can be overwritten by field and value + // This handles main controller interaction logics + my.setAndGetUrlParameters = function setAndGetUrlParameters(field, value) { + + // overwrite fields by field and value + if (field != null && value != null && field != '') set(field, value); + + // read fields + var debug = my.get('debug'); + var from_date = my.get('from_date'); + var till_date = my.get('till_date'); + var date = my.get('date'); + var month = my.get('month'); + var weekday = my.get('weekday'); + var time = ''; + var series_name = my.get('series_name'); + var search_field = my.get('search'); + + // delete filters by current action + if ((field == 'search' && search_field != '') + || (field == 'series_name' && series_name != '')) { + weekday = ''; + date = ''; + from_date = ''; + till_date = ''; + } + + if (field == 'search') { + series_name = ''; + program = ''; + } + + if (field == 'series_name') { + search_field = ''; + program = ''; + } + + if (field == 'month') { + if (month != null && month != '') { + let date = month; + let year = date.substring(0,4); + let mon = date.substring(5,7); + from_date = date; + till_date = date.substring(0, date.length - 2) + + new Date(year, mon , 0).getDate(); + } + weekday = ''; + date = ''; + series_name = ''; + search_field = ''; + } + + if (field == 'week') { + weekday = ''; + date = ''; + series_name = ''; + search_field = ''; + } + + if (field == 'weekday') { + series_name = ''; + search_field = ''; + } + + if (field == 'date') { + weekday = ''; + from_date = ''; + till_date = ''; + series_name = ''; + search_field = ''; + } + + if (field == 'time') { + if (time == 'null') { + return; + } else { + weekday = ''; + } + } + + if (field == 'month' || field == 'week' || field == 'weekday') { + time = ''; + } + + // build target URL + var url = ''; + + if (field == 'month' || field == 'week') { + if (from_date != '') url += '/' + from_date; + if (till_date != '') url += '/' + till_date; + } else if (weekday != '') { + if (from_date != '') url += '/' + from_date; + if (till_date != '') url += '/' + till_date; + url += '/' + weekday; + } else if (date != '') { + if (date == 'today') { + url += '/heute/'; + } else { + url += '/' + date; + } + } + + if (search_field != '') { + url += "/suche/" + search_field; + } + + if (series_name != null && series_name != '') { + url += "/sendereihe/" + series_name; + } + + if (url.substr(url.length - 1, url.length) != '/') { + url += '/'; + } + + if (field == 'print') { + url += "&print=1"; + } + + if (debug != '') { + url += '&debug=' + debug; + } + + return url; + } + + // show current series + my.showProjectSeriesNames = function showProjectSeriesNames(project) { + var projectJsName = calcms.getJsName(project); + $('#calcmsSeriesNamesForm select').each(function() { + var id = $(this).attr('id'); + if (id == "calcms_series_name_" + projectJsName) { + if ($(this).css('display') == 'none') $(this).show(); + } else { + if ($(this).css('display') != 'none') $(this).hide(); + } + }); + } + + // get current project + my.getProject = function getProject() { + var project = $('#calcms_project'); + if (project.length == 0) return 'all'; + return project.val(); + } + + // remove projects from form without series_names + my.removeEmptyProjects = function removeEmptyProjects() { + $('#calcms_project option').each( + function() { + var project = $(this).val(); + var hasSeries = $('#calcms_series_name_' + + calcms.getJsName(project)).length; + if (hasSeries == 0) { + $(this).remove(); + } + }); + } + + my.clearOnChangeArchive = function clearOnChangeArchive() { + $('#calcms_archive').off(); + } + + // register action on changing archive + my.registerOnChangeArchive = function registerOnChangeArchive(action) { + my.clearOnChangeArchive(); + $('#calcms_archive').on('click', action); + } + + // show all events for a given project + my.showSearchResultsByProject = function showSearchResultsByProject( + project, value, archive) { + if (value != null && value != '') { + var url = my.get('search_url'); + if (project != '' && project != null) + url += escape(project) + '/'; + else + url += 'all/'; + if (value != '' && value != null) url += escape(value) + '/'; + if (archive != null && archive == 0) url += 'kommende/'; + if (archive != null && archive == 1) url += 'vergangene/'; + my.updateContainer('calcms_list', url); + } + } + + // show all events for a given project and series + my.showEventsByProjectAndSeriesName = function showEventsByProjectAndSeriesName( + project, seriesName, archive) { + if (seriesName != '' && seriesName != null) { + var url = my.get('search_series_name_url'); + if (project != '' && project != null) url += escape(project) + '/'; + if (seriesName != '' && seriesName != null) + url += escape(seriesName) + '/'; + if (archive != null && archive == 0) url += 'kommende/'; + if (archive != null && archive == 1) url += 'vergangene/'; + my.updateContainer('calcms_list', url); + } + } + + // show all events for a given series + my.showEventsBySeriesName = function showEventsBySeriesName(value) { + if (value != '' && value != null) { + my.updateContainer('calcms_list', my.get('search_series_name_url') + + escape(value) + '/'); + } + } + + // show all events for a given program + my.showEventsByProgram = function showEventsByProgram(value) { + var events_url = my.get('events_url'); + var url = my.setAndGetUrlParameters('program', value); + if (value != '' && value != null) { + my.updateContainer('calcms_list', url); + } + } + + // show next event of a given series + my.showNextSeriesEvent = function showNextSeriesEvent(value) { + var events_url = my.get('next_series_url'); + my.load(events_url + '/' + value + '.html'); + } + + // show previous event of a given series + my.showPrevSeriesEvent = function showPrevSeriesEvent(value) { + var events_url = my.get('prev_series_url'); + my.load(events_url + '/' + value + '.html'); + } + + my.showMenuAndList = function showMenuAndList(target, field, value) { + + var events_url = my.get('events_url'); + var menu_url = my.get('menu_url'); + var event_id = my.get('event_id'); + + var url = my.setAndGetUrlParameters(field, value); + + if (target == 'window') { + window.location.href = events_url + url; + } else { + my.updateContainer('calcms_menu', menu_url + url); + + if (event_id != '' && event_id != null && Number(event_id) != 'NaN') { + // load list selected by url + my.showEvents(event_id, ''); + my.set('event_id', ''); + } else { + // load event list + my.updateContainer('calcms_list', events_url + url); + my.set('last_list_url', events_url + url); + } + + } + return false; + } + + // load given event details into list + my.showEvents = function showEvents(event_id, view) { + if (view == null || view == '') view = 'list_url'; + if (event_id != '') { + var url = my.get(view) + '/' + event_id + '/'; + my.updateContainer('calcms_list', url); + } else { + document.getElementById('calcms_list').innerHTML = 'keine Sendung gefunden...'; + } + } + + // load given event details into list + my.showEvent = function showEvent(event_id) { + var old_url = my.get('last_list_url'); + var url = my.get('list_url') + '/' + event_id + '/'; + if (url != old_url) { + my.set('last_event_id', event_id); + my + .updateContainer( + 'calcms_list', + url, + function(responseText, textStatus, XMLHttpRequest) { + var back_link = '<a href="#" onclick="updateContainer(\'calcms_list\',\'' + + old_url + + '\');return false;">zurück</a>'; + document.getElementById('calcms_list').innerHTML = back_link + + document + .getElementById('calcms_list').innerHTML + + '<p><hr/>' + back_link; + }); + } + } + + // Calendar actions + + // update menu and list by given date + my.showEventsByDate = function showEventsByDate(date) { + my.showMenuAndList('', 'date', date); + return false; + + }; + + // update menu and list by events from weekday at given date range + my.showEventsByWeekday = function showEventsByWeekday(from, till, weekday) { + my.set('from_date', from); + my.set('till_date', till); + my.set('weekday', weekday); + my.showMenuAndList('', 'weekday'); + return false; + + }; + + // update menu and list by events from given date range + my.showEventsByDateRange = function showEventsByDateRange(from, till) { + my.set('from_date', from); + my.set('till_date', till); + my.showMenuAndList('', 'week'); + return false; + }; + + // load calendar content + my.showCalendar = function showCalendar(target, field) { + var calendar_debug = my.get('calendar_debug'); + var calendar_url = my.get('calendar_url'); + var debug = my.get('debug'); + var date = my.get('month'); + + var url = calendar_url; + + if (field == 'month') { + url += '/' + date + '/'; + } + if (debug != '') { + url += '&debug=' + debug; + } + + if (target == 'window') { + window.location.href = events_url + url; + } else { + my.updateContainer('calcms_calendar', url); + } + + if (calendar_debug != null) { + calendar_debug.innerHTML = url; + } + return false; + } + + // update menu, list and calendar widget by entries of given month YYYY-MM + my.showCalendarAndEventsByMonth = function showCalendarAndEventsByMonth( + month) { + my.set('month', month); + my.showMenuAndList('', 'month'); + my.showCalendar('', 'month'); + return false; + + }; + + // end of Calendar actions + + // show comment for given event id and start time + my.showCommentsByEventIdOrEventStart = function showCommentsByEventIdOrEventStart( + event_id, event_start) { + var url = my.get('comments_url') || '/agenda/kommentare/'; + if (event_id == '' || event_start == '' || url == '') return false; + console.log("showCommentsByEventIdOrEventStart url=" + url); + + my.set('comments_event_start', event_start); + my.set('comments_event_id', event_id); + + url += event_id + '/' + event_start + '/'; + + my.updateContainer('calcms_comments', url); + } + + // add a comment to a event + my.addComment = function addComment(id, comment) { + var url = my.get('add_comment_url'); + if (url == '') return; + + var formElement = document.getElementById(id); + const data = new URLSearchParams(); + for (const pair of new FormData(formElement)) { + data.append(pair[0], pair[1]); + } + fetch( url, { + method: 'post', + body: data + }) + .then( response => response.text() ) + .then( result => { + console.log('Success:', result); + my.showCommentsByEventIdOrEventStart( + my.get('comments_event_id'), + my.get('comments_event_start') + ); + }) + .catch( error => { + console.error('Error:', error); + }); + + return false; + } + + // insert new comment form + my.showCommentForm = function showCommentForm(id, parent_id, event_id, + event_start) { + var response = '<div>'; + if (parent_id != '') response += 'Deine Anwort:'; + var html = response + html += '<form id="add_comment_' + parent_id + '"' + html += ' action="/agenda/kommentar_neu/?" method="post"' + html += ' onsubmit="calcms.addComment(\'add_comment_' + parent_id + + '\',this);return false;"' + html += '>' + html += 'Mit dem Absenden Ihres Kommentars erklären Sie sich mit der Veröffentlichung der Daten einverstanden.<br> '; + html += 'Die Email-Addresse ist optional, dient privaten Antworten und wird nicht veröffentlicht.<br> ' + html += 'Details siehe <a href="/datenschutzerklaerung/">Datenschutzerklärung und Widerrufshinweise</a>.<br>' + html += '<input name="author" maxlength="40" placeholder="Nickname"/><br />' + html += '<textarea name="content" cols="60" rows="10"' + html += ' onkeyup="javascript:if (this.value.length>1000) this.value=this.value.substr(0,1000)"' + html += ' placeholder="Was ich sagen will, ist..."' + html += ' ></textarea><br />' + html += '<input name="email" maxlength="40" placeholder="Email-Addresse für Rückmeldungen"/><br />' + html += '<input type="submit" value="absenden!" style="color:#000"/>' + html += '<input name="event_id" value="' + event_id + + '" type="hidden" />' + html += '<input name="parent_id" value="' + parent_id + + '" type="hidden" />' + html += '<input name="event_start" value="' + event_start + + '" type="hidden" />' + html += '</form>' + html += '</div>'; + + document.getElementById(id).innerHTML = html; + my.show(document.getElementById(id)); + document.getElementById(id).style.visibility = "visible"; + } + // end of Comment actions + + // used to embed playlist in external pages + my.showPlaylist = function showPlaylist() { + var url = my.get('playlist_url'); + my.updateContainer('calcms_playlist', url); + } + + // load comments into #calcms_newest_comments if not embedded yet + my.showNewestComments = function showNewestComments() { + if (my.get('preloaded') == '') { + var url = my.get('newest_comments_url'); + my.updateContainer('calcms_newest_comments', url); + } + return false; + } + + // export selected events to ical + my.exportSelectedToICal = function exportSelectedToICal() { + window.location = my.get('ical_url') + my.setAndGetUrlParameters(); + return false; + } + + // init search interface: load search form content if not loaded yet + my.initSearch = function initSearch(target, field) { + if (my.get('preloaded') == '') { + var program_url = my.get('program_url'); + var series_name_url = my.get('series_name_url'); + var debug = my.get('debug'); + + if (program_url != null && program_url != '') + my.updateContainer('calcms_programs', program_url); + if (series_name_url != null && series_name_url != '') + my.updateContainer('calcms_series_names', series_name_url); + } + return false; + } + + // return instance + return my; }(jQuery)); - diff --git a/website/agenda/js/jquery.jplayer.min.js b/website/agenda/js/jquery.jplayer.min.js deleted file mode 100644 index 99f64d7..0000000 --- a/website/agenda/js/jquery.jplayer.min.js +++ /dev/null @@ -1,3 +0,0 @@ -/*! jPlayer 2.9.2 for jQuery ~ (c) 2009-2014 Happyworm Ltd ~ MIT License */ -!function(a,b){"function"==typeof define&&define.amd?define(["jquery"],b):b("object"==typeof exports?require("jquery"):a.jQuery?a.jQuery:a.Zepto)}(this,function(a,b){a.fn.jPlayer=function(c){var d="jPlayer",e="string"==typeof c,f=Array.prototype.slice.call(arguments,1),g=this;return c=!e&&f.length?a.extend.apply(null,[!0,c].concat(f)):c,e&&"_"===c.charAt(0)?g:(this.each(e?function(){var e=a(this).data(d),h=e&&a.isFunction(e[c])?e[c].apply(e,f):e;return h!==e&&h!==b?(g=h,!1):void 0}:function(){var b=a(this).data(d);b?b.option(c||{}):a(this).data(d,new a.jPlayer(c,this))}),g)},a.jPlayer=function(b,c){if(arguments.length){this.element=a(c),this.options=a.extend(!0,{},this.options,b);var d=this;this.element.bind("remove.jPlayer",function(){d.destroy()}),this._init()}},"function"!=typeof a.fn.stop&&(a.fn.stop=function(){}),a.jPlayer.emulateMethods="load play pause",a.jPlayer.emulateStatus="src readyState networkState currentTime duration paused ended playbackRate",a.jPlayer.emulateOptions="muted volume",a.jPlayer.reservedEvent="ready flashreset resize repeat error warning",a.jPlayer.event={},a.each(["ready","setmedia","flashreset","resize","repeat","click","error","warning","loadstart","progress","suspend","abort","emptied","stalled","play","pause","loadedmetadata","loadeddata","waiting","playing","canplay","canplaythrough","seeking","seeked","timeupdate","ended","ratechange","durationchange","volumechange"],function(){a.jPlayer.event[this]="jPlayer_"+this}),a.jPlayer.htmlEvent=["loadstart","abort","emptied","stalled","loadedmetadata","canplay","canplaythrough"],a.jPlayer.pause=function(){a.jPlayer.prototype.destroyRemoved(),a.each(a.jPlayer.prototype.instances,function(a,b){b.data("jPlayer").status.srcSet&&b.jPlayer("pause")})},a.jPlayer.timeFormat={showHour:!1,showMin:!0,showSec:!0,padHour:!1,padMin:!0,padSec:!0,sepHour:":",sepMin:":",sepSec:""};var c=function(){this.init()};c.prototype={init:function(){this.options={timeFormat:a.jPlayer.timeFormat}},time:function(a){a=a&&"number"==typeof a?a:0;var b=new Date(1e3*a),c=b.getUTCHours(),d=this.options.timeFormat.showHour?b.getUTCMinutes():b.getUTCMinutes()+60*c,e=this.options.timeFormat.showMin?b.getUTCSeconds():b.getUTCSeconds()+60*d,f=this.options.timeFormat.padHour&&10>c?"0"+c:c,g=this.options.timeFormat.padMin&&10>d?"0"+d:d,h=this.options.timeFormat.padSec&&10>e?"0"+e:e,i="";return i+=this.options.timeFormat.showHour?f+this.options.timeFormat.sepHour:"",i+=this.options.timeFormat.showMin?g+this.options.timeFormat.sepMin:"",i+=this.options.timeFormat.showSec?h+this.options.timeFormat.sepSec:""}};var d=new c;a.jPlayer.convertTime=function(a){return d.time(a)},a.jPlayer.uaBrowser=function(a){var b=a.toLowerCase(),c=/(webkit)[ \/]([\w.]+)/,d=/(opera)(?:.*version)?[ \/]([\w.]+)/,e=/(msie) ([\w.]+)/,f=/(mozilla)(?:.*? rv:([\w.]+))?/,g=c.exec(b)||d.exec(b)||e.exec(b)||b.indexOf("compatible")<0&&f.exec(b)||[];return{browser:g[1]||"",version:g[2]||"0"}},a.jPlayer.uaPlatform=function(a){var b=a.toLowerCase(),c=/(ipad|iphone|ipod|android|blackberry|playbook|windows ce|webos)/,d=/(ipad|playbook)/,e=/(android)/,f=/(mobile)/,g=c.exec(b)||[],h=d.exec(b)||!f.exec(b)&&e.exec(b)||[];return g[1]&&(g[1]=g[1].replace(/\s/g,"_")),{platform:g[1]||"",tablet:h[1]||""}},a.jPlayer.browser={},a.jPlayer.platform={};var e=a.jPlayer.uaBrowser(navigator.userAgent);e.browser&&(a.jPlayer.browser[e.browser]=!0,a.jPlayer.browser.version=e.version);var f=a.jPlayer.uaPlatform(navigator.userAgent);f.platform&&(a.jPlayer.platform[f.platform]=!0,a.jPlayer.platform.mobile=!f.tablet,a.jPlayer.platform.tablet=!!f.tablet),a.jPlayer.getDocMode=function(){var b;return a.jPlayer.browser.msie&&(document.documentMode?b=document.documentMode:(b=5,document.compatMode&&"CSS1Compat"===document.compatMode&&(b=7))),b},a.jPlayer.browser.documentMode=a.jPlayer.getDocMode(),a.jPlayer.nativeFeatures={init:function(){var a,b,c,d=document,e=d.createElement("video"),f={w3c:["fullscreenEnabled","fullscreenElement","requestFullscreen","exitFullscreen","fullscreenchange","fullscreenerror"],moz:["mozFullScreenEnabled","mozFullScreenElement","mozRequestFullScreen","mozCancelFullScreen","mozfullscreenchange","mozfullscreenerror"],webkit:["","webkitCurrentFullScreenElement","webkitRequestFullScreen","webkitCancelFullScreen","webkitfullscreenchange",""],webkitVideo:["webkitSupportsFullscreen","webkitDisplayingFullscreen","webkitEnterFullscreen","webkitExitFullscreen","",""],ms:["","msFullscreenElement","msRequestFullscreen","msExitFullscreen","MSFullscreenChange","MSFullscreenError"]},g=["w3c","moz","webkit","webkitVideo","ms"];for(this.fullscreen=a={support:{w3c:!!d[f.w3c[0]],moz:!!d[f.moz[0]],webkit:"function"==typeof d[f.webkit[3]],webkitVideo:"function"==typeof e[f.webkitVideo[2]],ms:"function"==typeof e[f.ms[2]]},used:{}},b=0,c=g.length;c>b;b++){var h=g[b];if(a.support[h]){a.spec=h,a.used[h]=!0;break}}if(a.spec){var i=f[a.spec];a.api={fullscreenEnabled:!0,fullscreenElement:function(a){return a=a?a:d,a[i[1]]},requestFullscreen:function(a){return a[i[2]]()},exitFullscreen:function(a){return a=a?a:d,a[i[3]]()}},a.event={fullscreenchange:i[4],fullscreenerror:i[5]}}else a.api={fullscreenEnabled:!1,fullscreenElement:function(){return null},requestFullscreen:function(){},exitFullscreen:function(){}},a.event={}}},a.jPlayer.nativeFeatures.init(),a.jPlayer.focus=null,a.jPlayer.keyIgnoreElementNames="A INPUT TEXTAREA SELECT BUTTON";var g=function(b){var c,d=a.jPlayer.focus;d&&(a.each(a.jPlayer.keyIgnoreElementNames.split(/\s+/g),function(a,d){return b.target.nodeName.toUpperCase()===d.toUpperCase()?(c=!0,!1):void 0}),c||a.each(d.options.keyBindings,function(c,e){return e&&a.isFunction(e.fn)&&("number"==typeof e.key&&b.which===e.key||"string"==typeof e.key&&b.key===e.key)?(b.preventDefault(),e.fn(d),!1):void 0}))};a.jPlayer.keys=function(b){var c="keydown.jPlayer";a(document.documentElement).unbind(c),b&&a(document.documentElement).bind(c,g)},a.jPlayer.keys(!0),a.jPlayer.prototype={count:0,version:{script:"2.9.2",needFlash:"2.9.0",flash:"unknown"},options:{swfPath:"js",solution:"html, flash",supplied:"mp3",auroraFormats:"wav",preload:"metadata",volume:.8,muted:!1,remainingDuration:!1,toggleDuration:!1,captureDuration:!0,playbackRate:1,defaultPlaybackRate:1,minPlaybackRate:.5,maxPlaybackRate:4,wmode:"opaque",backgroundColor:"#000000",cssSelectorAncestor:"#jp_container_1",cssSelector:{videoPlay:".jp-video-play",play:".jp-play",pause:".jp-pause",stop:".jp-stop",seekBar:".jp-seek-bar",playBar:".jp-play-bar",mute:".jp-mute",unmute:".jp-unmute",volumeBar:".jp-volume-bar",volumeBarValue:".jp-volume-bar-value",volumeMax:".jp-volume-max",playbackRateBar:".jp-playback-rate-bar",playbackRateBarValue:".jp-playback-rate-bar-value",currentTime:".jp-current-time",duration:".jp-duration",title:".jp-title",fullScreen:".jp-full-screen",restoreScreen:".jp-restore-screen",repeat:".jp-repeat",repeatOff:".jp-repeat-off",gui:".jp-gui",noSolution:".jp-no-solution"},stateClass:{playing:"jp-state-playing",seeking:"jp-state-seeking",muted:"jp-state-muted",looped:"jp-state-looped",fullScreen:"jp-state-full-screen",noVolume:"jp-state-no-volume"},useStateClassSkin:!1,autoBlur:!0,smoothPlayBar:!1,fullScreen:!1,fullWindow:!1,autohide:{restored:!1,full:!0,fadeIn:200,fadeOut:600,hold:1e3},loop:!1,repeat:function(b){b.jPlayer.options.loop?a(this).unbind(".jPlayerRepeat").bind(a.jPlayer.event.ended+".jPlayer.jPlayerRepeat",function(){a(this).jPlayer("play")}):a(this).unbind(".jPlayerRepeat")},nativeVideoControls:{},noFullWindow:{msie:/msie [0-6]\./,ipad:/ipad.*?os [0-4]\./,iphone:/iphone/,ipod:/ipod/,android_pad:/android [0-3]\.(?!.*?mobile)/,android_phone:/(?=.*android)(?!.*chrome)(?=.*mobile)/,blackberry:/blackberry/,windows_ce:/windows ce/,iemobile:/iemobile/,webos:/webos/},noVolume:{ipad:/ipad/,iphone:/iphone/,ipod:/ipod/,android_pad:/android(?!.*?mobile)/,android_phone:/android.*?mobile/,blackberry:/blackberry/,windows_ce:/windows ce/,iemobile:/iemobile/,webos:/webos/,playbook:/playbook/},timeFormat:{},keyEnabled:!1,audioFullScreen:!1,keyBindings:{play:{key:80,fn:function(a){a.status.paused?a.play():a.pause()}},fullScreen:{key:70,fn:function(a){(a.status.video||a.options.audioFullScreen)&&a._setOption("fullScreen",!a.options.fullScreen)}},muted:{key:77,fn:function(a){a._muted(!a.options.muted)}},volumeUp:{key:190,fn:function(a){a.volume(a.options.volume+.1)}},volumeDown:{key:188,fn:function(a){a.volume(a.options.volume-.1)}},loop:{key:76,fn:function(a){a._loop(!a.options.loop)}}},verticalVolume:!1,verticalPlaybackRate:!1,globalVolume:!1,idPrefix:"jp",noConflict:"jQuery",emulateHtml:!1,consoleAlerts:!0,errorAlerts:!1,warningAlerts:!1},optionsAudio:{size:{width:"0px",height:"0px",cssClass:""},sizeFull:{width:"0px",height:"0px",cssClass:""}},optionsVideo:{size:{width:"480px",height:"270px",cssClass:"jp-video-270p"},sizeFull:{width:"100%",height:"100%",cssClass:"jp-video-full"}},instances:{},status:{src:"",media:{},paused:!0,format:{},formatType:"",waitForPlay:!0,waitForLoad:!0,srcSet:!1,video:!1,seekPercent:0,currentPercentRelative:0,currentPercentAbsolute:0,currentTime:0,duration:0,remaining:0,videoWidth:0,videoHeight:0,readyState:0,networkState:0,playbackRate:1,ended:0},internal:{ready:!1},solution:{html:!0,aurora:!0,flash:!0},format:{mp3:{codec:"audio/mpeg",flashCanPlay:!0,media:"audio"},m4a:{codec:'audio/mp4; codecs="mp4a.40.2"',flashCanPlay:!0,media:"audio"},m3u8a:{codec:'application/vnd.apple.mpegurl; codecs="mp4a.40.2"',flashCanPlay:!1,media:"audio"},m3ua:{codec:"audio/mpegurl",flashCanPlay:!1,media:"audio"},oga:{codec:'audio/ogg; codecs="vorbis, opus"',flashCanPlay:!1,media:"audio"},flac:{codec:"audio/x-flac",flashCanPlay:!1,media:"audio"},wav:{codec:'audio/wav; codecs="1"',flashCanPlay:!1,media:"audio"},webma:{codec:'audio/webm; codecs="vorbis"',flashCanPlay:!1,media:"audio"},fla:{codec:"audio/x-flv",flashCanPlay:!0,media:"audio"},rtmpa:{codec:'audio/rtmp; codecs="rtmp"',flashCanPlay:!0,media:"audio"},m4v:{codec:'video/mp4; codecs="avc1.42E01E, mp4a.40.2"',flashCanPlay:!0,media:"video"},m3u8v:{codec:'application/vnd.apple.mpegurl; codecs="avc1.42E01E, mp4a.40.2"',flashCanPlay:!1,media:"video"},m3uv:{codec:"audio/mpegurl",flashCanPlay:!1,media:"video"},ogv:{codec:'video/ogg; codecs="theora, vorbis"',flashCanPlay:!1,media:"video"},webmv:{codec:'video/webm; codecs="vorbis, vp8"',flashCanPlay:!1,media:"video"},flv:{codec:"video/x-flv",flashCanPlay:!0,media:"video"},rtmpv:{codec:'video/rtmp; codecs="rtmp"',flashCanPlay:!0,media:"video"}},_init:function(){var c=this;if(this.element.empty(),this.status=a.extend({},this.status),this.internal=a.extend({},this.internal),this.options.timeFormat=a.extend({},a.jPlayer.timeFormat,this.options.timeFormat),this.internal.cmdsIgnored=a.jPlayer.platform.ipad||a.jPlayer.platform.iphone||a.jPlayer.platform.ipod,this.internal.domNode=this.element.get(0),this.options.keyEnabled&&!a.jPlayer.focus&&(a.jPlayer.focus=this),this.androidFix={setMedia:!1,play:!1,pause:!1,time:0/0},a.jPlayer.platform.android&&(this.options.preload="auto"!==this.options.preload?"metadata":"auto"),this.formats=[],this.solutions=[],this.require={},this.htmlElement={},this.html={},this.html.audio={},this.html.video={},this.aurora={},this.aurora.formats=[],this.aurora.properties=[],this.flash={},this.css={},this.css.cs={},this.css.jq={},this.ancestorJq=[],this.options.volume=this._limitValue(this.options.volume,0,1),a.each(this.options.supplied.toLowerCase().split(","),function(b,d){var e=d.replace(/^\s+|\s+$/g,"");if(c.format[e]){var f=!1;a.each(c.formats,function(a,b){return e===b?(f=!0,!1):void 0}),f||c.formats.push(e)}}),a.each(this.options.solution.toLowerCase().split(","),function(b,d){var e=d.replace(/^\s+|\s+$/g,"");if(c.solution[e]){var f=!1;a.each(c.solutions,function(a,b){return e===b?(f=!0,!1):void 0}),f||c.solutions.push(e)}}),a.each(this.options.auroraFormats.toLowerCase().split(","),function(b,d){var e=d.replace(/^\s+|\s+$/g,"");if(c.format[e]){var f=!1;a.each(c.aurora.formats,function(a,b){return e===b?(f=!0,!1):void 0}),f||c.aurora.formats.push(e)}}),this.internal.instance="jp_"+this.count,this.instances[this.internal.instance]=this.element,this.element.attr("id")||this.element.attr("id",this.options.idPrefix+"_jplayer_"+this.count),this.internal.self=a.extend({},{id:this.element.attr("id"),jq:this.element}),this.internal.audio=a.extend({},{id:this.options.idPrefix+"_audio_"+this.count,jq:b}),this.internal.video=a.extend({},{id:this.options.idPrefix+"_video_"+this.count,jq:b}),this.internal.flash=a.extend({},{id:this.options.idPrefix+"_flash_"+this.count,jq:b,swf:this.options.swfPath+(".swf"!==this.options.swfPath.toLowerCase().slice(-4)?(this.options.swfPath&&"/"!==this.options.swfPath.slice(-1)?"/":"")+"jquery.jplayer.swf":"")}),this.internal.poster=a.extend({},{id:this.options.idPrefix+"_poster_"+this.count,jq:b}),a.each(a.jPlayer.event,function(a,d){c.options[a]!==b&&(c.element.bind(d+".jPlayer",c.options[a]),c.options[a]=b)}),this.require.audio=!1,this.require.video=!1,a.each(this.formats,function(a,b){c.require[c.format[b].media]=!0}),this.options=this.require.video?a.extend(!0,{},this.optionsVideo,this.options):a.extend(!0,{},this.optionsAudio,this.options),this._setSize(),this.status.nativeVideoControls=this._uaBlocklist(this.options.nativeVideoControls),this.status.noFullWindow=this._uaBlocklist(this.options.noFullWindow),this.status.noVolume=this._uaBlocklist(this.options.noVolume),a.jPlayer.nativeFeatures.fullscreen.api.fullscreenEnabled&&this._fullscreenAddEventListeners(),this._restrictNativeVideoControls(),this.htmlElement.poster=document.createElement("img"),this.htmlElement.poster.id=this.internal.poster.id,this.htmlElement.poster.onload=function(){(!c.status.video||c.status.waitForPlay)&&c.internal.poster.jq.show()},this.element.append(this.htmlElement.poster),this.internal.poster.jq=a("#"+this.internal.poster.id),this.internal.poster.jq.css({width:this.status.width,height:this.status.height}),this.internal.poster.jq.hide(),this.internal.poster.jq.bind("click.jPlayer",function(){c._trigger(a.jPlayer.event.click)}),this.html.audio.available=!1,this.require.audio&&(this.htmlElement.audio=document.createElement("audio"),this.htmlElement.audio.id=this.internal.audio.id,this.html.audio.available=!!this.htmlElement.audio.canPlayType&&this._testCanPlayType(this.htmlElement.audio)),this.html.video.available=!1,this.require.video&&(this.htmlElement.video=document.createElement("video"),this.htmlElement.video.id=this.internal.video.id,this.html.video.available=!!this.htmlElement.video.canPlayType&&this._testCanPlayType(this.htmlElement.video)),this.flash.available=this._checkForFlash(10.1),this.html.canPlay={},this.aurora.canPlay={},this.flash.canPlay={},a.each(this.formats,function(b,d){c.html.canPlay[d]=c.html[c.format[d].media].available&&""!==c.htmlElement[c.format[d].media].canPlayType(c.format[d].codec),c.aurora.canPlay[d]=a.inArray(d,c.aurora.formats)>-1,c.flash.canPlay[d]=c.format[d].flashCanPlay&&c.flash.available}),this.html.desired=!1,this.aurora.desired=!1,this.flash.desired=!1,a.each(this.solutions,function(b,d){if(0===b)c[d].desired=!0;else{var e=!1,f=!1;a.each(c.formats,function(a,b){c[c.solutions[0]].canPlay[b]&&("video"===c.format[b].media?f=!0:e=!0)}),c[d].desired=c.require.audio&&!e||c.require.video&&!f}}),this.html.support={},this.aurora.support={},this.flash.support={},a.each(this.formats,function(a,b){c.html.support[b]=c.html.canPlay[b]&&c.html.desired,c.aurora.support[b]=c.aurora.canPlay[b]&&c.aurora.desired,c.flash.support[b]=c.flash.canPlay[b]&&c.flash.desired}),this.html.used=!1,this.aurora.used=!1,this.flash.used=!1,a.each(this.solutions,function(b,d){a.each(c.formats,function(a,b){return c[d].support[b]?(c[d].used=!0,!1):void 0})}),this._resetActive(),this._resetGate(),this._cssSelectorAncestor(this.options.cssSelectorAncestor),this.html.used||this.aurora.used||this.flash.used?this.css.jq.noSolution.length&&this.css.jq.noSolution.hide():(this._error({type:a.jPlayer.error.NO_SOLUTION,context:"{solution:'"+this.options.solution+"', supplied:'"+this.options.supplied+"'}",message:a.jPlayer.errorMsg.NO_SOLUTION,hint:a.jPlayer.errorHint.NO_SOLUTION}),this.css.jq.noSolution.length&&this.css.jq.noSolution.show()),this.flash.used){var d,e="jQuery="+encodeURI(this.options.noConflict)+"&id="+encodeURI(this.internal.self.id)+"&vol="+this.options.volume+"&muted="+this.options.muted;if(a.jPlayer.browser.msie&&(Number(a.jPlayer.browser.version)<9||a.jPlayer.browser.documentMode<9)){var f='<object id="'+this.internal.flash.id+'" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="0" height="0" tabindex="-1"></object>',g=['<param name="movie" value="'+this.internal.flash.swf+'" />','<param name="FlashVars" value="'+e+'" />','<param name="allowScriptAccess" value="always" />','<param name="bgcolor" value="'+this.options.backgroundColor+'" />','<param name="wmode" value="'+this.options.wmode+'" />'];d=document.createElement(f);for(var h=0;h<g.length;h++)d.appendChild(document.createElement(g[h]))}else{var i=function(a,b,c){var d=document.createElement("param");d.setAttribute("name",b),d.setAttribute("value",c),a.appendChild(d)};d=document.createElement("object"),d.setAttribute("id",this.internal.flash.id),d.setAttribute("name",this.internal.flash.id),d.setAttribute("data",this.internal.flash.swf),d.setAttribute("type","application/x-shockwave-flash"),d.setAttribute("width","1"),d.setAttribute("height","1"),d.setAttribute("tabindex","-1"),i(d,"flashvars",e),i(d,"allowscriptaccess","always"),i(d,"bgcolor",this.options.backgroundColor),i(d,"wmode",this.options.wmode)}this.element.append(d),this.internal.flash.jq=a(d)}this.status.playbackRateEnabled=this.html.used&&!this.flash.used?this._testPlaybackRate("audio"):!1,this._updatePlaybackRate(),this.html.used&&(this.html.audio.available&&(this._addHtmlEventListeners(this.htmlElement.audio,this.html.audio),this.element.append(this.htmlElement.audio),this.internal.audio.jq=a("#"+this.internal.audio.id)),this.html.video.available&&(this._addHtmlEventListeners(this.htmlElement.video,this.html.video),this.element.append(this.htmlElement.video),this.internal.video.jq=a("#"+this.internal.video.id),this.internal.video.jq.css(this.status.nativeVideoControls?{width:this.status.width,height:this.status.height}:{width:"0px",height:"0px"}),this.internal.video.jq.bind("click.jPlayer",function(){c._trigger(a.jPlayer.event.click)}))),this.aurora.used,this.options.emulateHtml&&this._emulateHtmlBridge(),!this.html.used&&!this.aurora.used||this.flash.used||setTimeout(function(){c.internal.ready=!0,c.version.flash="n/a",c._trigger(a.jPlayer.event.repeat),c._trigger(a.jPlayer.event.ready)},100),this._updateNativeVideoControls(),this.css.jq.videoPlay.length&&this.css.jq.videoPlay.hide(),a.jPlayer.prototype.count++},destroy:function(){this.clearMedia(),this._removeUiClass(),this.css.jq.currentTime.length&&this.css.jq.currentTime.text(""),this.css.jq.duration.length&&this.css.jq.duration.text(""),a.each(this.css.jq,function(a,b){b.length&&b.unbind(".jPlayer")}),this.internal.poster.jq.unbind(".jPlayer"),this.internal.video.jq&&this.internal.video.jq.unbind(".jPlayer"),this._fullscreenRemoveEventListeners(),this===a.jPlayer.focus&&(a.jPlayer.focus=null),this.options.emulateHtml&&this._destroyHtmlBridge(),this.element.removeData("jPlayer"),this.element.unbind(".jPlayer"),this.element.empty(),delete this.instances[this.internal.instance]},destroyRemoved:function(){var b=this;a.each(this.instances,function(a,c){b.element!==c&&(c.data("jPlayer")||(c.jPlayer("destroy"),delete b.instances[a]))})},enable:function(){},disable:function(){},_testCanPlayType:function(a){try{return a.canPlayType(this.format.mp3.codec),!0}catch(b){return!1}},_testPlaybackRate:function(a){var b,c=.5;a="string"==typeof a?a:"audio",b=document.createElement(a);try{return"playbackRate"in b?(b.playbackRate=c,b.playbackRate===c):!1}catch(d){return!1}},_uaBlocklist:function(b){var c=navigator.userAgent.toLowerCase(),d=!1;return a.each(b,function(a,b){return b&&b.test(c)?(d=!0,!1):void 0}),d},_restrictNativeVideoControls:function(){this.require.audio&&this.status.nativeVideoControls&&(this.status.nativeVideoControls=!1,this.status.noFullWindow=!0)},_updateNativeVideoControls:function(){this.html.video.available&&this.html.used&&(this.htmlElement.video.controls=this.status.nativeVideoControls,this._updateAutohide(),this.status.nativeVideoControls&&this.require.video?(this.internal.poster.jq.hide(),this.internal.video.jq.css({width:this.status.width,height:this.status.height})):this.status.waitForPlay&&this.status.video&&(this.internal.poster.jq.show(),this.internal.video.jq.css({width:"0px",height:"0px"})))},_addHtmlEventListeners:function(b,c){var d=this;b.preload=this.options.preload,b.muted=this.options.muted,b.volume=this.options.volume,this.status.playbackRateEnabled&&(b.defaultPlaybackRate=this.options.defaultPlaybackRate,b.playbackRate=this.options.playbackRate),b.addEventListener("progress",function(){c.gate&&(d.internal.cmdsIgnored&&this.readyState>0&&(d.internal.cmdsIgnored=!1),d._getHtmlStatus(b),d._updateInterface(),d._trigger(a.jPlayer.event.progress))},!1),b.addEventListener("loadeddata",function(){c.gate&&(d.androidFix.setMedia=!1,d.androidFix.play&&(d.androidFix.play=!1,d.play(d.androidFix.time)),d.androidFix.pause&&(d.androidFix.pause=!1,d.pause(d.androidFix.time)),d._trigger(a.jPlayer.event.loadeddata))},!1),b.addEventListener("timeupdate",function(){c.gate&&(d._getHtmlStatus(b),d._updateInterface(),d._trigger(a.jPlayer.event.timeupdate))},!1),b.addEventListener("durationchange",function(){c.gate&&(d._getHtmlStatus(b),d._updateInterface(),d._trigger(a.jPlayer.event.durationchange))},!1),b.addEventListener("play",function(){c.gate&&(d._updateButtons(!0),d._html_checkWaitForPlay(),d._trigger(a.jPlayer.event.play))},!1),b.addEventListener("playing",function(){c.gate&&(d._updateButtons(!0),d._seeked(),d._trigger(a.jPlayer.event.playing))},!1),b.addEventListener("pause",function(){c.gate&&(d._updateButtons(!1),d._trigger(a.jPlayer.event.pause))},!1),b.addEventListener("waiting",function(){c.gate&&(d._seeking(),d._trigger(a.jPlayer.event.waiting))},!1),b.addEventListener("seeking",function(){c.gate&&(d._seeking(),d._trigger(a.jPlayer.event.seeking))},!1),b.addEventListener("seeked",function(){c.gate&&(d._seeked(),d._trigger(a.jPlayer.event.seeked))},!1),b.addEventListener("volumechange",function(){c.gate&&(d.options.volume=b.volume,d.options.muted=b.muted,d._updateMute(),d._updateVolume(),d._trigger(a.jPlayer.event.volumechange))},!1),b.addEventListener("ratechange",function(){c.gate&&(d.options.defaultPlaybackRate=b.defaultPlaybackRate,d.options.playbackRate=b.playbackRate,d._updatePlaybackRate(),d._trigger(a.jPlayer.event.ratechange))},!1),b.addEventListener("suspend",function(){c.gate&&(d._seeked(),d._trigger(a.jPlayer.event.suspend))},!1),b.addEventListener("ended",function(){c.gate&&(a.jPlayer.browser.webkit||(d.htmlElement.media.currentTime=0),d.htmlElement.media.pause(),d._updateButtons(!1),d._getHtmlStatus(b,!0),d._updateInterface(),d._trigger(a.jPlayer.event.ended))},!1),b.addEventListener("error",function(){c.gate&&(d._updateButtons(!1),d._seeked(),d.status.srcSet&&(clearTimeout(d.internal.htmlDlyCmdId),d.status.waitForLoad=!0,d.status.waitForPlay=!0,d.status.video&&!d.status.nativeVideoControls&&d.internal.video.jq.css({width:"0px",height:"0px"}),d._validString(d.status.media.poster)&&!d.status.nativeVideoControls&&d.internal.poster.jq.show(),d.css.jq.videoPlay.length&&d.css.jq.videoPlay.show(),d._error({type:a.jPlayer.error.URL,context:d.status.src,message:a.jPlayer.errorMsg.URL,hint:a.jPlayer.errorHint.URL})))},!1),a.each(a.jPlayer.htmlEvent,function(e,f){b.addEventListener(this,function(){c.gate&&d._trigger(a.jPlayer.event[f])},!1)})},_addAuroraEventListeners:function(b,c){var d=this;b.volume=100*this.options.volume,b.on("progress",function(){c.gate&&(d.internal.cmdsIgnored&&this.readyState>0&&(d.internal.cmdsIgnored=!1),d._getAuroraStatus(b),d._updateInterface(),d._trigger(a.jPlayer.event.progress),b.duration>0&&d._trigger(a.jPlayer.event.timeupdate))},!1),b.on("ready",function(){c.gate&&d._trigger(a.jPlayer.event.loadeddata)},!1),b.on("duration",function(){c.gate&&(d._getAuroraStatus(b),d._updateInterface(),d._trigger(a.jPlayer.event.durationchange))},!1),b.on("end",function(){c.gate&&(d._updateButtons(!1),d._getAuroraStatus(b,!0),d._updateInterface(),d._trigger(a.jPlayer.event.ended))},!1),b.on("error",function(){c.gate&&(d._updateButtons(!1),d._seeked(),d.status.srcSet&&(d.status.waitForLoad=!0,d.status.waitForPlay=!0,d.status.video&&!d.status.nativeVideoControls&&d.internal.video.jq.css({width:"0px",height:"0px"}),d._validString(d.status.media.poster)&&!d.status.nativeVideoControls&&d.internal.poster.jq.show(),d.css.jq.videoPlay.length&&d.css.jq.videoPlay.show(),d._error({type:a.jPlayer.error.URL,context:d.status.src,message:a.jPlayer.errorMsg.URL,hint:a.jPlayer.errorHint.URL})))},!1)},_getHtmlStatus:function(a,b){var c=0,d=0,e=0,f=0;isFinite(a.duration)&&(this.status.duration=a.duration),c=a.currentTime,d=this.status.duration>0?100*c/this.status.duration:0,"object"==typeof a.seekable&&a.seekable.length>0?(e=this.status.duration>0?100*a.seekable.end(a.seekable.length-1)/this.status.duration:100,f=this.status.duration>0?100*a.currentTime/a.seekable.end(a.seekable.length-1):0):(e=100,f=d),b&&(c=0,f=0,d=0),this.status.seekPercent=e,this.status.currentPercentRelative=f,this.status.currentPercentAbsolute=d,this.status.currentTime=c,this.status.remaining=this.status.duration-this.status.currentTime,this.status.videoWidth=a.videoWidth,this.status.videoHeight=a.videoHeight,this.status.readyState=a.readyState,this.status.networkState=a.networkState,this.status.playbackRate=a.playbackRate,this.status.ended=a.ended},_getAuroraStatus:function(a,b){var c=0,d=0,e=0,f=0;this.status.duration=a.duration/1e3,c=a.currentTime/1e3,d=this.status.duration>0?100*c/this.status.duration:0,a.buffered>0?(e=this.status.duration>0?a.buffered*this.status.duration/this.status.duration:100,f=this.status.duration>0?c/(a.buffered*this.status.duration):0):(e=100,f=d),b&&(c=0,f=0,d=0),this.status.seekPercent=e,this.status.currentPercentRelative=f,this.status.currentPercentAbsolute=d,this.status.currentTime=c,this.status.remaining=this.status.duration-this.status.currentTime,this.status.readyState=4,this.status.networkState=0,this.status.playbackRate=1,this.status.ended=!1},_resetStatus:function(){this.status=a.extend({},this.status,a.jPlayer.prototype.status)},_trigger:function(b,c,d){var e=a.Event(b);e.jPlayer={},e.jPlayer.version=a.extend({},this.version),e.jPlayer.options=a.extend(!0,{},this.options),e.jPlayer.status=a.extend(!0,{},this.status),e.jPlayer.html=a.extend(!0,{},this.html),e.jPlayer.aurora=a.extend(!0,{},this.aurora),e.jPlayer.flash=a.extend(!0,{},this.flash),c&&(e.jPlayer.error=a.extend({},c)),d&&(e.jPlayer.warning=a.extend({},d)),this.element.trigger(e)},jPlayerFlashEvent:function(b,c){if(b===a.jPlayer.event.ready)if(this.internal.ready){if(this.flash.gate){if(this.status.srcSet){var d=this.status.currentTime,e=this.status.paused;this.setMedia(this.status.media),this.volumeWorker(this.options.volume),d>0&&(e?this.pause(d):this.play(d))}this._trigger(a.jPlayer.event.flashreset)}}else this.internal.ready=!0,this.internal.flash.jq.css({width:"0px",height:"0px"}),this.version.flash=c.version,this.version.needFlash!==this.version.flash&&this._error({type:a.jPlayer.error.VERSION,context:this.version.flash,message:a.jPlayer.errorMsg.VERSION+this.version.flash,hint:a.jPlayer.errorHint.VERSION}),this._trigger(a.jPlayer.event.repeat),this._trigger(b);if(this.flash.gate)switch(b){case a.jPlayer.event.progress:this._getFlashStatus(c),this._updateInterface(),this._trigger(b);break;case a.jPlayer.event.timeupdate:this._getFlashStatus(c),this._updateInterface(),this._trigger(b);break;case a.jPlayer.event.play:this._seeked(),this._updateButtons(!0),this._trigger(b);break;case a.jPlayer.event.pause:this._updateButtons(!1),this._trigger(b);break;case a.jPlayer.event.ended:this._updateButtons(!1),this._trigger(b);break;case a.jPlayer.event.click:this._trigger(b);break;case a.jPlayer.event.error:this.status.waitForLoad=!0,this.status.waitForPlay=!0,this.status.video&&this.internal.flash.jq.css({width:"0px",height:"0px"}),this._validString(this.status.media.poster)&&this.internal.poster.jq.show(),this.css.jq.videoPlay.length&&this.status.video&&this.css.jq.videoPlay.show(),this.status.video?this._flash_setVideo(this.status.media):this._flash_setAudio(this.status.media),this._updateButtons(!1),this._error({type:a.jPlayer.error.URL,context:c.src,message:a.jPlayer.errorMsg.URL,hint:a.jPlayer.errorHint.URL});break;case a.jPlayer.event.seeking:this._seeking(),this._trigger(b);break;case a.jPlayer.event.seeked:this._seeked(),this._trigger(b);break;case a.jPlayer.event.ready:break;default:this._trigger(b)}return!1},_getFlashStatus:function(a){this.status.seekPercent=a.seekPercent,this.status.currentPercentRelative=a.currentPercentRelative,this.status.currentPercentAbsolute=a.currentPercentAbsolute,this.status.currentTime=a.currentTime,this.status.duration=a.duration,this.status.remaining=a.duration-a.currentTime,this.status.videoWidth=a.videoWidth,this.status.videoHeight=a.videoHeight,this.status.readyState=4,this.status.networkState=0,this.status.playbackRate=1,this.status.ended=!1},_updateButtons:function(a){a===b?a=!this.status.paused:this.status.paused=!a,a?this.addStateClass("playing"):this.removeStateClass("playing"),!this.status.noFullWindow&&this.options.fullWindow?this.addStateClass("fullScreen"):this.removeStateClass("fullScreen"),this.options.loop?this.addStateClass("looped"):this.removeStateClass("looped"),this.css.jq.play.length&&this.css.jq.pause.length&&(a?(this.css.jq.play.hide(),this.css.jq.pause.show()):(this.css.jq.play.show(),this.css.jq.pause.hide())),this.css.jq.restoreScreen.length&&this.css.jq.fullScreen.length&&(this.status.noFullWindow?(this.css.jq.fullScreen.hide(),this.css.jq.restoreScreen.hide()):this.options.fullWindow?(this.css.jq.fullScreen.hide(),this.css.jq.restoreScreen.show()):(this.css.jq.fullScreen.show(),this.css.jq.restoreScreen.hide())),this.css.jq.repeat.length&&this.css.jq.repeatOff.length&&(this.options.loop?(this.css.jq.repeat.hide(),this.css.jq.repeatOff.show()):(this.css.jq.repeat.show(),this.css.jq.repeatOff.hide()))},_updateInterface:function(){this.css.jq.seekBar.length&&this.css.jq.seekBar.width(this.status.seekPercent+"%"),this.css.jq.playBar.length&&(this.options.smoothPlayBar?this.css.jq.playBar.stop().animate({width:this.status.currentPercentAbsolute+"%"},250,"linear"):this.css.jq.playBar.width(this.status.currentPercentRelative+"%"));var a="";this.css.jq.currentTime.length&&(a=this._convertTime(this.status.currentTime),a!==this.css.jq.currentTime.text()&&this.css.jq.currentTime.text(this._convertTime(this.status.currentTime)));var b="",c=this.status.duration,d=this.status.remaining;this.css.jq.duration.length&&("string"==typeof this.status.media.duration?b=this.status.media.duration:("number"==typeof this.status.media.duration&&(c=this.status.media.duration,d=c-this.status.currentTime),b=this.options.remainingDuration?(d>0?"-":"")+this._convertTime(d):this._convertTime(c)),b!==this.css.jq.duration.text()&&this.css.jq.duration.text(b))},_convertTime:c.prototype.time,_seeking:function(){this.css.jq.seekBar.length&&this.css.jq.seekBar.addClass("jp-seeking-bg"),this.addStateClass("seeking")},_seeked:function(){this.css.jq.seekBar.length&&this.css.jq.seekBar.removeClass("jp-seeking-bg"),this.removeStateClass("seeking")},_resetGate:function(){this.html.audio.gate=!1,this.html.video.gate=!1,this.aurora.gate=!1,this.flash.gate=!1},_resetActive:function(){this.html.active=!1,this.aurora.active=!1,this.flash.active=!1},_escapeHtml:function(a){return a.split("&").join("&").split("<").join("<").split(">").join(">").split('"').join(""")},_qualifyURL:function(a){var b=document.createElement("div"); -return b.innerHTML='<a href="'+this._escapeHtml(a)+'">x</a>',b.firstChild.href},_absoluteMediaUrls:function(b){var c=this;return a.each(b,function(a,d){d&&c.format[a]&&"data:"!==d.substr(0,5)&&(b[a]=c._qualifyURL(d))}),b},addStateClass:function(a){this.ancestorJq.length&&this.ancestorJq.addClass(this.options.stateClass[a])},removeStateClass:function(a){this.ancestorJq.length&&this.ancestorJq.removeClass(this.options.stateClass[a])},setMedia:function(b){var c=this,d=!1,e=this.status.media.poster!==b.poster;this._resetMedia(),this._resetGate(),this._resetActive(),this.androidFix.setMedia=!1,this.androidFix.play=!1,this.androidFix.pause=!1,b=this._absoluteMediaUrls(b),a.each(this.formats,function(e,f){var g="video"===c.format[f].media;return a.each(c.solutions,function(e,h){if(c[h].support[f]&&c._validString(b[f])){var i="html"===h,j="aurora"===h;return g?(i?(c.html.video.gate=!0,c._html_setVideo(b),c.html.active=!0):(c.flash.gate=!0,c._flash_setVideo(b),c.flash.active=!0),c.css.jq.videoPlay.length&&c.css.jq.videoPlay.show(),c.status.video=!0):(i?(c.html.audio.gate=!0,c._html_setAudio(b),c.html.active=!0,a.jPlayer.platform.android&&(c.androidFix.setMedia=!0)):j?(c.aurora.gate=!0,c._aurora_setAudio(b),c.aurora.active=!0):(c.flash.gate=!0,c._flash_setAudio(b),c.flash.active=!0),c.css.jq.videoPlay.length&&c.css.jq.videoPlay.hide(),c.status.video=!1),d=!0,!1}}),d?!1:void 0}),d?(this.status.nativeVideoControls&&this.html.video.gate||this._validString(b.poster)&&(e?this.htmlElement.poster.src=b.poster:this.internal.poster.jq.show()),"string"==typeof b.title&&(this.css.jq.title.length&&this.css.jq.title.html(b.title),this.htmlElement.audio&&this.htmlElement.audio.setAttribute("title",b.title),this.htmlElement.video&&this.htmlElement.video.setAttribute("title",b.title)),this.status.srcSet=!0,this.status.media=a.extend({},b),this._updateButtons(!1),this._updateInterface(),this._trigger(a.jPlayer.event.setmedia)):this._error({type:a.jPlayer.error.NO_SUPPORT,context:"{supplied:'"+this.options.supplied+"'}",message:a.jPlayer.errorMsg.NO_SUPPORT,hint:a.jPlayer.errorHint.NO_SUPPORT})},_resetMedia:function(){this._resetStatus(),this._updateButtons(!1),this._updateInterface(),this._seeked(),this.internal.poster.jq.hide(),clearTimeout(this.internal.htmlDlyCmdId),this.html.active?this._html_resetMedia():this.aurora.active?this._aurora_resetMedia():this.flash.active&&this._flash_resetMedia()},clearMedia:function(){this._resetMedia(),this.html.active?this._html_clearMedia():this.aurora.active?this._aurora_clearMedia():this.flash.active&&this._flash_clearMedia(),this._resetGate(),this._resetActive()},load:function(){this.status.srcSet?this.html.active?this._html_load():this.aurora.active?this._aurora_load():this.flash.active&&this._flash_load():this._urlNotSetError("load")},focus:function(){this.options.keyEnabled&&(a.jPlayer.focus=this)},play:function(a){var b="object"==typeof a;b&&this.options.useStateClassSkin&&!this.status.paused?this.pause(a):(a="number"==typeof a?a:0/0,this.status.srcSet?(this.focus(),this.html.active?this._html_play(a):this.aurora.active?this._aurora_play(a):this.flash.active&&this._flash_play(a)):this._urlNotSetError("play"))},videoPlay:function(){this.play()},pause:function(a){a="number"==typeof a?a:0/0,this.status.srcSet?this.html.active?this._html_pause(a):this.aurora.active?this._aurora_pause(a):this.flash.active&&this._flash_pause(a):this._urlNotSetError("pause")},tellOthers:function(b,c){var d=this,e="function"==typeof c,f=Array.prototype.slice.call(arguments);"string"==typeof b&&(e&&f.splice(1,1),a.jPlayer.prototype.destroyRemoved(),a.each(this.instances,function(){d.element!==this&&(!e||c.call(this.data("jPlayer"),d))&&this.jPlayer.apply(this,f)}))},pauseOthers:function(a){this.tellOthers("pause",function(){return this.status.srcSet},a)},stop:function(){this.status.srcSet?this.html.active?this._html_pause(0):this.aurora.active?this._aurora_pause(0):this.flash.active&&this._flash_pause(0):this._urlNotSetError("stop")},playHead:function(a){a=this._limitValue(a,0,100),this.status.srcSet?this.html.active?this._html_playHead(a):this.aurora.active?this._aurora_playHead(a):this.flash.active&&this._flash_playHead(a):this._urlNotSetError("playHead")},_muted:function(a){this.mutedWorker(a),this.options.globalVolume&&this.tellOthers("mutedWorker",function(){return this.options.globalVolume},a)},mutedWorker:function(b){this.options.muted=b,this.html.used&&this._html_setProperty("muted",b),this.aurora.used&&this._aurora_mute(b),this.flash.used&&this._flash_mute(b),this.html.video.gate||this.html.audio.gate||(this._updateMute(b),this._updateVolume(this.options.volume),this._trigger(a.jPlayer.event.volumechange))},mute:function(a){var c="object"==typeof a;c&&this.options.useStateClassSkin&&this.options.muted?this._muted(!1):(a=a===b?!0:!!a,this._muted(a))},unmute:function(a){a=a===b?!0:!!a,this._muted(!a)},_updateMute:function(a){a===b&&(a=this.options.muted),a?this.addStateClass("muted"):this.removeStateClass("muted"),this.css.jq.mute.length&&this.css.jq.unmute.length&&(this.status.noVolume?(this.css.jq.mute.hide(),this.css.jq.unmute.hide()):a?(this.css.jq.mute.hide(),this.css.jq.unmute.show()):(this.css.jq.mute.show(),this.css.jq.unmute.hide()))},volume:function(a){this.volumeWorker(a),this.options.globalVolume&&this.tellOthers("volumeWorker",function(){return this.options.globalVolume},a)},volumeWorker:function(b){b=this._limitValue(b,0,1),this.options.volume=b,this.html.used&&this._html_setProperty("volume",b),this.aurora.used&&this._aurora_volume(b),this.flash.used&&this._flash_volume(b),this.html.video.gate||this.html.audio.gate||(this._updateVolume(b),this._trigger(a.jPlayer.event.volumechange))},volumeBar:function(b){if(this.css.jq.volumeBar.length){var c=a(b.currentTarget),d=c.offset(),e=b.pageX-d.left,f=c.width(),g=c.height()-b.pageY+d.top,h=c.height();this.volume(this.options.verticalVolume?g/h:e/f)}this.options.muted&&this._muted(!1)},_updateVolume:function(a){a===b&&(a=this.options.volume),a=this.options.muted?0:a,this.status.noVolume?(this.addStateClass("noVolume"),this.css.jq.volumeBar.length&&this.css.jq.volumeBar.hide(),this.css.jq.volumeBarValue.length&&this.css.jq.volumeBarValue.hide(),this.css.jq.volumeMax.length&&this.css.jq.volumeMax.hide()):(this.removeStateClass("noVolume"),this.css.jq.volumeBar.length&&this.css.jq.volumeBar.show(),this.css.jq.volumeBarValue.length&&(this.css.jq.volumeBarValue.show(),this.css.jq.volumeBarValue[this.options.verticalVolume?"height":"width"](100*a+"%")),this.css.jq.volumeMax.length&&this.css.jq.volumeMax.show())},volumeMax:function(){this.volume(1),this.options.muted&&this._muted(!1)},_cssSelectorAncestor:function(b){var c=this;this.options.cssSelectorAncestor=b,this._removeUiClass(),this.ancestorJq=b?a(b):[],b&&1!==this.ancestorJq.length&&this._warning({type:a.jPlayer.warning.CSS_SELECTOR_COUNT,context:b,message:a.jPlayer.warningMsg.CSS_SELECTOR_COUNT+this.ancestorJq.length+" found for cssSelectorAncestor.",hint:a.jPlayer.warningHint.CSS_SELECTOR_COUNT}),this._addUiClass(),a.each(this.options.cssSelector,function(a,b){c._cssSelector(a,b)}),this._updateInterface(),this._updateButtons(),this._updateAutohide(),this._updateVolume(),this._updateMute()},_cssSelector:function(b,c){var d=this;if("string"==typeof c)if(a.jPlayer.prototype.options.cssSelector[b]){if(this.css.jq[b]&&this.css.jq[b].length&&this.css.jq[b].unbind(".jPlayer"),this.options.cssSelector[b]=c,this.css.cs[b]=this.options.cssSelectorAncestor+" "+c,this.css.jq[b]=c?a(this.css.cs[b]):[],this.css.jq[b].length&&this[b]){var e=function(c){c.preventDefault(),d[b](c),d.options.autoBlur?a(this).blur():a(this).focus()};this.css.jq[b].bind("click.jPlayer",e)}c&&1!==this.css.jq[b].length&&this._warning({type:a.jPlayer.warning.CSS_SELECTOR_COUNT,context:this.css.cs[b],message:a.jPlayer.warningMsg.CSS_SELECTOR_COUNT+this.css.jq[b].length+" found for "+b+" method.",hint:a.jPlayer.warningHint.CSS_SELECTOR_COUNT})}else this._warning({type:a.jPlayer.warning.CSS_SELECTOR_METHOD,context:b,message:a.jPlayer.warningMsg.CSS_SELECTOR_METHOD,hint:a.jPlayer.warningHint.CSS_SELECTOR_METHOD});else this._warning({type:a.jPlayer.warning.CSS_SELECTOR_STRING,context:c,message:a.jPlayer.warningMsg.CSS_SELECTOR_STRING,hint:a.jPlayer.warningHint.CSS_SELECTOR_STRING})},duration:function(a){this.options.toggleDuration&&(this.options.captureDuration&&a.stopPropagation(),this._setOption("remainingDuration",!this.options.remainingDuration))},seekBar:function(b){if(this.css.jq.seekBar.length){var c=a(b.currentTarget),d=c.offset(),e=b.pageX-d.left,f=c.width(),g=100*e/f;this.playHead(g)}},playbackRate:function(a){this._setOption("playbackRate",a)},playbackRateBar:function(b){if(this.css.jq.playbackRateBar.length){var c,d,e=a(b.currentTarget),f=e.offset(),g=b.pageX-f.left,h=e.width(),i=e.height()-b.pageY+f.top,j=e.height();c=this.options.verticalPlaybackRate?i/j:g/h,d=c*(this.options.maxPlaybackRate-this.options.minPlaybackRate)+this.options.minPlaybackRate,this.playbackRate(d)}},_updatePlaybackRate:function(){var a=this.options.playbackRate,b=(a-this.options.minPlaybackRate)/(this.options.maxPlaybackRate-this.options.minPlaybackRate);this.status.playbackRateEnabled?(this.css.jq.playbackRateBar.length&&this.css.jq.playbackRateBar.show(),this.css.jq.playbackRateBarValue.length&&(this.css.jq.playbackRateBarValue.show(),this.css.jq.playbackRateBarValue[this.options.verticalPlaybackRate?"height":"width"](100*b+"%"))):(this.css.jq.playbackRateBar.length&&this.css.jq.playbackRateBar.hide(),this.css.jq.playbackRateBarValue.length&&this.css.jq.playbackRateBarValue.hide())},repeat:function(a){var b="object"==typeof a;this._loop(b&&this.options.useStateClassSkin&&this.options.loop?!1:!0)},repeatOff:function(){this._loop(!1)},_loop:function(b){this.options.loop!==b&&(this.options.loop=b,this._updateButtons(),this._trigger(a.jPlayer.event.repeat))},option:function(c,d){var e=c;if(0===arguments.length)return a.extend(!0,{},this.options);if("string"==typeof c){var f=c.split(".");if(d===b){for(var g=a.extend(!0,{},this.options),h=0;h<f.length;h++){if(g[f[h]]===b)return this._warning({type:a.jPlayer.warning.OPTION_KEY,context:c,message:a.jPlayer.warningMsg.OPTION_KEY,hint:a.jPlayer.warningHint.OPTION_KEY}),b;g=g[f[h]]}return g}e={};for(var i=e,j=0;j<f.length;j++)j<f.length-1?(i[f[j]]={},i=i[f[j]]):i[f[j]]=d}return this._setOptions(e),this},_setOptions:function(b){var c=this;return a.each(b,function(a,b){c._setOption(a,b)}),this},_setOption:function(b,c){var d=this;switch(b){case"volume":this.volume(c);break;case"muted":this._muted(c);break;case"globalVolume":this.options[b]=c;break;case"cssSelectorAncestor":this._cssSelectorAncestor(c);break;case"cssSelector":a.each(c,function(a,b){d._cssSelector(a,b)});break;case"playbackRate":this.options[b]=c=this._limitValue(c,this.options.minPlaybackRate,this.options.maxPlaybackRate),this.html.used&&this._html_setProperty("playbackRate",c),this._updatePlaybackRate();break;case"defaultPlaybackRate":this.options[b]=c=this._limitValue(c,this.options.minPlaybackRate,this.options.maxPlaybackRate),this.html.used&&this._html_setProperty("defaultPlaybackRate",c),this._updatePlaybackRate();break;case"minPlaybackRate":this.options[b]=c=this._limitValue(c,.1,this.options.maxPlaybackRate-.1),this._updatePlaybackRate();break;case"maxPlaybackRate":this.options[b]=c=this._limitValue(c,this.options.minPlaybackRate+.1,16),this._updatePlaybackRate();break;case"fullScreen":if(this.options[b]!==c){var e=a.jPlayer.nativeFeatures.fullscreen.used.webkitVideo;(!e||e&&!this.status.waitForPlay)&&(e||(this.options[b]=c),c?this._requestFullscreen():this._exitFullscreen(),e||this._setOption("fullWindow",c))}break;case"fullWindow":this.options[b]!==c&&(this._removeUiClass(),this.options[b]=c,this._refreshSize());break;case"size":this.options.fullWindow||this.options[b].cssClass===c.cssClass||this._removeUiClass(),this.options[b]=a.extend({},this.options[b],c),this._refreshSize();break;case"sizeFull":this.options.fullWindow&&this.options[b].cssClass!==c.cssClass&&this._removeUiClass(),this.options[b]=a.extend({},this.options[b],c),this._refreshSize();break;case"autohide":this.options[b]=a.extend({},this.options[b],c),this._updateAutohide();break;case"loop":this._loop(c);break;case"remainingDuration":this.options[b]=c,this._updateInterface();break;case"toggleDuration":this.options[b]=c;break;case"nativeVideoControls":this.options[b]=a.extend({},this.options[b],c),this.status.nativeVideoControls=this._uaBlocklist(this.options.nativeVideoControls),this._restrictNativeVideoControls(),this._updateNativeVideoControls();break;case"noFullWindow":this.options[b]=a.extend({},this.options[b],c),this.status.nativeVideoControls=this._uaBlocklist(this.options.nativeVideoControls),this.status.noFullWindow=this._uaBlocklist(this.options.noFullWindow),this._restrictNativeVideoControls(),this._updateButtons();break;case"noVolume":this.options[b]=a.extend({},this.options[b],c),this.status.noVolume=this._uaBlocklist(this.options.noVolume),this._updateVolume(),this._updateMute();break;case"emulateHtml":this.options[b]!==c&&(this.options[b]=c,c?this._emulateHtmlBridge():this._destroyHtmlBridge());break;case"timeFormat":this.options[b]=a.extend({},this.options[b],c);break;case"keyEnabled":this.options[b]=c,c||this!==a.jPlayer.focus||(a.jPlayer.focus=null);break;case"keyBindings":this.options[b]=a.extend(!0,{},this.options[b],c);break;case"audioFullScreen":this.options[b]=c;break;case"autoBlur":this.options[b]=c}return this},_refreshSize:function(){this._setSize(),this._addUiClass(),this._updateSize(),this._updateButtons(),this._updateAutohide(),this._trigger(a.jPlayer.event.resize)},_setSize:function(){this.options.fullWindow?(this.status.width=this.options.sizeFull.width,this.status.height=this.options.sizeFull.height,this.status.cssClass=this.options.sizeFull.cssClass):(this.status.width=this.options.size.width,this.status.height=this.options.size.height,this.status.cssClass=this.options.size.cssClass),this.element.css({width:this.status.width,height:this.status.height})},_addUiClass:function(){this.ancestorJq.length&&this.ancestorJq.addClass(this.status.cssClass)},_removeUiClass:function(){this.ancestorJq.length&&this.ancestorJq.removeClass(this.status.cssClass)},_updateSize:function(){this.internal.poster.jq.css({width:this.status.width,height:this.status.height}),!this.status.waitForPlay&&this.html.active&&this.status.video||this.html.video.available&&this.html.used&&this.status.nativeVideoControls?this.internal.video.jq.css({width:this.status.width,height:this.status.height}):!this.status.waitForPlay&&this.flash.active&&this.status.video&&this.internal.flash.jq.css({width:this.status.width,height:this.status.height})},_updateAutohide:function(){var a=this,b="mousemove.jPlayer",c=".jPlayerAutohide",d=b+c,e=function(b){var c,d,e=!1;"undefined"!=typeof a.internal.mouse?(c=a.internal.mouse.x-b.pageX,d=a.internal.mouse.y-b.pageY,e=Math.floor(c)>0||Math.floor(d)>0):e=!0,a.internal.mouse={x:b.pageX,y:b.pageY},e&&a.css.jq.gui.fadeIn(a.options.autohide.fadeIn,function(){clearTimeout(a.internal.autohideId),a.internal.autohideId=setTimeout(function(){a.css.jq.gui.fadeOut(a.options.autohide.fadeOut)},a.options.autohide.hold)})};this.css.jq.gui.length&&(this.css.jq.gui.stop(!0,!0),clearTimeout(this.internal.autohideId),delete this.internal.mouse,this.element.unbind(c),this.css.jq.gui.unbind(c),this.status.nativeVideoControls?this.css.jq.gui.hide():this.options.fullWindow&&this.options.autohide.full||!this.options.fullWindow&&this.options.autohide.restored?(this.element.bind(d,e),this.css.jq.gui.bind(d,e),this.css.jq.gui.hide()):this.css.jq.gui.show())},fullScreen:function(a){var b="object"==typeof a;b&&this.options.useStateClassSkin&&this.options.fullScreen?this._setOption("fullScreen",!1):this._setOption("fullScreen",!0)},restoreScreen:function(){this._setOption("fullScreen",!1)},_fullscreenAddEventListeners:function(){var b=this,c=a.jPlayer.nativeFeatures.fullscreen;c.api.fullscreenEnabled&&c.event.fullscreenchange&&("function"!=typeof this.internal.fullscreenchangeHandler&&(this.internal.fullscreenchangeHandler=function(){b._fullscreenchange()}),document.addEventListener(c.event.fullscreenchange,this.internal.fullscreenchangeHandler,!1))},_fullscreenRemoveEventListeners:function(){var b=a.jPlayer.nativeFeatures.fullscreen;this.internal.fullscreenchangeHandler&&document.removeEventListener(b.event.fullscreenchange,this.internal.fullscreenchangeHandler,!1)},_fullscreenchange:function(){this.options.fullScreen&&!a.jPlayer.nativeFeatures.fullscreen.api.fullscreenElement()&&this._setOption("fullScreen",!1)},_requestFullscreen:function(){var b=this.ancestorJq.length?this.ancestorJq[0]:this.element[0],c=a.jPlayer.nativeFeatures.fullscreen;c.used.webkitVideo&&(b=this.htmlElement.video),c.api.fullscreenEnabled&&c.api.requestFullscreen(b)},_exitFullscreen:function(){var b,c=a.jPlayer.nativeFeatures.fullscreen;c.used.webkitVideo&&(b=this.htmlElement.video),c.api.fullscreenEnabled&&c.api.exitFullscreen(b)},_html_initMedia:function(b){var c=a(this.htmlElement.media).empty();a.each(b.track||[],function(a,b){var d=document.createElement("track");d.setAttribute("kind",b.kind?b.kind:""),d.setAttribute("src",b.src?b.src:""),d.setAttribute("srclang",b.srclang?b.srclang:""),d.setAttribute("label",b.label?b.label:""),b.def&&d.setAttribute("default",b.def),c.append(d)}),this.htmlElement.media.src=this.status.src,"none"!==this.options.preload&&this._html_load(),this._trigger(a.jPlayer.event.timeupdate)},_html_setFormat:function(b){var c=this;a.each(this.formats,function(a,d){return c.html.support[d]&&b[d]?(c.status.src=b[d],c.status.format[d]=!0,c.status.formatType=d,!1):void 0})},_html_setAudio:function(a){this._html_setFormat(a),this.htmlElement.media=this.htmlElement.audio,this._html_initMedia(a)},_html_setVideo:function(a){this._html_setFormat(a),this.status.nativeVideoControls&&(this.htmlElement.video.poster=this._validString(a.poster)?a.poster:""),this.htmlElement.media=this.htmlElement.video,this._html_initMedia(a)},_html_resetMedia:function(){this.htmlElement.media&&(this.htmlElement.media.id!==this.internal.video.id||this.status.nativeVideoControls||this.internal.video.jq.css({width:"0px",height:"0px"}),this.htmlElement.media.pause())},_html_clearMedia:function(){this.htmlElement.media&&(this.htmlElement.media.src="about:blank",this.htmlElement.media.load())},_html_load:function(){this.status.waitForLoad&&(this.status.waitForLoad=!1,this.htmlElement.media.load()),clearTimeout(this.internal.htmlDlyCmdId)},_html_play:function(a){var b=this,c=this.htmlElement.media;if(this.androidFix.pause=!1,this._html_load(),this.androidFix.setMedia)this.androidFix.play=!0,this.androidFix.time=a;else if(isNaN(a))c.play();else{this.internal.cmdsIgnored&&c.play();try{if(c.seekable&&!("object"==typeof c.seekable&&c.seekable.length>0))throw 1;c.currentTime=a,c.play()}catch(d){return void(this.internal.htmlDlyCmdId=setTimeout(function(){b.play(a)},250))}}this._html_checkWaitForPlay()},_html_pause:function(a){var b=this,c=this.htmlElement.media;if(this.androidFix.play=!1,a>0?this._html_load():clearTimeout(this.internal.htmlDlyCmdId),c.pause(),this.androidFix.setMedia)this.androidFix.pause=!0,this.androidFix.time=a;else if(!isNaN(a))try{if(c.seekable&&!("object"==typeof c.seekable&&c.seekable.length>0))throw 1;c.currentTime=a}catch(d){return void(this.internal.htmlDlyCmdId=setTimeout(function(){b.pause(a)},250))}a>0&&this._html_checkWaitForPlay()},_html_playHead:function(a){var b=this,c=this.htmlElement.media;this._html_load();try{if("object"==typeof c.seekable&&c.seekable.length>0)c.currentTime=a*c.seekable.end(c.seekable.length-1)/100;else{if(!(c.duration>0)||isNaN(c.duration))throw"e";c.currentTime=a*c.duration/100}}catch(d){return void(this.internal.htmlDlyCmdId=setTimeout(function(){b.playHead(a)},250))}this.status.waitForLoad||this._html_checkWaitForPlay()},_html_checkWaitForPlay:function(){this.status.waitForPlay&&(this.status.waitForPlay=!1,this.css.jq.videoPlay.length&&this.css.jq.videoPlay.hide(),this.status.video&&(this.internal.poster.jq.hide(),this.internal.video.jq.css({width:this.status.width,height:this.status.height})))},_html_setProperty:function(a,b){this.html.audio.available&&(this.htmlElement.audio[a]=b),this.html.video.available&&(this.htmlElement.video[a]=b)},_aurora_setAudio:function(b){var c=this;a.each(this.formats,function(a,d){return c.aurora.support[d]&&b[d]?(c.status.src=b[d],c.status.format[d]=!0,c.status.formatType=d,!1):void 0}),this.aurora.player=new AV.Player.fromURL(this.status.src),this._addAuroraEventListeners(this.aurora.player,this.aurora),"auto"===this.options.preload&&(this._aurora_load(),this.status.waitForLoad=!1)},_aurora_resetMedia:function(){this.aurora.player&&this.aurora.player.stop()},_aurora_clearMedia:function(){},_aurora_load:function(){this.status.waitForLoad&&(this.status.waitForLoad=!1,this.aurora.player.preload())},_aurora_play:function(b){this.status.waitForLoad||isNaN(b)||this.aurora.player.seek(b),this.aurora.player.playing||this.aurora.player.play(),this.status.waitForLoad=!1,this._aurora_checkWaitForPlay(),this._updateButtons(!0),this._trigger(a.jPlayer.event.play)},_aurora_pause:function(b){isNaN(b)||this.aurora.player.seek(1e3*b),this.aurora.player.pause(),b>0&&this._aurora_checkWaitForPlay(),this._updateButtons(!1),this._trigger(a.jPlayer.event.pause)},_aurora_playHead:function(a){this.aurora.player.duration>0&&this.aurora.player.seek(a*this.aurora.player.duration/100),this.status.waitForLoad||this._aurora_checkWaitForPlay()},_aurora_checkWaitForPlay:function(){this.status.waitForPlay&&(this.status.waitForPlay=!1)},_aurora_volume:function(a){this.aurora.player.volume=100*a},_aurora_mute:function(a){a?(this.aurora.properties.lastvolume=this.aurora.player.volume,this.aurora.player.volume=0):this.aurora.player.volume=this.aurora.properties.lastvolume,this.aurora.properties.muted=a},_flash_setAudio:function(b){var c=this;try{a.each(this.formats,function(a,d){if(c.flash.support[d]&&b[d]){switch(d){case"m4a":case"fla":c._getMovie().fl_setAudio_m4a(b[d]);break;case"mp3":c._getMovie().fl_setAudio_mp3(b[d]);break;case"rtmpa":c._getMovie().fl_setAudio_rtmp(b[d])}return c.status.src=b[d],c.status.format[d]=!0,c.status.formatType=d,!1}}),"auto"===this.options.preload&&(this._flash_load(),this.status.waitForLoad=!1)}catch(d){this._flashError(d)}},_flash_setVideo:function(b){var c=this;try{a.each(this.formats,function(a,d){if(c.flash.support[d]&&b[d]){switch(d){case"m4v":case"flv":c._getMovie().fl_setVideo_m4v(b[d]);break;case"rtmpv":c._getMovie().fl_setVideo_rtmp(b[d])}return c.status.src=b[d],c.status.format[d]=!0,c.status.formatType=d,!1}}),"auto"===this.options.preload&&(this._flash_load(),this.status.waitForLoad=!1)}catch(d){this._flashError(d)}},_flash_resetMedia:function(){this.internal.flash.jq.css({width:"0px",height:"0px"}),this._flash_pause(0/0)},_flash_clearMedia:function(){try{this._getMovie().fl_clearMedia()}catch(a){this._flashError(a)}},_flash_load:function(){try{this._getMovie().fl_load()}catch(a){this._flashError(a)}this.status.waitForLoad=!1},_flash_play:function(a){try{this._getMovie().fl_play(a)}catch(b){this._flashError(b)}this.status.waitForLoad=!1,this._flash_checkWaitForPlay()},_flash_pause:function(a){try{this._getMovie().fl_pause(a)}catch(b){this._flashError(b)}a>0&&(this.status.waitForLoad=!1,this._flash_checkWaitForPlay())},_flash_playHead:function(a){try{this._getMovie().fl_play_head(a)}catch(b){this._flashError(b)}this.status.waitForLoad||this._flash_checkWaitForPlay()},_flash_checkWaitForPlay:function(){this.status.waitForPlay&&(this.status.waitForPlay=!1,this.css.jq.videoPlay.length&&this.css.jq.videoPlay.hide(),this.status.video&&(this.internal.poster.jq.hide(),this.internal.flash.jq.css({width:this.status.width,height:this.status.height})))},_flash_volume:function(a){try{this._getMovie().fl_volume(a)}catch(b){this._flashError(b)}},_flash_mute:function(a){try{this._getMovie().fl_mute(a)}catch(b){this._flashError(b)}},_getMovie:function(){return document[this.internal.flash.id]},_getFlashPluginVersion:function(){var a,b=0;if(window.ActiveXObject)try{if(a=new ActiveXObject("ShockwaveFlash.ShockwaveFlash")){var c=a.GetVariable("$version");c&&(c=c.split(" ")[1].split(","),b=parseInt(c[0],10)+"."+parseInt(c[1],10))}}catch(d){}else navigator.plugins&&navigator.mimeTypes.length>0&&(a=navigator.plugins["Shockwave Flash"],a&&(b=navigator.plugins["Shockwave Flash"].description.replace(/.*\s(\d+\.\d+).*/,"$1")));return 1*b},_checkForFlash:function(a){var b=!1;return this._getFlashPluginVersion()>=a&&(b=!0),b},_validString:function(a){return a&&"string"==typeof a},_limitValue:function(a,b,c){return b>a?b:a>c?c:a},_urlNotSetError:function(b){this._error({type:a.jPlayer.error.URL_NOT_SET,context:b,message:a.jPlayer.errorMsg.URL_NOT_SET,hint:a.jPlayer.errorHint.URL_NOT_SET})},_flashError:function(b){var c;c=this.internal.ready?"FLASH_DISABLED":"FLASH",this._error({type:a.jPlayer.error[c],context:this.internal.flash.swf,message:a.jPlayer.errorMsg[c]+b.message,hint:a.jPlayer.errorHint[c]}),this.internal.flash.jq.css({width:"1px",height:"1px"})},_error:function(b){this._trigger(a.jPlayer.event.error,b),this.options.errorAlerts&&this._alert("Error!"+(b.message?"\n"+b.message:"")+(b.hint?"\n"+b.hint:"")+"\nContext: "+b.context)},_warning:function(c){this._trigger(a.jPlayer.event.warning,b,c),this.options.warningAlerts&&this._alert("Warning!"+(c.message?"\n"+c.message:"")+(c.hint?"\n"+c.hint:"")+"\nContext: "+c.context)},_alert:function(a){var b="jPlayer "+this.version.script+" : id='"+this.internal.self.id+"' : "+a;this.options.consoleAlerts?window.console&&window.console.log&&window.console.log(b):alert(b)},_emulateHtmlBridge:function(){var b=this;a.each(a.jPlayer.emulateMethods.split(/\s+/g),function(a,c){b.internal.domNode[c]=function(a){b[c](a)}}),a.each(a.jPlayer.event,function(c,d){var e=!0;a.each(a.jPlayer.reservedEvent.split(/\s+/g),function(a,b){return b===c?(e=!1,!1):void 0}),e&&b.element.bind(d+".jPlayer.jPlayerHtml",function(){b._emulateHtmlUpdate();var a=document.createEvent("Event");a.initEvent(c,!1,!0),b.internal.domNode.dispatchEvent(a)})})},_emulateHtmlUpdate:function(){var b=this;a.each(a.jPlayer.emulateStatus.split(/\s+/g),function(a,c){b.internal.domNode[c]=b.status[c]}),a.each(a.jPlayer.emulateOptions.split(/\s+/g),function(a,c){b.internal.domNode[c]=b.options[c]})},_destroyHtmlBridge:function(){var b=this;this.element.unbind(".jPlayerHtml");var c=a.jPlayer.emulateMethods+" "+a.jPlayer.emulateStatus+" "+a.jPlayer.emulateOptions;a.each(c.split(/\s+/g),function(a,c){delete b.internal.domNode[c]})}},a.jPlayer.error={FLASH:"e_flash",FLASH_DISABLED:"e_flash_disabled",NO_SOLUTION:"e_no_solution",NO_SUPPORT:"e_no_support",URL:"e_url",URL_NOT_SET:"e_url_not_set",VERSION:"e_version"},a.jPlayer.errorMsg={FLASH:"jPlayer's Flash fallback is not configured correctly, or a command was issued before the jPlayer Ready event. Details: ",FLASH_DISABLED:"jPlayer's Flash fallback has been disabled by the browser due to the CSS rules you have used. Details: ",NO_SOLUTION:"No solution can be found by jPlayer in this browser. Neither HTML nor Flash can be used.",NO_SUPPORT:"It is not possible to play any media format provided in setMedia() on this browser using your current options.",URL:"Media URL could not be loaded.",URL_NOT_SET:"Attempt to issue media playback commands, while no media url is set.",VERSION:"jPlayer "+a.jPlayer.prototype.version.script+" needs Jplayer.swf version "+a.jPlayer.prototype.version.needFlash+" but found "},a.jPlayer.errorHint={FLASH:"Check your swfPath option and that Jplayer.swf is there.",FLASH_DISABLED:"Check that you have not display:none; the jPlayer entity or any ancestor.",NO_SOLUTION:"Review the jPlayer options: support and supplied.",NO_SUPPORT:"Video or audio formats defined in the supplied option are missing.",URL:"Check media URL is valid.",URL_NOT_SET:"Use setMedia() to set the media URL.",VERSION:"Update jPlayer files."},a.jPlayer.warning={CSS_SELECTOR_COUNT:"e_css_selector_count",CSS_SELECTOR_METHOD:"e_css_selector_method",CSS_SELECTOR_STRING:"e_css_selector_string",OPTION_KEY:"e_option_key"},a.jPlayer.warningMsg={CSS_SELECTOR_COUNT:"The number of css selectors found did not equal one: ",CSS_SELECTOR_METHOD:"The methodName given in jPlayer('cssSelector') is not a valid jPlayer method.",CSS_SELECTOR_STRING:"The methodCssSelector given in jPlayer('cssSelector') is not a String or is empty.",OPTION_KEY:"The option requested in jPlayer('option') is undefined."},a.jPlayer.warningHint={CSS_SELECTOR_COUNT:"Check your css selector and the ancestor.",CSS_SELECTOR_METHOD:"Check your method name.",CSS_SELECTOR_STRING:"Check your css selector is a string.",OPTION_KEY:"Check your option name."}}); \ No newline at end of file diff --git a/website/agenda/js/jquery.min.js b/website/agenda/js/jquery.min.js index 5fd1339..2c69bc9 100644 --- a/website/agenda/js/jquery.min.js +++ b/website/agenda/js/jquery.min.js @@ -1,6 +1,2 @@ -/*! jQuery v1.12.4 | (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="1.12.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 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!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(n.isPlainObject(c)||(b=n.isArray(c)))?(b?(b=!1,f=a&&n.isArray(a)?a:[]):f=a&&n.isPlainObject(a)?a:{},g[d]=n.extend(j,f,c)):void 0!==c&&(g[d]=c));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||function(a){return"array"===n.type(a)},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},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;try{if(a.constructor&&!k.call(a,"constructor")&&!k.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(!l.ownFirst)for(b in a)return k.call(a,b);for(b in a);return void 0===b||k.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?i[j.call(a)]||"object":typeof a},globalEval:function(b){b&&n.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},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){var d;if(b){if(h)return h.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[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&&(f=a[b],b=a,a=f),n.isFunction(a)?(c=e.call(arguments,2),d=function(){return a.apply(b||this,c.concat(e.call(arguments)))},d.guid=a.guid=a.guid||n.guid++,d):void 0},now:function(){return+new Date},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 n.inArray(a,b)>-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=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;e>b;b++)if(n.contains(d[b],this))return!0}));for(b=0;e>b;b++)n.find(a,d[b],c);return c=this.pushStack(e>1?n.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},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.charAt(0)&&">"===a.charAt(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}if(f=d.getElementById(e[2]),f&&f.parentNode){if(f.id!==e[2])return A.find(a);this.length=1,this[0]=f}return this.context=d,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof 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,c=n(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(n.contains(this,c[b]))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?n.inArray(this[0],n(a)):n.inArray(a.jquery?a[0]:a,this):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){do a=a[b];while(a&&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 n.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document: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]||(e=n.uniqueSort(e)),D.test(a)&&(e=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=!0,c||j.disable(),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.addEventListener?(d.removeEventListener("DOMContentLoaded",K),a.removeEventListener("load",K)):(d.detachEvent("onreadystatechange",K),a.detachEvent("onload",K))}function K(){(d.addEventListener||"load"===a.event.type||"complete"===d.readyState)&&(J(),n.ready())}n.ready.promise=function(b){if(!I)if(I=n.Deferred(),"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll)a.setTimeout(n.ready);else if(d.addEventListener)d.addEventListener("DOMContentLoaded",K),a.addEventListener("load",K);else{d.attachEvent("onreadystatechange",K),a.attachEvent("onload",K);var c=!1;try{c=null==a.frameElement&&d.documentElement}catch(e){}c&&c.doScroll&&!function f(){if(!n.isReady){try{c.doScroll("left")}catch(b){return a.setTimeout(f,50)}J(),n.ready()}}()}return I.promise(b)},n.ready.promise();var L;for(L in n(l))break;l.ownFirst="0"===L,l.inlineBlockNeedsLayout=!1,n(function(){var a,b,c,e;c=d.getElementsByTagName("body")[0],c&&c.style&&(b=d.createElement("div"),e=d.createElement("div"),e.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(e).appendChild(b),"undefined"!=typeof b.style.zoom&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",l.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(e))}),function(){var a=d.createElement("div");l.deleteExpando=!0;try{delete a.test}catch(b){l.deleteExpando=!1}a=null}();var M=function(a){var b=n.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b},N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(O,"-$1").toLowerCase();if(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){}n.data(a,b,c)}else c=void 0; -}return c}function Q(a){var b;for(b in a)if(("data"!==b||!n.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function R(a,b,d,e){if(M(a)){var f,g,h=n.expando,i=a.nodeType,j=i?n.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||n.guid++:h),j[k]||(j[k]=i?{}:{toJSON:n.noop}),"object"!=typeof b&&"function"!=typeof b||(e?j[k]=n.extend(j[k],b):j[k].data=n.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[n.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[n.camelCase(b)])):f=g,f}}function S(a,b,c){if(M(a)){var d,e,f=a.nodeType,g=f?n.cache:a,h=f?a[n.expando]:n.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){n.isArray(b)?b=b.concat(n.map(b,n.camelCase)):b in d?b=[b]:(b=n.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!Q(d):!n.isEmptyObject(d))return}(c||(delete g[h].data,Q(g[h])))&&(f?n.cleanData([a],!0):l.deleteExpando||g!=g.window?delete g[h]:g[h]=void 0)}}}n.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?n.cache[a[n.expando]]:a[n.expando],!!a&&!Q(a)},data:function(a,b,c){return R(a,b,c)},removeData:function(a,b){return S(a,b)},_data:function(a,b,c){return R(a,b,c,!0)},_removeData:function(a,b){return S(a,b,!0)}}),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=n.data(f),1===f.nodeType&&!n._data(f,"parsedAttrs"))){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])));n._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){n.data(this,a)}):arguments.length>1?this.each(function(){n.data(this,a,b)}):f?P(f,a,n.data(f,a)):void 0},removeData:function(a){return this.each(function(){n.removeData(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=n._data(a,b),c&&(!d||n.isArray(c)?d=n._data(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._data(a,c)||n._data(a,c,{empty:n.Callbacks("once memory").add(function(){n._removeData(a,b+"queue"),n._removeData(a,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._data(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}}),function(){var a;l.shrinkWrapBlocks=function(){if(null!=a)return a;a=!1;var b,c,e;return c=d.getElementsByTagName("body")[0],c&&c.style?(b=d.createElement("div"),e=d.createElement("div"),e.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(e).appendChild(b),"undefined"!=typeof b.style.zoom&&(b.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:1px;width:1px;zoom:1",b.appendChild(d.createElement("div")).style.width="5px",a=3!==b.offsetWidth),c.removeChild(e),a):void 0}}();var T=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,U=new RegExp("^(?:([+-])=|)("+T+")([a-z%]*)$","i"),V=["Top","Right","Bottom","Left"],W=function(a,b){return a=b||a,"none"===n.css(a,"display")||!n.contains(a.ownerDocument,a)};function X(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)&&U.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 Y=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)Y(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},Z=/^(?:checkbox|radio)$/i,$=/<([\w:-]+)/,_=/^$|\/(?:java|ecma)script/i,aa=/^\s+/,ba="abbr|article|aside|audio|bdi|canvas|data|datalist|details|dialog|figcaption|figure|footer|header|hgroup|main|mark|meter|nav|output|picture|progress|section|summary|template|time|video";function ca(a){var b=ba.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}!function(){var a=d.createElement("div"),b=d.createDocumentFragment(),c=d.createElement("input");a.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",l.leadingWhitespace=3===a.firstChild.nodeType,l.tbody=!a.getElementsByTagName("tbody").length,l.htmlSerialize=!!a.getElementsByTagName("link").length,l.html5Clone="<:nav></:nav>"!==d.createElement("nav").cloneNode(!0).outerHTML,c.type="checkbox",c.checked=!0,b.appendChild(c),l.appendChecked=c.checked,a.innerHTML="<textarea>x</textarea>",l.noCloneChecked=!!a.cloneNode(!0).lastChild.defaultValue,b.appendChild(a),c=d.createElement("input"),c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),a.appendChild(c),l.checkClone=a.cloneNode(!0).cloneNode(!0).lastChild.checked,l.noCloneEvent=!!a.addEventListener,a[n.expando]=1,l.attributes=!a.getAttribute(n.expando)}();var da={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:l.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]};da.optgroup=da.option,da.tbody=da.tfoot=da.colgroup=da.caption=da.thead,da.th=da.td;function ea(a,b){var c,d,e=0,f="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||n.nodeName(d,b)?f.push(d):n.merge(f,ea(d,b));return void 0===b||b&&n.nodeName(a,b)?n.merge([a],f):f}function fa(a,b){for(var c,d=0;null!=(c=a[d]);d++)n._data(c,"globalEval",!b||n._data(b[d],"globalEval"))}var ga=/<|&#?\w+;/,ha=/<tbody/i;function ia(a){Z.test(a.type)&&(a.defaultChecked=a.checked)}function ja(a,b,c,d,e){for(var f,g,h,i,j,k,m,o=a.length,p=ca(b),q=[],r=0;o>r;r++)if(g=a[r],g||0===g)if("object"===n.type(g))n.merge(q,g.nodeType?[g]:g);else if(ga.test(g)){i=i||p.appendChild(b.createElement("div")),j=($.exec(g)||["",""])[1].toLowerCase(),m=da[j]||da._default,i.innerHTML=m[1]+n.htmlPrefilter(g)+m[2],f=m[0];while(f--)i=i.lastChild;if(!l.leadingWhitespace&&aa.test(g)&&q.push(b.createTextNode(aa.exec(g)[0])),!l.tbody){g="table"!==j||ha.test(g)?"<table>"!==m[1]||ha.test(g)?0:i:i.firstChild,f=g&&g.childNodes.length;while(f--)n.nodeName(k=g.childNodes[f],"tbody")&&!k.childNodes.length&&g.removeChild(k)}n.merge(q,i.childNodes),i.textContent="";while(i.firstChild)i.removeChild(i.firstChild);i=p.lastChild}else q.push(b.createTextNode(g));i&&p.removeChild(i),l.appendChecked||n.grep(ea(q,"input"),ia),r=0;while(g=q[r++])if(d&&n.inArray(g,d)>-1)e&&e.push(g);else if(h=n.contains(g.ownerDocument,g),i=ea(p.appendChild(g),"script"),h&&fa(i),c){f=0;while(g=i[f++])_.test(g.type||"")&&c.push(g)}return i=null,p}!function(){var b,c,e=d.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(l[b]=c in a)||(e.setAttribute(c,"t"),l[b]=e.attributes[c].expando===!1);e=null}();var ka=/^(?:input|select|textarea)$/i,la=/^key/,ma=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,na=/^(?:focusinfocus|focusoutblur)$/,oa=/^([^.]*)(?:\.(.+)|)/;function pa(){return!0}function qa(){return!1}function ra(){try{return d.activeElement}catch(a){}}function sa(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)sa(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=qa;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._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=n.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return"undefined"==typeof n||a&&n.event.triggered===a.type?void 0:n.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(G)||[""],h=b.length;while(h--)f=oa.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=n.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=n.event.special[o]||{},l=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(".")},i),(m=g[o])||(m=g[o]=[],m.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,l):m.push(l),n.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n.hasData(a)&&n._data(a);if(r&&(k=r.events)){b=(b||"").match(G)||[""],j=b.length;while(j--)if(h=oa.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=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=m.length;while(f--)g=m[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(m.splice(f,1),g.selector&&m.delegateCount--,l.remove&&l.remove.call(a,g));i&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(k)&&(delete r.handle,n._removeData(a,"events"))}},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(i=m=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!na.test(q+n.event.triggered)&&(q.indexOf(".")>-1&&(r=q.split("."),q=r.shift(),r.sort()),h=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]),l=n.event.special[q]||{},f||!l.trigger||l.trigger.apply(e,c)!==!1)){if(!f&&!l.noBubble&&!n.isWindow(e)){for(j=l.delegateType||q,na.test(j+q)||(i=i.parentNode);i;i=i.parentNode)p.push(i),m=i;m===(e.ownerDocument||d)&&p.push(m.defaultView||m.parentWindow||a)}o=0;while((i=p[o++])&&!b.isPropagationStopped())b.type=o>1?j:l.bindType||q,g=(n._data(i,"events")||{})[b.type]&&n._data(i,"handle"),g&&g.apply(i,c),g=h&&i[h],g&&g.apply&&M(i)&&(b.result=g.apply(i,c),b.result===!1&&b.preventDefault());if(b.type=q,!f&&!b.isDefaultPrevented()&&(!l._default||l._default.apply(p.pop(),c)===!1)&&M(e)&&h&&e[q]&&!n.isWindow(e)){m=e[h],m&&(e[h]=null),n.event.triggered=q;try{e[q]()}catch(s){}n.event.triggered=void 0,m&&(e[h]=m)}return b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,d,f,g,h=[],i=e.call(arguments),j=(n._data(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},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=ma.test(f)?this.mouseHooks:la.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=g.srcElement||d),3===a.target.nodeType&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,h.filter?h.filter(a,g):a},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 fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,e,f,g=b.button,h=b.fromElement;return null==a.pageX&&null!=b.clientX&&(e=a.target.ownerDocument||d,f=e.documentElement,c=e.body,a.pageX=b.clientX+(f&&f.scrollLeft||c&&c.scrollLeft||0)-(f&&f.clientLeft||c&&c.clientLeft||0),a.pageY=b.clientY+(f&&f.scrollTop||c&&c.scrollTop||0)-(f&&f.clientTop||c&&c.clientTop||0)),!a.relatedTarget&&h&&(a.relatedTarget=h===a.target?b.toElement:h),a.which||void 0===g||(a.which=1&g?1:2&g?3:4&g?2:0),a}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==ra()&&this.focus)try{return this.focus(),!1}catch(a){}},delegateType:"focusin"},blur:{trigger:function(){return this===ra()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return n.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(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){var d=n.extend(new n.Event,c,{type:a,isSimulated:!0});n.event.trigger(d,null,b),d.isDefaultPrevented()&&c.preventDefault()}},n.removeEvent=d.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c)}:function(a,b,c){var d="on"+b;a.detachEvent&&("undefined"==typeof a[d]&&(a[d]=null),a.detachEvent(d,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?pa:qa):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:qa,isPropagationStopped:qa,isImmediatePropagationStopped:qa,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=pa,a&&(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=pa,a&&!this.isSimulated&&(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=pa,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}}}),l.submit||(n.event.special.submit={setup:function(){return n.nodeName(this,"form")?!1:void n.event.add(this,"click._submit keypress._submit",function(a){var b=a.target,c=n.nodeName(b,"input")||n.nodeName(b,"button")?n.prop(b,"form"):void 0;c&&!n._data(c,"submit")&&(n.event.add(c,"submit._submit",function(a){a._submitBubble=!0}),n._data(c,"submit",!0))})},postDispatch:function(a){a._submitBubble&&(delete a._submitBubble,this.parentNode&&!a.isTrigger&&n.event.simulate("submit",this.parentNode,a))},teardown:function(){return n.nodeName(this,"form")?!1:void n.event.remove(this,"._submit")}}),l.change||(n.event.special.change={setup:function(){return ka.test(this.nodeName)?("checkbox"!==this.type&&"radio"!==this.type||(n.event.add(this,"propertychange._change",function(a){"checked"===a.originalEvent.propertyName&&(this._justChanged=!0)}),n.event.add(this,"click._change",function(a){this._justChanged&&!a.isTrigger&&(this._justChanged=!1),n.event.simulate("change",this,a)})),!1):void n.event.add(this,"beforeactivate._change",function(a){var b=a.target;ka.test(b.nodeName)&&!n._data(b,"change")&&(n.event.add(b,"change._change",function(a){!this.parentNode||a.isSimulated||a.isTrigger||n.event.simulate("change",this.parentNode,a)}),n._data(b,"change",!0))})},handle:function(a){var b=a.target;return this!==b||a.isSimulated||a.isTrigger||"radio"!==b.type&&"checkbox"!==b.type?a.handleObj.handler.apply(this,arguments):void 0},teardown:function(){return n.event.remove(this,"._change"),!ka.test(this.nodeName)}}),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._data(d,b);e||d.addEventListener(a,c,!0),n._data(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=n._data(d,b)-1;e?n._data(d,b,e):(d.removeEventListener(a,c,!0),n._removeData(d,b))}}}),n.fn.extend({on:function(a,b,c,d){return sa(this,a,b,c,d)},one:function(a,b,c,d){return sa(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=qa),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 ta=/ jQuery\d+="(?:null|\d+)"/g,ua=new RegExp("<(?:"+ba+")[\\s/>]","i"),va=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,wa=/<script|<style|<link/i,xa=/checked\s*(?:[^=]|=\s*.checked.)/i,ya=/^true\/(.*)/,za=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,Aa=ca(d),Ba=Aa.appendChild(d.createElement("div"));function Ca(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 Da(a){return a.type=(null!==n.find.attr(a,"type"))+"/"+a.type,a}function Ea(a){var b=ya.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Fa(a,b){if(1===b.nodeType&&n.hasData(a)){var c,d,e,f=n._data(a),g=n._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)n.event.add(b,c,h[c][d])}g.data&&(g.data=n.extend({},g.data))}}function Ga(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!l.noCloneEvent&&b[n.expando]){e=n._data(b);for(d in e.events)n.removeEvent(b,d,e.handle);b.removeAttribute(n.expando)}"script"===c&&b.text!==a.text?(Da(b).text=a.text,Ea(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),l.html5Clone&&a.innerHTML&&!n.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&Z.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:"input"!==c&&"textarea"!==c||(b.defaultValue=a.defaultValue)}}function Ha(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&&xa.test(q))return a.each(function(e){var f=a.eq(e);r&&(b[0]=q.call(this,e,f.html())),Ha(f,b,c,d)});if(o&&(k=ja(b,a[0].ownerDocument,!1,a,d),e=k.firstChild,1===k.childNodes.length&&(k=e),e||d)){for(i=n.map(ea(k,"script"),Da),h=i.length;o>m;m++)g=k,m!==p&&(g=n.clone(g,!0,!0),h&&n.merge(i,ea(g,"script"))),c.call(a[m],g,m);if(h)for(j=i[i.length-1].ownerDocument,n.map(i,Ea),m=0;h>m;m++)g=i[m],_.test(g.type||"")&&!n._data(g,"globalEval")&&n.contains(j,g)&&(g.src?n._evalUrl&&n._evalUrl(g.src):n.globalEval((g.text||g.textContent||g.innerHTML||"").replace(za,"")));k=e=null}return a}function Ia(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(ea(d)),d.parentNode&&(c&&n.contains(d.ownerDocument,d)&&fa(ea(d,"script")),d.parentNode.removeChild(d));return a}n.extend({htmlPrefilter:function(a){return a.replace(va,"<$1></$2>")},clone:function(a,b,c){var d,e,f,g,h,i=n.contains(a.ownerDocument,a);if(l.html5Clone||n.isXMLDoc(a)||!ua.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(Ba.innerHTML=a.outerHTML,Ba.removeChild(f=Ba.firstChild)),!(l.noCloneEvent&&l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(d=ea(f),h=ea(a),g=0;null!=(e=h[g]);++g)d[g]&&Ga(e,d[g]);if(b)if(c)for(h=h||ea(a),d=d||ea(f),g=0;null!=(e=h[g]);g++)Fa(e,d[g]);else Fa(a,f);return d=ea(f,"script"),d.length>0&&fa(d,!i&&ea(a,"script")),d=h=e=null,f},cleanData:function(a,b){for(var d,e,f,g,h=0,i=n.expando,j=n.cache,k=l.attributes,m=n.event.special;null!=(d=a[h]);h++)if((b||M(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)m[e]?n.event.remove(d,e):n.removeEvent(d,e,g.handle);j[f]&&(delete j[f],k||"undefined"==typeof d.removeAttribute?d[i]=void 0:d.removeAttribute(i),c.push(f))}}}),n.fn.extend({domManip:Ha,detach:function(a){return Ia(this,a,!0)},remove:function(a){return Ia(this,a)},text:function(a){return Y(this,function(a){return void 0===a?n.text(this):this.empty().append((this[0]&&this[0].ownerDocument||d).createTextNode(a))},null,a,arguments.length)},append:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.appendChild(a)}})},prepend:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ha(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(ea(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&n.nodeName(a,"select")&&(a.options.length=0)}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 Y(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(ta,""):void 0;if("string"==typeof a&&!wa.test(a)&&(l.htmlSerialize||!ua.test(a))&&(l.leadingWhitespace||!aa.test(a))&&!da[($.exec(a)||["",""])[1].toLowerCase()]){a=n.htmlPrefilter(a);try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ea(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return Ha(this,arguments,function(b){var c=this.parentNode;n.inArray(this,a)<0&&(n.cleanData(ea(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=0,e=[],f=n(a),h=f.length-1;h>=d;d++)c=d===h?this:this.clone(!0),n(f[d])[b](c),g.apply(e,c.get());return this.pushStack(e)}});var Ja,Ka={HTML:"block",BODY:"block"};function La(a,b){var c=n(b.createElement(a)).appendTo(b.body),d=n.css(c[0],"display");return c.detach(),d}function Ma(a){var b=d,c=Ka[a];return c||(c=La(a,b),"none"!==c&&c||(Ja=(Ja||n("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=(Ja[0].contentWindow||Ja[0].contentDocument).document,b.write(),b.close(),c=La(a,b),Ja.detach()),Ka[a]=c),c}var Na=/^margin/,Oa=new RegExp("^("+T+")(?!px)[a-z%]+$","i"),Pa=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},Qa=d.documentElement;!function(){var b,c,e,f,g,h,i=d.createElement("div"),j=d.createElement("div");if(j.style){j.style.cssText="float:left;opacity:.5",l.opacity="0.5"===j.style.opacity,l.cssFloat=!!j.style.cssFloat,j.style.backgroundClip="content-box",j.cloneNode(!0).style.backgroundClip="",l.clearCloneStyle="content-box"===j.style.backgroundClip,i=d.createElement("div"),i.style.cssText="border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute",j.innerHTML="",i.appendChild(j),l.boxSizing=""===j.style.boxSizing||""===j.style.MozBoxSizing||""===j.style.WebkitBoxSizing,n.extend(l,{reliableHiddenOffsets:function(){return null==b&&k(),f},boxSizingReliable:function(){return null==b&&k(),e},pixelMarginRight:function(){return null==b&&k(),c},pixelPosition:function(){return null==b&&k(),b},reliableMarginRight:function(){return null==b&&k(),g},reliableMarginLeft:function(){return null==b&&k(),h}});function k(){var k,l,m=d.documentElement;m.appendChild(i),j.style.cssText="-webkit-box-sizing:border-box;box-sizing:border-box;position:relative;display:block;margin:auto;border:1px;padding:1px;top:1%;width:50%",b=e=h=!1,c=g=!0,a.getComputedStyle&&(l=a.getComputedStyle(j),b="1%"!==(l||{}).top,h="2px"===(l||{}).marginLeft,e="4px"===(l||{width:"4px"}).width,j.style.marginRight="50%",c="4px"===(l||{marginRight:"4px"}).marginRight,k=j.appendChild(d.createElement("div")),k.style.cssText=j.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",k.style.marginRight=k.style.width="0",j.style.width="1px",g=!parseFloat((a.getComputedStyle(k)||{}).marginRight),j.removeChild(k)),j.style.display="none",f=0===j.getClientRects().length,f&&(j.style.display="",j.innerHTML="<table><tr><td></td><td>t</td></tr></table>",j.childNodes[0].style.borderCollapse="separate",k=j.getElementsByTagName("td"),k[0].style.cssText="margin:0;border:0;padding:0;display:none",f=0===k[0].offsetHeight,f&&(k[0].style.display="",k[1].style.display="none",f=0===k[0].offsetHeight)),m.removeChild(i)}}}();var Ra,Sa,Ta=/^(top|right|bottom|left)$/;a.getComputedStyle?(Ra=function(b){var c=b.ownerDocument.defaultView;return c&&c.opener||(c=a),c.getComputedStyle(b)},Sa=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ra(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()&&Oa.test(g)&&Na.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+""}):Qa.currentStyle&&(Ra=function(a){return a.currentStyle},Sa=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ra(a),g=c?c[b]:void 0,null==g&&h&&h[b]&&(g=h[b]),Oa.test(g)&&!Ta.test(b)&&(d=h.left,e=a.runtimeStyle,f=e&&e.left,f&&(e.left=a.currentStyle.left),h.left="fontSize"===b?"1em":g,g=h.pixelLeft+"px",h.left=d,f&&(e.left=f)),void 0===g?g:g+""||"auto"});function Ua(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}var Va=/alpha\([^)]*\)/i,Wa=/opacity\s*=\s*([^)]*)/i,Xa=/^(none|table(?!-c[ea]).+)/,Ya=new RegExp("^("+T+")(.*)$","i"),Za={position:"absolute",visibility:"hidden",display:"block"},$a={letterSpacing:"0",fontWeight:"400"},_a=["Webkit","O","Moz","ms"],ab=d.createElement("div").style;function bb(a){if(a in ab)return a;var b=a.charAt(0).toUpperCase()+a.slice(1),c=_a.length;while(c--)if(a=_a[c]+b,a in ab)return a}function cb(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=n._data(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&W(d)&&(f[g]=n._data(d,"olddisplay",Ma(d.nodeName)))):(e=W(d),(c&&"none"!==c||!e)&&n._data(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}function db(a,b,c){var d=Ya.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function eb(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+V[f],!0,e)),d?("content"===c&&(g-=n.css(a,"padding"+V[f],!0,e)),"margin"!==c&&(g-=n.css(a,"border"+V[f]+"Width",!0,e))):(g+=n.css(a,"padding"+V[f],!0,e),"padding"!==c&&(g+=n.css(a,"border"+V[f]+"Width",!0,e)));return g}function fb(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=Ra(a),g=l.boxSizing&&"border-box"===n.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=Sa(a,b,f),(0>e||null==e)&&(e=a.style[b]),Oa.test(e))return e;d=g&&(l.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+eb(a,b,c||(g?"border":"content"),d,f)+"px"}n.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Sa(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":l.cssFloat?"cssFloat":"styleFloat"},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;if(b=n.cssProps[h]||(n.cssProps[h]=bb(h)||h),g=n.cssHooks[b]||n.cssHooks[h],void 0===c)return g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b];if(f=typeof c,"string"===f&&(e=U.exec(c))&&e[1]&&(c=X(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)))))try{i[b]=c}catch(j){}}},css:function(a,b,c,d){var e,f,g,h=n.camelCase(b);return b=n.cssProps[h]||(n.cssProps[h]=bb(h)||h),g=n.cssHooks[b]||n.cssHooks[h],g&&"get"in g&&(f=g.get(a,!0,c)),void 0===f&&(f=Sa(a,b,d)),"normal"===f&&b in $a&&(f=$a[b]),""===c||c?(e=parseFloat(f),c===!0||isFinite(e)?e||0:f):f}}),n.each(["height","width"],function(a,b){n.cssHooks[b]={get:function(a,c,d){return c?Xa.test(n.css(a,"display"))&&0===a.offsetWidth?Pa(a,Za,function(){return fb(a,b,d)}):fb(a,b,d):void 0},set:function(a,c,d){var e=d&&Ra(a);return db(a,c,d?eb(a,b,d,l.boxSizing&&"border-box"===n.css(a,"boxSizing",!1,e),e):0)}}}),l.opacity||(n.cssHooks.opacity={get:function(a,b){return Wa.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=n.isNumeric(b)?"alpha(opacity="+100*b+")":"",f=d&&d.filter||c.filter||"";c.zoom=1,(b>=1||""===b)&&""===n.trim(f.replace(Va,""))&&c.removeAttribute&&(c.removeAttribute("filter"),""===b||d&&!d.filter)||(c.filter=Va.test(f)?f.replace(Va,e):f+" "+e)}}),n.cssHooks.marginRight=Ua(l.reliableMarginRight,function(a,b){return b?Pa(a,{display:"inline-block"},Sa,[a,"marginRight"]):void 0}),n.cssHooks.marginLeft=Ua(l.reliableMarginLeft,function(a,b){return b?(parseFloat(Sa(a,"marginLeft"))||(n.contains(a.ownerDocument,a)?a.getBoundingClientRect().left-Pa(a,{ -marginLeft:0},function(){return a.getBoundingClientRect().left}):0))+"px":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+V[d]+b]=f[d]||f[d-2]||f[0];return e}},Na.test(a)||(n.cssHooks[a+b].set=db)}),n.fn.extend({css:function(a,b){return Y(this,function(a,b,c){var d,e,f={},g=0;if(n.isArray(b)){for(d=Ra(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 cb(this,!0)},hide:function(){return cb(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){W(this)?n(this).show():n(this).hide()})}});function gb(a,b,c,d,e){return new gb.prototype.init(a,b,c,d,e)}n.Tween=gb,gb.prototype={constructor:gb,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=gb.propHooks[this.prop];return a&&a.get?a.get(this):gb.propHooks._default.get(this)},run:function(a){var b,c=gb.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):gb.propHooks._default.set(this),this}},gb.prototype.init.prototype=gb.prototype,gb.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)}}},gb.propHooks.scrollTop=gb.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=gb.prototype.init,n.fx.step={};var hb,ib,jb=/^(?:toggle|show|hide)$/,kb=/queueHooks$/;function lb(){return a.setTimeout(function(){hb=void 0}),hb=n.now()}function mb(a,b){var c,d={height:a},e=0;for(b=b?1:0;4>e;e+=2-b)c=V[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function nb(a,b,c){for(var d,e=(qb.tweeners[b]||[]).concat(qb.tweeners["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function ob(a,b,c){var d,e,f,g,h,i,j,k,m=this,o={},p=a.style,q=a.nodeType&&W(a),r=n._data(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++,m.always(function(){m.always(function(){h.unqueued--,n.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[p.overflow,p.overflowX,p.overflowY],j=n.css(a,"display"),k="none"===j?n._data(a,"olddisplay")||Ma(a.nodeName):j,"inline"===k&&"none"===n.css(a,"float")&&(l.inlineBlockNeedsLayout&&"inline"!==Ma(a.nodeName)?p.zoom=1:p.display="inline-block")),c.overflow&&(p.overflow="hidden",l.shrinkWrapBlocks()||m.always(function(){p.overflow=c.overflow[0],p.overflowX=c.overflow[1],p.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],jb.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(q?"hide":"show")){if("show"!==e||!r||void 0===r[d])continue;q=!0}o[d]=r&&r[d]||n.style(a,d)}else j=void 0;if(n.isEmptyObject(o))"inline"===("none"===j?Ma(a.nodeName):j)&&(p.display=j);else{r?"hidden"in r&&(q=r.hidden):r=n._data(a,"fxshow",{}),f&&(r.hidden=!q),q?n(a).show():m.done(function(){n(a).hide()}),m.done(function(){var b;n._removeData(a,"fxshow");for(b in o)n.style(a,b,o[b])});for(d in o)g=nb(q?r[d]:0,d,m),d in r||(r[d]=g.start,q&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function pb(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 qb(a,b,c){var d,e,f=0,g=qb.prefilters.length,h=n.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=hb||lb(),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:hb||lb(),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(pb(k,j.opts.specialEasing);g>f;f++)if(d=qb.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,nb,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(qb,{tweeners:{"*":[function(a,b){var c=this.createTween(a,b);return X(c.elem,a,U.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],qb.tweeners[c]=qb.tweeners[c]||[],qb.tweeners[c].unshift(b)},prefilters:[ob],prefilter:function(a,b){b?qb.prefilters.unshift(a):qb.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(W).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=qb(this,n.extend({},a),f);(e||n._data(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._data(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&kb.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._data(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(mb(b,!0),a,d,e)}}),n.each({slideDown:mb("show"),slideUp:mb("hide"),slideToggle:mb("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=n.timers,c=0;for(hb=n.now();c<b.length;c++)a=b[c],a()||b[c]!==a||b.splice(c--,1);b.length||n.fx.stop(),hb=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(){ib||(ib=a.setInterval(n.fx.tick,n.fx.interval))},n.fx.stop=function(){a.clearInterval(ib),ib=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,b=d.createElement("input"),c=d.createElement("div"),e=d.createElement("select"),f=e.appendChild(d.createElement("option"));c=d.createElement("div"),c.setAttribute("className","t"),c.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",a=c.getElementsByTagName("a")[0],b.setAttribute("type","checkbox"),c.appendChild(b),a=c.getElementsByTagName("a")[0],a.style.cssText="top:1px",l.getSetAttribute="t"!==c.className,l.style=/top/.test(a.getAttribute("style")),l.hrefNormalized="/a"===a.getAttribute("href"),l.checkOn=!!b.value,l.optSelected=f.selected,l.enctype=!!d.createElement("form").enctype,e.disabled=!0,l.optDisabled=!f.disabled,b=d.createElement("input"),b.setAttribute("value",""),l.input=""===b.getAttribute("value"),b.value="t",b.setAttribute("type","radio"),l.radioValue="t"===b.value}();var rb=/\r/g,sb=/[\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(rb,""):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(sb," ")}},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--)if(d=e[g],n.inArray(n.valHooks.option.get(d),f)>-1)try{d.selected=c=!0}catch(h){d.scrollHeight}else d.selected=!1;return c||(a.selectedIndex=-1),e}}}}),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 tb,ub,vb=n.expr.attrHandle,wb=/^(?:checked|selected)$/i,xb=l.getSetAttribute,yb=l.input;n.fn.extend({attr:function(a,b){return Y(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)?ub:tb)),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)?yb&&xb||!wb.test(c)?a[d]=!1:a[n.camelCase("default-"+c)]=a[d]=!1:n.attr(a,c,""),a.removeAttribute(xb?c:d)}}),ub={set:function(a,b,c){return b===!1?n.removeAttr(a,c):yb&&xb||!wb.test(c)?a.setAttribute(!xb&&n.propFix[c]||c,c):a[n.camelCase("default-"+c)]=a[c]=!0,c}},n.each(n.expr.match.bool.source.match(/\w+/g),function(a,b){var c=vb[b]||n.find.attr;yb&&xb||!wb.test(b)?vb[b]=function(a,b,d){var e,f;return d||(f=vb[b],vb[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,vb[b]=f),e}:vb[b]=function(a,b,c){return c?void 0:a[n.camelCase("default-"+b)]?b.toLowerCase():null}}),yb&&xb||(n.attrHooks.value={set:function(a,b,c){return n.nodeName(a,"input")?void(a.defaultValue=b):tb&&tb.set(a,b,c)}}),xb||(tb={set:function(a,b,c){var d=a.getAttributeNode(c);return d||a.setAttributeNode(d=a.ownerDocument.createAttribute(c)),d.value=b+="","value"===c||b===a.getAttribute(c)?b:void 0}},vb.id=vb.name=vb.coords=function(a,b,c){var d;return c?void 0:(d=a.getAttributeNode(b))&&""!==d.value?d.value:null},n.valHooks.button={get:function(a,b){var c=a.getAttributeNode(b);return c&&c.specified?c.value:void 0},set:tb.set},n.attrHooks.contenteditable={set:function(a,b,c){tb.set(a,""===b?!1:b,c)}},n.each(["width","height"],function(a,b){n.attrHooks[b]={set:function(a,c){return""===c?(a.setAttribute(b,"auto"),c):void 0}}})),l.style||(n.attrHooks.style={get:function(a){return a.style.cssText||void 0},set:function(a,b){return a.style.cssText=b+""}});var zb=/^(?:input|select|textarea|button|object)$/i,Ab=/^(?:a|area)$/i;n.fn.extend({prop:function(a,b){return Y(this,n.prop,a,b,arguments.length>1)},removeProp:function(a){return a=n.propFix[a]||a,this.each(function(){try{this[a]=void 0,delete this[a]}catch(b){}})}}),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):zb.test(a.nodeName)||Ab.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),l.hrefNormalized||n.each(["href","src"],function(a,b){n.propHooks[b]={get:function(a){return a.getAttribute(b,4)}}}),l.optSelected||(n.propHooks.selected={get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,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}),l.enctype||(n.propFix.enctype="encoding");var Bb=/[\t\r\n\f]/g;function Cb(a){return n.attr(a,"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,Cb(this)))});if("string"==typeof a&&a){b=a.match(G)||[];while(c=this[i++])if(e=Cb(c),d=1===c.nodeType&&(" "+e+" ").replace(Bb," ")){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=n.trim(d),e!==h&&n.attr(c,"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,Cb(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(G)||[];while(c=this[i++])if(e=Cb(c),d=1===c.nodeType&&(" "+e+" ").replace(Bb," ")){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=n.trim(d),e!==h&&n.attr(c,"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,Cb(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=Cb(this),b&&n._data(this,"__className__",b),n.attr(this,"class",b||a===!1?"":n._data(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+Cb(c)+" ").replace(Bb," ").indexOf(b)>-1)return!0;return!1}}),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)}});var Db=a.location,Eb=n.now(),Fb=/\?/,Gb=/(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;n.parseJSON=function(b){if(a.JSON&&a.JSON.parse)return a.JSON.parse(b+"");var c,d=null,e=n.trim(b+"");return e&&!n.trim(e.replace(Gb,function(a,b,e,f){return c&&b&&(d=0),0===d?a:(c=e||b,d+=!f-!e,"")}))?Function("return "+e)():n.error("Invalid JSON: "+b)},n.parseXML=function(b){var c,d;if(!b||"string"!=typeof b)return null;try{a.DOMParser?(d=new a.DOMParser,c=d.parseFromString(b,"text/xml")):(c=new a.ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b))}catch(e){c=void 0}return c&&c.documentElement&&!c.getElementsByTagName("parsererror").length||n.error("Invalid XML: "+b),c};var Hb=/#.*$/,Ib=/([?&])_=[^&]*/,Jb=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Kb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Lb=/^(?:GET|HEAD)$/,Mb=/^\/\//,Nb=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,Ob={},Pb={},Qb="*/".concat("*"),Rb=Db.href,Sb=Nb.exec(Rb.toLowerCase())||[];function Tb(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.charAt(0)?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Ub(a,b,c,d){var e={},f=a===Pb;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 Vb(a,b){var c,d,e=n.ajaxSettings.flatOptions||{};for(d in b)void 0!==b[d]&&((e[d]?a:c||(c={}))[d]=b[d]);return c&&n.extend(!0,a,c),a}function Wb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===e&&(e=a.mimeType||b.getResponseHeader("Content-Type"));if(e)for(g in h)if(h[g]&&h[g].test(e)){i.unshift(g);break}if(i[0]in c)f=i[0];else{for(g in c){if(!i[0]||a.converters[g+" "+i[0]]){f=g;break}d||(d=g)}f=f||d}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function Xb(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:Rb,type:"GET",isLocal:Kb.test(Sb[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Qb,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?Vb(Vb(a,n.ajaxSettings),b):Vb(n.ajaxSettings,a)},ajaxPrefilter:Tb(Ob),ajaxTransport:Tb(Pb),ajax:function(b,c){"object"==typeof b&&(c=b,b=void 0),c=c||{};var d,e,f,g,h,i,j,k,l=n.ajaxSetup({},c),m=l.context||l,o=l.context&&(m.nodeType||m.jquery)?n(m):n.event,p=n.Deferred(),q=n.Callbacks("once memory"),r=l.statusCode||{},s={},t={},u=0,v="canceled",w={readyState:0,getResponseHeader:function(a){var b;if(2===u){if(!k){k={};while(b=Jb.exec(g))k[b[1].toLowerCase()]=b[2]}b=k[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===u?g:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return u||(a=t[c]=t[c]||a,s[a]=b),this},overrideMimeType:function(a){return u||(l.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>u)for(b in a)r[b]=[r[b],a[b]];else w.always(a[w.status]);return this},abort:function(a){var b=a||v;return j&&j.abort(b),y(0,b),this}};if(p.promise(w).complete=q.add,w.success=w.done,w.error=w.fail,l.url=((b||l.url||Rb)+"").replace(Hb,"").replace(Mb,Sb[1]+"//"),l.type=c.method||c.type||l.method||l.type,l.dataTypes=n.trim(l.dataType||"*").toLowerCase().match(G)||[""],null==l.crossDomain&&(d=Nb.exec(l.url.toLowerCase()),l.crossDomain=!(!d||d[1]===Sb[1]&&d[2]===Sb[2]&&(d[3]||("http:"===d[1]?"80":"443"))===(Sb[3]||("http:"===Sb[1]?"80":"443")))),l.data&&l.processData&&"string"!=typeof l.data&&(l.data=n.param(l.data,l.traditional)),Ub(Ob,l,c,w),2===u)return w;i=n.event&&l.global,i&&0===n.active++&&n.event.trigger("ajaxStart"),l.type=l.type.toUpperCase(),l.hasContent=!Lb.test(l.type),f=l.url,l.hasContent||(l.data&&(f=l.url+=(Fb.test(f)?"&":"?")+l.data,delete l.data),l.cache===!1&&(l.url=Ib.test(f)?f.replace(Ib,"$1_="+Eb++):f+(Fb.test(f)?"&":"?")+"_="+Eb++)),l.ifModified&&(n.lastModified[f]&&w.setRequestHeader("If-Modified-Since",n.lastModified[f]),n.etag[f]&&w.setRequestHeader("If-None-Match",n.etag[f])),(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&w.setRequestHeader("Content-Type",l.contentType),w.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+("*"!==l.dataTypes[0]?", "+Qb+"; q=0.01":""):l.accepts["*"]);for(e in l.headers)w.setRequestHeader(e,l.headers[e]);if(l.beforeSend&&(l.beforeSend.call(m,w,l)===!1||2===u))return w.abort();v="abort";for(e in{success:1,error:1,complete:1})w[e](l[e]);if(j=Ub(Pb,l,c,w)){if(w.readyState=1,i&&o.trigger("ajaxSend",[w,l]),2===u)return w;l.async&&l.timeout>0&&(h=a.setTimeout(function(){w.abort("timeout")},l.timeout));try{u=1,j.send(s,y)}catch(x){if(!(2>u))throw x;y(-1,x)}}else y(-1,"No Transport");function y(b,c,d,e){var k,s,t,v,x,y=c;2!==u&&(u=2,h&&a.clearTimeout(h),j=void 0,g=e||"",w.readyState=b>0?4:0,k=b>=200&&300>b||304===b,d&&(v=Wb(l,w,d)),v=Xb(l,v,w,k),k?(l.ifModified&&(x=w.getResponseHeader("Last-Modified"),x&&(n.lastModified[f]=x),x=w.getResponseHeader("etag"),x&&(n.etag[f]=x)),204===b||"HEAD"===l.type?y="nocontent":304===b?y="notmodified":(y=v.state,s=v.data,t=v.error,k=!t)):(t=y,!b&&y||(y="error",0>b&&(b=0))),w.status=b,w.statusText=(c||y)+"",k?p.resolveWith(m,[s,y,w]):p.rejectWith(m,[w,y,t]),w.statusCode(r),r=void 0,i&&o.trigger(k?"ajaxSuccess":"ajaxError",[w,l,k?s:t]),q.fireWith(m,[w,y]),i&&(o.trigger("ajaxComplete",[w,l]),--n.active||n.event.trigger("ajaxStop")))}return w},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",cache:!0,async:!1,global:!1,"throws":!0})},n.fn.extend({wrapAll:function(a){if(n.isFunction(a))return this.each(function(b){n(this).wrapAll(a.call(this,b))});if(this[0]){var 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.firstChild&&1===a.firstChild.nodeType)a=a.firstChild;return a}).append(this)}return 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()}});function Yb(a){return a.style&&a.style.display||n.css(a,"display")}function Zb(a){if(!n.contains(a.ownerDocument||d,a))return!0;while(a&&1===a.nodeType){if("none"===Yb(a)||"hidden"===a.type)return!0;a=a.parentNode}return!1}n.expr.filters.hidden=function(a){return l.reliableHiddenOffsets()?a.offsetWidth<=0&&a.offsetHeight<=0&&!a.getClientRects().length:Zb(a)},n.expr.filters.visible=function(a){return!n.expr.filters.hidden(a)};var $b=/%20/g,_b=/\[\]$/,ac=/\r?\n/g,bc=/^(?:submit|button|image|reset|file)$/i,cc=/^(?:input|select|textarea|keygen)/i;function dc(a,b,c,d){var e;if(n.isArray(b))n.each(b,function(b,e){c||_b.test(a)?d(a,e):dc(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)dc(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)dc(c,a[c],b,e);return d.join("&").replace($b,"+")},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")&&cc.test(this.nodeName)&&!bc.test(a)&&(this.checked||!Z.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(ac,"\r\n")}}):{name:b.name,value:c.replace(ac,"\r\n")}}).get()}}),n.ajaxSettings.xhr=void 0!==a.ActiveXObject?function(){return this.isLocal?ic():d.documentMode>8?hc():/^(get|post|head|put|delete|options)$/i.test(this.type)&&hc()||ic()}:hc;var ec=0,fc={},gc=n.ajaxSettings.xhr();a.attachEvent&&a.attachEvent("onunload",function(){for(var a in fc)fc[a](void 0,!0)}),l.cors=!!gc&&"withCredentials"in gc,gc=l.ajax=!!gc,gc&&n.ajaxTransport(function(b){if(!b.crossDomain||l.cors){var c;return{send:function(d,e){var f,g=b.xhr(),h=++ec;if(g.open(b.type,b.url,b.async,b.username,b.password),b.xhrFields)for(f in b.xhrFields)g[f]=b.xhrFields[f];b.mimeType&&g.overrideMimeType&&g.overrideMimeType(b.mimeType),b.crossDomain||d["X-Requested-With"]||(d["X-Requested-With"]="XMLHttpRequest");for(f in d)void 0!==d[f]&&g.setRequestHeader(f,d[f]+"");g.send(b.hasContent&&b.data||null),c=function(a,d){var f,i,j;if(c&&(d||4===g.readyState))if(delete fc[h],c=void 0,g.onreadystatechange=n.noop,d)4!==g.readyState&&g.abort();else{j={},f=g.status,"string"==typeof g.responseText&&(j.text=g.responseText);try{i=g.statusText}catch(k){i=""}f||!b.isLocal||b.crossDomain?1223===f&&(f=204):f=j.text?200:404}j&&e(f,i,j,g.getAllResponseHeaders())},b.async?4===g.readyState?a.setTimeout(c):g.onreadystatechange=fc[h]=c:c()},abort:function(){c&&c(void 0,!0)}}}});function hc(){try{return new a.XMLHttpRequest}catch(b){}}function ic(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}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",a.global=!1)}),n.ajaxTransport("script",function(a){if(a.crossDomain){var b,c=d.head||n("head")[0]||d.documentElement;return{send:function(e,f){b=d.createElement("script"),b.async=!0,a.scriptCharset&&(b.charset=a.scriptCharset),b.src=a.url,b.onload=b.onreadystatechange=function(a,c){(c||!b.readyState||/loaded|complete/.test(b.readyState))&&(b.onload=b.onreadystatechange=null,b.parentNode&&b.parentNode.removeChild(b),b=null,c||f(200,"success"))},c.insertBefore(b,c.firstChild)},abort:function(){b&&b.onload(void 0,!0)}}}});var jc=[],kc=/(=)\?(?=&|$)|\?\?/;n.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=jc.pop()||n.expando+"_"+Eb++;return this[a]=!0,a}}),n.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(kc.test(b.url)?"url":"string"==typeof b.data&&0===(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&kc.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(kc,"$1"+e):b.jsonp!==!1&&(b.url+=(Fb.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,jc.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=ja([a],b,f),f&&f.length&&n(f).remove(),n.merge([],e.childNodes))};var lc=n.fn.load;n.fn.load=function(a,b,c){if("string"!=typeof a&&lc)return lc.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>-1&&(d=n.trim(a.slice(h,a.length)),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 mc(a){return n.isWindow(a)?a:9===a.nodeType?a.defaultView||a.parentWindow:!1}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)&&n.inArray("auto",[f,i])>-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={top:0,left:0},e=this[0],f=e&&e.ownerDocument;if(f)return b=f.documentElement,n.contains(b,e)?("undefined"!=typeof e.getBoundingClientRect&&(d=e.getBoundingClientRect()),c=mc(f),{top:d.top+(c.pageYOffset||b.scrollTop)-(b.clientTop||0),left:d.left+(c.pageXOffset||b.scrollLeft)-(b.clientLeft||0)}):d},position:function(){if(this[0]){var a,b,c={top:0,left:0},d=this[0];return"fixed"===n.css(d,"position")?b=d.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),n.nodeName(a[0],"html")||(c=a.offset()),c.top+=n.css(a[0],"borderTopWidth",!0),c.left+=n.css(a[0],"borderLeftWidth",!0)),{top:b.top-c.top-n.css(d,"marginTop",!0),left:b.left-c.left-n.css(d,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent;while(a&&!n.nodeName(a,"html")&&"static"===n.css(a,"position"))a=a.offsetParent;return a||Qa})}}),n.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c=/Y/.test(b);n.fn[a]=function(d){return Y(this,function(a,d,e){var f=mc(a);return void 0===e?f?b in f?f[b]:f.document.documentElement[d]:a[d]:void(f?f.scrollTo(c?n(f).scrollLeft():e,c?e:n(f).scrollTop()):a[d]=e)},a,d,arguments.length,null)}}),n.each(["top","left"],function(a,b){n.cssHooks[b]=Ua(l.pixelPosition,function(a,c){return c?(c=Sa(a,b),Oa.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 Y(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)}}),n.fn.size=function(){return this.length},n.fn.andSelf=n.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return n});var nc=a.jQuery,oc=a.$;return n.noConflict=function(b){return a.$===n&&(a.$=oc),b&&a.jQuery===n&&(a.jQuery=nc),n},b||(a.jQuery=a.$=n),n}); - +/*! jQuery v3.6.1 | (c) OpenJS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,y=n.hasOwnProperty,a=y.toString,l=a.call(Object),v={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.1",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0<t&&t-1 in e)}S.fn=S.prototype={jquery:f,constructor:S,length:0,toArray:function(){return s.call(this)},get:function(e){return null==e?s.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=S.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return S.each(this,e)},map:function(n){return this.pushStack(S.map(this,function(e,t){return n.call(e,t,e)}))},slice:function(){return this.pushStack(s.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},even:function(){return this.pushStack(S.grep(this,function(e,t){return(t+1)%2}))},odd:function(){return this.pushStack(S.grep(this,function(e,t){return t%2}))},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(0<=n&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:u,sort:t.sort,splice:t.splice},S.extend=S.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for("boolean"==typeof a&&(l=a,a=arguments[s]||{},s++),"object"==typeof a||m(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(e=arguments[s]))for(t in e)r=e[t],"__proto__"!==t&&a!==r&&(l&&r&&(S.isPlainObject(r)||(i=Array.isArray(r)))?(n=a[t],o=i&&!Array.isArray(n)?[]:i||S.isPlainObject(n)?n:{},i=!1,a[t]=S.extend(l,o,r)):void 0!==r&&(a[t]=r));return a},S.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isPlainObject:function(e){var t,n;return!(!e||"[object Object]"!==o.call(e))&&(!(t=r(e))||"function"==typeof(n=y.call(t,"constructor")&&t.constructor)&&a.call(n)===l)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},globalEval:function(e,t,n){b(e,{nonce:t&&t.nonce},n)},each:function(e,t){var n,r=0;if(p(e)){for(n=e.length;r<n;r++)if(!1===t.call(e[r],r,e[r]))break}else for(r in e)if(!1===t.call(e[r],r,e[r]))break;return e},makeArray:function(e,t){var n=t||[];return null!=e&&(p(Object(e))?S.merge(n,"string"==typeof e?[e]:e):u.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:i.call(t,e,n)},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;r++)e[i++]=t[r];return e.length=i,e},grep:function(e,t,n){for(var r=[],i=0,o=e.length,a=!n;i<o;i++)!t(e[i],i)!==a&&r.push(e[i]);return r},map:function(e,t,n){var r,i,o=0,a=[];if(p(e))for(r=e.length;o<r;o++)null!=(i=t(e[o],o,n))&&a.push(i);else for(o in e)null!=(i=t(e[o],o,n))&&a.push(i);return g(a)},guid:1,support:v}),"function"==typeof Symbol&&(S.fn[Symbol.iterator]=t[Symbol.iterator]),S.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(e,t){n["[object "+t+"]"]=t.toLowerCase()});var d=function(n){var e,d,b,o,i,h,f,g,w,u,l,T,C,a,E,y,s,c,v,S="sizzle"+1*new Date,p=n.document,k=0,r=0,m=ue(),x=ue(),A=ue(),N=ue(),j=function(e,t){return e===t&&(l=!0),0},D={}.hasOwnProperty,t=[],q=t.pop,L=t.push,H=t.push,O=t.slice,P=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},R="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",I="(?:\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+",W="\\["+M+"*("+I+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+I+"))|)"+M+"*\\]",F=":("+I+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+W+")*)|.*)\\)|)",$=new RegExp(M+"+","g"),B=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),_=new RegExp("^"+M+"*,"+M+"*"),z=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&v(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!y||!y.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ve(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ye(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ve(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],y=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="<a id='"+S+"'></a><select id='"+S+"-\r\\' msallowcapture=''><option selected=''></option></select>",e.querySelectorAll("[msallowcapture^='']").length&&y.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||y.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||y.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||y.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||y.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||y.push(".#.+[+~]"),e.querySelectorAll("\\\f"),y.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="<a href='' disabled='disabled'></a><select disabled='disabled'><option/></select>";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&y.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&y.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&y.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),y.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),y=y.length&&new RegExp(y.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),v=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&v(p,e)?-1:t==C||t.ownerDocument==p&&v(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!y||!y.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0<se(t,C,null,[e]).length},se.contains=function(e,t){return(e.ownerDocument||e)!=C&&T(e),v(e,t)},se.attr=function(e,t){(e.ownerDocument||e)!=C&&T(e);var n=b.attrHandle[t.toLowerCase()],r=n&&D.call(b.attrHandle,t.toLowerCase())?n(e,t,!E):void 0;return void 0!==r?r:d.attributes||!E?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},se.escape=function(e){return(e+"").replace(re,ie)},se.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},se.uniqueSort=function(e){var t,n=[],r=0,i=0;if(l=!d.detectDuplicates,u=!d.sortStable&&e.slice(0),e.sort(j),l){while(t=e[i++])t===e[i]&&(r=n.push(i));while(r--)e.splice(n[r],1)}return u=null,e},o=se.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else while(t=e[r++])n+=o(t);return n},(b=se.selectors={cacheLength:50,createPseudo:le,match:G,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1<t.indexOf(i):"$="===r?i&&t.slice(-i.length)===i:"~="===r?-1<(" "+t.replace($," ")+" ").indexOf(i):"|="===r&&(t===i||t.slice(0,i.length+1)===i+"-"))}},CHILD:function(h,e,t,g,y){var v="nth"!==h.slice(0,3),m="last"!==h.slice(-4),x="of-type"===e;return 1===g&&0===y?function(e){return!!e.parentNode}:function(e,t,n){var r,i,o,a,s,u,l=v!==m?"nextSibling":"previousSibling",c=e.parentNode,f=x&&e.nodeName.toLowerCase(),p=!n&&!x,d=!1;if(c){if(v){while(l){a=e;while(a=a[l])if(x?a.nodeName.toLowerCase()===f:1===a.nodeType)return!1;u=l="only"===h&&!u&&"nextSibling"}return!0}if(u=[m?c.firstChild:c.lastChild],m&&p){d=(s=(r=(i=(o=(a=c)[S]||(a[S]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]||[])[0]===k&&r[1])&&r[2],a=s&&c.childNodes[s];while(a=++s&&a&&a[l]||(d=s=0)||u.pop())if(1===a.nodeType&&++d&&a===e){i[h]=[k,s,d];break}}else if(p&&(d=s=(r=(i=(o=(a=e)[S]||(a[S]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]||[])[0]===k&&r[1]),!1===d)while(a=++s&&a&&a[l]||(d=s=0)||u.pop())if((x?a.nodeName.toLowerCase()===f:1===a.nodeType)&&++d&&(p&&((i=(o=a[S]||(a[S]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]=[k,d]),a===e))break;return(d-=y)===g||d%g==0&&0<=d/g}}},PSEUDO:function(e,o){var t,a=b.pseudos[e]||b.setFilters[e.toLowerCase()]||se.error("unsupported pseudo: "+e);return a[S]?a(o):1<a.length?(t=[e,e,"",o],b.setFilters.hasOwnProperty(e.toLowerCase())?le(function(e,t){var n,r=a(e,o),i=r.length;while(i--)e[n=P(e,r[i])]=!(t[n]=r[i])}):function(e){return a(e,0,t)}):a}},pseudos:{not:le(function(e){var r=[],i=[],s=f(e.replace(B,"$1"));return s[S]?le(function(e,t,n,r){var i,o=s(e,null,r,[]),a=e.length;while(a--)(i=o[a])&&(e[a]=!(t[a]=i))}):function(e,t,n){return r[0]=e,s(r,null,n,i),r[0]=null,!i.pop()}}),has:le(function(t){return function(e){return 0<se(t,e).length}}),contains:le(function(t){return t=t.replace(te,ne),function(e){return-1<(e.textContent||o(e)).indexOf(t)}}),lang:le(function(n){return V.test(n||"")||se.error("unsupported lang: "+n),n=n.replace(te,ne).toLowerCase(),function(e){var t;do{if(t=E?e.lang:e.getAttribute("xml:lang")||e.getAttribute("lang"))return(t=t.toLowerCase())===n||0===t.indexOf(n+"-")}while((e=e.parentNode)&&1===e.nodeType);return!1}}),target:function(e){var t=n.location&&n.location.hash;return t&&t.slice(1)===e.id},root:function(e){return e===a},focus:function(e){return e===C.activeElement&&(!C.hasFocus||C.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:ge(!1),disabled:ge(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!b.pseudos.empty(e)},header:function(e){return J.test(e.nodeName)},input:function(e){return Q.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:ye(function(){return[0]}),last:ye(function(e,t){return[t-1]}),eq:ye(function(e,t,n){return[n<0?n+t:n]}),even:ye(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:ye(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:ye(function(e,t,n){for(var r=n<0?n+t:t<n?t:n;0<=--r;)e.push(r);return e}),gt:ye(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}}).pseudos.nth=b.pseudos.eq,{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})b.pseudos[e]=de(e);for(e in{submit:!0,reset:!0})b.pseudos[e]=he(e);function me(){}function xe(e){for(var t=0,n=e.length,r="";t<n;t++)r+=e[t].value;return r}function be(s,e,t){var u=e.dir,l=e.next,c=l||u,f=t&&"parentNode"===c,p=r++;return e.first?function(e,t,n){while(e=e[u])if(1===e.nodeType||f)return s(e,t,n);return!1}:function(e,t,n){var r,i,o,a=[k,p];if(n){while(e=e[u])if((1===e.nodeType||f)&&s(e,t,n))return!0}else while(e=e[u])if(1===e.nodeType||f)if(i=(o=e[S]||(e[S]={}))[e.uniqueID]||(o[e.uniqueID]={}),l&&l===e.nodeName.toLowerCase())e=e[u]||e;else{if((r=i[c])&&r[0]===k&&r[1]===p)return a[2]=r[2];if((i[c]=a)[2]=s(e,t,n))return!0}return!1}}function we(i){return 1<i.length?function(e,t,n){var r=i.length;while(r--)if(!i[r](e,t,n))return!1;return!0}:i[0]}function Te(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;s<u;s++)(o=e[s])&&(n&&!n(o,r,i)||(a.push(o),l&&t.push(s)));return a}function Ce(d,h,g,y,v,e){return y&&!y[S]&&(y=Ce(y)),v&&!v[S]&&(v=Ce(v,e)),le(function(e,t,n,r){var i,o,a,s=[],u=[],l=t.length,c=e||function(e,t,n){for(var r=0,i=t.length;r<i;r++)se(e,t[r],n);return n}(h||"*",n.nodeType?[n]:n,[]),f=!d||!e&&h?c:Te(c,s,d,n,r),p=g?v||(e?d:l||y)?[]:t:f;if(g&&g(f,p,n,r),y){i=Te(p,u),y(i,[],n,r),o=i.length;while(o--)(a=i[o])&&(p[u[o]]=!(f[u[o]]=a))}if(e){if(v||d){if(v){i=[],o=p.length;while(o--)(a=p[o])&&i.push(f[o]=a);v(null,p=[],i,r)}o=p.length;while(o--)(a=p[o])&&-1<(i=v?P(e,a):s[o])&&(e[i]=!(t[i]=a))}}else p=Te(p===t?p.splice(l,p.length):p),v?v(null,t,p,r):H.apply(t,p)})}function Ee(e){for(var i,t,n,r=e.length,o=b.relative[e[0].type],a=o||b.relative[" "],s=o?1:0,u=be(function(e){return e===i},a,!0),l=be(function(e){return-1<P(i,e)},a,!0),c=[function(e,t,n){var r=!o&&(n||t!==w)||((i=t).nodeType?u(e,t,n):l(e,t,n));return i=null,r}];s<r;s++)if(t=b.relative[e[s].type])c=[be(we(c),t)];else{if((t=b.filter[e[s].type].apply(null,e[s].matches))[S]){for(n=++s;n<r;n++)if(b.relative[e[n].type])break;return Ce(1<s&&we(c),1<s&&xe(e.slice(0,s-1).concat({value:" "===e[s-2].type?"*":""})).replace(B,"$1"),t,s<n&&Ee(e.slice(s,n)),n<r&&Ee(e=e.slice(n)),n<r&&xe(e))}c.push(t)}return we(c)}return me.prototype=b.filters=b.pseudos,b.setFilters=new me,h=se.tokenize=function(e,t){var n,r,i,o,a,s,u,l=x[e+" "];if(l)return t?0:l.slice(0);a=e,s=[],u=b.preFilter;while(a){for(o in n&&!(r=_.exec(a))||(r&&(a=a.slice(r[0].length)||a),s.push(i=[])),n=!1,(r=z.exec(a))&&(n=r.shift(),i.push({value:n,type:r[0].replace(B," ")}),a=a.slice(n.length)),b.filter)!(r=G[o].exec(a))||u[o]&&!(r=u[o](r))||(n=r.shift(),i.push({value:n,type:o,matches:r}),a=a.slice(n.length));if(!n)break}return t?a.length:a?se.error(e):x(e,s).slice(0)},f=se.compile=function(e,t){var n,y,v,m,x,r,i=[],o=[],a=A[e+" "];if(!a){t||(t=h(e)),n=t.length;while(n--)(a=Ee(t[n]))[S]?i.push(a):o.push(a);(a=A(e,(y=o,m=0<(v=i).length,x=0<y.length,r=function(e,t,n,r,i){var o,a,s,u=0,l="0",c=e&&[],f=[],p=w,d=e||x&&b.find.TAG("*",i),h=k+=null==p?1:Math.random()||.1,g=d.length;for(i&&(w=t==C||t||i);l!==g&&null!=(o=d[l]);l++){if(x&&o){a=0,t||o.ownerDocument==C||(T(o),n=!E);while(s=y[a++])if(s(o,t||C,n)){r.push(o);break}i&&(k=h)}m&&((o=!s&&o)&&u--,e&&c.push(o))}if(u+=l,m&&l!==u){a=0;while(s=v[a++])s(c,f,t,n);if(e){if(0<u)while(l--)c[l]||f[l]||(f[l]=q.call(r));f=Te(f)}H.apply(r,f),i&&!e&&0<f.length&&1<u+v.length&&se.uniqueSort(r)}return i&&(k=h,w=p),c},m?le(r):r))).selector=e}return a},g=se.select=function(e,t,n,r){var i,o,a,s,u,l="function"==typeof e&&e,c=!r&&h(e=l.selector||e);if(n=n||[],1===c.length){if(2<(o=c[0]=c[0].slice(0)).length&&"ID"===(a=o[0]).type&&9===t.nodeType&&E&&b.relative[o[1].type]){if(!(t=(b.find.ID(a.matches[0].replace(te,ne),t)||[])[0]))return n;l&&(t=t.parentNode),e=e.slice(o.shift().value.length)}i=G.needsContext.test(e)?0:o.length;while(i--){if(a=o[i],b.relative[s=a.type])break;if((u=b.find[s])&&(r=u(a.matches[0].replace(te,ne),ee.test(o[0].type)&&ve(t.parentNode)||t))){if(o.splice(i,1),!(e=r.length&&xe(o)))return H.apply(n,r),n;break}}}return(l||f(e,c))(r,t,!E,n,!t||ee.test(e)&&ve(t.parentNode)||t),n},d.sortStable=S.split("").sort(j).join("")===S,d.detectDuplicates=!!l,T(),d.sortDetached=ce(function(e){return 1&e.compareDocumentPosition(C.createElement("fieldset"))}),ce(function(e){return e.innerHTML="<a href='#'></a>","#"===e.firstChild.getAttribute("href")})||fe("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),d.attributes&&ce(function(e){return e.innerHTML="<input/>",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||fe("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),ce(function(e){return null==e.getAttribute("disabled")})||fe(R,function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),se}(C);S.find=d,S.expr=d.selectors,S.expr[":"]=S.expr.pseudos,S.uniqueSort=S.unique=d.uniqueSort,S.text=d.getText,S.isXMLDoc=d.isXML,S.contains=d.contains,S.escapeSelector=d.escape;var h=function(e,t,n){var r=[],i=void 0!==n;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&S(e).is(n))break;r.push(e)}return r},T=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},k=S.expr.match.needsContext;function A(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var N=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1<i.call(n,e)!==r}):S.filter(n,e,r)}S.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?S.find.matchesSelector(r,e)?[r]:[]:S.find.matches(e,S.grep(t,function(e){return 1===e.nodeType}))},S.fn.extend({find:function(e){var t,n,r=this.length,i=this;if("string"!=typeof e)return this.pushStack(S(e).filter(function(){for(t=0;t<r;t++)if(S.contains(i[t],this))return!0}));for(n=this.pushStack([]),t=0;t<r;t++)S.find(e,i[t],n);return 1<r?S.uniqueSort(n):n},filter:function(e){return this.pushStack(j(this,e||[],!1))},not:function(e){return this.pushStack(j(this,e||[],!0))},is:function(e){return!!j(this,"string"==typeof e&&k.test(e)?S(e):e||[],!1).length}});var D,q=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e<n;e++)if(S.contains(this,t[e]))return!0})},closest:function(e,t){var n,r=0,i=this.length,o=[],a="string"!=typeof e&&S(e);if(!k.test(e))for(;r<i;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(n.nodeType<11&&(a?-1<a.index(n):1===n.nodeType&&S.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(1<o.length?S.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?i.call(S(e),this[0]):i.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(S.uniqueSort(S.merge(this.get(),S(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),S.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return h(e,"parentNode")},parentsUntil:function(e,t,n){return h(e,"parentNode",n)},next:function(e){return O(e,"nextSibling")},prev:function(e){return O(e,"previousSibling")},nextAll:function(e){return h(e,"nextSibling")},prevAll:function(e){return h(e,"previousSibling")},nextUntil:function(e,t,n){return h(e,"nextSibling",n)},prevUntil:function(e,t,n){return h(e,"previousSibling",n)},siblings:function(e){return T((e.parentNode||{}).firstChild,e)},children:function(e){return T(e.firstChild)},contents:function(e){return null!=e.contentDocument&&r(e.contentDocument)?e.contentDocument:(A(e,"template")&&(e=e.content||e),S.merge([],e.childNodes))}},function(r,i){S.fn[r]=function(e,t){var n=S.map(this,i,e);return"Until"!==r.slice(-5)&&(t=e),t&&"string"==typeof t&&(n=S.filter(t,n)),1<this.length&&(H[r]||S.uniqueSort(n),L.test(r)&&n.reverse()),this.pushStack(n)}});var P=/[^\x20\t\r\n\f]+/g;function R(e){return e}function M(e){throw e}function I(e,t,n,r){var i;try{e&&m(i=e.promise)?i.call(e).done(t).fail(n):e&&m(i=e.then)?i.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n.apply(void 0,[e])}}S.Callbacks=function(r){var e,n;r="string"==typeof r?(e=r,n={},S.each(e.match(P)||[],function(e,t){n[t]=!0}),n):S.extend({},r);var i,t,o,a,s=[],u=[],l=-1,c=function(){for(a=a||r.once,o=i=!0;u.length;l=-1){t=u.shift();while(++l<s.length)!1===s[l].apply(t[0],t[1])&&r.stopOnFalse&&(l=s.length,t=!1)}r.memory||(t=!1),i=!1,a&&(s=t?[]:"")},f={add:function(){return s&&(t&&!i&&(l=s.length-1,u.push(t)),function n(e){S.each(e,function(e,t){m(t)?r.unique&&f.has(t)||s.push(t):t&&t.length&&"string"!==w(t)&&n(t)})}(arguments),t&&!i&&c()),this},remove:function(){return S.each(arguments,function(e,t){var n;while(-1<(n=S.inArray(t,s,n)))s.splice(n,1),n<=l&&l--}),this},has:function(e){return e?-1<S.inArray(e,s):0<s.length},empty:function(){return s&&(s=[]),this},disable:function(){return a=u=[],s=t="",this},disabled:function(){return!s},lock:function(){return a=u=[],t||i||(s=t=""),this},locked:function(){return!!a},fireWith:function(e,t){return a||(t=[e,(t=t||[]).slice?t.slice():t],u.push(t),i||c()),this},fire:function(){return f.fireWith(this,arguments),this},fired:function(){return!!o}};return f},S.extend({Deferred:function(e){var o=[["notify","progress",S.Callbacks("memory"),S.Callbacks("memory"),2],["resolve","done",S.Callbacks("once memory"),S.Callbacks("once memory"),0,"resolved"],["reject","fail",S.Callbacks("once memory"),S.Callbacks("once memory"),1,"rejected"]],i="pending",a={state:function(){return i},always:function(){return s.done(arguments).fail(arguments),this},"catch":function(e){return a.then(null,e)},pipe:function(){var i=arguments;return S.Deferred(function(r){S.each(o,function(e,t){var n=m(i[t[4]])&&i[t[4]];s[t[1]](function(){var e=n&&n.apply(this,arguments);e&&m(e.promise)?e.promise().progress(r.notify).done(r.resolve).fail(r.reject):r[t[0]+"With"](this,n?[e]:arguments)})}),i=null}).promise()},then:function(t,n,r){var u=0;function l(i,o,a,s){return function(){var n=this,r=arguments,e=function(){var e,t;if(!(i<u)){if((e=a.apply(n,r))===o.promise())throw new TypeError("Thenable self-resolution");t=e&&("object"==typeof e||"function"==typeof e)&&e.then,m(t)?s?t.call(e,l(u,o,R,s),l(u,o,M,s)):(u++,t.call(e,l(u,o,R,s),l(u,o,M,s),l(u,o,R,o.notifyWith))):(a!==R&&(n=void 0,r=[e]),(s||o.resolveWith)(n,r))}},t=s?e:function(){try{e()}catch(e){S.Deferred.exceptionHook&&S.Deferred.exceptionHook(e,t.stackTrace),u<=i+1&&(a!==M&&(n=void 0,r=[e]),o.rejectWith(n,r))}};i?t():(S.Deferred.getStackHook&&(t.stackTrace=S.Deferred.getStackHook()),C.setTimeout(t))}}return S.Deferred(function(e){o[0][3].add(l(0,e,m(r)?r:R,e.notifyWith)),o[1][3].add(l(0,e,m(t)?t:R)),o[2][3].add(l(0,e,m(n)?n:M))}).promise()},promise:function(e){return null!=e?S.extend(e,a):a}},s={};return S.each(o,function(e,t){var n=t[2],r=t[5];a[t[1]]=n.add,r&&n.add(function(){i=r},o[3-e][2].disable,o[3-e][3].disable,o[0][2].lock,o[0][3].lock),n.add(t[3].fire),s[t[0]]=function(){return s[t[0]+"With"](this===s?void 0:this,arguments),this},s[t[0]+"With"]=n.fireWith}),a.promise(s),e&&e.call(s,s),s},when:function(e){var n=arguments.length,t=n,r=Array(t),i=s.call(arguments),o=S.Deferred(),a=function(t){return function(e){r[t]=this,i[t]=1<arguments.length?s.call(arguments):e,--n||o.resolveWith(r,i)}};if(n<=1&&(I(e,o.done(a(t)).resolve,o.reject,!n),"pending"===o.state()||m(i[t]&&i[t].then)))return o.then();while(t--)I(i[t],a(t),o.reject);return o.promise()}});var W=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;S.Deferred.exceptionHook=function(e,t){C.console&&C.console.warn&&e&&W.test(e.name)&&C.console.warn("jQuery.Deferred exception: "+e.message,e.stack,t)},S.readyException=function(e){C.setTimeout(function(){throw e})};var F=S.Deferred();function $(){E.removeEventListener("DOMContentLoaded",$),C.removeEventListener("load",$),S.ready()}S.fn.ready=function(e){return F.then(e)["catch"](function(e){S.readyException(e)}),this},S.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--S.readyWait:S.isReady)||(S.isReady=!0)!==e&&0<--S.readyWait||F.resolveWith(E,[S])}}),S.ready.then=F.then,"complete"===E.readyState||"loading"!==E.readyState&&!E.documentElement.doScroll?C.setTimeout(S.ready):(E.addEventListener("DOMContentLoaded",$),C.addEventListener("load",$));var B=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if("object"===w(n))for(s in i=!0,n)B(e,t,s,n[s],!0,o,a);else if(void 0!==r&&(i=!0,m(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(S(e),n)})),t))for(;s<u;s++)t(e[s],n,a?r:r.call(e[s],s,t(e[s],n)));return i?e:l?t.call(e):u?t(e[0],n):o},_=/^-ms-/,z=/-([a-z])/g;function U(e,t){return t.toUpperCase()}function X(e){return e.replace(_,"ms-").replace(z,U)}var V=function(e){return 1===e.nodeType||9===e.nodeType||!+e.nodeType};function G(){this.expando=S.expando+G.uid++}G.uid=1,G.prototype={cache:function(e){var t=e[this.expando];return t||(t={},V(e)&&(e.nodeType?e[this.expando]=t:Object.defineProperty(e,this.expando,{value:t,configurable:!0}))),t},set:function(e,t,n){var r,i=this.cache(e);if("string"==typeof t)i[X(t)]=n;else for(r in t)i[X(r)]=t[r];return i},get:function(e,t){return void 0===t?this.cache(e):e[this.expando]&&e[this.expando][X(t)]},access:function(e,t,n){return void 0===t||t&&"string"==typeof t&&void 0===n?this.get(e,t):(this.set(e,t,n),void 0!==n?n:t)},remove:function(e,t){var n,r=e[this.expando];if(void 0!==r){if(void 0!==t){n=(t=Array.isArray(t)?t.map(X):(t=X(t))in r?[t]:t.match(P)||[]).length;while(n--)delete r[t[n]]}(void 0===t||S.isEmptyObject(r))&&(e.nodeType?e[this.expando]=void 0:delete e[this.expando])}},hasData:function(e){var t=e[this.expando];return void 0!==t&&!S.isEmptyObject(t)}};var Y=new G,Q=new G,J=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,K=/[A-Z]/g;function Z(e,t,n){var r,i;if(void 0===n&&1===e.nodeType)if(r="data-"+t.replace(K,"-$&").toLowerCase(),"string"==typeof(n=e.getAttribute(r))){try{n="true"===(i=n)||"false"!==i&&("null"===i?null:i===+i+""?+i:J.test(i)?JSON.parse(i):i)}catch(e){}Q.set(e,t,n)}else n=void 0;return n}S.extend({hasData:function(e){return Q.hasData(e)||Y.hasData(e)},data:function(e,t,n){return Q.access(e,t,n)},removeData:function(e,t){Q.remove(e,t)},_data:function(e,t,n){return Y.access(e,t,n)},_removeData:function(e,t){Y.remove(e,t)}}),S.fn.extend({data:function(n,e){var t,r,i,o=this[0],a=o&&o.attributes;if(void 0===n){if(this.length&&(i=Q.get(o),1===o.nodeType&&!Y.get(o,"hasDataAttrs"))){t=a.length;while(t--)a[t]&&0===(r=a[t].name).indexOf("data-")&&(r=X(r.slice(5)),Z(o,r,i[r]));Y.set(o,"hasDataAttrs",!0)}return i}return"object"==typeof n?this.each(function(){Q.set(this,n)}):B(this,function(e){var t;if(o&&void 0===e)return void 0!==(t=Q.get(o,n))?t:void 0!==(t=Z(o,n))?t:void 0;this.each(function(){Q.set(this,n,e)})},null,e,1<arguments.length,null,!0)},removeData:function(e){return this.each(function(){Q.remove(this,e)})}}),S.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=Y.get(e,t),n&&(!r||Array.isArray(n)?r=Y.access(e,t,S.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=S.queue(e,t),r=n.length,i=n.shift(),o=S._queueHooks(e,t);"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,function(){S.dequeue(e,t)},o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return Y.get(e,n)||Y.access(e,n,{empty:S.Callbacks("once memory").add(function(){Y.remove(e,[t+"queue",n])})})}}),S.fn.extend({queue:function(t,n){var e=2;return"string"!=typeof t&&(n=t,t="fx",e--),arguments.length<e?S.queue(this[0],t):void 0===n?this:this.each(function(){var e=S.queue(this,t,n);S._queueHooks(this,t),"fx"===t&&"inprogress"!==e[0]&&S.dequeue(this,t)})},dequeue:function(e){return this.each(function(){S.dequeue(this,e)})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=S.Deferred(),o=this,a=this.length,s=function(){--r||i.resolveWith(o,[o])};"string"!=typeof e&&(t=e,e=void 0),e=e||"fx";while(a--)(n=Y.get(o[a],e+"queueHooks"))&&n.empty&&(r++,n.empty.add(s));return s(),i.promise(t)}});var ee=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,te=new RegExp("^(?:([+-])=|)("+ee+")([a-z%]*)$","i"),ne=["Top","Right","Bottom","Left"],re=E.documentElement,ie=function(e){return S.contains(e.ownerDocument,e)},oe={composed:!0};re.getRootNode&&(ie=function(e){return S.contains(e.ownerDocument,e)||e.getRootNode(oe)===e.ownerDocument});var ae=function(e,t){return"none"===(e=t||e).style.display||""===e.style.display&&ie(e)&&"none"===S.css(e,"display")};function se(e,t,n,r){var i,o,a=20,s=r?function(){return r.cur()}:function(){return S.css(e,t,"")},u=s(),l=n&&n[3]||(S.cssNumber[t]?"":"px"),c=e.nodeType&&(S.cssNumber[t]||"px"!==l&&+u)&&te.exec(S.css(e,t));if(c&&c[3]!==l){u/=2,l=l||c[3],c=+u||1;while(a--)S.style(e,t,c+l),(1-o)*(1-(o=s()/u||.5))<=0&&(a=0),c/=o;c*=2,S.style(e,t,c+l),n=n||[]}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}var ue={};function le(e,t){for(var n,r,i,o,a,s,u,l=[],c=0,f=e.length;c<f;c++)(r=e[c]).style&&(n=r.style.display,t?("none"===n&&(l[c]=Y.get(r,"display")||null,l[c]||(r.style.display="")),""===r.style.display&&ae(r)&&(l[c]=(u=a=o=void 0,a=(i=r).ownerDocument,s=i.nodeName,(u=ue[s])||(o=a.body.appendChild(a.createElement(s)),u=S.css(o,"display"),o.parentNode.removeChild(o),"none"===u&&(u="block"),ue[s]=u)))):"none"!==n&&(l[c]="none",Y.set(r,"display",n)));for(c=0;c<f;c++)null!=l[c]&&(e[c].style.display=l[c]);return e}S.fn.extend({show:function(){return le(this,!0)},hide:function(){return le(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){ae(this)?S(this).show():S(this).hide()})}});var ce,fe,pe=/^(?:checkbox|radio)$/i,de=/<([a-z][^\/\0>\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),v.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="<textarea>x</textarea>",v.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="<option></option>",v.option=!!ce.lastChild;var ge={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,"",""]};function ye(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ve(e,t){for(var n=0,r=e.length;n<r;n++)Y.set(e[n],"globalEval",!t||Y.get(t[n],"globalEval"))}ge.tbody=ge.tfoot=ge.colgroup=ge.caption=ge.thead,ge.th=ge.td,v.option||(ge.optgroup=ge.option=[1,"<select multiple='multiple'>","</select>"]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d<h;d++)if((o=e[d])||0===o)if("object"===w(o))S.merge(p,o.nodeType?[o]:o);else if(me.test(o)){a=a||f.appendChild(t.createElement("div")),s=(de.exec(o)||["",""])[1].toLowerCase(),u=ge[s]||ge._default,a.innerHTML=u[1]+S.htmlPrefilter(o)+u[2],c=u[0];while(c--)a=a.lastChild;S.merge(p,a.childNodes),(a=f.firstChild).textContent=""}else p.push(t.createTextNode(o));f.textContent="",d=0;while(o=p[d++])if(r&&-1<S.inArray(o,r))i&&i.push(o);else if(l=ie(o),a=ye(f.appendChild(o),"script"),l&&ve(a),n){c=0;while(o=a[c++])he.test(o.type||"")&&n.push(o)}return f}var be=/^([^.]*)(?:\.(.+)|)/;function we(){return!0}function Te(){return!1}function Ce(e,t){return e===function(){try{return E.activeElement}catch(e){}}()==("focus"===t)}function Ee(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"!=typeof n&&(r=r||n,n=void 0),t)Ee(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Te;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return S().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=S.guid++)),e.each(function(){S.event.add(this,t,i,r,n)})}function Se(e,i,o){o?(Y.set(e,i,!1),S.event.add(e,i,{namespace:!1,handler:function(e){var t,n,r=Y.get(this,i);if(1&e.isTrigger&&this[i]){if(r.length)(S.event.special[i]||{}).delegateType&&e.stopPropagation();else if(r=s.call(arguments),Y.set(this,i,r),t=o(this,i),this[i](),r!==(n=Y.get(this,i))||t?Y.set(this,i,!1):n={},r!==n)return e.stopImmediatePropagation(),e.preventDefault(),n&&n.value}else r.length&&(Y.set(this,i,{value:S.event.trigger(S.extend(r[0],S.Event.prototype),r.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===Y.get(e,i)&&S.event.add(e,i,we)}S.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,y=Y.get(t);if(V(t)){n.handler&&(n=(o=n).handler,i=o.selector),i&&S.find.matchesSelector(re,i),n.guid||(n.guid=S.guid++),(u=y.events)||(u=y.events=Object.create(null)),(a=y.handle)||(a=y.handle=function(e){return"undefined"!=typeof S&&S.event.triggered!==e.type?S.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||"").match(P)||[""]).length;while(l--)d=g=(s=be.exec(e[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=S.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=S.event.special[d]||{},c=S.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&S.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(d,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),S.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,y=Y.hasData(e)&&Y.get(e);if(y&&(u=y.events)){l=(t=(t||"").match(P)||[""]).length;while(l--)if(d=g=(s=be.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d){f=S.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,y.handle)||S.removeEvent(e,d,y.handle),delete u[d])}else for(d in u)S.event.remove(e,d+t[l],n,r,!0);S.isEmptyObject(u)&&Y.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=new Array(arguments.length),u=S.event.fix(e),l=(Y.get(this,"events")||Object.create(null))[u.type]||[],c=S.event.special[u.type]||{};for(s[0]=u,t=1;t<arguments.length;t++)s[t]=arguments[t];if(u.delegateTarget=this,!c.preDispatch||!1!==c.preDispatch.call(this,u)){a=S.event.handlers.call(this,u,l),t=0;while((i=a[t++])&&!u.isPropagationStopped()){u.currentTarget=i.elem,n=0;while((o=i.handlers[n++])&&!u.isImmediatePropagationStopped())u.rnamespace&&!1!==o.namespace&&!u.rnamespace.test(o.namespace)||(u.handleObj=o,u.data=o.data,void 0!==(r=((S.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,s))&&!1===(u.result=r)&&(u.preventDefault(),u.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,u),u.result}},handlers:function(e,t){var n,r,i,o,a,s=[],u=t.delegateCount,l=e.target;if(u&&l.nodeType&&!("click"===e.type&&1<=e.button))for(;l!==this;l=l.parentNode||this)if(1===l.nodeType&&("click"!==e.type||!0!==l.disabled)){for(o=[],a={},n=0;n<u;n++)void 0===a[i=(r=t[n]).selector+" "]&&(a[i]=r.needsContext?-1<S(i,this).index(l):S.find(i,this,null,[l]).length),a[i]&&o.push(r);o.length&&s.push({elem:l,handlers:o})}return l=this,u<t.length&&s.push({elem:l,handlers:t.slice(u)}),s},addProp:function(t,e){Object.defineProperty(S.Event.prototype,t,{enumerable:!0,configurable:!0,get:m(e)?function(){if(this.originalEvent)return e(this.originalEvent)}:function(){if(this.originalEvent)return this.originalEvent[t]},set:function(e){Object.defineProperty(this,t,{enumerable:!0,configurable:!0,writable:!0,value:e})}})},fix:function(e){return e[S.expando]?e:new S.Event(e)},special:{load:{noBubble:!0},click:{setup:function(e){var t=this||e;return pe.test(t.type)&&t.click&&A(t,"input")&&Se(t,"click",we),!1},trigger:function(e){var t=this||e;return pe.test(t.type)&&t.click&&A(t,"input")&&Se(t,"click"),!0},_default:function(e){var t=e.target;return pe.test(t.type)&&t.click&&A(t,"input")&&Y.get(t,"click")||A(t,"a")}},beforeunload:{postDispatch:function(e){void 0!==e.result&&e.originalEvent&&(e.originalEvent.returnValue=e.result)}}}},S.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n)},S.Event=function(e,t){if(!(this instanceof S.Event))return new S.Event(e,t);e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||void 0===e.defaultPrevented&&!1===e.returnValue?we:Te,this.target=e.target&&3===e.target.nodeType?e.target.parentNode:e.target,this.currentTarget=e.currentTarget,this.relatedTarget=e.relatedTarget):this.type=e,t&&S.extend(this,t),this.timeStamp=e&&e.timeStamp||Date.now(),this[S.expando]=!0},S.Event.prototype={constructor:S.Event,isDefaultPrevented:Te,isPropagationStopped:Te,isImmediatePropagationStopped:Te,isSimulated:!1,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=we,e&&!this.isSimulated&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=we,e&&!this.isSimulated&&e.stopPropagation()},stopImmediatePropagation:function(){var e=this.originalEvent;this.isImmediatePropagationStopped=we,e&&!this.isSimulated&&e.stopImmediatePropagation(),this.stopPropagation()}},S.each({altKey:!0,bubbles:!0,cancelable:!0,changedTouches:!0,ctrlKey:!0,detail:!0,eventPhase:!0,metaKey:!0,pageX:!0,pageY:!0,shiftKey:!0,view:!0,"char":!0,code:!0,charCode:!0,key:!0,keyCode:!0,button:!0,buttons:!0,clientX:!0,clientY:!0,offsetX:!0,offsetY:!0,pointerId:!0,pointerType:!0,screenX:!0,screenY:!0,targetTouches:!0,toElement:!0,touches:!0,which:!0},S.event.addProp),S.each({focus:"focusin",blur:"focusout"},function(t,e){S.event.special[t]={setup:function(){return Se(this,t,Ce),!1},trigger:function(){return Se(this,t),!0},_default:function(e){return Y.get(e.target,t)},delegateType:e}}),S.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(e,i){S.event.special[e]={delegateType:i,bindType:i,handle:function(e){var t,n=e.relatedTarget,r=e.handleObj;return n&&(n===this||S.contains(this,n))||(e.type=r.origType,t=r.handler.apply(this,arguments),e.type=i),t}}}),S.fn.extend({on:function(e,t,n,r){return Ee(this,e,t,n,r)},one:function(e,t,n,r){return Ee(this,e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,S(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return!1!==t&&"function"!=typeof t||(n=t,t=void 0),!1===n&&(n=Te),this.each(function(){S.event.remove(this,e,n,t)})}});var ke=/<script|<style|<link/i,Ae=/checked\s*(?:[^=]|=\s*.checked.)/i,Ne=/^\s*<!\[CDATA\[|\]\]>\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n<r;n++)S.event.add(t,i,s[i][n]);Q.hasData(e)&&(o=Q.access(e),a=S.extend({},o),Q.set(t,a))}}function He(n,r,i,o){r=g(r);var e,t,a,s,u,l,c=0,f=n.length,p=f-1,d=r[0],h=m(d);if(h||1<f&&"string"==typeof d&&!v.checkClone&&Ae.test(d))return n.each(function(e){var t=n.eq(e);h&&(r[0]=d.call(this,e,t.html())),He(t,r,i,o)});if(f&&(t=(e=xe(r,n[0].ownerDocument,!1,n,o)).firstChild,1===e.childNodes.length&&(e=t),t||o)){for(s=(a=S.map(ye(e,"script"),De)).length;c<f;c++)u=e,c!==p&&(u=S.clone(u,!0,!0),s&&S.merge(a,ye(u,"script"))),i.call(n[c],u,c);if(s)for(l=a[a.length-1].ownerDocument,S.map(a,qe),c=0;c<s;c++)u=a[c],he.test(u.type||"")&&!Y.access(u,"globalEval")&&S.contains(l,u)&&(u.src&&"module"!==(u.type||"").toLowerCase()?S._evalUrl&&!u.noModule&&S._evalUrl(u.src,{nonce:u.nonce||u.getAttribute("nonce")},l):b(u.textContent.replace(Ne,""),u,l))}return n}function Oe(e,t,n){for(var r,i=t?S.filter(t,e):e,o=0;null!=(r=i[o]);o++)n||1!==r.nodeType||S.cleanData(ye(r)),r.parentNode&&(n&&ie(r)&&ve(ye(r,"script")),r.parentNode.removeChild(r));return e}S.extend({htmlPrefilter:function(e){return e},clone:function(e,t,n){var r,i,o,a,s,u,l,c=e.cloneNode(!0),f=ie(e);if(!(v.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||S.isXMLDoc(e)))for(a=ye(c),r=0,i=(o=ye(e)).length;r<i;r++)s=o[r],u=a[r],void 0,"input"===(l=u.nodeName.toLowerCase())&&pe.test(s.type)?u.checked=s.checked:"input"!==l&&"textarea"!==l||(u.defaultValue=s.defaultValue);if(t)if(n)for(o=o||ye(e),a=a||ye(c),r=0,i=o.length;r<i;r++)Le(o[r],a[r]);else Le(e,c);return 0<(a=ye(c,"script")).length&&ve(a,!f&&ye(e,"script")),c},cleanData:function(e){for(var t,n,r,i=S.event.special,o=0;void 0!==(n=e[o]);o++)if(V(n)){if(t=n[Y.expando]){if(t.events)for(r in t.events)i[r]?S.event.remove(n,r):S.removeEvent(n,r,t.handle);n[Y.expando]=void 0}n[Q.expando]&&(n[Q.expando]=void 0)}}}),S.fn.extend({detach:function(e){return Oe(this,e,!0)},remove:function(e){return Oe(this,e)},text:function(e){return B(this,function(e){return void 0===e?S.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return He(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||je(this,e).appendChild(e)})},prepend:function(){return He(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=je(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return He(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return He(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(S.cleanData(ye(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return S.clone(this,e,t)})},html:function(e){return B(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!ke.test(e)&&!ge[(de.exec(e)||["",""])[1].toLowerCase()]){e=S.htmlPrefilter(e);try{for(;n<r;n++)1===(t=this[n]||{}).nodeType&&(S.cleanData(ye(t,!1)),t.innerHTML=e);t=0}catch(e){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var n=[];return He(this,arguments,function(e){var t=this.parentNode;S.inArray(this,n)<0&&(S.cleanData(ye(this)),t&&t.replaceChild(e,this))},n)}}),S.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,a){S.fn[e]=function(e){for(var t,n=[],r=S(e),i=r.length-1,o=0;o<=i;o++)t=o===i?this:this.clone(!0),S(r[o])[a](t),u.apply(n,t.get());return this.pushStack(n)}});var Pe=new RegExp("^("+ee+")(?!px)[a-z%]+$","i"),Re=/^--/,Me=function(e){var t=e.ownerDocument.defaultView;return t&&t.opener||(t=C),t.getComputedStyle(e)},Ie=function(e,t,n){var r,i,o={};for(i in t)o[i]=e.style[i],e.style[i]=t[i];for(i in r=n.call(e),t)e.style[i]=o[i];return r},We=new RegExp(ne.join("|"),"i"),Fe="[\\x20\\t\\r\\n\\f]",$e=new RegExp("^"+Fe+"+|((?:^|[^\\\\])(?:\\\\.)*)"+Fe+"+$","g");function Be(e,t,n){var r,i,o,a,s=Re.test(t),u=e.style;return(n=n||Me(e))&&(a=n.getPropertyValue(t)||n[t],s&&(a=a.replace($e,"$1")),""!==a||ie(e)||(a=S.style(e,t)),!v.pixelBoxStyles()&&Pe.test(a)&&We.test(t)&&(r=u.width,i=u.minWidth,o=u.maxWidth,u.minWidth=u.maxWidth=u.width=a,a=n.width,u.width=r,u.minWidth=i,u.maxWidth=o)),void 0!==a?a+"":a}function _e(e,t){return{get:function(){if(!e())return(this.get=t).apply(this,arguments);delete this.get}}}!function(){function e(){if(l){u.style.cssText="position:absolute;left:-11111px;width:60px;margin-top:1px;padding:0;border:0",l.style.cssText="position:relative;display:block;box-sizing:border-box;overflow:scroll;margin:auto;border:1px;padding:1px;width:60%;top:1%",re.appendChild(u).appendChild(l);var e=C.getComputedStyle(l);n="1%"!==e.top,s=12===t(e.marginLeft),l.style.right="60%",o=36===t(e.right),r=36===t(e.width),l.style.position="absolute",i=12===t(l.offsetWidth/3),re.removeChild(u),l=null}}function t(e){return Math.round(parseFloat(e))}var n,r,i,o,a,s,u=E.createElement("div"),l=E.createElement("div");l.style&&(l.style.backgroundClip="content-box",l.cloneNode(!0).style.backgroundClip="",v.clearCloneStyle="content-box"===l.style.backgroundClip,S.extend(v,{boxSizingReliable:function(){return e(),r},pixelBoxStyles:function(){return e(),o},pixelPosition:function(){return e(),n},reliableMarginLeft:function(){return e(),s},scrollboxSize:function(){return e(),i},reliableTrDimensions:function(){var e,t,n,r;return null==a&&(e=E.createElement("table"),t=E.createElement("tr"),n=E.createElement("div"),e.style.cssText="position:absolute;left:-11111px;border-collapse:separate",t.style.cssText="border:1px solid",t.style.height="1px",n.style.height="9px",n.style.display="block",re.appendChild(e).appendChild(t).appendChild(n),r=C.getComputedStyle(t),a=parseInt(r.height,10)+parseInt(r.borderTopWidth,10)+parseInt(r.borderBottomWidth,10)===t.offsetHeight,re.removeChild(e)),a}}))}();var ze=["Webkit","Moz","ms"],Ue=E.createElement("div").style,Xe={};function Ve(e){var t=S.cssProps[e]||Xe[e];return t||(e in Ue?e:Xe[e]=function(e){var t=e[0].toUpperCase()+e.slice(1),n=ze.length;while(n--)if((e=ze[n]+t)in Ue)return e}(e)||e)}var Ge=/^(none|table(?!-c[ea]).+)/,Ye={position:"absolute",visibility:"hidden",display:"block"},Qe={letterSpacing:"0",fontWeight:"400"};function Je(e,t,n){var r=te.exec(t);return r?Math.max(0,r[2]-(n||0))+(r[3]||"px"):t}function Ke(e,t,n,r,i,o){var a="width"===t?1:0,s=0,u=0;if(n===(r?"border":"content"))return 0;for(;a<4;a+=2)"margin"===n&&(u+=S.css(e,n+ne[a],!0,i)),r?("content"===n&&(u-=S.css(e,"padding"+ne[a],!0,i)),"margin"!==n&&(u-=S.css(e,"border"+ne[a]+"Width",!0,i))):(u+=S.css(e,"padding"+ne[a],!0,i),"padding"!==n?u+=S.css(e,"border"+ne[a]+"Width",!0,i):s+=S.css(e,"border"+ne[a]+"Width",!0,i));return!r&&0<=o&&(u+=Math.max(0,Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-o-u-s-.5))||0),u}function Ze(e,t,n){var r=Me(e),i=(!v.boxSizingReliable()||n)&&"border-box"===S.css(e,"boxSizing",!1,r),o=i,a=Be(e,t,r),s="offset"+t[0].toUpperCase()+t.slice(1);if(Pe.test(a)){if(!n)return a;a="auto"}return(!v.boxSizingReliable()&&i||!v.reliableTrDimensions()&&A(e,"tr")||"auto"===a||!parseFloat(a)&&"inline"===S.css(e,"display",!1,r))&&e.getClientRects().length&&(i="border-box"===S.css(e,"boxSizing",!1,r),(o=s in e)&&(a=e[s])),(a=parseFloat(a)||0)+Ke(e,t,n||(i?"border":"content"),o,r,a)+"px"}function et(e,t,n,r,i){return new et.prototype.init(e,t,n,r,i)}S.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Be(e,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,gridArea:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnStart:!0,gridRow:!0,gridRowEnd:!0,gridRowStart:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=X(t),u=Re.test(t),l=e.style;if(u||(t=Ve(s)),a=S.cssHooks[t]||S.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];"string"===(o=typeof n)&&(i=te.exec(n))&&i[1]&&(n=se(e,t,i),o="number"),null!=n&&n==n&&("number"!==o||u||(n+=i&&i[3]||(S.cssNumber[s]?"":"px")),v.clearCloneStyle||""!==n||0!==t.indexOf("background")||(l[t]="inherit"),a&&"set"in a&&void 0===(n=a.set(e,n,r))||(u?l.setProperty(t,n):l[t]=n))}},css:function(e,t,n,r){var i,o,a,s=X(t);return Re.test(t)||(t=Ve(s)),(a=S.cssHooks[t]||S.cssHooks[s])&&"get"in a&&(i=a.get(e,!0,n)),void 0===i&&(i=Be(e,t,r)),"normal"===i&&t in Qe&&(i=Qe[t]),""===n||n?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),S.each(["height","width"],function(e,u){S.cssHooks[u]={get:function(e,t,n){if(t)return!Ge.test(S.css(e,"display"))||e.getClientRects().length&&e.getBoundingClientRect().width?Ze(e,u,n):Ie(e,Ye,function(){return Ze(e,u,n)})},set:function(e,t,n){var r,i=Me(e),o=!v.scrollboxSize()&&"absolute"===i.position,a=(o||n)&&"border-box"===S.css(e,"boxSizing",!1,i),s=n?Ke(e,u,n,a,i):0;return a&&o&&(s-=Math.ceil(e["offset"+u[0].toUpperCase()+u.slice(1)]-parseFloat(i[u])-Ke(e,u,"border",!1,i)-.5)),s&&(r=te.exec(t))&&"px"!==(r[3]||"px")&&(e.style[u]=t,t=S.css(e,u)),Je(0,t,s)}}}),S.cssHooks.marginLeft=_e(v.reliableMarginLeft,function(e,t){if(t)return(parseFloat(Be(e,"marginLeft"))||e.getBoundingClientRect().left-Ie(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}))+"px"}),S.each({margin:"",padding:"",border:"Width"},function(i,o){S.cssHooks[i+o]={expand:function(e){for(var t=0,n={},r="string"==typeof e?e.split(" "):[e];t<4;t++)n[i+ne[t]+o]=r[t]||r[t-2]||r[0];return n}},"margin"!==i&&(S.cssHooks[i+o].set=Je)}),S.fn.extend({css:function(e,t){return B(this,function(e,t,n){var r,i,o={},a=0;if(Array.isArray(t)){for(r=Me(e),i=t.length;a<i;a++)o[t[a]]=S.css(e,t[a],!1,r);return o}return void 0!==n?S.style(e,t,n):S.css(e,t)},e,t,1<arguments.length)}}),((S.Tween=et).prototype={constructor:et,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||S.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(S.cssNumber[n]?"":"px")},cur:function(){var e=et.propHooks[this.prop];return e&&e.get?e.get(this):et.propHooks._default.get(this)},run:function(e){var t,n=et.propHooks[this.prop];return this.options.duration?this.pos=t=S.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):et.propHooks._default.set(this),this}}).init.prototype=et.prototype,(et.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=S.css(e.elem,e.prop,""))&&"auto"!==t?t:0},set:function(e){S.fx.step[e.prop]?S.fx.step[e.prop](e):1!==e.elem.nodeType||!S.cssHooks[e.prop]&&null==e.elem.style[Ve(e.prop)]?e.elem[e.prop]=e.now:S.style(e.elem,e.prop,e.now+e.unit)}}}).scrollTop=et.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},S.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},S.fx=et.prototype.init,S.fx.step={};var tt,nt,rt,it,ot=/^(?:toggle|show|hide)$/,at=/queueHooks$/;function st(){nt&&(!1===E.hidden&&C.requestAnimationFrame?C.requestAnimationFrame(st):C.setTimeout(st,S.fx.interval),S.fx.tick())}function ut(){return C.setTimeout(function(){tt=void 0}),tt=Date.now()}function lt(e,t){var n,r=0,i={height:e};for(t=t?1:0;r<4;r+=2-t)i["margin"+(n=ne[r])]=i["padding"+n]=e;return t&&(i.opacity=i.width=e),i}function ct(e,t,n){for(var r,i=(ft.tweeners[t]||[]).concat(ft.tweeners["*"]),o=0,a=i.length;o<a;o++)if(r=i[o].call(n,t,e))return r}function ft(o,e,t){var n,a,r=0,i=ft.prefilters.length,s=S.Deferred().always(function(){delete u.elem}),u=function(){if(a)return!1;for(var e=tt||ut(),t=Math.max(0,l.startTime+l.duration-e),n=1-(t/l.duration||0),r=0,i=l.tweens.length;r<i;r++)l.tweens[r].run(n);return s.notifyWith(o,[l,n,t]),n<1&&i?t:(i||s.notifyWith(o,[l,1,0]),s.resolveWith(o,[l]),!1)},l=s.promise({elem:o,props:S.extend({},e),opts:S.extend(!0,{specialEasing:{},easing:S.easing._default},t),originalProperties:e,originalOptions:t,startTime:tt||ut(),duration:t.duration,tweens:[],createTween:function(e,t){var n=S.Tween(o,l.opts,e,t,l.opts.specialEasing[e]||l.opts.easing);return l.tweens.push(n),n},stop:function(e){var t=0,n=e?l.tweens.length:0;if(a)return this;for(a=!0;t<n;t++)l.tweens[t].run(1);return e?(s.notifyWith(o,[l,1,0]),s.resolveWith(o,[l,e])):s.rejectWith(o,[l,e]),this}}),c=l.props;for(!function(e,t){var n,r,i,o,a;for(n in e)if(i=t[r=X(n)],o=e[n],Array.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),(a=S.cssHooks[r])&&"expand"in a)for(n in o=a.expand(o),delete e[r],o)n in e||(e[n]=o[n],t[n]=i);else t[r]=i}(c,l.opts.specialEasing);r<i;r++)if(n=ft.prefilters[r].call(l,o,c,l.opts))return m(n.stop)&&(S._queueHooks(l.elem,l.opts.queue).stop=n.stop.bind(n)),n;return S.map(c,ct,l),m(l.opts.start)&&l.opts.start.call(o,l),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always),S.fx.timer(S.extend(u,{elem:o,anim:l,queue:l.opts.queue})),l}S.Animation=S.extend(ft,{tweeners:{"*":[function(e,t){var n=this.createTween(e,t);return se(n.elem,e,te.exec(t),n),n}]},tweener:function(e,t){m(e)?(t=e,e=["*"]):e=e.match(P);for(var n,r=0,i=e.length;r<i;r++)n=e[r],ft.tweeners[n]=ft.tweeners[n]||[],ft.tweeners[n].unshift(t)},prefilters:[function(e,t,n){var r,i,o,a,s,u,l,c,f="width"in t||"height"in t,p=this,d={},h=e.style,g=e.nodeType&&ae(e),y=Y.get(e,"fxshow");for(r in n.queue||(null==(a=S._queueHooks(e,"fx")).unqueued&&(a.unqueued=0,s=a.empty.fire,a.empty.fire=function(){a.unqueued||s()}),a.unqueued++,p.always(function(){p.always(function(){a.unqueued--,S.queue(e,"fx").length||a.empty.fire()})})),t)if(i=t[r],ot.test(i)){if(delete t[r],o=o||"toggle"===i,i===(g?"hide":"show")){if("show"!==i||!y||void 0===y[r])continue;g=!0}d[r]=y&&y[r]||S.style(e,r)}if((u=!S.isEmptyObject(t))||!S.isEmptyObject(d))for(r in f&&1===e.nodeType&&(n.overflow=[h.overflow,h.overflowX,h.overflowY],null==(l=y&&y.display)&&(l=Y.get(e,"display")),"none"===(c=S.css(e,"display"))&&(l?c=l:(le([e],!0),l=e.style.display||l,c=S.css(e,"display"),le([e]))),("inline"===c||"inline-block"===c&&null!=l)&&"none"===S.css(e,"float")&&(u||(p.done(function(){h.display=l}),null==l&&(c=h.display,l="none"===c?"":c)),h.display="inline-block")),n.overflow&&(h.overflow="hidden",p.always(function(){h.overflow=n.overflow[0],h.overflowX=n.overflow[1],h.overflowY=n.overflow[2]})),u=!1,d)u||(y?"hidden"in y&&(g=y.hidden):y=Y.access(e,"fxshow",{display:l}),o&&(y.hidden=!g),g&&le([e],!0),p.done(function(){for(r in g||le([e]),Y.remove(e,"fxshow"),d)S.style(e,r,d[r])})),u=ct(g?y[r]:0,r,p),r in y||(y[r]=u.start,g&&(u.end=u.start,u.start=0))}],prefilter:function(e,t){t?ft.prefilters.unshift(e):ft.prefilters.push(e)}}),S.speed=function(e,t,n){var r=e&&"object"==typeof e?S.extend({},e):{complete:n||!n&&t||m(e)&&e,duration:e,easing:n&&t||t&&!m(t)&&t};return S.fx.off?r.duration=0:"number"!=typeof r.duration&&(r.duration in S.fx.speeds?r.duration=S.fx.speeds[r.duration]:r.duration=S.fx.speeds._default),null!=r.queue&&!0!==r.queue||(r.queue="fx"),r.old=r.complete,r.complete=function(){m(r.old)&&r.old.call(this),r.queue&&S.dequeue(this,r.queue)},r},S.fn.extend({fadeTo:function(e,t,n,r){return this.filter(ae).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(t,e,n,r){var i=S.isEmptyObject(t),o=S.speed(e,n,r),a=function(){var e=ft(this,S.extend({},t),o);(i||Y.get(this,"finish"))&&e.stop(!0)};return a.finish=a,i||!1===o.queue?this.each(a):this.queue(o.queue,a)},stop:function(i,e,o){var a=function(e){var t=e.stop;delete e.stop,t(o)};return"string"!=typeof i&&(o=e,e=i,i=void 0),e&&this.queue(i||"fx",[]),this.each(function(){var e=!0,t=null!=i&&i+"queueHooks",n=S.timers,r=Y.get(this);if(t)r[t]&&r[t].stop&&a(r[t]);else for(t in r)r[t]&&r[t].stop&&at.test(t)&&a(r[t]);for(t=n.length;t--;)n[t].elem!==this||null!=i&&n[t].queue!==i||(n[t].anim.stop(o),e=!1,n.splice(t,1));!e&&o||S.dequeue(this,i)})},finish:function(a){return!1!==a&&(a=a||"fx"),this.each(function(){var e,t=Y.get(this),n=t[a+"queue"],r=t[a+"queueHooks"],i=S.timers,o=n?n.length:0;for(t.finish=!0,S.queue(this,a,[]),r&&r.stop&&r.stop.call(this,!0),e=i.length;e--;)i[e].elem===this&&i[e].queue===a&&(i[e].anim.stop(!0),i.splice(e,1));for(e=0;e<o;e++)n[e]&&n[e].finish&&n[e].finish.call(this);delete t.finish})}}),S.each(["toggle","show","hide"],function(e,r){var i=S.fn[r];S.fn[r]=function(e,t,n){return null==e||"boolean"==typeof e?i.apply(this,arguments):this.animate(lt(r,!0),e,t,n)}}),S.each({slideDown:lt("show"),slideUp:lt("hide"),slideToggle:lt("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,r){S.fn[e]=function(e,t,n){return this.animate(r,e,t,n)}}),S.timers=[],S.fx.tick=function(){var e,t=0,n=S.timers;for(tt=Date.now();t<n.length;t++)(e=n[t])()||n[t]!==e||n.splice(t--,1);n.length||S.fx.stop(),tt=void 0},S.fx.timer=function(e){S.timers.push(e),S.fx.start()},S.fx.interval=13,S.fx.start=function(){nt||(nt=!0,st())},S.fx.stop=function(){nt=null},S.fx.speeds={slow:600,fast:200,_default:400},S.fn.delay=function(r,e){return r=S.fx&&S.fx.speeds[r]||r,e=e||"fx",this.queue(e,function(e,t){var n=C.setTimeout(e,r);t.stop=function(){C.clearTimeout(n)}})},rt=E.createElement("input"),it=E.createElement("select").appendChild(E.createElement("option")),rt.type="checkbox",v.checkOn=""!==rt.value,v.optSelected=it.selected,(rt=E.createElement("input")).value="t",rt.type="radio",v.radioValue="t"===rt.value;var pt,dt=S.expr.attrHandle;S.fn.extend({attr:function(e,t){return B(this,S.attr,e,t,1<arguments.length)},removeAttr:function(e){return this.each(function(){S.removeAttr(this,e)})}}),S.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return"undefined"==typeof e.getAttribute?S.prop(e,t,n):(1===o&&S.isXMLDoc(e)||(i=S.attrHooks[t.toLowerCase()]||(S.expr.match.bool.test(t)?pt:void 0)),void 0!==n?null===n?void S.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:null==(r=S.find.attr(e,t))?void 0:r)},attrHooks:{type:{set:function(e,t){if(!v.radioValue&&"radio"===t&&A(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(P);if(i&&1===e.nodeType)while(n=i[r++])e.removeAttribute(n)}}),pt={set:function(e,t,n){return!1===t?S.removeAttr(e,n):e.setAttribute(n,n),n}},S.each(S.expr.match.bool.source.match(/\w+/g),function(e,t){var a=dt[t]||S.find.attr;dt[t]=function(e,t,n){var r,i,o=t.toLowerCase();return n||(i=dt[o],dt[o]=r,r=null!=a(e,t,n)?o:null,dt[o]=i),r}});var ht=/^(?:input|select|textarea|button)$/i,gt=/^(?:a|area)$/i;function yt(e){return(e.match(P)||[]).join(" ")}function vt(e){return e.getAttribute&&e.getAttribute("class")||""}function mt(e){return Array.isArray(e)?e:"string"==typeof e&&e.match(P)||[]}S.fn.extend({prop:function(e,t){return B(this,S.prop,e,t,1<arguments.length)},removeProp:function(e){return this.each(function(){delete this[S.propFix[e]||e]})}}),S.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&S.isXMLDoc(e)||(t=S.propFix[t]||t,i=S.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=S.find.attr(e,"tabindex");return t?parseInt(t,10):ht.test(e.nodeName)||gt.test(e.nodeName)&&e.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),v.optSelected||(S.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),S.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){S.propFix[this.toLowerCase()]=this}),S.fn.extend({addClass:function(t){var e,n,r,i,o,a;return m(t)?this.each(function(e){S(this).addClass(t.call(this,e,vt(this)))}):(e=mt(t)).length?this.each(function(){if(r=vt(this),n=1===this.nodeType&&" "+yt(r)+" "){for(o=0;o<e.length;o++)i=e[o],n.indexOf(" "+i+" ")<0&&(n+=i+" ");a=yt(n),r!==a&&this.setAttribute("class",a)}}):this},removeClass:function(t){var e,n,r,i,o,a;return m(t)?this.each(function(e){S(this).removeClass(t.call(this,e,vt(this)))}):arguments.length?(e=mt(t)).length?this.each(function(){if(r=vt(this),n=1===this.nodeType&&" "+yt(r)+" "){for(o=0;o<e.length;o++){i=e[o];while(-1<n.indexOf(" "+i+" "))n=n.replace(" "+i+" "," ")}a=yt(n),r!==a&&this.setAttribute("class",a)}}):this:this.attr("class","")},toggleClass:function(t,n){var e,r,i,o,a=typeof t,s="string"===a||Array.isArray(t);return m(t)?this.each(function(e){S(this).toggleClass(t.call(this,e,vt(this),n),n)}):"boolean"==typeof n&&s?n?this.addClass(t):this.removeClass(t):(e=mt(t),this.each(function(){if(s)for(o=S(this),i=0;i<e.length;i++)r=e[i],o.hasClass(r)?o.removeClass(r):o.addClass(r);else void 0!==t&&"boolean"!==a||((r=vt(this))&&Y.set(this,"__className__",r),this.setAttribute&&this.setAttribute("class",r||!1===t?"":Y.get(this,"__className__")||""))}))},hasClass:function(e){var t,n,r=0;t=" "+e+" ";while(n=this[r++])if(1===n.nodeType&&-1<(" "+yt(vt(n))+" ").indexOf(t))return!0;return!1}});var xt=/\r/g;S.fn.extend({val:function(n){var r,e,i,t=this[0];return arguments.length?(i=m(n),this.each(function(e){var t;1===this.nodeType&&(null==(t=i?n.call(this,e,S(this).val()):n)?t="":"number"==typeof t?t+="":Array.isArray(t)&&(t=S.map(t,function(e){return null==e?"":e+""})),(r=S.valHooks[this.type]||S.valHooks[this.nodeName.toLowerCase()])&&"set"in r&&void 0!==r.set(this,t,"value")||(this.value=t))})):t?(r=S.valHooks[t.type]||S.valHooks[t.nodeName.toLowerCase()])&&"get"in r&&void 0!==(e=r.get(t,"value"))?e:"string"==typeof(e=t.value)?e.replace(xt,""):null==e?"":e:void 0}}),S.extend({valHooks:{option:{get:function(e){var t=S.find.attr(e,"value");return null!=t?t:yt(S.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a="select-one"===e.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r<u;r++)if(((n=i[r]).selected||r===o)&&!n.disabled&&(!n.parentNode.disabled||!A(n.parentNode,"optgroup"))){if(t=S(n).val(),a)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=S.makeArray(t),a=i.length;while(a--)((r=i[a]).selected=-1<S.inArray(S.valHooks.option.get(r),o))&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),S.each(["radio","checkbox"],function(){S.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=-1<S.inArray(S(e).val(),t)}},v.checkOn||(S.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})}),v.focusin="onfocusin"in C;var bt=/^(?:focusinfocus|focusoutblur)$/,wt=function(e){e.stopPropagation()};S.extend(S.event,{trigger:function(e,t,n,r){var i,o,a,s,u,l,c,f,p=[n||E],d=y.call(e,"type")?e.type:e,h=y.call(e,"namespace")?e.namespace.split("."):[];if(o=f=a=n=n||E,3!==n.nodeType&&8!==n.nodeType&&!bt.test(d+S.event.triggered)&&(-1<d.indexOf(".")&&(d=(h=d.split(".")).shift(),h.sort()),u=d.indexOf(":")<0&&"on"+d,(e=e[S.expando]?e:new S.Event(d,"object"==typeof e&&e)).isTrigger=r?2:3,e.namespace=h.join("."),e.rnamespace=e.namespace?new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,e.result=void 0,e.target||(e.target=n),t=null==t?[e]:S.makeArray(t,[e]),c=S.event.special[d]||{},r||!c.trigger||!1!==c.trigger.apply(n,t))){if(!r&&!c.noBubble&&!x(n)){for(s=c.delegateType||d,bt.test(s+d)||(o=o.parentNode);o;o=o.parentNode)p.push(o),a=o;a===(n.ownerDocument||E)&&p.push(a.defaultView||a.parentWindow||C)}i=0;while((o=p[i++])&&!e.isPropagationStopped())f=o,e.type=1<i?s:c.bindType||d,(l=(Y.get(o,"events")||Object.create(null))[e.type]&&Y.get(o,"handle"))&&l.apply(o,t),(l=u&&o[u])&&l.apply&&V(o)&&(e.result=l.apply(o,t),!1===e.result&&e.preventDefault());return e.type=d,r||e.isDefaultPrevented()||c._default&&!1!==c._default.apply(p.pop(),t)||!V(n)||u&&m(n[d])&&!x(n)&&((a=n[u])&&(n[u]=null),S.event.triggered=d,e.isPropagationStopped()&&f.addEventListener(d,wt),n[d](),e.isPropagationStopped()&&f.removeEventListener(d,wt),S.event.triggered=void 0,a&&(n[u]=a)),e.result}},simulate:function(e,t,n){var r=S.extend(new S.Event,n,{type:e,isSimulated:!0});S.event.trigger(r,null,t)}}),S.fn.extend({trigger:function(e,t){return this.each(function(){S.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return S.event.trigger(e,t,n,!0)}}),v.focusin||S.each({focus:"focusin",blur:"focusout"},function(n,r){var i=function(e){S.event.simulate(r,e.target,S.event.fix(e))};S.event.special[r]={setup:function(){var e=this.ownerDocument||this.document||this,t=Y.access(e,r);t||e.addEventListener(n,i,!0),Y.access(e,r,(t||0)+1)},teardown:function(){var e=this.ownerDocument||this.document||this,t=Y.access(e,r)-1;t?Y.access(e,r,t):(e.removeEventListener(n,i,!0),Y.remove(e,r))}}});var Tt=C.location,Ct={guid:Date.now()},Et=/\?/;S.parseXML=function(e){var t,n;if(!e||"string"!=typeof e)return null;try{t=(new C.DOMParser).parseFromString(e,"text/xml")}catch(e){}return n=t&&t.getElementsByTagName("parsererror")[0],t&&!n||S.error("Invalid XML: "+(n?S.map(n.childNodes,function(e){return e.textContent}).join("\n"):e)),t};var St=/\[\]$/,kt=/\r?\n/g,At=/^(?:submit|button|image|reset|file)$/i,Nt=/^(?:input|select|textarea|keygen)/i;function jt(n,e,r,i){var t;if(Array.isArray(e))S.each(e,function(e,t){r||St.test(n)?i(n,t):jt(n+"["+("object"==typeof t&&null!=t?e:"")+"]",t,r,i)});else if(r||"object"!==w(e))i(n,e);else for(t in e)jt(n+"["+t+"]",e[t],r,i)}S.param=function(e,t){var n,r=[],i=function(e,t){var n=m(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(null==e)return"";if(Array.isArray(e)||e.jquery&&!S.isPlainObject(e))S.each(e,function(){i(this.name,this.value)});else for(n in e)jt(n,e[n],t,i);return r.join("&")},S.fn.extend({serialize:function(){return S.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=S.prop(this,"elements");return e?S.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!S(this).is(":disabled")&&Nt.test(this.nodeName)&&!At.test(e)&&(this.checked||!pe.test(e))}).map(function(e,t){var n=S(this).val();return null==n?null:Array.isArray(n)?S.map(n,function(e){return{name:t.name,value:e.replace(kt,"\r\n")}}):{name:t.name,value:n.replace(kt,"\r\n")}}).get()}});var Dt=/%20/g,qt=/#.*$/,Lt=/([?&])_=[^&]*/,Ht=/^(.*?):[ \t]*([^\r\n]*)$/gm,Ot=/^(?:GET|HEAD)$/,Pt=/^\/\//,Rt={},Mt={},It="*/".concat("*"),Wt=E.createElement("a");function Ft(o){return function(e,t){"string"!=typeof e&&(t=e,e="*");var n,r=0,i=e.toLowerCase().match(P)||[];if(m(t))while(n=i[r++])"+"===n[0]?(n=n.slice(1)||"*",(o[n]=o[n]||[]).unshift(t)):(o[n]=o[n]||[]).push(t)}}function $t(t,i,o,a){var s={},u=t===Mt;function l(e){var r;return s[e]=!0,S.each(t[e]||[],function(e,t){var n=t(i,o,a);return"string"!=typeof n||u||s[n]?u?!(r=n):void 0:(i.dataTypes.unshift(n),l(n),!1)}),r}return l(i.dataTypes[0])||!s["*"]&&l("*")}function Bt(e,t){var n,r,i=S.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&S.extend(!0,e,r),e}Wt.href=Tt.href,S.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Tt.href,type:"GET",isLocal:/^(?:about|app|app-storage|.+-extension|file|res|widget):$/.test(Tt.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":It,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":S.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?Bt(Bt(e,S.ajaxSettings),t):Bt(S.ajaxSettings,e)},ajaxPrefilter:Ft(Rt),ajaxTransport:Ft(Mt),ajax:function(e,t){"object"==typeof e&&(t=e,e=void 0),t=t||{};var c,f,p,n,d,r,h,g,i,o,y=S.ajaxSetup({},t),v=y.context||y,m=y.context&&(v.nodeType||v.jquery)?S(v):S.event,x=S.Deferred(),b=S.Callbacks("once memory"),w=y.statusCode||{},a={},s={},u="canceled",T={readyState:0,getResponseHeader:function(e){var t;if(h){if(!n){n={};while(t=Ht.exec(p))n[t[1].toLowerCase()+" "]=(n[t[1].toLowerCase()+" "]||[]).concat(t[2])}t=n[e.toLowerCase()+" "]}return null==t?null:t.join(", ")},getAllResponseHeaders:function(){return h?p:null},setRequestHeader:function(e,t){return null==h&&(e=s[e.toLowerCase()]=s[e.toLowerCase()]||e,a[e]=t),this},overrideMimeType:function(e){return null==h&&(y.mimeType=e),this},statusCode:function(e){var t;if(e)if(h)T.always(e[T.status]);else for(t in e)w[t]=[w[t],e[t]];return this},abort:function(e){var t=e||u;return c&&c.abort(t),l(0,t),this}};if(x.promise(T),y.url=((e||y.url||Tt.href)+"").replace(Pt,Tt.protocol+"//"),y.type=t.method||t.type||y.method||y.type,y.dataTypes=(y.dataType||"*").toLowerCase().match(P)||[""],null==y.crossDomain){r=E.createElement("a");try{r.href=y.url,r.href=r.href,y.crossDomain=Wt.protocol+"//"+Wt.host!=r.protocol+"//"+r.host}catch(e){y.crossDomain=!0}}if(y.data&&y.processData&&"string"!=typeof y.data&&(y.data=S.param(y.data,y.traditional)),$t(Rt,y,t,T),h)return T;for(i in(g=S.event&&y.global)&&0==S.active++&&S.event.trigger("ajaxStart"),y.type=y.type.toUpperCase(),y.hasContent=!Ot.test(y.type),f=y.url.replace(qt,""),y.hasContent?y.data&&y.processData&&0===(y.contentType||"").indexOf("application/x-www-form-urlencoded")&&(y.data=y.data.replace(Dt,"+")):(o=y.url.slice(f.length),y.data&&(y.processData||"string"==typeof y.data)&&(f+=(Et.test(f)?"&":"?")+y.data,delete y.data),!1===y.cache&&(f=f.replace(Lt,"$1"),o=(Et.test(f)?"&":"?")+"_="+Ct.guid+++o),y.url=f+o),y.ifModified&&(S.lastModified[f]&&T.setRequestHeader("If-Modified-Since",S.lastModified[f]),S.etag[f]&&T.setRequestHeader("If-None-Match",S.etag[f])),(y.data&&y.hasContent&&!1!==y.contentType||t.contentType)&&T.setRequestHeader("Content-Type",y.contentType),T.setRequestHeader("Accept",y.dataTypes[0]&&y.accepts[y.dataTypes[0]]?y.accepts[y.dataTypes[0]]+("*"!==y.dataTypes[0]?", "+It+"; q=0.01":""):y.accepts["*"]),y.headers)T.setRequestHeader(i,y.headers[i]);if(y.beforeSend&&(!1===y.beforeSend.call(v,T,y)||h))return T.abort();if(u="abort",b.add(y.complete),T.done(y.success),T.fail(y.error),c=$t(Mt,y,t,T)){if(T.readyState=1,g&&m.trigger("ajaxSend",[T,y]),h)return T;y.async&&0<y.timeout&&(d=C.setTimeout(function(){T.abort("timeout")},y.timeout));try{h=!1,c.send(a,l)}catch(e){if(h)throw e;l(-1,e)}}else l(-1,"No Transport");function l(e,t,n,r){var i,o,a,s,u,l=t;h||(h=!0,d&&C.clearTimeout(d),c=void 0,p=r||"",T.readyState=0<e?4:0,i=200<=e&&e<300||304===e,n&&(s=function(e,t,n){var r,i,o,a,s=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader("Content-Type"));if(r)for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+" "+u[0]]){o=i;break}a||(a=i)}o=o||a}if(o)return o!==u[0]&&u.unshift(o),n[o]}(y,T,n)),!i&&-1<S.inArray("script",y.dataTypes)&&S.inArray("json",y.dataTypes)<0&&(y.converters["text script"]=function(){}),s=function(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if("*"===o)o=u;else if("*"!==u&&u!==o){if(!(a=l[u+" "+o]||l["* "+o]))for(i in l)if((s=i.split(" "))[1]===o&&(a=l[u+" "+s[0]]||l["* "+s[0]])){!0===a?a=l[i]:!0!==l[i]&&(o=s[0],c.unshift(s[1]));break}if(!0!==a)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(e){return{state:"parsererror",error:a?e:"No conversion from "+u+" to "+o}}}return{state:"success",data:t}}(y,s,T,i),i?(y.ifModified&&((u=T.getResponseHeader("Last-Modified"))&&(S.lastModified[f]=u),(u=T.getResponseHeader("etag"))&&(S.etag[f]=u)),204===e||"HEAD"===y.type?l="nocontent":304===e?l="notmodified":(l=s.state,o=s.data,i=!(a=s.error))):(a=l,!e&&l||(l="error",e<0&&(e=0))),T.status=e,T.statusText=(t||l)+"",i?x.resolveWith(v,[o,l,T]):x.rejectWith(v,[T,l,a]),T.statusCode(w),w=void 0,g&&m.trigger(i?"ajaxSuccess":"ajaxError",[T,y,i?o:a]),b.fireWith(v,[T,l]),g&&(m.trigger("ajaxComplete",[T,y]),--S.active||S.event.trigger("ajaxStop")))}return T},getJSON:function(e,t,n){return S.get(e,t,n,"json")},getScript:function(e,t){return S.get(e,void 0,t,"script")}}),S.each(["get","post"],function(e,i){S[i]=function(e,t,n,r){return m(t)&&(r=r||n,n=t,t=void 0),S.ajax(S.extend({url:e,type:i,dataType:r,data:t,success:n},S.isPlainObject(e)&&e))}}),S.ajaxPrefilter(function(e){var t;for(t in e.headers)"content-type"===t.toLowerCase()&&(e.contentType=e.headers[t]||"")}),S._evalUrl=function(e,t,n){return S.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,converters:{"text script":function(){}},dataFilter:function(e){S.globalEval(e,t,n)}})},S.fn.extend({wrapAll:function(e){var t;return this[0]&&(m(e)&&(e=e.call(this[0])),t=S(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(n){return m(n)?this.each(function(e){S(this).wrapInner(n.call(this,e))}):this.each(function(){var e=S(this),t=e.contents();t.length?t.wrapAll(n):e.append(n)})},wrap:function(t){var n=m(t);return this.each(function(e){S(this).wrapAll(n?t.call(this,e):t)})},unwrap:function(e){return this.parent(e).not("body").each(function(){S(this).replaceWith(this.childNodes)}),this}}),S.expr.pseudos.hidden=function(e){return!S.expr.pseudos.visible(e)},S.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},S.ajaxSettings.xhr=function(){try{return new C.XMLHttpRequest}catch(e){}};var _t={0:200,1223:204},zt=S.ajaxSettings.xhr();v.cors=!!zt&&"withCredentials"in zt,v.ajax=zt=!!zt,S.ajaxTransport(function(i){var o,a;if(v.cors||zt&&!i.crossDomain)return{send:function(e,t){var n,r=i.xhr();if(r.open(i.type,i.url,i.async,i.username,i.password),i.xhrFields)for(n in i.xhrFields)r[n]=i.xhrFields[n];for(n in i.mimeType&&r.overrideMimeType&&r.overrideMimeType(i.mimeType),i.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest"),e)r.setRequestHeader(n,e[n]);o=function(e){return function(){o&&(o=a=r.onload=r.onerror=r.onabort=r.ontimeout=r.onreadystatechange=null,"abort"===e?r.abort():"error"===e?"number"!=typeof r.status?t(0,"error"):t(r.status,r.statusText):t(_t[r.status]||r.status,r.statusText,"text"!==(r.responseType||"text")||"string"!=typeof r.responseText?{binary:r.response}:{text:r.responseText},r.getAllResponseHeaders()))}},r.onload=o(),a=r.onerror=r.ontimeout=o("error"),void 0!==r.onabort?r.onabort=a:r.onreadystatechange=function(){4===r.readyState&&C.setTimeout(function(){o&&a()})},o=o("abort");try{r.send(i.hasContent&&i.data||null)}catch(e){if(o)throw e}},abort:function(){o&&o()}}}),S.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),S.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return S.globalEval(e),e}}}),S.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),S.ajaxTransport("script",function(n){var r,i;if(n.crossDomain||n.scriptAttrs)return{send:function(e,t){r=S("<script>").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Ut,Xt=[],Vt=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Xt.pop()||S.expando+"_"+Ct.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Vt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Vt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Vt,"$1"+r):!1!==e.jsonp&&(e.url+=(Et.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Xt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),v.createHTMLDocument=((Ut=E.implementation.createHTMLDocument("").body).innerHTML="<form></form><form></form>",2===Ut.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(v.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1<s&&(r=yt(e.slice(s)),e=e.slice(0,s)),m(t)?(n=t,t=void 0):t&&"object"==typeof t&&(i="POST"),0<a.length&&S.ajax({url:e,type:i||"GET",dataType:"html",data:t}).done(function(e){o=arguments,a.html(r?S("<div>").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return B(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=_e(v.pixelPosition,function(e,t){if(t)return t=Be(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return B(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0<arguments.length?this.on(n,null,e,t):this.trigger(n)}});var Gt=/^[\s\uFEFF\xA0]+|([^\s\uFEFF\xA0])[\s\uFEFF\xA0]+$/g;S.proxy=function(e,t){var n,r,i;if("string"==typeof t&&(n=e[t],t=e,e=n),m(e))return r=s.call(arguments,2),(i=function(){return e.apply(t||this,r.concat(s.call(arguments)))}).guid=e.guid=e.guid||S.guid++,i},S.holdReady=function(e){e?S.readyWait++:S.ready(!0)},S.isArray=Array.isArray,S.parseJSON=JSON.parse,S.nodeName=A,S.isFunction=m,S.isWindow=x,S.camelCase=X,S.type=w,S.now=Date.now,S.isNumeric=function(e){var t=S.type(e);return("number"===t||"string"===t)&&!isNaN(e-parseFloat(e))},S.trim=function(e){return null==e?"":(e+"").replace(Gt,"$1")},"function"==typeof define&&define.amd&&define("jquery",[],function(){return S});var Yt=C.jQuery,Qt=C.$;return S.noConflict=function(e){return C.$===S&&(C.$=Qt),e&&C.jQuery===S&&(C.jQuery=Yt),S},"undefined"==typeof e&&(C.jQuery=C.$=S),S}); diff --git a/website/agenda/planung/.htaccess b/website/agenda/planung/.htaccess index 9022838..bb80c71 100644 --- a/website/agenda/planung/.htaccess +++ b/website/agenda/planung/.htaccess @@ -18,3 +18,13 @@ LimitRequestBody 2000000000 Require all granted + +AddOutputFilterByType DEFLATE application/json +AddOutputFilterByType DEFLATE application/xml +AddOutputFilterByType DEFLATE application/json +AddOutputFilterByType DEFLATE application/json +AddOutputFilterByType DEFLATE text/css +AddOutputFilterByType DEFLATE text/javascript +AddOutputFilterByType DEFLATE text/html +AddOutputFilterByType DEFLATE text/plain + diff --git a/website/agenda/planung/assign-series.cgi b/website/agenda/planung/assign-series.cgi new file mode 100755 index 0000000..e2c0148 --- /dev/null +++ b/website/agenda/planung/assign-series.cgi @@ -0,0 +1,271 @@ +#!/usr/bin/perl + +use strict; +use warnings; +no warnings 'redefine'; + +use Data::Dumper; +use URI::Escape(); +use Encode(); + +use params(); +use config(); +use entry(); +use log(); +use template(); +use auth(); +use uac(); +use roles(); +use project(); +use studios(); +use events(); +use series(); +use series_schedule(); +use series_events(); +use series_dates(); +use markup(); +use localization(); + +binmode STDOUT, ":utf8"; + +my $r = shift; +( my $cgi, my $params, my $error ) = params::get($r); + +my $config = config::get('../config/config.cgi'); +my $debug = $config->{system}->{debug}; +my ( $user, $expires ) = auth::get_user( $config, $params, $cgi ); +return if ( !defined $user ) || ( $user eq '' ); + +my $user_presets = uac::get_user_presets( + $config, + { + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + user => $user + } +); +$params->{default_studio_id} = $user_presets->{studio_id}; +$params = uac::setDefaultStudio( $params, $user_presets ); +$params = uac::setDefaultProject( $params, $user_presets ); + +my $request = { + url => $ENV{QUERY_STRING} || '', + params => { + original => $params, + checked => check_params($params), + }, +}; +$request = uac::prepare_request( $request, $user_presets ); + +$params = $request->{params}->{checked}; + +#process header +my $headerParams = uac::set_template_permissions( $request->{permissions}, $params ); +$headerParams->{loc} = localization::get( $config, { user => $user, file => 'menu' } ); +template::process( $config, 'print', template::check( $config, 'assign-series-header.html' ), $headerParams ); +return unless uac::check( $config, $params, $user_presets ) == 1; + +my $permissions = $request->{permissions}; +unless ( $permissions->{scan_series_events} == 1 ) { + uac::permissions_denied('scan_series_events'); + return; +} + +if ( defined $params->{action} ) { + assign_series( $config, $request ) if $params->{action} eq 'assign_series'; + unassign_series( $config, $request ) if $params->{action} eq 'unassign_series'; +} +show_series( $config, $request ); + +sub show_series { + my $config = shift; + my $request = shift; + + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + unless ( $permissions->{assign_series_events} == 1 ) { + uac::permissions_denied('assign_series_events'); + return; + } + + my $projects = project::get( $config, { project_id => $params->{project_id} } ); + my $project = $projects->[0]; + return unless scalar @$projects == 1; + + my $studios = studios::get( $config, + { project_id => $params->{project_id}, studio_id => $params->{studio_id} } ); + my $studio = $studios->[0]; + return unless scalar @$studios == 1; + + my $project_name = $project->{name}; + my $studio_name = $studio->{location}; + + #get series_names + my $dbh = db::connect($config); + my $query = q{ + select project_id, studio_id, series_id, series_name, title + from calcms_series s, calcms_project_series ps + where s.id=ps.series_id + order by series_name, title + }; + my $results = db::get( $dbh, $query ); + + # get projects by id + my $projects_by_id = {}; + $projects = project::get($config); + for my $project (@$projects) { + $projects_by_id->{ $project->{project_id} } = $project; + } + + # get studios by id + my $studios_by_id = {}; + $studios = studios::get($config); + for my $studio (@$studios) { + $studios_by_id->{ $studio->{id} } = $studio; + } + + #add project and studio name to series + for my $result (@$results) { + $result->{project_name} = $projects_by_id->{ $result->{project_id} }->{name}; + $result->{studio_name} = $studios_by_id->{ $result->{studio_id} }->{location}; + $result->{series_name} = 'Einzelsendung' if $result->{series_name} eq '_single_'; + } + $params->{series} = $results; + + #fill template + $params->{project_name} = $project_name; + $params->{studio_name} = $studio_name; + + template::process( $config, 'print', $params->{template}, $params ); +} + +sub assign_series { + my $config = shift; + my $request = shift; + + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + unless ( $permissions->{assign_series_events} == 1 ) { + uac::permissions_denied('assign_series_events'); + return; + } + + my $entry = {}; + for my $attr ( 'project_id', 'studio_id', 'series_id' ) { + if ( defined $params->{$attr} ) { + $entry->{$attr} = $params->{$attr}; + } else { + uac::print_error( $attr . ' not given!' ); + return; + } + } + + $config->{access}->{write} = 1; + + #check if series is assigned to project/studio + my $series = series::get( + $config, + { + project_id => $entry->{project_id}, + studio_id => $entry->{studio_id}, + series_id => $entry->{series_id}, + } + ); + + if ( @$series == 0 ) { + + # assign series to project/studio + project::assign_series( + $config, + { + project_id => $entry->{project_id}, + studio_id => $entry->{studio_id}, + series_id => $entry->{series_id}, + } + ); + + } else { + print STDERR "ERROR: series $entry->{series_id} already assigned to project $entry->{project_id}, studio $entry->{studio_id}\n"; + } + + $config->{access}->{write} = 0; + uac::print_info("The series $entry->{series_id} successfully assigned to project $entry->{project_id} and studio $entry->{studio_id}"); + return; +} + +sub unassign_series { + my $config = shift; + my $request = shift; + + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + unless ( $permissions->{assign_series_events} == 1 ) { + uac::permissions_denied('assign_series_events'); + return; + } + + my $entry = {}; + for my $attr ( 'project_id', 'studio_id', 'series_id' ) { + if ( defined $params->{$attr} ) { + $entry->{$attr} = $params->{$attr}; + } else { + uac::print_error( $attr . ' not given!' ); + return; + } + } + + $config->{access}->{write} = 1; + + #check if series is assigned to project/studio + my $series = series::get( + $config, + { + project_id => $entry->{project_id}, + studio_id => $entry->{studio_id}, + series_id => $entry->{series_id}, + } + ); + + if ( @$series > 0 ) { + + # assign series to project/studio + project::unassign_series( + $config, + { + project_id => $entry->{project_id}, + studio_id => $entry->{studio_id}, + series_id => $entry->{series_id}, + } + ); + + } else { + print STDERR "series $entry->{series_id} is not assigned to project $entry->{project_id}, studio $entry->{studio_id}\n"; + } + + $config->{access}->{write} = 0; + uac::print_info("The series $entry->{series_id} was removed from the project $entry->{project_id} and the studio $entry->{studio_id}."); + return; +} + +sub check_params { + my $params = shift; + + my $checked = {}; + + $checked->{action} = entry::element_of( $params->{action}, ['assign_series','unassign_series'] ); + + $checked->{exclude} = 0; + entry::set_numbers( $checked, $params, [ + 'id', 'project_id', 'studio_id', 'series_id' + ]); + + if ( defined $checked->{studio_id} ) { + $checked->{default_studio_id} = $checked->{studio_id}; + } else { + $checked->{studio_id} = -1; + } + + $checked->{template} = template::check( $config, $params->{template}, 'assign-series' ); + + return $checked; +} diff --git a/website/agenda/planung/assign_series.cgi b/website/agenda/planung/assign_series.cgi deleted file mode 100755 index 08458f4..0000000 --- a/website/agenda/planung/assign_series.cgi +++ /dev/null @@ -1,251 +0,0 @@ -#! /usr/bin/perl -w - -use warnings "all"; -use strict; -use Data::Dumper; - -use params; -use config; -use log; -use template; -use auth; -use uac; -use roles; -use project; -use studios; -use events; -use series; -use series_schedule; -use series_events; -use series_dates; -use markup; -use URI::Escape; -use Encode; -use localization; - -binmode STDOUT, ":utf8"; - -my $r = shift; -( my $cgi, my $params, my $error ) = params::get($r); - -my $config = config::get('../config/config.cgi'); -my $debug = $config->{system}->{debug}; -my ( $user, $expires ) = auth::get_user( $cgi, $config ); -return if ( ( !defined $user ) || ( $user eq '' ) ); - -#print STDERR $params->{project_id}."\n"; -my $user_presets = uac::get_user_presets( - $config, - { - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - user => $user - } -); -$params->{default_studio_id} = $user_presets->{studio_id}; -$params->{studio_id} = $params->{default_studio_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); -$params->{project_id} = $user_presets->{project_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); - -#print STDERR $params->{project_id}."\n"; -my $request = { - url => $ENV{QUERY_STRING} || '', - params => { - original => $params, - checked => check_params($params), - }, -}; -$request = uac::prepare_request( $request, $user_presets ); -log::init($request); - -$params = $request->{params}->{checked}; - -#process header -my $headerParams = uac::set_template_permissions( $request->{permissions}, $params ); -$headerParams->{loc} = localization::get( $config, { user => $user, file => 'menu' } ); -template::process( 'print', template::check('default.html'), $headerParams ); -return unless uac::check( $config, $params, $user_presets ) == 1; - -print q{ - <script src="js/datetime.js" type="text/javascript"></script> - <script src="js/event.js" type="text/javascript"></script> - <script src="js/localization.js" type="text/javascript"></script> - <link rel="stylesheet" href="css/series.css" type="text/css" /> -}; - -my $permissions = $request->{permissions}; -unless ( $permissions->{scan_series_events} == 1 ) { - uac::permissions_denied('scan_series_events'); - return; -} - -if ( defined $params->{action} ) { - assign_series( $config, $request ) if ( $params->{action} eq 'assign_series' ); -} -show_events( $config, $request ); - -sub show_events { - my $config = shift; - my $request = shift; - - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - unless ( $permissions->{assign_series_events} == 1 ) { - uac::permissions_denied('assign_series_events'); - return; - } - - my $projects = project::get( $config, { project_id => $params->{project_id} } ); - my $project = $projects->[0]; - return unless ( @$projects == 1 ); - - my $studios = studios::get( $config, { project_id => $params->{project_id}, studio_id => $params->{studio_id} } ); - my $studio = $studios->[0]; - return unless ( @$studios == 1 ); - - my $project_name = $project->{name}; - my $studio_name = $studio->{location}; - - #get series_names - my $dbh = db::connect($config); - my $query = q{ - select project_id, studio_id, series_id, series_name, title - from calcms_series s, calcms_project_series ps - where s.id=ps.series_id - order by series_name, title - }; - my $results = db::get( $dbh, $query ); - - # get projects by id - my $projects_by_id = {}; - $projects = project::get($config); - for my $project (@$projects) { - $projects_by_id->{ $project->{project_id} } = $project; - } - - # get studios by id - my $studios_by_id = {}; - $studios = studios::get($config); - for my $studio (@$studios) { - $studios_by_id->{ $studio->{id} } = $studio; - } - - #add project and studio name to series - for my $result (@$results) { - $result->{project_name} = $projects_by_id->{ $result->{project_id} }->{name}; - $result->{studio_name} = $studios_by_id->{ $result->{studio_id} }->{location}; - $result->{series_name} = 'Einzelsendung' if $result->{series_name} eq '_single_'; - } - $params->{series} = $results; - - #fill template - $params->{project_name} = $project_name; - $params->{studio_name} = $studio_name; - - template::process( 'print', $params->{template}, $params ); -} - -sub assign_series { - my $config = shift; - my $request = shift; - - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - unless ( $permissions->{assign_series_events} == 1 ) { - uac::permissions_denied('assign_series_events'); - return; - } - - my $entry = {}; - for my $attr ( 'project_id', 'studio_id', 'series_id' ) { - if ( defined $params->{$attr} ) { - $entry->{$attr} = $params->{$attr}; - } else { - uac::print_error( $attr . ' not given!' ); - return; - } - } - - $config->{access}->{write} = 1; - - #check if series is assigned to project/studio - my $series = series::get( - $config, - { - project_id => $entry->{project_id}, - studio_id => $entry->{studio_id}, - series_id => $entry->{series_id}, - } - ); - - #print Dumper($series); - if ( @$series == 0 ) { - - # assign series to project/studio - project::assign_series( - $config, - { - project_id => $entry->{project_id}, - studio_id => $entry->{studio_id}, - series_id => $entry->{series_id}, - } - ); - - #print "assign\n"; - } else { - print STDERR -"event $entry->{event_id} already assigned to project $entry->{project_id}, studio $entry->{studio_id}, series $entry->{series_id}\n"; - - #print "is schon\n"; - } - - $config->{access}->{write} = 0; - uac::print_info("event successfully assigned to series"); -} - -sub check_params { - my $params = shift; - - my $checked = {}; - - my $debug = $params->{debug} || ''; - if ( $debug =~ /([a-z\_\,]+)/ ) { - $debug = $1; - } - $checked->{debug} = $debug; - - #actions and roles - $checked->{action} = ''; - if ( defined $params->{action} ) { - if ( $params->{action} =~ /^(assign_series)$/ ) { - $checked->{action} = $params->{action}; - } - } - - #numeric values - $checked->{exclude} = 0; - for my $param ( 'id', 'project_id', 'studio_id', 'series_id' ) { - if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /^\d+$/ ) ) { - $checked->{$param} = $params->{$param}; - } - } - - if ( defined $checked->{studio_id} ) { - $checked->{default_studio_id} = $checked->{studio_id}; - } else { - $checked->{studio_id} = -1; - } - - $checked->{template} = template::check( $params->{template}, 'assign_series' ); - - return $checked; -} - -__DATA__ - -SELECT ps.project_id, ps.studio_id, ps.series_id,p.name,s.name,se.series_name,se.title -FROM calcms_project_series ps ,calcms_projects p,calcms_studios s,calcms_series se -where ps.project_id=p.project_id and ps.studio_id=s.id and ps.series_id=se.id -order by se.series_name,p.name,s.name - diff --git a/website/agenda/planung/assignments.cgi b/website/agenda/planung/assignments.cgi index dbaaec3..87cc686 100755 --- a/website/agenda/planung/assignments.cgi +++ b/website/agenda/planung/assignments.cgi @@ -1,27 +1,29 @@ -#! /usr/bin/perl -w +#!/usr/bin/perl -use warnings "all"; use strict; -use Data::Dumper; +use warnings; +no warnings 'redefine'; -use params; -use config; -use log; -use template; -use auth; -use uac; -use roles; -use project; -use studios; -use events; -use series; -use series_schedule; -use series_events; -use series_dates; -use markup; -use URI::Escape; -use Encode; -use localization; +use URI::Escape(); +use Encode(); + +use params(); +use config(); +use entry(); +use log(); +use template(); +use auth(); +use uac(); +use roles(); +use project(); +use studios(); +use events(); +use series(); +use series_schedule(); +use series_events(); +use series_dates(); +use markup(); +use localization(); binmode STDOUT, ":utf8"; @@ -30,132 +32,120 @@ my $r = shift; my $config = config::get('../config/config.cgi'); my $debug = $config->{system}->{debug}; -my ( $user, $expires ) = auth::get_user( $cgi, $config ); +my ( $user, $expires ) = auth::get_user( $config, $params, $cgi ); return if ( ( !defined $user ) || ( $user eq '' ) ); #print STDERR $params->{project_id}."\n"; my $user_presets = uac::get_user_presets( - $config, - { - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - user => $user - } + $config, + { + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + user => $user + } ); $params->{default_studio_id} = $user_presets->{studio_id}; -$params->{studio_id} = $params->{default_studio_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); -$params->{project_id} = $user_presets->{project_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); +$params = uac::setDefaultStudio( $params, $user_presets ); +$params = uac::setDefaultProject( $params, $user_presets ); #print STDERR $params->{project_id}."\n"; my $request = { - url => $ENV{QUERY_STRING} || '', - params => { - original => $params, - checked => check_params($params), - }, + url => $ENV{QUERY_STRING} || '', + params => { + original => $params, + checked => check_params($params), + }, }; $request = uac::prepare_request( $request, $user_presets ); -log::init($request); $params = $request->{params}->{checked}; #process header my $headerParams = uac::set_template_permissions( $request->{permissions}, $params ); $headerParams->{loc} = localization::get( $config, { user => $user, file => 'menu' } ); -template::process( 'print', template::check('default.html'), $headerParams ); +template::process( $config, 'print', template::check( $config, 'assignments-header.html' ), $headerParams ); return unless uac::check( $config, $params, $user_presets ) == 1; -print q{ - <script src="js/datetime.js" type="text/javascript"></script> - <script src="js/event.js" type="text/javascript"></script> - <script src="js/localization.js" type="text/javascript"></script> - <link rel="stylesheet" href="css/series.css" type="text/css" /> -}; - my $permissions = $request->{permissions}; unless ( $permissions->{scan_series_events} == 1 ) { - uac::permissions_denied('scan_series_events'); - return; + uac::permissions_denied('scan_series_events'); + return; } if ( defined $params->{action} ) { - assign_events( $config, $request ) if ( $params->{action} eq 'assign_events' ); + assign_events( $config, $request ) if ( $params->{action} eq 'assign_events' ); } show_events( $config, $request ); sub show_events { - my $config = shift; - my $request = shift; + my $config = shift; + my $request = shift; - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - unless ( $permissions->{assign_series_events} == 1 ) { - uac::permissions_denied('assign_series_events'); - return; - } + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + unless ( $permissions->{assign_series_events} == 1 ) { + uac::permissions_denied('assign_series_events'); + return; + } - my $projects = project::get( $config, { project_id => $params->{project_id} } ); - my $project = $projects->[0]; + my $projects = project::get( $config, { project_id => $params->{project_id} } ); + my $project = $projects->[0]; - #print STDERR Dumper($project); - return unless ( @$projects == 1 ); + return unless ( @$projects == 1 ); - my $studios = studios::get( $config, { project_id => $params->{project_id}, studio_id => $params->{studio_id} } ); - my $studio = $studios->[0]; + my $studios = studios::get( $config, { project_id => $params->{project_id}, studio_id => $params->{studio_id} } ); + my $studio = $studios->[0]; - #print STDERR Dumper($studio); - return unless ( @$studios == 1 ); + return unless ( @$studios == 1 ); - my $project_name = $project->{name}; - my $studio_name = $studio->{location}; + my $project_name = $project->{name}; + my $studio_name = $studio->{location}; - #get series_names - my $dbh = db::connect($config); - my $query = q{ + #get series_names + my $dbh = db::connect($config); + my $query = q{ select project_id, studio_id, series_id, series_name, title from calcms_series s, calcms_project_series ps where s.id=ps.series_id order by series_name, title }; - my $results = db::get( $dbh, $query ); + my $results = db::get( $dbh, $query ); - # get projects by id - my $projects_by_id = {}; - $projects = project::get($config); - for my $project (@$projects) { - $projects_by_id->{ $project->{project_id} } = $project; - } + # get projects by id + my $projects_by_id = {}; + $projects = project::get($config); + for my $project (@$projects) { + $projects_by_id->{ $project->{project_id} } = $project; + } - # get studios by id - my $studios_by_id = {}; - $studios = studios::get($config); - for my $studio (@$studios) { - $studios_by_id->{ $studio->{id} } = $studio; - } + # get studios by id + my $studios_by_id = {}; + $studios = studios::get($config); + for my $studio (@$studios) { + $studios_by_id->{ $studio->{id} } = $studio; + } - #add project and studio name to series - for my $result (@$results) { - $result->{project_name} = $projects_by_id->{ $result->{project_id} }->{name}; - $result->{studio_name} = $studios_by_id->{ $result->{studio_id} }->{location}; - $result->{series_name} = 'Einzelsendung' if $result->{series_name} eq '_single_'; - } - $params->{series} = $results; + #add project and studio name to series + for my $result (@$results) { + $result->{project_name} = $projects_by_id->{ $result->{project_id} }->{name}; + $result->{studio_name} = $studios_by_id->{ $result->{studio_id} }->{location}; + $result->{series_name} = 'Einzelsendung' if $result->{series_name} eq '_single_'; + } + $params->{series} = $results; - # get events not assigned to series - my $conditions = []; - my $bind_values = []; - if ( $project_name ne '' ) { - push @$conditions, 'e.project=?'; - push @$bind_values, $project_name; - } - if ( $studio_name ne '' ) { - push @$conditions, 'e.location=?'; - push @$bind_values, $studio_name; - } - $conditions = ' and ' . join( ' and ', @$conditions ) if ( @$conditions > 0 ); - $query = qq{ + # get events not assigned to series + my $conditions = []; + my $bind_values = []; + if ( $project_name ne '' ) { + push @$conditions, 'e.project=?'; + push @$bind_values, $project_name; + } + if ( $studio_name ne '' ) { + push @$conditions, 'e.location=?'; + push @$bind_values, $studio_name; + } + $conditions = ' and ' . join( ' and ', @$conditions ) if scalar(@$conditions) > 0; + $query = qq{ select e.id, program, project, location, start, series_name, title, episode, rerun from calcms_events e left join calcms_series_events se on se.event_id =e.id where se.event_id is null @@ -163,253 +153,233 @@ sub show_events { order by series_name,title,start limit 1000 }; - print '<pre>' . Dumper($query) . Dumper($bind_values) . '</pre>'; - $results = db::get( $dbh, $query, $bind_values ); + $results = db::get( $dbh, $query, $bind_values ); - # detect title and episode - for my $result (@$results) { - $result->{rerun} .= ''; - if ( $result->{title} =~ /\#(\d+)([a-z])?\s*$/ ) { - $result->{episode} = $1 unless defined $result->{episode}; - $result->{rerun} = $2 || '' unless ( $result->{rerun} =~ /\d/ ); - $result->{title} =~ s/\#\d+[a-z]?\s*$//; - $result->{title} =~ s/\s+$//; - } - my $a = time::datetime_to_array( $result->{start} ); + # detect title and episode + my $weekdayNamesShort = time::getWeekdayNamesShort('de'); + for my $result (@$results) { + $result->{rerun} .= ''; + if ( $result->{title} =~ /\#(\d+)([a-z])?\s*$/ ) { + $result->{episode} = $1 unless defined $result->{episode}; + $result->{rerun} = $2 || '' unless ( $result->{rerun} =~ /\d/ ); + $result->{title} =~ s/\#\d+[a-z]?\s*$//; + $result->{title} =~ s/\s+$//; + } + my $a = time::datetime_to_array( $result->{start} ); - #print STDERR "($a->[0],$a->[1],$a->[2])\n"; - $result->{weekday} = time::weekday( $a->[0], $a->[1], $a->[2] ); - $result->{weekday} = $time::names->{de}->{weekdays_abbr}->[ $result->{weekday} - 1 ]; - } + #print STDERR "($a->[0],$a->[1],$a->[2])\n"; + $result->{weekday} = time::weekday( $a->[0], $a->[1], $a->[2] ); + $result->{weekday} = $weekdayNamesShort->[ $result->{weekday} - 1 ]; + } - #fill template - $params->{unassigned_events} = $results; - $params->{sum_events} = @$results; - $params->{project_name} = $project_name; - $params->{studio_name} = $studio_name; + #fill template + $params->{unassigned_events} = $results; + $params->{sum_events} = @$results; + $params->{project_name} = $project_name; + $params->{studio_name} = $studio_name; - template::process( 'print', $params->{template}, $params ); + template::process( $config, 'print', $params->{template}, $params ); } sub assign_events { - my $config = shift; - my $request = shift; + my $config = shift; + my $request = shift; - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - unless ( $permissions->{assign_series_events} == 1 ) { - uac::permissions_denied('assign_series_events'); - return; - } + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + unless ( $permissions->{assign_series_events} == 1 ) { + uac::permissions_denied('assign_series_events'); + return; + } - my $entry = {}; - for my $attr ( 'project_id', 'studio_id', 'series_id', 'event_ids' ) { - if ( defined $params->{$attr} ) { - $entry->{$attr} = $params->{$attr}; - } else { - uac::print_error( $attr . ' not given!' ); - return; - } - } + my $entry = {}; + for my $attr ( 'project_id', 'studio_id', 'series_id', 'event_ids' ) { + if ( defined $params->{$attr} ) { + $entry->{$attr} = $params->{$attr}; + } else { + uac::print_error( $attr . ' not given!' ); + return; + } + } - $config->{access}->{write} = 1; - for my $event_id ( split( /[\,\s]+/, $params->{event_ids} ) ) { - next unless $event_id =~ /^\d+/; - $entry->{event_id} = $event_id; + $config->{access}->{write} = 1; + for my $event_id ( split( /[\,\s]+/, $params->{event_ids} ) ) { + next unless $event_id =~ /^\d+/; + $entry->{event_id} = $event_id; - #get and parse event - my $request2 = { - params => { - checked => events::check_params( - $config, - { - event_id => $entry->{event_id}, - template => 'no', - limit => 1, - archive => 'all', - no_exclude => '1' - } - ) - }, - config => $request->{config}, - permissions => $request->{permissions} - }; - $request2->{params}->{checked}->{published} = 'all'; - my $events = events::get( $config, $request2 ); - my $event = $events->[0]; - unless ( defined $event ) { - print STDERR + #get and parse event + my $request2 = { + params => { + checked => events::check_params( + $config, + { + event_id => $entry->{event_id}, + template => 'no', + limit => 1, + archive => 'all', + } + ) + }, + config => $request->{config}, + permissions => $request->{permissions} + }; + $request2->{params}->{checked}->{published} = 'all'; + my $events = events::get( $config, $request2 ); + my $event = $events->[0]; + unless ( defined $event ) { + print STDERR "event not found for project $entry->{project_id}, studio $entry->{studio_id}, series $entry->{series_id}, event $entry->{event_id}\n"; - next; - } - print STDERR "'" . $event->{event_id} . "' '" . $event->{series_name} . "' '" . $event->{title} . "' '" . $event->{episode} . "'\n"; + next; + } + print STDERR "'" + . $event->{event_id} . "' '" + . $event->{series_name} . "' '" + . $event->{title} . "' '" + . $event->{episode} . "'\n"; - #next; + #next; - #check if series is assigned to project/studio - my $series = series::get( - $config, - { - project_id => $entry->{project_id}, - studio_id => $entry->{studio_id}, - series_id => $entry->{series_id}, - } - ); - if ( @$series == 0 ) { + #check if series is assigned to project/studio + my $series = series::get( + $config, + { + project_id => $entry->{project_id}, + studio_id => $entry->{studio_id}, + series_id => $entry->{series_id}, + } + ); + if ( scalar(@$series) == 0 ) { - # assign series to project/studio - project::assign_series( - $config, - { - project_id => $entry->{project_id}, - studio_id => $entry->{studio_id}, - series_id => $entry->{series_id}, - } - ); - } else { - print STDERR + # assign series to project/studio + project::assign_series( + $config, + { + project_id => $entry->{project_id}, + studio_id => $entry->{studio_id}, + series_id => $entry->{series_id}, + } + ); + } else { + print STDERR "event $entry->{event_id} already asigned to project $entry->{project_id}, studio $entry->{studio_id}, series $entry->{series_id}\n"; - } + } - #get series - $series = series::get( - $config, - { - project_id => $entry->{project_id}, - studio_id => $entry->{studio_id}, - series_id => $entry->{series_id}, - } - ); - if ( @$series == 1 ) { - my $serie = $series->[0]; + #get series + $series = series::get( + $config, + { + project_id => $entry->{project_id}, + studio_id => $entry->{studio_id}, + series_id => $entry->{series_id}, + } + ); + if ( scalar(@$series) == 1 ) { + my $serie = $series->[0]; - #set event's series name to value from series - my $series_name = $serie->{series_name} || ''; - if ( $series_name ne '' ) { + #set event's series name to value from series + my $series_name = $serie->{series_name} || ''; + if ( $series_name ne '' ) { - # prepend series_name from event to title on adding to single_events series - my $title = $event->{title}; - if ( $serie->{has_single_events} eq '1' ) { - $title = $event->{series_name} . ' - ' . $title if $event->{series_name} ne ''; - } + # prepend series_name from event to title on adding to single_events series + my $title = $event->{title}; + if ( $serie->{has_single_events} eq '1' ) { + $title = $event->{series_name} . ' - ' . $title if $event->{series_name} ne ''; + } - # save event content - series_events::save_content( - $config, - { - studio_id => $entry->{studio_id}, - id => $entry->{event_id}, #TODO: id=> event_id - series_name => $series_name, - title => $title, - episode => $event->{episode}, - rerun => $event->{rerun}, - modified_by => $params->{presets}->{user}, - } - ); + # save event content + series_events::save_content( + $config, + { + studio_id => $entry->{studio_id}, + id => $entry->{event_id}, #TODO: id=> event_id + series_name => $series_name, + title => $title, + episode => $event->{episode}, + rerun => $event->{rerun}, + modified_by => $params->{presets}->{user}, + } + ); - # add to history - $event->{project_id} = $entry->{project_id}; - $event->{studio_id} = $entry->{studio_id}; - $event->{series_id} = $entry->{series_id}; - $event->{event_id} = $entry->{event_id}; - $event->{series_name} = $series_name; - $event->{title} = $title; - $event->{user} = $params->{presets}->{user}; - event_history::insert( $config, $event ); + # add to history + $event->{project_id} = $entry->{project_id}; + $event->{studio_id} = $entry->{studio_id}; + $event->{series_id} = $entry->{series_id}; + $event->{event_id} = $entry->{event_id}; + $event->{series_name} = $series_name; + $event->{title} = $title; + $event->{user} = $params->{presets}->{user}; + event_history::insert( $config, $event ); - # print STDERR "ok\n"; - } - } else { - print STDERR "no series title found for studio $entry->{studio_id} series $entry->{series_id}, event $entry->{event_id}\n"; - next; - } + # print STDERR "ok\n"; + } + } else { + print STDERR +"no series title found for studio $entry->{studio_id} series $entry->{series_id}, event $entry->{event_id}\n"; + next; + } - #assign event - my $result = series::assign_event( - $config, - { - project_id => $entry->{project_id}, - studio_id => $entry->{studio_id}, - series_id => $entry->{series_id}, - event_id => $entry->{event_id}, - manual => 1 - } - ); - unless ( defined $result ) { - uac::print_error("error on assigning event to series"); - return undef; - } - } + #assign event + my $result = series::assign_event( + $config, + { + project_id => $entry->{project_id}, + studio_id => $entry->{studio_id}, + series_id => $entry->{series_id}, + event_id => $entry->{event_id}, + manual => 1 + } + ); + unless ( defined $result ) { + uac::print_error("error on assigning event to series"); + return undef; + } + } - $config->{access}->{write} = 0; - uac::print_info("event successfully assigned to series"); + $config->{access}->{write} = 0; + uac::print_info("event successfully assigned to series"); - #$params->{getBack}=1; + #$params->{getBack}=1; } sub check_params { - my $params = shift; + my $params = shift; - my $checked = {}; + my $checked = {}; - my $debug = $params->{debug} || ''; - if ( $debug =~ /([a-z\_\,]+)/ ) { - $debug = $1; - } - $checked->{debug} = $debug; + $checked->{action} = entry::element_of($params->{action}, ['assign_events']); - #actions and roles - $checked->{action} = ''; - if ( defined $params->{action} ) { - if ( $params->{action} =~ /^(assign_events)$/ ) { - $checked->{action} = $params->{action}; - } - } + $checked->{exclude} = 0; + entry::set_numbers( $checked, $params, [ + 'id', 'project_id', 'studio_id', 'series_id', 'event_id' + ]); - #numeric values - $checked->{exclude} = 0; - for my $param ( 'id', 'project_id', 'studio_id', 'series_id', 'event_id' ) { - if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /^\d+$/ ) ) { - $checked->{$param} = $params->{$param}; - } - } + for my $param ('event_ids') { + if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /^[\d,]+$/ ) ) { + $checked->{$param} = $params->{$param}; + } + } - for my $param ('event_ids') { - if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /^[\d,]+$/ ) ) { - $checked->{$param} = $params->{$param}; - } - } + if ( defined $checked->{studio_id} ) { + $checked->{default_studio_id} = $checked->{studio_id}; + } else { + $checked->{studio_id} = -1; + } - if ( defined $checked->{studio_id} ) { - $checked->{default_studio_id} = $checked->{studio_id}; - } else { - $checked->{studio_id} = -1; - } + $checked->{template} = template::check( $config, $params->{template}, 'assignments' ); - $checked->{template} = template::check( $params->{template}, 'assignments' ); + if ( ( defined $checked->{action} ) && ( $checked->{action} eq 'save_schedule' ) ) { - if ( ( defined $checked->{action} ) && ( $checked->{action} eq 'save_schedule' ) ) { + #set defaults + $checked->{create_events} = 0; + $checked->{publish_events} = 0; + } + entry::set_numbers( $checked, $params, [ + 'frequency', 'duration', 'default_duration', 'create_events', 'publish_events', 'live']); - #set defaults - $checked->{create_events} = 0; - $checked->{publish_events} = 0; - } - for my $param ( 'frequency', 'duration', 'default_duration', 'create_events', 'publish_events', 'live', 'count_episodes' ) { - if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /(\d+)/ ) ) { - $checked->{$param} = $1; - } - } + entry::set_strings( $checked, $params, + [ 'search', 'from', 'till' ]); - #scalars - for my $param ( 'search', 'from', 'till' ) { - if ( defined $params->{$param} ) { - $checked->{$param} = $params->{$param}; - $checked->{$param} =~ s/^\s+//g; - $checked->{$param} =~ s/\s+$//g; - } - } - - return $checked; + return $checked; } __DATA__ diff --git a/website/agenda/planung/audio-recordings.cgi b/website/agenda/planung/audio-recordings.cgi new file mode 100755 index 0000000..9523a38 --- /dev/null +++ b/website/agenda/planung/audio-recordings.cgi @@ -0,0 +1,566 @@ +#!/usr/bin/perl + +use strict; +use warnings; +no warnings 'redefine'; + +use Data::Dumper; +use CGI::Simple(); +use ModPerl::Util (); +use Date::Calc(); +use Time::Local(); +use File::Temp(); + +use config(); +use log(); +use entry(); +use localization(); +use auth(); +use uac(); +use studios(); +use series(); +use template(); +use audio_recordings(); +use events(); +use audio(); +use time(); + +#$|=1; +binmode STDOUT, ":utf8"; + +our $config = config::get('../config/config.cgi'); +our $debug = $config->{system}->{debug}; +my $base_dir = $config->{locations}->{base_dir}; + +my $tempDir = '/var/tmp'; +my $uploadLimit = 700_000_000; + +my %params = (); +my $error = ''; +my $cgi = undef; +my $fh = undef; + +#### simple CGI +$CGI::Simple::POST_MAX = $uploadLimit; +$CGI::Simple::DISABLE_UPLOADS = 0; + +$cgi = CGI::Simple->new; +my $filename = $cgi->param('upload'); +$fh = $cgi->upload($filename); +$error = $cgi->cgi_error() || ''; +%params = $cgi->Vars(); + +my $params = \%params; +binmode $fh if defined $fh; + +#print "Content-type:text/html; charset=UTF-8;\n\n"; +my ( $user, $expires ) = auth::get_user( $config, $params, $cgi ); +exit if ( !defined $user ) || ( $user eq '' ); + +my $user_presets = uac::get_user_presets( + $config, + { + user => $user, + project_id => $params->{project_id}, + studio_id => $params->{studio_id} + } +); + +$params->{default_studio_id} = $user_presets->{studio_id}; +$params = uac::setDefaultStudio( $params, $user_presets ); +$params = uac::setDefaultProject( $params, $user_presets ); + +my $request = { + url => $ENV{QUERY_STRING} || '', + params => { + original => $params, + checked => check_params( $config, $params ), + }, +}; + +$request = uac::prepare_request( $request, $user_presets ); + +$params = $request->{params}->{checked}; + +my $headerParams = uac::set_template_permissions( $request->{permissions}, $params ); +$headerParams->{loc} = localization::get( $config, { user => $user, file => 'menu' } ); +template::process( $config, 'print', template::check( $config, 'default.html' ), $headerParams ); + +exit unless uac::check( $config, $params, $user_presets ) == 1; +template::process( $config, 'print', template::check( $config, 'audio-recordings-header.html' ), $headerParams ) + unless params::isJson; + +my $permissions = $request->{permissions}; +$params->{action} = '' unless defined $params->{action}; +$params->{error} = $error || ''; + +if ( $params->{action} eq 'upload' ) { + uploadRecording( $config, $request ); +} elsif ( $params->{action} eq 'delete' ) { + deleteRecording( $config, $request ); +} + +showAudioRecordings( $config, $request ); + +print STDERR "$0 ERROR: " . $params->{error} . "\n" if $params->{error} ne ''; +$params->{loc} = + localization::get( $config, { user => $params->{presets}->{user}, file => 'event,comment' } ); +template::process( $config, 'print', $params->{template}, $params ); + +exit; + +sub uploadRecording { + my $config = shift; + my $request = shift; + + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + + unless ( $permissions->{upload_audio_recordings} == 1 ) { + uac::permissions_denied('upload_audio_recordings'); + return; + } + + for my $attr ( 'project_id', 'studio_id', 'series_id', 'event_id' ) { + unless ( defined $params->{$attr} ) { + uac::print_error( "missing " . $attr . " to upload productions" ); + return; + } + } + + if ( defined $fh ) { + print STDERR "upload\n"; + events::set_upload_status($config, {event_id=>$params->{event_id}, upload_status=>'uploading' }); + my $fileInfo = uploadFile( $config, $fh, $params->{event_id}, $user, $params->{upload} ); + $params->{error} .= $fileInfo->{error} if defined $fileInfo->{error}; + $params->{path} = $fileInfo->{path}; + $params->{size} = $fileInfo->{size}; + + #$params->{duration} = $fileInfo->{duration}; + if ($params->{error} eq ''){ + $params = updateDatabase( $config, $params, $user ) ; + events::set_upload_status($config, {event_id=>$params->{event_id}, upload_status=>'uploaded' }); + } + + } else { + print STDERR "could not get file handle\n"; + $params->{error} .= 'Could not get file handle'; + } + + if ( $params->{error} ne '' ) { + events::set_upload_status($config, {event_id=>$params->{event_id}, upload_status=>'upload failed' }); + if ( $params->{error} =~ /limit/ ) { + $params->{error} .= + "audio file size is limited to " + . int( $uploadLimit / 1000000 ) . " MB!" + . "Please make it smaller and try again!"; + } else { + $params->{error} .= "Error:'$error'"; + } + } +} + +# return 1 if file has been deleted +sub deleteFile { + my $file = shift; + return 0 unless defined $file; + + if ( -e $file ) { + if ( -w $file ) { + unlink $file; + + # check if file has been deleted + if ( -e $file ) { + uac::print_error("could not delete audio file '$file', $!\n"); + return 0; + } + } else { + uac::print_error("cannot delete audio file '$file', missing permissions\n"); + return 0; + } + } + return 1; +} + +sub deleteRecording { + my $config = shift; + my $request = shift; + + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + + unless ( $permissions->{delete_audio_recordings} == 1 ) { + uac::permissions_denied('delete_audio_recordings'); + return; + } + + for my $attr ( + 'project_id', 'studio_id', + + #'series_id', + 'event_id', 'path' + ) + { + unless ( defined $params->{$attr} ) { + uac::print_error( "missing " . $attr . " to delete production" ); + return; + } + } + + my $dbh = db::connect($config); + $config->{access}->{write} = 0; + + my $audioRecordings = audio_recordings::get( + $config, + { + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + event_id => $params->{event_id}, + path => $params->{path} + } + ); + + unless ( ( defined $audioRecordings ) && ( scalar @$audioRecordings > 0 ) ) { + uac::print_error("could not find audio file $params->{path} in database"); + return; + } + + my $targetDir = $config->{locations}->{local_audio_recordings_dir}; + unless ( defined $targetDir ) { + uac::print_error("'local_audio_recordings_dir' is not configured."); + return; + } + unless ( -d $targetDir ) { + uac::print_error("audio dir '$targetDir' does not exist"); + return; + } + + my $file = $targetDir . '/' . $params->{path}; + print STDERR "ERROR: cannot delete audio file '$file', file does not exist\n" unless -e $file; + + my $isDeleted = deleteFile($file); + return unless $isDeleted; + + $config->{access}->{write} = 1; + $audioRecordings = audio_recordings::delete( + $config, $dbh, + { + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + event_id => $params->{event_id}, + path => $params->{path}, + } + ); + $config->{access}->{write} = 0; + +} + +sub showAudioRecordings { + my $config = shift; + my $request = shift; + + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + + for my $attr ( 'project_id', 'studio_id', 'series_id', 'event_id' ) { + unless ( defined $params->{$attr} ) { + uac::print_error( "missing " . $attr . " to show productions" ); + return; + } + } + + my $event = series::get_event( + $config, + { + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + series_id => $params->{series_id}, + event_id => $params->{event_id} + } + ); + unless ( defined $event ) { + uac::print_error("event not found"); + return; + } + + my $audioRecordings = audio_recordings::get( + $config, + { + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + event_id => $params->{event_id}, + } + ); + for my $recording (@$audioRecordings) { + $recording->{size} =~ s/(\d)(\d\d\d)$/$1\.$2/g; + $recording->{size} =~ s/(\d)(\d\d\d\.\d\d\d)$/$1\.$2/g; + + $recording->{processed} = $recording->{processed} ? 'yes' : 'no'; + $recording->{mastered} = $recording->{mastered} ? 'yes' : 'no'; + + $recording->{eventDuration} = getDuration( $recording->{eventDuration} ); + $recording->{audioDuration} = audio::formatDuration( + $recording->{audioDuration}, + $recording->{eventDuration}, + getDuration( $recording->{audioDuration} ) + ); + + $recording->{rmsLeft} = audio::formatLoudness( $recording->{rmsLeft}, 'L:' ); + $recording->{rmsRight} = audio::formatLoudness( $recording->{rmsRight}, 'R:' ); + } + + my $now = time(); + my $timeZone = $config->{date}->{time_zone}; + my $start = time::datetime_to_utc( $event->{start}, $timeZone ); + my $end = time::datetime_to_utc( $event->{end}, $timeZone ); + if ( $now > $end ) { + uac::print_error("upload is expired due to the show is over"); + $params->{isOver} = 1; + } + my $days = 24 * 60 * 60; + uac::print_warn("show is more than a week ahead") if ( $now + 7 * $days ) < $start; + + $params->{event} = $event; + $params->{audio_recordings} = $audioRecordings; + +} + +sub getDuration { + my $duration = shift; + my $hour = int( $duration / 3600 ); + $duration -= $hour * 3600; + + my $minutes = int( $duration / 60 ); + $duration -= $minutes * 60; + + my $seconds = int($duration); + $duration -= $seconds; + + my $milli = int( 100 * $duration ); + return sprintf( "%02d:%02d:%02d.%02d", $hour, $minutes, $seconds, $milli ); +} + +sub uploadFile { + my $config = $_[0]; + my $fh = $_[1]; + my $eventId = $_[2]; + my $user = $_[3] || ''; + my $filename = $_[4] || ''; + + # check target directory + my $targetDir = $config->{locations}->{local_audio_recordings_dir}; + return { error => "could not find local_audio_recordings_dir" } unless defined $targetDir; + return { error => "local_audio_recordings_dir does not exist" } unless -e $targetDir; + + # save file to disk + my $userName = $user; + $userName =~ s/[^a-zA-Z0-9\.\-\_]//g; + + my $time = time::time_to_datetime(); + $time =~ s/\:/\-/g; + $time =~ s/\s/\_/g; + $time =~ s/[^a-zA-Z0-9\.\-\_]//g; + + my $extension =~ ( split( /\./, $filename) ) [-1]; + $filename =~ s/\.$extension$//; + $extension =~ s/[^a-zA-Z0-9\.\-\_]//g; + + $filename = join( '-', ( $time, 'id' . $eventId, $userName, $filename ) ); + $filename =~ s/[^a-zA-Z0-9\.\-\_]//g; + $filename .= $extension; + + my $tempFile = "$targetDir/$filename"; + print STDERR "tempFile=$tempFile\n"; + + my $start = time(); + open my $out, '>', $tempFile + or return { error => 'could not save upload. ' . $! . " " . $tempFile }; + binmode $out; + my $buffer=''; + print $out $buffer while read( $fh, $buffer, 4096 ); + close $out; + + my $size = (stat($tempFile))[7]; + + return { + dir => $targetDir, + path => $filename, + size => $size, + }; + +} + +sub updateDatabase { + my $config = shift; + my $params = shift; + my $user = shift; + + my $eventDuration = getEventDuration( $config, $params->{event_id} ); + + my $entry = { + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + event_id => $params->{event_id}, + path => $params->{path}, + size => $params->{size}, + created_by => $user, + eventDuration => $eventDuration + }; + + #connect + $config->{access}->{write} = 1; + my $dbh = db::connect($config); + + my $entries = audio_recordings::get( + $config, + { + project_id => $entry->{project_id}, + studio_id => $entry->{studio_id}, + event_id => $entry->{event_id}, + path => $entry->{path} + } + ); + + if ( ( defined $entries ) && ( scalar @$entries > 0 ) ) { + print STDERR "update\n"; + audio_recordings::update( $config, $dbh, $entry ); + my $entry = $entries->[0]; + $params->{id} = $entry->{id}; + } else { + print STDERR "insert\n"; + $entry->{created_by} = $user; + $entry->{processed} = 0; + $entry->{mastered} = 0; + $entry->{rmsLeft} = 0.0; + $entry->{rmsRight} = 0.0; + $entry->{audioDuration} = 0.0; + $entry->{modified_at} = time(); + $params->{id} = audio_recordings::insert( $config, $dbh, $entry ); + } + $config->{access}->{write} = 0; + $params->{action_result} = 'done!'; + + return $params; +} + +# return filename, filehandle and optionally error from upload +sub getFilename { + my $cgi = shift; + my $upload = shift; + + if ( defined $upload ) { + + # try apache2 module + my $filename = $upload->filename(); + return { + filename => $filename, + fh => $upload->fh(), + error => '' + }; + + } + + # fallback to CGI module + my $file = $cgi->param("upload"); + return { error => "is no file" } if ( defined $file ) && ( $file =~ /\|/ ); + + my $fileInfo = $cgi->uploadInfo($file); + + if ( defined $fileInfo ) { + my $filename = $fileInfo->{'Content-Disposition'} || ''; + if ( $filename =~ /filename=\"(.*?)\"/ ) { + $filename = $1; + return { + filename => $filename, + fh => $file, + error => '' + }; + + } + } + + #error + return { error => 'Could not detect file name!' }; +} + +# get extension and optionally error +sub checkFilename { + my $filename = shift; + + my @validExtensions = ('mp3','mp4','m4a','wav','ogg','flac'); + if ( $filename =~ /\.([a-zA-Z]{3,5})$/ ) { + my $extension = lc $1; + unless ( grep( /$extension/, @validExtensions ) ) { + return {error => 'Following file formats are supported: ' + . join( ",", @validExtensions ) + . '!' }; + } + return { + extension => $extension, + error => '' + }; + } + return {error => 'Not matching file extension found! Supported are: ' + . join( ",", @validExtensions ) + . '!' }; +} + +# return event duration in seconds +sub getEventDuration { + my $config = shift; + my $eventId = shift; + + if ( $eventId < 1 ) { + print STDERR "invalid eventId $eventId\n"; + return 0; + } + + my $request = { + params => { + checked => events::check_params( + $config, + { + event_id => $eventId, + template => 'no', + limit => 1, + } + ) + }, + config => $config + }; + $request->{params}->{checked}->{published} = 'all'; + my $events = events::get( $config, $request ); + if ( scalar @$events == 0 ) { + print STDERR "getEventDuration: no event found with event_id=$eventId\n"; + } + my $event = $events->[0]; + my $duration = + time::get_duration_seconds( $event->{start}, $event->{end}, $config->{date}->{time_zone} ); + return $duration; +} + +sub check_params { + my $config = shift; + my $params = shift; + + my $checked = {}; + $checked->{error} = ''; + $checked->{template} = template::check( $config, $params->{template}, 'upload-audio-recordings' ); + + entry::set_numbers( $checked, $params, [ + 'project_id', 'studio_id', 'default_studio_id', 'series_id', 'event_id', 'id']); + + if ( defined $checked->{studio_id} ) { + $checked->{default_studio_id} = $checked->{studio_id}; + } else { + $checked->{studio_id} = -1; + } + + $checked->{action} = entry::element_of( $params->{action}, ['upload', 'delete'] ); + + entry::set_strings( $checked, $params, [ 'name', 'description', 'path' ]); + + $checked->{upload} = $params->{upload}; + return $checked; +} + diff --git a/website/agenda/planung/audio_recordings.cgi b/website/agenda/planung/audio_recordings.cgi deleted file mode 100755 index 334f84c..0000000 --- a/website/agenda/planung/audio_recordings.cgi +++ /dev/null @@ -1,582 +0,0 @@ -#!/usr/bin/perl - -local $| = 0; - -use warnings; -use strict; - -use Data::Dumper; - -use CGI::Simple (); -use ModPerl::Util (); - -use Date::Calc; -use Time::Local; -use File::Temp; - -use config; -use log; -use localization; -use auth; -use uac; -use studios; -use series; -use template; -use audio_recordings; -use events; -use time; - -#$|=1; -binmode STDOUT, ":utf8"; - -my $useCgi = 0; - -our $config = config::get('../config/config.cgi'); -our $debug = $config->{system}->{debug}; -my $base_dir = $config->{locations}->{base_dir}; - -my $tempDir = '/var/tmp'; -my $uploadLimit = 200_000_000; - -my %params = (); -my $error = ''; -my $cgi = undef; -my $fh = undef; - -#### simple CGI -$CGI::Simple::POST_MAX = $uploadLimit; -$CGI::Simple::DISABLE_UPLOADS = 0; - -$cgi = $cgi = CGI::Simple->new; -my $filename = $cgi->param('upload'); -$fh = $cgi->upload($filename); -$error = $cgi->cgi_error() || ''; -%params = $cgi->Vars(); - -my $params = \%params; -binmode $fh if defined $fh; - -#print "Content-type:text/html; charset=UTF-8;\n\n"; -my ( $user, $expires ) = auth::get_user( $cgi, $config ); -exit if ( !defined $user ) || ( $user eq '' ); - -my $user_presets = uac::get_user_presets( - $config, - { - user => $user, - project_id => $params->{project_id}, - studio_id => $params->{studio_id} - } -); - -$params->{default_studio_id} = $user_presets->{studio_id}; -$params->{studio_id} = $params->{default_studio_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); -$params->{project_id} = $user_presets->{project_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); - -my $request = { - url => $ENV{QUERY_STRING} || '', - params => { - original => $params, - checked => check_params($params), - }, -}; - -#delete $params->{presets}; -#print Dumper($request->{params}->{checked}); - -$request = uac::prepare_request( $request, $user_presets ); -log::init($request); - -$params = $request->{params}->{checked}; - -my $headerParams = uac::set_template_permissions( $request->{permissions}, $params ); -$headerParams->{loc} = localization::get( $config, { user => $user, file => 'menu' } ); -template::process( 'print', template::check('default.html'), $headerParams ); - -exit unless defined uac::check( $config, $params, $user_presets ); - -print q{ - <script src="js/audio_recordings.js" type="text/javascript"></script> - <link rel="stylesheet" href="css/audio_recordings.css" type="text/css" /> -} unless (params::isJson); - -my $permissions = $request->{permissions}; -$params->{action} = '' unless defined $params->{action}; -$params->{error} = $error || ''; - -#print STDERR Dumper($params); - -if ( $params->{action} eq 'upload' ) { - uploadRecording( $config, $request ); -} elsif ( $params->{action} eq 'delete' ) { - deleteRecording( $config, $request ); -} - -showAudioRecordings( $config, $request ); - -print STDERR "$0 ERROR: " . $params->{error} . "\n" if $params->{error} ne ''; -$params->{loc} = localization::get( $config, { user => $params->{presets}->{user}, file => 'event,comment' } ); -template::process( 'print', $params->{template}, $params ); - -exit; - -sub uploadRecording { - my $config = shift; - my $request = shift; - - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - - unless ( $permissions->{upload_audio_recordings} == 1 ) { - uac::permissions_denied('upload_audio_recordings'); - return; - } - - for my $attr ( 'project_id', 'studio_id', 'series_id', 'event_id' ) { - unless ( defined $params->{$attr} ) { - uac::print_error( "missing " . $attr . " to upload productions" ); - return; - } - } - - if ( defined $fh ) { - print STDERR "upload\n"; - - #print STDERR Dumper($fh)."<br>"; - my $fileInfo = uploadFile( $config, $fh, $params->{event_id}, $user, $params->{upload} ); - $params->{error} .= $fileInfo->{error} if defined $fileInfo->{error}; - $params->{path} = $fileInfo->{path}; - $params->{size} = $fileInfo->{size}; - #$params->{duration} = $fileInfo->{duration}; - $params = updateDatabase( $config, $params, $user ) if $params->{error} eq ''; - } else { - $params->{error} .= 'Could not get file handle'; - } - - if ( $params->{error} ne '' ) { - if ( $params->{error} =~ /limit/ ) { - $params->{error} .= - "audio file size is limited to " . int( $uploadLimit / 1000000 ) . " MB!" . "Please make it smaller and try again!"; - } else { - $params->{error} .= "Error:'$error'"; - } - } -} - -# return 1 if file has been deleted -sub deleteFile { - my $file = shift; - return 0 unless defined $file; - - if ( -e $file ) { - if ( -w $file ) { - unlink $file; - - # check if file has been deleted - if ( -e $file ) { - uac::print_error("could not delete audio file '$file', $!\n"); - return 0; - } - } else { - uac::print_error("cannot delete audio file '$file', missing permissions\n"); - return 0; - } - } - return 1; -} - -sub deleteRecording { - my $config = shift; - my $request = shift; - - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - - unless ( $permissions->{delete_audio_recordings} == 1 ) { - uac::permissions_denied('delete_audio_recordings'); - return; - } - - for my $attr ( - 'project_id', 'studio_id', - - #'series_id', - 'event_id', 'path' - ) - { - unless ( defined $params->{$attr} ) { - uac::print_error( "missing " . $attr . " to delete production" ); - return; - } - } - - my $dbh = db::connect($config); - $config->{access}->{write} = 0; - - my $audioRecordings = audio_recordings::get( - $config, - { - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - event_id => $params->{event_id}, - path => $params->{path} - } - ); - - unless ( ( defined $audioRecordings ) && ( scalar @$audioRecordings > 0 ) ) { - uac::print_error("could not find audio file $params->{path} in database"); - return; - } - - my $targetDir = $config->{locations}->{local_audio_recordings_dir}; - unless ( defined $targetDir ) { - uac::print_error("'local_audio_recordings_dir' is not configured."); - return; - } - unless ( -d $targetDir ) { - uac::print_error("audio dir '$targetDir' does not exist"); - return; - } - - my $file = $targetDir . '/' . $params->{path}; - print STDERR "ERROR: cannot delete audio file '$file', file does not exist\n" unless -e $file; - - my $isDeleted = deleteFile($file); - return unless $isDeleted; - - $config->{access}->{write} = 1; - $audioRecordings = audio_recordings::delete( - $config, $dbh, - { - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - event_id => $params->{event_id}, - path => $params->{path}, - } - ); - $config->{access}->{write} = 0; - -} - -sub showAudioRecordings { - my $config = shift; - my $request = shift; - - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - - for my $attr ( 'project_id', 'studio_id', 'series_id', 'event_id' ) { - unless ( defined $params->{$attr} ) { - uac::print_error( "missing " . $attr . " to show productions" ); - return; - } - } - - my $event = series::get_event( - $config, - { - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - series_id => $params->{series_id}, - event_id => $params->{event_id} - } - ); - unless ( defined $event ) { - uac::print_error("event not found"); - return; - } - - #print '<pre>'.Dumper($event).'</pre>'; - - my $audioRecordings = audio_recordings::get( - $config, - { - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - event_id => $params->{event_id}, - } - ); - for my $recording (@$audioRecordings) { - $recording->{size} =~ s/(\d)(\d\d\d)$/$1\.$2/g; - $recording->{size} =~ s/(\d)(\d\d\d\.\d\d\d)$/$1\.$2/g; - - $recording->{processed} = $recording->{processed} ? 'yes' : 'no'; - $recording->{mastered} = $recording->{mastered} ? 'yes' : 'no'; - - $recording->{eventDuration} = getDuration( $recording->{eventDuration} ); - $recording->{audioDuration} = getDuration( $recording->{audioDuration} ); - - $recording->{rmsLeft} ||= '-'; - $recording->{rmsRight} ||= '-'; - } - - my $now = time(); - my $timeZone = $config->{date}->{time_zone}; - my $start = time::datetime_to_utc( $event->{start}, $timeZone ); - my $end = time::datetime_to_utc( $event->{end}, $timeZone ); - if ( $now > $end ) { - uac::print_error("upload is expired due to the show is over"); - $params->{isOver} = 1; - } - my $days = 24 * 60 * 60; - uac::print_warn("show is more than a week ahead") if ( $now + 7 * $days ) < $start; - - $params->{event} = $event; - $params->{audio_recordings} = $audioRecordings; - -} - -sub getDuration{ - my $duration=shift; - my $hour = int($duration / 3600); - $duration -= $hour * 3600; - - my $minutes = int($duration / 60); - $duration -= $minutes * 60; - - my $seconds = int($duration); - $duration -= $seconds; - - my $milli= int(100 * $duration); - return sprintf("%02d:%02d:%02d.%02d",$hour, $minutes, $seconds, $milli); -} - -sub uploadFile { - my $config = $_[0]; - my $fh = $_[1]; - my $eventId = $_[2]; - my $user = $_[3] || ''; - my $filename = $_[4] || ''; - - # check target directory - my $targetDir = $config->{locations}->{local_audio_recordings_dir}; - return { error => "could not find local_audio_recordings_dir" } unless defined $targetDir; - return { error => "local_audio_recordings_dir does not exist" } unless -e $targetDir; - - # save file to disk - my $userName = $user; - $userName =~ s/[^a-zA-Z0-9\.\-\_]//g; - - my $time = time::time_to_datetime(); - $time =~ s/\:/\-/g; - $time =~ s/\s/\_/g; - $time =~ s/[^a-zA-Z0-9\.\-\_]//g; - - $filename =~ s/\.(mp3)$//g; - $filename = join( '-', ( $time, 'id' . $eventId, $userName, $filename ) ) . '.mp3'; - $filename =~ s/[^a-zA-Z0-9\.\-\_]//g; - - my $tempFile = $targetDir . '/' . $filename; - print STDERR "tempFile=$tempFile\n"; - - my $start = time(); - open DAT, '>', $tempFile or return { error => 'could not save upload. ' . $! . " " . $tempFile }; - binmode DAT; - my $size = 0; - my $data = ''; - while ( my $bytesRead = $fh->read( $data, 65000 ) ) { - print DAT $data; - $size += $bytesRead; - $data = ''; - } - close DAT; - - return { - dir => $targetDir, - path => $filename, - size => $size, - }; - -} - -sub updateDatabase { - my $config = shift; - my $params = shift; - my $user = shift; - - my $eventDuration = getEventDuration($config, $params->{event_id}); - - my $entry = { - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - event_id => $params->{event_id}, - path => $params->{path}, - size => $params->{size}, - created_by => $user, - eventDuration => $eventDuration - }; - #print STDERR "updateDatabase:" . Dumper($entry); - - #connect - $config->{access}->{write} = 1; - my $dbh = db::connect($config); - - my $entries = audio_recordings::get( - $config, - { - project_id => $entry->{project_id}, - studio_id => $entry->{studio_id}, - event_id => $entry->{event_id}, - path => $entry->{path} - } - ); - - if ( ( defined $entries ) && ( scalar @$entries > 0 ) ) { - print STDERR "update\n"; - audio_recordings::update( $config, $dbh, $entry ); - my $entry = $entries->[0]; - $params->{id} = $entry->{id}; - } else { - print STDERR "insert\n"; - $entry->{created_by} = $user; - $entry->{processed} = 0; - $entry->{mastered} = 0; - $entry->{rmsLeft} = 0.0; - $entry->{rmsRight} = 0.0; - $entry->{audioDuration} = 0.0; - $entry->{modified_at} = time(); - $params->{id} = audio_recordings::insert( $config, $dbh, $entry ); - } - $config->{access}->{write} = 0; - $params->{action_result} = 'done!'; - - return $params; -} - -# return filename, filehandle and optionally error from upload -sub getFilename { - my $cgi = shift; - my $upload = shift; - - if ( defined $upload ) { - - # try apache2 module - my $filename = $upload->filename(); - return { - filename => $filename, - fh => $upload->fh(), - error => '' - }; - - } - - #print STDERR "cgi:".Dumper($cgi); - - # fallback to CGI module - my $file = $cgi->param("upload"); - return { error => "is no file" } if ( defined $file ) && ( $file =~ /\|/ ); - - #print STDERR "file:".Dumper($file); - my $fileInfo = $cgi->uploadInfo($file); - - #print STDERR "fileInfo:".Dumper($fileInfo); - - if ( defined $fileInfo ) { - my $filename = $fileInfo->{'Content-Disposition'} || ''; - if ( $filename =~ /filename=\"(.*?)\"/ ) { - $filename = $1; - return { - filename => $filename, - fh => $file, - error => '' - }; - - } - } - - #error - return { error => 'Could not detect file name!' }; -} - -# get extension and optionally error -sub checkFilename { - my $filename = shift; - - my @validExtensions = ('mp3'); - if ( $filename =~ /\.([a-zA-Z]{3,5})$/ ) { - my $extension = lc $1; - unless ( grep( /$extension/, @validExtensions ) ) { - return { error => 'Following file formats are supported: ' . join( ",", @validExtensions ) . '!' }; - } - return { - extension => $extension, - error => '' - }; - } - return { error => 'Not matching file extension found! Supported are: ' . join( ",", @validExtensions ) . '!' }; -} - -# return event duration in seconds -sub getEventDuration{ - my $config = shift; - my $eventId = shift; - - if ($eventId<1){ - print STDERR "invalid eventId $eventId\n"; - return 0; - } - - my $request = { - params => { - checked => events::check_params( - $config, - { - event_id => $eventId, - template => 'no', - limit => 1, - } - ) - }, - config => $config - }; - my $events = events::get( $config, $request ); - if (scalar @$events == 0){ - print STDERR "getEventDuration: no event found with event_id=$eventId\n"; - }; - my $event = $events->[0]; - my $duration = time::get_duration_seconds( $event->{start}, $event->{end}, $config->{date}->{time_zone} ); - return $duration; -} - - -sub check_params { - my $params = shift; - - my $checked = {}; - $checked->{error} = ''; - $checked->{template} = template::check( $params->{template}, 'upload_audio_recordings' ); - - #print Dumper($params); - #numeric values - for my $param ( 'project_id', 'studio_id', 'default_studio_id', 'series_id', 'event_id', 'id' ) { - if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /^\d+$/ ) ) { - $checked->{$param} = $params->{$param}; - } - } - - if ( defined $checked->{studio_id} ) { - $checked->{default_studio_id} = $checked->{studio_id}; - } else { - $checked->{studio_id} = -1; - } - - #word - for my $param ( 'debug', 'name', 'description' ) { - if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /^\s*(.+?)\s*$/ ) ) { - $checked->{$param} = $1; - } - } - - # words - for my $attr ( 'action', 'path' ) { - if ( ( defined $params->{$attr} ) && ( $params->{$attr} =~ /(\S+)/ ) ) { - $checked->{$attr} = $params->{$attr}; - } - } - - $checked->{upload} = $params->{upload}; - return $checked; -} - diff --git a/website/agenda/planung/calendar.cgi b/website/agenda/planung/calendar.cgi index 2b9a700..bcd29d5 100755 --- a/website/agenda/planung/calendar.cgi +++ b/website/agenda/planung/calendar.cgi @@ -1,33 +1,40 @@ -#! /usr/bin/perl -w +#!/usr/bin/perl -use warnings "all"; use strict; -use Data::Dumper; -use URI::Escape; -use Encode; +use warnings; +no warnings 'redefine'; + use utf8; -use params; -use config; -use log; -use template; -use calendar; -use auth; -use uac; -use roles; -use project; -use studios; -use events; -use series; -use markup; -use series_dates; -use studio_timeslot_dates; -use work_dates; -use playout; -use markup; -use user_settings; -use localization; -use DateTime; +use Data::Dumper; +use URI::Escape(); +use DateTime(); + +use utf8(); +use params(); +use config(); +use entry(); +use log(); +use entry(); +use template(); +use calendar(); +use auth(); +use uac(); +use roles(); +use project(); +use studios(); +use events(); +use series(); +use series_dates(); +use markup(); +use localization(); +use studio_timeslot_dates(); +use work_dates(); +use playout(); +use user_settings(); +use audio_recordings(); +use audio(); +use user_day_start(); binmode STDOUT, ":utf8"; @@ -36,115 +43,101 @@ my $r = shift; my $config = config::get('../config/config.cgi'); my $debug = $config->{system}->{debug}; -my ( $user, $expires ) = auth::get_user( $cgi, $config ); -return if ( ( !defined $user ) || ( $user eq '' ) ); +my ( $user, $expires ) = auth::get_user( $config, $params, $cgi ); +return if ( !defined $user ) || ( $user eq '' ); +$config->{user} = $user; my $user_presets = uac::get_user_presets( - $config, - { - user => $user, - project_id => $params->{project_id}, - studio_id => $params->{studio_id} - } + $config, + { + user => $user, + project_id => $params->{project_id}, + studio_id => $params->{studio_id} + } ); $params->{default_studio_id} = $user_presets->{studio_id}; -$params->{project_id} = $user_presets->{project_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); +$params = uac::setDefaultStudio( $params, $user_presets ); $params->{expires} = $expires; -#print STDERR Dumper($params); - my $scriptName = 'calendar.cgi'; #add "all" studio to select box unshift @{ $user_presets->{studios} }, { - id => -1, - name => '-all-' + id => -1, + name => '-all-' }; # select studios, TODO: do in JS if ( $params->{studio_id} eq '-1' ) { - for my $studio ( @{ $user_presets->{studios} } ) { - delete $studio->{selected}; - $studio->{selected} = 1 if $params->{studio_id} eq $studio->{id}; - } + for my $studio ( @{ $user_presets->{studios} } ) { + delete $studio->{selected}; + $studio->{selected} = 1 if $params->{studio_id} eq $studio->{id}; + } } my $request = { - url => $ENV{QUERY_STRING} || '', - params => { - original => $params, - checked => check_params( $params, $config ), - }, + url => $ENV{QUERY_STRING} || '', + params => { + original => $params, + checked => check_params( $config, $params ), + }, }; - $request = uac::prepare_request( $request, $user_presets ); -log::init($request); - $params = $request->{params}->{checked}; -#print STDERR Dumper($request); if ( - ( - ( defined $params->{action} ) && ( ( $params->{action} eq 'show' ) - || ( $params->{action} eq 'edit_event' ) ) - ) - || ( $params->{part} == 1 ) + ( + ( defined $params->{action} ) && ( ( $params->{action} eq 'show' ) + || ( $params->{action} eq 'edit_event' ) ) + ) + || ( $params->{part} == 1 ) ) { - print "Content-type:text/html; charset=UTF-8;\n\n"; + print "Content-type:text/html; charset=UTF-8;\n\n"; } else { - #process header - my $headerParams = uac::set_template_permissions( $request->{permissions}, $params ); - $headerParams->{loc} = localization::get( $config, { user => $user, file => 'menu' } ); - template::process( 'print', template::check('default.html'), $headerParams ); - print q{ - <link href="css/jquery-ui-timepicker.css" type="text/css" rel="stylesheet" /> - <link rel="stylesheet" href="css/calendar.css" type="text/css" /> - - <script src="js/jquery-ui-timepicker.js" type="text/javascript"></script> - <script src="js/calendar.js" type="text/javascript"></script> - <script src="js/datetime.js" type="text/javascript"></script> - }; - if ( $params->{list} eq '1' ) { - print q{ - <!--<link href="css/theme.default.css" rel="stylesheet">--> + #process header + my $headerParams = uac::set_template_permissions( $request->{permissions}, $params ); + $headerParams->{loc} = localization::get( $config, { user => $user, file => 'menu' } ); + template::process( $config, 'print', template::check( $config, 'calendar-header.html' ), + $headerParams ); + if ( $params->{list} eq '1' ) { + print q{ <script src="js/jquery.tablesorter.min.js"></script> - <script src="js/jquery.tablesorter.widgets.min.js"></script> + <style>#content{ top:5rem; position:relative; }</style> }; - } + } } if ( defined $user_presets->{error} ) { - print "<br><br>"; - uac::print_error( $user_presets->{error} ); - return; + print "<br><br>"; + uac::print_error( $user_presets->{error} ); + return; } $config->{access}->{write} = 0; unless ( defined $params->{project_id} ) { - uac::print_error("Please select a project"); - return; + uac::print_error("Please select a project"); + return; } if ( $params->{project_id} ne '-1' ) { - if ( project::check( $config, { project_id => $params->{project_id} } ) ne '1' ) { - uac::print_error("invalid project"); - return; - } + if ( project::check( $config, { project_id => $params->{project_id} } ) ne '1' ) { + uac::print_error("invalid project"); + return; + } } unless ( defined $params->{studio_id} ) { - uac::print_error("Please select a studio"); - return; + uac::print_error("Please select a studio"); + return; } if ( $params->{studio_id} ne '-1' ) { - if ( studios::check( $config, { studio_id => $params->{studio_id} } ) ne '1' ) { - uac::print_error("invalid studio"); - return; - } + if ( studios::check( $config, { studio_id => $params->{studio_id} } ) ne '1' ) { + uac::print_error("invalid studio"); + return; + } } my $start_of_day = $params->{day_start}; @@ -154,286 +147,340 @@ our $hour_height = 60; our $yzoom = 1.5; showCalendar( - $config, $request, - { - hour_height => $hour_height, - yzoom => $yzoom, - start_of_day => $start_of_day, - end_of_day => $end_of_day, - } + $config, $request, + { + hour_height => $hour_height, + yzoom => $yzoom, + start_of_day => $start_of_day, + end_of_day => $end_of_day, + } ); sub showCalendar { - my $config = shift; - my $request = shift; - my $cal_options = shift; + my $config = shift; + my $request = shift; + my $cal_options = shift; - my $hour_height = $cal_options->{hour_height}; - my $yzoom = $cal_options->{yzoom}; - my $start_of_day = $cal_options->{start_of_day}; - my $end_of_day = $cal_options->{end_of_day}; + my $hour_height = $cal_options->{hour_height}; + my $yzoom = $cal_options->{yzoom}; + my $start_of_day = $cal_options->{start_of_day}; + my $end_of_day = $cal_options->{end_of_day}; - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - unless ( $permissions->{read_series} == 1 ) { - uac::permissions_denied('read_series'); - return; - } + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions} || {}; + unless ( $permissions->{read_series} == 1 ) { + uac::permissions_denied('read_series'); + return; + } - #get range from user settings - my $user_settings = user_settings::get( $config, { user => $params->{presets}->{user} } ); - $params->{range} = $user_settings->{range} unless defined $params->{range}; - $params->{range} = 28 unless defined $params->{range}; + #get range from user settings + my $user_settings = user_settings::get( $config, { user => $params->{presets}->{user} } ); + $params->{range} = $user_settings->{range} unless defined $params->{range}; + $params->{range} = 28 unless defined $params->{range}; - #get colors from user settings - print user_settings::getColorCss( $config, { user => $params->{presets}->{user} } ) if $params->{part} == 0; + #get colors from user settings + print user_settings::getColorCss( $config, { user => $params->{presets}->{user} } ) + if $params->{part} == 0; - $params->{loc} = localization::get( $config, { user => $params->{presets}->{user}, file => 'all,calendar' } ); - my $language = $user_settings->{language} || 'en'; - $params->{language} = $language; - print localization::getJavascript( $params->{loc} ) if $params->{part} == 0; + $params->{loc} = + localization::get( $config, { user => $params->{presets}->{user}, file => 'all,calendar' } ); + my $language = $user_settings->{language} || 'en'; + $params->{language} = $language; + print localization::getJavascript( $params->{loc} ) if $params->{part} == 0; - my $calendar = getCalendar( $config, $params, $language ); - my $options = {}; - my $events = []; + my $calendar = getCalendar( $config, $params, $language ); + my $options = {}; + my $events = []; - if ( ( $params->{part} == 1 ) || ( $params->{list} == 1 ) ) { + if ( ( $params->{part} == 1 ) || ( $params->{list} == 1 ) ) { - #set date range - my $from = $calendar->{from_date}; - my $till = $calendar->{till_date}; + #set date range + my $from = $calendar->{from_date}; + my $till = $calendar->{till_date}; - my $project_id = $params->{project_id}; - my $studio_id = $params->{studio_id}; + my $project_id = $params->{project_id}; + my $studio_id = $params->{studio_id}; - #build event filter - $options = { - project_id => $project_id, - template => 'no', - limit => 600, - get => 'no_content', - from_date => $from, - till_date => $till, - date_range_include => 1, - archive => 'all', - no_exclude => '1', - }; + #build event filter + $options = { + project_id => $project_id, + template => 'html', + limit => 600, + #get => 'no_content', + from_date => $from, + till_date => $till, + date_range_include => 1, + archive => 'all', + }; - # set options depending on switches - if ( $params->{studio_id} ne '-1' ) { - $options->{studio_id} = $studio_id; - my $location = $params->{presets}->{studio}->{location}; - $options->{location} = $location if $location =~ /\S/; - } + # set options depending on switches + if ( $params->{studio_id} ne '-1' ) { + $options->{studio_id} = $studio_id; + my $location = $params->{presets}->{studio}->{location}; + $options->{location} = $location if $location =~ /\S/; + } - if ( $params->{project_id} ne '-1' ) { - $options->{project_id} = $project_id; - my $project = $params->{presets}->{project}->{name}; - $options->{project} = $project if $project =~ /\S/; - } + if ( $params->{project_id} ne '-1' ) { + $options->{project_id} = $project_id; + my $project = $params->{presets}->{project}->{name}; + $options->{project} = $project if $project =~ /\S/; + } - if ( defined $params->{series_id} ) { - $options->{series_id} = $params->{series_id}; - delete $options->{from_date}; - delete $options->{till_date}; - delete $options->{date_range_include}; - } + if ( defined $params->{series_id} ) { + $options->{series_id} = $params->{series_id}; + delete $options->{from_date}; + delete $options->{till_date}; + delete $options->{date_range_include}; + } - if ( $params->{search} =~ /\S/ ) { - $options->{search} = $params->{search}; - delete $options->{from_date} if ( $params->{list} == 1 ); - delete $options->{till_date} if ( $params->{list} == 1 ); - delete $options->{date_range_include} if ( $params->{list} == 1 ); - } - - $options->{draft}=0 unless $params->{list}==1; + if ( $params->{search} =~ /\S/ ) { + if ( $params->{list} == 1 ) { + $options->{search} = $params->{search}; + delete $options->{from_date}; + delete $options->{till_date}; + delete $options->{date_range_include}; + } + } + $options->{from_time} = '00:00' if defined $options->{from_date}; - #get events sorted by date - $events = getSeriesEvents( $config, $request, $options, $params ); - unless ( $params->{list} == 1 ) { - for my $event (@$events) { - $event->{origStart} = $event->{start}; - } - $events = break_dates( $events, $start_of_day ); - } + $options->{draft} = 0 unless $params->{list} == 1; - # recalc after break (for list only?) - for my $event (@$events) { + #get events sorted by date + $events = getSeriesEvents( $config, $request, $options, $params ); + unless ( $params->{list} == 1 ) { + for my $event (@$events) { + $event->{origStart} = $event->{start}; + $event->{origContent} = $event->{origContent}; + } + $events = break_dates( $events, $start_of_day ); + } - #if ($event->{splitCount}>0){ - delete $event->{day}; - delete $event->{start_date}; - delete $event->{end_date}; - $event = events::calc_dates( $config, $event ); + # recalc after break (for list only?) + for my $event (@$events) { + delete $event->{day}; + delete $event->{start_date}; + delete $event->{end_date}; + $event = events::calc_dates( $config, $event ); + } - #} - } + my $events_by_start = {}; + for my $event (@$events) { + $events_by_start->{ $event->{start} } = $event; + } - my $events_by_start = {}; - for my $event (@$events) { - $events_by_start->{ $event->{start} } = $event; - } + #build series filter + $options = { + project_id => $project_id, + studio_id => $studio_id, + from => $from, + till => $till, + date_range_include => 1, + exclude => 0 + }; - #build series filter - $options = { - project_id => $project_id, - studio_id => $studio_id, - from => $from, - till => $till, - date_range_include => 1, - exclude => 0 - }; + if ( defined $params->{series_id} ) { + $options->{series_id} = $params->{series_id}; + delete $options->{from}; + delete $options->{till}; + delete $options->{date_range_include}; + } - if ( defined $params->{series_id} ) { - $options->{series_id} = $params->{series_id}; - delete $options->{from}; - delete $options->{till}; - delete $options->{date_range_include}; - } + if ( $params->{search} =~ /\S/ ) { + $options->{search} = $params->{search}; + if ( $params->{list} == 1 ) { + delete $options->{from}; + delete $options->{till}; + delete $options->{date_range_include}; + } + } - if ( $params->{search} =~ /\S/ ) { - $options->{search} = $params->{search}; - delete $options->{from} if ( $params->{list} == 1 ); - delete $options->{till} if ( $params->{list} == 1 ); - delete $options->{date_range_include} if ( $params->{list} == 1 ); - } + #get all series dates + my $series_dates = series_dates::get_series( $config, $options ); + my $id = 0; + for my $date (@$series_dates) { + $date->{schedule} = 1; - #get all series dates - my $series_dates = series_dates::get_series( $config, $options ); - my $id = 0; - for my $date (@$series_dates) { - $date->{schedule} = 1; + #$date->{event_id}=-1; + $date->{event_id} = $id; + $date->{origStart} = $date->{start}; + delete $date->{day}; + delete $date->{start_date}; + delete $date->{end_date}; + $id++; + } + unless ( $params->{list} == 1 ) { + $series_dates = break_dates( $series_dates, $start_of_day ); + } - #$date->{event_id}=-1; - $date->{event_id} = $id; - $date->{origStart} = $date->{start}; - delete $date->{day}; - delete $date->{start_date}; - delete $date->{end_date}; - $id++; - } - unless ( $params->{list} == 1 ) { - $series_dates = break_dates( $series_dates, $start_of_day ); - } + #merge series and events + for my $date (@$series_dates) { + $date = events::calc_dates( $config, $date ); + push @$events, $date; + } - #merge series and events - for my $date (@$series_dates) { - $date = events::calc_dates( $config, $date ); - push @$events, $date; - } + #get timeslot_dates + my $studio_dates = studio_timeslot_dates::get( $config, $options ); - #get timeslot_dates - my $studio_dates = studio_timeslot_dates::get( $config, $options ); + $id = 0; + for my $date (@$studio_dates) { + $date->{grid} = 1; + $date->{series_id} = -1; - #print STDERR Dumper($options); - $id = 0; - for my $date (@$studio_dates) { - $date->{grid} = 1; - $date->{series_id} = -1; + #$date->{event_id}=-1; + $date->{event_id} = $id; + $date->{origStart} = $date->{start}; + delete $date->{day}; + delete $date->{start_date}; + delete $date->{end_date}; + $id++; + } + unless ( $params->{list} == 1 ) { + $studio_dates = break_dates( $studio_dates, $start_of_day ); + } - #$date->{event_id}=-1; - $date->{event_id} = $id; - $date->{origStart} = $date->{start}; - delete $date->{day}; - delete $date->{start_date}; - delete $date->{end_date}; - $id++; - } - unless ( $params->{list} == 1 ) { - $studio_dates = break_dates( $studio_dates, $start_of_day ); - } + for my $date (@$studio_dates) { + $date = events::calc_dates( $config, $date ); + push @$events, $date; + } - for my $date (@$studio_dates) { - $date = events::calc_dates( $config, $date ); - push @$events, $date; - } + #get work_dates + my $work_dates = work_dates::get( $config, $options ); + for my $date (@$work_dates) { + $date->{work} = 1; + $date->{series_id} = -1; + $date->{event_id} = -1; + $date->{origStart} = $date->{start}; + delete $date->{day}; + delete $date->{start_date}; + delete $date->{end_date}; + } + unless ( $params->{list} == 1 ) { + $work_dates = break_dates( $work_dates, $start_of_day ); + } - #get work_dates - my $work_dates = work_dates::get( $config, $options ); - for my $date (@$work_dates) { - $date->{work} = 1; - $date->{series_id} = -1; - $date->{event_id} = -1; - $date->{origStart} = $date->{start}; - delete $date->{day}; - delete $date->{start_date}; - delete $date->{end_date}; - } - unless ( $params->{list} == 1 ) { - $work_dates = break_dates( $work_dates, $start_of_day ); - } + for my $date (@$work_dates) { + $date = events::calc_dates( $config, $date ); + push @$events, $date; + } - for my $date (@$work_dates) { - $date = events::calc_dates( $config, $date ); - push @$events, $date; - } + #get playout + delete $options->{exclude}; + my $playout_dates = playout::get_scheduled( $config, $options ); + $id = 0; + for my $date (@$playout_dates) { + my $format = undef; + if ( defined $date->{'format'} ) { + $format = + ( $date->{'format'} || '' ) . " " + . ( $date->{'format_version'} || '' ) . " " + . ( $date->{'format_profile'} || '' ); + $format =~ s/MPEG Audio Version 1 Layer 3/MP3/g; + $format .= ' ' . ( $date->{'format_settings'} || '' ) + if defined $date->{'format_settings'}; + $format .= '<br>'; + } - #get playout - delete $options->{exclude}; - my $playout_dates = playout::get( $config, $options ); - $id = 0; - for my $date (@$playout_dates) { - my $format = undef; - if ( defined $date->{'format'} ) { - $format = - ( $date->{'format'} || '' ) . " " . ( $date->{'format_version'} || '' ) . " " . ( $date->{'format_profile'} || '' ); - $format =~ s/MPEG Audio Version 1 Layer 3/MP3/g; - $format .= ' ' . ( $date->{'format_settings'} || '' ) if defined $date->{'format_settings'}; - $format .= '<br>'; - } + $date->{play} = 1; + $date->{series_id} = -1; + $date->{event_id} = $id; + $date->{title} = ''; + $date->{title} .= '<b>errors</b>: ' . $date->{errors} . '<br>' + if defined $date->{errors}; + $date->{title} .= audio::formatDuration( + $date->{duration}, + $date->{event_duration}, + sprintf( "duration: %.1g h", $date->{duration} / 3600 ) . "<br>", + sprintf( "%d s", $date->{duration} ) + ) if defined $date->{duration}; + $date->{title} .= audio::formatLoudness( $date->{rms_left}, 'L: ' ) . ', ' + if defined $date->{rms_left}; + $date->{title} .= audio::formatLoudness( $date->{rms_right}, 'R: ' ) . '<br>' + if defined $date->{rms_right}; + $date->{title} .= audio::formatBitrate( $date->{bitrate} ) if defined $date->{bitrate}; + $date->{title} .= ' ' . audio::formatBitrateMode( $date->{bitrate_mode} ) . '<br>' + if defined $date->{bitrate_mode}; + $date->{title} .= + '<b>replay gain</b> ' . sprintf( "%.1f", $date->{replay_gain} ) . '<br>' + if defined $date->{replay_gain}; + $date->{title} .= audio::formatSamplingRate( $date->{sampling_rate} ) + if defined $date->{sampling_rate}; + $date->{title} .= audio::formatChannels( $date->{channels} ) . '<br>' + if defined $date->{channels}; + $date->{title} .= int( ( $date->{'stream_size'} || '0' ) / ( 1024 * 1024 ) ) . 'MB<br>' + if defined $date->{'stream_size'}; + $date->{title} .= $format if defined $format; + $date->{title} .= '<b>library</b>: ' . ( $date->{writing_library} || '' ) . '<br>' + if defined $date->{'writing_library'}; + $date->{title} .= '<b>path</b>: ' . ( $date->{file} || '' ) . '<br>' + if defined $date->{file}; + $date->{title} .= '<b>updated_at</b>: ' . ( $date->{updated_at} || '' ) . '<br>' + if defined $date->{updated_at}; + $date->{title} .= '<b>modified_at</b>: ' . ( $date->{modified_at} || '' ) . '<br>' + if defined $date->{modified_at}; - #print STDERR Dumper($date); - $date->{play} = 1; - $date->{series_id} = -1; - $date->{event_id} = $id; - $date->{title} = ''; - $date->{title} .= '<b>errors</b>: ' . $date->{errors} . '<br>' if defined $date->{errors}; - $date->{title} .= formatDuration( $date->{duration} ) . "s<br>" if defined $date->{duration}; - $date->{title} .= formatLoudness( "L:", $date->{rms_left} ) . ' dB, ' if defined $date->{rms_left}; - $date->{title} .= formatLoudness( "R:", $date->{rms_right} ) . ' dB<br>' if defined $date->{rms_right}; - $date->{title} .= formatBitrate( $date->{bitrate} ) . ' ' . $date->{bitrate_mode} . '<br>' if defined $date->{bitrate}; - $date->{title} .= '<b>replay gain</b> ' . sprintf( "%.1f", $date->{replay_gain} ) . '<br>' if defined $date->{replay_gain}; - $date->{title} .= ( ( $date->{sampling_rate} || '0' ) / 1000 ) . ' kHz<br>' if defined $date->{sampling_rate}; - $date->{title} .= ( $date->{channels} || '' ) . ' channels<br>' if defined $date->{channels}; - $date->{title} .= int( ( $date->{'stream_size'} || '0' ) / ( 1024 * 1024 ) ) . 'MB<br>' if defined $date->{'stream_size'}; - $date->{title} .= $format if defined $format; - $date->{title} .= '<b>library</b>: ' . ( $date->{writing_library} || '' ) . '<br>' if defined $date->{'writing_library'}; - $date->{title} .= '<b>path</b>: ' . ( $date->{file} || '' ) . '<br>' if defined $date->{file}; + $date->{rms_image} = URI::Escape::uri_unescape( $date->{rms_image} ) + if defined $date->{rms_image}; - #$date->{title}.= '<b>rms_image</b>: ' .($date->{rms_image}||'').'<br>' if defined $date->{rms_image}; + $date->{origStart} = $date->{start}; - $date->{rms_image} = uri_unescape( $date->{rms_image} ) if defined $date->{rms_image}; + # set end date seconds to 00 to handle error at break_dates/join_dates + $date->{end} =~ s/(\d\d\:\d\d)\:\d\d/$1\:00/; + delete $date->{day}; + delete $date->{start_date}; + delete $date->{end_date}; + $id++; + } - $date->{origStart} = $date->{start}; + unless ( $params->{list} == 1 ) { + $playout_dates = break_dates( $playout_dates, $start_of_day ); + } - # set end date seconds to 00 to handle error at break_dates/join_dates - $date->{end} =~ s/(\d\d\:\d\d)\:\d\d/$1\:00/; - delete $date->{day}; - delete $date->{start_date}; - delete $date->{end_date}; - $id++; - } + for my $date (@$playout_dates) { + $date = events::calc_dates( $config, $date ); + if ( defined $events_by_start->{ $date->{start} } ) { + $events_by_start->{ $date->{start} }->{duration} = $date->{duration} || 0; + $events_by_start->{ $date->{start} }->{event_duration} = + $date->{event_duration} || 0; + $events_by_start->{ $date->{start} }->{rms_left} = $date->{rms_left} || 0; + $events_by_start->{ $date->{start} }->{rms_right} = $date->{rms_right} || 0; + $events_by_start->{ $date->{start} }->{playout_modified_at} = $date->{modified_at}; + $events_by_start->{ $date->{start} }->{playout_updated_at} = $date->{updated_at}; + $events_by_start->{ $date->{start} }->{file} = $date->{file}; + } + push @$events, $date; + } + + # series dates + if ($params->{list} == 1 and defined $options->{series_id}){ + my $series = series::get( + $config, + { + #project_id => $project_id, + #studio_id => $studio_id, + series_id => $options->{series_id} + } + ); + if ( defined $series->[0] and $series->[0]->{predecessor_id} + and $series->[0]->{predecessor_id} ne $series->[0]->{id} ){ + my $events2 = getSeriesEvents( $config, $request, { + series_id => $series->[0]->{predecessor_id} + }, $params ); + + for my $event (@$events2) { + delete $event->{day}; + delete $event->{start_date}; + delete $event->{end_date}; + push @$events, events::calc_dates( $config, $event ); + } + } + } + } - unless ( $params->{list} == 1 ) { - $playout_dates = break_dates( $playout_dates, $start_of_day ); - } + #output + printToolbar( $config, $params, $calendar ) if $params->{part} == 0; - for my $date (@$playout_dates) { - $date = events::calc_dates( $config, $date ); - if ( defined $events_by_start->{ $date->{start} } ) { - $events_by_start->{ $date->{start} }->{duration} = $date->{duration} || 0; - $events_by_start->{ $date->{start} }->{rms_left} = $date->{rms_left} || 0; - $events_by_start->{ $date->{start} }->{rms_right} = $date->{rms_right} || 0; - } - push @$events, $date; - } - } - - #output - printToolbar( $config, $params, $calendar ) if $params->{part} == 0; - - #if($params->{part}==1){ - print qq{ + #if($params->{part}==1){ + print qq{ <script> var current_date="$calendar->{month} $calendar->{year}"; var previous_date="$calendar->{previous_date}"; @@ -441,277 +488,247 @@ sub showCalendar { </script> }; - #} + #} - #filter events by time - unless ( $params->{list} == 1 ) { - $events = filterEvents( $events, $options, $start_of_day ); - } + #filter events by time + unless ( $params->{list} == 1 ) { + $events = filterEvents( $events, $options, $start_of_day ); + } - #sort events by start - @$events = sort { $a->{start} cmp $b->{start} } @$events; + #sort events by start + @$events = sort { $a->{start} cmp $b->{start} } @$events; - #for my $date(@$events){debugDate($date);} + #separate by day (e.g. to 6 pm) + my $events_by_day = {}; + for my $event (@$events) { + my $day = + time::datetime_to_date( time::add_hours_to_datetime( $event->{start}, -$start_of_day ) ); + push @{ $events_by_day->{$day} }, $event; + } - #separate by day (e.g. to 6 pm) - my $events_by_day = {}; - for my $event (@$events) { - my $day = time::datetime_to_date( time::add_hours_to_datetime( $event->{start}, -$start_of_day ) ); - push @{ $events_by_day->{$day} }, $event; - } + #get min and max hour from all events + unless ( $params->{list} == 1 ) { + my $min_hour = 48; + my $max_hour = 0; - #get min and max hour from all events - unless ( $params->{list} == 1 ) { - my $min_hour = 48; - my $max_hour = 0; + for my $event (@$events) { + if ( $event->{start} =~ /(\d\d)\:\d\d\:\d\d$/ ) { + my $hour = $1; + $hour += 24 if $hour < $start_of_day; + $min_hour = $hour if ( $hour < $min_hour ) && ( $hour >= $start_of_day ); + } + if ( $event->{end} =~ /(\d\d)\:\d\d\:\d\d$/ ) { + my $hour = $1; + $hour += 24 if $hour <= $start_of_day; + $max_hour = $hour if ( $hour > $max_hour ) && ( $hour <= $end_of_day ); + } + } + $cal_options->{min_hour} = $min_hour; + $cal_options->{max_hour} = $max_hour; + } - for my $event (@$events) { - if ( $event->{start} =~ /(\d\d)\:\d\d\:\d\d$/ ) { - my $hour = $1; - $hour += 24 if $hour < $start_of_day; - $min_hour = $hour if ( ( $hour < $min_hour ) && ( $hour >= $start_of_day ) ); - } - if ( $event->{end} =~ /(\d\d)\:\d\d\:\d\d$/ ) { - my $hour = $1; - $hour += 24 if $hour <= $start_of_day; - $max_hour = $hour if ( ( $hour > $max_hour ) && ( $hour <= $end_of_day ) ); - } - } - $cal_options->{min_hour} = $min_hour; - $cal_options->{max_hour} = $max_hour; - } + # calculate positions and find schedule errors (depending on position) + for my $date ( sort ( keys %$events_by_day ) ) { + my $events = $events_by_day->{$date}; + calc_positions( $events, $cal_options ); + find_errors($events); + } - #print STDERR $start_of_day." ".$cal_options->{min_hour}."\n"; + for my $event (@$events) { + next unless defined $event->{uploaded_at}; + next + if ( defined $event->{playout_updated_at} ) + && ( $event->{uploaded_at} lt $event->{playout_updated_at} ); - # calculate positions and find schedule errors (depending on position) - for my $date ( sort ( keys %$events_by_day ) ) { - for my $events ( $events_by_day->{$date} ) { - calc_positions( $events, $cal_options ); - find_errors($events); - } - } + } - if ( $params->{list} == 1 ) { - showEventList( $config, $permissions, $params, $events_by_day ); - } else { - if ( $params->{part} == 0 ) { - print qq{<div id="calendarTable"> </div>}; - } - if ( $params->{part} == 1 ) { - calcCalendarTable( $config, $permissions, $params, $calendar, $events_by_day, $cal_options ); - printTableHeader( $config, $permissions, $params, $cal_options ); - printTableBody( $config, $permissions, $params, $cal_options ); - } - if ( $params->{part} == 0 ) { - printSeries( $config, $permissions, $params, $cal_options ); - print qq{ - </div><!--content--> - </center> + if ( $params->{list} == 1 ) { + showEventList( $config, $permissions, $params, $events_by_day ); + } else { + if ( $params->{part} == 0 ) { + print qq{<div id="calendarTable"> </div>}; + } + if ( $params->{part} == 1 ) { + calcCalendarTable( $config, $permissions, $params, $calendar, $events_by_day, + $cal_options ); + printTableHeader( $config, $permissions, $params, $cal_options ); + printTableBody( $config, $permissions, $params, $cal_options ); + } + if ( $params->{part} == 0 ) { + printSeries( $config, $permissions, $params, $cal_options ); + print qq{ + </main> }; - } + } - # time has to be set when events come in - printJavascript( $config, $permissions, $params, $cal_options ); - if ( $params->{part} == 0 ) { - print qq{ + # time has to be set when events come in + printJavascript( $config, $permissions, $params, $cal_options ); + if ( $params->{part} == 0 ) { + print qq{ </body> </html> }; - } - if ( $params->{part} == 1 ) { - } - } -} - -sub formatLoudness { - my $label = shift; - my $value = shift; - return '' unless defined $value; - return '' if $value == 0; - return '' if $value eq ''; - - #print STDERR "'$value'\n"; - $value = sprintf( "%.1f", $value ); - my $class = 'ok'; - $class = 'warn' if $value > -18.5; - $class = 'error' if $value > -16.0; - $class = 'warn' if $value < -24.0; - $class = 'error' if $value < -27.0; - return qq{$label<span class="$class">} . $value . qq{</span>}; -} - -sub formatDuration { - my $duration = shift; - return '' unless defined $duration; - return '' if $duration eq ''; - my $result = int( ( $duration + 3600 ) * 10 + 0.5) % 600; - my $class = "ok"; - $class = "warn" if $result > 1; - $class = "error" if $result > 10; - return sprintf( qq{<span class="%s">%.01f</span>}, $class, $duration ); -} - -sub formatBitrate { - my $bitrate = shift; - return '' if $bitrate eq ''; - if ( $bitrate >= 200 ) { - return qq{<span class="warn">$bitrate</span>}; - } elsif ( $bitrate < 190 ) { - return qq{<span class="error">$bitrate</span>}; - } else { - return qq{<span class="ok">$bitrate</span>}; - } + } + } } sub debugDate { - my $date = shift; - $date->{program} = '' unless defined $date->{program}; - $date->{series_name} = '' unless defined $date->{series_name}; - $date->{title} = '' unless defined $date->{title}; - $date->{splitCount} = 0 unless defined $date->{splitCount}; - my $dt = ( $date->{start} || '' ) . " " . ( $date->{end} | '' ); - my $da = ( $date->{start_date} || '' ) . " " . ( $date->{end_date} || '' ); - my $type = "schedule:" . ( $date->{schedule} || "" ) . " grid:" . ( $date->{grid} || "" ); - - #print STDERR "$dt $da count:$date->{splitCount} $type $date->{program}-$date->{series_name}-$date->{title}\n"; + my $date = shift; + $date->{program} = '' unless defined $date->{program}; + $date->{series_name} = '' unless defined $date->{series_name}; + $date->{title} = '' unless defined $date->{title}; + $date->{splitCount} = 0 unless defined $date->{splitCount}; + my $dt = ( $date->{start} || '' ) . " " . ( $date->{end} | '' ); + my $da = ( $date->{start_date} || '' ) . " " . ( $date->{end_date} || '' ); + my $type = "schedule:" . ( $date->{schedule} || "" ) . " grid:" . ( $date->{grid} || "" ); } # break dates at start_of_day sub break_dates { - my $dates = shift; - my $start_of_day = shift; + my $dates = shift; + my $start_of_day = shift; - #return $dates if $start_of_day eq '0'; + #return $dates if $start_of_day eq '0'; - for my $date (@$dates) { - next unless defined $date; + for my $date (@$dates) { + next unless defined $date; - $date->{splitCount} = 0 unless defined $date->{splitCount}; + $date->{splitCount} = 0 unless defined $date->{splitCount}; - #debugDate($date); + #debugDate($date); - next if $date->{splitCount} > 6; - my $nextDayStart = breaks_day( $date->{start}, $date->{end}, $start_of_day ); - next if $nextDayStart eq '0'; + next if $date->{splitCount} > 6; + my $nextDayStart = breaks_day( $date->{start}, $date->{end}, $start_of_day ); + next if $nextDayStart eq '0'; - # add new entry - my $entry = {}; - for my $key ( keys %$date ) { - $entry->{$key} = $date->{$key}; - } - $entry->{start} = $nextDayStart; - $entry->{splitCount}++; - push @$dates, $entry; + # add new entry + my $entry = {}; + for my $key ( keys %$date ) { + $entry->{$key} = $date->{$key}; + } + $entry->{start} = $nextDayStart; + $entry->{splitCount}++; + push @$dates, $entry; # print STDERR "add $entry->{start} $entry->{end} count:$entry->{splitCount} $entry->{program}-$entry->{series_name}-$entry->{title}\n"; - #modify existing entry - my $start_date = time::datetime_to_date( $date->{start} ); - $date->{end} = $nextDayStart; - $date->{splitCount}++; + #modify existing entry + my $start_date = time::datetime_to_date( $date->{start} ); + $date->{end} = $nextDayStart; + $date->{splitCount}++; # print STDERR "set $date->{start} $date->{end} count:$date->{splitCount} $date->{program}-$date->{series_name}-$date->{title}\n"; - } + } - return join_dates( $dates, $start_of_day ); + return join_dates( $dates, $start_of_day ); } # check if event breaks the start of day (e.g. 06:00) sub breaks_day { - my $start = shift; - my $end = shift; - my $start_of_day = shift; + my $start = shift; + my $end = shift; + my $start_of_day = shift; - my $starts = time::datetime_to_array($start); - my $startDate = time::array_to_date($starts); - my $startTime = time::array_to_time($starts); - $start = $startDate . ' ' . $startTime; + my $starts = time::datetime_to_array($start); + my $startDate = time::array_to_date($starts); + my $startTime = time::array_to_time($starts); + $start = $startDate . ' ' . $startTime; - my $ends = time::datetime_to_array($end); - my $endDate = time::array_to_date($ends); - my $endTime = time::array_to_time($ends); - $end = $endDate . ' ' . $endTime; + my $ends = time::datetime_to_array($end); + my $endDate = time::array_to_date($ends); + my $endTime = time::array_to_time($ends); + $end = $endDate . ' ' . $endTime; - my $dayStartTime = time::array_to_time($start_of_day); - my $dayStart = $startDate . ' ' . $dayStartTime; + my $dayStartTime = time::array_to_time($start_of_day); + my $dayStart = $startDate . ' ' . $dayStartTime; - # start before 6:00 of same day - return $dayStart if ( $start lt $dayStart ) && ( $end gt $dayStart ); + # start before 6:00 of same day + return $dayStart if ( $start lt $dayStart ) && ( $end gt $dayStart ); - # start before 6:00 of next day - my $nextDayStart = time::add_days_to_datetime( $dayStart, 1 ); + # start before 6:00 of next day + my $nextDayStart = time::add_days_to_datetime( $dayStart, 1 ); - #$nextDayStart=~s/:00$//; - return $nextDayStart if ( $start lt $nextDayStart ) && ( $end gt $nextDayStart ); + #$nextDayStart=~s/:00$//; + return $nextDayStart if ( $start lt $nextDayStart ) && ( $end gt $nextDayStart ); - return 0; + return 0; } # merge events with same seriesId and eventId at 00:00 sub join_dates { - my $dates = shift; - my $start_of_day = shift; + my $dates = shift; + my $start_of_day = shift; - return $dates if $start_of_day == 0; - @$dates = sort { $a->{start} cmp $b->{start} } @$dates; + return $dates if $start_of_day == 0; + @$dates = sort { $a->{start} cmp $b->{start} } @$dates; - my $prev_date = undef; - for my $date (@$dates) { - next unless defined $date; - unless ( defined $prev_date ) { - $prev_date = $date; - next; - } - if ( ( $date->{event_id} == $prev_date->{event_id} ) - && ( $date->{series_id} == $prev_date->{series_id} ) - && ( $date->{start} eq $prev_date->{end} ) - && ( $date->{start} =~ /00\:00\:\d\d/ ) ) - { - $prev_date->{end} = $date->{end}; - $date = undef; - next; - } - $prev_date = $date; - } + my $prev_date = undef; + for my $date (@$dates) { + next unless defined $date; + unless ( defined $prev_date ) { + $prev_date = $date; + next; + } + if ( ( $date->{event_id} == $prev_date->{event_id} ) + && ( $date->{series_id} == $prev_date->{series_id} ) + && ( $date->{start} eq $prev_date->{end} ) + && ( $date->{start} =~ /00\:00\:\d\d/ ) ) + { + $prev_date->{end} = $date->{end}; + $date = undef; + next; + } + $prev_date = $date; + } - my $results = []; - for my $date (@$dates) { - next unless defined $date; - push @$results, $date; - } + my $results = []; + for my $date (@$dates) { + next unless defined $date; + push @$results, $date; + } - return $results; + return $results; } sub filterEvents { - my $events = shift; - my $options = shift; - my $start_of_day = shift; + my $events = shift; + my $options = shift; + my $start_of_day = shift; - return [] unless defined $options->{from}; - return [] unless defined $options->{till}; + return [] unless defined $options->{from}; + return [] unless defined $options->{till}; - my $dayStartTime = time::array_to_time($start_of_day); - my $startDatetime = $options->{from} . ' ' . $dayStartTime; - my $endDatetime = $options->{till} . ' ' . $dayStartTime; + my $dayStartTime = time::array_to_time($start_of_day); + my $startDatetime = $options->{from} . ' ' . $dayStartTime; + my $endDatetime = $options->{till} . ' ' . $dayStartTime; - my $results = []; - for my $date (@$events) { - next if ( ( $date->{start} ge $endDatetime ) || ( $date->{end} le $startDatetime ) ); - push @$results, $date; - } - return $results; + my $results = []; + for my $date (@$events) { + next if ( ( $date->{start} ge $endDatetime ) || ( $date->{end} le $startDatetime ) ); + push @$results, $date; + } + return $results; } sub showEventList { - my $config = shift; - my $permissions = shift; - my $params = shift; - my $events_by_day = shift; - my $language = $params->{language}; + my $config = shift; + my $permissions = shift; + my $params = shift; + my $events_by_day = shift; + my $language = $params->{language}; - print qq{ + my $rerunIcon = qq{<img src="image/replay.svg" title="$params->{loc}->{label_rerun}">}; + my $liveIcon = qq{<img src="image/mic.svg" title="$params->{loc}->{label_live}">}; + my $draftIcon = qq{<img src="image/draft.svg" title="$params->{loc}->{label_draft}">}; + my $archiveIcon = qq{<img src="image/archive.svg" title="$params->{loc}->{label_archived}">}; + my $playoutIcon = qq{<img src="image/play.svg">}; + my $processingIcon = qq{<img src="image/processsing.svg">}; + my $preparedIcon = qq{<img src="image/prepared.svg>}; + my $creoleIcon = qq{<img src="image/creole.svg>}; + + my $out = ''; + $out = qq{ <div id="event_list"> <table> <thead> @@ -721,133 +738,184 @@ sub showEventList { <th class="start_date">$params->{loc}->{label_start}</th> <th class="start_time">$params->{loc}->{label_end}</th> <th class="series_name">$params->{loc}->{label_series}</th> + <th class="series_id">sid</th> <th class="title">$params->{loc}->{label_title}</th> <th class="episode">$params->{loc}->{label_episode}</th> - <th class="rerun" title="$params->{loc}->{label_rerun}"><img src="image/32/rerun.png"></th> - <th class="live" title="$params->{loc}->{label_live}"><img src="image/32/live.png"></th> - <th class="draft" title="$params->{loc}->{label_draft}"><img src="image/32/draft.png"></th> - <th class="archive" title="$params->{loc}->{label_archived}"><img src="image/32/archived.png"></th> + <th class="rerun">$rerunIcon</th> + <th class="draft">$draftIcon</th> + <th class="live">$liveIcon</th> + <th class="playout" title="$params->{loc}->{label_playout}">$playoutIcon</th> + <th class="archive">$archiveIcon</th> + <th class="project_id">project</th> + <th class="studio">studio</th> + <th class="creole">wiki format</th> </tr> </thead> <tbody> } if $params->{part} == 0; - my $i = 1; + my $i = 1; - my $scheduled_events = {}; - for my $date ( reverse sort ( keys %$events_by_day ) ) { - for my $event ( reverse @{ $events_by_day->{$date} } ) { - next unless defined $event; - next if defined $event->{grid}; - next if defined $event->{work}; - next if defined $event->{play}; + my $scheduled_events = {}; + for my $date ( reverse sort ( keys %$events_by_day ) ) { + for my $event ( reverse @{ $events_by_day->{$date} } ) { + next unless defined $event; + next if defined $event->{grid}; + next if defined $event->{work}; + next if defined $event->{play}; - #schedules with matching date are marked to be hidden in find_errors - next if defined $event->{hide}; - $event->{project_id} = $params->{project_id}; - $event->{studio_id} = $params->{studio_id}; - $event->{series_id} = '-1' unless defined $event->{series_id}; - $event->{event_id} = '-1' unless defined $event->{event_id}; - my $id = 'event_' . $event->{project_id} . '_' . $event->{studio_id} . '_' . $event->{series_id} . '_' . $event->{event_id}; + #schedules with matching date are marked to be hidden in find_errors + next if defined $event->{hide}; + $event->{project_id} //= $params->{project_id}; + $event->{studio_id} //= $params->{studio_id}; + $event->{series_id} = '-1' unless defined $event->{series_id}; + $event->{event_id} = '-1' unless defined $event->{event_id}; + my $id = + 'event_' + . $event->{project_id} . '_' + . $event->{studio_id} . '_' + . $event->{series_id} . '_' + . $event->{event_id}; - my $class = 'event'; - $class = $event->{class} if defined $event->{class}; - $class = 'schedule' if defined $event->{schedule}; - if ( $class =~ /(event|schedule)/ ) { - $class .= ' scheduled' if defined $event->{scheduled}; - $class .= ' error' if defined $event->{error}; - $class .= ' no_series' if ( ( $class eq 'event' ) && ( $event->{series_id} eq '-1' ) ); + my $class = 'event'; + $class = $event->{class} if defined $event->{class}; + $class = 'schedule' if defined $event->{schedule}; + if ( $class =~ /(event|schedule)/ ) { + $class .= ' scheduled' if defined $event->{scheduled}; + $class .= ' error' if defined $event->{error}; + $class .= ' no_series' + if ( ( $class eq 'event' ) && ( $event->{series_id} eq '-1' ) ); - for my $filter ( 'rerun', 'archived', 'playout', 'published', 'live', 'disable_event_sync', 'draft' ) { - $class .= ' ' . $filter if ( ( defined $event->{$filter} ) && ( $event->{$filter} eq '1' ) ); - } - $class .= ' preproduced' unless ( ( defined $event->{'live'} ) && ( $event->{'live'} eq '1' ) ); - $class .= ' no_playout' unless ( ( defined $event->{'playout'} ) && ( $event->{'playout'} eq '1' ) ); - $class .= ' no_rerun' unless ( ( defined $event->{'rerun'} ) && ( $event->{'rerun'} eq '1' ) ); - } + for my $filter ( + 'rerun', 'archived', 'playout', 'published', + 'live', 'disable_event_sync', 'draft' + ) + { + $class .= ' ' . $filter + if ( ( defined $event->{$filter} ) && ( $event->{$filter} eq '1' ) ); + } + $class .= ' preproduced' + unless ( ( defined $event->{'live'} ) && ( $event->{'live'} eq '1' ) ); + $class .= ' no_playout' + unless ( ( defined $event->{'playout'} ) && ( defined $event->{'playout'} and $event->{'playout'} eq '1' ) ); + $class .= ' no_rerun' + unless ( ( defined $event->{'rerun'} ) && ( $event->{'rerun'} eq '1' ) ); + } - $event->{start} ||= ''; - $event->{weekday_short_name} ||= ''; - $event->{start_date_name} ||= ''; - $event->{start_time_name} ||= ''; - $event->{end_time} ||= ''; - $event->{series_name} ||= ''; - $event->{title} ||= ''; - $event->{user_title} ||= ''; - $event->{episode} ||= ''; - $event->{rerun} ||= ''; - $event->{draft} ||= ''; - $id ||= ''; - $class ||= ''; + $event->{start} ||= ''; + $event->{weekday_short_name} ||= ''; + $event->{start_date_name} ||= ''; + $event->{start_time_name} ||= ''; + $event->{end_time} ||= ''; + $event->{series_name} ||= ''; + $event->{title} ||= ''; + $event->{user_title} ||= ''; + $event->{episode} ||= ''; + $event->{rerun} ||= ''; + $event->{draft} ||= ''; + $event->{playout} ||= ''; + $id ||= ''; + $class ||= ''; - my $archived = $event->{archived} || '-'; - $archived = '-' if $archived eq '0'; - $archived = 'x' if $archived eq '1'; + my $archived = $event->{archived} || '-'; + $archived = '-' if $archived eq '0'; + $archived = $archiveIcon if $archived eq '1'; - my $live = $event->{live} || '-'; - $live = '-' if $live eq '0'; - $live = 'x' if $live eq '1'; + my $live = $event->{live} || '-'; + $live = '-' if $live eq '0'; + $live = $liveIcon if $live eq '1'; - my $rerun = $event->{rerun} || '-'; - - #$rerun='-' if $rerun eq '0'; - #$rerun='x' if $rerun eq '1'; - $rerun = " [" . markup::base26( $event->{recurrence_count} + 1 ) . "]" - if ( defined $event->{recurrence_count} ) && ( $event->{recurrence_count} ne '' ) && ( $event->{recurrence_count} > 0 ); + my $rerun = $event->{rerun} || '-'; + $rerun = " [" . markup::base26( $event->{recurrence_count} + 1 ) . "]" + if ( defined $event->{recurrence_count} ) + && ( $event->{recurrence_count} ne '' ) + && ( $event->{recurrence_count} > 0 ); my $draft = $event->{draft} || '0'; - $draft='-' if $draft eq '0'; - $draft='x' if $draft eq '1'; + $draft = '-' if $draft eq '0'; + $draft = $draftIcon if $draft eq '1'; - my $title = $event->{title}; - $title .= ': ' . $event->{user_title} if $event->{user_title} ne ''; + my $playout = '-'; + if (defined $event->{upload_status}){ + $playout = $processingIcon if $event->{upload_status} ne ''; + $playout = $preparedIcon if $event->{upload_status} eq 'done'; + } + $playout = $playoutIcon if $event->{playout} eq '1'; - print qq!<tr id="$id" class="$class" date="$event->{start}" >! - . qq!<td class="day_of_year">! - . time::dayOfYear( $event->{start} ) - . q!</td>! - . qq!<td class="weekday">$event->{weekday_short_name},</td>! - . qq!<td class="start_date">$event->{start_date_name}</td>! - . qq!<td class="start_time">$event->{start_time_name} - $event->{end_time}</td>! - . qq!<td class="series_name">$event->{series_name}</td>! - . qq!<td class="title">$title</td>! - . qq!<td class="episode">$event->{episode}</td>! - . qq!<td class="rerun">$rerun</td>! - . qq!<td class="draft">$draft</td>! - . qq!<td class="live">$live</td>! - . qq!<td class="archived">$archived</td>! - . qq!</tr>! . "\n"; - } - $i++; - } - print qq{ + my $title = $event->{title}; + $title .= ': ' . $event->{user_title} if $event->{user_title} ne ''; + + my $other_studio = $params->{studio_id} ne $event->{studio_id}; + my $other_project = $params->{project_id} ne $event->{project_id}; + $class.=' predecessor' if $other_project or $other_studio; + $other_studio = '<img src="image/globe.svg">' if $other_studio; + $other_project = '<img src="image/globe.svg">' if $other_project; + + my $file = $event->{file} + ? 'playout: ' . $event->{file} =~ s/\'/\'/gr + : 'playout'; + my $playout_info = $file // $event->{upload_status} // ''; + + my $studio_name = $event->{studio_name} // '-'; + + my $format = {"markdown" => "-", "creole" => "Lang Belta" }->{$event->{content_format}//''} // 'Lang Belta'; + $out .= + qq!<tr id="$id" class="$class" start="$event->{start}" >! + . qq!<td class="day_of_year">! + . (defined $event->{start} ? time::dayOfYear( $event->{start} ) :'') + . q!</td>! + . qq!<td class="weekday">$event->{weekday_short_name},</td>! + . qq!<td class="start_date" data-text="$event->{start_datetime}">$event->{start_date_name}</td>! + . qq!<td class="start_time">$event->{start_time_name} - $event->{end_time}</td>! + . qq!<td class="series_name">$event->{series_name}</td>! + . qq!<td class="series_id">$event->{series_id}</td>! + . qq!<td class="title">$title</td>! + . qq!<td class="episode">$event->{episode}</td>! + . qq!<td class="rerun">$rerun</td>! + . qq!<td class="draft">$draft</td>! + . qq!<td class="live">$live</td>! + . qq!<td class="playout" title="$playout_info">$playout</td>! + . qq!<td class="archived">$archived</td>! + . qq!<td>$event->{project_name} $other_studio</td>! + . qq!<td>$studio_name $other_studio</td>! + . qq!<td>$format</td>! + . qq!</tr>! . "\n"; + } + $i++; + if ( $i % 100 == 0 ) { + print $out; + $out = ''; + } + } + $out .= qq{ </tbody> </table> </div> } if $params->{part} == 0; - my $project_id = $params->{project_id}; - my $studio_id = $params->{studio_id}; + my $project_id = $params->{project_id}; + my $studio_id = $params->{studio_id}; - #add handler for events not assigned to series - if ( ( $params->{studio_id} ne '' ) && ( $params->{studio_id} ne '-1' ) ) { - my $series = series::get( - $config, - { - project_id => $project_id, - studio_id => $studio_id - } - ); - print q{<div id="event_no_series" style="display:none">}; - print addEventsToSeries( $series, $params ) - if ( ( defined $permissions->{assign_series_events} ) && ( $permissions->{assign_series_events} eq '1' ) ); - print createSeries($params) if ( ( defined $permissions->{create_series} ) && ( $permissions->{create_series} eq '1' ) ); - print q{</div>}; - } + #add handler for events not assigned to series + if ( ( $params->{studio_id} ne '' ) && ( $params->{studio_id} ne '-1' ) ) { + my $series = series::get( + $config, + { + project_id => $project_id, + studio_id => $studio_id + } + ); + $out .= q{<div id="event_no_series" style="display:none">}; + $out .= addEventsToSeries( $series, $params ) + if ( defined $permissions->{assign_series_events} ) + && ( $permissions->{assign_series_events} eq '1' ); + $out .= createSeries($params) + if ( defined $permissions->{create_series} ) && ( $permissions->{create_series} eq '1' ); + $out .= q{</div>}; + } - print qq{ - </div><!--content--> - </center> + $out .= qq{ + </main> <script> var region='} . $params->{loc}->{region} . q{'; var calendarTable=0; @@ -855,101 +923,114 @@ sub showEventList { var label_schedule='} . $params->{loc}->{label_schedule} . q{'; var label_worktime='} . $params->{loc}->{label_worktime} . q{'; var label_playout='} . $params->{loc}->{label_playout} . q{'; + var label_descriptions='} . $params->{loc}->{label_descriptions} . q{'; + var label_pin='} . $params->{loc}->{label_pin} . q{'; </script> </body> </html> } if $params->{part} == 0; + print $out; + } sub calcCalendarTable { - my $config = shift; - my $permissions = shift; - my $params = shift; - my $calendar = shift; - my $events_by_day = shift; - my $cal_options = shift; + my $config = shift; + my $permissions = shift; + my $params = shift; + my $calendar = shift; + my $events_by_day = shift; + my $cal_options = shift; - my $start_of_day = $cal_options->{start_of_day}; - my $end_of_day = $cal_options->{end_of_day}; - my $min_hour = $cal_options->{min_hour}; - my $max_hour = $cal_options->{max_hour}; - my $project_id = $params->{project_id}; - my $studio_id = $params->{studio_id}; - my $language = $params->{language}; + my $start_of_day = $cal_options->{start_of_day}; + my $end_of_day = $cal_options->{end_of_day}; + my $min_hour = $cal_options->{min_hour}; + my $max_hour = $cal_options->{max_hour}; + my $project_id = $params->{project_id}; + my $studio_id = $params->{studio_id}; + my $language = $params->{language}; - #insert time column - for my $hour ( $min_hour .. $max_hour ) { - push @{ $events_by_day->{0} }, - { - start => sprintf( '%02d:00', $hour % 24 ), - start_time => sprintf( '%02d:00', $hour ), - end_time => sprintf( '%02d:00', $hour + 1 ), - series_id => -1, - event_id => -1, - project_id => $project_id, - studio_id => $studio_id, - class => 'time', - time => sprintf( '%02d', $hour % 24 ) - }; - } + #insert time column + for my $hour ( $min_hour .. $max_hour ) { + push @{ $events_by_day->{0} }, + { + start => sprintf( '%02d:00', $hour % 24 ), + start_time => sprintf( '%02d:00', $hour ), + end_time => sprintf( '%02d:00', $hour + 1 ), + series_id => -1, + event_id => -1, + project_id => $project_id, + studio_id => $studio_id, + class => 'time', + 'time' => sprintf( '%02d', $hour % 24 ) + }; + } - #insert current time - my $now = time::get_datetime( time::time_to_datetime(), $config->{date}->{time_zone} ); - my $time = '00:00'; - my $date = ''; - if ( $now =~ /(\d\d\d\d\-\d\d\-\d\d)[ T](\d\d\:\d\d)/ ) { - $date = $1; - $time = $2; - } + #insert current time + my $time = '00:00'; + my $date = ''; + if ( time::get_datetime( + time::time_to_datetime(time()), + $config->{date}->{time_zone} + ) =~ /(\d\d\d\d\-\d\d\-\d\d)[ T](\d\d\:\d\d)/ ) { + $date = $1; + $time = $2; + } - push @{ $events_by_day->{0} }, - { - start => $time, - start_time => $time, - end_time => $time, - series_id => -1, - event_id => -1, - project_id => -1, - studio_id => -1, - class => 'time now', - time => $time, - }; - calc_positions( $events_by_day->{0}, $cal_options ); + my $next_time = '00:00'; + if ( time::get_datetime( + time::time_to_datetime(time()+60), + $config->{date}->{time_zone} + ) =~ /(\d\d\d\d\-\d\d\-\d\d)[ T](\d\d\:\d\d)/ ) { + $next_time = $2; + } - #print Dumper($events_by_day); - my $yoffset = $min_hour * $hour_height; - my @days = sort keys %$events_by_day; + unshift @{ $events_by_day->{0} }, + { + #start => $time, + start_time => $time, + end_time => $next_time, + series_id => -1, + event_id => -1, + project_id => -1, + studio_id => -1, + class => 'time now', + 'time' => $time, + }; + calc_positions( $events_by_day->{0}, $cal_options ); - $cal_options->{days} = \@days; - $cal_options->{yoffset} = $yoffset; - $cal_options->{events_by_day} = $events_by_day; - $cal_options->{date} = $date; + my $yoffset = $min_hour * $hour_height; + my @days = sort keys %$events_by_day; + + $cal_options->{days} = \@days; + $cal_options->{yoffset} = $yoffset; + $cal_options->{events_by_day} = $events_by_day; + $cal_options->{date} = $date; } sub printTableHeader { - my $config = shift; - my $permissions = shift; - my $params = shift; - my $cal_options = shift; + my $config = shift; + my $permissions = shift; + my $params = shift; + my $cal_options = shift; - my $days = $cal_options->{days}; - my $events_by_day = $cal_options->{events_by_day}; - my $yoffset = $cal_options->{yoffset}; - my $date = $cal_options->{date}; - my $min_hour = $cal_options->{min_hour}; + my $days = $cal_options->{days}; + my $events_by_day = $cal_options->{events_by_day}; + my $yoffset = $cal_options->{yoffset}; + my $date = $cal_options->{date}; + my $min_hour = $cal_options->{min_hour}; - my $project_id = $params->{project_id}; - my $studio_id = $params->{studio_id}; - my $language = $params->{language}; + my $project_id = $params->{project_id}; + my $studio_id = $params->{studio_id}; + my $language = $params->{language}; - #print row with weekday and date - my $out = ''; + #print row with weekday and date + my $out = ''; - my $numberOfDays = scalar(@$days); - my $width = int( 85 / $numberOfDays ); - $out .= qq! + my $numberOfDays = scalar(@$days); + my $width = int( 85 / $numberOfDays ); + $out .= qq! <script> var days=$numberOfDays; </script> @@ -966,226 +1047,245 @@ sub printTableHeader { </style> !; - $out .= q{ + $out .= q{ <div id="calendar_weekdays" style="visibility:hidden"> <table> <tbody> <tr> }; - my $next_day_found = 0; + my $next_day_found = 0; - #print navigation and weekday - my $ypos = 0; - my $old_week = undef; - my $dt = undef; - for my $day (@$days) { - my $events = $events_by_day->{$day}; + #print navigation and weekday + my $ypos = 0; + my $old_week = undef; + my $dt = undef; + for my $day (@$days) { + my $events = $events_by_day->{$day}; - if ( $day ne '0' ) { - $dt = time::get_datetime( $day . 'T00:00:00', $config->{date}->{time_zone} ); - my $week = $dt->week_number(); - if ( ( defined $old_week ) && ( $week ne $old_week ) ) { - $out .= qq{<td class="week"><div class="week"></div></td>}; - } - $old_week = $week; - } + if ( $day ne '0' ) { + $dt = time::get_datetime( $day . 'T00:00:00', $config->{date}->{time_zone} ); + my $week = $dt->week_number(); + if ( ( defined $old_week ) && ( $week ne $old_week ) ) { + $out .= qq{<td class="week"><div class="week"></div></td>}; + } + $old_week = $week; + } - #header - $out .= qq{<td>}; - my $event = $events->[0]; - my $content = ''; - my $class = 'date'; - if ( $day eq '0' ) { - $out .= qq{<div id="position"></div></td>}; - next; - } else { + #header + $out .= qq{<td>}; + my $event = $events->[0]; + my $content = ''; + my $class = 'date'; + if ( $day eq '0' ) { + $out .= qq{<div id="position"></div></td>}; + next; + } else { - #print weekday - $dt->set_locale($language); - $content = $dt->day_name() . '<br>'; - $content .= $dt->strftime('%d. %b %Y') . '<br>'; - $content .= time::dayOfYear( $event->{start} ) . '<br>'; + #print weekday + $dt->set_locale($language); + $content = $dt->day_name() . '<br>'; + $content .= $dt->strftime('%d. %b %Y') . '<br>'; + $content .= time::dayOfYear( $event->{start} ) . '<br>'; - #$class="date"; - if ( ( $day ge $date ) && ( $next_day_found == 0 ) ) { - $class = "date today"; - $next_day_found = 1; - } - } + #$class="date"; + if ( ( $day ge $date ) && ( $next_day_found == 0 ) ) { + $class = "date today"; + $next_day_found = 1; + } + } - #insert date name - my $hour = $min_hour; - my $date = $day; - $event = { - start => sprintf( '%02d:00', $hour % 24 ), - start_time => sprintf( '%02d:00', $hour ), - end_time => sprintf( '%02d:30', $hour + 1 ), - project_id => $project_id, - studio_id => $studio_id, - content => $content, - class => $class, - date => $date - }; + #insert date name + my $hour = $min_hour; + my $date = $day; + $event = { + start => sprintf( '%02d:00', $hour % 24 ), + start_time => sprintf( '%02d:00', $hour ), + end_time => sprintf( '%02d:30', $hour + 1 ), + project_id => $project_id, + studio_id => $studio_id, + content => $content, + class => $class, + date => $date + }; - calc_positions( [$event], $cal_options ); - $out .= print_event( $params, $event, $ypos, $yoffset, $yzoom ); + calc_positions( [$event], $cal_options ); + $out .= print_event( $params, $event, $ypos, $yoffset, $yzoom ); - $out .= '</td>'; - } - $out .= q{ + $out .= '</td>'; + } + $out .= q{ </tr> </tbody> </table> </div> }; - print $out; + print $out; } sub printTableBody { - my $config = shift; - my $permissions = shift; - my $params = shift; - my $cal_options = shift; + my $config = shift; + my $permissions = shift; + my $params = shift; + my $cal_options = shift; - my $days = $cal_options->{days}; - my $events_by_day = $cal_options->{events_by_day}; - my $yoffset = $cal_options->{yoffset}; + my $days = $cal_options->{days}; + my $events_by_day = $cal_options->{events_by_day}; + my $yoffset = $cal_options->{yoffset}; - my $project_id = $params->{project_id}; - my $studio_id = $params->{studio_id}; + my $project_id = $params->{project_id}; + my $studio_id = $params->{studio_id}; - if ( scalar( @{$days} ) == 0 ) { - uac::print_info("no dates found at the selected time span"); - } + if ( scalar( @{$days} ) == 0 ) { + uac::print_info("no dates found at the selected time span"); + } - my $out = q{ + my $out = q{ <div id="calendar" style="display:none"> <table> <tbody> <tr> }; - #print events with weekday and date - my $ypos = 1; - my $dt = undef; - my $old_week = undef; + #print events with weekday and date + my $ypos = 1; + my $dt = undef; + my $old_week = undef; - #print Dumper($days); - for my $day (@$days) { - my $events = $events_by_day->{$day}; + for my $day (@$days) { + my $events = $events_by_day->{$day}; - if ( $day ne '0' ) { - $dt = time::get_datetime( $day . 'T00:00:00', $config->{date}->{time_zone} ); - my $week = $dt->week_number(); - if ( ( defined $old_week ) && ( $week ne $old_week ) ) { - $out .= qq{<td class="week"><div class="week"></div></td>}; - } - $old_week = $week; - } + if ( $day ne '0' ) { + $dt = time::get_datetime( $day . 'T00:00:00', $config->{date}->{time_zone} ); + my $week = $dt->week_number(); + if ( ( defined $old_week ) && ( $week ne $old_week ) ) { + $out .= qq{<td class="week"><div class="week"></div></td>}; + } + $old_week = $week; + } - $out .= qq{<td>}; # width="$width">}; + $out .= qq{<td>}; # width="$width">}; - for my $event (@$events) { - my $content = ''; - if ( ( defined $event->{series_name} ) && ( $event->{series_name} ne '' ) ) { - $event->{series_name} = $params->{loc}->{single_event} - if $event->{series_name} eq '' || $event->{series_name} eq '_single_'; - $content = '<b>' . $event->{series_name} . '</b><br>'; - } + for my $event (@$events) { + my $content = ''; + if ( ( defined $event->{series_name} ) && ( $event->{series_name} ne '' ) ) { + $event->{series_name} = $params->{loc}->{single_event} + if $event->{series_name} eq '' || $event->{series_name} eq '_single_'; + $content = '<b>' . $event->{series_name} . '</b><br>'; + } - if ( ( defined $event->{title} ) && ( defined $event->{title} ne '' ) ) { - $content .= $event->{title}; - unless ( $event->{title} =~ /\#\d+/ ) { - $content .= ' #' . $event->{episode} if ( ( defined $event->{episode} ) && ( $event->{episode} ne '' ) ); - } - } - $content = $event->{start} if $day eq '0'; - $event->{project_id} = $project_id unless defined $event->{project_id}; - $event->{studio_id} = $studio_id unless defined $event->{studio_id}; - $event->{content} = $content unless ( ( defined $event->{class} ) && ( $event->{class} eq 'time now' ) ); - $event->{class} = 'event' if $day ne '0'; - $event->{class} = 'grid' if ( ( defined $event->{grid} ) && ( $event->{grid} == 1 ) ); - $event->{class} = 'schedule' if ( ( defined $event->{schedule} ) && ( $event->{schedule} == 1 ) ); - $event->{class} = 'work' if ( ( defined $event->{work} ) && ( $event->{work} == 1 ) ); - $event->{class} = 'play' if ( ( defined $event->{play} ) && ( $event->{play} == 1 ) ); + if ( ( defined $event->{title} ) && ( defined $event->{title} ne '' ) ) { + $content .= $event->{title}; + unless ( $event->{title} =~ /\#\d+/ ) { + $content .= ' #' . $event->{episode} + if ( ( defined $event->{episode} ) && ( $event->{episode} ne '' ) ); + } + } + $content = $event->{start} if $day eq '0'; + $event->{project_id} = $project_id unless defined $event->{project_id}; + $event->{studio_id} = $studio_id unless defined $event->{studio_id}; + $event->{content} = $content + unless ( ( defined $event->{class} ) && ( $event->{class} eq 'time now' ) ); + $event->{class} = 'event' if $day ne '0'; + $event->{class} = 'grid' if ( ( defined $event->{grid} ) && ( $event->{grid} == 1 ) ); + $event->{class} = 'schedule' + if ( ( defined $event->{schedule} ) && ( $event->{schedule} == 1 ) ); + $event->{class} = 'work' if ( ( defined $event->{work} ) && ( $event->{work} == 1 ) ); + $event->{class} = 'play' if ( ( defined $event->{play} ) && ( $event->{play} == 1 ) ); - if ( $event->{class} eq 'event' ) { - $event->{content} .= '<br><span class="weak">'; - $event->{content} .= formatDuration( $event->{duration} ) . 's ' if defined $event->{duration}; - $event->{content} .= formatLoudness( 'L', $event->{rms_left} ) . ' ' if defined $event->{rms_left}; - $event->{content} .= formatLoudness( 'R', $event->{rms_right} ) if defined $event->{rms_right}; - $event->{content} .= '</span>'; - } + if ( $event->{class} eq 'event' ) { + $event->{content} .= '<br><span class="weak">'; + $event->{content} .= audio::formatFile($event->{file}, $event->{event_id}); + $event->{content} .= audio::formatDuration( + $event->{duration}, + $event->{event_duration}, + sprintf( "%d min", ( $event->{duration} + 30 ) / 60 ), + sprintf( "%d s", $event->{duration} ) + ) + . ' ' + if defined $event->{duration}; + $event->{content} .= audio::formatLoudness( $event->{rms_left}, 'L: ' ,'round') . ' ' + if defined $event->{rms_left}; + $event->{content} .= audio::formatLoudness( $event->{rms_right}, 'R: ','round' ) + if defined $event->{rms_right}; + #$event->{content} .= formatBitrate( $event->{bitrate} ) if defined $event->{bitrate}; + $event->{content} .= '</span>'; + } - $out .= print_event( $params, $event, $ypos, $yoffset, $yzoom ); + $out .= print_event( $params, $event, $ypos, $yoffset, $yzoom ); - $ypos++; - } - $out .= '</td>'; - } - $out .= q{ + $ypos++; + } + $out .= '</td>'; + } + $out .= q{ </tr> </tbody> </table> </div><!--table--> }; - print $out; + print $out; } sub printSeries { - my $config = shift; - my $permissions = shift; - my $params = shift; - my $cal_options = shift; + my $config = shift; + my $permissions = shift; + my $params = shift; + my $cal_options = shift; - my $project_id = $params->{project_id}; - my $studio_id = $params->{studio_id}; + my $project_id = $params->{project_id}; + my $studio_id = $params->{studio_id}; - my $series = series::get( - $config, - { - project_id => $project_id, - studio_id => $studio_id - } - ); + my $series = series::get( + $config, + { + project_id => $project_id, + studio_id => $studio_id + } + ); - my $out = ''; + my $out = ''; - #add schedule entry for series - if ( ( defined $permissions->{update_schedule} ) && ( $permissions->{update_schedule} eq '1' ) && ( @$series > 0 ) ) { - $out .= q{<div id="series" style="display:none">}; - $out .= addSeries( $series, $params ); - $out .= q{</div>}; - } + #add schedule entry for series + if ( ( defined $permissions->{update_schedule} ) + && ( $permissions->{update_schedule} eq '1' ) + && ( scalar(@$series) > 0 ) ) + { + $out .= q{<div id="series" style="display:none">}; + $out .= addSeries( $series, $params ); + $out .= q{</div>}; + } - if ( ( $params->{studio_id} ne '' ) && ( $params->{studio_id} ne '-1' ) ) { - $out .= q{<div id="event_no_series" style="display:none">}; - $out .= addEventsToSeries( $series, $params ) - if ( ( defined $permissions->{assign_series_events} ) && ( $permissions->{assign_series_events} eq '1' ) ); - $out .= createSeries($params) if ( ( defined $permissions->{create_series} ) && ( $permissions->{create_series} eq '1' ) ); - $out .= q{</div>}; - } + if ( ( $params->{studio_id} ne '' ) && ( $params->{studio_id} ne '-1' ) ) { + $out .= q{<div id="event_no_series" style="display:none">}; + $out .= addEventsToSeries( $series, $params ) + if ( ( defined $permissions->{assign_series_events} ) + && ( $permissions->{assign_series_events} eq '1' ) ); + $out .= createSeries($params) + if ( ( defined $permissions->{create_series} ) + && ( $permissions->{create_series} eq '1' ) ); + $out .= q{</div>}; + } - $out .= q{ + $out .= q{ <div id="no_studio_selected" style="display:none"> } . $params->{loc}->{label_no_studio_selected} . q{ </div> }; - print $out; + print $out; } sub printJavascript { - my $config = shift; - my $permissions = shift; - my $params = shift; - my $cal_options = shift; + my $config = shift; + my $permissions = shift; + my $params = shift; + my $cal_options = shift; - my $startOfDay = $cal_options->{min_hour} % 24; + my $startOfDay = $cal_options->{min_hour} % 24; - #print STDERR "js: ".$cal_options->{min_hour}." ".$startOfDay."\n"; - my $out = q{ + #print STDERR "js: ".$cal_options->{min_hour}." ".$startOfDay."\n"; + my $out = q{ <script> var region='} . $params->{loc}->{region} . q{'; var calendarTable=1; @@ -1193,59 +1293,66 @@ sub printJavascript { var label_events='} . $params->{loc}->{label_events} . q{'; var label_schedule='} . $params->{loc}->{label_schedule} . q{'; var label_worktime='} . $params->{loc}->{label_worktime} . q{'; + var label_descriptions='} . $params->{loc}->{label_descriptions} . q{'; var label_playout='} . $params->{loc}->{label_playout} . q{'; + var label_pin='} . $params->{loc}->{label_pin} . q{'; </script> }; - print $out; + print $out; } #TODO: Javascript sub addCalendarButton { - my $params = shift; - my $calendar = shift; + my $params = shift; + my $calendar = shift; - #add calendar button - my $content = qq{ + #add calendar button + my $content = qq{ <div id="previous_month"><a id="previous">«</a></div> - <div id="selectDate"> - <input id="start_date"/> + <div id="selectDate" data-toggle> + <input id="start_date" data-input/> <div id="current_date">$calendar->{month} $calendar->{year}</div> </div> <div id="next_month"><a id="next">»</a></div> }; - return $content; + return $content; } sub addSeries { - my $series = shift; - my $params = shift; + my $series = shift; + my $params = shift; - return unless defined $series; - return unless @$series > 0; + return unless defined $series; + return unless scalar @$series > 0; - my $out = ''; - $out .= q{ + my $out = ''; + $out .= q{ <table> <tr> <td>} . $params->{loc}->{label_series} . q{</td> <td><select id="series_select" name="series_id"> }; - for my $serie (@$series) { - my $id = $serie->{series_id} || -1; - my $duration = $serie->{duration} || 0; - my $name = $serie->{series_name} || ''; - my $title = $serie->{title} || ''; - $name = $params->{loc}->{single_events} if $serie->{has_single_events} eq '1'; - $title = ' - ' . $title if $title ne ''; + for my $serie (@$series) { + my $id = $serie->{series_id} || -1; + my $duration = $serie->{duration} || 0; + my $name = $serie->{series_name} || ''; + my $title = $serie->{title} || ''; + $name = $params->{loc}->{single_events} if $serie->{has_single_events} eq '1'; + $title = ' - ' . $title if $title ne ''; - $out .= '<option value="' . $id . '" duration="' . $duration . '">' . $name . $title . '</option>' . "\n"; - } + $out .= + '<option value="' + . $id + . '" duration="' + . $duration . '">' + . $name + . $title + . '</option>' . "\n"; + } - #print Dumper($series); - - $out .= q{ + $out .= q{ </select> </td> </tr> @@ -1260,22 +1367,22 @@ sub addSeries { </table> </div> }; - return $out; + return $out; } # create form to add events to series (that are not assigned to series, yet) sub addEventsToSeries { - my $series = shift; - my $params = shift; + my $series = shift; + my $params = shift; - return unless defined $series; - return unless @$series > 0; - my $project_id = $params->{project_id}; - my $studio_id = $params->{studio_id}; + return unless defined $series; + return unless scalar @$series > 0; + my $project_id = $params->{project_id}; + my $studio_id = $params->{studio_id}; - my $out = ''; - $out .= qq{ + my $out = ''; + $out .= qq{ <div> <b>} . $params->{loc}->{label_assign_event_series} . qq{</b> <form id="assign_series_events" method="post" action="series.cgi"> @@ -1288,54 +1395,61 @@ sub addEventsToSeries { <td><select id="select_series" name="series_id"> }; - for my $serie (@$series) { - my $id = $serie->{series_id} || -1; - my $duration = $serie->{duration} || ''; - my $name = $serie->{series_name} || ''; - my $title = $serie->{title} || ''; - $name = $params->{loc}->{single_events} if $serie->{has_single_events} == 1; - $title = ' - ' . $title if $title ne ''; - $out .= '<option value="' . $id . '" duration="' . $duration . '">' . $name . $title . '</option>' . "\n"; - } + for my $serie (@$series) { + my $id = $serie->{series_id} || -1; + my $duration = $serie->{duration} || ''; + my $name = $serie->{series_name} || ''; + my $title = $serie->{title} || ''; + $name = $params->{loc}->{single_events} if $serie->{has_single_events} == 1; + $title = ' - ' . $title if $title ne ''; + $out .= + '<option value="' + . $id + . '" duration="' + . $duration . '">' + . $name + . $title + . '</option>' . "\n"; + } - #print Dumper($series); - - $out .= q{ + $out .= q{ </select> </td> </tr> <tr><td></td> <td> <button type="submit" name="action" value="assign_event">} - . $params->{loc}->{button_assign_event_series} - . q{</button> + . $params->{loc}->{button_assign_event_series} . q{</button> </td> </tr> </table> </form> </div> }; - return $out; + return $out; } # insert form to create series on not assigned events sub createSeries { - my $params = shift; + my $params = shift; - my $project_id = $params->{project_id}; - my $studio_id = $params->{studio_id}; - return qq{ + my $project_id = $params->{project_id}; + my $studio_id = $params->{studio_id}; + return qq{ <div> <b>} . $params->{loc}->{label_create_series} . qq{</b> <form method="post" action="series.cgi"> <input type="hidden" name="project_id" value="$project_id"> <input type="hidden" name="studio_id" value="$studio_id"> <table> - <tr><td class="label">} . $params->{loc}->{label_name} . qq{</td> <td><input name="series_name"></td></tr> - <tr><td class="label">} . $params->{loc}->{label_title} . qq{</td> <td><input name="title"></td></tr> + <tr><td class="label">} + . $params->{loc}->{label_name} . qq{</td> <td><input name="series_name"></td></tr> + <tr><td class="label">} + . $params->{loc}->{label_title} . qq{</td> <td><input name="title"></td></tr> <tr><td></td> <td> - <button type="submit" name="action" value="create">} . $params->{loc}->{button_create_series} . qq{</button> + <button type="submit" name="action" value="create">} + . $params->{loc}->{button_create_series} . qq{</button> </td> </tr> </table> @@ -1345,520 +1459,574 @@ sub createSeries { } sub print_event { - my $params = shift; - my $event = shift; - my $ypos = shift; - my $yoffset = shift; - my $yzoom = shift; + my $params = shift; + my $event = shift; + my $ypos = shift; + my $yoffset = shift; + my $yzoom = shift; - $event->{project_id} = '-1' unless defined $event->{project_id}; - $event->{studio_id} = '-1' unless defined $event->{studio_id}; - $event->{series_id} = '-1' unless defined $event->{series_id}; - $event->{event_id} = '-1' unless defined $event->{event_id}; + $event->{project_id} = '-1' unless defined $event->{project_id}; + $event->{studio_id} = '-1' unless defined $event->{studio_id}; + $event->{series_id} = '-1' unless defined $event->{series_id}; + $event->{event_id} = '-1' unless defined $event->{event_id}; - my $id = 'event_' . $event->{project_id} . '_' . $event->{studio_id} . '_' . $event->{series_id} . '_' . $event->{event_id}; - $id = 'grid_' . $event->{project_id} . '_' . $event->{studio_id} . '_' . $event->{series_id} if defined $event->{grid}; - $id = 'work_' . $event->{project_id} . '_' . $event->{studio_id} . '_' . $event->{schedule_id} if defined $event->{work}; - $id = 'play_' . $event->{project_id} . '_' . $event->{studio_id} if defined $event->{play}; + my $id = + 'event_' + . $event->{project_id} . '_' + . $event->{studio_id} . '_' + . $event->{series_id} . '_' + . $event->{event_id}; + $id = 'grid_' . $event->{project_id} . '_' . $event->{studio_id} . '_' . $event->{series_id} + if defined $event->{grid}; + $id = 'work_' . $event->{project_id} . '_' . $event->{studio_id} . '_' . $event->{schedule_id} + if defined $event->{work}; + $id = 'play_' . $event->{project_id} . '_' . $event->{studio_id} if defined $event->{play}; - my $class = $event->{class} || ''; - my $showIcons = 0; - if ( $class =~ /(event|schedule)/ ) { - $class .= ' scheduled' if defined $event->{scheduled}; - $class .= ' no_series' if ( ( $class eq 'event' ) && ( $event->{series_id} eq '-1' ) ); - $class .= " error x$event->{error}" if defined $event->{error}; + my $class = $event->{class} || ''; + my $showIcons = 0; + if ( $class =~ /(event|schedule)/ ) { + $class .= ' scheduled' if defined $event->{scheduled}; + $class .= ' no_series' if ( ( $class eq 'event' ) && ( $event->{series_id} eq '-1' ) ); + $class .= " error x$event->{error}" if defined $event->{error}; - for my $filter ( 'rerun', 'archived', 'playout', 'published', 'live', 'disable_event_sync', 'draft' ) { - $class .= ' ' . $filter if ( ( defined $event->{$filter} ) && ( $event->{$filter} eq '1' ) ); - } - $class .= ' preproduced' unless ( ( defined $event->{'live'} ) && ( $event->{'live'} eq '1' ) ); - $class .= ' no_playout' unless ( ( defined $event->{'playout'} ) && ( $event->{'playout'} eq '1' ) ); - $class .= ' no_rerun' unless ( ( defined $event->{'rerun'} ) && ( $event->{'rerun'} eq '1' ) ); - $showIcons = 1; - } + for my $filter ( 'rerun', 'archived', 'playout', 'published', 'live', 'disable_event_sync', + 'draft' ) + { + $class .= ' ' . $filter + if ( ( defined $event->{$filter} ) && ( $event->{$filter} eq '1' ) ); + } + $class .= ' preproduced' + unless ( ( defined $event->{'live'} ) && ( $event->{'live'} eq '1' ) ); + $class .= ' no_playout' + unless ( ( defined $event->{'playout'} ) && ( $event->{'playout'} eq '1' ) ); + $class .= ' no_rerun' + unless ( ( defined $event->{'rerun'} ) && ( $event->{'rerun'} eq '1' ) ); + $showIcons = 1; + } - my $ystart = $event->{ystart} - $yoffset; - my $yend = $event->{yend} - $yoffset - 10; + my $ystart = $event->{ystart} - $yoffset; + my $yend = $event->{yend} - $yoffset - 10; - $ystart = int( $ystart * $yzoom ); - $yend = int( $yend * $yzoom ); - my $height = $yend - $ystart + 2; + $ystart = int( $ystart * $yzoom ); + $yend = int( $yend * $yzoom ); + my $height = $yend - $ystart + 1; - if ( $ypos > 0 ) { - $height = q{height:} . ($height) . 'px;'; - } else { - $height = ''; - } + if ( $ypos > 0 ) { + $height = q{height:} . ($height) . 'px;'; + } else { + $height = ''; + } - my $date = $event->{origStart} || $event->{start} || ''; - $date = $event->{time} if defined $event->{time}; - $date = $event->{date} if defined $event->{date}; - my $content = $event->{content} || ''; + my $content = '<div class="header">'; + $content .= qq!<img class="icon" src="!.($event->{series_icon_url}).q!">! if $class=~/event/; + $content .= $event->{content} || ''; + $content .= '</div>'; - if ( $class =~ /schedule/ ) { - my $frequency = getFrequency($event); - $content .= "<br>($frequency)" if defined $frequency; - } + if ( $class =~ /schedule/ ) { + my $frequency = getFrequency($event); + $content .= "<br>($frequency)" if defined $frequency; + } - my $attr = ''; - if ( $class =~ /play/ ) { - $attr .= ' rms="' . $event->{rms_image} . '"' if defined $event->{rms_image}; - $attr .= ' start="' . $event->{start} . '"' if defined $event->{start}; - } + my $attr = ''; + if ( $class =~ /play/ ) { + $attr .= ' rms="' . $event->{rms_image} . '"' if defined $event->{rms_image}; + $attr .= ' start="' . $event->{start} . '"' if defined $event->{start}; + } - if ($showIcons) { - $content = '<div class="text">' . $content . '</div><div class="icons"></div>'; - } + if ( defined $event->{upload} ) { + $content .= '<br>uploading <progress max="10" ></progress> '; + } - return - q{<div } - . qq{class="$class" id="$id" style="} - . $height . q{top:} - . $ystart . q{px;"} - . qq{ date="$date"} - . qq{ $attr} - . qq{>$content</div>} . "\n"; + $content .= q{<div class="scrollable">}; + $content .= q{<div class="excerpt">}.$event->{excerpt}.q{</div>} if defined $event->{excerpt}; + $content .= q{<div class="excerpt">}.$event->{html_topic}.q{</div>} if defined $event->{topic}; + $content .= q{</div>}; + + if ($showIcons) { + my $attr = { map { $_ => undef } split( /\s+/, $class) }; + + my $file = $event->{file} + ? 'playout: ' . $event->{file} =~ s/\'/\'/gr + : 'playout'; + + my $playoutClass = qq{<img src="image/play.svg">}; + my $processingClass = qq{<img src="image/processing.svg">}; + my $preparedClass = qq{<img src="image/prepare.svg">}; + my $icons = ''; + + if ( exists $attr->{event} ){ + my $playout = ''; + if (exists $attr->{upload_status}){ + $playout = $processingClass if $attr->{upload_status} ne ''; + $playout = $preparedClass if $attr->{upload_status} eq 'done'; + } + $playout = $playoutClass if exists $attr->{playout}; + $icons.='<img src="image/mic.svg" title="live"/>' + if exists($attr->{live}) && exists($attr->{no_rerun}); + $icons.='<img src="image/mic_off.svg" title="preproduced"/>' + if exists($attr->{preproduced}) && exists($attr->{no_rerun}); + $icons.='<img src="image/replay.svg" title="rerun"/>' + if exists $attr->{rerun}; + $icons.=qq{<img src="image/play.svg" title="$file" onmouseenter="console.log('$file');"/>} + if $playout; + $icons.='<img src="image/archive.svg" title="archived"/>' + if exists $attr->{archived}; + } + + $content = qq{<div class="text" style="$height">$content</div><div class="icons">$icons</div>}; + } + + my $time = ''; + $time = qq{ time="$event->{time}"} if $class =~ m/time/; + + my $date = ''; + $date = qq{ date="$event->{date}"} if $class =~ m/date/; + + my $line = q{<div } . qq{class="$class" id="$id"}; + $line .= qq{ style="} . $height . q{top:} . $ystart . q{px;"}; + $line .= $time . $date . qq{ $attr}; + $line .= qq{>$content</div>}; + $line .= "\n"; + return $line; } sub getFrequency { - my $event = shift; + my $event = shift; - my $period_type = $event->{period_type}; - return undef unless defined $period_type; - return undef if $period_type ne 'days'; + my $period_type = $event->{period_type}; + return undef unless defined $period_type; + return undef if $period_type ne 'days'; - my $frequency = $event->{frequency}; - return undef unless defined $frequency; - return undef unless $frequency > 0; + my $frequency = $event->{frequency}; + return undef unless defined $frequency; + return undef unless $frequency > 0; - if ( ( $frequency >= 7 ) && ( ( $frequency % 7 ) == 0 ) ) { - $frequency /= 7; - return '1 week' if $frequency == 1; - return $frequency .= ' weeks'; - } + if ( ( $frequency >= 7 ) && ( ( $frequency % 7 ) == 0 ) ) { + $frequency /= 7; + return '1 week' if $frequency == 1; + return $frequency .= ' weeks'; + } - return '1 day' if $frequency == 1; - return $frequency .= ' days'; + return '1 day' if $frequency == 1; + return $frequency .= ' days'; } sub calc_positions { - my $events = $_[0]; - my $cal_options = $_[1]; + my $events = $_[0]; + my $cal_options = $_[1]; - my $start_of_day = $cal_options->{start_of_day}; + my $start_of_day = $cal_options->{start_of_day}; - for my $event (@$events) { - my ( $start_hour, $start_min ) = getTime( $event->{start_time} ); - my ( $end_hour, $end_min ) = getTime( $event->{end_time} ); + for my $event (@$events) { + my ( $start_hour, $start_min ) = getTime( $event->{start_time} ); + my ( $end_hour, $end_min ) = getTime( $event->{end_time} ); - $start_hour += 24 if $start_hour < $start_of_day; - $end_hour += 24 if $end_hour <= $start_of_day; - $event->{ystart} = $start_hour * 60 + $start_min; - $event->{yend} = $end_hour * 60 + $end_min; - } + $start_hour += 24 if $start_hour < $start_of_day; + $end_hour += 24 if $end_hour < $start_of_day; + $end_hour += 24 if $start_hour > $end_hour; + $end_hour += 24 if ( $start_hour == $end_hour ) && ( $start_min == $end_min ); + + $event->{ystart} = $start_hour * 60 + $start_min; + $event->{yend} = $end_hour * 60 + $end_min; + } } sub find_errors { - my $events = $_[0]; + my $events = $_[0]; - for my $event (@$events) { - next if defined $event->{grid}; - next if defined $event->{work}; - next if defined $event->{play}; - next if (defined $event->{draft}) && ($event->{draft} == 1); - next unless defined $event->{ystart}; - next unless defined $event->{yend}; - $event->{check_errors} = 1; - } + for my $event (@$events) { + next if defined $event->{grid}; + next if defined $event->{work}; + next if defined $event->{play}; + next if ( defined $event->{draft} ) && ( $event->{draft} == 1 ); + next unless defined $event->{ystart}; + next unless defined $event->{yend}; + $event->{check_errors} = 1; + } - #check next events - for my $i ( 0 .. @$events - 1 ) { - my $event = $events->[$i]; - next unless defined $event->{check_errors}; + #check next events + for my $i ( 0 .. scalar(@$events) - 1 ) { + my $event = $events->[$i]; + next unless defined $event->{check_errors}; - #look for conflicts with next 5 events of day - my $min_index = $i + 1; - next if $min_index >= @$events; - my $max_index = $i + 8; - $max_index = @$events - 1 if $max_index >= @$events; - for my $j ( $min_index .. $max_index ) { - my $event2 = $events->[$j]; - next unless defined $event2->{check_errors}; + #look for conflicts with next 5 events of day + my $min_index = $i + 1; + next if $min_index >= scalar @$events; + my $max_index = $i + 8; + $max_index = scalar(@$events) - 1 if $max_index >= (@$events); + for my $j ( $min_index .. $max_index ) { + my $event2 = $events->[$j]; + next unless defined $event2->{check_errors}; - #mark events if same start,stop,series_id, one is schedule one is event - if ( ( defined $event->{series_id} ) - && ( defined $event2->{series_id} ) - && ( $event->{series_id} == $event2->{series_id} ) ) - { - if ( ( $event->{ystart} eq $event2->{ystart} ) - && ( $event->{yend} eq $event2->{yend} ) ) - { - if ( ( defined $event->{schedule} ) && ( !( defined $event2->{schedule} ) ) ) { - $event->{hide} = 1; - $event2->{scheduled} = 1; - next; - } - if ( ( !( defined $event->{schedule} ) ) && ( defined $event2->{schedule} ) ) { - $event->{scheduled} = 1; - $event2->{hide} = 1; - next; - } - } elsif ( ( $event->{ystart} >= $event2->{ystart} ) - && ( $event->{scheduled} == 1 ) - && ( $event2->{scheduled} == 1 ) ) - { - #subsequent schedules - $event->{error}++; - $event2->{error} = 1 unless defined $event2->{error}; - $event2->{error}++; - next; - } - } elsif ( $event->{ystart} >= $event2->{ystart} ) { + #mark events if same start,stop,series_id, one is schedule one is event + if ( ( defined $event->{series_id} ) + && ( defined $event2->{series_id} ) + && ( $event->{series_id} == $event2->{series_id} ) ) + { + if ( ( $event->{ystart} eq $event2->{ystart} ) + && ( $event->{yend} eq $event2->{yend} ) ) + { + if ( ( defined $event->{schedule} ) && ( !( defined $event2->{schedule} ) ) ) { + $event->{hide} = 1; + $event2->{scheduled} = 1; + next; + } + if ( ( !( defined $event->{schedule} ) ) && ( defined $event2->{schedule} ) ) { + $event->{scheduled} = 1; + $event2->{hide} = 1; + next; + } + } elsif ( ( $event->{ystart} >= $event2->{ystart} ) + && ( $event->{scheduled} == 1 ) + && ( $event2->{scheduled} == 1 ) ) + { + #subsequent schedules + $event->{error}++; + $event2->{error} = 1 unless defined $event2->{error}; + $event2->{error}++; + next; + } + } elsif ( $event->{ystart} >= $event2->{ystart} ) { - #errors on multiple schedules or events - $event->{error}++; - $event2->{error} = 1 unless defined $event2->{error}; - $event2->{error}++; - } - } - } + #errors on multiple schedules or events + $event->{error}++; + $event2->{error} = 1 unless defined $event2->{error}; + $event2->{error}++; + } + } + } - #remove error tags from correctly scheduled entries (subsequent entries with same series id) - for my $event (@$events) { - delete $event->{error} - if ( - ( defined $event->{error} ) - && ( ( ( defined $event->{scheduled} ) && ( $event->{scheduled} == 1 ) ) - || ( ( defined $event->{hide} ) && ( $event->{hide} == 1 ) ) ) - ); - } + #remove error tags from correctly scheduled entries (subsequent entries with same series id) + for my $event (@$events) { + delete $event->{error} + if ( + ( defined $event->{error} ) + && ( ( ( defined $event->{scheduled} ) && ( $event->{scheduled} == 1 ) ) + || ( ( defined $event->{hide} ) && ( $event->{hide} == 1 ) ) ) + ); + } } sub printToolbar { - my $config = shift; - my $params = shift; - my $calendar = shift; + my $config = shift; + my $params = shift; + my $calendar = shift; - #print Dumper($params); - my $today = time::time_to_date(); + my $today = time::time_to_date(); - #setToday (TODO:javascript) - my $toolbar = '<div id="toolbar">'; + my $toolbar = '<div id="toolbar">'; - #$toolbar.='<div class="cal_nav">'.addCalendarButton($params, $calendar).'</div>'; - $toolbar .= addCalendarButton( $params, $calendar ); - $toolbar .= qq{<button id="setToday">} . $params->{loc}->{button_today} . qq{</button>}; + $toolbar .= addCalendarButton( $params, $calendar ); + $toolbar .= qq{<button id="setToday">} . $params->{loc}->{button_today} . qq{</button>}; - #ranges - my $ranges = { - $params->{loc}->{label_month} => 'month', - $params->{loc}->{label_4_weeks} => '28', - $params->{loc}->{label_2_weeks} => '14', - $params->{loc}->{label_1_week} => '7', - $params->{loc}->{label_day} => '1', - }; - $toolbar .= qq{ + #ranges + my $ranges = { + $params->{loc}->{label_month} => 'month', + $params->{loc}->{label_4_weeks} => '28', + $params->{loc}->{label_2_weeks} => '14', + $params->{loc}->{label_1_week} => '7', + $params->{loc}->{label_day} => '1', + }; + $toolbar .= qq{ <select id="range" name="range" onchange="reloadCalendar()" value="$params->{range}"> }; - # my $options=[]; - for my $range ( - $params->{loc}->{label_month}, $params->{loc}->{label_4_weeks}, $params->{loc}->{label_2_weeks}, - $params->{loc}->{label_1_week}, $params->{loc}->{label_day} - ) - { - my $value = $ranges->{$range} || ''; - $toolbar .= qq{<option name="$range" value="$value">} . $range . '</option>'; - } - $toolbar .= q{ + # my $options=[]; + for my $range ( + $params->{loc}->{label_month}, $params->{loc}->{label_4_weeks}, + $params->{loc}->{label_2_weeks}, $params->{loc}->{label_1_week}, + $params->{loc}->{label_day} + ) + { + my $value = $ranges->{$range} || ''; + $toolbar .= qq{<option name="$range" value="$value">} . $range . '</option>'; + } + $toolbar .= q{ </select> }; - # start of day - my $day_start = $params->{day_start} || ''; - $toolbar .= qq{ - <select id="day_start" name="day_start" onchange="reloadCalendar()" value="$day_start"> + # start of day + my $day_start = $params->{day_start} || ''; + $toolbar .= qq{ + <select id="day_start" name="day_start" onchange="updateDayStart();reloadCalendar()" value="$day_start"> }; - for my $hour ( 0 .. 24 ) { - my $selected = ''; - $selected = 'selected="selected"' if $hour eq $day_start; - $toolbar .= qq{<option value="$hour">} . sprintf( "%02d:00", $hour ) . '</option>'; - } - $toolbar .= q{ + for my $hour ( 0 .. 24 ) { + my $selected = ''; + $selected = 'selected="selected"' if $hour eq $day_start; + $toolbar .= qq{<option value="$hour">} . sprintf( "%02d:00", $hour ) . '</option>'; + } + $toolbar .= q{ </select> }; - #filter - my $filter = $params->{filter} || ''; - $toolbar .= qq{ + #filter + my $filter = $params->{filter} || ''; + $toolbar .= qq{ <select id="filter" name="filter" onchange="reloadCalendar()"> }; - for my $filter ( 'no markup', 'conflicts', 'rerun', 'archived', 'playout', 'published', 'live', 'disable_event_sync', 'draft' ) { - my $key = $filter; - $key =~ s/ /_/g; + for my $filter ( + 'no markup', 'conflicts', 'rerun', 'archived', + 'playout', 'published', 'live', 'disable_event_sync', + 'draft' + ) + { + my $key = $filter; + $key =~ s/ /_/g; - $toolbar .= qq{<option value="$filter">} . $params->{loc}->{ 'label_' . $key } . '</option>'; - } + $toolbar .= + qq{<option value="$filter">} . $params->{loc}->{ 'label_' . $key } . '</option>'; + } - $toolbar .= q{ + $toolbar .= q{ </select> }; - #search - $toolbar .= qq{ + #search + $toolbar .= qq{ <form class="search"> <input type="hidden" name="project_id" value="$params->{project_id}"> <input type="hidden" name="studio_id" value="$params->{studio_id}"> <input type="hidden" name="date" value="$params->{date}"> <input type="hidden" name="list" value="1"> - <input class="search" name="search" value="$params->{search}" placeholder="} . $params->{loc}->{button_search} . qq{"> - <button type="submit" name="action" value="search">} . $params->{loc}->{button_search} . qq{</button> + <input class="search" name="search" value="$params->{search}" placeholder="} + . $params->{loc}->{button_search} . qq{"> + <button type="submit" name="action" value="search">} + . $params->{loc}->{button_search} . qq{</button> </form> }; - # - $toolbar .= qq{ + # + $toolbar .= qq{ <button id="editSeries">} . $params->{loc}->{button_edit_series} . qq{</button> } if $params->{list} == 1; - $toolbar .= qq{ + $toolbar .= qq{ </div> }; - print $toolbar; + print $toolbar; } sub getTime { - my $time = shift; - if ( $time =~ /^(\d\d)\:(\d\d)/ ) { - return ( $1, $2 ); - } - return ( -1, -1 ); + my $time = shift; + if ( $time =~ /^(\d\d)\:(\d\d)/ ) { + return ( $1, $2 ); + } + return ( -1, -1 ); } sub getCalendar { - my $config = shift; - my $params = shift; - my $language = shift; + my $config = shift; + my $params = shift; + my $language = shift; - my $from_date = getFromDate( $config, $params ); - my $till_date = getTillDate( $config, $params ); - my $range = $params->{range}; + my $from_date = getFromDate( $config, $params ); + my $till_date = getTillDate( $config, $params ); + my $range = $params->{range}; - my $previous = ''; - my $next = ''; - if ( $range eq 'month' ) { - $previous = time::get_datetime( $from_date, $config->{date}->{time_zone} )->subtract( months => 1 )->set_day(1)->date(); - $next = time::get_datetime( $from_date, $config->{date}->{time_zone} )->add( months => 1 )->set_day(1)->date(); - } else { - $previous = time::get_datetime( $from_date, $config->{date}->{time_zone} )->subtract( days => $range )->date(); - $next = time::get_datetime( $from_date, $config->{date}->{time_zone} )->add( days => $range )->date(); - } - my ( $year, $month, $day ) = split( /\-/, $from_date ); - $month = $time::names->{$language}->{months_abbr}->[ $month - 1 ] || ''; + my $previous = ''; + my $next = ''; + if ( $range eq 'month' ) { + $previous = + time::get_datetime( $from_date, $config->{date}->{time_zone} )->subtract( months => 1 ) + ->set_day(1)->date(); + $next = time::get_datetime( $from_date, $config->{date}->{time_zone} )->add( months => 1 ) + ->set_day(1)->date(); + } else { + $previous = time::get_datetime( $from_date, $config->{date}->{time_zone} ) + ->subtract( days => $range )->date(); + $next = + time::get_datetime( $from_date, $config->{date}->{time_zone} )->add( days => $range ) + ->date(); + } + my ( $year, $month, $day ) = split( /\-/, $from_date ); + my $monthName = time::getMonthNamesShort($language)->[ $month - 1 ] || ''; - return { - from_date => $from_date, - till_date => $till_date, - next_date => $next, - previous_date => $previous, - month => $month, - year => $year - }; + return { + from_date => $from_date, + till_date => $till_date, + next_date => $next, + previous_date => $previous, + month => $monthName, + year => $year + }; } sub getFromDate { - my $config = shift; - my $params = shift; + my $config = shift; + my $params = shift; - if ( $params->{from_date} ne '' ) { - return $params->{from_date}; - } - my $date = $params->{date}; - if ( $date eq '' ) { - $date = DateTime->now( time_zone => $config->{date}->{time_zone} )->date(); - } + if ( $params->{from_date} ne '' ) { + return $params->{from_date}; + } + my $date = $params->{date}; + if ( $date eq '' ) { + $date = DateTime->now( time_zone => $config->{date}->{time_zone} )->date(); + } - if ( $params->{range} eq '28' ) { + if ( $params->{range} eq '28' ) { - #get start of 4 week period - $date = time::get_datetime( $date, $config->{date}->{time_zone} )->truncate( to => 'week' )->ymd(); - } - if ( $params->{range} eq 'month' ) { + #get start of 4 week period + $date = time::get_datetime( $date, $config->{date}->{time_zone} )->truncate( to => 'week' ) + ->ymd(); + } + if ( $params->{range} eq 'month' ) { - #get first day of month - return time::get_datetime( $date, $config->{date}->{time_zone} )->set_day(1)->date(); - } + #get first day of month + return time::get_datetime( $date, $config->{date}->{time_zone} )->set_day(1)->date(); + } - #get date - return time::get_datetime( $date, $config->{date}->{time_zone} )->date(); + #get date + return time::get_datetime( $date, $config->{date}->{time_zone} )->date(); } sub getTillDate { - my $config = shift; - my $params = shift; - if ( $params->{till_date} ne '' ) { - return $params->{till_date}; - } - my $date = $params->{date} || ''; - if ( $date eq '' ) { - $date = DateTime->now( time_zone => $config->{date}->{time_zone} )->date(); - } - if ( $params->{range} eq '28' ) { - $date = time::get_datetime( $date, $config->{date}->{time_zone} )->truncate( to => 'week' )->ymd(); - } - if ( $params->{range} eq 'month' ) { + my $config = shift; + my $params = shift; + if ( $params->{till_date} ne '' ) { + return $params->{till_date}; + } + my $date = $params->{date} || ''; + if ( $date eq '' ) { + $date = DateTime->now( time_zone => $config->{date}->{time_zone} )->date(); + } + if ( $params->{range} eq '28' ) { + $date = time::get_datetime( $date, $config->{date}->{time_zone} )->truncate( to => 'week' ) + ->ymd(); + } + if ( $params->{range} eq 'month' ) { - #get last day of month - return time::get_datetime( $date, $config->{date}->{time_zone} )->set_day(1)->add( months => 1 )->subtract( days => 1 )->date(); - } + #get last day of month + return time::get_datetime( $date, $config->{date}->{time_zone} )->set_day(1) + ->add( months => 1 )->subtract( days => 1 )->date(); + } - #add range to date - return time::get_datetime( $date, $config->{date}->{time_zone} )->add( days => $params->{range} )->date(); + #add range to date + return time::get_datetime( $date, $config->{date}->{time_zone} ) + ->add( days => $params->{range} )->date(); } sub getSeriesEvents { - my $config = shift; - my $request = shift; - my $options = shift; - my $params = shift; + my $config = shift; + my $request = shift; + my $options = shift; + my $params = shift; - #get events by series id - my $series_id = $request->{params}->{checked}->{series_id}; - if ( defined $series_id ) { - my $events = series::get_events( $request->{config}, $options ); - return $events; - } + #get events by series id + my $series_id = $request->{params}->{checked}->{series_id}; + if ( defined $series_id ) { + my $events = series::get_events( $request->{config}, $options ); + return $events; + } - #get events (directly from database to get the ones, not assigned, yet) - delete $options->{studio_id}; - delete $options->{project_id}; + #get events (directly from database to get the ones, not assigned, yet) + delete $options->{studio_id}; + delete $options->{project_id}; + $options->{recordings} = 1; - my $request2 = { - params => { - checked => events::check_params( $config, $options ) - }, - config => $request->{config}, - permissions => $request->{permissions} - }; - $request2->{params}->{checked}->{published} = 'all'; - $request2->{params}->{checked}->{draft} = '1' if $params->{list}==1; - delete $request2->{params}->{checked}->{exclude_locations} - if ( ( $params->{studio_id} == -1 ) && ( defined $request2->{params}->{checked}->{exclude_locations} ) ); + my $request2 = { + params => { + checked => events::check_params( $config, $options ) + }, + config => $request->{config}, + permissions => $request->{permissions} + }; + $request2->{params}->{checked}->{published} = 'all'; + $request2->{params}->{checked}->{draft} = '1' if $params->{list} == 1; - my $events = events::get( $config, $request2 ); + my $events = events::get( $config, $request2 ); - #print STDERR Dumper($request2->{params}->{checked}); - #print STDERR Dumper($events); - series::add_series_ids_to_events( $request->{config}, $events ); + series::add_series_ids_to_events( $request->{config}, $events ); - my $studios = studios::get( - $request->{config}, - { - project_id => $options->{project_id} - } - ); - my $studio_id_by_location = {}; - for my $studio (@$studios) { - $studio_id_by_location->{ $studio->{location} } = $studio->{id}; - } + my $studios = studios::get( + $request->{config}, + { + project_id => $options->{project_id} + } + ); + my $studio_id_by_location = {}; + for my $studio (@$studios) { + $studio_id_by_location->{ $studio->{location} } = $studio->{id}; + } - for my $event (@$events) { - $event->{project_id} = $options->{project_id} unless defined $event->{project_id}; - $event->{studio_id} = $studio_id_by_location->{ $event->{location} } unless defined $event->{studio_id}; - } + for my $event (@$events) { + $event->{project_id} = $options->{project_id} unless defined $event->{project_id}; + $event->{studio_id} = $studio_id_by_location->{ $event->{location} } + unless defined $event->{studio_id}; + } - return $events; + return $events; } sub check_params { - my $params = shift; - my $config = shift; + my $config = shift; + my $params = shift; - my $checked = {}; - my $template = ''; - $checked->{template} = template::check( $params->{template}, 'series' ); + my $checked = { + user => $config->{user} + }; + my $template = ''; + $checked->{template} = template::check( $config, $params->{template}, 'series' ); - my $debug = $params->{debug} || ''; - if ( $debug =~ /([a-z\_\,]+)/ ) { - $debug = $1; - } - $checked->{debug} = $debug; + #numeric values + $checked->{part} = 0; + $checked->{list} = 0; + $checked->{open_end} = 1; + entry::set_numbers( $checked, $params, [ + 'id', 'project_id', 'studio_id', 'default_studio_id', + 'user_id', 'series_id', 'event_id', 'part', + 'list', 'day_start', 'open_end' + ]); - #numeric values - $checked->{part} = 0; - $checked->{list} = 0; - for my $param ( 'id', 'project_id', 'studio_id', 'default_studio_id', 'user_id', 'series_id', 'event_id', 'part', 'list', 'day_start' ) - { - if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /^\d+$/ ) ) { - $checked->{$param} = $params->{$param}; - } - } + my $start = user_day_start::get( $config, { + user => $checked->{user}, + project_id => $checked->{project_id}, + studio_id => $checked->{studio_id} + }); + print STDERR "read start $start\n"; + $checked->{day_start} = $start->{day_start} if $start; + $checked->{day_start} = $config->{date}->{day_starting_hour} + unless defined $checked->{day_start}; + $checked->{day_start} %= 24; - $checked->{day_start} = $config->{date}->{day_starting_hour} unless defined $checked->{day_start}; - $checked->{day_start} %= 24; + if ( defined $checked->{studio_id} ) { - if ( defined $checked->{studio_id} ) { + # a studio is selected, use the studio from parameter + $checked->{default_studio_id} = $checked->{studio_id}; + } elsif ( ( defined $params->{studio_id} ) && ( $params->{studio_id} eq '-1' ) ) { - # a studio is selected, use the studio from parameter - $checked->{default_studio_id} = $checked->{studio_id}; - } elsif ( ( defined $params->{studio_id} ) && ( $params->{studio_id} eq '-1' ) ) { + # all studios selected, use -1 + $checked->{studio_id} = -1; + } else { - # all studios selected, use -1 - $checked->{studio_id} = -1; - } else { + # no studio given, use default studio + $checked->{studio_id} = $checked->{default_studio_id}; + } - # no studio given, use default studio - $checked->{studio_id} = $checked->{default_studio_id}; - } + for my $param ('expires') { + $checked->{$param} = time::check_datetime( $params->{$param} ); + } - $checked->{open_end} = 1; - for my $param ('open_end') { - if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /^\d+$/ ) ) { - $checked->{$param} = $params->{$param}; - } - } + #scalars + $checked->{search} = ''; + $checked->{filter} = ''; - #scalars - $checked->{search} = ''; - $checked->{filter} = ''; + for my $param ( 'date', 'from_date', 'till_date' ) { + $checked->{$param} = time::check_date( $params->{$param} ); + } - #$checked->{range}='month'; - for my $param ( 'search', 'filter', 'range' ) { - if ( defined $params->{$param} ) { - $checked->{$param} = $params->{$param}; - $checked->{$param} =~ s/^\s+//g; - $checked->{$param} =~ s/\s+$//g; - } - } + entry::set_strings( $checked, $params, [ + 'search', 'filter', 'range', + 'series_name', 'title', 'excerpt', 'content', + 'program', 'image', 'user_content' + ]); - for my $param ('expires') { - $checked->{$param} = time::check_datetime( $params->{$param} ); - } + $checked->{action} = entry::element_of( $params->{action}, + [ 'add_user', 'remove_user', 'delete', 'save', 'details', 'show', 'edit_event', 'save_event' ] + ); - for my $param ( 'date', 'from_date', 'till_date' ) { - $checked->{$param} = time::check_date( $params->{$param} ); - } - - for my $param ( 'series_name', 'title', 'excerpt', 'content', 'program', 'category', 'image', 'user_content' ) { - if ( defined $params->{$param} ) { - - #$checked->{$param}=uri_unescape(); - $checked->{$param} = $params->{$param}; - $checked->{$param} =~ s/^\s+//g; - $checked->{$param} =~ s/\s+$//g; - } - } - - #actions and roles - if ( defined $params->{action} ) { - if ( $params->{action} =~ /^(add_user|remove_user|delete|save|details|show|edit_event|save_event)$/ ) { - $checked->{action} = $params->{action}; - } - } - - return $checked; + return $checked; } diff --git a/website/agenda/planung/comment.cgi b/website/agenda/planung/comment.cgi index 64af386..cfb680e 100755 --- a/website/agenda/planung/comment.cgi +++ b/website/agenda/planung/comment.cgi @@ -1,34 +1,30 @@ #! /usr/bin/perl -w -use warnings "all"; use strict; -use URI::Escape; -use Encode; +use warnings; +no warnings 'redefine'; + +use URI::Escape(); +use Encode(); use Data::Dumper; -use MIME::Base64; -use Encode::Locale; +use MIME::Base64(); +use Encode::Locale(); -use params; -use config; -use log; -use template; -use db; -use auth; -use uac; +use params(); +use config(); +use entry(); +use log(); +use template(); +use db(); +use auth(); +use uac(); -#use roles; -use time; -use markup; -use project; -use studios; -use comments; - -#use events; -#use series; -#use series_dates; -#use series_events; -#use user_stats; -use localization; +use time(); +use markup(); +use project(); +use studios(); +use comments(); +use localization(); binmode STDOUT, ":utf8"; @@ -37,295 +33,283 @@ my $r = shift; my $config = config::get('../config/config.cgi'); my $debug = $config->{system}->{debug}; -my ( $user, $expires ) = auth::get_user( $cgi, $config ); -return if ( ( !defined $user ) || ( $user eq '' ) ); +my ( $user, $expires ) = auth::get_user( $config, $params, $cgi ); +return if ( !defined $user ) || ( $user eq '' ); my $user_presets = uac::get_user_presets( - $config, - { - user => $user, - project_id => $params->{project_id}, - studio_id => $params->{studio_id} - } + $config, + { + user => $user, + project_id => $params->{project_id}, + studio_id => $params->{studio_id} + } ); $params->{default_studio_id} = $user_presets->{studio_id}; -$params->{studio_id} = $params->{default_studio_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); -$params->{project_id} = $user_presets->{project_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); +$params = uac::setDefaultStudio( $params, $user_presets ); +$params = uac::setDefaultProject( $params, $user_presets ); my $request = { - url => $ENV{QUERY_STRING} || '', - params => { - original => $params, - checked => check_params($params), - }, + url => $ENV{QUERY_STRING} || '', + params => { + original => $params, + checked => check_params( $config, $params ), + }, }; #set user at params->presets->user $request = uac::prepare_request( $request, $user_presets ); -log::init($request); $params = $request->{params}->{checked}; -#print Dumper($params); #show header if ( ( params::isJson() ) || ( defined $params->{action} ) ) { - print "Content-Type:text/html; charset=utf-8;\n\n"; + print "Content-Type:text/html; charset=utf-8;\n\n"; } else { - my $headerParams = uac::set_template_permissions( $request->{permissions}, $params ); - $headerParams->{loc} = localization::get( $config, { user => $user, file => 'menu' } ); - template::process( 'print', template::check('default.html'), $headerParams ); - print q{ - <script src="js/datetime.js" type="text/javascript"></script> - } unless (params::isJson); + my $headerParams = uac::set_template_permissions( $request->{permissions}, $params ); + $headerParams->{loc} = localization::get( $config, { user => $user, file => 'menu' } ); + template::process( $config, 'print', template::check( $config, 'default.html' ), $headerParams ); + template::process( $config, 'print', template::check( $config, 'comment-header.html' ), $headerParams ) + unless (params::isJson); } -return unless defined uac::check( $config, $params, $user_presets ); +return unless uac::check( $config, $params, $user_presets ) == 1; if ( defined $params->{action} ) { - if ( $params->{action} eq 'get_json' ) { - getJson( $config, $request ); - return; - } - if ( $params->{action} eq 'setLock' ) { - setLock( $config, $request ); - return; - } - if ( $params->{action} eq 'setRead' ) { - setRead( $config, $request ); - return; - } + if ( $params->{action} eq 'get_json' ) { + getJson( $config, $request ); + return; + } + if ( $params->{action} eq 'setLock' ) { + setLock( $config, $request ); + return; + } + if ( $params->{action} eq 'setRead' ) { + setRead( $config, $request ); + return; + } } $config->{access}->{write} = 0; showComments( $config, $request ); sub showComments { - my $config = shift; - my $request = shift; + my $config = shift; + my $request = shift; - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - unless ( $permissions->{read_comment} == 1 ) { - uac::permissions_denied('read_comment'); - return; - } + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + unless ( $permissions->{read_comment} == 1 ) { + uac::permissions_denied('read_comment'); + return; + } - for my $attr ( 'project_id', 'studio_id' ) { - unless ( defined $params->{$attr} ) { - uac::print_error( "missing " . $attr . " to show comment" ); - return; - } - } + for my $attr ( 'project_id', 'studio_id' ) { + unless ( defined $params->{$attr} ) { + uac::print_error( "missing " . $attr . " to show comment" ); + return; + } + } - $config->{access}->{write} = 0; - my $dbh = db::connect($config); + $config->{access}->{write} = 0; + my $dbh = db::connect($config); - my $comment = $params->{comment}; - my $template_parameters = {}; + my $comment = $params->{comment}; + my $template_parameters = {}; - #my $nodes={}; - #my $sorted_nodes=[]; + #my $nodes={}; + #my $sorted_nodes=[]; - my $results = []; - if ( $params->{search} ne '' ) { - $params->{comment}->{search} = $params->{search}; - $results = comments::get_by_event( $dbh, $config, $request ); - } elsif ( $comment->{event_id} ne '' ) { - $results = comments::get_by_event( $dbh, $config, $request ); - } else { - $results = comments::get_by_time( $dbh, $config, $comment ); - } + my $results = []; + if ( $params->{search} ne '' ) { + $params->{comment}->{search} = $params->{search}; + $results = comments::get_by_event( $dbh, $config, $request ); + } elsif ( $comment->{event_id} ne '' ) { + $results = comments::get_by_event( $dbh, $config, $request ); + } else { + $results = comments::get_by_time( $dbh, $config, $comment ); + } - my $events = []; - my $comment_count = 0; - if ( @$results > 0 ) { - my $comments = modify_comments( $request, $results ); + my $events = []; + my $comment_count = 0; + if ( scalar(@$results) > 0 ) { + my $comments = modify_comments( $config, $request, $results ); - $comments = comments::sort( $config, $comments ); + $comments = comments::sort( $config, $comments ); - $events = comments::get_events( $dbh, $config, $request, $comments ); - my $language = $config::config->{date}->{language} || 'en'; - for my $event (@$events) { - $event->{start} = time::date_time_format( $event->{start}, $language ); - $comment_count += $event->{comment_count} if ( defined $event->{comment_count} ); - $event->{cache_base_url} = $config::config->{cache}->{base_url}; - } - } - for my $param (%$comment) { - $template_parameters->{$param} = $comment->{$param}; - } + $events = comments::get_events( $dbh, $config, $request, $comments ); + my $language = $config->{date}->{language} || 'en'; + for my $event (@$events) { + $event->{start} = time::date_time_format( $config, $event->{start}, $language ); + $comment_count += $event->{comment_count} if defined $event->{comment_count}; + $event->{cache_base_url} = $config->{cache}->{base_url}; + } + } + for my $param (%$comment) { + $template_parameters->{$param} = $comment->{$param}; + } - $template_parameters->{search} = markup::fix_utf8( $request->{params}->{original}->{search} ); - $template_parameters->{events} = $events; - $template_parameters->{debug} = $config->{system}->{debug}; - $template_parameters->{event_count} = @$events + 0; - $template_parameters->{comment_count} = $comment_count; - $template_parameters->{is_empty} = 1 if ( @$events == 0 ); - $template_parameters->{projects} = project::get_with_dates($config); - $template_parameters->{controllers} = $config->{controllers}; - $template_parameters->{allow} = $permissions; - $template_parameters->{loc} = localization::get( $config, { user => $params->{presets}->{user}, file => 'comment' } ); + $template_parameters->{search} = markup::fix_utf8( $request->{params}->{original}->{search} ); + $template_parameters->{events} = $events; + $template_parameters->{debug} = $config->{system}->{debug}; + $template_parameters->{event_count} = scalar(@$events); + $template_parameters->{comment_count} = $comment_count; + $template_parameters->{is_empty} = 1 if scalar @$events == 0; + $template_parameters->{projects} = project::get_with_dates($config); + $template_parameters->{controllers} = $config->{controllers}; + $template_parameters->{allow} = $permissions; + $template_parameters->{loc} = + localization::get( $config, { user => $params->{presets}->{user}, file => 'comment' } ); - #fill and output template - template::process( 'print', $params->{template}, $template_parameters ); + #fill and output template + template::process( $config, 'print', $params->{template}, $template_parameters ); } sub modify_comments { - my $request = shift; - my $results = shift; + my $config = shift; + my $request = shift; + my $results = shift; - my $language = $config::config->{date}->{language} || 'en'; - for my $result (@$results) { - $result->{start_date_name} = time::date_format( $result->{created_at}, $language ); - $result->{start_time_name} = time::time_format( $result->{created_at} ); - $result->{ $result->{lock_status} } = 1; - $result->{ $result->{news_status} } = 1; - } - return $results; + my $language = $config->{date}->{language} || 'en'; + for my $result (@$results) { + $result->{start_date_name} = time::date_format( $config, $result->{created_at}, $language ); + $result->{start_time_name} = time::time_format( $result->{created_at} ); + $result->{ $result->{lock_status} } = 1; + $result->{ $result->{news_status} } = 1; + } + return $results; } sub setLock { - my $config = shift; - my $request = shift; + my $config = shift; + my $request = shift; - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; - unless ( $permissions->{update_comment_status_lock} == 1 ) { - uac::permissions_denied('update_comment_status_lock'); - return; - } + unless ( $permissions->{update_comment_status_lock} == 1 ) { + uac::permissions_denied('update_comment_status_lock'); + return; + } - my $comment = $params->{comment}; - $comment->{id} = $comment->{comment_id}; - if ( $comment->{id} eq '' ) { - return; - } + my $comment = $params->{comment}; + $comment->{id} = $comment->{comment_id}; + if ( $comment->{id} eq '' ) { + return; + } - #todo change set_news_status to lock_status in comment module - $comment->{set_lock_status} = $comment->{lockStatus}; - $comment->{set_lock_status} = 'blocked' unless $comment->{set_lock_status} eq 'show'; + #todo change set_news_status to lock_status in comment module + $comment->{set_lock_status} = $comment->{lockStatus}; + $comment->{set_lock_status} = 'blocked' unless $comment->{set_lock_status} eq 'show'; - $config->{access}->{write} = 1; - my $dbh = db::connect($config); - print STDERR "setLock " . Dumper($comment); - comments::set_lock_status( $dbh, $config, $comment ); - print "done\n"; + $config->{access}->{write} = 1; + my $dbh = db::connect($config); + print STDERR "setLock " . Dumper($comment); + comments::set_lock_status( $dbh, $config, $comment ); + print "done\n"; } sub setRead { - my $config = shift; - my $request = shift; + my $config = shift; + my $request = shift; - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; - unless ( $permissions->{update_comment_status_read} == 1 ) { - uac::permissions_denied('update_comment_status_read'); - return; - } + unless ( $permissions->{update_comment_status_read} == 1 ) { + uac::permissions_denied('update_comment_status_read'); + return; + } - $config->{access}->{write} = 1; - my $dbh = db::connect($config); + $config->{access}->{write} = 1; + my $dbh = db::connect($config); - my $comment = $params->{comment}; - $comment->{id} = $comment->{comment_id}; - if ( $comment->{id} eq '' ) { - return; - } + my $comment = $params->{comment}; + $comment->{id} = $comment->{comment_id}; + if ( $comment->{id} eq '' ) { + return; + } - #todo change set_news_status to read_status in comment module - $comment->{set_news_status} = $comment->{readStatus}; - $comment->{set_news_status} = 'received' unless $comment->{set_news_status} eq 'unread'; + #todo change set_news_status to read_status in comment module + $comment->{set_news_status} = $comment->{readStatus}; + $comment->{set_news_status} = 'received' unless $comment->{set_news_status} eq 'unread'; - print STDERR "setRead " . Dumper($comment); - comments::set_news_status( $dbh, $config, $comment ); - print "done\n"; + print STDERR "setRead " . Dumper($comment); + comments::set_news_status( $dbh, $config, $comment ); + print "done\n"; } sub check_params { - my $params = shift; + my $config = shift; + my $params = shift; - my $checked = {}; + my $checked = {}; - #actions + $checked->{action} = entry::element_of($params->{action}, + [ 'setLock', 'setRead', 'showComment', 'update', 'delete']); - if ( defined $params->{action} ) { - if ( $params->{action} =~ /^(setLock|setRead|showComment)$/ ) { - $checked->{action} = $params->{action}; - } - } + #template + my $template = ''; + if ( defined $checked->{action} ) { + $template = template::check( $config, $params->{template}, 'edit-comment' ) + if $checked->{action} eq 'showComment'; + } else { + $template = template::check( $config, $params->{template}, 'comments' ); + } + $checked->{template} = $template; - #template - my $template = ''; - if ( defined $checked->{action} ) { - $template = template::check( $params->{template}, 'edit_comment' ) if $checked->{action} eq 'showComment'; - } else { - $template = template::check( $params->{template}, 'comments' ); - } - $checked->{template} = $template; + entry::set_numbers( $checked, $params, [ + 'project_id', 'studio_id', 'default_studio_id']); + + if ( defined $checked->{studio_id} ) { + $checked->{default_studio_id} = $checked->{studio_id}; + } else { + $checked->{studio_id} = -1; + } - #numeric values - for my $param ( 'project_id', 'studio_id', 'default_studio_id' ) { - if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /^\d+$/ ) ) { - $checked->{$param} = $params->{$param}; - } - } - if ( defined $checked->{studio_id} ) { - $checked->{default_studio_id} = $checked->{studio_id}; - } else { - $checked->{studio_id} = -1; - } + my $comment = {}; - my $comment = {}; + for my $key ('readStatus') { + my $value = $params->{$key}; + $comment->{$key} = $value if ( defined $value ) && ( $value =~ /^(received|unread)$/ ); + } - for my $key ('readStatus') { - my $value = $params->{$key}; - $comment->{$key} = $value if ( defined $value ) && ( $value =~ /^(received|unread)$/ ); - } + for my $key ('lockStatus') { + my $value = $params->{$key}; + $comment->{$key} = $value if ( defined $value ) && ( $value =~ /^(blocked|show)$/ ); + } - for my $key ('lockStatus') { - my $value = $params->{$key}; - $comment->{$key} = $value if ( defined $value ) && ( $value =~ /^(blocked|show)$/ ); - } + $comment->{event_start} = time::check_date( $params->{event_start} ) || ''; + $comment->{from} = time::check_date( $params->{from} ) || ''; + $comment->{till} = time::check_date( $params->{till} ) || ''; - $comment->{event_start} = time::check_date( $params->{event_start} ) || ''; - $comment->{from} = time::check_date( $params->{from} ) || ''; - $comment->{till} = time::check_date( $params->{till} ) || ''; + my $event_id = $params->{event_id} || ''; + if ( $event_id =~ /^(\d+)$/ ) { + $comment->{event_id} = $1; + } + $comment->{event_id} = '' unless defined $comment->{event_id}; - my $event_id = $params->{event_id} || ''; - if ( $event_id =~ /^(\d+)$/ ) { - $comment->{event_id} = $1; - } else { + my $id = $params->{comment_id} || ''; + if ( $id =~ /^(\d+)$/ ) { + $comment->{comment_id} = $1; + } + $comment->{comment_id} = '' unless defined $comment->{comment_id}; - # error('invalid event_id'); - } - $comment->{event_id} = '' unless defined $comment->{event_id}; + my $age = $params->{age} || ''; + if ( $age =~ /^(\d+)$/ ) { + $comment->{age} = $1; + } + $comment->{age} = '365' unless defined $comment->{age}; - my $id = $params->{comment_id} || ''; - if ( $id =~ /^(\d+)$/ ) { - $comment->{comment_id} = $1; - } - $comment->{comment_id} = '' unless defined $comment->{comment_id}; + my $search = $params->{search} || ''; + if ( ( defined $search ) && ( $search ne '' ) ) { + $search = substr( $search, 0, 100 ); + $search =~ s/^\s+//gi; + $search =~ s/\s+$//gi; + $search =~ s/\-\-//gi; + $search =~ s/\;//gi; + $checked->{search} = $search if $search ne ''; + } + $checked->{search} = '' unless defined $checked->{search}; + $checked->{comment} = $comment; - my $age = $params->{age} || ''; - if ( $age =~ /^(\d+)$/ ) { - $comment->{age} = $1; - } - $comment->{age} = '365' unless defined $comment->{age}; - - my $search = $params->{search} || ''; - if ( ( defined $search ) && ( $search ne '' ) ) { - $search = substr( $search, 0, 100 ); - $search =~ s/^\s+//gi; - $search =~ s/\s+$//gi; - $search =~ s/\-\-//gi; - $search =~ s/\;//gi; - $checked->{search} = $search if $search ne ''; - } - $checked->{search} = '' unless defined $checked->{search}; - $checked->{comment} = $comment; - - return $checked; + return $checked; } diff --git a/website/agenda/planung/create-events.cgi b/website/agenda/planung/create-events.cgi new file mode 100755 index 0000000..a95c22d --- /dev/null +++ b/website/agenda/planung/create-events.cgi @@ -0,0 +1,226 @@ +#!/usr/bin/perl + +use strict; +use warnings; +no warnings 'redefine'; + +use Data::Dumper; + +use params(); +use config(); +use entry(); +use template(); +use auth(); +use uac(); +use time(); + +use series(); +use eventOps(); + +use series_dates(); +use localization(); + +binmode STDOUT, ":utf8"; + +my $r = shift; +( my $cgi, my $params, my $error ) = params::get($r); + +my $config = config::get('../config/config.cgi'); +my $debug = $config->{system}->{debug}; +my ( $user, $expires ) = auth::get_user( $config, $params, $cgi ); +return if ( ( !defined $user ) || ( $user eq '' ) ); + +#print STDERR $params->{project_id}."\n"; +my $user_presets = uac::get_user_presets( + $config, + { + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + user => $user + } +); +$params->{default_studio_id} = $user_presets->{studio_id}; +$params = uac::setDefaultStudio( $params, $user_presets ); +$params = uac::setDefaultProject( $params, $user_presets ); + +#print STDERR $params->{project_id}."\n"; +my $request = { + url => $ENV{QUERY_STRING} || '', + params => { + original => $params, + checked => check_params( $config, $params ), + }, +}; +$request = uac::prepare_request( $request, $user_presets ); +$params = $request->{params}->{checked}; + +#process header +my $headerParams = uac::set_template_permissions( $request->{permissions}, $params ); +$headerParams->{loc} = localization::get( $config, { user => $user, file => 'menu' } ); +template::process( $config, 'print', template::check( $config, 'create-events-header.html' ), $headerParams ); +return unless uac::check( $config, $params, $user_presets ) == 1; + +my $permissions = $request->{permissions}; +unless ( $permissions->{create_event_from_schedule} == 1 ) { + uac::permissions_denied('create_event_from_schedule'); + return; +} + +if ( $params->{action} eq 'create_events' ) { + create_events( $config, $request ); +} else { + show_events( $config, $request ); +} + +sub show_events { + my $config = shift; + my $request = shift; + + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + unless ( $permissions->{assign_series_events} == 1 ) { + uac::permissions_denied('read_events'); + return; + } + + my $events = getDates( $config, $request ); + $params->{events} = $events; + $params->{total} = scalar(@$events); + $params->{action} = 'show'; + template::process( $config, 'print', $params->{template}, $params ); + +} + +sub create_events { + my $config = shift; + my $request = shift; + + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + unless ( $permissions->{assign_series_events} == 1 ) { + uac::permissions_denied('assign_series_events'); + return; + } + + print STDERR "create events\n"; + my $dates = getDates( $config, $request ); + + print STDERR "<pre>found " . ( scalar @$dates ) . " dates\n"; + my $events = []; + for my $date (@$dates) { + + #print STDERR $date->{start}."\n"; + push @$events, createEvent( $config, $request, $date ); + } + $params->{events} = $events; + $params->{total} = scalar(@$events); + $params->{action} = 'created'; + template::process( $config, 'print', $params->{template}, $params ); +} + +sub getDates { + my $config = shift; + my $request = shift; + + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + unless ( $permissions->{read_event} == 1 ) { + uac::permissions_denied('read_event'); + return; + } + + my $project_id = $params->{project_id}; + my $studio_id = $params->{studio_id}; + my $from_date = $params->{from_date}; + my $till_date = $params->{till_date}; + my $duration = $params->{duration}; + + $from_date = time::time_to_datetime(); + if ( $from_date =~ /(\d\d\d\d\-\d\d\-\d\d \d\d)/ ) { + $from_date = $1 . ':00'; + } + $till_date = time::add_days_to_datetime( $from_date, $duration ); + if ( $from_date =~ /(\d\d\d\d\-\d\d\-\d\d)/ ) { + $from_date = $1; + } + if ( $till_date =~ /(\d\d\d\d\-\d\d\-\d\d)/ ) { + $till_date = $1; + } + $params->{from_date} = $from_date; + $params->{till_date} = $till_date; + print STDERR "$0: get events from $from_date to $till_date\n"; + + my $dates = series_dates::getDatesWithoutEvent( + $config, + { + project_id => $project_id, + studio_id => $studio_id, + from => $from_date, + till => $till_date + } + ); + my $series = series::get( $config, { + project_id => $project_id, + studio_id => $studio_id + }); + my %series_by_id = map { $_->{series_id} => $_ } @$series; + for my $date (@$dates) { + my $serie = $series_by_id{$date->{series_id}}; + $date->{series_name} = $serie->{series_name}; + $date->{series_title} = $serie->{series_title}; + } + + return $dates; +} + +sub createEvent { + my $config = shift; + my $request = shift; + my $date = shift; + + my $permissions = $request->{permissions}; + my $user = $request->{user}; + + $date->{show_new_event_from_schedule} = 1; + unless ( $permissions->{create_event_from_schedule} == 1 ) { + uac::permissions_denied('create_event_from_schedule'); + return; + } + + $date->{start_date} = $date->{start}; + my $event = eventOps::getNewEvent( $config, $date, 'show_new_event_from_schedule' ); + + return undef unless defined $event; + + $event->{start_date} = $event->{start}; + eventOps::createEvent( $request, $event, 'create_event_from_schedule' ); + return $event; + +} + +sub check_params { + my $config = shift; + my $params = shift; + + my $checked = {}; + + $checked->{action} = entry::element_of($params->{action}, + ['create_events', 'show_events'])//''; + + $checked->{exclude} = 0; + $checked->{duration} = 28; + entry::set_numbers( $checked, $params, [ + 'id', 'project_id', 'studio_id', 'duration']); + $checked->{"duration".$checked->{duration}}='selected="selected"'; + + if ( defined $checked->{studio_id} ) { + $checked->{default_studio_id} = $checked->{studio_id}; + } else { + $checked->{studio_id} = -1; + } + + $checked->{template} = template::check( $config, $params->{template}, 'create-events' ); + + return $checked; +} + diff --git a/website/agenda/planung/create_events.cgi b/website/agenda/planung/create_events.cgi deleted file mode 100755 index 00f34b6..0000000 --- a/website/agenda/planung/create_events.cgi +++ /dev/null @@ -1,312 +0,0 @@ -#! /usr/bin/perl -w - -use warnings "all"; -use strict; -use Data::Dumper; - -use params; -use config; - -#use log; -#use template; -use auth; -use uac; - -#use roles; -#use project; -#use studios; -#use events; -use series; - -#use series_schedule; -#use series_events; -#use series_dates; -#use markup; -#use URI::Escape; -#use Encode; -use localization; - -binmode STDOUT, ":utf8"; - -my $r = shift; -( my $cgi, my $params, my $error ) = params::get($r); - -my $config = config::get('../config/config.cgi'); -my $debug = $config->{system}->{debug}; -my ( $user, $expires ) = auth::get_user( $cgi, $config ); -return if ( ( !defined $user ) || ( $user eq '' ) ); - -#print STDERR $params->{project_id}."\n"; -my $user_presets = uac::get_user_presets( - $config, - { - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - user => $user - } -); -$params->{default_studio_id} = $user_presets->{studio_id}; -$params->{studio_id} = $params->{default_studio_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); -$params->{project_id} = $user_presets->{project_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); - -#print STDERR $params->{project_id}."\n"; -my $request = { - url => $ENV{QUERY_STRING} || '', - params => { - original => $params, - checked => check_params($params), - }, -}; -$request = uac::prepare_request( $request, $user_presets ); -log::init($request); - -$params = $request->{params}->{checked}; - -#process header -my $headerParams = uac::set_template_permissions( $request->{permissions}, $params ); -$headerParams->{loc} = localization::get( $config, { user => $user, file => 'menu' } ); -template::process( 'print', template::check('default.html'), $headerParams ); -return unless uac::check( $config, $params, $user_presets ) == 1; - -print q{ - <script src="js/datetime.js" type="text/javascript"></script> - <script src="js/event.js" type="text/javascript"></script> - <script src="js/localization.js" type="text/javascript"></script> - <link rel="stylesheet" href="css/series.css" type="text/css" /> -}; - -my $permissions = $request->{permissions}; -unless ( $permissions->{create_event_from_schedule} == 1 ) { - uac::permissions_denied('create_event_from_schedule'); - return; -} - -if ( defined $params->{action} ) { - - # assign_series ($config, $request) if ($params->{action} eq 'assign_series'); -} - -#print Dumper($params); -show_events( $config, $request ); - -sub show_events { - my $config = shift; - my $request = shift; - - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - unless ( $permissions->{assign_series_events} == 1 ) { - uac::permissions_denied('assign_series_events'); - return; - } - - #print STDERR Dumper($params); - #print '<pre>'.Dumper($eventsByStart); - #return; - - my $scheduleDates = getScheduleDates( $config, $request ); - my $schedulesByStart = getEventsByDate($scheduleDates); - - my $events = getEvents( $config, $request ); - my $eventsByStart = getEventsByDate($events); - - print "<pre>\n"; - for my $date ( sort keys %$schedulesByStart ) { - my $schedules = $schedulesByStart->{$date}; - my $scheduleCount = scalar(@$schedules); - if ( $scheduleCount == 0 ) { - print "skip datetime $date, no schedule found\n"; - next; - } - if ( $scheduleCount > 1 ) { - print "skip datetime $date, $scheduleCount schedules found\n"; - next; - } - my $schedule = $schedules->[0]; - - if ( defined $eventsByStart->{$date} ) { - my $events = $eventsByStart->{$date}; - my $eventCount = scalar(@$events); - if ( $eventCount > 0 ) { - print "skip datetime $date, $eventCount events already exist\n"; - next; - } - } - print "found schedule without event for $date" . " - " . $schedule->{series_name} . " - " . $schedule->{title} . "\n"; - - #createEvent($config, $request, $schedule); - } -} - -# get a list of events with given start datetime -sub getEventsByDate { - my $events = shift; - - my $eventsByDate = {}; - for my $event (@$events) { - my $startDate = $event->{start}; - push @{ $eventsByDate->{$startDate} }, $event; - } - return $eventsByDate; -} - -sub getScheduleDates { - my $config = shift; - my $request = shift; - - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - - my $options = {}; - - my $from = $params->{from_date}; - my $till = $params->{till_date}; - my $project_id = $params->{project_id}; - my $studio_id = $params->{studio_id}; - - #build series filter - $options = { - project_id => $project_id, - studio_id => $studio_id, - from => $from, - till => $till, - date_range_include => 1, - exclude => 0 - }; - - #get all series dates - my $series_dates = series_dates::get_series( $config, $options ); - return $series_dates; -} - -sub getEvents { - my $config = shift; - my $request = shift; - - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - - my $options = {}; - - my $from = $params->{from_date}; - my $till = $params->{till_date}; - my $project_id = $params->{project_id}; - my $studio_id = $params->{studio_id}; - - #build event filter - $options = { - project_id => $project_id, - template => 'no', - limit => 600, - get => 'no_content', - from_date => $from, - till_date => $till, - date_range_include => 1, - archive => 'all', - no_exclude => '1', - }; - - my $events = getSeriesEvents( $config, $request, $options, $params ); - return $events; -} - -sub getSeriesEvents { - my $config = shift; - my $request = shift; - my $options = shift; - my $params = shift; - - #get events by series id - my $series_id = $request->{params}->{checked}->{series_id}; - if ( defined $series_id ) { - my $events = series::get_events( $request->{config}, $options ); - return $events; - } - - #get events (directly from database to get the ones, not assigned, yet) - delete $options->{studio_id}; - delete $options->{project_id}; - - my $request2 = { - params => { - checked => events::check_params( $config, $options ) - }, - config => $request->{config}, - permissions => $request->{permissions} - }; - $request2->{params}->{checked}->{published} = 'all'; - delete $request2->{params}->{checked}->{exclude_locations} - if ( ( $params->{studio_id} == -1 ) && ( defined $request2->{params}->{checked}->{exclude_locations} ) ); - - my $events = events::get( $config, $request2 ); - - #print STDERR Dumper($request2->{params}->{checked}); - #print STDERR Dumper($events); - series::add_series_ids_to_events( $request->{config}, $events ); - - my $studios = studios::get( - $request->{config}, - { - project_id => $options->{project_id} - } - ); - my $studio_id_by_location = {}; - for my $studio (@$studios) { - $studio_id_by_location->{ $studio->{location} } = $studio->{id}; - } - - for my $event (@$events) { - $event->{project_id} = $options->{project_id} unless defined $event->{project_id}; - $event->{studio_id} = $studio_id_by_location->{ $event->{location} } unless defined $event->{studio_id}; - } - - return $events; -} - -sub check_params { - my $params = shift; - - my $checked = {}; - - my $debug = $params->{debug} || ''; - if ( $debug =~ /([a-z\_\,]+)/ ) { - $debug = $1; - } - $checked->{debug} = $debug; - - #actions and roles - $checked->{action} = ''; - if ( defined $params->{action} ) { - if ( $params->{action} =~ /^(create_events)$/ ) { - $checked->{action} = $params->{action}; - } - } - - #numeric values - $checked->{exclude} = 0; - for my $param ( 'id', 'project_id', 'studio_id', 'series_id' ) { - if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /^\d+$/ ) ) { - $checked->{$param} = $params->{$param}; - } - } - - if ( defined $checked->{studio_id} ) { - $checked->{default_studio_id} = $checked->{studio_id}; - } else { - $checked->{studio_id} = -1; - } - - for my $param ( 'date', 'from_date', 'till_date' ) { - $checked->{$param} = time::check_date( $params->{$param} ); - } - - $checked->{template} = template::check( $params->{template}, 'create_events' ); - - return $checked; -} - -__DATA__ - -https://piradio.de/agenda/planung/create_events.cgi?project_id=1&studio_id=1&from_date=2016-09-01&till_date=2016-10-01 diff --git a/website/agenda/planung/css/admin.css b/website/agenda/planung/css/admin.css deleted file mode 100644 index 2477454..0000000 --- a/website/agenda/planung/css/admin.css +++ /dev/null @@ -1,429 +0,0 @@ - -body{ - margin:0; - padding:0; - color:#000; - background:#efefef; - height:100%; - text-align:center; -} - -body #content{ - margin:0; - padding:1em; - max-width:980px; - color:#000; - background:#fff; - text-align:left; -} - -body, -#content input, -#content textarea, -#content td, -#content div, -#content select, -#content option, -#content li{ - font-size:14px; - font-size:0.75rem; - font-family:sans-serif; -} - -#content textarea{ - padding:6px; - border:1px solid #ccc; -} - -@media handheld{ - body{ - max-width:800px; - font-size:1em; - } - input,button{ - padding:16px; - } - - #calcms_admin_menu{ - min-width:640px; - max-width:800px; - } -} - -#calcms_admin_menu{ - display: flex; - flex-wrap: wrap; - align-items: center; - justify-content: center; - vertical-align:middle; - z-index:99; -} - -#calcms_admin_menu, -#calcms_admin_menu a, -#calcms_admin_menu div, -#calcms_admin_menu input, -#calcms_admin_menu select, -#calcms_admin_menu option, -#calcms_admin_menu img -{ - margin:0; - padding:0; - color:#fff; -} - -#calcms_admin_menu img{ - border:0; - vertical-align:middle; -} - -#calcms_admin_menu, -#calcms_admin_menu select{ - background:#444; -} - -#calcms_admin_menu div a, -#calcms_admin_menu select{ - font-size:14px; - padding:6px; - padding-top:1em; - padding-bottom:1em; - line-height:3em; -} - -#calcms_admin_menu div:hover, -#calcms_admin_menu select:hover{ - background:#888; -} - -#calcms_admin_menu div { - transition: all 0.2s; -} - -#calcms_admin_menu select, -#calcms_admin_menu option{ - font-size:0.8rem; - width:8em; - border:0; - padding-left:0; - padding-right:0; - border-left:1px solid #666; -} - -#calcms_admin_menu a#logout{ - color:#ff4444; -} - -a{ - color:#000; - text-decoration:none; -} - -#content table{ - margin:1; - border-collapse:collapse; - width:100% -} - -#content table td{ - padding:6px; - border-collapse:collapse; - border-right:0; - border-left:0; -} - -#content table th{ - padding:6px; - border-collapse:collapse; -} - -#info{ - color:#000; - background:#fff; -} - -#content textarea{ - font-weight:normal; -} - - -#content div{ - padding:6px; -} - -#content div.header{ - font-size:16px; - text-align:left; - padding-left:0; -} - -#content .field{ - width:30em; -} - -#content .button{ - width:10em; -} - -*:focus {outline: none;} - -#content a{ - color:#000; - font-weight:normal; -} -#content a:hover{ - text-decoration:underline; -} - -#content form{ - border:0; - padding:0; - margin:0; -} - -#content div,td,tr,table{ - vertical-align:middle; -} - -#content td{ - padding:3px; -} - -#content pre, .pre { - border:0; - padding:2em; - color:#000; - background:#eee; -} - -.error.head{ - position:relative; - top:3em; -} - -li.ui-menu-item{ - background:none; - list-style-image:url(); - list-style-type:none; -} - -#content h1, -#content h2{ - margin:1em; - padding:0; - font-weight:100; -} - -#jobs th{ - text-align:left; -} - -#jobs td.status.finished a{ - color:#000; -} - -#jobs td.status.ongoing a{ - text-decoration:blink; - color:green; -} - -#jobs td.status.scheduled a{ - color:green; -} - -div.ok{ - border:2px solid #aca; - background:#cfc; - background: linear-gradient(to right, #cfc, white); - opacity:0.8; -} - -div.warn{ - border:2px solid #ff0; - background:#ff0; - background: linear-gradient(to right, #ff3, white); - opacity:0.8; -} - -div.error{ - border:2px solid #f99; - background:#fcc; - background: linear-gradient(to right, #fcc, white); - opacity:0.8; -} - -#content button, -#content select, -#content input{ - padding:4px; -} - -#content div.flex{ - display: flex; - flex-wrap: wrap; - align-items: center; - justify-content: center; -} - -#content div.card{ - border:0; - margin:1em; - box-shadow:0 2px 5px 0 rgba(0,0,0,.12),0 2px 10px 0 rgba(0,0,0,.09); - border-radius:3px; -} - -#content div.card div.title{ - font-size:16px; -} - -#content table.table tr{ - border-bottom:solid 1px #ebebeb; -} -#content table.table tr:hover{ - background:#ebebeb -} - -#content div.card tr{ - border-bottom:none; -} -#content div.card tr:hover{ - background:none; -} - -/*overwrite jquery ui*/ - -#content .ui-tabs-nav{ - border:0; - background:#fff; - border-bottom: solid 1px #ccc; -} - -#content .ui-tab a{ - color:#fff; -} - -#content .ui-tabs-tab{ - border:0; - background:#aaa; - padding:6px; - border-radius: 3px 3px 0 0; -} - -#content .ui-tab a:hover{ - text-decoration:none; -} - -/* overwrite tablesorter */ -tr.tablesorter-filter-row{ - background:#ccc; -} -tr.tablesorter-filter-row input{ - height:1rem; - color:#000; -} - -/*colors*/ -#content input[type="submit"], -#content input[type="file"], -#content button, -#content .ui-state-active, -#content a.ui-button:active, -#content .ui-button:active{ - background-color:#2196f3; -} - -#content input[type="submit"]:hover, -#content input[type="file"]:hover, -#content button:hover, -#content .ui-button.ui-state-active:hover{ - background-color:#39a1f4; -} - -/*colors end */ -#content input[type="submit"], -#content input[type="file"], -#content button{ - border:none; - color:#fff; - padding:8px; - margin-top:0px; - margin-bottom:0px; - margin-left:6px; - text-align: center; - text-decoration: none; - font-size: 12px; -} - -#content input[type="submit"], -#content input[type="file"], -#content button{ - box-shadow:0 2px 5px 0 rgba(0,0,0,.16),0 2px 10px 0 rgba(0,0,0,.12); - position:relative; - transition:background-color .3s cubic-bezier(.64,.09,.08,1),box-shadow .3s cubic-bezier(.64,.09,.08,1); - padding:10px 20px; - display:inline-block; - border:0 -} - -#content input[type="submit"]:hover, -#content input[type="file"]:hover, -#content button:focus{ - outline:0; - transition:all 0.5s cubic-bezier(.64,.09,.08,1) -} - -#content input[type="submit"]:hover, -#content input[type="file"]:hover, -#content button:hover{ - box-shadow:0 5px 11px 0 rgba(0,0,0,.18),0 4px 15px 0 rgba(0,0,0,.15); -} - -#content input{ - border:none; - border-bottom:1px solid #03a9f4; - color:#000; - background:#fefefe; - padding:8px; - margin-top:0px; - margin-bottom:0px; - margin-left:6px; - text-decoration: none; -} - -#content input[type="text"]:focus{ - border-bottom:2px solid #03a9f4; -} - -#content textarea:focus{ - border:1px solid #03a9f4; -} - -#content select{ - color:#000; - padding:6px; - padding-left:0; - padding-right:0; - border:none; - border-bottom:solid 1px #9e9e9e; - cursor:pointer; - margin-left:6px; -} - -#content select, -input[type='checkbox']{ - margin-top:0px; -} - -#content div.buttons button{ - margin-bottom:6px; -} - -#content div.formField div.label{ - display:hide; - padding-left:1em; - color:#999; -} -#content div.formField input{ - clear:both; -} - diff --git a/website/agenda/planung/css/audio-recordings.css b/website/agenda/planung/css/audio-recordings.css new file mode 100644 index 0000000..05fd94d --- /dev/null +++ b/website/agenda/planung/css/audio-recordings.css @@ -0,0 +1,72 @@ +img { + margin-right: 1em; + margin-bottom: 1em; + vertical-align: middle +} + +#content div.panel { + padding: 1em; +} + +h2 { + line-height: 1.5em; +} + +.thin { + font-weight: 100; +} + +th { + text-align: center; +} + +tr.active{ + border-left:6px solid #0c0; +} +tr.inactive{ + border-left:6px solid #c00; +} + +#progressBar { + width: 100%; + height: 1rem; + border: 0; + box-shadow: #888 2px 2px 1px 1px; + transition : width 1s ease; +} + +#content div.ok, +#content div.warn, +#content div.error { + padding-top: 3px; + padding-bottom: 3px; + margin: 1px; + border-radius: 4px; + text-align: center; +} + +#progress_container{ + display:flex; + box-shadow: #888 2px 2px 1px 1px; + width:100%; + padding:0; +} + +#progress_container div{ + transition : width 1s linear; + text-align: center; + padding: 1rem; + color:white; + overflow:none; + white-space: nowrap; +} + +#progress_container #progress_done{ + background:#004f9b; +} + +#progress_container #progress_todo{ + color: #004f9b; + background:#ccc; +} + diff --git a/website/agenda/planung/css/audio_recordings.css b/website/agenda/planung/css/audio_recordings.css deleted file mode 100644 index fd1576d..0000000 --- a/website/agenda/planung/css/audio_recordings.css +++ /dev/null @@ -1,21 +0,0 @@ -img{ - margin-right :1em; - margin-bottom :1em; - vertical-align:middle -} - -#content div.panel{ - padding:1em; -} - -h2 { - line-height:1.5em; -} - -.thin{ - font-weight:100; -} - -th{ - text-align:center; -} diff --git a/website/agenda/planung/css/calendar.css b/website/agenda/planung/css/calendar.css index a3e21d8..995d12c 100644 --- a/website/agenda/planung/css/calendar.css +++ b/website/agenda/planung/css/calendar.css @@ -1,517 +1,660 @@ -body #content{ - padding:0; +body #content { + padding: 0; } -button:hover{ - cursor:pointer; +button:hover { + cursor: pointer; } -@media print{ - #calcms_admin_menu{ - display:none; - } - #toolbar{ - display:none; - } - tr,td,div.event,div.schedule,div.work,div.play{ - border:1pt solid black; - } - #content{ - top:0; - } -} - -#content #calendar_weekdays, -#content #calendar_weekdays table, -#content #calendar{ - position:absolute; - padding:0; - left:0; -} - -#content #calendar_weekdays{ - font-size:12px; -} - -@media screen{ - #content #calendar{ - overflow-x:hidden; - overflow-y:scroll; - } -} - -#calendar_weekdays table, -#calendar table{ - table-layout:fixed; -} - -#calendar_weekdays table td, -#calendar table td{ - vertical-align:top; - padding:0; - min-width:100px; -} - -#calendar_weekdays table td{ - white-space:normal; -} - -#calendar_weekdays table td:nth-child(1), -#calendar table td:nth-child(1){ - min-width:80px !important; -} - -#calendar table td{ - word-wrap:break-word; - hyphens:auto; -} - -#calendar div.text{ - padding-right:0; -} -@media (min-width: 720em) { - #calendar div.text{ - padding-right:16px; +@media print { + #calcms_nav { + display: none; + } + #toolbar { + display: none; + } + tr, + td, + div.event, + div.schedule, + div.work, + div.play { + border: 1pt solid black; + } + #content { + top: 0; } } -#calendar div.event img{ - width:16px; - height:16px; - border:0; - margin:-2px; - padding:0px; +#content #calendar_weekdays, +#content #calendar_weekdays table, +#content #calendar + { + position: absolute; + padding: 0; + left: 0; } -#event_list tr{ - border-bottom:1px solid #999; +#content #calendar_weekdays { + font-size: 12px; } -#calendar div.schedule div.text, -#calendar div.event div.text{ - positions:absolute; - top:0; - left:0; - padding-left:0; - padding-top:0; - padding-bottom:0; +@media screen { + #content #calendar { + overflow-x: hidden; + overflow-y: scroll; + } + + #content #calendar.pin { + overflow-x: initial; + overflow-y: initial; + } + } -#calendar div.event div.icons{ - position:absolute; - top:-5px; - right:-7px; - width:16px; +#calendar_weekdays table, +#calendar table { + table-layout: fixed; +} + +#calendar_weekdays table td, +#calendar table td { + vertical-align: top; + padding: 0; + min-width: 100px; +} + +#calendar_weekdays table td { + white-space: normal; +} + +#calendar_weekdays table td:nth-child(1), +#calendar table td:nth-child(1) + { + min-width: 80px !important; +} + +#calendar table td { + word-wrap: break-word; + hyphens: auto; +} + +#calendar div.text { + padding-right: 0; +} + +@media ( min-width : 720em) { + #calendar div.text { + padding-right: 16px; + } +} + +#event_list tr { + border-bottom: 1px solid #999; +} + +#calendar div.schedule div.text, +#calendar div.event div.text { + top: 0; + left: 0; + padding-left: 0; + padding-top: 0; + padding-bottom: 0; + padding:0.5rem; +} + +#calendar div.event div.icons { + position: absolute; + top: 0px; + right: 0px; + margin: 0; + width: 24px; + font-size: 24px; +} + +#calendar div.icons img{ + margin:-0.3rem; } #calendar div.time.now { - padding:0; - margin:0; - border:2px dashed #99f; - width:100%; - height:0px; - z-index:0; + padding: 0; + margin: 0; + border: 2px dashed #99f; + width: 100%; + height: 0px; + z-index: 0; } -#calendar_weekdays div.date, +#calendar_weekdays div.date, #calendar div.time { - text-align:center; - vertical-align:middle; - z-index:5; + text-align: center; + vertical-align: middle; + z-index: 5; } #calendar_weekdays div.date.today { - background:#ccf; + background: #ccf; } -#calendar div.grid{ - overflow:hidden; - position:absolute; - background:white; +#calendar_weekdays td.week, +#calendar td.week { + padding: 0; + width: 0px; + min-width: 0px; + max-width: 0px; +} + +#calendar_weekdays td.week div, +#calendar td.week div { + padding: 0; + min-width: 1px; + background: #ccc; } -#calendar_weekdays td.week, #calendar td.week{ - padding:0; - width:0px; - min-width:0px; - max-width:0px; + height:100hv; +} +#calendar td.week div { + height:100hv; } -#calendar_weekdays td.week div, -#calendar td.week div{ - padding:0; - min-width:1px; - height:100%; - background:#666; - background-image:url(../image/chess.gif); -} - -#calendar td.week div{ - height:180em; -} - - -#calendar div.time, -#calendar_weekdays div.date, +#calendar div.time, +#calendar_weekdays div.date, #calendar div.event, -#calendar div.schedule, -#calendar div.work, -#calendar div.play{ - overflow:hidden; - font-size:12px; - border-right:0; - position:absolute; - margin-left:0px; - border:0; - border-bottom:1px solid #666; - border-top:1px solid #666; +#calendar div.schedule, +#calendar div.work, +#calendar div.play { + position: absolute; + overflow: hidden; + margin-left: 0; + border: 0; + border-bottom: 1px solid #fff; + border-top: 1px solid #fff; } -#calendar div.time, -#calendar_weekdays div.date{ - border:0; +#calendar div.time, +#calendar_weekdays div.date { + border: 0; } -#calendar div.time, -#calendar_weekdays div.time{ - border-top:1px solid #666; +#calendar div.time, +#calendar_weekdays div.time { + border-top: 1px solid #fff; +} + +#content div.event img { + box-shadow: 1px 1px 1px 1px rgba(0,0,0,0.3); + border-radius:99px; +} + +#content div.event img.icon { + margin-right:8px; + margin-top:-2px; + filter: grayscale(60%); + opacity: 0.8; + vertical-align:middle; + width:14px; + height:14px; +} + +#content div.event div.excerpt { + opacity:0.5; + font-size:small; + padding-bottom:0.5rem; } /* calendar list*/ - - -#content div.event{ - z-index:5; +#content div.event { + z-index: 5; } -#content div.schedule{ - font-weight:normal; - z-index:4; +#content div.schedule { + font-weight: normal; + z-index: 4; } -#content .scheduled{ - color:#000; - font-weight:normal; - z-index:4; +#content .scheduled { + color: #000; + font-weight: normal; + z-index: 4; } -#content div.work{ - font-weight:normal; - z-index:3; +#content div.work { + font-weight: normal; + z-index: 3; } -#content div.play{ - font-weight:normal; - z-index:1; +#content div.play { + font-weight: normal; + z-index: 1; } -#content div.grid{ - z-index:1; - margin-left:0px; - background:white; +#content div.grid { + z-index: 1; + background: white; + overflow: hidden; + position: absolute; + background: repeating-linear-gradient(45deg, #fff, #fff 1rem, #eee 1rem, #eee 2rem); + cursor: pointer; } -#event_list tr th:hover{ - cursor:pointer; +#event_list tr th:hover { + cursor: pointer; } -#event_list tr th, -#event_list tr td, +#event_list tr th, +#event_list tr td, #event_list .tablesorter-header-inner{ - padding:6px; - padding-left:6px; - padding-right:0px; -} -input.tablesorter-filter{ - width:4em; + padding: 6px; + padding-left: 6px; + padding-right: 0px; } -#event_list tr td.day_of_year{ +input.tablesorter-filter { + width: 4em; +} + +#event_list tr td.day_of_year { white-space: nowrap; } -#event_list td:nth-child(1), -#event_list th:nth-child(1), -#event_list td:nth-child(1) .tablesorter-filter{ + +#event_list td:nth-child(1), +#event_list th:nth-child(1), +#event_list td:nth-child(1) .tablesorter-filter +{ white-space: nowrap; - padding:0; - width:3em; - text-align:center; + padding: 0; + width: 3em; + text-align: center; } -#event_list tr td.weekday{ +#event_list tr td.weekday { white-space: nowrap; } -#event_list td:nth-child(2), -#event_list th:nth-child(2), -#event_list td:nth-child(2) .tablesorter-filter{ + +#event_list td:nth-child(2), +#event_list th:nth-child(2), +#event_list td:nth-child(2) .tablesorter-filter +{ white-space: nowrap; - padding:0; - width:2em; - text-align:right; + padding: 0; + width: 2em; + text-align: right; } - -#event_list tr td.start_date{ +#event_list tr td.start_date { white-space: nowrap; - font-family:monospace; -} -#event_list tr .start_date{ - text-align:left; + font-family: monospace; + word-spacing:-0.2rem; } -#event_list tr td.start_time{ +#event_list tr .start_date { + text-align: left; +} + +#event_list tr td.start_time { white-space: nowrap; } -#event_list tr td.series_name{ -} -#event_list tr td.title{ - max-width:20em; -} -#event_list tr td.user_title{ -} -#event_list tr td.episode{ - white-space: nowrap; -} -#event_list td:nth-child(7), -#event_list th:nth-child(7), -#event_list td:nth-child(7) .tablesorter-filter{ - white-space: nowrap; - padding:0; - width:2em; - text-align:right; -} - -#event_list tr td.rerun{ - white-space: nowrap; -} -#event_list tr .rerun{ - width:1em; - text-align:center; -} - -#event_list tr th.draft, -#event_list tr td.draft{ - background:none; -} - -#event_list tr th{ - border-right:1px solid #ccc; -} - -#event_list td:nth-child(9), -#event_list th:nth-child(9), -#event_list td:nth-child(9) .tablesorter-filter{ - white-space: nowrap; - padding:0; - width:1em; - text-align:center; -} - -#event_list td:nth-child(10), -#event_list th:nth-child(10), -#event_list td:nth-child(10) .tablesorter-filter{ - padding:0; - width:1em; - text-align:center; -} - -#event_list tr:hover{ - border-left:1px solid #333; - border-right:1px solid #333; - cursor:pointer; -} - -/* calendar colors */ - -#content div.event.no_series{ - color:#000; -} - -#content.conflicts .schedule.error{ - color:#000; -} - -#content.conflicts .error{ - color:#000; -} - -/* color end*/ - -#content .weak{ - font-weight:300; -} - -#content .schedule, -#content .event{ - cursor:pointer; -} - -#content #calendar_weekdays td:nth-child(1) div.date a{ - font-size:1.7em; -} - -#content #position{ - word-wrap:break-word; - word-break:normal; - text-align:center; -} - -div#toolbar{ - z-index:999; - padding:0; - width:100%; - background:#ddd; - - display: flex; - flex-wrap: wrap; - align-items: center; - vertical-align:middle; - z-index:99; -} - -div#toolbar div{ - display:table-cell; - vertical-align:middle; -} - -div#toolbar select{ - padding:8px; - margin-left:6px; -} - -div#toolbar input.search{ - padding:9px; -} - -#content #toolbar div{ - padding:0; - padding-left:6px; -} - -#content #toolbar div:hover, -#content #toolbar select:hover, -#content #toolbar input:hover{ - background:#ccc; - padding-top:6px; - padding-bottom:6px; -} - -#content #toolbar div#selectDate:hover{ - padding-top:0; - padding-bottom:0; -} - -#content #toolbar div#current_date{ - cursor:pointer; - font-size:1.5em; - width:5em; - text-align:center; - padding:5px; -} - -#content #toolbar div#previous_month, -#content #toolbar div#next_month{ - cursor:pointer; - font-size:1.7em; - padding:6px; -} - -#content #toolbar input#start_date{ - display:none; -} - -#series td{ - padding:6px; -} - -#calendar div { - transition: all 0.1s; - transition-delay: 0s; -} - -#calendar td div.play:hover { - min-height: 180px!important; - min-width: 420px!important; - z-index:99; - box-shadow:0 2px 5px 0 rgba(0,0,0,.12),0 2px 10px 0 rgba(0,0,0,.09); - border-radius:3px; -} - -#calendar td div.play:hover img{ - display:show; -} - -#calendar td div.play img{ - position:absolute; - top:1em; - right:1em; - width:40%; - height:40%; - display:none; -} - -#calendar td div.play img:hover{ - cursor:pointer; -} - -#calendar div.ui-draggable-dragging{ - z-index:99; - cursor:move; -} - -#calendar div.intersect{ - background:#fcc; -} - -#calendar div.event.error, -#calendar div.event.schedule{ -/* width:50%; */ -} - -#calendar div.event.error.x2, -#calendar div.event.schedule.x2{ - /* - margin-left:50%; - */ -} - -div.rms_detail{ - width:100% -} - -div.rms_detail div.image{ - width:100%; - float:right; -} -div.rms_detail div.image img{ +#event_list tr td.series_name { } -div.rms_detail div.text{ - width:100%; - text-align:left; - float:left; - font-size:0.8rem; +#event_list tr td.title { + text-overflow: ellipsis; + overflow: hidden; } -div.event .ok, -div.play .ok{ - display:inline; - background:#4caf50; +#event_list tr td.user_title { + } -div.event .warn, -div.play .warn{ - display:inline; - background:#ffeb3b; +#event_list tr td.episode { + white-space: nowrap; } -div.event .error, -div.play .error{ - display:inline; - background:#f44336; +#event_list td:nth-child(7), +#event_list th:nth-child(7), +#event_list td:nth-child(7) .tablesorter-filter +{ + max-width: 20rem; + white-space: nowrap; + padding: 0; + text-align: right; +} + +#event_list tr td.rerun { + white-space: nowrap; +} + +#event_list tr .rerun { + width: 1em; + text-align: center; +} + +#event_list tr th.draft, +#event_list tr td.draft { + background: none; +} + +#event_list tr th { + border-right: 1px solid #ccc; +} + +#event_list td:nth-child(9), +#event_list th:nth-child(9), +#event_list td:nth-child(9) .tablesorter-filter + { + white-space: nowrap; + padding: 0; + width: 1em; + text-align: center; +} + +#event_list td:nth-child(10), +#event_list th:nth-child(10), +#event_list td:nth-child(10) .tablesorter-filter + { + padding: 0; + width: 1em; + text-align: center; +} + +#event_list tr:hover { + border-left: 1px solid #333; + border-right: 1px solid #333; + cursor: pointer; +} + +/* calendar colors */ +#content div.event.no_series { + color: #000; +} + +#content.conflicts .schedule.error { + color: #000; +} + +#content.conflicts .error { + color: #000; +} + +/* color end*/ +#content .weak { + font-weight: 300; +} + +#content .weak span { + border-radius: 4px; +} + +#content .schedule, +#content .event { + cursor: pointer; +} + +#content #calendar_weekdays td:nth-child(1) div.date a { + font-size: 1.7em; +} + +#content #position { + word-wrap: break-word; + word-break: normal; + text-align: center; +} + +div#toolbar { + z-index: 9; + padding: 0; + width: 100%; + background: #ddd; + display: flex; + flex-wrap: wrap; + align-items: center; + vertical-align: middle; + left: 0; +} + +div#toolbar div { + display: table-cell; + vertical-align: middle; +} + +div#toolbar select { + padding: 8px; + margin-left: 6px; +} + +div#toolbar input.search { + padding: 9px; +} + +#content #toolbar div { + padding: 0; + padding-left: 6px; +} + +#content #toolbar div:hover, +#content #toolbar select:hover, +#content #toolbar input:hover + { + background: #ccc; + padding-top: 6px; + padding-bottom: 6px; +} + +#content #toolbar div#selectDate:hover { + padding-top: 0; + padding-bottom: 0; +} + +#content #toolbar div#current_date { + cursor: pointer; + font-size: 1.5em; + width: 5em; + text-align: center; + padding: 5px; +} + +#content #toolbar div#previous_month, +#content #toolbar div#next_month { + cursor: pointer; + font-size: 1.7em; + padding: 6px; +} + +#content #toolbar input#start_date { + display: none; +} + +#toolbar button.pressed{ + transition: all 0.1s linear; + box-shadow: inset 0px 0px 5px #c1c1c1; + background: #105a91 } +#series td { + padding: 6px; +} + +#calendar div.badge-ok, +#calendar div.badge-warn, +#calendar div.badge-error{ + font-size:small; + font-weight:bold; +} +#calendar td div.play:hover { + min-height: 250px !important; + min-width: 420px !important; + z-index: 99; + box-shadow: 0 2px 5px 0 rgba(0, 0, 0, .12), 0 2px 10px 0 + rgba(0, 0, 0, .09); + border-radius: 3px; + cursor: pointer; +} + +#calendar td div.play:hover img { + display: show; +} + +#calendar td div.play img { + position: absolute; + top: 1em; + right: 1em; + width: 40%; + height: 40%; + display: none; +} + +#calendar div.event:hover { + min-height: 4rem !important; + z-index: 99; + box-shadow: 1px 1px 1px 1px rgba(0,0,0,0.2); + transition: all 0.3s; +} + +#calendar div.intersect { + background: #fcc; +} + +div.rms_detail { + width: 100% +} + +div.rms_detail div.image { + width: 100%; + float: right; +} + +div.rms_detail div.text { + width: 100%; + text-align: left; + float: left; + font-size: 0.8rem; +} + +div.event .ok, +div.play .ok { + display: inline; + background: #4caf50; +} + +div.event .warn, +div.play .warn { + display: inline; + background: #ffeb3b; +} + +div.event .error, +div.play .error { + display: inline; + background: #f44336; +} + +#content div.event, +#content div.schedule, +#content div.grid, +#content div.play, +#content div.error { + padding-left: 0px; + padding-top: 0px; + padding-bottom: 12px; + padding-right: 28px; + border-radius:4px; +} + +#content div.ok, +#content div.warn, +#content div.error { + padding-top: 3px; + padding-bottom: 3px; + margin: 1px; + border-radius: 4px; + text-align: center; +} + +#content tr.event.predecessor{ + #background:#f0cccc; + opacity:0.5; +} +#content tr.event.predecessor:hover{ + #background:#fdcccc +} + +/* switch start, Code Copyright 2018 Materialize. Code released under the MIT license. */ +.switch, .switch * { + -webkit-tap-highlight-color: transparent; + user-select: none; +} +.switch label { + cursor: pointer; +} +.switch label input[type="checkbox"] { + opacity: 0; + width: 0; + height: 0; +} +.switch [type="checkbox"]:not(:checked), .switch [type="checkbox"]:checked { + position: absolute; + opacity: 0; + pointer-events: none; +} +.switch [type="checkbox"], .switch [type="radio"] { + -webkit-box-sizing: border-box; + box-sizing: border-box; + padding: 0; +} +.switch label .lever { + content: ""; + display: inline-block; + position: relative; + width: 36px; + height: 14px; + background-color: rgba(0,0,0,0.38); + border-radius: 15px; + margin-right: 10px; + -webkit-transition: background 0.3s ease; + transition: background 0.3s ease; + vertical-align: middle; + margin: 0 16px; +} +switch label .lever::before { + background-color: rgba(38,166,154,0.15); +} +.switch label .lever::before, .switch label .lever::after { + content: ""; + position: absolute; + display: inline-block; + width: 20px; + height: 20px; + border-radius: 50%; + left: 0; + top: -3px; + -webkit-transition: left 0.3s ease, background .3s ease, -webkit-box-shadow 0.1s ease, -webkit-transform .1s ease; + transition: left 0.3s ease, background .3s ease, -webkit-box-shadow 0.1s ease, -webkit-transform .1s ease; + transition: left 0.3s ease, background .3s ease, box-shadow 0.1s ease, transform .1s ease; + transition: left 0.3s ease, background .3s ease, box-shadow 0.1s ease, transform .1s ease, -webkit-box-shadow 0.1s ease, -webkit-transform .1s ease; +} +.switch label .lever::after { + background-color: #F1F1F1; + -webkit-box-shadow: 0px 3px 1px -2px rgba(0,0,0,0.2),0px 2px 2px 0px rgba(0,0,0,0.14),0px 1px 5px 0px rgba(0,0,0,0.12); + box-shadow: 0px 3px 1px -2px rgba(0,0,0,0.2),0px 2px 2px 0px rgba(0,0,0,0.14),0px 1px 5px 0px rgba(0,0,0,0.12); +} +.switch, .switch * { + -webkit-tap-highlight-color: transparent; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.switch label input[type="checkbox"]:checked + .lever { + background-color: #84c7c1; +} +.switch label input[type="checkbox"]:checked + .lever::before, .switch label input[type="checkbox"]:checked + .lever::after { + left: 18px; +} +.switch label input[type="checkbox"]:checked + .lever::after { + background-color: #26a69a; +} +/* switch end */ diff --git a/website/agenda/planung/css/comment.css b/website/agenda/planung/css/comment.css index d1c91f8..70be210 100644 --- a/website/agenda/planung/css/comment.css +++ b/website/agenda/planung/css/comment.css @@ -1,128 +1,131 @@ -#comments td,th,input { - line-height:100%; - ffont-size:10px; -} -#comments td,th{ - display:table-cell; - font-weight:normal; - padding:6px; +#comments table { + border-collapse: collapse; } -#comments td.level0, td.level1, td.level2, td.level3, td.level4, td.level5{ - border:0; +#comments td, th, input { + line-height: 100%; + ffont-size: 10px; } -#comments td.host{ - color:gray; +#comments td, th { + display: table-cell; + font-weight: normal; + padding: 1rem; } -#comments td.level0{ - padding-left:0px; -} -#comments td.level1{ - padding-left:20px; -} -#comments td.level2{ - padding-left:40px; -} -#comments td.level3{ - padding-left:60px; -} -#comments td.level4{ - padding-left:80px; -} -#comments td.level5{ - padding-left:100px; +#comments td.level0, td.level1, td.level2, td.level3, td.level4, td.level5 { + border: 0; } -#comments img.level0{ - margin-left:0px; -} -#comments img.level1{ - margin-left:20px; -} -#comments img.level2{ - margin-left:40px; -} -#comments img.level3{ - margin-left:60px; -} -#comments img.level4{ - margin-left:80px; -} -#comments img.level5{ - margin-left:100px; +#comments td.host { + color: gray; } -#comments tr{ - vertical-align:middle; +#comments td.level0 { + padding-left: 0px; } -#comments tr.show{ - color:#030; - text-decoration:none; +#comments td.level1 { + padding-left: 20px; } -#content tr.show td{ - padding-top:0px; - padding-bottom:0px; +#comments td.level2 { + padding-left: 40px; } -#comments tr.blocked{ - color:#a33; - text-decoration:break-through; +#comments td.level3 { + padding-left: 60px; } -#comments textarea{ - width:100%; +#comments td.level4 { + padding-left: 80px; } -#comments td.content.unread{ - font-weight:bold; +#comments td.level5 { + padding-left: 100px; } -#comments td.content.received{ - font-weight:normal; +#comments img.level0 { + margin-left: 0px; } - -#comments table.event_comments{ - /*width:800px;*/ +#comments img.level1 { + margin-left: 20px; } -#comments table.event_comments td{ - padding:3px; - background-color:#ccc; +#comments img.level2 { + margin-left: 40px; } -#comments .event th{ - text-align:left; -} -#comments .event td{ - padding:3px; - border-right:1px solid #fff; +#comments img.level3 { + margin-left: 60px; } -#comments .event button{ - text-align:right; +#comments img.level4 { + margin-left: 80px; } -#comments .event_start{ - width:200px; - text-align:center; +#comments img.level5 { + margin-left: 100px; } -#comments .event_title{ - width:400px; +#comments tr { + vertical-align: middle; } -#comments .event_show_comments{ - height:2em; +#comments tr.show { + color: #030; + text-decoration: none; } -#comments .event_excerpt{ +#content tr.show td { + padding-top: 0px; + padding-bottom: 0px; } -#content #comments td.content{ - width:100%; +#comments tr.blocked { + color: #a33; + text-decoration: break-through; +} + +#comments textarea { + width: 100%; +} + +#comments td.content.unread { + font-weight: bold; +} + +#comments td.content.received { + font-weight: normal; +} + +#comments table.event_comments td { + padding: 3px; + background-color: #ccc; +} + +#comments .event th { + text-align: left; +} + +#comments .event button { + text-align: right; +} + +#comments .event_start { + width: 200px; + text-align: center; +} + +#comments .event_title { + width: 400px; +} + +#comments .event_show_comments { + height: 2em; +} + +#content #comments td.content { + width: 100%; } diff --git a/website/agenda/planung/css/comment_manager.css b/website/agenda/planung/css/comment_manager.css deleted file mode 100644 index c630bf3..0000000 --- a/website/agenda/planung/css/comment_manager.css +++ /dev/null @@ -1,125 +0,0 @@ - td,th,input { - line-height:100%; - ffont-size:10px; - } - td,th{ - display:table-cell; - font-weight:normal; - } - - td.level0, td.level1, td.level2, td.level3, td.level4, td.level5{ - opacity:0.8; - border:0; - } - - td.host{ - color:gray; - } - - td.level0{ - padding-left:0px; - } - td.level1{ - padding-left:20px; - } - td.level2{ - padding-left:40px; - } - td.level3{ - padding-left:60px; - } - td.level4{ - padding-left:80px; - } - td.level5{ - padding-left:100px; - } - - img.level0{ - margin-left:0px; - } - img.level1{ - margin-left:20px; - } - img.level2{ - margin-left:40px; - } - img.level3{ - margin-left:60px; - } - img.level4{ - margin-left:80px; - } - img.level5{ - margin-left:100px; - } - - tr{ - vertical-align:middle; - } - - tr.show{ - color:#030; - text-decoration:none; - } - - #content tr.show td{ - padding-top:0px; - padding-bottom:0px; - } - - tr.blocked{ - color:#a33; - text-decoration:break-through; - } - - td.content.unread{ - font-weight:bold; - } - - td.content.received{ - font-weight:normal; - } - - - table.event_comments{ - width:800px; - } - - table.event_comments td{ - padding:3px; - background-color:#ccc; - } - - .event th{ - text-align:left; - opacity:0.8; - } - .event td{ - padding:3px; - border-right:1px solid #fff; - } - - .event button{ - text-align:right; - opacity:0.8; - } - - .event_start{ - width:200px; - text-align:center; - } - - .event_title{ - width:400px; - } - - .event_show_comments{ - height:2em; - } - - .event_excerpt{ - opacity:0.8; - } - - diff --git a/website/agenda/planung/css/default.css b/website/agenda/planung/css/default.css new file mode 100644 index 0000000..59ed096 --- /dev/null +++ b/website/agenda/planung/css/default.css @@ -0,0 +1,743 @@ +/* roboto-regular - latin_latin-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + src: url('../fonts/roboto-v18-latin_latin-ext-regular.eot'); /* IE9 Compat Modes */ + src: local('Roboto'), local('Roboto-Regular'), + url('../fonts/roboto-v18-latin_latin-ext-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ + url('../fonts/roboto-v18-latin_latin-ext-regular.woff2') format('woff2'), /* Super Modern Browsers */ + url('../fonts/roboto-v18-latin_latin-ext-regular.woff') format('woff'), /* Modern Browsers */ + url('../fonts/roboto-v18-latin_latin-ext-regular.ttf') format('truetype'), /* Safari, Android, iOS */ + url('../fonts/roboto-v18-latin_latin-ext-regular.svg#Roboto') format('svg'); /* Legacy iOS */ +} + +/* open-sans-regular - latin_latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: url('../fonts/open-sans-v15-latin_latin-ext-regular.eot'); /* IE9 Compat Modes */ + src: local('Open Sans Regular'), local('OpenSans-Regular'), + url('../fonts/open-sans-v15-latin_latin-ext-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ + url('../fonts/open-sans-v15-latin_latin-ext-regular.woff2') format('woff2'), /* Super Modern Browsers */ + url('../fonts/open-sans-v15-latin_latin-ext-regular.woff') format('woff'), /* Modern Browsers */ + url('../fonts/open-sans-v15-latin_latin-ext-regular.ttf') format('truetype'), /* Safari, Android, iOS */ + url('../fonts/open-sans-v15-latin_latin-ext-regular.svg#OpenSans') format('svg'); /* Legacy iOS */ +} + +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} + +body { + color: #000; + background: #efefef; + height: 100%; + text-align: center; +} + +body #content { + color: #000; + text-align: left; + min-width: 480px; + max-width: 960px; + margin-left: auto; + margin-right: auto; +} + +h1{ + font-size:3rem; +} +h2{ + font-size:2rem; +} + +div { + transition: background-color 0.5s linear; + transition: z-index 2s linear; +} + +#selectImage #content { + max-width: none; +} + +body, +#content input, +#content textarea, +#content td, +#content div, +#content select, +#content option, +#content li, +#content input[type="submit"], +#content input[type="file"], +#content .label { + font-family: Roboto, sans-serif; + font-size: 0.937rem; +} + +#content div.panel-header, +#content button { + font-size: 1rem; + font-family: Roboto, sans-serif; +} + +#content textarea { + padding: 0.5rem; + border: 1px solid #fff; + box-sizing:border-box; +} + +@media handheld { + body { + max-width: 800px; + font-size: 1em; + } + input, button { + padding: 1rem; + } + #calcms_nav { + min-width: 640px; + max-width: 800px; + } +} + +#calcms_nav { + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: center; + z-index: 99; +} + +#calcms_nav, +#calcms_nav a, +#calcms_nav div, +#calcms_nav input, +#calcms_nav select, +#calcms_nav option { + color: #fff; +} + +#calcms_nav, +#calcms_nav select { + background-color: #004f9b; +} + +#calcms_nav a:hover, +#calcms_nav select:hover { + background-color: #007acc; + transition: all 0.5s linear; + box-shadow: 0 5px 11px 0 rgba(0, 0, 0, .18), 0 4px 15px 0 + rgba(0, 0, 0, .15); +} + +#calcms_nav div a, +#calcms_nav select { + padding-left: 0.5rem; + padding-right: 0.5rem; + line-height: 3em; +} + +#calcms_nav div { + transition: background 0.2s; +} + +#calcms_nav select, +#calcms_nav option { + max-width: 8em; + border: 0; + padding-left: 0; + padding-right: 0; + border-left: 1px solid #666; +} + +#calcms_nav a#logout { + color: #ff4444; +} + +#calcms_nav { + position: fixed; + top: 0; + left: 0; + right: 0; +} + +#calcms_nav div a, +#calcms_nav select, +#calcms_nav option { + font-size: 0.9375rem; +} + +#calcms_nav select, +#calcms_nav option { + border: 0; + text-align: left; + border: none; +} + +select#studio_id, +select#project_id { + padding:0.8rem; + padding-left:24px; + background-repeat:no-repeat; + background-position:6px center; +} + +select#studio_id { + background-image:url(../image/antenna.svg); +} +select#project_id { + background-image:url(../image/home.svg); +} + + +select#studio_id::after, +select#project_id::after { + content : "url(../image/arrow-down.svg)" +} + +#calcms_nav #bars { + cursor: pointer; +} + +#calcms_nav.mobile { + flex-direction: column; + position: absolute; +} + +#calcms_nav.mobile div { + text-align: left; +} + +#calcms_nav .dropdown { + position: relative; + display: inline-block; +} + +#calcms_nav .dropdown-content { + display: none; + position: absolute; + z-index: 100; + text-align: left; + vertical-align:middle; + background: #004f9b; + min-width: 10rem; +} + +#calcms_nav .dropdown-content a { + min-width: 10rem; + display: inline-block; +} + +#calcms_nav > div > a { + display: flex; +} + +#calcms_nav > div { +} + +nav img { + vertical-align: text-bottom; + display: inline-block; +} + +#calcms_nav .dropdown:hover .dropdown-content { + display: block; + transition: all 1s linear; +} + +a { + color: #000; + text-decoration: none; +} + +#content table { + border-collapse: collapse; + width: 100% +} + +#content table.data tr { + border-bottom: 1px solid rgba(0, 0, 0, 0.12); +} + +#content table td { + padding: 0.5rem; + border-collapse: collapse; + border-right: 0; + border-left: 0; +} + +#content table th { + padding: 0.5rem; + border-collapse: collapse; +} + +#info { + color: #000; + background: #fff; +} + +#content .panel { + background:white; + margin: 1rem; + padding: 1rem; + + border: 1px solid rgba(0, 0, 0, .03); + border-radius:0.5rem; + position: relative; +} + +#content .panel, +#content div.card { + box-shadow: 0 1px 3px rgba(0,0,0,0.16), 0 1px 3px rgba(0,0,0,0.23); + transition: all 0.3s cubic-bezier(.25,.8,.25,1); +} + +#content .panel:hover, +#content div.card:hover { + box-shadow: 0 14px 28px rgba(0,0,0,0.25), 0 10px 10px rgba(0,0,0,0.22); +} + +#content div.panel-header { + font-weight:bold; + clear: both; + text-align: left; + align-content: center; + align-items: center; + display: flex; + justify-content: center; + padding: 0.5rem; +} + +#content .field { + width: 30em; +} + +*:focus { + outline: none; +} + +#content a { + color: #000; + font-weight: normal; +} + +#content a:hover { + text-decoration: underline; +} + +#content div, +td, +tr, +table { + vertical-align: middle; +} + +#content td { + padding: 0.5rem; +} + +#content pre, +.pre { + border: 0; + padding-top:1rem; + padding-bottom:1rem; + color: #000; +} + +.error.head { + position: relative; + top: 3em; + padding:0; +} + +#jobs th { + text-align: left; +} + +#jobs td.status.finished a { + color: #000; +} + +#jobs td.status.ongoing a { + text-decoration: blink; + color: green; +} + +#jobs td.status.scheduled a { + color: green; +} + +#content ul.error{ + padding:0; +} + +#content div.ok, +#content div.warn, +#content div.error { + font-weight: bold; + margin: 0; + padding: 1rem; +} + +#content span.ok, +#content span.warn, +#content span.error { + font-weight: bold; + padding: 0; +} + +#content span.ok, +#content span.error { + color: white; +} + +div.ok { + color: white; + background: #0c0; +} + +div.warn { + background: #ff0; +} + +div.error { + color: white; + background: #d00; +} + +/* badges */ +div.badge-ok, +div.badge-warn, +div.badge-error { + border-radius: 0.3rem; + display: inline; + margin-right: 0.5rem; + margin-top: 0.5rem; + padding: 0.2rem; + line-height:1.6rem; + white-space: nowrap; +} + +div.badge-ok { + color: white; + background: #0c0; +} + +div.badge-warn { + background: #ff0; +} + +div.badge-error { + color: white; + background: #d00; +} + +#content button, +#content select, +#content input { + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} + +#content div.flex { + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: center; +} + +#content div.card { + border: 0; + margin: 1em; + border-radius: 0.5rem; +} + +#content table.table tr:hover { + background: #ebebeb +} + +#content div.card tr { + border-bottom: none; +} + +#content div.card tr:hover { + background: none; +} + +/* overwrite tablesorter */ +tr.tablesorter-filter-row { + background: #ccc; +} + +tr.tablesorter-filter-row input { + height: 1rem; + color: #000; +} + +table.table tr, +table.tablesorter tr { + border-bottom: solid 1px #ebebeb; +} + +#content table.tablesorter td, +#content table.table td { + padding: 0.3rem; + text-align: left; + vertical-align: middle; +} + +/*colors*/ +#content input[type="submit"], +#content input[type="file"], +#content button{ + background-color: #2196f3; + cursor: pointer; +} + +#content input[type="submit"]:hover, +#content input[type="file"]:hover, +#content button:hover{ + background-color: #1678c2; +} + +#content button.text, +#content #dialog button.dialog-cancel{ + color:#2196f3; + background:none; + box-shadow:none; + transition: all 0.1s linear; +} +#content button.text:hover{ + color:#1678c2; + background:none; + box-shadow:none; + transition: all 0.1s linear; +} + +#content .button { + cursor: pointer; +} + +/*colors end */ +#content input[type="submit"], +#content input[type="file"], +#content button{ + display: inline-block; + border: 0; + padding-left: 0.4rem; + padding-right: 0.4rem; + margin: 0.3rem; + text-align: center; + text-decoration: none; + min-width: 5rem; + border-radius: 1rem; + color: #fff; + height: 2.3rem; + position: relative; + transition: background-color .3s cubic-bezier(.05, .05, .05, 1), + box-shadow .3s cubic-bezier(.05, .05, .05, 1); +} + +#content button.primary { + border: 1px solid #167ec2; + box-shadow: 0 5px 11px 0 rgba(0, 0, 0, .18), + 0 4px 15px 0 rgba(0, 0, 0, .15); +} + +#content input[type="submit"]:hover, +#content input[type="file"]:hover, +#content button:focus { + outline: 0; + transition: background 0.5s cubic-bezier(.64, .09, .08, 1) +} + +#content input[type="submit"]:hover, +#content input[type="file"]:hover, +#content button:hover { + box-shadow: 0 5px 11px 0 rgba(0, 0, 0, .18), 0 4px 15px 0 + rgba(0, 0, 0, .15); +} + +#content input { + border: none; + border-bottom: 1px solid #ccc; + color: #000; + background: #fefefe; + box-sizing:border-box; +} + +#content input.error { + border-bottom: 2px solid #d30000; +} + +#content input:hover, +#content input:focus { + border-bottom: 1px solid #03a9f4; +} + +#content textarea { + font-weight: normal; + border-bottom:1px solid #ccc; +} + +#content textarea:hover, +#content textarea:focus { + border-bottom: 1px solid #03a9f4; + background:#fff; +} + +#content select { + color: #000; + background:#fff; + padding-left: 0; + padding-right: 0; + border: none; + border-bottom: solid 1px #03a9f4; + cursor: pointer; +} + +#content select, +input[type='checkbox'] { + margin-top: 0px; +} + +#content div.formField div.label { + display: hide; + padding-left: 1em; + color: #999; +} + +#content div.formField input { + clear: both; +} + +#content button.selectImage { + padding: 0 !important; + float: left; + min-width: 32px; +} + +#content img{ + border-radius: 0.3rem; +} + +#content button.selectImage, +#content button.selectImage img { + width: 32px; + height: 32px; +} + +input.image { + width: 28ch; +} + +#content .select .option { + font-size: 1rem; + line-height: 2rem; +} + +#content #imageList div.images { + max-height: 650px; + overflow-y: scroll +} + +div#tabs > div { + background:white; +} + +ul.tabContainer{ + background:none; + display:block; +} +ul.tabContainer li.active{ + background:#1678c2; +} +ul.tabContainer li:hover{ + border-bottom-color:#1678c2; +} +#content ul.tabContainer li a:hover{ + text-decoration:none; +} + +#content ul.tabContainer li.active a{ + color:#fff; +} +#content ul.tabContainer li.active a:hover{ + color:#fff; +} +ul.tabContainer li{ + background:white; + display:inline-block; + padding:1rem; + cursor:pointer; + border: 1px solid rgba(0, 0, 0, .03); + box-shadow: 0 2px 2px rgba(0, 0, 0, .24), + 0 0 2px rgba(0, 0, 0, .12); + margin-left:-3px; + margin-bottom:-2px; +} +ul.tabContainer li:first-child{ + border-top-left-radius:0.5rem; + margin-left:4px; +} +ul.tabContainer li:last-child{ + border-top-right-radius:0.5rem; +} + +#content .editor input.datetimepicker{ + padding-left:0; + padding-right:0; +} + +#content #dialog{ + position:absolute; + z-index:1000; + left: 0; + right: 0; + top: 0; + bottom: 0; + margin-left: auto; + margin-right: auto; + margin-top: auto; + margin-bottom: auto; + width: 15rem; + height: 4rem; + text-align:center; + vertical-align:middle; + display:inline; +} + +.right{ + margin-left:auto; +} + +#content .right, +.right{ + margin-left:auto; +} + +#content .bottom, +.bottom{ + margin-bottom:auto; +} + diff --git a/website/agenda/planung/css/diff.css b/website/agenda/planung/css/diff.css index c242db6..c4c1a8c 100644 --- a/website/agenda/planung/css/diff.css +++ b/website/agenda/planung/css/diff.css @@ -1,49 +1,48 @@ table.diff { - border-collapse: collapse; - border-top: solid 1px #999999; - border-left: solid 1px #999999; + border-collapse: collapse; + border-top: solid 1px #999999; + border-left: solid 1px #999999; } table.diff td { - padding: 2px; - padding-left: 5px; - padding-right: 5px; - border-right: solid 1px #999999; - border-bottom: solid 1px #999999; + padding: 2px; + padding-left: 5px; + padding-right: 5px; + border-right: solid 1px #999999; + border-bottom: solid 1px #999999; } -table.diff td:nth-child(1), +table.diff td:nth-child(1), table.diff td:nth-child(2) { - background-color: #deedff; + background-color: #deedff; } -table.diff tr.change, -table.diff tr.disc_a, +table.diff tr.change, +table.diff tr.disc_a, table.diff tr.disc_b { - background-color: #ffffdd; + background-color: #ffffdd; } table.diff tr.del { - background-color: #ffeeee; + background-color: #ffeeee; } table.diff tr.ins { - background-color: #eeffee; + background-color: #eeffee; } table.diff td ins { - padding: 2px; - color: #009900; - background-color: #ccffcc; - text-decoration: none; - font-weight: bold; + padding: 2px; + color: #009900; + background-color: #ccffcc; + text-decoration: none; + font-weight: bold; } table.diff td del { - padding: 2px; - color: #990000; - background-color: #ffcccc; - text-decoration: none; - font-weight: bold; -} - + padding: 2px; + color: #990000; + background-color: #ffcccc; + text-decoration: none; + font-weight: bold; +} \ No newline at end of file diff --git a/website/agenda/planung/css/event.css b/website/agenda/planung/css/event.css index 3fc4c5f..1d0118c 100644 --- a/website/agenda/planung/css/event.css +++ b/website/agenda/planung/css/event.css @@ -1,66 +1,75 @@ -pre{ - white-space:pre-wrap; +pre { + white-space: pre-wrap; } #content div.editor div p a img { - float:right; + float: right; } -#content div.editor td{ - width:800px; - padding-left:0; +#content div.editor td { + width: 100%; } -#content div.editor td.label{ - width:11em; +#content div.editor td.label { + width:6rem; + color:#666; } -#content div.editor input.image{ - width:90%; +#content div.editor span.label { + width: 6rem; + color:#666; } -#content .editor img{ - padding:0; - margin:0; - border:none; - width:24px; - height:24px; +#content .editor img { + padding: 0; + margin: 0; + border: none; + width: 24px; + height: 24px; } - -#content .edit_event input, -#content .edit_event select, -#content .edit_event textarea{ - padding:0.5em; +#content .edit_event input, +#content .edit_event select, +#content .edit_event textarea { + padding: 0.5em; } -#content .excerpt{ - width:100%; - height:3em; +#content .excerpt { + width: 100%; + height: 3rem; } -#content textarea{ - width:100%; +#content textarea { + width: 100%; } -#content .edit_event input.url{ - width:100%; +#content .edit_event input.url { + width: 100%; } -#content .panel{ - margin:1em; - border:1px solid #ccc; +.date { + width: 9rem; } -.date{ - width:10em; +.time { + width: 5rem; } -.time{ - width:6em; +.episode { + width: 3rem; } -.episode{ - width:3em; +div#edit_new form, +div#edit_new table{ + width:480px; +} + +#content table.edit_event{ + background:white; +} + +#content table.edit_event td{ + padding-left:1rem; + padding-right:1rem; } diff --git a/website/agenda/planung/css/fileUploader.css b/website/agenda/planung/css/fileUploader.css deleted file mode 100644 index d29ee1e..0000000 --- a/website/agenda/planung/css/fileUploader.css +++ /dev/null @@ -1,46 +0,0 @@ -#px_display { - padding-top: 10px; - padding-bottom: 10px; -} -.uploadData { - padding: 5px; - width: 420px; - margin-top: 5px; - margin-bottom: 5px; - background-color: #F0F8FF; - border: 1px solid #B0D8FF; - position: relative; -} -.uploadData .fname { - padding-right: 10px; - width: 120px; -} -.uploadData .loader { - width: 140px; - text-align: center; - border-bottom-width: 1px; - border-bottom-style: dotted; - border-bottom-color: #999999; -} -.uploadData .result { - display: block; - float: left; - width: 130px; - padding-left: 10px; -} -.uploadData .close { - background-image: url(close.gif); - height: 16px; - width: 16px; - position: absolute; - top: 5px; - right: 5px; - cursor: pointer; -} -.uploadData .close:hover { - background-position: 16px 0px; -} -#px_button input{ - margin-right: 6px; - padding: 5px; -} diff --git a/website/agenda/planung/css/flatpickr.min.css b/website/agenda/planung/css/flatpickr.min.css new file mode 100644 index 0000000..2b5da59 --- /dev/null +++ b/website/agenda/planung/css/flatpickr.min.css @@ -0,0 +1,13 @@ +.flatpickr-calendar{background:transparent;opacity:0;display:none;text-align:center;visibility:hidden;padding:0;-webkit-animation:none;animation:none;direction:ltr;border:0;font-size:14px;line-height:24px;border-radius:5px;position:absolute;width:307.875px;-webkit-box-sizing:border-box;box-sizing:border-box;-ms-touch-action:manipulation;touch-action:manipulation;background:#fff;-webkit-box-shadow:1px 0 0 #e6e6e6,-1px 0 0 #e6e6e6,0 1px 0 #e6e6e6,0 -1px 0 #e6e6e6,0 3px 13px rgba(0,0,0,0.08);box-shadow:1px 0 0 #e6e6e6,-1px 0 0 #e6e6e6,0 1px 0 #e6e6e6,0 -1px 0 #e6e6e6,0 3px 13px rgba(0,0,0,0.08)}.flatpickr-calendar.open,.flatpickr-calendar.inline{opacity:1;max-height:640px;visibility:visible}.flatpickr-calendar.open{display:inline-block;z-index:99999}.flatpickr-calendar.animate.open{-webkit-animation:fpFadeInDown 300ms cubic-bezier(.23,1,.32,1);animation:fpFadeInDown 300ms cubic-bezier(.23,1,.32,1)}.flatpickr-calendar.inline{display:block;position:relative;top:2px}.flatpickr-calendar.static{position:absolute;top:calc(100% + 2px)}.flatpickr-calendar.static.open{z-index:999;display:block}.flatpickr-calendar.multiMonth .flatpickr-days .dayContainer:nth-child(n+1) .flatpickr-day.inRange:nth-child(7n+7){-webkit-box-shadow:none !important;box-shadow:none !important}.flatpickr-calendar.multiMonth .flatpickr-days .dayContainer:nth-child(n+2) .flatpickr-day.inRange:nth-child(7n+1){-webkit-box-shadow:-2px 0 0 #e6e6e6,5px 0 0 #e6e6e6;box-shadow:-2px 0 0 #e6e6e6,5px 0 0 #e6e6e6}.flatpickr-calendar .hasWeeks .dayContainer,.flatpickr-calendar .hasTime .dayContainer{border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.flatpickr-calendar .hasWeeks .dayContainer{border-left:0}.flatpickr-calendar.hasTime .flatpickr-time{height:40px;border-top:1px solid #e6e6e6}.flatpickr-calendar.noCalendar.hasTime .flatpickr-time{height:auto}.flatpickr-calendar:before,.flatpickr-calendar:after{position:absolute;display:block;pointer-events:none;border:solid transparent;content:'';height:0;width:0;left:22px}.flatpickr-calendar.rightMost:before,.flatpickr-calendar.arrowRight:before,.flatpickr-calendar.rightMost:after,.flatpickr-calendar.arrowRight:after{left:auto;right:22px}.flatpickr-calendar.arrowCenter:before,.flatpickr-calendar.arrowCenter:after{left:50%;right:50%}.flatpickr-calendar:before{border-width:5px;margin:0 -5px}.flatpickr-calendar:after{border-width:4px;margin:0 -4px}.flatpickr-calendar.arrowTop:before,.flatpickr-calendar.arrowTop:after{bottom:100%}.flatpickr-calendar.arrowTop:before{border-bottom-color:#e6e6e6}.flatpickr-calendar.arrowTop:after{border-bottom-color:#fff}.flatpickr-calendar.arrowBottom:before,.flatpickr-calendar.arrowBottom:after{top:100%}.flatpickr-calendar.arrowBottom:before{border-top-color:#e6e6e6}.flatpickr-calendar.arrowBottom:after{border-top-color:#fff}.flatpickr-calendar:focus{outline:0}.flatpickr-wrapper{position:relative;display:inline-block}.flatpickr-months{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.flatpickr-months .flatpickr-month{background:transparent;color:rgba(0,0,0,0.9);fill:rgba(0,0,0,0.9);height:34px;line-height:1;text-align:center;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;overflow:hidden;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.flatpickr-months .flatpickr-prev-month,.flatpickr-months .flatpickr-next-month{text-decoration:none;cursor:pointer;position:absolute;top:0;height:34px;padding:10px;z-index:3;color:rgba(0,0,0,0.9);fill:rgba(0,0,0,0.9)}.flatpickr-months .flatpickr-prev-month.flatpickr-disabled,.flatpickr-months .flatpickr-next-month.flatpickr-disabled{display:none}.flatpickr-months .flatpickr-prev-month i,.flatpickr-months .flatpickr-next-month i{position:relative}.flatpickr-months .flatpickr-prev-month.flatpickr-prev-month,.flatpickr-months .flatpickr-next-month.flatpickr-prev-month{/* + /*rtl:begin:ignore*/left:0/* + /*rtl:end:ignore*/}/* + /*rtl:begin:ignore*/ +/* + /*rtl:end:ignore*/ +.flatpickr-months .flatpickr-prev-month.flatpickr-next-month,.flatpickr-months .flatpickr-next-month.flatpickr-next-month{/* + /*rtl:begin:ignore*/right:0/* + /*rtl:end:ignore*/}/* + /*rtl:begin:ignore*/ +/* + /*rtl:end:ignore*/ +.flatpickr-months .flatpickr-prev-month:hover,.flatpickr-months .flatpickr-next-month:hover{color:#959ea9}.flatpickr-months .flatpickr-prev-month:hover svg,.flatpickr-months .flatpickr-next-month:hover svg{fill:#f64747}.flatpickr-months .flatpickr-prev-month svg,.flatpickr-months .flatpickr-next-month svg{width:14px;height:14px}.flatpickr-months .flatpickr-prev-month svg path,.flatpickr-months .flatpickr-next-month svg path{-webkit-transition:fill .1s;transition:fill .1s;fill:inherit}.numInputWrapper{position:relative;height:auto}.numInputWrapper input,.numInputWrapper span{display:inline-block}.numInputWrapper input{width:100%}.numInputWrapper input::-ms-clear{display:none}.numInputWrapper input::-webkit-outer-spin-button,.numInputWrapper input::-webkit-inner-spin-button{margin:0;-webkit-appearance:none}.numInputWrapper span{position:absolute;right:0;width:14px;padding:0 4px 0 2px;height:50%;line-height:50%;opacity:0;cursor:pointer;border:1px solid rgba(57,57,57,0.15);-webkit-box-sizing:border-box;box-sizing:border-box}.numInputWrapper span:hover{background:rgba(0,0,0,0.1)}.numInputWrapper span:active{background:rgba(0,0,0,0.2)}.numInputWrapper span:after{display:block;content:"";position:absolute}.numInputWrapper span.arrowUp{top:0;border-bottom:0}.numInputWrapper span.arrowUp:after{border-left:4px solid transparent;border-right:4px solid transparent;border-bottom:4px solid rgba(57,57,57,0.6);top:26%}.numInputWrapper span.arrowDown{top:50%}.numInputWrapper span.arrowDown:after{border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid rgba(57,57,57,0.6);top:40%}.numInputWrapper span svg{width:inherit;height:auto}.numInputWrapper span svg path{fill:rgba(0,0,0,0.5)}.numInputWrapper:hover{background:rgba(0,0,0,0.05)}.numInputWrapper:hover span{opacity:1}.flatpickr-current-month{font-size:135%;line-height:inherit;font-weight:300;color:inherit;position:absolute;width:75%;left:12.5%;padding:7.48px 0 0 0;line-height:1;height:34px;display:inline-block;text-align:center;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.flatpickr-current-month span.cur-month{font-family:inherit;font-weight:700;color:inherit;display:inline-block;margin-left:.5ch;padding:0}.flatpickr-current-month span.cur-month:hover{background:rgba(0,0,0,0.05)}.flatpickr-current-month .numInputWrapper{width:6ch;width:7ch\0;display:inline-block}.flatpickr-current-month .numInputWrapper span.arrowUp:after{border-bottom-color:rgba(0,0,0,0.9)}.flatpickr-current-month .numInputWrapper span.arrowDown:after{border-top-color:rgba(0,0,0,0.9)}.flatpickr-current-month input.cur-year{background:transparent;-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;cursor:text;padding:0 0 0 .5ch;margin:0;display:inline-block;font-size:inherit;font-family:inherit;font-weight:300;line-height:inherit;height:auto;border:0;border-radius:0;vertical-align:initial;-webkit-appearance:textfield;-moz-appearance:textfield;appearance:textfield}.flatpickr-current-month input.cur-year:focus{outline:0}.flatpickr-current-month input.cur-year[disabled],.flatpickr-current-month input.cur-year[disabled]:hover{font-size:100%;color:rgba(0,0,0,0.5);background:transparent;pointer-events:none}.flatpickr-current-month .flatpickr-monthDropdown-months{appearance:menulist;background:transparent;border:none;border-radius:0;box-sizing:border-box;color:inherit;cursor:pointer;font-size:inherit;font-family:inherit;font-weight:300;height:auto;line-height:inherit;margin:-1px 0 0 0;outline:none;padding:0 0 0 .5ch;position:relative;vertical-align:initial;-webkit-box-sizing:border-box;-webkit-appearance:menulist;-moz-appearance:menulist;width:auto}.flatpickr-current-month .flatpickr-monthDropdown-months:focus,.flatpickr-current-month .flatpickr-monthDropdown-months:active{outline:none}.flatpickr-current-month .flatpickr-monthDropdown-months:hover{background:rgba(0,0,0,0.05)}.flatpickr-current-month .flatpickr-monthDropdown-months .flatpickr-monthDropdown-month{background-color:transparent;outline:none;padding:0}.flatpickr-weekdays{background:transparent;text-align:center;overflow:hidden;width:100%;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;height:28px}.flatpickr-weekdays .flatpickr-weekdaycontainer{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}span.flatpickr-weekday{cursor:default;font-size:90%;background:transparent;color:rgba(0,0,0,0.54);line-height:1;margin:0;text-align:center;display:block;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;font-weight:bolder}.dayContainer,.flatpickr-weeks{padding:1px 0 0 0}.flatpickr-days{position:relative;overflow:hidden;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start;width:307.875px}.flatpickr-days:focus{outline:0}.dayContainer{padding:0;outline:0;text-align:left;width:307.875px;min-width:307.875px;max-width:307.875px;-webkit-box-sizing:border-box;box-sizing:border-box;display:inline-block;display:-ms-flexbox;display:-webkit-box;display:-webkit-flex;display:flex;-webkit-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-wrap:wrap;-ms-flex-pack:justify;-webkit-justify-content:space-around;justify-content:space-around;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}.dayContainer + .dayContainer{-webkit-box-shadow:-1px 0 0 #e6e6e6;box-shadow:-1px 0 0 #e6e6e6}.flatpickr-day{background:none;border:1px solid transparent;border-radius:150px;-webkit-box-sizing:border-box;box-sizing:border-box;color:#393939;cursor:pointer;font-weight:400;width:14.2857143%;-webkit-flex-basis:14.2857143%;-ms-flex-preferred-size:14.2857143%;flex-basis:14.2857143%;max-width:39px;height:39px;line-height:39px;margin:0;display:inline-block;position:relative;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;text-align:center}.flatpickr-day.inRange,.flatpickr-day.prevMonthDay.inRange,.flatpickr-day.nextMonthDay.inRange,.flatpickr-day.today.inRange,.flatpickr-day.prevMonthDay.today.inRange,.flatpickr-day.nextMonthDay.today.inRange,.flatpickr-day:hover,.flatpickr-day.prevMonthDay:hover,.flatpickr-day.nextMonthDay:hover,.flatpickr-day:focus,.flatpickr-day.prevMonthDay:focus,.flatpickr-day.nextMonthDay:focus{cursor:pointer;outline:0;background:#e6e6e6;border-color:#e6e6e6}.flatpickr-day.today{border-color:#959ea9}.flatpickr-day.today:hover,.flatpickr-day.today:focus{border-color:#959ea9;background:#959ea9;color:#fff}.flatpickr-day.selected,.flatpickr-day.startRange,.flatpickr-day.endRange,.flatpickr-day.selected.inRange,.flatpickr-day.startRange.inRange,.flatpickr-day.endRange.inRange,.flatpickr-day.selected:focus,.flatpickr-day.startRange:focus,.flatpickr-day.endRange:focus,.flatpickr-day.selected:hover,.flatpickr-day.startRange:hover,.flatpickr-day.endRange:hover,.flatpickr-day.selected.prevMonthDay,.flatpickr-day.startRange.prevMonthDay,.flatpickr-day.endRange.prevMonthDay,.flatpickr-day.selected.nextMonthDay,.flatpickr-day.startRange.nextMonthDay,.flatpickr-day.endRange.nextMonthDay{background:#569ff7;-webkit-box-shadow:none;box-shadow:none;color:#fff;border-color:#569ff7}.flatpickr-day.selected.startRange,.flatpickr-day.startRange.startRange,.flatpickr-day.endRange.startRange{border-radius:50px 0 0 50px}.flatpickr-day.selected.endRange,.flatpickr-day.startRange.endRange,.flatpickr-day.endRange.endRange{border-radius:0 50px 50px 0}.flatpickr-day.selected.startRange + .endRange:not(:nth-child(7n+1)),.flatpickr-day.startRange.startRange + .endRange:not(:nth-child(7n+1)),.flatpickr-day.endRange.startRange + .endRange:not(:nth-child(7n+1)){-webkit-box-shadow:-10px 0 0 #569ff7;box-shadow:-10px 0 0 #569ff7}.flatpickr-day.selected.startRange.endRange,.flatpickr-day.startRange.startRange.endRange,.flatpickr-day.endRange.startRange.endRange{border-radius:50px}.flatpickr-day.inRange{border-radius:0;-webkit-box-shadow:-5px 0 0 #e6e6e6,5px 0 0 #e6e6e6;box-shadow:-5px 0 0 #e6e6e6,5px 0 0 #e6e6e6}.flatpickr-day.flatpickr-disabled,.flatpickr-day.flatpickr-disabled:hover,.flatpickr-day.prevMonthDay,.flatpickr-day.nextMonthDay,.flatpickr-day.notAllowed,.flatpickr-day.notAllowed.prevMonthDay,.flatpickr-day.notAllowed.nextMonthDay{color:rgba(57,57,57,0.3);background:transparent;border-color:transparent;cursor:default}.flatpickr-day.flatpickr-disabled,.flatpickr-day.flatpickr-disabled:hover{cursor:not-allowed;color:rgba(57,57,57,0.1)}.flatpickr-day.week.selected{border-radius:0;-webkit-box-shadow:-5px 0 0 #569ff7,5px 0 0 #569ff7;box-shadow:-5px 0 0 #569ff7,5px 0 0 #569ff7}.flatpickr-day.hidden{visibility:hidden}.rangeMode .flatpickr-day{margin-top:1px}.flatpickr-weekwrapper{float:left}.flatpickr-weekwrapper .flatpickr-weeks{padding:0 12px;-webkit-box-shadow:1px 0 0 #e6e6e6;box-shadow:1px 0 0 #e6e6e6}.flatpickr-weekwrapper .flatpickr-weekday{float:none;width:100%;line-height:28px}.flatpickr-weekwrapper span.flatpickr-day,.flatpickr-weekwrapper span.flatpickr-day:hover{display:block;width:100%;max-width:none;color:rgba(57,57,57,0.3);background:transparent;cursor:default;border:none}.flatpickr-innerContainer{display:block;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden}.flatpickr-rContainer{display:inline-block;padding:0;-webkit-box-sizing:border-box;box-sizing:border-box}.flatpickr-time{text-align:center;outline:0;display:block;height:0;line-height:40px;max-height:40px;-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.flatpickr-time:after{content:"";display:table;clear:both}.flatpickr-time .numInputWrapper{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;width:40%;height:40px;float:left}.flatpickr-time .numInputWrapper span.arrowUp:after{border-bottom-color:#393939}.flatpickr-time .numInputWrapper span.arrowDown:after{border-top-color:#393939}.flatpickr-time.hasSeconds .numInputWrapper{width:26%}.flatpickr-time.time24hr .numInputWrapper{width:49%}.flatpickr-time input{background:transparent;-webkit-box-shadow:none;box-shadow:none;border:0;border-radius:0;text-align:center;margin:0;padding:0;height:inherit;line-height:inherit;color:#393939;font-size:14px;position:relative;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-appearance:textfield;-moz-appearance:textfield;appearance:textfield}.flatpickr-time input.flatpickr-hour{font-weight:bold}.flatpickr-time input.flatpickr-minute,.flatpickr-time input.flatpickr-second{font-weight:400}.flatpickr-time input:focus{outline:0;border:0}.flatpickr-time .flatpickr-time-separator,.flatpickr-time .flatpickr-am-pm{height:inherit;float:left;line-height:inherit;color:#393939;font-weight:bold;width:2%;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-align-self:center;-ms-flex-item-align:center;align-self:center}.flatpickr-time .flatpickr-am-pm{outline:0;width:18%;cursor:pointer;text-align:center;font-weight:400}.flatpickr-time input:hover,.flatpickr-time .flatpickr-am-pm:hover,.flatpickr-time input:focus,.flatpickr-time .flatpickr-am-pm:focus{background:#eee}.flatpickr-input[readonly]{cursor:pointer}@-webkit-keyframes fpFadeInDown{from{opacity:0;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}to{opacity:1;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes fpFadeInDown{from{opacity:0;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}to{opacity:1;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}} \ No newline at end of file diff --git a/website/agenda/planung/css/image.css b/website/agenda/planung/css/image.css new file mode 100644 index 0000000..7ddbb31 --- /dev/null +++ b/website/agenda/planung/css/image.css @@ -0,0 +1,77 @@ +input.field{ + width:30em; +} + +#content div.image{ + display:inline-block; + vertical-alignment:top; + border:1px solid gray; + margin:6px; + padding:0; + text-align:left; + background-repeat:no-repeat; + width:150px; + height:150px; + vertical-align:bottom; +} + +#content .close{ + text-align:right; + padding:0; + margin:0; + color:white; + float:right; +} + +#content div.image:hover{ + cursor:pointer; + background-color:#39a1f4; + font-weight:bold; + opacity:0.9; + filter:contrast(120%); + box-shadow: 0 5px 11px 0 rgba(0,0,0,.18),0 4px 15px 0 rgba(0,0,0,.15); +} + +#content div.image .label{ + text-align:center; + background-color:#333; + color:#fff; + vertical-align:bottom; + opacity:0.9; + padding:6px; + width:138px; + margin:0; +} + +#content div.image.active .label{ + background-color:#39a1f4; + font-weight:bold; +} + +#content div.image.active{ + border:1px solid #39a1f4; + box-shadow: 0 5px 11px 0 rgba(0,0,0,.18),0 4px 15px 0 rgba(0,0,0,.15); +} + +#content div.image.inactive{ + opacity:0.5; +} + +#imageEditor{ + min-height:800px; + height:100%; +} + +#content #imageEditor input, +#content #imageEditor select, +#content #imageEditor textarea{ + margin-left:0; + margin-bottom:1rem; + padding:1rem; +} + +#content label{ + margin-top: 1rem; + text-transform: uppercase; + color:#999; +} diff --git a/website/agenda/planung/css/image_manager.css b/website/agenda/planung/css/image_manager.css deleted file mode 100644 index a6088fb..0000000 --- a/website/agenda/planung/css/image_manager.css +++ /dev/null @@ -1,48 +0,0 @@ -#content div.image{ - display:inline-block; - vertical-alignment:top; - border:1px solid gray; - margin:6px; - padding:0; - text-align:left; - background-repeat:no-repeat; - width:150px; - height:150px; - vertical-align:bottom; -} - -#content .image_detail{ - width:150px; - height:150px; -} - -#content .close{ - text-align:right; - padding:0; - margin:0; - color:white; - float:right; -} - -form table{ - width:100%; - height:100%; -} - -input.field{ - width:30em; -} - - -#content div.image .label{ - text-align:center; - background-color:#333; - color:#fff; - vertical-align:bottom; - opacity:0.8; - padding:6px; - width:138px; - margin:0; -} - - diff --git a/website/agenda/planung/css/images/ui-bg_glass_55_fbf9ee_1x400.png b/website/agenda/planung/css/images/ui-bg_glass_55_fbf9ee_1x400.png deleted file mode 100644 index 3b56cb9..0000000 Binary files a/website/agenda/planung/css/images/ui-bg_glass_55_fbf9ee_1x400.png and /dev/null differ diff --git a/website/agenda/planung/css/images/ui-bg_glass_65_ffffff_1x400.png b/website/agenda/planung/css/images/ui-bg_glass_65_ffffff_1x400.png deleted file mode 100644 index be2dd5e..0000000 Binary files a/website/agenda/planung/css/images/ui-bg_glass_65_ffffff_1x400.png and /dev/null differ diff --git a/website/agenda/planung/css/images/ui-bg_glass_75_dadada_1x400.png b/website/agenda/planung/css/images/ui-bg_glass_75_dadada_1x400.png deleted file mode 100644 index 9e071d8..0000000 Binary files a/website/agenda/planung/css/images/ui-bg_glass_75_dadada_1x400.png and /dev/null differ diff --git a/website/agenda/planung/css/images/ui-bg_glass_75_e6e6e6_1x400.png b/website/agenda/planung/css/images/ui-bg_glass_75_e6e6e6_1x400.png deleted file mode 100644 index 4ba81a5..0000000 Binary files a/website/agenda/planung/css/images/ui-bg_glass_75_e6e6e6_1x400.png and /dev/null differ diff --git a/website/agenda/planung/css/images/ui-bg_glass_95_fef1ec_1x400.png b/website/agenda/planung/css/images/ui-bg_glass_95_fef1ec_1x400.png deleted file mode 100644 index 24b909e..0000000 Binary files a/website/agenda/planung/css/images/ui-bg_glass_95_fef1ec_1x400.png and /dev/null differ diff --git a/website/agenda/planung/css/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/website/agenda/planung/css/images/ui-bg_highlight-soft_75_cccccc_1x100.png deleted file mode 100644 index 28bcf94..0000000 Binary files a/website/agenda/planung/css/images/ui-bg_highlight-soft_75_cccccc_1x100.png and /dev/null differ diff --git a/website/agenda/planung/css/images/ui-icons_222222_256x240.png b/website/agenda/planung/css/images/ui-icons_222222_256x240.png deleted file mode 100644 index e9c8e16..0000000 Binary files a/website/agenda/planung/css/images/ui-icons_222222_256x240.png and /dev/null differ diff --git a/website/agenda/planung/css/images/ui-icons_2e83ff_256x240.png b/website/agenda/planung/css/images/ui-icons_2e83ff_256x240.png deleted file mode 100644 index f2bf838..0000000 Binary files a/website/agenda/planung/css/images/ui-icons_2e83ff_256x240.png and /dev/null differ diff --git a/website/agenda/planung/css/images/ui-icons_454545_256x240.png b/website/agenda/planung/css/images/ui-icons_454545_256x240.png deleted file mode 100644 index d6169e8..0000000 Binary files a/website/agenda/planung/css/images/ui-icons_454545_256x240.png and /dev/null differ diff --git a/website/agenda/planung/css/images/ui-icons_888888_256x240.png b/website/agenda/planung/css/images/ui-icons_888888_256x240.png deleted file mode 100644 index d3e6e02..0000000 Binary files a/website/agenda/planung/css/images/ui-icons_888888_256x240.png and /dev/null differ diff --git a/website/agenda/planung/css/images/ui-icons_cd0a0a_256x240.png b/website/agenda/planung/css/images/ui-icons_cd0a0a_256x240.png deleted file mode 100644 index 4937018..0000000 Binary files a/website/agenda/planung/css/images/ui-icons_cd0a0a_256x240.png and /dev/null differ diff --git a/website/agenda/planung/css/jquery-ui-timepicker.css b/website/agenda/planung/css/jquery-ui-timepicker.css deleted file mode 100644 index 02f77ba..0000000 --- a/website/agenda/planung/css/jquery-ui-timepicker.css +++ /dev/null @@ -1,30 +0,0 @@ -.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: none; border: none; margin: 0; padding: 0; } -.ui-timepicker-div .ui_tpicker_unit_hide{ display: none; } - -.ui-timepicker-div .ui_tpicker_time .ui_tpicker_time_input { background: none; color: inherit; border: none; outline: none; border-bottom: solid 1px #555; width: 95%; } -.ui-timepicker-div .ui_tpicker_time .ui_tpicker_time_input:focus { border-bottom-color: #aaa; } - -.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; } - -/* Shortened version style */ -.ui-timepicker-div.ui-timepicker-oneLine { padding-right: 2px; } -.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_time, -.ui-timepicker-div.ui-timepicker-oneLine dt { display: none; } -.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_time_label { display: block; padding-top: 2px; } -.ui-timepicker-div.ui-timepicker-oneLine dl { text-align: right; } -.ui-timepicker-div.ui-timepicker-oneLine dl dd, -.ui-timepicker-div.ui-timepicker-oneLine dl dd > div { display:inline-block; margin:0; } -.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_minute:before, -.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_second:before { content:':'; display:inline-block; } -.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_millisec:before, -.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_microsec:before { content:'.'; display:inline-block; } -.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_unit_hide, -.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_unit_hide:before{ display: none; } diff --git a/website/agenda/planung/css/jquery-ui-timepicker.old.css b/website/agenda/planung/css/jquery-ui-timepicker.old.css deleted file mode 100644 index 6ef513c..0000000 --- a/website/agenda/planung/css/jquery-ui-timepicker.old.css +++ /dev/null @@ -1,11 +0,0 @@ -.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: none; border: none; 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; } diff --git a/website/agenda/planung/css/jquery-ui.css b/website/agenda/planung/css/jquery-ui.css deleted file mode 100644 index 93707f4..0000000 --- a/website/agenda/planung/css/jquery-ui.css +++ /dev/null @@ -1,1312 +0,0 @@ -/*! jQuery UI - v1.12.1 - 2016-09-14 -* http://jqueryui.com -* Includes: core.css, accordion.css, autocomplete.css, menu.css, button.css, controlgroup.css, checkboxradio.css, datepicker.css, dialog.css, draggable.css, resizable.css, progressbar.css, selectable.css, selectmenu.css, slider.css, sortable.css, spinner.css, tabs.css, tooltip.css, theme.css -* To view and modify this theme, visit http://jqueryui.com/themeroller/?bgShadowXPos=&bgOverlayXPos=&bgErrorXPos=&bgHighlightXPos=&bgContentXPos=&bgHeaderXPos=&bgActiveXPos=&bgHoverXPos=&bgDefaultXPos=&bgShadowYPos=&bgOverlayYPos=&bgErrorYPos=&bgHighlightYPos=&bgContentYPos=&bgHeaderYPos=&bgActiveYPos=&bgHoverYPos=&bgDefaultYPos=&bgShadowRepeat=&bgOverlayRepeat=&bgErrorRepeat=&bgHighlightRepeat=&bgContentRepeat=&bgHeaderRepeat=&bgActiveRepeat=&bgHoverRepeat=&bgDefaultRepeat=&iconsHover=url(%22images%2Fui-icons_555555_256x240.png%22)&iconsHighlight=url(%22images%2Fui-icons_777620_256x240.png%22)&iconsHeader=url(%22images%2Fui-icons_444444_256x240.png%22)&iconsError=url(%22images%2Fui-icons_cc0000_256x240.png%22)&iconsDefault=url(%22images%2Fui-icons_777777_256x240.png%22)&iconsContent=url(%22images%2Fui-icons_444444_256x240.png%22)&iconsActive=url(%22images%2Fui-icons_ffffff_256x240.png%22)&bgImgUrlShadow=&bgImgUrlOverlay=&bgImgUrlHover=&bgImgUrlHighlight=&bgImgUrlHeader=&bgImgUrlError=&bgImgUrlDefault=&bgImgUrlContent=&bgImgUrlActive=&opacityFilterShadow=Alpha(Opacity%3D30)&opacityFilterOverlay=Alpha(Opacity%3D30)&opacityShadowPerc=30&opacityOverlayPerc=30&iconColorHover=%23555555&iconColorHighlight=%23777620&iconColorHeader=%23444444&iconColorError=%23cc0000&iconColorDefault=%23777777&iconColorContent=%23444444&iconColorActive=%23ffffff&bgImgOpacityShadow=0&bgImgOpacityOverlay=0&bgImgOpacityError=95&bgImgOpacityHighlight=55&bgImgOpacityContent=75&bgImgOpacityHeader=75&bgImgOpacityActive=65&bgImgOpacityHover=75&bgImgOpacityDefault=75&bgTextureShadow=flat&bgTextureOverlay=flat&bgTextureError=flat&bgTextureHighlight=flat&bgTextureContent=flat&bgTextureHeader=flat&bgTextureActive=flat&bgTextureHover=flat&bgTextureDefault=flat&cornerRadius=3px&fwDefault=normal&ffDefault=Arial%2CHelvetica%2Csans-serif&fsDefault=1em&cornerRadiusShadow=8px&thicknessShadow=5px&offsetLeftShadow=0px&offsetTopShadow=0px&opacityShadow=.3&bgColorShadow=%23666666&opacityOverlay=.3&bgColorOverlay=%23aaaaaa&fcError=%235f3f3f&borderColorError=%23f1a899&bgColorError=%23fddfdf&fcHighlight=%23777620&borderColorHighlight=%23dad55e&bgColorHighlight=%23fffa90&fcContent=%23333333&borderColorContent=%23dddddd&bgColorContent=%23ffffff&fcHeader=%23333333&borderColorHeader=%23dddddd&bgColorHeader=%23e9e9e9&fcActive=%23ffffff&borderColorActive=%23003eff&bgColorActive=%23007fff&fcHover=%232b2b2b&borderColorHover=%23cccccc&bgColorHover=%23ededed&fcDefault=%23454545&borderColorDefault=%23c5c5c5&bgColorDefault=%23f6f6f6 -* Copyright jQuery Foundation and other contributors; Licensed MIT */ - -/* Layout helpers -----------------------------------*/ -.ui-helper-hidden { - display: none; -} -.ui-helper-hidden-accessible { - border: 0; - clip: rect(0 0 0 0); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - width: 1px; -} -.ui-helper-reset { - margin: 0; - padding: 0; - border: 0; - outline: 0; - line-height: 1.3; - text-decoration: none; - font-size: 100%; - list-style: none; -} -.ui-helper-clearfix:before, -.ui-helper-clearfix:after { - content: ""; - display: table; - border-collapse: collapse; -} -.ui-helper-clearfix:after { - clear: both; -} -.ui-helper-zfix { - width: 100%; - height: 100%; - top: 0; - left: 0; - position: absolute; - opacity: 0; - filter:Alpha(Opacity=0); /* support: IE8 */ -} - -.ui-front { - z-index: 100; -} - - -/* Interaction Cues -----------------------------------*/ -.ui-state-disabled { - cursor: default !important; - pointer-events: none; -} - - -/* Icons -----------------------------------*/ -.ui-icon { - display: inline-block; - vertical-align: middle; - margin-top: -.25em; - position: relative; - text-indent: -99999px; - overflow: hidden; - background-repeat: no-repeat; -} - -.ui-widget-icon-block { - left: 50%; - margin-left: -8px; - display: block; -} - -/* Misc visuals -----------------------------------*/ - -/* Overlays */ -.ui-widget-overlay { - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; -} -.ui-accordion .ui-accordion-header { - display: block; - cursor: pointer; - position: relative; - margin: 2px 0 0 0; - padding: .5em .5em .5em .7em; - font-size: 100%; -} -.ui-accordion .ui-accordion-content { - padding: 1em 2.2em; - border-top: 0; - overflow: auto; -} -.ui-autocomplete { - position: absolute; - top: 0; - left: 0; - cursor: default; -} -.ui-menu { - list-style: none; - padding: 0; - margin: 0; - display: block; - outline: 0; -} -.ui-menu .ui-menu { - position: absolute; -} -.ui-menu .ui-menu-item { - margin: 0; - cursor: pointer; - /* support: IE10, see #8844 */ - list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"); -} -.ui-menu .ui-menu-item-wrapper { - position: relative; - padding: 3px 1em 3px .4em; -} -.ui-menu .ui-menu-divider { - margin: 5px 0; - height: 0; - font-size: 0; - line-height: 0; - border-width: 1px 0 0 0; -} -.ui-menu .ui-state-focus, -.ui-menu .ui-state-active { - margin: -1px; -} - -/* icon support */ -.ui-menu-icons { - position: relative; -} -.ui-menu-icons .ui-menu-item-wrapper { - padding-left: 2em; -} - -/* left-aligned */ -.ui-menu .ui-icon { - position: absolute; - top: 0; - bottom: 0; - left: .2em; - margin: auto 0; -} - -/* right-aligned */ -.ui-menu .ui-menu-icon { - left: auto; - right: 0; -} -.ui-button { - padding: .4em 1em; - display: inline-block; - position: relative; - line-height: normal; - margin-right: .1em; - cursor: pointer; - vertical-align: middle; - text-align: center; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - - /* Support: IE <= 11 */ - overflow: visible; -} - -.ui-button, -.ui-button:link, -.ui-button:visited, -.ui-button:hover, -.ui-button:active { - text-decoration: none; -} - -/* to make room for the icon, a width needs to be set here */ -.ui-button-icon-only { - width: 2em; - box-sizing: border-box; - text-indent: -9999px; - white-space: nowrap; -} - -/* no icon support for input elements */ -input.ui-button.ui-button-icon-only { - text-indent: 0; -} - -/* button icon element(s) */ -.ui-button-icon-only .ui-icon { - position: absolute; - top: 50%; - left: 50%; - margin-top: -8px; - margin-left: -8px; -} - -.ui-button.ui-icon-notext .ui-icon { - padding: 0; - width: 2.1em; - height: 2.1em; - text-indent: -9999px; - white-space: nowrap; - -} - -input.ui-button.ui-icon-notext .ui-icon { - width: auto; - height: auto; - text-indent: 0; - white-space: normal; - padding: .4em 1em; -} - -/* workarounds */ -/* Support: Firefox 5 - 40 */ -input.ui-button::-moz-focus-inner, -button.ui-button::-moz-focus-inner { - border: 0; - padding: 0; -} -.ui-controlgroup { - vertical-align: middle; - display: inline-block; -} -.ui-controlgroup > .ui-controlgroup-item { - float: left; - margin-left: 0; - margin-right: 0; -} -.ui-controlgroup > .ui-controlgroup-item:focus, -.ui-controlgroup > .ui-controlgroup-item.ui-visual-focus { - z-index: 9999; -} -.ui-controlgroup-vertical > .ui-controlgroup-item { - display: block; - float: none; - width: 100%; - margin-top: 0; - margin-bottom: 0; - text-align: left; -} -.ui-controlgroup-vertical .ui-controlgroup-item { - box-sizing: border-box; -} -.ui-controlgroup .ui-controlgroup-label { - padding: .4em 1em; -} -.ui-controlgroup .ui-controlgroup-label span { - font-size: 80%; -} -.ui-controlgroup-horizontal .ui-controlgroup-label + .ui-controlgroup-item { - border-left: none; -} -.ui-controlgroup-vertical .ui-controlgroup-label + .ui-controlgroup-item { - border-top: none; -} -.ui-controlgroup-horizontal .ui-controlgroup-label.ui-widget-content { - border-right: none; -} -.ui-controlgroup-vertical .ui-controlgroup-label.ui-widget-content { - border-bottom: none; -} - -/* Spinner specific style fixes */ -.ui-controlgroup-vertical .ui-spinner-input { - - /* Support: IE8 only, Android < 4.4 only */ - width: 75%; - width: calc( 100% - 2.4em ); -} -.ui-controlgroup-vertical .ui-spinner .ui-spinner-up { - border-top-style: solid; -} - -.ui-checkboxradio-label .ui-icon-background { - box-shadow: inset 1px 1px 1px #ccc; - border-radius: .12em; - border: none; -} -.ui-checkboxradio-radio-label .ui-icon-background { - width: 16px; - height: 16px; - border-radius: 1em; - overflow: visible; - border: none; -} -.ui-checkboxradio-radio-label.ui-checkboxradio-checked .ui-icon, -.ui-checkboxradio-radio-label.ui-checkboxradio-checked:hover .ui-icon { - background-image: none; - width: 8px; - height: 8px; - border-width: 4px; - border-style: solid; -} -.ui-checkboxradio-disabled { - pointer-events: none; -} -.ui-datepicker { - width: 17em; - padding: .2em .2em 0; - display: none; -} -.ui-datepicker .ui-datepicker-header { - position: relative; - padding: .2em 0; -} -.ui-datepicker .ui-datepicker-prev, -.ui-datepicker .ui-datepicker-next { - position: absolute; - top: 2px; - width: 1.8em; - height: 1.8em; -} -.ui-datepicker .ui-datepicker-prev-hover, -.ui-datepicker .ui-datepicker-next-hover { - top: 1px; -} -.ui-datepicker .ui-datepicker-prev { - left: 2px; -} -.ui-datepicker .ui-datepicker-next { - right: 2px; -} -.ui-datepicker .ui-datepicker-prev-hover { - left: 1px; -} -.ui-datepicker .ui-datepicker-next-hover { - right: 1px; -} -.ui-datepicker .ui-datepicker-prev span, -.ui-datepicker .ui-datepicker-next span { - display: block; - position: absolute; - left: 50%; - margin-left: -8px; - top: 50%; - margin-top: -8px; -} -.ui-datepicker .ui-datepicker-title { - margin: 0 2.3em; - line-height: 1.8em; - text-align: center; -} -.ui-datepicker .ui-datepicker-title select { - font-size: 1em; - margin: 1px 0; -} -.ui-datepicker select.ui-datepicker-month, -.ui-datepicker select.ui-datepicker-year { - width: 45%; -} -.ui-datepicker table { - width: 100%; - font-size: .9em; - border-collapse: collapse; - margin: 0 0 .4em; -} -.ui-datepicker th { - padding: .7em .3em; - text-align: center; - font-weight: bold; - border: 0; -} -.ui-datepicker td { - border: 0; - padding: 1px; -} -.ui-datepicker td span, -.ui-datepicker td a { - display: block; - padding: .2em; - text-align: right; - text-decoration: none; -} -.ui-datepicker .ui-datepicker-buttonpane { - background-image: none; - margin: .7em 0 0 0; - padding: 0 .2em; - border-left: 0; - border-right: 0; - border-bottom: 0; -} -.ui-datepicker .ui-datepicker-buttonpane button { - float: right; - margin: .5em .2em .4em; - cursor: pointer; - padding: .2em .6em .3em .6em; - width: auto; - overflow: visible; -} -.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { - float: left; -} - -/* with multiple calendars */ -.ui-datepicker.ui-datepicker-multi { - width: auto; -} -.ui-datepicker-multi .ui-datepicker-group { - float: left; -} -.ui-datepicker-multi .ui-datepicker-group table { - width: 95%; - margin: 0 auto .4em; -} -.ui-datepicker-multi-2 .ui-datepicker-group { - width: 50%; -} -.ui-datepicker-multi-3 .ui-datepicker-group { - width: 33.3%; -} -.ui-datepicker-multi-4 .ui-datepicker-group { - width: 25%; -} -.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header, -.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { - border-left-width: 0; -} -.ui-datepicker-multi .ui-datepicker-buttonpane { - clear: left; -} -.ui-datepicker-row-break { - clear: both; - width: 100%; - font-size: 0; -} - -/* RTL support */ -.ui-datepicker-rtl { - direction: rtl; -} -.ui-datepicker-rtl .ui-datepicker-prev { - right: 2px; - left: auto; -} -.ui-datepicker-rtl .ui-datepicker-next { - left: 2px; - right: auto; -} -.ui-datepicker-rtl .ui-datepicker-prev:hover { - right: 1px; - left: auto; -} -.ui-datepicker-rtl .ui-datepicker-next:hover { - left: 1px; - right: auto; -} -.ui-datepicker-rtl .ui-datepicker-buttonpane { - clear: right; -} -.ui-datepicker-rtl .ui-datepicker-buttonpane button { - float: left; -} -.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current, -.ui-datepicker-rtl .ui-datepicker-group { - float: right; -} -.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header, -.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { - border-right-width: 0; - border-left-width: 1px; -} - -/* Icons */ -.ui-datepicker .ui-icon { - display: block; - text-indent: -99999px; - overflow: hidden; - background-repeat: no-repeat; - left: .5em; - top: .3em; -} -.ui-dialog { - position: absolute; - top: 0; - left: 0; - padding: .2em; - outline: 0; -} -.ui-dialog .ui-dialog-titlebar { - padding: .4em 1em; - position: relative; -} -.ui-dialog .ui-dialog-title { - float: left; - margin: .1em 0; - white-space: nowrap; - width: 90%; - overflow: hidden; - text-overflow: ellipsis; -} -.ui-dialog .ui-dialog-titlebar-close { - position: absolute; - right: .3em; - top: 50%; - width: 20px; - margin: -10px 0 0 0; - padding: 1px; - height: 20px; -} -.ui-dialog .ui-dialog-content { - position: relative; - border: 0; - padding: .5em 1em; - background: none; - overflow: auto; -} -.ui-dialog .ui-dialog-buttonpane { - text-align: left; - border-width: 1px 0 0 0; - background-image: none; - margin-top: .5em; - padding: .3em 1em .5em .4em; -} -.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { - float: right; -} -.ui-dialog .ui-dialog-buttonpane button { - margin: .5em .4em .5em 0; - cursor: pointer; -} -.ui-dialog .ui-resizable-n { - height: 2px; - top: 0; -} -.ui-dialog .ui-resizable-e { - width: 2px; - right: 0; -} -.ui-dialog .ui-resizable-s { - height: 2px; - bottom: 0; -} -.ui-dialog .ui-resizable-w { - width: 2px; - left: 0; -} -.ui-dialog .ui-resizable-se, -.ui-dialog .ui-resizable-sw, -.ui-dialog .ui-resizable-ne, -.ui-dialog .ui-resizable-nw { - width: 7px; - height: 7px; -} -.ui-dialog .ui-resizable-se { - right: 0; - bottom: 0; -} -.ui-dialog .ui-resizable-sw { - left: 0; - bottom: 0; -} -.ui-dialog .ui-resizable-ne { - right: 0; - top: 0; -} -.ui-dialog .ui-resizable-nw { - left: 0; - top: 0; -} -.ui-draggable .ui-dialog-titlebar { - cursor: move; -} -.ui-draggable-handle { - -ms-touch-action: none; - touch-action: none; -} -.ui-resizable { - position: relative; -} -.ui-resizable-handle { - position: absolute; - font-size: 0.1px; - display: block; - -ms-touch-action: none; - touch-action: none; -} -.ui-resizable-disabled .ui-resizable-handle, -.ui-resizable-autohide .ui-resizable-handle { - display: none; -} -.ui-resizable-n { - cursor: n-resize; - height: 7px; - width: 100%; - top: -5px; - left: 0; -} -.ui-resizable-s { - cursor: s-resize; - height: 7px; - width: 100%; - bottom: -5px; - left: 0; -} -.ui-resizable-e { - cursor: e-resize; - width: 7px; - right: -5px; - top: 0; - height: 100%; -} -.ui-resizable-w { - cursor: w-resize; - width: 7px; - left: -5px; - top: 0; - height: 100%; -} -.ui-resizable-se { - cursor: se-resize; - width: 12px; - height: 12px; - right: 1px; - bottom: 1px; -} -.ui-resizable-sw { - cursor: sw-resize; - width: 9px; - height: 9px; - left: -5px; - bottom: -5px; -} -.ui-resizable-nw { - cursor: nw-resize; - width: 9px; - height: 9px; - left: -5px; - top: -5px; -} -.ui-resizable-ne { - cursor: ne-resize; - width: 9px; - height: 9px; - right: -5px; - top: -5px; -} -.ui-progressbar { - height: 2em; - text-align: left; - overflow: hidden; -} -.ui-progressbar .ui-progressbar-value { - margin: -1px; - height: 100%; -} -.ui-progressbar .ui-progressbar-overlay { - background: url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw=="); - height: 100%; - filter: alpha(opacity=25); /* support: IE8 */ - opacity: 0.25; -} -.ui-progressbar-indeterminate .ui-progressbar-value { - background-image: none; -} -.ui-selectable { - -ms-touch-action: none; - touch-action: none; -} -.ui-selectable-helper { - position: absolute; - z-index: 100; - border: 1px dotted black; -} -.ui-selectmenu-menu { - padding: 0; - margin: 0; - position: absolute; - top: 0; - left: 0; - display: none; -} -.ui-selectmenu-menu .ui-menu { - overflow: auto; - overflow-x: hidden; - padding-bottom: 1px; -} -.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup { - font-size: 1em; - font-weight: bold; - line-height: 1.5; - padding: 2px 0.4em; - margin: 0.5em 0 0 0; - height: auto; - border: 0; -} -.ui-selectmenu-open { - display: block; -} -.ui-selectmenu-text { - display: block; - margin-right: 20px; - overflow: hidden; - text-overflow: ellipsis; -} -.ui-selectmenu-button.ui-button { - text-align: left; - white-space: nowrap; - width: 14em; -} -.ui-selectmenu-icon.ui-icon { - float: right; - margin-top: 0; -} -.ui-slider { - position: relative; - text-align: left; -} -.ui-slider .ui-slider-handle { - position: absolute; - z-index: 2; - width: 1.2em; - height: 1.2em; - cursor: default; - -ms-touch-action: none; - touch-action: none; -} -.ui-slider .ui-slider-range { - position: absolute; - z-index: 1; - font-size: .7em; - display: block; - border: 0; - background-position: 0 0; -} - -/* support: IE8 - See #6727 */ -.ui-slider.ui-state-disabled .ui-slider-handle, -.ui-slider.ui-state-disabled .ui-slider-range { - filter: inherit; -} - -.ui-slider-horizontal { - height: .8em; -} -.ui-slider-horizontal .ui-slider-handle { - top: -.3em; - margin-left: -.6em; -} -.ui-slider-horizontal .ui-slider-range { - top: 0; - height: 100%; -} -.ui-slider-horizontal .ui-slider-range-min { - left: 0; -} -.ui-slider-horizontal .ui-slider-range-max { - right: 0; -} - -.ui-slider-vertical { - width: .8em; - height: 100px; -} -.ui-slider-vertical .ui-slider-handle { - left: -.3em; - margin-left: 0; - margin-bottom: -.6em; -} -.ui-slider-vertical .ui-slider-range { - left: 0; - width: 100%; -} -.ui-slider-vertical .ui-slider-range-min { - bottom: 0; -} -.ui-slider-vertical .ui-slider-range-max { - top: 0; -} -.ui-sortable-handle { - -ms-touch-action: none; - touch-action: none; -} -.ui-spinner { - position: relative; - display: inline-block; - overflow: hidden; - padding: 0; - vertical-align: middle; -} -.ui-spinner-input { - border: none; - background: none; - color: inherit; - padding: .222em 0; - margin: .2em 0; - vertical-align: middle; - margin-left: .4em; - margin-right: 2em; -} -.ui-spinner-button { - width: 1.6em; - height: 50%; - font-size: .5em; - padding: 0; - margin: 0; - text-align: center; - position: absolute; - cursor: default; - display: block; - overflow: hidden; - right: 0; -} -/* more specificity required here to override default borders */ -.ui-spinner a.ui-spinner-button { - border-top-style: none; - border-bottom-style: none; - border-right-style: none; -} -.ui-spinner-up { - top: 0; -} -.ui-spinner-down { - bottom: 0; -} -.ui-tabs { - position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ - padding: .2em; -} -.ui-tabs .ui-tabs-nav { - margin: 0; - padding: .2em .2em 0; -} -.ui-tabs .ui-tabs-nav li { - list-style: none; - float: left; - position: relative; - top: 0; - margin: 1px .2em 0 0; - border-bottom-width: 0; - padding: 0; - white-space: nowrap; -} -.ui-tabs .ui-tabs-nav .ui-tabs-anchor { - float: left; - padding: .5em 1em; - text-decoration: none; -} -.ui-tabs .ui-tabs-nav li.ui-tabs-active { - margin-bottom: -1px; - padding-bottom: 1px; -} -.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor, -.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor, -.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor { - cursor: text; -} -.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor { - cursor: pointer; -} -.ui-tabs .ui-tabs-panel { - display: block; - border-width: 0; - padding: 1em 1.4em; - background: none; -} -.ui-tooltip { - padding: 8px; - position: absolute; - z-index: 9999; - max-width: 300px; -} -body .ui-tooltip { - border-width: 2px; -} - -/* Component containers -----------------------------------*/ -.ui-widget { - font-family: Arial,Helvetica,sans-serif; - font-size: 1em; -} -.ui-widget .ui-widget { - font-size: 1em; -} -.ui-widget input, -.ui-widget select, -.ui-widget textarea, -.ui-widget button { - font-family: Arial,Helvetica,sans-serif; - font-size: 1em; -} -.ui-widget.ui-widget-content { - border: 1px solid #c5c5c5; -} -.ui-widget-content { - border: 1px solid #dddddd; - background: #ffffff; - color: #333333; -} -.ui-widget-content a { - color: #333333; -} -.ui-widget-header { - border: 1px solid #dddddd; - background: #e9e9e9; - color: #333333; - font-weight: bold; -} -.ui-widget-header a { - color: #333333; -} - -/* Interaction states -----------------------------------*/ -.ui-state-default, -.ui-widget-content .ui-state-default, -.ui-widget-header .ui-state-default, -.ui-button, - -/* We use html here because we need a greater specificity to make sure disabled -works properly when clicked or hovered */ -html .ui-button.ui-state-disabled:hover, -html .ui-button.ui-state-disabled:active { - border: 1px solid #c5c5c5; - background: #f6f6f6; - font-weight: normal; - color: #454545; -} -.ui-state-default a, -.ui-state-default a:link, -.ui-state-default a:visited, -a.ui-button, -a:link.ui-button, -a:visited.ui-button, -.ui-button { - color: #454545; - text-decoration: none; -} -.ui-state-hover, -.ui-widget-content .ui-state-hover, -.ui-widget-header .ui-state-hover, -.ui-state-focus, -.ui-widget-content .ui-state-focus, -.ui-widget-header .ui-state-focus, -.ui-button:hover, -.ui-button:focus { - border: 1px solid #cccccc; - background: #ededed; - font-weight: normal; - color: #2b2b2b; -} -.ui-state-hover a, -.ui-state-hover a:hover, -.ui-state-hover a:link, -.ui-state-hover a:visited, -.ui-state-focus a, -.ui-state-focus a:hover, -.ui-state-focus a:link, -.ui-state-focus a:visited, -a.ui-button:hover, -a.ui-button:focus { - color: #2b2b2b; - text-decoration: none; -} - -.ui-visual-focus { - box-shadow: 0 0 3px 1px rgb(94, 158, 214); -} -.ui-state-active, -.ui-widget-content .ui-state-active, -.ui-widget-header .ui-state-active, -a.ui-button:active, -.ui-button:active, -.ui-button.ui-state-active:hover { - border: 1px solid #003eff; - background: #007fff; - font-weight: normal; - color: #ffffff; -} -.ui-icon-background, -.ui-state-active .ui-icon-background { - border: #003eff; - background-color: #ffffff; -} -.ui-state-active a, -.ui-state-active a:link, -.ui-state-active a:visited { - color: #ffffff; - text-decoration: none; -} - -/* Interaction Cues -----------------------------------*/ -.ui-state-highlight, -.ui-widget-content .ui-state-highlight, -.ui-widget-header .ui-state-highlight { - border: 1px solid #dad55e; - background: #fffa90; - color: #777620; -} -.ui-state-checked { - border: 1px solid #dad55e; - background: #fffa90; -} -.ui-state-highlight a, -.ui-widget-content .ui-state-highlight a, -.ui-widget-header .ui-state-highlight a { - color: #777620; -} -.ui-state-error, -.ui-widget-content .ui-state-error, -.ui-widget-header .ui-state-error { - border: 1px solid #f1a899; - background: #fddfdf; - color: #5f3f3f; -} -.ui-state-error a, -.ui-widget-content .ui-state-error a, -.ui-widget-header .ui-state-error a { - color: #5f3f3f; -} -.ui-state-error-text, -.ui-widget-content .ui-state-error-text, -.ui-widget-header .ui-state-error-text { - color: #5f3f3f; -} -.ui-priority-primary, -.ui-widget-content .ui-priority-primary, -.ui-widget-header .ui-priority-primary { - font-weight: bold; -} -.ui-priority-secondary, -.ui-widget-content .ui-priority-secondary, -.ui-widget-header .ui-priority-secondary { - opacity: .7; - filter:Alpha(Opacity=70); /* support: IE8 */ - font-weight: normal; -} -.ui-state-disabled, -.ui-widget-content .ui-state-disabled, -.ui-widget-header .ui-state-disabled { - opacity: .35; - filter:Alpha(Opacity=35); /* support: IE8 */ - background-image: none; -} -.ui-state-disabled .ui-icon { - filter:Alpha(Opacity=35); /* support: IE8 - See #6059 */ -} - -/* Icons -----------------------------------*/ - -/* states and images */ -.ui-icon { - width: 16px; - height: 16px; -} -.ui-icon, -.ui-widget-content .ui-icon { - background-image: url("images/ui-icons_444444_256x240.png"); -} -.ui-widget-header .ui-icon { - background-image: url("images/ui-icons_444444_256x240.png"); -} -.ui-state-hover .ui-icon, -.ui-state-focus .ui-icon, -.ui-button:hover .ui-icon, -.ui-button:focus .ui-icon { - background-image: url("images/ui-icons_555555_256x240.png"); -} -.ui-state-active .ui-icon, -.ui-button:active .ui-icon { - background-image: url("images/ui-icons_ffffff_256x240.png"); -} -.ui-state-highlight .ui-icon, -.ui-button .ui-state-highlight.ui-icon { - background-image: url("images/ui-icons_777620_256x240.png"); -} -.ui-state-error .ui-icon, -.ui-state-error-text .ui-icon { - background-image: url("images/ui-icons_cc0000_256x240.png"); -} -.ui-button .ui-icon { - background-image: url("images/ui-icons_777777_256x240.png"); -} - -/* positioning */ -.ui-icon-blank { background-position: 16px 16px; } -.ui-icon-caret-1-n { background-position: 0 0; } -.ui-icon-caret-1-ne { background-position: -16px 0; } -.ui-icon-caret-1-e { background-position: -32px 0; } -.ui-icon-caret-1-se { background-position: -48px 0; } -.ui-icon-caret-1-s { background-position: -65px 0; } -.ui-icon-caret-1-sw { background-position: -80px 0; } -.ui-icon-caret-1-w { background-position: -96px 0; } -.ui-icon-caret-1-nw { background-position: -112px 0; } -.ui-icon-caret-2-n-s { background-position: -128px 0; } -.ui-icon-caret-2-e-w { background-position: -144px 0; } -.ui-icon-triangle-1-n { background-position: 0 -16px; } -.ui-icon-triangle-1-ne { background-position: -16px -16px; } -.ui-icon-triangle-1-e { background-position: -32px -16px; } -.ui-icon-triangle-1-se { background-position: -48px -16px; } -.ui-icon-triangle-1-s { background-position: -65px -16px; } -.ui-icon-triangle-1-sw { background-position: -80px -16px; } -.ui-icon-triangle-1-w { background-position: -96px -16px; } -.ui-icon-triangle-1-nw { background-position: -112px -16px; } -.ui-icon-triangle-2-n-s { background-position: -128px -16px; } -.ui-icon-triangle-2-e-w { background-position: -144px -16px; } -.ui-icon-arrow-1-n { background-position: 0 -32px; } -.ui-icon-arrow-1-ne { background-position: -16px -32px; } -.ui-icon-arrow-1-e { background-position: -32px -32px; } -.ui-icon-arrow-1-se { background-position: -48px -32px; } -.ui-icon-arrow-1-s { background-position: -65px -32px; } -.ui-icon-arrow-1-sw { background-position: -80px -32px; } -.ui-icon-arrow-1-w { background-position: -96px -32px; } -.ui-icon-arrow-1-nw { background-position: -112px -32px; } -.ui-icon-arrow-2-n-s { background-position: -128px -32px; } -.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } -.ui-icon-arrow-2-e-w { background-position: -160px -32px; } -.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } -.ui-icon-arrowstop-1-n { background-position: -192px -32px; } -.ui-icon-arrowstop-1-e { background-position: -208px -32px; } -.ui-icon-arrowstop-1-s { background-position: -224px -32px; } -.ui-icon-arrowstop-1-w { background-position: -240px -32px; } -.ui-icon-arrowthick-1-n { background-position: 1px -48px; } -.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } -.ui-icon-arrowthick-1-e { background-position: -32px -48px; } -.ui-icon-arrowthick-1-se { background-position: -48px -48px; } -.ui-icon-arrowthick-1-s { background-position: -64px -48px; } -.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } -.ui-icon-arrowthick-1-w { background-position: -96px -48px; } -.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } -.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } -.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } -.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } -.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } -.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } -.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } -.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } -.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } -.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } -.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } -.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } -.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } -.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } -.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } -.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } -.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } -.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } -.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } -.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } -.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } -.ui-icon-arrow-4 { background-position: 0 -80px; } -.ui-icon-arrow-4-diag { background-position: -16px -80px; } -.ui-icon-extlink { background-position: -32px -80px; } -.ui-icon-newwin { background-position: -48px -80px; } -.ui-icon-refresh { background-position: -64px -80px; } -.ui-icon-shuffle { background-position: -80px -80px; } -.ui-icon-transfer-e-w { background-position: -96px -80px; } -.ui-icon-transferthick-e-w { background-position: -112px -80px; } -.ui-icon-folder-collapsed { background-position: 0 -96px; } -.ui-icon-folder-open { background-position: -16px -96px; } -.ui-icon-document { background-position: -32px -96px; } -.ui-icon-document-b { background-position: -48px -96px; } -.ui-icon-note { background-position: -64px -96px; } -.ui-icon-mail-closed { background-position: -80px -96px; } -.ui-icon-mail-open { background-position: -96px -96px; } -.ui-icon-suitcase { background-position: -112px -96px; } -.ui-icon-comment { background-position: -128px -96px; } -.ui-icon-person { background-position: -144px -96px; } -.ui-icon-print { background-position: -160px -96px; } -.ui-icon-trash { background-position: -176px -96px; } -.ui-icon-locked { background-position: -192px -96px; } -.ui-icon-unlocked { background-position: -208px -96px; } -.ui-icon-bookmark { background-position: -224px -96px; } -.ui-icon-tag { background-position: -240px -96px; } -.ui-icon-home { background-position: 0 -112px; } -.ui-icon-flag { background-position: -16px -112px; } -.ui-icon-calendar { background-position: -32px -112px; } -.ui-icon-cart { background-position: -48px -112px; } -.ui-icon-pencil { background-position: -64px -112px; } -.ui-icon-clock { background-position: -80px -112px; } -.ui-icon-disk { background-position: -96px -112px; } -.ui-icon-calculator { background-position: -112px -112px; } -.ui-icon-zoomin { background-position: -128px -112px; } -.ui-icon-zoomout { background-position: -144px -112px; } -.ui-icon-search { background-position: -160px -112px; } -.ui-icon-wrench { background-position: -176px -112px; } -.ui-icon-gear { background-position: -192px -112px; } -.ui-icon-heart { background-position: -208px -112px; } -.ui-icon-star { background-position: -224px -112px; } -.ui-icon-link { background-position: -240px -112px; } -.ui-icon-cancel { background-position: 0 -128px; } -.ui-icon-plus { background-position: -16px -128px; } -.ui-icon-plusthick { background-position: -32px -128px; } -.ui-icon-minus { background-position: -48px -128px; } -.ui-icon-minusthick { background-position: -64px -128px; } -.ui-icon-close { background-position: -80px -128px; } -.ui-icon-closethick { background-position: -96px -128px; } -.ui-icon-key { background-position: -112px -128px; } -.ui-icon-lightbulb { background-position: -128px -128px; } -.ui-icon-scissors { background-position: -144px -128px; } -.ui-icon-clipboard { background-position: -160px -128px; } -.ui-icon-copy { background-position: -176px -128px; } -.ui-icon-contact { background-position: -192px -128px; } -.ui-icon-image { background-position: -208px -128px; } -.ui-icon-video { background-position: -224px -128px; } -.ui-icon-script { background-position: -240px -128px; } -.ui-icon-alert { background-position: 0 -144px; } -.ui-icon-info { background-position: -16px -144px; } -.ui-icon-notice { background-position: -32px -144px; } -.ui-icon-help { background-position: -48px -144px; } -.ui-icon-check { background-position: -64px -144px; } -.ui-icon-bullet { background-position: -80px -144px; } -.ui-icon-radio-on { background-position: -96px -144px; } -.ui-icon-radio-off { background-position: -112px -144px; } -.ui-icon-pin-w { background-position: -128px -144px; } -.ui-icon-pin-s { background-position: -144px -144px; } -.ui-icon-play { background-position: 0 -160px; } -.ui-icon-pause { background-position: -16px -160px; } -.ui-icon-seek-next { background-position: -32px -160px; } -.ui-icon-seek-prev { background-position: -48px -160px; } -.ui-icon-seek-end { background-position: -64px -160px; } -.ui-icon-seek-start { background-position: -80px -160px; } -/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ -.ui-icon-seek-first { background-position: -80px -160px; } -.ui-icon-stop { background-position: -96px -160px; } -.ui-icon-eject { background-position: -112px -160px; } -.ui-icon-volume-off { background-position: -128px -160px; } -.ui-icon-volume-on { background-position: -144px -160px; } -.ui-icon-power { background-position: 0 -176px; } -.ui-icon-signal-diag { background-position: -16px -176px; } -.ui-icon-signal { background-position: -32px -176px; } -.ui-icon-battery-0 { background-position: -48px -176px; } -.ui-icon-battery-1 { background-position: -64px -176px; } -.ui-icon-battery-2 { background-position: -80px -176px; } -.ui-icon-battery-3 { background-position: -96px -176px; } -.ui-icon-circle-plus { background-position: 0 -192px; } -.ui-icon-circle-minus { background-position: -16px -192px; } -.ui-icon-circle-close { background-position: -32px -192px; } -.ui-icon-circle-triangle-e { background-position: -48px -192px; } -.ui-icon-circle-triangle-s { background-position: -64px -192px; } -.ui-icon-circle-triangle-w { background-position: -80px -192px; } -.ui-icon-circle-triangle-n { background-position: -96px -192px; } -.ui-icon-circle-arrow-e { background-position: -112px -192px; } -.ui-icon-circle-arrow-s { background-position: -128px -192px; } -.ui-icon-circle-arrow-w { background-position: -144px -192px; } -.ui-icon-circle-arrow-n { background-position: -160px -192px; } -.ui-icon-circle-zoomin { background-position: -176px -192px; } -.ui-icon-circle-zoomout { background-position: -192px -192px; } -.ui-icon-circle-check { background-position: -208px -192px; } -.ui-icon-circlesmall-plus { background-position: 0 -208px; } -.ui-icon-circlesmall-minus { background-position: -16px -208px; } -.ui-icon-circlesmall-close { background-position: -32px -208px; } -.ui-icon-squaresmall-plus { background-position: -48px -208px; } -.ui-icon-squaresmall-minus { background-position: -64px -208px; } -.ui-icon-squaresmall-close { background-position: -80px -208px; } -.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } -.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } -.ui-icon-grip-solid-vertical { background-position: -32px -224px; } -.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } -.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } -.ui-icon-grip-diagonal-se { background-position: -80px -224px; } - - -/* Misc visuals -----------------------------------*/ - -/* Corner radius */ -.ui-corner-all, -.ui-corner-top, -.ui-corner-left, -.ui-corner-tl { - border-top-left-radius: 3px; -} -.ui-corner-all, -.ui-corner-top, -.ui-corner-right, -.ui-corner-tr { - border-top-right-radius: 3px; -} -.ui-corner-all, -.ui-corner-bottom, -.ui-corner-left, -.ui-corner-bl { - border-bottom-left-radius: 3px; -} -.ui-corner-all, -.ui-corner-bottom, -.ui-corner-right, -.ui-corner-br { - border-bottom-right-radius: 3px; -} - -/* Overlays */ -.ui-widget-overlay { - background: #aaaaaa; - opacity: .003; - filter: Alpha(Opacity=.3); /* support: IE8 */ -} -.ui-widget-shadow { - -webkit-box-shadow: 0px 0px 5px #666666; - box-shadow: 0px 0px 5px #666666; -} diff --git a/website/agenda/planung/css/jquery-ui.min.css b/website/agenda/planung/css/jquery-ui.min.css deleted file mode 100644 index 776e259..0000000 --- a/website/agenda/planung/css/jquery-ui.min.css +++ /dev/null @@ -1,7 +0,0 @@ -/*! jQuery UI - v1.12.1 - 2016-09-14 -* http://jqueryui.com -* Includes: core.css, accordion.css, autocomplete.css, menu.css, button.css, controlgroup.css, checkboxradio.css, datepicker.css, dialog.css, draggable.css, resizable.css, progressbar.css, selectable.css, selectmenu.css, slider.css, sortable.css, spinner.css, tabs.css, tooltip.css, theme.css -* To view and modify this theme, visit http://jqueryui.com/themeroller/?bgShadowXPos=&bgOverlayXPos=&bgErrorXPos=&bgHighlightXPos=&bgContentXPos=&bgHeaderXPos=&bgActiveXPos=&bgHoverXPos=&bgDefaultXPos=&bgShadowYPos=&bgOverlayYPos=&bgErrorYPos=&bgHighlightYPos=&bgContentYPos=&bgHeaderYPos=&bgActiveYPos=&bgHoverYPos=&bgDefaultYPos=&bgShadowRepeat=&bgOverlayRepeat=&bgErrorRepeat=&bgHighlightRepeat=&bgContentRepeat=&bgHeaderRepeat=&bgActiveRepeat=&bgHoverRepeat=&bgDefaultRepeat=&iconsHover=url(%22images%2Fui-icons_555555_256x240.png%22)&iconsHighlight=url(%22images%2Fui-icons_777620_256x240.png%22)&iconsHeader=url(%22images%2Fui-icons_444444_256x240.png%22)&iconsError=url(%22images%2Fui-icons_cc0000_256x240.png%22)&iconsDefault=url(%22images%2Fui-icons_777777_256x240.png%22)&iconsContent=url(%22images%2Fui-icons_444444_256x240.png%22)&iconsActive=url(%22images%2Fui-icons_ffffff_256x240.png%22)&bgImgUrlShadow=&bgImgUrlOverlay=&bgImgUrlHover=&bgImgUrlHighlight=&bgImgUrlHeader=&bgImgUrlError=&bgImgUrlDefault=&bgImgUrlContent=&bgImgUrlActive=&opacityFilterShadow=Alpha(Opacity%3D30)&opacityFilterOverlay=Alpha(Opacity%3D30)&opacityShadowPerc=30&opacityOverlayPerc=30&iconColorHover=%23555555&iconColorHighlight=%23777620&iconColorHeader=%23444444&iconColorError=%23cc0000&iconColorDefault=%23777777&iconColorContent=%23444444&iconColorActive=%23ffffff&bgImgOpacityShadow=0&bgImgOpacityOverlay=0&bgImgOpacityError=95&bgImgOpacityHighlight=55&bgImgOpacityContent=75&bgImgOpacityHeader=75&bgImgOpacityActive=65&bgImgOpacityHover=75&bgImgOpacityDefault=75&bgTextureShadow=flat&bgTextureOverlay=flat&bgTextureError=flat&bgTextureHighlight=flat&bgTextureContent=flat&bgTextureHeader=flat&bgTextureActive=flat&bgTextureHover=flat&bgTextureDefault=flat&cornerRadius=3px&fwDefault=normal&ffDefault=Arial%2CHelvetica%2Csans-serif&fsDefault=1em&cornerRadiusShadow=8px&thicknessShadow=5px&offsetLeftShadow=0px&offsetTopShadow=0px&opacityShadow=.3&bgColorShadow=%23666666&opacityOverlay=.3&bgColorOverlay=%23aaaaaa&fcError=%235f3f3f&borderColorError=%23f1a899&bgColorError=%23fddfdf&fcHighlight=%23777620&borderColorHighlight=%23dad55e&bgColorHighlight=%23fffa90&fcContent=%23333333&borderColorContent=%23dddddd&bgColorContent=%23ffffff&fcHeader=%23333333&borderColorHeader=%23dddddd&bgColorHeader=%23e9e9e9&fcActive=%23ffffff&borderColorActive=%23003eff&bgColorActive=%23007fff&fcHover=%232b2b2b&borderColorHover=%23cccccc&bgColorHover=%23ededed&fcDefault=%23454545&borderColorDefault=%23c5c5c5&bgColorDefault=%23f6f6f6 -* Copyright jQuery Foundation and other contributors; Licensed MIT */ - -.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important;pointer-events:none}.ui-icon{display:inline-block;vertical-align:middle;margin-top:-.25em;position:relative;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-icon-block{left:50%;margin-left:-8px;display:block}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-accordion .ui-accordion-header{display:block;cursor:pointer;position:relative;margin:2px 0 0 0;padding:.5em .5em .5em .7em;font-size:100%}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;overflow:auto}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-menu{list-style:none;padding:0;margin:0;display:block;outline:0}.ui-menu .ui-menu{position:absolute}.ui-menu .ui-menu-item{margin:0;cursor:pointer;list-style-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7")}.ui-menu .ui-menu-item-wrapper{position:relative;padding:3px 1em 3px .4em}.ui-menu .ui-menu-divider{margin:5px 0;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-state-focus,.ui-menu .ui-state-active{margin:-1px}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item-wrapper{padding-left:2em}.ui-menu .ui-icon{position:absolute;top:0;bottom:0;left:.2em;margin:auto 0}.ui-menu .ui-menu-icon{left:auto;right:0}.ui-button{padding:.4em 1em;display:inline-block;position:relative;line-height:normal;margin-right:.1em;cursor:pointer;vertical-align:middle;text-align:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;overflow:visible}.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none}.ui-button-icon-only{width:2em;box-sizing:border-box;text-indent:-9999px;white-space:nowrap}input.ui-button.ui-button-icon-only{text-indent:0}.ui-button-icon-only .ui-icon{position:absolute;top:50%;left:50%;margin-top:-8px;margin-left:-8px}.ui-button.ui-icon-notext .ui-icon{padding:0;width:2.1em;height:2.1em;text-indent:-9999px;white-space:nowrap}input.ui-button.ui-icon-notext .ui-icon{width:auto;height:auto;text-indent:0;white-space:normal;padding:.4em 1em}input.ui-button::-moz-focus-inner,button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-controlgroup{vertical-align:middle;display:inline-block}.ui-controlgroup > .ui-controlgroup-item{float:left;margin-left:0;margin-right:0}.ui-controlgroup > .ui-controlgroup-item:focus,.ui-controlgroup > .ui-controlgroup-item.ui-visual-focus{z-index:9999}.ui-controlgroup-vertical > .ui-controlgroup-item{display:block;float:none;width:100%;margin-top:0;margin-bottom:0;text-align:left}.ui-controlgroup-vertical .ui-controlgroup-item{box-sizing:border-box}.ui-controlgroup .ui-controlgroup-label{padding:.4em 1em}.ui-controlgroup .ui-controlgroup-label span{font-size:80%}.ui-controlgroup-horizontal .ui-controlgroup-label + .ui-controlgroup-item{border-left:none}.ui-controlgroup-vertical .ui-controlgroup-label + .ui-controlgroup-item{border-top:none}.ui-controlgroup-horizontal .ui-controlgroup-label.ui-widget-content{border-right:none}.ui-controlgroup-vertical .ui-controlgroup-label.ui-widget-content{border-bottom:none}.ui-controlgroup-vertical .ui-spinner-input{width:75%;width:calc( 100% - 2.4em )}.ui-controlgroup-vertical .ui-spinner .ui-spinner-up{border-top-style:solid}.ui-checkboxradio-label .ui-icon-background{box-shadow:inset 1px 1px 1px #ccc;border-radius:.12em;border:none}.ui-checkboxradio-radio-label .ui-icon-background{width:16px;height:16px;border-radius:1em;overflow:visible;border:none}.ui-checkboxradio-radio-label.ui-checkboxradio-checked .ui-icon,.ui-checkboxradio-radio-label.ui-checkboxradio-checked:hover .ui-icon{background-image:none;width:8px;height:8px;border-width:4px;border-style:solid}.ui-checkboxradio-disabled{pointer-events:none}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:45%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:bold;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-datepicker .ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat;left:.5em;top:.3em}.ui-dialog{position:absolute;top:0;left:0;padding:.2em;outline:0}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 0;white-space:nowrap;width:90%;overflow:hidden;text-overflow:ellipsis}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:20px;margin:-10px 0 0 0;padding:1px;height:20px}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:none;overflow:auto}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0 0;background-image:none;margin-top:.5em;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-n{height:2px;top:0}.ui-dialog .ui-resizable-e{width:2px;right:0}.ui-dialog .ui-resizable-s{height:2px;bottom:0}.ui-dialog .ui-resizable-w{width:2px;left:0}.ui-dialog .ui-resizable-se,.ui-dialog .ui-resizable-sw,.ui-dialog .ui-resizable-ne,.ui-dialog .ui-resizable-nw{width:7px;height:7px}.ui-dialog .ui-resizable-se{right:0;bottom:0}.ui-dialog .ui-resizable-sw{left:0;bottom:0}.ui-dialog .ui-resizable-ne{right:0;top:0}.ui-dialog .ui-resizable-nw{left:0;top:0}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-draggable-handle{-ms-touch-action:none;touch-action:none}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display:block;-ms-touch-action:none;touch-action:none}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.ui-progressbar .ui-progressbar-overlay{background:url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==");height:100%;filter:alpha(opacity=25);opacity:0.25}.ui-progressbar-indeterminate .ui-progressbar-value{background-image:none}.ui-selectable{-ms-touch-action:none;touch-action:none}.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted black}.ui-selectmenu-menu{padding:0;margin:0;position:absolute;top:0;left:0;display:none}.ui-selectmenu-menu .ui-menu{overflow:auto;overflow-x:hidden;padding-bottom:1px}.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup{font-size:1em;font-weight:bold;line-height:1.5;padding:2px 0.4em;margin:0.5em 0 0 0;height:auto;border:0}.ui-selectmenu-open{display:block}.ui-selectmenu-text{display:block;margin-right:20px;overflow:hidden;text-overflow:ellipsis}.ui-selectmenu-button.ui-button{text-align:left;white-space:nowrap;width:14em}.ui-selectmenu-icon.ui-icon{float:right;margin-top:0}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default;-ms-touch-action:none;touch-action:none}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider.ui-state-disabled .ui-slider-handle,.ui-slider.ui-state-disabled .ui-slider-range{filter:inherit}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-sortable-handle{-ms-touch-action:none;touch-action:none}.ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle}.ui-spinner-input{border:none;background:none;color:inherit;padding:.222em 0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:2em}.ui-spinner-button{width:1.6em;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0}.ui-spinner a.ui-spinner-button{border-top-style:none;border-bottom-style:none;border-right-style:none}.ui-spinner-up{top:0}.ui-spinner-down{bottom:0}.ui-tabs{position:relative;padding:.2em}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom-width:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav .ui-tabs-anchor{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor{cursor:text}.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:none}.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px}body .ui-tooltip{border-width:2px}.ui-widget{font-family:Arial,Helvetica,sans-serif;font-size:1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Arial,Helvetica,sans-serif;font-size:1em}.ui-widget.ui-widget-content{border:1px solid #c5c5c5}.ui-widget-content{border:1px solid #ddd;background:#fff;color:#333}.ui-widget-content a{color:#333}.ui-widget-header{border:1px solid #ddd;background:#e9e9e9;color:#333;font-weight:bold}.ui-widget-header a{color:#333}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default,.ui-button,html .ui-button.ui-state-disabled:hover,html .ui-button.ui-state-disabled:active{border:1px solid #c5c5c5;background:#f6f6f6;font-weight:normal;color:#454545}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited,a.ui-button,a:link.ui-button,a:visited.ui-button,.ui-button{color:#454545;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus,.ui-button:hover,.ui-button:focus{border:1px solid #ccc;background:#ededed;font-weight:normal;color:#2b2b2b}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited,a.ui-button:hover,a.ui-button:focus{color:#2b2b2b;text-decoration:none}.ui-visual-focus{box-shadow:0 0 3px 1px rgb(94,158,214)}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active,a.ui-button:active,.ui-button:active,.ui-button.ui-state-active:hover{border:1px solid #003eff;background:#007fff;font-weight:normal;color:#fff}.ui-icon-background,.ui-state-active .ui-icon-background{border:#003eff;background-color:#fff}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#fff;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #dad55e;background:#fffa90;color:#777620}.ui-state-checked{border:1px solid #dad55e;background:#fffa90}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#777620}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #f1a899;background:#fddfdf;color:#5f3f3f}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#5f3f3f}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#5f3f3f}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url("images/ui-icons_444444_256x240.png")}.ui-widget-header .ui-icon{background-image:url("images/ui-icons_444444_256x240.png")}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon,.ui-button:hover .ui-icon,.ui-button:focus .ui-icon{background-image:url("images/ui-icons_555555_256x240.png")}.ui-state-active .ui-icon,.ui-button:active .ui-icon{background-image:url("images/ui-icons_ffffff_256x240.png")}.ui-state-highlight .ui-icon,.ui-button .ui-state-highlight.ui-icon{background-image:url("images/ui-icons_777620_256x240.png")}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url("images/ui-icons_cc0000_256x240.png")}.ui-button .ui-icon{background-image:url("images/ui-icons_777777_256x240.png")}.ui-icon-blank{background-position:16px 16px}.ui-icon-caret-1-n{background-position:0 0}.ui-icon-caret-1-ne{background-position:-16px 0}.ui-icon-caret-1-e{background-position:-32px 0}.ui-icon-caret-1-se{background-position:-48px 0}.ui-icon-caret-1-s{background-position:-65px 0}.ui-icon-caret-1-sw{background-position:-80px 0}.ui-icon-caret-1-w{background-position:-96px 0}.ui-icon-caret-1-nw{background-position:-112px 0}.ui-icon-caret-2-n-s{background-position:-128px 0}.ui-icon-caret-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-65px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-65px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:1px -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:3px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:3px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:3px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:3px}.ui-widget-overlay{background:#aaa;opacity:.003;filter:Alpha(Opacity=.3)}.ui-widget-shadow{-webkit-box-shadow:0 0 5px #666;box-shadow:0 0 5px #666} \ No newline at end of file diff --git a/website/agenda/planung/css/jquery-ui.structure.css b/website/agenda/planung/css/jquery-ui.structure.css deleted file mode 100644 index 8184e15..0000000 --- a/website/agenda/planung/css/jquery-ui.structure.css +++ /dev/null @@ -1,833 +0,0 @@ -/*! - * jQuery UI CSS Framework 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/category/theming/ - */ - -/* Layout helpers -----------------------------------*/ -.ui-helper-hidden { - display: none; -} -.ui-helper-hidden-accessible { - border: 0; - clip: rect(0 0 0 0); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - width: 1px; -} -.ui-helper-reset { - margin: 0; - padding: 0; - border: 0; - outline: 0; - line-height: 1.3; - text-decoration: none; - font-size: 100%; - list-style: none; -} -.ui-helper-clearfix:before, -.ui-helper-clearfix:after { - content: ""; - display: table; - border-collapse: collapse; -} -.ui-helper-clearfix:after { - clear: both; -} -.ui-helper-clearfix { - min-height: 0; /* support: IE7 */ -} -.ui-helper-zfix { - width: 100%; - height: 100%; - top: 0; - left: 0; - position: absolute; - opacity: 0; - filter:Alpha(Opacity=0); /* support: IE8 */ -} - -.ui-front { - z-index: 100; -} - - -/* Interaction Cues -----------------------------------*/ -.ui-state-disabled { - cursor: default !important; -} - - -/* Icons -----------------------------------*/ - -/* states and images */ -.ui-icon { - display: block; - text-indent: -99999px; - overflow: hidden; - background-repeat: no-repeat; -} - - -/* Misc visuals -----------------------------------*/ - -/* Overlays */ -.ui-widget-overlay { - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; -} -.ui-draggable-handle { - -ms-touch-action: none; - touch-action: none; -} -.ui-resizable { - position: relative; -} -.ui-resizable-handle { - position: absolute; - font-size: 0.1px; - display: block; - -ms-touch-action: none; - touch-action: none; -} -.ui-resizable-disabled .ui-resizable-handle, -.ui-resizable-autohide .ui-resizable-handle { - display: none; -} -.ui-resizable-n { - cursor: n-resize; - height: 7px; - width: 100%; - top: -5px; - left: 0; -} -.ui-resizable-s { - cursor: s-resize; - height: 7px; - width: 100%; - bottom: -5px; - left: 0; -} -.ui-resizable-e { - cursor: e-resize; - width: 7px; - right: -5px; - top: 0; - height: 100%; -} -.ui-resizable-w { - cursor: w-resize; - width: 7px; - left: -5px; - top: 0; - height: 100%; -} -.ui-resizable-se { - cursor: se-resize; - width: 12px; - height: 12px; - right: 1px; - bottom: 1px; -} -.ui-resizable-sw { - cursor: sw-resize; - width: 9px; - height: 9px; - left: -5px; - bottom: -5px; -} -.ui-resizable-nw { - cursor: nw-resize; - width: 9px; - height: 9px; - left: -5px; - top: -5px; -} -.ui-resizable-ne { - cursor: ne-resize; - width: 9px; - height: 9px; - right: -5px; - top: -5px; -} -.ui-selectable { - -ms-touch-action: none; - touch-action: none; -} -.ui-selectable-helper { - position: absolute; - z-index: 100; - border: 1px dotted black; -} -.ui-sortable-handle { - -ms-touch-action: none; - touch-action: none; -} -.ui-accordion .ui-accordion-header { - display: block; - cursor: pointer; - position: relative; - margin: 2px 0 0 0; - padding: .5em .5em .5em .7em; - min-height: 0; /* support: IE7 */ - font-size: 100%; -} -.ui-accordion .ui-accordion-icons { - padding-left: 2.2em; -} -.ui-accordion .ui-accordion-icons .ui-accordion-icons { - padding-left: 2.2em; -} -.ui-accordion .ui-accordion-header .ui-accordion-header-icon { - position: absolute; - left: .5em; - top: 50%; - margin-top: -8px; -} -.ui-accordion .ui-accordion-content { - padding: 1em 2.2em; - border-top: 0; - overflow: auto; -} -.ui-autocomplete { - position: absolute; - top: 0; - left: 0; - cursor: default; -} -.ui-button { - display: inline-block; - position: relative; - padding: 0; - line-height: normal; - margin-right: .1em; - cursor: pointer; - vertical-align: middle; - text-align: center; - overflow: visible; /* removes extra width in IE */ -} -.ui-button, -.ui-button:link, -.ui-button:visited, -.ui-button:hover, -.ui-button:active { - text-decoration: none; -} -/* to make room for the icon, a width needs to be set here */ -.ui-button-icon-only { - width: 2.2em; -} -/* button elements seem to need a little more width */ -button.ui-button-icon-only { - width: 2.4em; -} -.ui-button-icons-only { - width: 3.4em; -} -button.ui-button-icons-only { - width: 3.7em; -} - -/* button text element */ -.ui-button .ui-button-text { - display: block; - line-height: normal; -} -.ui-button-text-only .ui-button-text { - padding: .4em 1em; -} -.ui-button-icon-only .ui-button-text, -.ui-button-icons-only .ui-button-text { - padding: .4em; - text-indent: -9999999px; -} -.ui-button-text-icon-primary .ui-button-text, -.ui-button-text-icons .ui-button-text { - padding: .4em 1em .4em 2.1em; -} -.ui-button-text-icon-secondary .ui-button-text, -.ui-button-text-icons .ui-button-text { - padding: .4em 2.1em .4em 1em; -} -.ui-button-text-icons .ui-button-text { - padding-left: 2.1em; - padding-right: 2.1em; -} -/* no icon support for input elements, provide padding by default */ -input.ui-button { - padding: .4em 1em; -} - -/* button icon element(s) */ -.ui-button-icon-only .ui-icon, -.ui-button-text-icon-primary .ui-icon, -.ui-button-text-icon-secondary .ui-icon, -.ui-button-text-icons .ui-icon, -.ui-button-icons-only .ui-icon { - position: absolute; - top: 50%; - margin-top: -8px; -} -.ui-button-icon-only .ui-icon { - left: 50%; - margin-left: -8px; -} -.ui-button-text-icon-primary .ui-button-icon-primary, -.ui-button-text-icons .ui-button-icon-primary, -.ui-button-icons-only .ui-button-icon-primary { - left: .5em; -} -.ui-button-text-icon-secondary .ui-button-icon-secondary, -.ui-button-text-icons .ui-button-icon-secondary, -.ui-button-icons-only .ui-button-icon-secondary { - right: .5em; -} - -/* button sets */ -.ui-buttonset { - margin-right: 7px; -} -.ui-buttonset .ui-button { - margin-left: 0; - margin-right: -.3em; -} - -/* workarounds */ -/* reset extra padding in Firefox, see h5bp.com/l */ -input.ui-button::-moz-focus-inner, -button.ui-button::-moz-focus-inner { - border: 0; - padding: 0; -} -.ui-datepicker { - width: 17em; - padding: .2em .2em 0; - display: none; -} -.ui-datepicker .ui-datepicker-header { - position: relative; - padding: .2em 0; -} -.ui-datepicker .ui-datepicker-prev, -.ui-datepicker .ui-datepicker-next { - position: absolute; - top: 2px; - width: 1.8em; - height: 1.8em; -} -.ui-datepicker .ui-datepicker-prev-hover, -.ui-datepicker .ui-datepicker-next-hover { - top: 1px; -} -.ui-datepicker .ui-datepicker-prev { - left: 2px; -} -.ui-datepicker .ui-datepicker-next { - right: 2px; -} -.ui-datepicker .ui-datepicker-prev-hover { - left: 1px; -} -.ui-datepicker .ui-datepicker-next-hover { - right: 1px; -} -.ui-datepicker .ui-datepicker-prev span, -.ui-datepicker .ui-datepicker-next span { - display: block; - position: absolute; - left: 50%; - margin-left: -8px; - top: 50%; - margin-top: -8px; -} -.ui-datepicker .ui-datepicker-title { - margin: 0 2.3em; - line-height: 1.8em; - text-align: center; -} -.ui-datepicker .ui-datepicker-title select { - font-size: 1em; - margin: 1px 0; -} -.ui-datepicker select.ui-datepicker-month, -.ui-datepicker select.ui-datepicker-year { - width: 45%; -} -.ui-datepicker table { - width: 100%; - font-size: .9em; - border-collapse: collapse; - margin: 0 0 .4em; -} -.ui-datepicker th { - padding: .7em .3em; - text-align: center; - font-weight: bold; - border: 0; -} -.ui-datepicker td { - border: 0; - padding: 1px; -} -.ui-datepicker td span, -.ui-datepicker td a { - display: block; - padding: .2em; - text-align: right; - text-decoration: none; -} -.ui-datepicker .ui-datepicker-buttonpane { - background-image: none; - margin: .7em 0 0 0; - padding: 0 .2em; - border-left: 0; - border-right: 0; - border-bottom: 0; -} -.ui-datepicker .ui-datepicker-buttonpane button { - float: right; - margin: .5em .2em .4em; - cursor: pointer; - padding: .2em .6em .3em .6em; - width: auto; - overflow: visible; -} -.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { - float: left; -} - -/* with multiple calendars */ -.ui-datepicker.ui-datepicker-multi { - width: auto; -} -.ui-datepicker-multi .ui-datepicker-group { - float: left; -} -.ui-datepicker-multi .ui-datepicker-group table { - width: 95%; - margin: 0 auto .4em; -} -.ui-datepicker-multi-2 .ui-datepicker-group { - width: 50%; -} -.ui-datepicker-multi-3 .ui-datepicker-group { - width: 33.3%; -} -.ui-datepicker-multi-4 .ui-datepicker-group { - width: 25%; -} -.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header, -.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { - border-left-width: 0; -} -.ui-datepicker-multi .ui-datepicker-buttonpane { - clear: left; -} -.ui-datepicker-row-break { - clear: both; - width: 100%; - font-size: 0; -} - -/* RTL support */ -.ui-datepicker-rtl { - direction: rtl; -} -.ui-datepicker-rtl .ui-datepicker-prev { - right: 2px; - left: auto; -} -.ui-datepicker-rtl .ui-datepicker-next { - left: 2px; - right: auto; -} -.ui-datepicker-rtl .ui-datepicker-prev:hover { - right: 1px; - left: auto; -} -.ui-datepicker-rtl .ui-datepicker-next:hover { - left: 1px; - right: auto; -} -.ui-datepicker-rtl .ui-datepicker-buttonpane { - clear: right; -} -.ui-datepicker-rtl .ui-datepicker-buttonpane button { - float: left; -} -.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current, -.ui-datepicker-rtl .ui-datepicker-group { - float: right; -} -.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header, -.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { - border-right-width: 0; - border-left-width: 1px; -} -.ui-dialog { - overflow: hidden; - position: absolute; - top: 0; - left: 0; - padding: .2em; - outline: 0; -} -.ui-dialog .ui-dialog-titlebar { - padding: .4em 1em; - position: relative; -} -.ui-dialog .ui-dialog-title { - float: left; - margin: .1em 0; - white-space: nowrap; - width: 90%; - overflow: hidden; - text-overflow: ellipsis; -} -.ui-dialog .ui-dialog-titlebar-close { - position: absolute; - right: .3em; - top: 50%; - width: 20px; - margin: -10px 0 0 0; - padding: 1px; - height: 20px; -} -.ui-dialog .ui-dialog-content { - position: relative; - border: 0; - padding: .5em 1em; - background: none; - overflow: auto; -} -.ui-dialog .ui-dialog-buttonpane { - text-align: left; - border-width: 1px 0 0 0; - background-image: none; - margin-top: .5em; - padding: .3em 1em .5em .4em; -} -.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { - float: right; -} -.ui-dialog .ui-dialog-buttonpane button { - margin: .5em .4em .5em 0; - cursor: pointer; -} -.ui-dialog .ui-resizable-se { - width: 12px; - height: 12px; - right: -5px; - bottom: -5px; - background-position: 16px 16px; -} -.ui-draggable .ui-dialog-titlebar { - cursor: move; -} -.ui-menu { - list-style: none; - padding: 0; - margin: 0; - display: block; - outline: none; -} -.ui-menu .ui-menu { - position: absolute; -} -.ui-menu .ui-menu-item { - position: relative; - margin: 0; - padding: 3px 1em 3px .4em; - cursor: pointer; - min-height: 0; /* support: IE7 */ - /* support: IE10, see #8844 */ - list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"); -} -.ui-menu .ui-menu-divider { - margin: 5px 0; - height: 0; - font-size: 0; - line-height: 0; - border-width: 1px 0 0 0; -} -.ui-menu .ui-state-focus, -.ui-menu .ui-state-active { - margin: -1px; -} - -/* icon support */ -.ui-menu-icons { - position: relative; -} -.ui-menu-icons .ui-menu-item { - padding-left: 2em; -} - -/* left-aligned */ -.ui-menu .ui-icon { - position: absolute; - top: 0; - bottom: 0; - left: .2em; - margin: auto 0; -} - -/* right-aligned */ -.ui-menu .ui-menu-icon { - left: auto; - right: 0; -} -.ui-progressbar { - height: 2em; - text-align: left; - overflow: hidden; -} -.ui-progressbar .ui-progressbar-value { - margin: -1px; - height: 100%; -} -.ui-progressbar .ui-progressbar-overlay { - background: url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw=="); - height: 100%; - filter: alpha(opacity=25); /* support: IE8 */ - opacity: 0.25; -} -.ui-progressbar-indeterminate .ui-progressbar-value { - background-image: none; -} -.ui-selectmenu-menu { - padding: 0; - margin: 0; - position: absolute; - top: 0; - left: 0; - display: none; -} -.ui-selectmenu-menu .ui-menu { - overflow: auto; - /* Support: IE7 */ - overflow-x: hidden; - padding-bottom: 1px; -} -.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup { - font-size: 1em; - font-weight: bold; - line-height: 1.5; - padding: 2px 0.4em; - margin: 0.5em 0 0 0; - height: auto; - border: 0; -} -.ui-selectmenu-open { - display: block; -} -.ui-selectmenu-button { - display: inline-block; - overflow: hidden; - position: relative; - text-decoration: none; - cursor: pointer; -} -.ui-selectmenu-button span.ui-icon { - right: 0.5em; - left: auto; - margin-top: -8px; - position: absolute; - top: 50%; -} -.ui-selectmenu-button span.ui-selectmenu-text { - text-align: left; - padding: 0.4em 2.1em 0.4em 1em; - display: block; - line-height: 1.4; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} -.ui-slider { - position: relative; - text-align: left; -} -.ui-slider .ui-slider-handle { - position: absolute; - z-index: 2; - width: 1.2em; - height: 1.2em; - cursor: default; - -ms-touch-action: none; - touch-action: none; -} -.ui-slider .ui-slider-range { - position: absolute; - z-index: 1; - font-size: .7em; - display: block; - border: 0; - background-position: 0 0; -} - -/* support: IE8 - See #6727 */ -.ui-slider.ui-state-disabled .ui-slider-handle, -.ui-slider.ui-state-disabled .ui-slider-range { - filter: inherit; -} - -.ui-slider-horizontal { - height: .8em; -} -.ui-slider-horizontal .ui-slider-handle { - top: -.3em; - margin-left: -.6em; -} -.ui-slider-horizontal .ui-slider-range { - top: 0; - height: 100%; -} -.ui-slider-horizontal .ui-slider-range-min { - left: 0; -} -.ui-slider-horizontal .ui-slider-range-max { - right: 0; -} - -.ui-slider-vertical { - width: .8em; - height: 100px; -} -.ui-slider-vertical .ui-slider-handle { - left: -.3em; - margin-left: 0; - margin-bottom: -.6em; -} -.ui-slider-vertical .ui-slider-range { - left: 0; - width: 100%; -} -.ui-slider-vertical .ui-slider-range-min { - bottom: 0; -} -.ui-slider-vertical .ui-slider-range-max { - top: 0; -} -.ui-spinner { - position: relative; - display: inline-block; - overflow: hidden; - padding: 0; - vertical-align: middle; -} -.ui-spinner-input { - border: none; - background: none; - color: inherit; - padding: 0; - margin: .2em 0; - vertical-align: middle; - margin-left: .4em; - margin-right: 22px; -} -.ui-spinner-button { - width: 16px; - height: 50%; - font-size: .5em; - padding: 0; - margin: 0; - text-align: center; - position: absolute; - cursor: default; - display: block; - overflow: hidden; - right: 0; -} -/* more specificity required here to override default borders */ -.ui-spinner a.ui-spinner-button { - border-top: none; - border-bottom: none; - border-right: none; -} -/* vertically center icon */ -.ui-spinner .ui-icon { - position: absolute; - margin-top: -8px; - top: 50%; - left: 0; -} -.ui-spinner-up { - top: 0; -} -.ui-spinner-down { - bottom: 0; -} - -/* TR overrides */ -.ui-spinner .ui-icon-triangle-1-s { - /* need to fix icons sprite */ - background-position: -65px -16px; -} -.ui-tabs { - position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ - padding: .2em; -} -.ui-tabs .ui-tabs-nav { - margin: 0; - padding: .2em .2em 0; -} -.ui-tabs .ui-tabs-nav li { - list-style: none; - float: left; - position: relative; - top: 0; - margin: 1px .2em 0 0; - border-bottom-width: 0; - padding: 0; - white-space: nowrap; -} -.ui-tabs .ui-tabs-nav .ui-tabs-anchor { - float: left; - padding: .5em 1em; - text-decoration: none; -} -.ui-tabs .ui-tabs-nav li.ui-tabs-active { - margin-bottom: -1px; - padding-bottom: 1px; -} -.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor, -.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor, -.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor { - cursor: text; -} -.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor { - cursor: pointer; -} -.ui-tabs .ui-tabs-panel { - display: block; - border-width: 0; - padding: 1em 1.4em; - background: none; -} -.ui-tooltip { - padding: 8px; - position: absolute; - z-index: 9999; - max-width: 300px; - -webkit-box-shadow: 0 0 5px #aaa; - box-shadow: 0 0 5px #aaa; -} -body .ui-tooltip { - border-width: 2px; -} diff --git a/website/agenda/planung/css/jquery-ui.structure.min.css b/website/agenda/planung/css/jquery-ui.structure.min.css deleted file mode 100644 index eeba7d2..0000000 --- a/website/agenda/planung/css/jquery-ui.structure.min.css +++ /dev/null @@ -1,5 +0,0 @@ -/*! jQuery UI - v1.11.4 - 2016-01-24 -* http://jqueryui.com -* Copyright jQuery Foundation and other contributors; Licensed MIT */ - -.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-draggable-handle{-ms-touch-action:none;touch-action:none}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display:block;-ms-touch-action:none;touch-action:none}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-selectable{-ms-touch-action:none;touch-action:none}.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted black}.ui-sortable-handle{-ms-touch-action:none;touch-action:none}.ui-accordion .ui-accordion-header{display:block;cursor:pointer;position:relative;margin:2px 0 0 0;padding:.5em .5em .5em .7em;min-height:0;font-size:100%}.ui-accordion .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-icons .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-header .ui-accordion-header-icon{position:absolute;left:.5em;top:50%;margin-top:-8px}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;overflow:auto}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-button{display:inline-block;position:relative;padding:0;line-height:normal;margin-right:.1em;cursor:pointer;vertical-align:middle;text-align:center;overflow:visible}.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none}.ui-button-icon-only{width:2.2em}button.ui-button-icon-only{width:2.4em}.ui-button-icons-only{width:3.4em}button.ui-button-icons-only{width:3.7em}.ui-button .ui-button-text{display:block;line-height:normal}.ui-button-text-only .ui-button-text{padding:.4em 1em}.ui-button-icon-only .ui-button-text,.ui-button-icons-only .ui-button-text{padding:.4em;text-indent:-9999999px}.ui-button-text-icon-primary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 1em .4em 2.1em}.ui-button-text-icon-secondary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 2.1em .4em 1em}.ui-button-text-icons .ui-button-text{padding-left:2.1em;padding-right:2.1em}input.ui-button{padding:.4em 1em}.ui-button-icon-only .ui-icon,.ui-button-text-icon-primary .ui-icon,.ui-button-text-icon-secondary .ui-icon,.ui-button-text-icons .ui-icon,.ui-button-icons-only .ui-icon{position:absolute;top:50%;margin-top:-8px}.ui-button-icon-only .ui-icon{left:50%;margin-left:-8px}.ui-button-text-icon-primary .ui-button-icon-primary,.ui-button-text-icons .ui-button-icon-primary,.ui-button-icons-only .ui-button-icon-primary{left:.5em}.ui-button-text-icon-secondary .ui-button-icon-secondary,.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em}.ui-buttonset{margin-right:7px}.ui-buttonset .ui-button{margin-left:0;margin-right:-.3em}input.ui-button::-moz-focus-inner,button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:45%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:bold;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-dialog{overflow:hidden;position:absolute;top:0;left:0;padding:.2em;outline:0}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 0;white-space:nowrap;width:90%;overflow:hidden;text-overflow:ellipsis}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:20px;margin:-10px 0 0 0;padding:1px;height:20px}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:none;overflow:auto}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0 0;background-image:none;margin-top:.5em;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-se{width:12px;height:12px;right:-5px;bottom:-5px;background-position:16px 16px}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-menu{list-style:none;padding:0;margin:0;display:block;outline:none}.ui-menu .ui-menu{position:absolute}.ui-menu .ui-menu-item{position:relative;margin:0;padding:3px 1em 3px .4em;cursor:pointer;min-height:0;list-style-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7")}.ui-menu .ui-menu-divider{margin:5px 0;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-state-focus,.ui-menu .ui-state-active{margin:-1px}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item{padding-left:2em}.ui-menu .ui-icon{position:absolute;top:0;bottom:0;left:.2em;margin:auto 0}.ui-menu .ui-menu-icon{left:auto;right:0}.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.ui-progressbar .ui-progressbar-overlay{background:url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==");height:100%;filter:alpha(opacity=25);opacity:0.25}.ui-progressbar-indeterminate .ui-progressbar-value{background-image:none}.ui-selectmenu-menu{padding:0;margin:0;position:absolute;top:0;left:0;display:none}.ui-selectmenu-menu .ui-menu{overflow:auto;overflow-x:hidden;padding-bottom:1px}.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup{font-size:1em;font-weight:bold;line-height:1.5;padding:2px 0.4em;margin:0.5em 0 0 0;height:auto;border:0}.ui-selectmenu-open{display:block}.ui-selectmenu-button{display:inline-block;overflow:hidden;position:relative;text-decoration:none;cursor:pointer}.ui-selectmenu-button span.ui-icon{right:0.5em;left:auto;margin-top:-8px;position:absolute;top:50%}.ui-selectmenu-button span.ui-selectmenu-text{text-align:left;padding:0.4em 2.1em 0.4em 1em;display:block;line-height:1.4;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default;-ms-touch-action:none;touch-action:none}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider.ui-state-disabled .ui-slider-handle,.ui-slider.ui-state-disabled .ui-slider-range{filter:inherit}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle}.ui-spinner-input{border:none;background:none;color:inherit;padding:0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:22px}.ui-spinner-button{width:16px;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0}.ui-spinner a.ui-spinner-button{border-top:none;border-bottom:none;border-right:none}.ui-spinner .ui-icon{position:absolute;margin-top:-8px;top:50%;left:0}.ui-spinner-up{top:0}.ui-spinner-down{bottom:0}.ui-spinner .ui-icon-triangle-1-s{background-position:-65px -16px}.ui-tabs{position:relative;padding:.2em}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom-width:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav .ui-tabs-anchor{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor{cursor:text}.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:none}.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px;-webkit-box-shadow:0 0 5px #aaa;box-shadow:0 0 5px #aaa}body .ui-tooltip{border-width:2px} \ No newline at end of file diff --git a/website/agenda/planung/css/jquery-ui.theme.css b/website/agenda/planung/css/jquery-ui.theme.css deleted file mode 100644 index add09e1..0000000 --- a/website/agenda/planung/css/jquery-ui.theme.css +++ /dev/null @@ -1,410 +0,0 @@ -/*! - * jQuery UI CSS Framework 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/category/theming/ - * - * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2CArial%2Csans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=highlight_soft&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=flat&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=glass&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=glass&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px - */ - - -/* Component containers -----------------------------------*/ -.ui-widget { - font-family: Verdana,Arial,sans-serif; - font-size: 1.1em; -} -.ui-widget .ui-widget { - font-size: 1em; -} -.ui-widget input, -.ui-widget select, -.ui-widget textarea, -.ui-widget button { - font-family: Verdana,Arial,sans-serif; - font-size: 1em; -} -.ui-widget-content { - border: 1px solid #aaaaaa; - background: #ffffff; - color: #222222; -} -.ui-widget-content a { - color: #222222; -} -.ui-widget-header { - border: 1px solid #aaaaaa; - background: #cccccc url("images/ui-bg_highlight-soft_75_cccccc_1x100.png") 50% 50% repeat-x; - color: #222222; - font-weight: bold; -} -.ui-widget-header a { - color: #222222; -} - -/* Interaction states -----------------------------------*/ -.ui-state-default, -.ui-widget-content .ui-state-default, -.ui-widget-header .ui-state-default { - border: 1px solid #d3d3d3; - background: #e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x; - font-weight: normal; - color: #555555; -} -.ui-state-default a, -.ui-state-default a:link, -.ui-state-default a:visited { - color: #555555; - text-decoration: none; -} -.ui-state-hover, -.ui-widget-content .ui-state-hover, -.ui-widget-header .ui-state-hover, -.ui-state-focus, -.ui-widget-content .ui-state-focus, -.ui-widget-header .ui-state-focus { - border: 1px solid #999999; - background: #dadada url("images/ui-bg_glass_75_dadada_1x400.png") 50% 50% repeat-x; - font-weight: normal; - color: #212121; -} -.ui-state-hover a, -.ui-state-hover a:hover, -.ui-state-hover a:link, -.ui-state-hover a:visited, -.ui-state-focus a, -.ui-state-focus a:hover, -.ui-state-focus a:link, -.ui-state-focus a:visited { - color: #212121; - text-decoration: none; -} -.ui-state-active, -.ui-widget-content .ui-state-active, -.ui-widget-header .ui-state-active { - border: 1px solid #aaaaaa; - background: #ffffff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x; - font-weight: normal; - color: #212121; -} -.ui-state-active a, -.ui-state-active a:link, -.ui-state-active a:visited { - color: #212121; - text-decoration: none; -} - -/* Interaction Cues -----------------------------------*/ -.ui-state-highlight, -.ui-widget-content .ui-state-highlight, -.ui-widget-header .ui-state-highlight { - border: 1px solid #fcefa1; - background: #fbf9ee url("images/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x; - color: #363636; -} -.ui-state-highlight a, -.ui-widget-content .ui-state-highlight a, -.ui-widget-header .ui-state-highlight a { - color: #363636; -} -.ui-state-error, -.ui-widget-content .ui-state-error, -.ui-widget-header .ui-state-error { - border: 1px solid #cd0a0a; - background: #fef1ec url("images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x; - color: #cd0a0a; -} -.ui-state-error a, -.ui-widget-content .ui-state-error a, -.ui-widget-header .ui-state-error a { - color: #cd0a0a; -} -.ui-state-error-text, -.ui-widget-content .ui-state-error-text, -.ui-widget-header .ui-state-error-text { - color: #cd0a0a; -} -.ui-priority-primary, -.ui-widget-content .ui-priority-primary, -.ui-widget-header .ui-priority-primary { - font-weight: bold; -} -.ui-priority-secondary, -.ui-widget-content .ui-priority-secondary, -.ui-widget-header .ui-priority-secondary { - opacity: .7; - filter:Alpha(Opacity=70); /* support: IE8 */ - font-weight: normal; -} -.ui-state-disabled, -.ui-widget-content .ui-state-disabled, -.ui-widget-header .ui-state-disabled { - opacity: .35; - filter:Alpha(Opacity=35); /* support: IE8 */ - background-image: none; -} -.ui-state-disabled .ui-icon { - filter:Alpha(Opacity=35); /* support: IE8 - See #6059 */ -} - -/* Icons -----------------------------------*/ - -/* states and images */ -.ui-icon { - width: 16px; - height: 16px; -} -.ui-icon, -.ui-widget-content .ui-icon { - background-image: url("images/ui-icons_222222_256x240.png"); -} -.ui-widget-header .ui-icon { - background-image: url("images/ui-icons_222222_256x240.png"); -} -.ui-state-default .ui-icon { - background-image: url("images/ui-icons_888888_256x240.png"); -} -.ui-state-hover .ui-icon, -.ui-state-focus .ui-icon { - background-image: url("images/ui-icons_454545_256x240.png"); -} -.ui-state-active .ui-icon { - background-image: url("images/ui-icons_454545_256x240.png"); -} -.ui-state-highlight .ui-icon { - background-image: url("images/ui-icons_2e83ff_256x240.png"); -} -.ui-state-error .ui-icon, -.ui-state-error-text .ui-icon { - background-image: url("images/ui-icons_cd0a0a_256x240.png"); -} - -/* positioning */ -.ui-icon-blank { background-position: 16px 16px; } -.ui-icon-carat-1-n { background-position: 0 0; } -.ui-icon-carat-1-ne { background-position: -16px 0; } -.ui-icon-carat-1-e { background-position: -32px 0; } -.ui-icon-carat-1-se { background-position: -48px 0; } -.ui-icon-carat-1-s { background-position: -64px 0; } -.ui-icon-carat-1-sw { background-position: -80px 0; } -.ui-icon-carat-1-w { background-position: -96px 0; } -.ui-icon-carat-1-nw { background-position: -112px 0; } -.ui-icon-carat-2-n-s { background-position: -128px 0; } -.ui-icon-carat-2-e-w { background-position: -144px 0; } -.ui-icon-triangle-1-n { background-position: 0 -16px; } -.ui-icon-triangle-1-ne { background-position: -16px -16px; } -.ui-icon-triangle-1-e { background-position: -32px -16px; } -.ui-icon-triangle-1-se { background-position: -48px -16px; } -.ui-icon-triangle-1-s { background-position: -64px -16px; } -.ui-icon-triangle-1-sw { background-position: -80px -16px; } -.ui-icon-triangle-1-w { background-position: -96px -16px; } -.ui-icon-triangle-1-nw { background-position: -112px -16px; } -.ui-icon-triangle-2-n-s { background-position: -128px -16px; } -.ui-icon-triangle-2-e-w { background-position: -144px -16px; } -.ui-icon-arrow-1-n { background-position: 0 -32px; } -.ui-icon-arrow-1-ne { background-position: -16px -32px; } -.ui-icon-arrow-1-e { background-position: -32px -32px; } -.ui-icon-arrow-1-se { background-position: -48px -32px; } -.ui-icon-arrow-1-s { background-position: -64px -32px; } -.ui-icon-arrow-1-sw { background-position: -80px -32px; } -.ui-icon-arrow-1-w { background-position: -96px -32px; } -.ui-icon-arrow-1-nw { background-position: -112px -32px; } -.ui-icon-arrow-2-n-s { background-position: -128px -32px; } -.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } -.ui-icon-arrow-2-e-w { background-position: -160px -32px; } -.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } -.ui-icon-arrowstop-1-n { background-position: -192px -32px; } -.ui-icon-arrowstop-1-e { background-position: -208px -32px; } -.ui-icon-arrowstop-1-s { background-position: -224px -32px; } -.ui-icon-arrowstop-1-w { background-position: -240px -32px; } -.ui-icon-arrowthick-1-n { background-position: 0 -48px; } -.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } -.ui-icon-arrowthick-1-e { background-position: -32px -48px; } -.ui-icon-arrowthick-1-se { background-position: -48px -48px; } -.ui-icon-arrowthick-1-s { background-position: -64px -48px; } -.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } -.ui-icon-arrowthick-1-w { background-position: -96px -48px; } -.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } -.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } -.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } -.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } -.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } -.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } -.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } -.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } -.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } -.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } -.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } -.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } -.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } -.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } -.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } -.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } -.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } -.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } -.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } -.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } -.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } -.ui-icon-arrow-4 { background-position: 0 -80px; } -.ui-icon-arrow-4-diag { background-position: -16px -80px; } -.ui-icon-extlink { background-position: -32px -80px; } -.ui-icon-newwin { background-position: -48px -80px; } -.ui-icon-refresh { background-position: -64px -80px; } -.ui-icon-shuffle { background-position: -80px -80px; } -.ui-icon-transfer-e-w { background-position: -96px -80px; } -.ui-icon-transferthick-e-w { background-position: -112px -80px; } -.ui-icon-folder-collapsed { background-position: 0 -96px; } -.ui-icon-folder-open { background-position: -16px -96px; } -.ui-icon-document { background-position: -32px -96px; } -.ui-icon-document-b { background-position: -48px -96px; } -.ui-icon-note { background-position: -64px -96px; } -.ui-icon-mail-closed { background-position: -80px -96px; } -.ui-icon-mail-open { background-position: -96px -96px; } -.ui-icon-suitcase { background-position: -112px -96px; } -.ui-icon-comment { background-position: -128px -96px; } -.ui-icon-person { background-position: -144px -96px; } -.ui-icon-print { background-position: -160px -96px; } -.ui-icon-trash { background-position: -176px -96px; } -.ui-icon-locked { background-position: -192px -96px; } -.ui-icon-unlocked { background-position: -208px -96px; } -.ui-icon-bookmark { background-position: -224px -96px; } -.ui-icon-tag { background-position: -240px -96px; } -.ui-icon-home { background-position: 0 -112px; } -.ui-icon-flag { background-position: -16px -112px; } -.ui-icon-calendar { background-position: -32px -112px; } -.ui-icon-cart { background-position: -48px -112px; } -.ui-icon-pencil { background-position: -64px -112px; } -.ui-icon-clock { background-position: -80px -112px; } -.ui-icon-disk { background-position: -96px -112px; } -.ui-icon-calculator { background-position: -112px -112px; } -.ui-icon-zoomin { background-position: -128px -112px; } -.ui-icon-zoomout { background-position: -144px -112px; } -.ui-icon-search { background-position: -160px -112px; } -.ui-icon-wrench { background-position: -176px -112px; } -.ui-icon-gear { background-position: -192px -112px; } -.ui-icon-heart { background-position: -208px -112px; } -.ui-icon-star { background-position: -224px -112px; } -.ui-icon-link { background-position: -240px -112px; } -.ui-icon-cancel { background-position: 0 -128px; } -.ui-icon-plus { background-position: -16px -128px; } -.ui-icon-plusthick { background-position: -32px -128px; } -.ui-icon-minus { background-position: -48px -128px; } -.ui-icon-minusthick { background-position: -64px -128px; } -.ui-icon-close { background-position: -80px -128px; } -.ui-icon-closethick { background-position: -96px -128px; } -.ui-icon-key { background-position: -112px -128px; } -.ui-icon-lightbulb { background-position: -128px -128px; } -.ui-icon-scissors { background-position: -144px -128px; } -.ui-icon-clipboard { background-position: -160px -128px; } -.ui-icon-copy { background-position: -176px -128px; } -.ui-icon-contact { background-position: -192px -128px; } -.ui-icon-image { background-position: -208px -128px; } -.ui-icon-video { background-position: -224px -128px; } -.ui-icon-script { background-position: -240px -128px; } -.ui-icon-alert { background-position: 0 -144px; } -.ui-icon-info { background-position: -16px -144px; } -.ui-icon-notice { background-position: -32px -144px; } -.ui-icon-help { background-position: -48px -144px; } -.ui-icon-check { background-position: -64px -144px; } -.ui-icon-bullet { background-position: -80px -144px; } -.ui-icon-radio-on { background-position: -96px -144px; } -.ui-icon-radio-off { background-position: -112px -144px; } -.ui-icon-pin-w { background-position: -128px -144px; } -.ui-icon-pin-s { background-position: -144px -144px; } -.ui-icon-play { background-position: 0 -160px; } -.ui-icon-pause { background-position: -16px -160px; } -.ui-icon-seek-next { background-position: -32px -160px; } -.ui-icon-seek-prev { background-position: -48px -160px; } -.ui-icon-seek-end { background-position: -64px -160px; } -.ui-icon-seek-start { background-position: -80px -160px; } -/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ -.ui-icon-seek-first { background-position: -80px -160px; } -.ui-icon-stop { background-position: -96px -160px; } -.ui-icon-eject { background-position: -112px -160px; } -.ui-icon-volume-off { background-position: -128px -160px; } -.ui-icon-volume-on { background-position: -144px -160px; } -.ui-icon-power { background-position: 0 -176px; } -.ui-icon-signal-diag { background-position: -16px -176px; } -.ui-icon-signal { background-position: -32px -176px; } -.ui-icon-battery-0 { background-position: -48px -176px; } -.ui-icon-battery-1 { background-position: -64px -176px; } -.ui-icon-battery-2 { background-position: -80px -176px; } -.ui-icon-battery-3 { background-position: -96px -176px; } -.ui-icon-circle-plus { background-position: 0 -192px; } -.ui-icon-circle-minus { background-position: -16px -192px; } -.ui-icon-circle-close { background-position: -32px -192px; } -.ui-icon-circle-triangle-e { background-position: -48px -192px; } -.ui-icon-circle-triangle-s { background-position: -64px -192px; } -.ui-icon-circle-triangle-w { background-position: -80px -192px; } -.ui-icon-circle-triangle-n { background-position: -96px -192px; } -.ui-icon-circle-arrow-e { background-position: -112px -192px; } -.ui-icon-circle-arrow-s { background-position: -128px -192px; } -.ui-icon-circle-arrow-w { background-position: -144px -192px; } -.ui-icon-circle-arrow-n { background-position: -160px -192px; } -.ui-icon-circle-zoomin { background-position: -176px -192px; } -.ui-icon-circle-zoomout { background-position: -192px -192px; } -.ui-icon-circle-check { background-position: -208px -192px; } -.ui-icon-circlesmall-plus { background-position: 0 -208px; } -.ui-icon-circlesmall-minus { background-position: -16px -208px; } -.ui-icon-circlesmall-close { background-position: -32px -208px; } -.ui-icon-squaresmall-plus { background-position: -48px -208px; } -.ui-icon-squaresmall-minus { background-position: -64px -208px; } -.ui-icon-squaresmall-close { background-position: -80px -208px; } -.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } -.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } -.ui-icon-grip-solid-vertical { background-position: -32px -224px; } -.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } -.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } -.ui-icon-grip-diagonal-se { background-position: -80px -224px; } - - -/* Misc visuals -----------------------------------*/ - -/* Corner radius */ -.ui-corner-all, -.ui-corner-top, -.ui-corner-left, -.ui-corner-tl { - border-top-left-radius: 4px; -} -.ui-corner-all, -.ui-corner-top, -.ui-corner-right, -.ui-corner-tr { - border-top-right-radius: 4px; -} -.ui-corner-all, -.ui-corner-bottom, -.ui-corner-left, -.ui-corner-bl { - border-bottom-left-radius: 4px; -} -.ui-corner-all, -.ui-corner-bottom, -.ui-corner-right, -.ui-corner-br { - border-bottom-right-radius: 4px; -} - -/* Overlays */ -.ui-widget-overlay { - background: #aaaaaa; - opacity: .3; - filter: Alpha(Opacity=30); /* support: IE8 */ -} -.ui-widget-shadow { - margin: -8px 0 0 -8px; - padding: 8px; - background: #aaaaaa; - opacity: .3; - filter: Alpha(Opacity=30); /* support: IE8 */ - border-radius: 8px; -} diff --git a/website/agenda/planung/css/jquery-ui.theme.min.css b/website/agenda/planung/css/jquery-ui.theme.min.css deleted file mode 100644 index ec8dc89..0000000 --- a/website/agenda/planung/css/jquery-ui.theme.min.css +++ /dev/null @@ -1,5 +0,0 @@ -/*! jQuery UI - v1.11.4 - 2016-01-26 -* http://jqueryui.com -* Copyright jQuery Foundation and other contributors; Licensed MIT */ - -.ui-widget{font-family:Verdana,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Verdana,Arial,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #aaa;background:#fff;color:#222}.ui-widget-content a{color:#222}.ui-widget-header{border:1px solid #aaa;background:#ccc url("images/ui-bg_highlight-soft_75_cccccc_1x100.png") 50% 50% repeat-x;color:#222;font-weight:bold}.ui-widget-header a{color:#222}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #d3d3d3;background:#e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x;font-weight:normal;color:#555}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#555;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #999;background:#dadada url("images/ui-bg_glass_75_dadada_1x400.png") 50% 50% repeat-x;font-weight:normal;color:#212121}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited{color:#212121;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #aaa;background:#fff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x;font-weight:normal;color:#212121}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#212121;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fcefa1;background:#fbf9ee url("images/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x;color:#363636}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#fef1ec url("images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x;color:#cd0a0a}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#cd0a0a}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#cd0a0a}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url("images/ui-icons_222222_256x240.png")}.ui-widget-header .ui-icon{background-image:url("images/ui-icons_222222_256x240.png")}.ui-state-default .ui-icon{background-image:url("images/ui-icons_888888_256x240.png")}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url("images/ui-icons_454545_256x240.png")}.ui-state-active .ui-icon{background-image:url("images/ui-icons_454545_256x240.png")}.ui-state-highlight .ui-icon{background-image:url("images/ui-icons_2e83ff_256x240.png")}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url("images/ui-icons_cd0a0a_256x240.png")}.ui-icon-blank{background-position:16px 16px}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:4px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:4px}.ui-widget-overlay{background:#aaa;opacity:.3;filter:Alpha(Opacity=30)}.ui-widget-shadow{margin:-8px 0 0 -8px;padding:8px;background:#aaa;opacity:.3;filter:Alpha(Opacity=30);border-radius:8px} \ No newline at end of file diff --git a/website/agenda/planung/css/list_series.css b/website/agenda/planung/css/list-series.css similarity index 59% rename from website/agenda/planung/css/list_series.css rename to website/agenda/planung/css/list-series.css index 1280e6f..eb27c70 100644 --- a/website/agenda/planung/css/list_series.css +++ b/website/agenda/planung/css/list-series.css @@ -10,37 +10,33 @@ div#oldSeries{ clear:both; } -div#newSeries, div#oldSeries{ +div#newSeries, +div#oldSeries{ display: flex; flex-wrap: wrap; align-items: center; justify-content: center; } -div#newSeries div, -div#oldSeries div{ +div#newSeries a, +div#oldSeries a{ color:#fff; background:#1abc9c; - padding:6px; - padding-top:6px; - margin:6px; - margin-left:6px; - margin-right:6px; - /*float:left;*/ + padding:0.5rem; + margin:0.5rem; cursor:pointer; text-align:center; display:table-cell; vertical-align:middle; width:10rem; - height:3rem; - line-height:2em; + height:4rem; + line-height:1.4rem; } -/* -*/ -div#newSeries div:hover, -div#oldSeries div:hover{ +div#newSeries a:hover, +div#oldSeries a:hover{ background:#1dd2af; + text-decoration:none; } div#search{ diff --git a/website/agenda/planung/css/notify-events.css b/website/agenda/planung/css/notify-events.css new file mode 100644 index 0000000..97f50a3 --- /dev/null +++ b/website/agenda/planung/css/notify-events.css @@ -0,0 +1,36 @@ +.mailHeader{ + background:#ccc; +} + +.mailSubject{ +} + +.mailBody{ + white-space:pre; +} + +.done{ + background:#cfc; +} + +table#events td:nth-of-type(1){ + width:15em; +} + +table#events td:nth-of-type(2){ + width:60em; +} + +td.action, input.action{ + width:5em; +} + +form input{ + width:50em; +} + +form textarea{ + width:50em; + height:14em; +} + diff --git a/website/agenda/planung/css/playlist.css b/website/agenda/planung/css/playlist.css index 37659d8..baaa85b 100644 --- a/website/agenda/planung/css/playlist.css +++ b/website/agenda/planung/css/playlist.css @@ -1,21 +1,19 @@ -table{ - padding:0; - margin:1em; - border-collapse:collapse; - empty-cells:show; +table { + padding: 0; + margin: 1em; + border-collapse: collapse; + empty-cells: show; } -tr{ - margin:0; - padding:0; - border-top:1px solid #666; -} - - -td{ - min-width:10em; - padding:3px; - margin:0; - font-size:-2; +tr { + margin: 0; + padding: 0; + border-top: 1px solid #666; } +td { + min-width: 10em; + padding: 3px; + margin: 0; + font-size: -2; +} \ No newline at end of file diff --git a/website/agenda/planung/css/projects.css b/website/agenda/planung/css/projects.css index 8407f88..0535287 100644 --- a/website/agenda/planung/css/projects.css +++ b/website/agenda/planung/css/projects.css @@ -1,44 +1,67 @@ -#content .label{ - width:10em; - padding:0; - margin:0; - color:#555; + +#content .label { + width: 10ch; + padding: 0; + margin: 0; + color: #555; } -#content div.project{ - width:45%; +#content div.project { + min-width: 40ch; } -#content div.editor{ - clear:both; +#content div.editor { + clear: both; } -#content div.view{ - clear:both; +#content div.view { + clear: both; } -#content div.view img{ - max-width:50px; - max-height:50px; +#content div.editor div.right { + float: right; + padding: 0; + margin: 0; } -#content div.editor div.right{ - float:right; - padding:0; - margin:0; -} - -#content div.editor div.buttons{ - text-align:center; - padding:0; +#content div.editor div.buttons { + text-align: center; + padding: 0; } #content div.editor div.buttons button, -#content div.editor div.buttons input{ - margin-left:1em; +#content div.editor div.buttons input { + margin-left: 1em; } -#content div.view{ - text-align:left; +#content div.view { + text-align: left; } +#content div.flex{ + align-items: inherit; +} + +body #content{ + max-width:none; +} + +.buttons{ + display: flex; +} + +#content .bottom, +.bottom{ + position: absolute; + bottom: 1rem; +} + +#content .bottom.right, +.bottom.right{ + position: absolute; + right: 1rem; +} + +#content div.title { + font-size:1.5rem; +} diff --git a/website/agenda/planung/css/series.css b/website/agenda/planung/css/series.css index 36f04fa..0536cf0 100644 --- a/website/agenda/planung/css/series.css +++ b/website/agenda/planung/css/series.css @@ -1,298 +1,269 @@ - -#content{ - margin-top:3em; - padding:1em; - max-width:1000px; - min-height:100%; +#content { + margin-top: 3rem; + min-height: 100%; } -#content td.label{ - max-width:3em; -} - -#content .label{ - padding:0; - margin:0; - color:#555; -} - -#content table.series{ - border-radius:1em; -} - -#content .series div.header{ - font-weight:bold; - cursor:pointer; -} - -#content div.header{ - clear:both; -} - -#content .right{ - float:right; - padding:0; - margin:0; -} - -#content .editor{ - clear:both; -} - -#content .editor div.buttons{ - text-align:center; - padding:0; -} - -#content .editor div.buttons button, -#content .editor div.buttons input{ - margin-left:1em; -} - -/* -#content .editor input, -#content .editor textarea, -#content .editor button{ - padding:6px; -} -*/ - -#imagePreview{ +#content table.td{ padding:0; - margin:0; - border:none; - width:24px; - height:24px; } -#context textarea{ - width:600px; - height:100px; +#content td.label { + max-width: 2rem; +} + +#content .label { + color: #555; } #content table.series { - border:1px solid #ddd; - + border-radius: 1rem; } -#content table.series table{ - width:100%; +#content .series div.header { + font-weight: bold; + cursor: pointer; } -#content table.series tr:nth-child(4n+1){ - background-color:#eee; +#content div.header { + clear: both; } -#content table.series tr.active td{ - background-color: #aaa; +#content .right { + float: right; } -#content .series table tr{ - padding:0; - margin:0; +#content .editor { + padding:0.5rem; + clear: both; + background:white; } -#content .series table td:nth-child(1){ - width:10em; +#content .editor td{ + padding:0; } -#content .series table td{ - padding:6px; - margin:0; +#content .editor div.buttons { + text-align: center; } -#content .editor .row{ - clear:both; - min-height:4em; +#content .editor div.buttons button, +#content .editor div.buttons input { + margin-left: 1rem; } -#content .editor .cell{ - float:left; - text-align:center; - white-space:nowrap; +#imagePreview { + border: none; + width: 24px; + height: 24px; } -#content .editor .row.active{ - background:#ff0; - min-height:4em; +#context textarea { + width: 600px; + height: 100px; } -#content div.ui-tabs-panel, -#content div.editor, -#content div.row.schedule{ - padding-left:0; - padding-right:0; +#content table.series { + border: 1px solid #ddd; } -/* start of schedule */ -#content div.cell{ - margin-left:6px; - margin-right:0; - padding-left:0; - padding-right:0; +#content table.series table { + width: 100%; +} + +#content table.series tr:nth-child(4n+1) { + background-color: #eee; +} + +#content table.series tr.active td { + background-color: #aaa; +} + +#content .series table td:nth-child(1) { + width: 10rem; +} + +#content .series table td { + padding: 0.5rem; +} + +#content .editor .row { + clear: both; + min-height: 4rem; +} + +#content .editor .cell { + display:table-cell; + text-align: center; + white-space: nowrap; + padding-right:0.5rem; +} + +#content .editor .row.active { + background: #ff0; + min-height: 4rem; +} + +#content div.cell select, +#content div.cell input{ + text-align:center; } #content div.cell.exclude, #content div.cell.nextDay, -#content div.cell.weekday{ - margin-left:0; +#content div.cell.weekday { + margin-left: 0; } -#content div.cell.containsInput{ - margin-right:12px; +#content div.cell.containsInput { + margin-right: 1rem; } -#content div.cell.containsSelect{ - margin-right:12px; +#content div.cell.containsSelect { + margin-right: 1rem; } #content div.cell.exclude, -#content div.cell.nextDay{ - width:1em; +#content div.cell.nextDay { + width: 2ch; } #content div.cell.weekday, #content div.cell.weekday input, -#content div.cell.weekday select{ - width:2em; - padding-top:2em; +#content div.cell.weekday select { + width: 2.5ch; + padding-top: 1.6rem; } #content div.cell.start, #content div.cell.start input, -#content div.cell.start select{ - width:9.5em; +#content div.cell.start select { + width: 14ch; } #content div.cell.duration, #content div.cell.duration input, -#content div.cell.duration select{ - width:7em; +#content div.cell.duration select { + width: 14ch; } #content div.cell.period_type, #content div.cell.period_type input, -#content div.cell.period_type select{ - width:7em; + #content div.cell.period_type select { + width: 14ch; } #content div.cell.period_type.isSingle, -#content div.cell.period_type select.isSingle{ - width:9em; +#content div.cell.period_type select.isSingle { + width: 14ch; } - - #content div.cell.end, #content div.cell.end input, -#content div.cell.end select{ - width:6em; +#content div.cell.end select { + width: 14ch; } #content div.cell.frequency, #content div.cell.frequency input, -#content div.cell.frequency select{ - width:6em; +#content div.cell.frequency select { + width: 14ch; } - #content div.cell.week_of_month, #content div.cell.week_of_month input, -#content div.cell.week_of_month select{ - width:6em; +#content div.cell.week_of_month select { + width: 7ch; } #content div.cell.schedule_weekday, #content div.cell.schedule_weekday input, -#content div.cell.schedule_weekday select{ - width:4em; +#content div.cell.schedule_weekday select { + width: 2.5ch; } #content div.cell.schedule_month, #content div.cell.schedule_month input, -#content div.cell.schedule_month select{ - width:6em; +#content div.cell.schedule_month select { + width: 7ch; } +#content div.cell.frequency button{ + width:10ch; +} + +#content div.cell.delete, +#content div.cell.delete button { + padding-right:0; + margin:0; + padding:0; +} /* end of schedule */ - -#content .create_events{ - width:5em; -} -#content .publish_events{ - width:5em; +#content .create_events { + width: 5rem; } -#content div.show_schedule{ - overflow:auto; - height:20em; - clear:both; +#content .publish_events { + width: 5rem; } - -#content div.show_schedule table{ - width:24em; +#content div.show_schedule { + overflow: auto; + height: 20rem; + clear: both; } -#content div.show_schedule td{ - width:10em; -} -#content div.show_schedule td:nth-child(1){ - width:2em; +#content div.show_schedule table { + width: 24rem; } -/* -#content div.show_schedule tr:nth-child(odd){ - background:#f0f0f0; -} -*/ - -#content div.show_schedule tr.exclude td{ - text-decoration:line-through; +#content div.show_schedule td { + width: 10rem; } -#content div.buttons{ - padding-left:12px; +#content div.show_schedule td:nth-child(1) { + width: 2rem; } -#content div.editor input.image{ - width:90%; +#content div.show_schedule tr.exclude td { + text-decoration: line-through; +} + +input.exclude{ + margin-top:0.5rem; +} + +#content div.editor input.image { + width: 90%; +} + +div#tabs > div { + background:white; } #content #tabs-events td.weekday, #content #tabs-events td.date, #content #tabs-events td.time, -#content #tabs-events td.spacer{ - width:0; -} -#content #tabs-events td.weekday, -#content #tabs-events td.spacer{ - padding:0; +#content #tabs-events td.spacer { + width: 0; } -#content input.datetimepicker{ - padding-left:0; - padding-right:0; -} - -button{ - cursor:pointer; -} - -form{ - padding:0; - margin:0; +button { + cursor: pointer; } @media print { - input,button{ - display:none; - } + input, button { + display: none; + } } -/* -#content .editor .row:nth-child(2n+1){ - background:#eee; +div.editor > form > table{ + background:white; } -*/ + +div.editor > form > table td{ + padding-left:1rem; + padding-right:1rem; +} + diff --git a/website/agenda/planung/css/show-playout.css b/website/agenda/planung/css/show-playout.css new file mode 100644 index 0000000..467e34d --- /dev/null +++ b/website/agenda/planung/css/show-playout.css @@ -0,0 +1,96 @@ +#content table, +#content tr, +#content td, +#content div.ok, +#content div.warn, + #content div.error { + margin: 0; + padding: 0; + border: 0; +} + +table { + margin: 1em; + border-collapse: collapse; + empty-cells: show; +} + +#content tr, +#content td { + vertical-align: top; +} + +#content tr { + border-top: 1px solid #666; +} + +#content #playout-table td.start { + width:10%; +} + +#content #playout-table td.path div { + width: 20%; +} +#content #playout-table td.path div { + width: 100%; + height: 100%; + word-break: break-word; + text-overflow: ellipsis; + overflow: hidden; + max-height:3.2rem; +} + +#content #playout-table td.path div:hover { + max-height:none; + transition: all 1s; +} + +#content #playout-table td.properties { + width: 50%; +} + +#content #playout-table td.image { + width: 10%; +} + + +#content tr.past { + background: #ccc; +} + +#content td { + padding: 3px; + font-size: -2; + text-align: center; +} + +#content img { + width:200px; + height:100px; +} + +img:hover { + transform:scale(1.5); + transition: all 1s; +} + +#content div.ok, +#content div.warn, +#content div.error{ + padding: 3px; + margin: 1px; + border-radius: 4px; + text-align: center; +} + +#content div.ok { + background: #4caf50; +} + +#content div.warn { + background: #ffeb3b; +} + +#content div.error { + background: #f44336; +} diff --git a/website/agenda/planung/css/studio-timeslots.css b/website/agenda/planung/css/studio-timeslots.css new file mode 100644 index 0000000..43159c8 --- /dev/null +++ b/website/agenda/planung/css/studio-timeslots.css @@ -0,0 +1,116 @@ +#content { + margin-top: 3rem; + padding: 1rem; + max-width: 960px; + min-height: 100%; +} + +#content .label { + padding: 0; + margin: 0; + color: #555; +} + +#content div.header { + clear: both; +} + +#content .right { + float: right; + padding: 0; + margin: 0; +} + +#content .editor { + clear: both; +} + +#content .editor div.buttons { + text-align: center; + padding: 0; +} + +#content .editor div.buttons button, +#content .editor div.buttons input { + margin-left: 1rem; +} + +#content .editor input, +#content .editor textarea, +#content .editor button { + padding: 0.5rem; +} + +#content .editor .row { + clear: both; +} + +#content .editor .cell { + display: table-cell ; + vertical-align:baseline; + text-align: center; +} + +#content .frequency { + width: 6em; +} + +#content div.weekday { + padding: 0; + width: 2em; + margin-right: -0.5em; + margin-top: 1.2em; +} + +#content div.show_schedule_head { + clear: both; +} + +#content div.show_schedule { + clear: both; + padding: 0; +} + +#content div.show_schedule table { + width: 66%; +} + +#content div.show_schedule td { + width: 10em; +} +/* weekday start*/ +#content div.show_schedule td:nth-child(1) { + width: 2em; +} + +/* weekday end*/ +#content div.show_schedule td:nth-child(3) { + width: 2em; +} + +#content div.show_schedule tr.exclude td { + text-decoration: line-through; +} + +#content div.buttons { + padding-left: 1rem; +} + +#content div.editor input.image { + width: 90%; +} + +button { + cursor: pointer; +} + +form { + padding: 0; + margin: 0; +} + +@media print { + input, button { + display: none; + } +} diff --git a/website/agenda/planung/css/studio_timeslots.css b/website/agenda/planung/css/studio_timeslots.css deleted file mode 100644 index d058000..0000000 --- a/website/agenda/planung/css/studio_timeslots.css +++ /dev/null @@ -1,114 +0,0 @@ - -#content{ - margin-top:3em; - padding:1em; - max-width:1000px; - min-height:100%; -} - -#content .label{ - padding:0; - margin:0; - color:#555; -} - -#content div.header{ - clear:both; -} - -#content .right{ - float:right; - padding:0; - margin:0; -} - -#content .editor{ - clear:both; -} - -#content .editor div.buttons{ - text-align:center; - padding:0; -} - -#content .editor div.buttons button, -#content .editor div.buttons input{ - margin-left:1em; -} - -#content .editor input, -#content .editor textarea, -#content .editor button{ - padding:6px; -} - -#content .editor .row{ - clear:both; -} -#content .editor .cell{ - float:left; - text-align:center; -} -#content .frequency{ - width:6em; -} -#content div.weekday{ - padding:0; - width:2em; - - margin-right:-0.5em; - margin-top:1.2em; -} - -#content div.show_schedule_head{ - clear:both; -} - -#content div.show_schedule{ - clear:both; -} - -#content div.show_schedule table{ - width:66%; -} - -#content div.show_schedule td{ - width:10em; -} -/* weekday start*/ -#content div.show_schedule td:nth-child(1){ - width:2em; -} - -/* weekday end*/ -#content div.show_schedule td:nth-child(3){ - width:2em; -} - -#content div.show_schedule tr.exclude td{ - text-decoration:line-through; -} - -#content div.buttons{ - padding-left:12px; -} - -#content div.editor input.image{ - width:90%; -} - -button{ - cursor:pointer; -} - -form{ - padding:0; - margin:0; -} - -@media print { - input,button{ - display:none; - } -} - diff --git a/website/agenda/planung/css/studios.css b/website/agenda/planung/css/studios.css index 94520d9..465b4eb 100644 --- a/website/agenda/planung/css/studios.css +++ b/website/agenda/planung/css/studios.css @@ -1,36 +1,67 @@ -#content .label{ - width:10em; - padding:0; - margin:0; - color:#555; +#content .label { + width: 10ch; + padding: 0; + margin: 0; + color: #555; } -#content div.studio{ - min-width:40%; +#content div.studio { + min-width: 40ch; } -#content div.editor{ - display:inline-block; +#content div.editor { + clear: both; } -#content div.editor div.right{ - float:right; - padding:0; - margin:0; +#content div.view { + clear: both; } -#content div.editor div.buttons{ - text-align:center; - padding:0; +#content div.editor div.right { + float: right; + padding: 0; + margin: 0; +} + +#content div.editor div.buttons { + text-align: center; + padding: 0; } #content div.editor div.buttons button, -#content div.editor div.buttons input{ - margin-left:1em; +#content div.editor div.buttons input { + margin-left: 1em; } -#content div.view{ - text-align:left; - clear:both; +#content div.view { + text-align: left; +} + +#content div.flex{ + align-items: inherit; +} + +body #content{ + max-width:none; +} + +.buttons{ + display: flex; +} + +#content .bottom, +.bottom{ + position: absolute; + bottom: 1rem; +} + +#content .bottom.right, +.bottom.right{ + position: absolute; + right: 1rem; +} + +#content .panel{ + min-height: 25rem; } diff --git a/website/agenda/planung/css/wiki_preview.css b/website/agenda/planung/css/wiki_preview.css deleted file mode 100644 index 556f222..0000000 --- a/website/agenda/planung/css/wiki_preview.css +++ /dev/null @@ -1,5 +0,0 @@ -form table{ - margin:6px; - padding:6px; -} - diff --git a/website/agenda/planung/css/work-time.css b/website/agenda/planung/css/work-time.css new file mode 100644 index 0000000..d141632 --- /dev/null +++ b/website/agenda/planung/css/work-time.css @@ -0,0 +1,269 @@ +#content { + margin-top: 3em; + padding: 1em; + max-width: 1000px; + min-height: 100%; +} + +#content td.label { + max-width: 3em; +} + +#content .label { + padding: 0; + margin: 0; + color: #555; +} + +#content div.header { + clear: both; +} + +#content .right { + float: right; + padding: 0; + margin: 0; +} + +#content .editor { + clear: both; +} + +#content .editor div.buttons { + text-align: center; + padding: 0; +} + +#content .editor div.buttons button, +#content .editor div.buttons input { + margin-left: 1em; +} + +#content .editor input, +#content .editor textarea, +#content .editor button { + padding: 6px; +} + +#context textarea { + width: 600px; + height: 100px; +} + +#content table.series { + border: 1px solid #ddd; +} + +#content table.series table { + width: 100%; +} + +#content table.series tr:nth-child(4n+1) { + background-color: #eee; +} + +#content table.series tr.active td { + background-color: #aaa; +} + +#content .series table tr { + padding: 0; + margin: 0; +} + +#content .series table td:nth-child(1) { + width: 10em; +} + +#content .series table td { + padding: 6px; + margin: 0; +} + +#content .series table tr:nth-child(odd) { + background: #eee; +} + +#content .editor .row { + clear: both; + min-height: 4em; +} + +#content .editor .cell { + float: left; + text-align: center; + white-space: nowrap; +} + +#content .editor .row.active { + background: #ff0; + min-height: 4em; +} + +#content .editor div.row.schedule.selected { + background: #ff0; + min-height: 4em; +} + +/* +#content .editor .row:nth-child(2n+1){ + background:#eee; +} +*/ + +#content div.editor, +#content div.row.schedule { + padding-left: 0; + padding-right: 0; +} + +/* start of schedule */ +#content div.cell { + margin-left: 6px; + margin-right: 0; + padding-left: 0; + padding-right: 0; +} + +#content div.cell.exclude, +#content div.cell.weekday { + margin-left: 0; +} + +#content div.cell.containsInput { + margin-right: 16px; +} + +#content div.cell.containsSelect { + margin-right: 16px; +} + +#content div.cell.exclude { + width: 1em; +} + +#content div.cell.weekday, +#content div.cell.weekday input, +#content div.cell.weekday select{ + width: 2em; + padding-top: 2em; +} + +#content div.cell.start, +#content div.cell.start input, +#content div.cell.start select{ + width: 9em; +} + +#content div.cell.duration, +#content div.cell.duration input, +#content div.cell.duration select{ + width: 7em; +} + +#content div.cell.title, +#content div.cell.title input, +#content div.cell.title select{ + width: 6em; +} + +#content div.cell.type, +#content div.cell.type input, +#content div.cell.type select{ + width: 6em; +} + +#content div.cell.period_type, +#content div.cell.period_type input, + #content div.cell.period_type select { + width: 7em; +} + +#content div.cell.period_type.isSingle, +#content div.cell.period_type select.isSingle{ + width: 9em; +} + +#content div.cell.end, +#content div.cell.end input, +#content div.cell.end select{ + width: 6em; +} + +#content div.cell.frequency, +#content div.cell.frequency input, +#content div.cell.frequency select{ + width: 6em; +} + + +#content div.cell.week_of_month, +#content div.cell.week_of_month input, + #content div.cell.week_of_month select { + width: 6em; +} + +#content div.cell.schedule_weekday, +#content div.cell.schedule_weekday input, + #content div.cell.schedule_weekday select { + width: 4em; +} + +#content div.cell.schedule_month, +#content div.cell.schedule_month input, + #content div.cell.schedule_month select { + width: 6em; +} + +/* end of schedule */ +#content div.show_schedule { + overflow: auto; + height: 20em; + clear: both; +} + +#content div.show_schedule table { + width: 50em; +} + +#content div.show_schedule td { + width: 10em; +} + +#content div.show_schedule td:nth-child(1) { + width: 2em; +} + +#content div.show_schedule tr.exclude td { + text-decoration: line-through; +} + +#content div.buttons { + padding-left: 12px; +} + +#content div.editor input.image { + width: 90%; +} + +button { + cursor: pointer; +} + +form { + padding: 0; + margin: 0; +} + +@media print { + input, button { + display: none; + } +} + +/* +#content div.show_schedule tr:nth-child(odd){ + background:#f0f0f0; +} + +*/ diff --git a/website/agenda/planung/css/work_time.css b/website/agenda/planung/css/work_time.css deleted file mode 100644 index 5f32319..0000000 --- a/website/agenda/planung/css/work_time.css +++ /dev/null @@ -1,278 +0,0 @@ -body{ - background:#666; -} - -#content{ - margin-top:3em; - padding:1em; - max-width:1000px; - min-height:100%; -} - -#content td.label{ - max-width:3em; -} - -#content .label{ - padding:0; - margin:0; - color:#555; -} - -#content div.header{ - clear:both; -} - -#content .right{ - float:right; - padding:0; - margin:0; -} - -#content .editor{ - clear:both; -} - -#content .editor div.buttons{ - text-align:center; - padding:0; -} - -#content .editor div.buttons button, -#content .editor div.buttons input{ - margin-left:1em; -} - -#content .editor input, -#content .editor textarea, -#content .editor button{ - padding:6px; -} - -#context textarea{ - width:600px; - height:100px; -} - -#content table.series { - border:1px solid #ddd; - -} - -#content table.series table{ - width:100%; -} - -#content table.series tr:nth-child(4n+1){ - background-color:#eee; -} - -#content table.series tr.active td{ - background-color: #aaa; -} - -#content .series table tr{ - padding:0; - margin:0; -} - -#content .series table td:nth-child(1){ - width:10em; -} - -#content .series table td{ - padding:6px; - margin:0; -} - -#content .series table tr:nth-child(odd){ - background:#eee; -} - -#content .editor .row{ - clear:both; - min-height:4em; -} - -#content .editor .cell{ - float:left; - text-align:center; - white-space:nowrap; -} - -#content .editor .row.active{ - background:#ff0; - min-height:4em; -} - -#content .editor div.row.schedule.selected{ - background:#ff0; - min-height:4em; -} - -/* -#content .editor .row:nth-child(2n+1){ - background:#eee; -} -*/ - -#content div.ui-tabs-panel, -#content div.editor, -#content div.row.schedule{ - padding-left:0; - padding-right:0; -} - -/* start of schedule */ -#content div.cell{ - margin-left:6px; - margin-right:0; - padding-left:0; - padding-right:0; -} - -#content div.cell.exclude, -#content div.cell.weekday{ - margin-left:0; -} - -#content div.cell.containsInput{ - margin-right:16px; -} - -#content div.cell.containsSelect{ - margin-right:16px; -} - -#content div.cell.exclude{ - width:1em; -} - -#content div.cell.weekday, -#content div.cell.weekday input, -#content div.cell.weekday select{ - width:2em; - padding-top:2em; -} - -#content div.cell.start, -#content div.cell.start input, -#content div.cell.start select{ - width:9em; -} - -#content div.cell.duration, -#content div.cell.duration input, -#content div.cell.duration select{ - width:7em; -} - -#content div.cell.title, -#content div.cell.title input, -#content div.cell.title select{ - width:6em; -} - -#content div.cell.type, -#content div.cell.type input, -#content div.cell.type select{ - width:6em; -} - -#content div.cell.period_type, -#content div.cell.period_type input, -#content div.cell.period_type select{ - width:7em; -} - -#content div.cell.period_type.isSingle, -#content div.cell.period_type select.isSingle{ - width:9em; -} - -#content div.cell.end, -#content div.cell.end input, -#content div.cell.end select{ - width:6em; -} - -#content div.cell.frequency, -#content div.cell.frequency input, -#content div.cell.frequency select{ - width:6em; -} - - -#content div.cell.week_of_month, -#content div.cell.week_of_month input, -#content div.cell.week_of_month select{ - width:6em; -} - -#content div.cell.schedule_weekday, -#content div.cell.schedule_weekday input, -#content div.cell.schedule_weekday select{ - width:4em; -} - -#content div.cell.schedule_month, -#content div.cell.schedule_month input, -#content div.cell.schedule_month select{ - width:6em; -} - - -/* end of schedule */ - -#content div.show_schedule{ - overflow:auto; - height:20em; - clear:both; -} - - -#content div.show_schedule table{ - width:50em; -} - -#content div.show_schedule td{ - width:10em; -} -#content div.show_schedule td:nth-child(1){ - width:2em; -} - -#content div.show_schedule tr.exclude td{ - text-decoration:line-through; -} - -#content div.buttons{ - padding-left:12px; -} - -#content div.editor input.image{ - width:90%; -} - - -button{ - cursor:pointer; -} - -form{ - padding:0; - margin:0; -} - -@media print { - input,button{ - display:none; - } -} - -/* -#content div.show_schedule tr:nth-child(odd){ - background:#f0f0f0; -} - -*/ diff --git a/website/agenda/planung/error_log.cgi b/website/agenda/planung/error_log.cgi deleted file mode 100755 index 31a3de9..0000000 --- a/website/agenda/planung/error_log.cgi +++ /dev/null @@ -1,87 +0,0 @@ -#! /usr/bin/perl -I../lib - -use warnings "all"; -use strict; -use Data::Dumper; -use HTML::Template; - -#use URI::Escape; -#use Encode; - -use config; -use log; -use template; -use params; -use config; -use auth; -use localization; -use studios; -binmode STDOUT, ":utf8"; -my $r = shift; -( my $cgi, my $params, my $error ) = params::get($r); - -my $config = config::get('../config/config.cgi'); -my $debug = $config->{system}->{debug}; -my ( $user, $expires ) = auth::get_user( $cgi, $config ); -return if ( !defined $user ) || ( $user eq '' ); - -my $user_presets = uac::get_user_presets( $config, { user => $user, studio_id => $params->{studio_id} } ); -my $request = { - url => $ENV{QUERY_STRING} || '', - params => { - original => $params, - checked => $params - - # checked => check_params($params), - }, -}; -$request = uac::prepare_request( $request, $user_presets ); -log::init($request); - -#process header -my $headerParams = uac::set_template_permissions( $request->{permissions}, $params ); -$headerParams->{loc} = localization::get( $config, { user => $user, file => 'menu' } ); -template::process( 'print', template::check('default.html'), $headerParams ); - -#filter -my $lines = $cgi->param('lines'); -$lines = 100 if $lines eq ''; - -my $filter = ''; -$filter = ' |grep -v "Use of uninitialized value in | grep -v redefined " ' if ( $cgi->param('warn') eq '1' ); - -#get file -my $file = $config->{system}->{log_file}; -if ( $cgi->param('log') eq 'app' ) { - $file = $config->{system}->{log_debug_file}; -} -if ( $cgi->param('log') eq 'mem' ) { - $file = $config->{system}->{log_debug_memory_file}; -} -if ( $cgi->param('log') eq 'job' ) { - $file = $config->{system}->{job_log}; -} - -#output header -my $out = ''; -template::process( 'print', 'templates/error_log.html', $params ); - -#get log -my $cmd = "tail -$lines " . $file . $filter; -print '<pre>' . $cmd . '</pre>'; - -my $log = `$cmd`; -$log = join( "\n", reverse( split( "\n", $log ) ) ); - -#replace -if ( $cgi->param('log') eq 'app' ) { - $log =~ s/\\n/<br>/gi; -} else { - $log =~ s/</\</gi; - $log =~ -s/\\n/<\/pre><pre>                                   /gi; -} - -#output content -print $log; - diff --git a/website/agenda/planung/event-history.cgi b/website/agenda/planung/event-history.cgi new file mode 100755 index 0000000..b8cb861 --- /dev/null +++ b/website/agenda/planung/event-history.cgi @@ -0,0 +1,273 @@ +#!/usr/bin/perl + +use strict; +use warnings; +no warnings 'redefine'; + +use URI::Escape(); +use Data::Dumper; +use MIME::Base64(); + +use params(); +use config(); +use entry(); +use log(); +use template(); +use db(); +use auth(); +use uac(); +use time(); +use markup(); +use studios(); +use event_history(); +use events(); +use series_events(); +use localization(); +use utf8; +binmode STDOUT, ":utf8"; + +my $r = shift; +( my $cgi, my $params, my $error ) = params::get($r); + +my $config = config::get('../config/config.cgi'); +my $debug = $config->{system}->{debug}; +my ( $user, $expires ) = auth::get_user( $config, $params, $cgi ); +return if ( ( !defined $user ) || ( $user eq '' ) ); +my $user_presets = uac::get_user_presets( + $config, + { + user => $user, + project_id => $params->{project_id}, + studio_id => $params->{studio_id} + } +); +$params->{default_studio_id} = $user_presets->{studio_id}; +$params = uac::setDefaultStudio( $params, $user_presets ); +$params = uac::setDefaultProject( $params, $user_presets ); + +my $request = { + url => $ENV{QUERY_STRING} || '', + params => { + original => $params, + checked => check_params( $config, $params ), + }, +}; + +#set user at params->presets->user +$request = uac::prepare_request( $request, $user_presets ); + +$params = $request->{params}->{checked}; + +#show header +my $headerParams = uac::set_template_permissions( $request->{permissions}, $params ); +$headerParams->{loc} = localization::get( $config, { user => $user, file => 'menu' } ); +template::process( $config, 'print', template::check( $config, 'default.html' ), $headerParams ); +return unless uac::check( $config, $params, $user_presets ) == 1; + +print q{ + <style> + pre{ + font-family:monospace; + } + textarea{ + height:fit-content; + min-height:500px; + width:50%; + } + </style> +}; + +$config->{access}->{write} = 0; +if ( $params->{action} eq 'diff' ) { + compare( $config, $request ); + return; +} +show_history( $config, $request ); + +#show existing event history +sub show_history { + my $config = shift; + my $request = shift; + + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + for my $attr ('studio_id') { # 'series_id','event_id' + unless ( defined $params->{$attr} ) { + uac::print_error( "missing " . $attr . " to show changes" ); + return; + } + } + + unless ( $permissions->{read_event} == 1 ) { + uac::print_error("missing permissions to show changes"); + return; + } + + my $options = { + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + limit => 200 + }; + $options->{series_id} = $params->{series_id} if defined $params->{series_id}; + $options->{event_id} = $params->{event_id} if defined $params->{event_id}; + + my $events = event_history::get( $config, $options ); + + return unless defined $events; + $params->{events} = $events; + + for my $permission ( keys %{$permissions} ) { + $params->{'allow'}->{$permission} = $request->{permissions}->{$permission}; + } + $params->{loc} = localization::get( $config, { user => $params->{presets}->{user}, file => 'event-history' } ); + + template::process( $config, 'print', template::check( $config, 'event-history' ), $params ); +} + +#show existing event history +sub compare { + my $config = shift; + my $request = shift; + + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + for my $attr ( 'project_id', 'studio_id', 'event_id', 'v1', 'v2' ) { + unless ( defined $params->{$attr} ) { + uac::print_error( "missing " . $attr . " to show changes" ); + return; + } + } + + unless ( $permissions->{read_event} == 1 ) { + uac::print_error("missing permissions to show changes"); + return; + } + + if ( $params->{v1} > $params->{v2} ) { + my $t = $params->{v1}; + $params->{v1} = $params->{v2}; + $params->{v2} = $t; + } + + my $options = { + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + series_id => $params->{series_id}, + event_id => $params->{event_id}, + change_id => $params->{v1}, + limit => 2 + }; + + my $events = event_history::get( $config, $options ); + return unless @$events == 1; + my $v1 = $events->[0]; + + $options->{change_id} = $params->{v2}; + $events = event_history::get( $config, $options ); + return unless @$events == 1; + my $v2 = $events->[0]; + + my $t1 = eventToText($v1); + my $t2 = eventToText($v2); + + if ( $t1 eq $t2 ) { + print "no changes\n"; + return; + } + + print '<textarea>' . $t1 . '</textarea>'; + print '<textarea>' . $t2 . '</textarea>'; + + my $cmd="/usr/bin/colordiff /tmp/diff-a.txt /tmp/diff-b.txt | ansi2html"; + #print "$cmd\n"; + log::save_file('/tmp/diff-a.txt', $t1); + log::save_file('/tmp/diff-b.txt', $t2); + print qq{ + <style> + pre { + font-weight: normal; + color: #bbb; + white-space: -moz-pre-wrap; + white-space: -o-pre-wrap; + white-space: -pre-wrap; + white-space: pre-wrap; + word-wrap: break-word; + overflow-wrap: break-word; +} +b {font-weight: normal} +b.BOLD {color: #fff} +b.ITA {font-style: italic} +b.UND {text-decoration: underline} +b.STR {text-decoration: line-through} +b.UNDSTR {text-decoration: underline line-through} +b.BLK {color: #000000} +b.RED {color: #aa0000} +b.GRN {color: #00aa00} +b.YEL {color: #aa5500} +b.BLU {color: #0000aa} +b.MAG {color: #aa00aa} +b.CYN {color: #00aaaa} +b.WHI {color: #aaaaaa} +b.HIK {color: #555555} +b.HIR {color: #ff5555} +b.HIG {color: #55ff55} +b.HIY {color: #ffff55} +b.HIB {color: #5555ff} +b.HIM {color: #ff55ff} +b.HIC {color: #55ffff} +b.HIW {color: #ffffff} +b.BBLK {background-color: #000000} +b.BRED {background-color: #aa0000} +b.BGRN {background-color: #00aa00} +b.BYEL {background-color: #aa5500} +b.BBLU {background-color: #0000aa} +b.BMAG {background-color: #aa00aa} +b.BCYN {background-color: #00aaaa} +b.BWHI {background-color: #aaaaaa} + </style> + }; + my $diff = qx{$cmd}; + $diff = substr($diff, index($diff, "<body>")+6); + $diff = substr($diff, 0, index($diff, "</body>")); + print "$diff\n"; + +} + +sub eventToText { + my $event = shift; + + my $s = events::get_keys($event)->{full_title} . "\n"; + $s .= $event->{excerpt} . "\n"; + $s .= $event->{user_excerpt} . "\n"; + $s .= $event->{topic} . "\n"; + $s .= $event->{content} . "\n"; + + #print STDERR "DUMP\n$s"; + return $s; + +} + +sub check_params { + my $config = shift; + my $params = shift; + + my $checked = {}; + my $template = ''; + $checked->{template} = template::check( $config, $params->{template}, 'event-history' ); + + #numeric values + entry::set_numbers( $checked, $params, [ + 'id', 'project_id', 'studio_id', 'default_studio_id', 'user_id', 'series_id', 'event_id', 'v1', 'v2' + ]); + + if ( defined $checked->{studio_id} ) { + $checked->{default_studio_id} = $checked->{studio_id}; + } else { + $checked->{studio_id} = -1; + } + + $checked->{action} = entry::element_of($params->{action}, ['show', 'diff']); + + return $checked; +} + diff --git a/website/agenda/planung/event.cgi b/website/agenda/planung/event.cgi index c1b0720..1822581 100755 --- a/website/agenda/planung/event.cgi +++ b/website/agenda/planung/event.cgi @@ -1,1011 +1,896 @@ -#! /usr/bin/perl -w +#!/usr/bin/perl -use warnings "all"; use strict; -use URI::Escape; -use Encode; -use Data::Dumper; -use MIME::Base64; -use Encode::Locale; +use warnings; +no warnings 'redefine'; -use params; -use config; -use log; -use template; -use db; -use auth; -use uac; +use Encode(); +use Data::Dumper; +$Data::Dumper::Sortkeys = 1; +use MIME::Base64(); +use Encode::Locale(); +use File::Basename qw(basename); + +use params(); +use config(); +use entry(); +use log(); +use template(); +use db(); +use auth(); +use uac(); #use roles; -use time; -use markup; -use project; -use studios; -use events; -use series; -use series_dates; -use series_events; -use user_stats; -use localization; -use eventOps; +use time(); +use markup(); +use project(); +use studios(); +use events(); +use series(); +use series_dates(); +use series_events(); +use user_stats(); +use localization(); +use eventOps(); +use images(); -binmode STDOUT, ":utf8"; +binmode STDOUT, ":encoding(utf8)"; my $r = shift; ( my $cgi, my $params, my $error ) = params::get($r); my $config = config::get('../config/config.cgi'); my $debug = $config->{system}->{debug}; -my ( $user, $expires ) = auth::get_user( $cgi, $config ); +my ( $user, $expires ) = auth::get_user( $config, $params, $cgi ); return if ( ( !defined $user ) || ( $user eq '' ) ); my $user_presets = uac::get_user_presets( - $config, - { - user => $user, - project_id => $params->{project_id}, - studio_id => $params->{studio_id} - } + $config, + { + user => $user, + project_id => $params->{project_id}, + studio_id => $params->{studio_id} + } ); $params->{default_studio_id} = $user_presets->{studio_id}; -$params->{studio_id} = $params->{default_studio_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); -$params->{project_id} = $user_presets->{project_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); +$params = uac::setDefaultStudio( $params, $user_presets ); +$params = uac::setDefaultProject( $params, $user_presets ); my $request = { - url => $ENV{QUERY_STRING} || '', - params => { - original => $params, - checked => check_params($params), - }, + url => $ENV{QUERY_STRING} || '', + params => { + original => $params, + checked => check_params( $config, $params ), + }, }; -#print STDERR Dumper($request)."\n"; - #set user at params->presets->user $request = uac::prepare_request( $request, $user_presets ); -log::init($request); $params = $request->{params}->{checked}; -#show header -unless ( params::isJson() ) { - my $headerParams = uac::set_template_permissions( $request->{permissions}, $params ); - $headerParams->{loc} = localization::get( $config, { user => $user, file => 'menu' } ); - template::process( 'print', template::check('default.html'), $headerParams ); -} -return unless defined uac::check( $config, $params, $user_presets ); +my $show_header = ! (params::isJson() or $params->{action} eq 'download_audio'); -print q{ - <script src="js/datetime.js" type="text/javascript"></script> - <script src="js/event.js" type="text/javascript"></script> - <link rel="stylesheet" href="css/event.css" type="text/css" /> -} unless (params::isJson); +if ( $show_header ) { + my $headerParams = uac::set_template_permissions( $request->{permissions}, $params ); + $headerParams->{loc} = localization::get( $config, { user => $user, file => 'menu' } ); + template::process( $config, 'print', template::check( $config, 'event-header.html' ), $headerParams ); +} +return unless uac::check( $config, $params, $user_presets ) == 1; if ( defined $params->{action} ) { - if ( ( $params->{action} eq 'show_new_event' ) - || ( $params->{action} eq 'show_new_event_from_schedule' ) ) - { - show_new_event( $config, $request ); - return; - } + if ( ( $params->{action} eq 'show_new_event' ) + || ( $params->{action} eq 'show_new_event_from_schedule' ) ) + { + show_new_event( $config, $request ); + return; + } - if ( ( $params->{action} eq 'create_event' ) - || ( $params->{action} eq 'create_event_from_schedule' ) ) - { - $params->{event_id} = create_event( $config, $request ); - unless ( defined $params->{event_id} ) { - uac::print_error("failed"); - return; - } - } - if ( $params->{action} eq 'get_json' ) { - getJson( $config, $request ); - return; - } - if ( $params->{action} eq 'delete' ) { delete_event( $config, $request ) } - if ( $params->{action} eq 'save' ) { save_event( $config, $request ) } - if ( $params->{action} eq 'download' ) { download( $config, $request ) } + if ( ( $params->{action} eq 'create_event' ) + || ( $params->{action} eq 'create_event_from_schedule' ) ) + { + $params->{event_id} = create_event( $config, $request ); + unless ( defined $params->{event_id} ) { + uac::print_error("failed"); + return; + } + } + if ( $params->{action} eq 'get_json' ) { + getJson( $config, $request ); + return; + } + if ( $params->{action} eq 'delete' ) { delete_event( $config, $request ) } + if ( $params->{action} eq 'save' ) { save_event( $config, $request ) } + if ( $params->{action} eq 'download' ) { download( $config, $request ) } + if ( $params->{action} eq 'download_audio' ) { + download_audio( $config, $request ); + return; + } } $config->{access}->{write} = 0; show_event( $config, $request ); #show existing event for edit sub show_event { - my $config = shift; - my $request = shift; + my $config = shift; + my $request = shift; - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; - for my $attr ( 'project_id', 'studio_id', 'series_id', 'event_id' ) { - unless ( defined $params->{$attr} ) { - uac::print_error( "missing " . $attr . " to show event" ); - return; - } - } + for my $attr ( 'project_id', 'studio_id', 'series_id', 'event_id' ) { + unless ( defined $params->{$attr} ) { + uac::print_error( "missing " . $attr . " to show event" ); + return; + } + } - my $result = series_events::check_permission( - $request, - { - permission => 'update_event_of_series,update_event_of_others', - check_for => [ 'studio', 'user', 'series', 'events' ], - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - series_id => $params->{series_id}, - event_id => $params->{event_id} - } - ); - unless ( $result eq '1' ) { - uac::print_error($result); - return undef; - } - $permissions->{update_event} = 1; - print STDERR "check series permission ok\n"; + my $result = series_events::check_permission( + $request, + { + permission => 'update_event_of_series,update_event_of_others', + check_for => [ 'studio', 'user', 'series', 'events' ], + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + series_id => $params->{series_id}, + event_id => $params->{event_id} + } + ); + unless ( $result eq '1' ) { + uac::print_error($result); + return undef; + } + $permissions->{update_event} = 1; + print STDERR "check series permission ok\n"; - #TODO: move to JS - my @durations = (); - for my $duration ( @{ time::get_durations() } ) { - my $entry = { - name => sprintf( "%02d:%02d", $duration / 60, $duration % 60 ), - value => $duration - }; - push @durations, $entry; - } + #TODO: move to JS + my @durations = (); + for my $duration ( @{ time::getDurations() } ) { + my $entry = { + name => sprintf( "%02d:%02d", $duration / 60, $duration % 60 ), + value => $duration + }; + push @durations, $entry; + } - my $event = series::get_event( - $config, - { - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - series_id => $params->{series_id}, - event_id => $params->{event_id} - } - ); - unless ( defined $event ) { - uac::print_error("event not found"); - } - #print STDERR "show:".Dumper($event->{draft}); + my $event = series::get_event( + $config, + { + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + series_id => $params->{series_id}, + event_id => $params->{event_id} + } + ); + unless ( defined $event ) { + uac::print_error("event not found"); + } - my $editLock = 1; - if ( ( defined $permissions->{update_event_after_week} ) && ( $permissions->{update_event_after_week} eq '1' ) ) { - $editLock = 0; - } else { - $editLock = 0 - if ( - series::is_event_older_than_days( - $config, - { - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - series_id => $params->{series_id}, - event_id => $params->{event_id}, - max_age => 14 - } - ) == 0 - ); - } + my $editLock = 1; + if ( ( defined $permissions->{update_event_after_week} ) + && ( $permissions->{update_event_after_week} eq '1' ) ) + { + $editLock = 0; + } else { + $editLock = 0 + if ( + series::is_event_older_than_days( + $config, + { + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + series_id => $params->{series_id}, + event_id => $params->{event_id}, + max_age => 14 + } + ) == 0 + ); + } - # for rerun, deprecated - if ( defined $params->{source_event_id} ) { - my $event2 = series::get_event( - $config, - { - allow_any => 1, + # for rerun, deprecated + if ( defined $params->{source_event_id} ) { + my $event2 = series::get_event( + $config, + { + allow_any => 1, - #project_id => $params->{project_id}, - #studio_id => $params->{studio_id}, - #series_id => $params->{series_id}, - event_id => $params->{source_event_id}, - draft => 0, - } - ); - if ( defined $event2 ) { - for my $attr ( - 'title', 'user_title', 'excerpt', 'user_excerpt', 'content', 'topic', - 'image', 'live no_event_sync', 'podcast_url', 'archive_url' - ) - { - $event->{$attr} = $event2->{$attr}; - } - $event->{recurrence} = eventOps::getRecurrenceBaseId($event2); - $event->{rerun} = 1; - } - } + #project_id => $params->{project_id}, + #studio_id => $params->{studio_id}, + #series_id => $params->{series_id}, + event_id => $params->{source_event_id}, + draft => 0, + } + ); + if ( defined $event2 ) { + for my $attr ( + 'title', 'user_title', + 'excerpt', 'user_excerpt', + 'content', 'topic', + 'image', 'image_label', + 'series_image', 'series_image_label', + 'live no_event_sync', 'podcast_url', + 'archive_url', 'content_format' + ) + { + $event->{$attr} = $event2->{$attr}; + } + $event->{recurrence} = eventOps::getRecurrenceBaseId($event2); + $event->{rerun} = 1; + } + } - $event->{rerun} = 1 if ( $event->{rerun} =~ /a-z/ ); + $event->{rerun} = 1 if ( $event->{rerun} =~ /a-z/ ); + $event->{series_id} = $params->{series_id}; - $event->{series_id} = $params->{series_id}; - $event->{duration} = events::get_duration( $config, $event ); - $event->{durations} = \@durations; - if ( defined $event->{duration} ) { - for my $duration ( @{ $event->{durations} } ) { - $duration->{selected} = 1 if ( $event->{duration} eq $duration->{value} ); - } - } - $event->{start} =~ s/(\d\d:\d\d)\:\d\d/$1/; - $event->{end} =~ s/(\d\d:\d\d)\:\d\d/$1/; + $event->{duration} = events::get_duration( $config, $event ); + $event->{durations} = \@durations; + if ( defined $event->{duration} ) { + for my $duration ( @{ $event->{durations} } ) { + $duration->{selected} = 1 if ( $event->{duration} eq $duration->{value} ); + } + } + $event->{start} =~ s/(\d\d:\d\d)\:\d\d/$1/; + $event->{end} =~ s/(\d\d:\d\d)\:\d\d/$1/; - # overwrite event with old one - #my $series_events=get_series_events($config,{ - # project_id => $params->{project_id}, - # studio_id => $params->{studio_id}, - # series_id => $params->{series_id} - #}); - #my @series_events=(); - #for my $series_event (@$series_events){ - # push @series_events, $series_event if ($series_event->{start} lt $event->{start}); - #} - #$params->{series_events}=\@series_events; + if ( ( defined $params->{setImage} ) and ( $params->{setImage} ne $event->{image} ) ) { + $event->{image} = $params->{setImage}; + $params->{forced_change} = 1; + } - # get all series - #my $series=series::get( - # $config,{ - # project_id => $params->{project_id}, - # studio_id => $params->{studio_id}, - # } - #); - #for my $serie (@$series){ - # $serie->{selected}=1 if $params->{series_id}==$serie->{series_id}; - #} - #$params->{series}=$series; + # overwrite event with old one + #my $series_events=get_series_events($config,{ + # project_id => $params->{project_id}, + # studio_id => $params->{studio_id}, + # series_id => $params->{series_id} + #}); + #my @series_events=(); + #for my $series_event (@$series_events){ + # push @series_events, $series_event if ($series_event->{start} lt $event->{start}); + #} + #$params->{series_events}=\@series_events; - # get event series - my $series = series::get( - $config, - { - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - series_id => $params->{series_id} - } - ); - if ( @$series == 1 ) { - $event->{has_single_events} = $series->[0]->{has_single_events}; - } + # get all series + #my $series=series::get( + # $config,{ + # project_id => $params->{project_id}, + # studio_id => $params->{studio_id}, + # } + #); + #for my $serie (@$series){ + # $serie->{selected}=1 if $params->{series_id}==$serie->{series_id}; + #} + #$params->{series}=$series; - #$event->{rerun}=1 if ((defined $event->{rerun})&&($event->{rerun}ne'0')&&($event->{rerun}ne'')); + # get event series + my $series = series::get( + $config, + { + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + series_id => $params->{series_id} + } + ); + if ( scalar(@$series) == 1 ) { + $event->{has_single_events} = $series->[0]->{has_single_events}; + } - my $users = series::get_users( - $config, - { - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - series_id => $params->{series_id} - } - ); - $params->{series_users} = $users; + #$event->{rerun}=1 if ((defined $event->{rerun})&&($event->{rerun}ne'0')&&($event->{rerun}ne'')); - #print STDERR Dumper($users); - $params->{series_users_email_list} = join( ',', ( map { $_->{email} } (@$users) ) ); - $params->{series_user_names} = join( ' und ', ( map { ( split( /\s+/, $_->{full_name} ) )[0] } (@$users) ) ); + my $users = series::get_users( + $config, + { + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + series_id => $params->{series_id} + } + ); + $params->{series_users} = $users; - for my $permission ( sort keys %{$permissions} ) { - $params->{'allow'}->{$permission} = $permissions->{$permission}; - } + $params->{series_users_email_list} = join( ',', ( map { $_->{email} } (@$users) ) ); + $params->{series_user_names} = + join( ' und ', ( map { ( split( /\s+/, $_->{full_name} ) )[0] } (@$users) ) ); - for my $key ( keys %$event ) { - $params->{$key} = $event->{$key}; - } - $params->{event_edited} = 1 if ( ( $params->{action} eq 'save' ) && ( !( defined $params->{error} ) ) ); - $params->{event_edited} = 1 if ( $params->{action} eq 'delete' ); - $params->{event_edited} = 1 if ( ( $params->{action} eq 'create_event' ) && ( !( defined $params->{error} ) ) ); - $params->{event_edited} = 1 if ( ( $params->{action} eq 'create_event_from_schedule' ) && ( !( defined $params->{error} ) ) ); - $params->{user} = $params->{presets}->{user}; + for my $permission ( sort keys %{$permissions} ) { + $params->{'allow'}->{$permission} = $permissions->{$permission}; + } - # remove all edit permissions if event is over for more than 2 weeks - if ( $editLock == 1 ) { - for my $key ( keys %$params ) { - unless ( $key =~ /create_download/ ) { - delete $params->{allow}->{$key} if $key =~ /^(update|delete|create|assign)/; - } - } - $params->{edit_lock} = 1; - } + for my $key (sort keys %$event ) { + $params->{$key} = $event->{$key}; + } + $params->{event_edited} = 1 + if ( ( $params->{action} eq 'save' ) && ( !( defined $params->{error} ) ) ); + $params->{event_edited} = 1 if ( $params->{action} eq 'delete' ); + $params->{event_edited} = 1 + if ( ( $params->{action} eq 'create_event' ) && ( !( defined $params->{error} ) ) ); + $params->{event_edited} = 1 + if ( ( $params->{action} eq 'create_event_from_schedule' ) + && ( !( defined $params->{error} ) ) ); + $params->{user} = $params->{presets}->{user}; - #print STDERR Dumper($params); - $params->{loc} = localization::get( $config, { user => $params->{presets}->{user}, file => 'event' } ); - template::process( 'print', template::check('edit_event'), $params ); + # remove all edit permissions if event is over for more than 2 weeks + if ( $editLock == 1 ) { + for my $key ( keys %$params ) { + unless ( $key =~ /create_download/ ) { + delete $params->{allow}->{$key} if $key =~ /^(update|delete|create|assign)/; + } + } + $params->{edit_lock} = 1; + } + + for my $value ('markdown', 'creole'){ + $params->{"content_format_$value"}=1 if ($params->{content_format}//'') eq $value; + } + + $params->{loc} = + localization::get( $config, { user => $params->{presets}->{user}, file => 'event' } ); + template::process( $config, 'print', template::check( $config, 'edit-event' ), $params ); } sub getJson { - my $config = shift; - my $request = shift; + my $config = shift; + my $request = shift; - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; - for my $attr ( 'project_id', 'studio_id', 'series_id', 'event_id' ) { - unless ( defined $params->{$attr} ) { - uac::print_error( "missing " . $attr . " to show event" ); - return; - } - } + for my $attr ( 'project_id', 'studio_id', 'series_id', 'event_id' ) { + unless ( defined $params->{$attr} ) { + uac::print_error( "missing " . $attr . " to show event" ); + return; + } + } - my $result = series_events::check_permission( - $request, - { - permission => 'update_event_of_series,update_event_of_others', - check_for => [ 'studio', 'user', 'series', 'events' ], - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - series_id => $params->{series_id}, - event_id => $params->{event_id} - } - ); - unless ( $result eq '1' ) { - uac::print_error($result); - return undef; - } - $permissions->{update_event} = 1; + my $result = series_events::check_permission( + $request, + { + permission => 'update_event_of_series,update_event_of_others', + check_for => [ 'studio', 'user', 'series', 'events' ], + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + series_id => $params->{series_id}, + event_id => $params->{event_id} + } + ); + unless ( $result eq '1' ) { + uac::print_error($result); + return undef; + } + $permissions->{update_event} = 1; - my $event = series::get_event( - $config, - { - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - series_id => $params->{series_id}, - event_id => $params->{event_id} - } - ); - unless ( defined $event ) { - uac::print_error("event not found"); - } + my $event = series::get_event( + $config, + { + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + series_id => $params->{series_id}, + event_id => $params->{event_id} + } + ); + unless ( defined $event ) { + uac::print_error("event not found"); + } - $event->{rerun} = 1 if ( $event->{rerun} =~ /a-z/ ); - $event->{series_id} = $params->{series_id}; - $event->{start} =~ s/(\d\d:\d\d)\:\d\d/$1/; - $event->{end} =~ s/(\d\d:\d\d)\:\d\d/$1/; + $event->{rerun} = 1 if ( $event->{rerun} =~ /a-z/ ); + $event->{series_id} = $params->{series_id}; + $event->{start} =~ s/(\d\d:\d\d)\:\d\d/$1/; + $event->{end} =~ s/(\d\d:\d\d)\:\d\d/$1/; - # get event series - my $series = series::get( - $config, - { - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - series_id => $params->{series_id} - } - ); + # get event series + my $series = series::get( + $config, + { + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + series_id => $params->{series_id} + } + ); - if ( @$series == 1 ) { - my $serie = $series->[0]; - $event->{has_single_events} = $serie->{has_single_events}; - if ( $event->{has_single_events} eq '1' ) { - $event->{has_single_events} = 1; - $event->{series_name} = undef; - $event->{episode} = undef; - } - } + if ( scalar @$series == 1 ) { + my $serie = $series->[0]; + $event->{has_single_events} = $serie->{has_single_events}; + if ( $event->{has_single_events} eq '1' ) { + $event->{has_single_events} = 1; + $event->{series_name} = undef; + $event->{episode} = undef; + } + } - $event->{duration} = events::get_duration( $config, $event ); + $event->{duration} = events::get_duration( $config, $event ); - # for rerun - if ( $params->{get_rerun} == 1 ) { - $event->{rerun} = 1; - $event->{recurrence} = eventOps::getRecurrenceBaseId($event); + # for rerun + if ( $params->{get_rerun} == 1 ) { + $event->{recurrence} = eventOps::getRecurrenceBaseId($event); + for my $key ( 'live', 'published', 'playout', 'archived', 'disable_event_sync', 'draft' ){ + $event->{$key}=0; + } + $event->{rerun} = 1; - #$event=events::calc_dates($config, $event); - } + #$event=events::calc_dates($config, $event); + } - #print to_json($event); - template::process( 'print', 'json-p', $event ); + #print to_json($event); + template::process( $config, 'print', 'json-p', $event ); } #show new event from schedule sub show_new_event { - my $config = shift; - my $request = shift; + my $config = shift; + my $request = shift; - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; - if ( $params->{action} eq 'show_new_event' ) { - $params->{show_new_event} = 1; - unless ( $permissions->{create_event} == 1 ) { - uac::permissions_denied('create_event'); - return; - } - } elsif ( $params->{action} eq 'show_new_event_from_schedule' ) { - $params->{show_new_event_from_schedule} = 1; - unless ( $permissions->{create_event_from_schedule} == 1 ) { - uac::permissions_denied('create_event_from_schedule'); - return; - } - } else { - uac::print_error("invalid action"); - return 1; - } + if ( $params->{action} eq 'show_new_event' ) { + $params->{show_new_event} = 1; + unless ( $permissions->{create_event} == 1 ) { + uac::permissions_denied('create_event'); + return; + } + } elsif ( $params->{action} eq 'show_new_event_from_schedule' ) { + $params->{show_new_event_from_schedule} = 1; + unless ( $permissions->{create_event_from_schedule} == 1 ) { + uac::permissions_denied('create_event_from_schedule'); + return; + } + } else { + uac::print_error("invalid action"); + return 1; + } - # check for missing parameters - my $required_fields = [ 'project_id', 'studio_id', 'series_id' ]; - push @$required_fields, 'start_date' if ( $params->{action} eq 'show_new_event_from_schedule' ); + my $event = eventOps::getNewEvent( $config, $params, $params->{action} ); - my $event = {}; - for my $attr (@$required_fields) { - unless ( defined $params->{$attr} ) { - uac::print_error( "missing " . $attr ); - return; - } - $event->{$attr} = $params->{$attr}; - } + #copy event to template params + for my $key ( keys %$event ) { + $params->{$key} = $event->{$key}; + } - my $serie = eventOps::setAttributesFromSeriesTemplate( $config, $params, $event ); + #add duration selectbox + #TODO: move to javascript + my @durations = (); + for my $duration ( @{ time::getDurations() } ) { + my $entry = { + name => sprintf( "%02d:%02d", $duration / 60, $duration % 60 ), + value => $duration + }; + push @durations, $entry; + } + $params->{durations} = \@durations; - if ( $params->{action} eq 'show_new_event_from_schedule' ) { - eventOps::setAttributesFromSchedule( $config, $params, $event ); - } else { - eventOps::setAttributesForCurrentTime( $serie, $event ); - } + #set duration preset + for my $duration ( @{ $params->{durations} } ) { + $duration->{selected} = 1 if ( $event->{duration} eq $duration->{value} ); + } - if ( defined $params->{source_event_id} ) { + #check user permissions and then: + $permissions->{update_event} = 1; - #overwrite by existing event (rerun) - eventOps::setAttributesFromOtherEvent( $config, $params, $event ); - } + #set permissions to template + for my $permission ( keys %{ $request->{permissions} } ) { + $params->{'allow'}->{$permission} = $request->{permissions}->{$permission}; + } - $event = events::calc_dates( $config, $event ); + for my $value ('markdown', 'creole'){ + $params->{"content_format_$value"}=1 if ($params->{content_format}//'') eq $value; + } - if ( $serie->{has_single_events} eq '1' ) { - $event->{has_single_events} = 1; - $event->{series_name} = undef; - $event->{episode} = undef; - } - - #get next episode - $event->{episode} = series::get_next_episode( - $config, - { - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - series_id => $params->{series_id}, - } - ); - delete $event->{episode} if $event->{episode} == 0; - - $event->{disable_event_sync} = 1; - $event->{published} = 1; - $event->{new_event} = 1; - - #copy event to template params - for my $key ( keys %$event ) { - $params->{$key} = $event->{$key}; - } - - #add duration selectbox - #TODO: move to javascript - my @durations = (); - for my $duration ( @{ time::get_durations() } ) { - my $entry = { - name => sprintf( "%02d:%02d", $duration / 60, $duration % 60 ), - value => $duration - }; - push @durations, $entry; - } - $params->{durations} = \@durations; - - #set duration preset - for my $duration ( @{ $params->{durations} } ) { - $duration->{selected} = 1 if ( $event->{duration} eq $duration->{value} ); - } - - #check user permissions and then: - $permissions->{update_event} = 1; - - #set permissions to template - for my $permission ( keys %{ $request->{permissions} } ) { - $params->{'allow'}->{$permission} = $request->{permissions}->{$permission}; - } - - $params->{loc} = localization::get( $config, { user => $params->{presets}->{user}, file => 'event,comment' } ); - template::process( 'print', template::check('edit_event'), $params ); - - #print '<pre>'.Dumper($params).'</pre>'; + $params->{loc} = + localization::get( $config, { user => $params->{presets}->{user}, file => 'event,comment' } ); + template::process( $config, 'print', template::check( $config, 'edit-event' ), $params ); } sub delete_event { - my $config = shift; - my $request = shift; + my $config = shift; + my $request = shift; - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; - my $event = {}; - for my $attr ( 'project_id', 'studio_id', 'series_id', 'event_id' ) { - unless ( defined $params->{$attr} ) { - uac::print_error( "missing " . $attr ); - return; - } - $event->{$attr} = $params->{$attr}; - } + my $event = {}; + for my $attr ( 'project_id', 'studio_id', 'series_id', 'event_id' ) { + unless ( defined $params->{$attr} ) { + uac::print_error( "missing " . $attr ); + return; + } + $event->{$attr} = $params->{$attr}; + } - my $result = series_events::check_permission( - $request, - { - permission => 'delete_event', - check_for => [ 'studio', 'user', 'series', 'events', 'event_age' ], - project_id => $params->{project_id}, - studio_id => $event->{studio_id}, - series_id => $event->{series_id}, - event_id => $event->{event_id} - } - ); - unless ( $result eq '1' ) { - uac::print_error($result); - return undef; - } + my $result = series_events::check_permission( + $request, + { + permission => 'delete_event', + check_for => [ 'studio', 'user', 'series', 'events', 'event_age' ], + project_id => $params->{project_id}, + studio_id => $event->{studio_id}, + series_id => $event->{series_id}, + event_id => $event->{event_id} + } + ); + unless ( $result eq '1' ) { + uac::print_error($result); + return undef; + } - $config->{access}->{write} = 1; + $config->{access}->{write} = 1; - #set user to be added to history - $event->{user} = $params->{presets}->{user}; - $result = series_events::delete_event( $config, $event ); - unless ( defined $result ) { - uac::print_error('could not delete event'); - return undef; - } + #set user to be added to history + $event->{user} = $params->{presets}->{user}; + $result = series_events::delete_event( $config, $event ); + unless ( defined $result ) { + uac::print_error('could not delete event'); + return undef; + } - user_stats::increase( - $config, - 'delete_events', - { - project_id => $event->{project_id}, - studio_id => $event->{studio_id}, - series_id => $event->{series_id}, - user => $event->{user} - } - ); + user_stats::increase( + $config, + 'delete_events', + { + project_id => $event->{project_id}, + studio_id => $event->{studio_id}, + series_id => $event->{series_id}, + user => $event->{user} + } + ); - uac::print_info("event deleted"); + uac::print_info("event deleted"); } #save existing event sub save_event { - my $config = shift; - my $request = shift; + my $config = shift; + my $request = shift; - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; - for my $attr ( 'project_id', 'studio_id', 'series_id', 'event_id' ) { - unless ( defined $params->{$attr} ) { - uac::print_error( "missing " . $attr . " to show event" ); - return; - } - } + for my $attr ( 'project_id', 'studio_id', 'series_id', 'event_id' ) { + unless ( defined $params->{$attr} ) { + uac::print_error( "missing " . $attr . " to show event" ); + return; + } + } - #print Dumper($params); - my $start = $params->{start_date}, my $end = time::add_minutes_to_datetime( $params->{start_date}, $params->{duration} ); + my $start = $params->{start_date}; + my $end = time::add_minutes_to_datetime( $params->{start_date}, $params->{duration} ); - #check permissions - my $options = { - permission => 'update_event_of_series,update_event_of_others', - check_for => [ 'studio', 'user', 'series', 'events', 'studio_timeslots', 'event_age' ], - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - series_id => $params->{series_id}, - event_id => $params->{event_id}, - draft => $params->{draft}, - start => $start, - end => $end, - }; + #check permissions + my $options = { + permission => 'update_event_of_series,update_event_of_others', + check_for => [ 'studio', 'user', 'series', 'events', 'studio_timeslots', 'event_age' ], + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + series_id => $params->{series_id}, + event_id => $params->{event_id}, + draft => $params->{draft}, + start => $start, + end => $end, + }; - my $result = series_events::check_permission( $request, $options ); - unless ( $result eq '1' ) { - uac::print_error($result); - return; - } + my $result = series_events::check_permission( $request, $options ); + unless ( $result eq '1' ) { + uac::print_error($result); + return; + } - #changed columns depending on permissions - my $entry = { id => $params->{event_id} }; + #changed columns depending on permissions + my $entry = { id => $params->{event_id} }; - my $found = 0; + my $found = 0; - #content fields - for my $key ( 'content', 'topic', 'title', 'excerpt', 'episode', 'image', 'podcast_url', 'archive_url' ) { - next unless defined $permissions->{ 'update_event_field_' . $key }; - if ( $permissions->{ 'update_event_field_' . $key } eq '1' ) { - $entry->{$key} = $params->{$key} if defined $params->{$key}; - $found++; - } - } + #content fields + for my $key ( + 'content', 'topic', 'title', 'excerpt', + 'episode', 'image', 'series_image', 'image_label', + 'series_image_label', 'podcast_url', 'archive_url', 'content_format' + ) + { + next unless defined $permissions->{ 'update_event_field_' . $key }; + if ( $permissions->{ 'update_event_field_' . $key } eq '1' ) { + next unless defined $params->{$key}; + $entry->{$key} = $params->{$key}; + $found++; + } + } - #user extension fields - for my $key ( 'title', 'excerpt' ) { - next unless defined $permissions->{ 'update_event_field_' . $key . '_extension' }; - if ( $permissions->{ 'update_event_field_' . $key . '_extension' } eq '1' ) { - $entry->{ 'user_' . $key } = $params->{ 'user_' . $key } if defined $params->{ 'user_' . $key }; - $found++; - } - } + #user extension fields + for my $key ( 'title', 'excerpt' ) { + next unless defined $permissions->{ 'update_event_field_' . $key . '_extension' }; + if ( $permissions->{ 'update_event_field_' . $key . '_extension' } eq '1' ) { + next unless defined $params->{ 'user_' . $key }; + $entry->{ 'user_' . $key } = $params->{ 'user_' . $key }; + $found++; + } + } - #status field - for my $key ( 'live', 'published', 'playout', 'archived', 'rerun', 'disable_event_sync', 'draft' ) { - next unless defined $permissions->{ 'update_event_status_' . $key }; - if ( $permissions->{ 'update_event_status_' . $key } eq '1' ) { - $entry->{$key} = $params->{$key} || 0; - $found++; - } - } + #status field + for + my $key ( 'live', 'published', 'playout', 'archived', 'rerun', 'disable_event_sync', 'draft' ) + { + next unless defined $permissions->{ 'update_event_status_' . $key }; + if ( $permissions->{ 'update_event_status_' . $key } eq '1' ) { + $entry->{$key} = $params->{$key} || 0; + $found++; + } + } - $entry->{modified_by} = $params->{presets}->{user}; + $entry->{modified_by} = $params->{presets}->{user}; - #get event from database (for history) - my $event = series::get_event( - $config, - { - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - series_id => $params->{series_id}, - event_id => $params->{event_id} - } - ); - unless ( defined $event ) { - uac::print_error("event not found"); - return; - } + #get event from database (for history) + my $event = series::get_event( + $config, + { + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + series_id => $params->{series_id}, + event_id => $params->{event_id} + } + ); + unless ( defined $event ) { + uac::print_error("event not found"); + return; + } - $config->{access}->{write} = 1; + # set series image + my $series = series::get( + $config, + { + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + series_id => $params->{series_id}, + } + ); + my $serie = $series->[0]; + unless ( defined $serie ) { + uac::print_error("series not found"); + return; + } + $entry->{image} = $serie->{series_image} if !$serie->{image} && $serie->{series_image}; + $entry->{image} = images::normalizeName( $entry->{image} ); + $entry->{series_image} = images::normalizeName( $serie->{series_image} ); - #update content - if ( $found > 0 ) { - $entry = series_events::save_content( $config, $entry ); - for my $key ( keys %$entry ) { - $event->{$key} = $entry->{$key}; - } - } + $config->{access}->{write} = 1; - #update time - if ( ( defined $permissions->{update_event_time} ) && ( $permissions->{update_event_time} eq '1' ) ) { - my $entry = { - id => $params->{event_id}, - start_date => $params->{start_date}, - duration => $params->{duration}, + #update content + if ( $found > 0 ) { + $entry = series_events::save_content( $config, $entry ); + for my $key ( keys %$entry ) { + $event->{$key} = $entry->{$key}; + } + } - # end => $params->{end_date} , - }; - $entry = series_events::save_event_time( $config, $entry ); - for my $key ( keys %$entry ) { - $event->{$key} = $entry->{$key}; - } - } + #update time + if ( ( defined $permissions->{update_event_time} ) + && ( $permissions->{update_event_time} eq '1' ) ) + { + my $entry = { + id => $params->{event_id}, + start_date => $params->{start_date}, + duration => $params->{duration}, - $event->{project_id} = $params->{project_id}; - $event->{studio_id} = $params->{studio_id}; - $event->{series_id} = $params->{series_id}; - $event->{event_id} = $params->{event_id}; - $event->{user} = $params->{presets}->{user}; + # end => $params->{end_date} , + }; + $entry = series_events::save_event_time( $config, $entry ); + for my $key ( keys %$entry ) { + $event->{$key} = $entry->{$key}; + } + } - #update recurrences - series::update_recurring_events( $config, $event ); + $event->{project_id} = $params->{project_id}; + $event->{studio_id} = $params->{studio_id}; + $event->{series_id} = $params->{series_id}; + $event->{event_id} = $params->{event_id}; + $event->{user} = $params->{presets}->{user}; - #update history - event_history::insert( $config, $event ); + #update recurrences + series::update_recurring_events( $config, $event ); - user_stats::increase( - $config, - 'update_events', - { - project_id => $event->{project_id}, - studio_id => $event->{studio_id}, - series_id => $event->{series_id}, - user => $event->{user} - } - ); + #update history + event_history::insert( $config, $event ); - #print "error" unless (defined $result); - $config->{access}->{write} = 0; - uac::print_info("event saved"); + user_stats::increase( + $config, + 'update_events', + { + project_id => $event->{project_id}, + studio_id => $event->{studio_id}, + series_id => $event->{series_id}, + user => $event->{user} + } + ); + + #print "error" unless (defined $result); + $config->{access}->{write} = 0; + uac::print_info("event saved"); } sub create_event { - my $config = shift; - my $request = shift; + my $config = shift; + my $request = shift; - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; + my $params = $request->{params}->{checked}; + my $event = $request->{params}->{checked}; + my $action = $params->{action}; + return eventOps::createEvent( $request, $event, $action ); +} - my $checklist = [ 'studio', 'user', 'create_events', 'studio_timeslots' ]; - if ( $params->{action} eq 'create_event_from_schedule' ) { - push @$checklist, 'schedule' if $params->{action} eq 'create_event_from_schedule'; - } +sub get_download_event{ + my $config = shift; + my $request = shift; - my $start = $params->{start_date}, my $end = time::add_minutes_to_datetime( $params->{start_date}, $params->{duration} ); + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; - my $result = series_events::check_permission( - $request, - { - permission => 'create_event,create_event_of_series', - check_for => $checklist, - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - series_id => $params->{series_id}, - start_date => $params->{start_date}, - draft => $params->{draft}, - start => $start, - end => $end, - } - ); + my $result = series_events::check_permission( + $request, + { + permission => 'update_event_of_series,update_event_of_others', + check_for => [ 'studio', 'user', 'series', 'events' ], + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + series_id => $params->{series_id}, + event_id => $params->{event_id} + } + ); + unless ( $result eq '1' ) { + uac::print_error($result); + return undef; + } + $permissions->{update_event} = 1; - #print Dumper(" start_date => $params->{start_date}"); - unless ( $result eq '1' ) { - uac::print_error($result); - return undef; - } + my $request2 = { + params => { + checked => events::check_params( + $config, + { + event_id => $params->{event_id}, + template => 'no', + limit => 1, - #get series name from series - my $series = series::get( - $config, - { - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - series_id => $params->{series_id}, - } - ); - if ( @$series != 1 ) { - uac::print_error("series not found"); - return undef; - } - my $serie = $series->[0]; + #no_exclude => 1 + } + ) + }, + config => $request->{config}, + permissions => $request->{permissions} + }; - #get studio location from studios - my $studios = studios::get( - $config, - { - project_id => $params->{project_id}, - studio_id => $params->{studio_id} - } - ); - unless ( defined $studios ) { - uac::print_error("studio not found"); - return undef; - } - unless ( @$studios == 1 ) { - uac::print_error("studio not found"); - return undef; - } - my $studio = $studios->[0]; - - $config->{access}->{write} = 1; - - #insert event content and save history - my $event_id = series_events::insert_event( - $config, - { - project_id => $params->{project_id}, - studio => $studio, - serie => $serie, - event => $params, - user => $params->{presets}->{user} - } - ); - uac::print_error("could not insert event") if $event_id <= 0; - - #assign event to series - $result = series::assign_event( - $config, - { - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - series_id => $params->{series_id}, - event_id => $event_id - } - ); - uac::print_error("could not assign event") unless defined $result; - - #update recurrences - my $event = $params; - $event->{event_id} = $event_id; - series::update_recurring_events( $config, $event ); - - # update user stats - user_stats::increase( - $config, - 'create_events', - { - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - series_id => $params->{series_id}, - user => $params->{presets}->{user} - } - ); - - #forward to edit event - #print STDERR Dumper($event_id); - #$params->{event_id}=$event_id; - uac::print_info("event created"); - return $event_id; + $request2->{params}->{checked}->{published} = 'all'; + my $events = events::get( $config, $request2 ); + my $event = $events->[0]; + return $event; } #TODO: replace permission check with download sub download { - my $config = shift; - my $request = shift; + my $config = shift; + my $request = shift; + + my $event = get_download_event($config, $request); + my $datetime = $event->{start_datetime}; + if ( $datetime =~ /(\d\d\d\d\-\d\d\-\d\d)[ T](\d\d)\:(\d\d)/ ) { + $datetime = $1 . '\ ' . $2 . '_' . $3; + } else { + print STDERR "event.cgi::download no valid datetime found $datetime\n"; + return; + } + my $archive_dir = $config->{locations}->{local_archive_dir}; + my $archive_url = $config->{locations}->{local_archive_url}; + print STDERR "archive_dir: " . $archive_dir . "\n"; + print STDERR "archive_url: " . $archive_url . "\n"; + print STDERR "event.cgi::download look for : $archive_dir/$datetime*.mp3\n"; + my @files = glob( $archive_dir . '/' . $datetime . '*.mp3' ); - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; + if ( @files > 0 ) { + my $file = $files[0]; + my $key = int( rand(99999999999999999) ); + $key = MIME::Base64::encode_base64($key); + $key =~ s/[^a-zA-Z0-9]//g; + $key = 'shared-'.$key; - my $result = series_events::check_permission( - $request, - { - permission => 'update_event_of_series,update_event_of_others', - check_for => [ 'studio', 'user', 'series', 'events' ], - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - series_id => $params->{series_id}, - event_id => $params->{event_id} - } - ); - unless ( $result eq '1' ) { - uac::print_error($result); - return undef; - } - $permissions->{update_event} = 1; + #decode filename + $file = Encode::decode( "UTF-8", $file ); - my $request2 = { - params => { - checked => events::check_params( - $config, - { - event_id => $params->{event_id}, - template => 'no', - limit => 1, - } - ) - }, - config => $request->{config}, - permissions => $request->{permissions} - }; + my $cmd = "ln -s '" . $file . "' '" . $archive_dir . '/' . $key . ".mp3'"; + my $url = $archive_url . '/' . $key . '.mp3'; - $request2->{params}->{checked}->{published} = 'all'; - my $events = events::get( $config, $request2 ); - my $event = $events->[0]; - my $datetime = $event->{start_datetime}; - if ( $datetime =~ /(\d\d\d\d\-\d\d\-\d\d)[ T](\d\d)\:(\d\d)/ ) { - $datetime = $1 . '\ ' . $2 . '_' . $3; - } else { - print STDERR "event.cgi::download no valid datetime found $datetime\n"; - return; - } - my $archive_dir = $config->{locations}->{local_archive_dir}; - my $archive_url = $config->{locations}->{local_archive_url}; - print STDERR "archive_dir: " . $archive_dir . "\n"; - print STDERR "archive_url: " . $archive_url . "\n"; - print STDERR "event.cgi::download look for : $archive_dir/$datetime*.mp3\n"; - my @files = glob( $archive_dir . '/' . $datetime . '*.mp3' ); + #print $cmd."\n"; + print `$cmd`; - #print STDERR Dumper(\@files); - if ( @files > 0 ) { - my $file = $files[0]; - my $key = int( rand(99999999999999999) ); - $key = encode_base64($key); - $key =~ s/[^a-zA-Z0-9]//g; + $request->{params}->{checked}->{download} = '' + . qq{<a href="$url" style="color:#39a1f4;" download="$event->{series_name}#$event->{episode}.mp3">} + . q{Download: } + . $event->{start_date_name} . ", " + . $event->{start_time_name} . " - " + . $event->{full_title} + . qq{</a>\n} + . qq{<pre>$url</pre>\n} + . qq{\nDer Link wird nach 7 Tagen geloescht.}; + } +} - #decode filename - $file = Encode::decode( "UTF-8", $file ); +sub download_audio { + my $config = shift; + my $request = shift; - my $cmd = "ln -s '" . $file . "' '" . $archive_dir . '/' . $key . ".mp3'"; - my $url = $archive_url . '/' . $key . '.mp3'; - - #print $cmd."\n"; - print `$cmd`; - - $request->{params}->{checked}->{download} = - "Hallo,\n\n" - . "anbei der Mitschnitt fuer\n" - . $event->{start_date_name} . ", " - . $event->{start_time_name} . " - " - . $event->{series_name} . ' - ' - . $event->{title} . ":\n" - . $url . "\n" - . "\nDer Link wird nach 7 Tagen geloescht. (bitte nicht weitergeben)\n" - . "Gruss, Peter\n"; - } + my $event = get_download_event($config, $request); + my $datetime = $event->{start_datetime}; + if ( $datetime =~ /(\d\d\d\d\-\d\d\-\d\d)[ T](\d\d)\:(\d\d)/ ) { + $datetime = $1 . '\ ' . $2 . '_' . $3; + } else { + print STDERR "event.cgi::download no valid datetime found $datetime\n"; + return; + } + my $archive_dir = $config->{locations}->{local_archive_dir}; + print STDERR "archive_dir: " . $archive_dir . "\n"; + print STDERR "event.cgi::download look for : $archive_dir/$datetime*.mp3\n"; + my @files = glob( $archive_dir . '/' . $datetime . '*.mp3' ); + if ( @files > 0 ) { + my $file = $files[0]; + $file = Encode::decode( "UTF-8", $file ); + print qq{Content-Disposition: attachment; filename="}.basename($file).qq{"\n}; + print qq{Content-Type: audio/mpeg\n\n}; + binmode STDOUT; + open my $fh, '<:raw', $file; + while (<$fh>){ + print $_; + } + close $fh; + } } sub check_params { - my $params = shift; + my $config = shift; + my $params = shift; - my $checked = {}; - my $template = ''; - $checked->{template} = template::check( $params->{template}, 'series' ); + my $checked = {}; + my $template = ''; + $checked->{template} = template::check( $config, $params->{template}, 'series' ); - my $debug = $params->{debug} || ''; - if ( $debug =~ /([a-z\_\,]+)/ ) { - $debug = $1; - } - $checked->{debug} = $debug; + entry::set_numbers( $checked, $params, [ + 'id', 'project_id', 'studio_id', 'default_studio_id', + 'user_id', 'series_id', 'event_id', 'source_event_id', + 'episode' + ]); - #numeric values - for my $param ( 'id', 'project_id', 'studio_id', 'default_studio_id', 'user_id', 'series_id', 'event_id', 'source_event_id', 'episode' ) - { - if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /^\d+$/ ) ) { - $checked->{$param} = $params->{$param}; - } - } + if ( defined $checked->{studio_id} ) { + $checked->{default_studio_id} = $checked->{studio_id}; + } else { + $checked->{studio_id} = -1; + } - if ( defined $checked->{studio_id} ) { - $checked->{default_studio_id} = $checked->{studio_id}; - } else { - $checked->{studio_id} = -1; - } + #scalars + entry::set_strings( $checked, $params, [ + 'studio', 'search', 'from', 'till', 'hide_series' + ]); - #scalars - for my $param ( 'studio', 'search', 'from', 'till', 'hide_series' ) { - if ( defined $params->{$param} ) { - $checked->{$param} = $params->{$param}; - $checked->{$param} =~ s/^\s+//g; - $checked->{$param} =~ s/\s+$//g; - } - } + entry::set_numbers( $checked, $params, [ + 'duration', 'recurrence' ]); - #numbers - for my $param ( 'duration', 'recurrence' ) { - if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /(\d+)/ ) ) { - $checked->{$param} = $1; - } - } + entry::set_bools( $checked, $params, [ + 'live', 'published', 'playout', 'archived', + 'rerun', 'draft', 'disable_event_sync', 'get_rerun' + ]); - #checkboxes - for my $param ( 'live', 'published', 'playout', 'archived', 'rerun', 'draft', 'disable_event_sync', 'get_rerun' ) { - if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /([01])/ ) ) { - $checked->{$param} = $1; - # print STDERR "check $param = $1\n"; - } - } + entry::set_strings( $checked, $params, [ + 'series_name', 'title', 'excerpt', 'content', + 'topic', 'program', 'image', + 'series_image', 'user_content', 'user_title', 'user_excerpt', + 'podcast_url', 'archive_url', 'setImage', 'content_format' + ]); + + #dates + for my $param ( 'start_date', 'end_date' ) { + if ( ( defined $params->{$param} ) + && ( $params->{$param} =~ /(\d\d\d\d\-\d\d\-\d\d \d\d\:\d\d)/ ) ) + { + $checked->{$param} = $1 . ':00'; + } + } - #strings - for my $param ( - 'series_name', 'title', 'excerpt', 'content', 'topic', 'program', 'category', 'image', - 'user_content', 'user_title', 'user_excerpt', 'podcast_url', 'archive_url' - ) - { - if ( defined $params->{$param} ) { - - #$checked->{$param}=uri_unescape(); - $checked->{$param} = $params->{$param}; - $checked->{$param} =~ s/^\s+//g; - $checked->{$param} =~ s/\s+$//g; - } - } - - #dates - for my $param ( 'start_date', 'end_date' ) { - if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /(\d\d\d\d\-\d\d\-\d\d \d\d\:\d\d)/ ) ) { - $checked->{$param} = $1 . ':00'; - } - } - - #actions and roles - $checked->{action} = ''; - if ( defined $params->{action} ) { - if ( $params->{action} =~ - /^(save|delete|download|show_new_event|show_new_event_from_schedule|create_event|create_event_from_schedule|get_json)$/ ) - { - $checked->{action} = $params->{action}; - } - } - - #print STDERR Dumper($checked); - return $checked; + $checked->{action} = entry::element_of( $params->{action}, + [ 'save', 'delete', 'download', 'download_audio', 'show_new_event', + 'show_new_event_from_schedule', + 'create_event', 'create_event_from_schedule', 'get_json' + ] + )//''; + return $checked; } - -__DATA__ - -#requires studio_id,series_id,location -sub get_series_events{ - my $config=shift; - my $options=shift; - - return undef unless defined $options->{project_id}; - return undef unless defined $options->{studio_id}; - return undef unless defined $options->{series_id}; - - $options->{template}= 'no'; # deprecated - $options->{limit} = 200; # deprecated - $options->{get} = 'no_content'; # deprecated - $options->{archive} = 'all'; # deprecated - - my $events=series::get_events($config, $options); - return $events; -} - diff --git a/website/agenda/planung/event_history.cgi b/website/agenda/planung/event_history.cgi deleted file mode 100755 index fb729df..0000000 --- a/website/agenda/planung/event_history.cgi +++ /dev/null @@ -1,241 +0,0 @@ -#! /usr/bin/perl -w - -use warnings "all"; -use strict; -use URI::Escape; -use Encode; -use Data::Dumper; -use MIME::Base64; - -#use Text::Diff (); -use Text::Diff::FormattedHTML; - -use params; -use config; -use log; -use template; -use db; -use auth; -use uac; - -#use roles; -use time; -use markup; -use studios; -use event_history; -use events; - -#use series; -#use series_dates; -use series_events; -use localization; -binmode STDOUT, ":utf8"; - -my $r = shift; -( my $cgi, my $params, my $error ) = params::get($r); - -my $config = config::get('../config/config.cgi'); -my $debug = $config->{system}->{debug}; -my ( $user, $expires ) = auth::get_user( $cgi, $config ); -return if ( ( !defined $user ) || ( $user eq '' ) ); - -my $user_presets = uac::get_user_presets( $config, { user => $user, studio_id => $params->{studio_id} } ); -$params->{default_studio_id} = $user_presets->{studio_id}; -$params->{studio_id} = $params->{default_studio_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); - -my $request = { - url => $ENV{QUERY_STRING} || '', - params => { - original => $params, - checked => check_params($params), - }, -}; - -#print STDERR Dumper($request)."\n"; - -#set user at params->presets->user -$request = uac::prepare_request( $request, $user_presets ); -log::init($request); - -$params = $request->{params}->{checked}; - -#show header -my $headerParams = uac::set_template_permissions( $request->{permissions}, $params ); -$headerParams->{loc} = localization::get( $config, { user => $user, file => 'menu' } ); -template::process( 'print', template::check('default.html'), $headerParams ); -return unless uac::check( $config, $params, $user_presets ) == 1; - -print q{ - <script src="js/datetime.js" type="text/javascript"></script> - <script src="js/event.js" type="text/javascript"></script> - <link rel="stylesheet" href="css/event.css" type="text/css" /> -}; - -$config->{access}->{write} = 0; -if ( $params->{action} eq 'diff' ) { - compare( $config, $request ); - return; -} -show_history( $config, $request ); - -#show existing event history -sub show_history { - my $config = shift; - my $request = shift; - - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - for my $attr ('studio_id') { # 'series_id','event_id' - unless ( defined $params->{$attr} ) { - uac::print_error( "missing " . $attr . " to show changes" ); - return; - } - } - - unless ( $permissions->{read_event} == 1 ) { - uac::print_error("missing permissions to show changes"); - return; - } - - my $options = { - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - limit => 200 - }; - $options->{series_id} = $params->{series_id} if defined $params->{series_id}; - $options->{event_id} = $params->{event_id} if defined $params->{event_id}; - - my $events = event_history::get( $config, $options ); - - #print STDERR Dumper($events); - return unless defined $events; - $params->{events} = $events; - - for my $permission ( keys %{$permissions} ) { - $params->{'allow'}->{$permission} = $request->{permissions}->{$permission}; - } - - #print STDERR Dumper($params); - $params->{loc} = localization::get( $config, { user => $params->{presets}->{user}, file => 'event_history' } ); - - template::process( 'print', template::check('event_history'), $params ); -} - -#show existing event history -sub compare { - my $config = shift; - my $request = shift; - - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - for my $attr ( 'project_id', 'studio_id', 'event_id', 'v1', 'v2' ) { - unless ( defined $params->{$attr} ) { - uac::print_error( "missing " . $attr . " to show changes" ); - return; - } - } - - unless ( $permissions->{read_event} == 1 ) { - uac::print_error("missing permissions to show changes"); - return; - } - - print qq{<link href="css/diff.css" rel="stylesheet">} . "\n"; - - if ( $params->{v1} > $params->{v2} ) { - my $t = $params->{v1}; - $params->{v1} = $params->{v2}; - $params->{v2} = $t; - } - - my $options = { - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - series_id => $params->{series_id}, - event_id => $params->{event_id}, - change_id => $params->{v1}, - limit => 2 - }; - - my $events = event_history::get( $config, $options ); - return unless @$events == 1; - my $v1 = $events->[0]; - - $options->{change_id} = $params->{v2}; - $events = event_history::get( $config, $options ); - return unless @$events == 1; - my $v2 = $events->[0]; - - my $t1 = eventToText($v1); - my $t2 = eventToText($v2); - - if ( $t1 eq $t2 ) { - print "no changes\n"; - return; - } - - #print "<style>".diff_css."</style>"; - #print '<pre>'; - #my $diff=diff_strings( { vertical => 1 }, $t1, $t2); - my $diff = diff_strings( {}, $t1, $t2 ); - - #print Text::Diff::diff(\$t1, \$t2, { STYLE => "Table" }); - #print Text::Diff::diff($v1, $v2, { STYLE => "Table" }); - print $diff; - - #print '</pre>'; -} - -sub eventToText { - my $event = shift; - - my $s = events::get_keys($event)->{full_title} . "\n"; - $s .= $event->{excerpt} . "\n"; - $s .= $event->{user_excerpt} . "\n"; - $s .= $event->{topic} . "\n"; - $s .= $event->{content} . "\n"; - - #print STDERR "DUMP\n$s"; - return $s; - -} - -sub check_params { - my $params = shift; - - my $checked = {}; - my $template = ''; - $checked->{template} = template::check( $params->{template}, 'event_history' ); - - my $debug = $params->{debug} || ''; - if ( $debug =~ /([a-z\_\,]+)/ ) { - $debug = $1; - } - $checked->{debug} = $debug; - - #numeric values - for my $param ( 'id', 'project_id', 'studio_id', 'default_studio_id', 'user_id', 'series_id', 'event_id', 'v1', 'v2' ) { - if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /^\d+$/ ) ) { - $checked->{$param} = $params->{$param}; - } - } - - if ( defined $checked->{studio_id} ) { - $checked->{default_studio_id} = $checked->{studio_id}; - } else { - $checked->{studio_id} = -1; - } - - #actions and roles - $checked->{action} = ''; - if ( defined $params->{action} ) { - if ( $params->{action} =~ /^(show|diff)$/ ) { - $checked->{action} = $params->{action}; - } - } - - #print STDERR Dumper($checked); - return $checked; -} - diff --git a/website/agenda/planung/fonts/open-sans-v15-latin_latin-ext-regular.eot b/website/agenda/planung/fonts/open-sans-v15-latin_latin-ext-regular.eot new file mode 100644 index 0000000..f25146f Binary files /dev/null and b/website/agenda/planung/fonts/open-sans-v15-latin_latin-ext-regular.eot differ diff --git a/website/agenda/planung/fonts/open-sans-v15-latin_latin-ext-regular.svg b/website/agenda/planung/fonts/open-sans-v15-latin_latin-ext-regular.svg new file mode 100644 index 0000000..78eb653 --- /dev/null +++ b/website/agenda/planung/fonts/open-sans-v15-latin_latin-ext-regular.svg @@ -0,0 +1,336 @@ +<?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"> +<defs > +<font id="OpenSans" horiz-adv-x="1206" ><font-face + font-family="Open Sans" + units-per-em="2048" + panose-1="2 11 6 6 3 5 4 2 2 4" + ascent="2189" + descent="-600" + alphabetic="0" /> +<glyph unicode=" " glyph-name="space" horiz-adv-x="532" /> +<glyph unicode="!" glyph-name="exclam" horiz-adv-x="547" d="M326 403H221L170 1462H377L326 403ZM152 106Q152 242 272 242Q330 242 361 207T393 106Q393 42 361 7T272 -29Q220 -29 186 2T152 106Z" /> +<glyph unicode=""" glyph-name="quotedbl" horiz-adv-x="821" d="M319 1462L279 934H174L133 1462H319ZM688 1462L647 934H543L502 1462H688Z" /> +<glyph unicode="#" glyph-name="numbersign" horiz-adv-x="1323" d="M981 899L915 559H1198V430H891L807 0H670L754 430H451L369 0H233L313 430H51V559H338L406 899H129V1026H428L510 1462H649L567 1026H872L956 1462H1090L1006 1026H1270V899H981ZM475 559H778L844 +899H541L475 559Z" /> +<glyph unicode="$" glyph-name="dollar" horiz-adv-x="1171" d="M1036 449Q1036 313 934 225T649 113V-119H520V104Q408 104 303 121T131 170V326Q214 289 322 266T520 242V682Q315 747 233 833T150 1055Q150 1186 251 1270T520 1372V1554H649V1374Q833 1369 1004 +1300L952 1169Q803 1228 649 1239V805Q806 755 884 708T999 599T1036 449ZM866 436Q866 508 822 552T649 641V252Q866 282 866 436ZM319 1057Q319 981 364 935T520 848V1235Q421 1219 370 1173T319 1057Z" /> +<glyph unicode="%" glyph-name="percent" horiz-adv-x="1686" d="M242 1026Q242 856 279 771T399 686Q563 686 563 1026Q563 1364 399 1364Q316 1364 279 1280T242 1026ZM700 1026Q700 798 624 682T399 565Q259 565 182 684T104 1026Q104 1253 178 1368T399 1483Q544 +1483 622 1364T700 1026ZM1122 440Q1122 269 1159 185T1280 100Q1364 100 1404 183T1444 440Q1444 611 1404 693T1280 776Q1196 776 1159 694T1122 440ZM1581 440Q1581 213 1505 97T1280 -20Q1138 -20 1062 99T985 440Q985 667 1059 782T1280 897Q1422 897 1501 +780T1581 440ZM1323 1462L512 0H365L1176 1462H1323Z" /> +<glyph unicode="&" glyph-name="ampersand" horiz-adv-x="1495" d="M414 1171Q414 1102 450 1040T573 889Q702 964 752 1027T803 1174Q803 1251 752 1299T614 1348Q525 1348 470 1300T414 1171ZM569 129Q810 129 969 283L532 707Q421 639 375 595T307 499T285 +383Q285 266 362 198T569 129ZM113 379Q113 509 182 609T432 811Q347 906 317 955T268 1057T250 1167Q250 1317 348 1401T621 1485Q783 1485 876 1402T969 1169Q969 1062 901 972T676 788L1083 397Q1139 459 1172 542T1229 725H1397Q1329 439 1192 291L1491 0H1262L1077 +178Q959 72 837 26T565 -20Q350 -20 232 86T113 379Z" /> +<glyph unicode="'" glyph-name="quotesingle" horiz-adv-x="453" d="M319 1462L279 934H174L133 1462H319Z" /> +<glyph unicode="(" glyph-name="parenleft" horiz-adv-x="606" d="M82 561Q82 826 159 1057T383 1462H545Q401 1269 329 1038T256 563Q256 323 330 94T543 -324H383Q236 -154 159 73T82 561Z" /> +<glyph unicode=")" glyph-name="parenright" horiz-adv-x="606" d="M524 561Q524 298 447 71T223 -324H63Q202 -136 276 93T350 563Q350 807 278 1038T61 1462H223Q370 1287 447 1056T524 561Z" /> +<glyph unicode="*" glyph-name="asterisk" horiz-adv-x="1130" d="M657 1556L614 1161L1012 1272L1038 1090L657 1059L905 733L733 639L557 1001L397 639L221 733L463 1059L86 1090L115 1272L506 1161L463 1556H657Z" /> +<glyph unicode="+" glyph-name="plus" horiz-adv-x="1171" d="M653 791H1065V653H653V227H514V653H104V791H514V1219H653V791Z" /> +<glyph unicode="," glyph-name="comma" horiz-adv-x="502" d="M350 238L365 215Q339 115 290 -17T188 -264H63Q90 -160 122 -7T168 238H350Z" /> +<glyph unicode="-" glyph-name="hyphen" horiz-adv-x="659" d="M84 473V625H575V473H84Z" /> +<glyph unicode="." glyph-name="period" horiz-adv-x="545" d="M152 106Q152 173 182 207T270 242Q328 242 360 208T393 106Q393 41 360 6T270 -29Q219 -29 186 2T152 106Z" /> +<glyph unicode="/" glyph-name="slash" horiz-adv-x="752" d="M731 1462L186 0H20L565 1462H731Z" /> +<glyph unicode="0" glyph-name="zero" horiz-adv-x="1171" d="M1069 733Q1069 354 950 167T584 -20Q348 -20 225 171T102 733Q102 1115 221 1300T584 1485Q822 1485 945 1292T1069 733ZM270 733Q270 414 345 269T584 123Q750 123 824 270T899 733Q899 1048 825 +1194T584 1341Q420 1341 345 1197T270 733Z" /> +<glyph unicode="1" glyph-name="one" horiz-adv-x="1171" d="M715 0H553V1042Q553 1172 561 1288Q540 1267 514 1244T276 1049L188 1163L575 1462H715V0Z" /> +<glyph unicode="2" glyph-name="two" horiz-adv-x="1171" d="M1061 0H100V143L485 530Q661 708 717 784T801 932T829 1087Q829 1204 758 1272T561 1341Q470 1341 389 1311T207 1202L119 1315Q321 1483 559 1483Q765 1483 882 1378T999 1094Q999 955 921 819T629 +475L309 162V154H1061V0Z" /> +<glyph unicode="3" glyph-name="three" horiz-adv-x="1171" d="M1006 1118Q1006 978 928 889T705 770V762Q881 740 966 650T1051 414Q1051 205 906 93T494 -20Q378 -20 282 -3T94 59V217Q189 170 296 146T500 121Q879 121 879 418Q879 684 461 684H317V827H463Q634 +827 734 902T834 1112Q834 1219 761 1280T561 1341Q465 1341 380 1315T186 1219L102 1331Q192 1402 309 1442T557 1483Q770 1483 888 1386T1006 1118Z" /> +<glyph unicode="4" glyph-name="four" horiz-adv-x="1171" d="M1130 336H913V0H754V336H43V481L737 1470H913V487H1130V336ZM754 487V973Q754 1116 764 1296H756Q708 1200 666 1137L209 487H754Z" /> +<glyph unicode="5" glyph-name="five" horiz-adv-x="1171" d="M557 893Q788 893 920 779T1053 465Q1053 238 909 109T510 -20Q263 -20 133 59V219Q203 174 307 149T512 123Q688 123 785 206T883 446Q883 752 508 752Q413 752 254 723L168 778L223 1462H950V1309H365L328 +870Q443 893 557 893Z" /> +<glyph unicode="6" glyph-name="six" horiz-adv-x="1171" d="M117 625Q117 1056 284 1269T780 1483Q893 1483 958 1464V1321Q881 1346 782 1346Q547 1346 423 1200T287 739H299Q409 911 647 911Q844 911 957 792T1071 469Q1071 241 947 111T610 -20Q383 -20 250 +150T117 625ZM608 121Q750 121 828 210T907 469Q907 614 834 697T616 780Q526 780 451 743T332 641T287 506Q287 403 327 314T440 173T608 121Z" /> +<glyph unicode="7" glyph-name="seven" horiz-adv-x="1171" d="M285 0L891 1309H94V1462H1067V1329L469 0H285Z" /> +<glyph unicode="8" glyph-name="eight" horiz-adv-x="1171" d="M584 1483Q784 1483 901 1390T1018 1133Q1018 1025 951 936T737 774Q915 689 990 596T1065 379Q1065 197 938 89T590 -20Q356 -20 230 82T104 373Q104 624 410 764Q272 842 212 932T152 1135Q152 +1294 269 1388T584 1483ZM268 369Q268 249 351 182T586 115Q735 115 818 185T901 377Q901 474 823 549T551 696Q402 632 335 555T268 369ZM582 1348Q457 1348 386 1288T315 1128Q315 1036 374 970T592 838Q735 898 794 967T854 1128Q854 1229 782 1288T582 1348Z" +/> +<glyph unicode="9" glyph-name="nine" horiz-adv-x="1171" d="M1061 838Q1061 -20 397 -20Q281 -20 213 0V143Q293 117 395 117Q635 117 757 265T891 721H879Q824 638 733 595T528 551Q334 551 220 667T106 991Q106 1219 233 1351T569 1483Q718 1483 829 1407T1001 +1184T1061 838ZM569 1341Q426 1341 348 1249T270 993Q270 849 342 767T561 684Q652 684 728 721T849 822T893 956Q893 1061 852 1150T738 1290T569 1341Z" /> +<glyph unicode=":" glyph-name="colon" horiz-adv-x="545" d="M152 106Q152 173 182 207T270 242Q328 242 360 208T393 106Q393 41 360 6T270 -29Q219 -29 186 2T152 106ZM152 989Q152 1124 270 1124Q393 1124 393 989Q393 924 360 889T270 854Q219 854 186 885T152 989Z" /> +<glyph unicode=";" glyph-name="semicolon" horiz-adv-x="545" d="M350 238L365 215Q339 115 290 -17T188 -264H63Q90 -160 122 -7T168 238H350ZM147 989Q147 1124 266 1124Q389 1124 389 989Q389 924 356 889T266 854Q208 854 178 889T147 989Z" /> +<glyph unicode="<" glyph-name="less" horiz-adv-x="1171" d="M1065 242L104 664V762L1065 1241V1092L283 721L1065 393V242Z" /> +<glyph unicode="=" glyph-name="equal" horiz-adv-x="1171" d="M119 858V995H1049V858H119ZM119 449V586H1049V449H119Z" /> +<glyph unicode=">" glyph-name="greater" horiz-adv-x="1171" d="M104 393L887 719L104 1092V1241L1065 762V664L104 242V393Z" /> +<glyph unicode="?" glyph-name="question" horiz-adv-x="879" d="M289 403V457Q289 574 325 649T459 809Q595 924 630 982T666 1122Q666 1224 601 1279T412 1335Q333 1335 258 1317T86 1249L27 1384Q216 1483 422 1483Q613 1483 719 1389T825 1124Q825 1051 806 +996T748 891T584 731Q483 645 451 588T418 436V403H289ZM240 106Q240 242 360 242Q418 242 449 207T481 106Q481 42 449 7T360 -29Q308 -29 274 2T240 106Z" /> +<glyph unicode="@" glyph-name="at" horiz-adv-x="1841" d="M1720 729Q1720 587 1676 469T1552 286T1368 221Q1282 221 1223 273T1153 406H1145Q1105 319 1031 270T854 221Q704 221 620 323T535 602Q535 806 653 933T963 1061Q1031 1061 1117 1049T1272 1014L1247 +544V522Q1247 344 1380 344Q1471 344 1528 451T1585 731Q1585 912 1511 1048T1301 1257T987 1331Q764 1331 599 1239T347 975T260 578Q260 273 421 109T885 -55Q1095 -55 1321 31V-102Q1129 -186 885 -186Q522 -186 322 13T121 571Q121 831 228 1034T533 1348T987 +1460Q1202 1460 1369 1370T1628 1113T1720 729ZM686 598Q686 344 881 344Q1088 344 1106 657L1120 918Q1048 938 963 938Q833 938 760 848T686 598Z" /> +<glyph unicode="A" glyph-name="A" horiz-adv-x="1296" d="M1120 0L938 465H352L172 0H0L578 1468H721L1296 0H1120ZM885 618L715 1071Q682 1157 647 1282Q625 1186 584 1071L412 618H885Z" /> +<glyph unicode="B" glyph-name="B" horiz-adv-x="1327" d="M201 1462H614Q905 1462 1035 1375T1165 1100Q1165 970 1093 886T881 776V766Q1214 709 1214 416Q1214 220 1082 110T711 0H201V1462ZM371 836H651Q831 836 910 892T989 1083Q989 1206 901 1260T621 1315H371V836ZM371 +692V145H676Q853 145 942 213T1032 428Q1032 564 941 628T662 692H371Z" /> +<glyph unicode="C" glyph-name="C" horiz-adv-x="1292" d="M827 1331Q586 1331 447 1171T307 731Q307 444 441 288T825 131Q978 131 1174 186V37Q1022 -20 799 -20Q476 -20 301 176T125 733Q125 959 209 1129T453 1391T829 1483Q1059 1483 1231 1399L1159 1253Q993 +1331 827 1331Z" /> +<glyph unicode="D" glyph-name="D" horiz-adv-x="1493" d="M1368 745Q1368 383 1172 192T606 0H201V1462H649Q990 1462 1179 1273T1368 745ZM1188 739Q1188 1025 1045 1170T618 1315H371V147H578Q882 147 1035 296T1188 739Z" /> +<glyph unicode="E" glyph-name="E" horiz-adv-x="1139" d="M1016 0H201V1462H1016V1311H371V840H977V690H371V152H1016V0Z" /> +<glyph unicode="F" glyph-name="F" horiz-adv-x="1057" d="M371 0H201V1462H1016V1311H371V776H977V625H371V0Z" /> +<glyph unicode="G" glyph-name="G" horiz-adv-x="1491" d="M844 766H1341V55Q1225 18 1105 -1T827 -20Q495 -20 310 177T125 731Q125 959 216 1130T480 1392T883 1483Q1117 1483 1319 1397L1253 1247Q1055 1331 872 1331Q605 1331 455 1172T305 731Q305 435 449 +282T874 129Q1026 129 1171 164V614H844V766Z" /> +<glyph unicode="H" glyph-name="H" horiz-adv-x="1511" d="M1311 0H1141V688H371V0H201V1462H371V840H1141V1462H1311V0Z" /> +<glyph unicode="I" glyph-name="I" horiz-adv-x="571" d="M201 0V1462H371V0H201Z" /> +<glyph unicode="J" glyph-name="J" horiz-adv-x="547" d="M-12 -385Q-106 -385 -160 -358V-213Q-89 -233 -12 -233Q87 -233 138 -173T190 0V1462H360V14Q360 -176 264 -280T-12 -385Z" /> +<glyph unicode="K" glyph-name="K" horiz-adv-x="1257" d="M1257 0H1057L524 709L371 573V0H201V1462H371V737L1034 1462H1235L647 827L1257 0Z" /> +<glyph unicode="L" glyph-name="L" horiz-adv-x="1063" d="M201 0V1462H371V154H1016V0H201Z" /> +<glyph unicode="M" glyph-name="M" horiz-adv-x="1849" d="M848 0L352 1296H344Q358 1142 358 930V0H201V1462H457L920 256H928L1395 1462H1649V0H1479V942Q1479 1104 1493 1294H1485L985 0H848Z" /> +<glyph unicode="N" glyph-name="N" horiz-adv-x="1544" d="M1343 0H1149L350 1227H342Q358 1011 358 831V0H201V1462H393L1190 240H1198Q1196 267 1189 413T1184 623V1462H1343V0Z" /> +<glyph unicode="O" glyph-name="O" horiz-adv-x="1595" d="M1470 733Q1470 382 1293 181T799 -20Q476 -20 301 177T125 735Q125 1092 301 1288T801 1485Q1116 1485 1293 1285T1470 733ZM305 733Q305 436 431 283T799 129Q1042 129 1166 282T1290 733Q1290 1028 +1167 1180T801 1333Q558 1333 432 1180T305 733Z" /> +<glyph unicode="P" glyph-name="P" horiz-adv-x="1233" d="M1128 1036Q1128 814 977 695T543 575H371V0H201V1462H580Q1128 1462 1128 1036ZM371 721H524Q750 721 851 794T952 1028Q952 1173 857 1244T561 1315H371V721Z" /> +<glyph unicode="Q" glyph-name="Q" horiz-adv-x="1595" d="M1470 733Q1470 452 1357 266T1038 14L1386 -348H1139L854 -18L799 -20Q476 -20 301 177T125 735Q125 1092 301 1288T801 1485Q1116 1485 1293 1285T1470 733ZM305 733Q305 436 431 283T799 129Q1042 +129 1166 282T1290 733Q1290 1028 1167 1180T801 1333Q558 1333 432 1180T305 733Z" /> +<glyph unicode="R" glyph-name="R" horiz-adv-x="1266" d="M371 608V0H201V1462H602Q871 1462 999 1359T1128 1049Q1128 759 834 657L1231 0H1030L676 608H371ZM371 754H604Q784 754 868 825T952 1040Q952 1185 867 1249T592 1313H371V754Z" /> +<glyph unicode="S" glyph-name="S" horiz-adv-x="1124" d="M1026 389Q1026 196 886 88T506 -20Q246 -20 106 47V211Q196 173 302 151T512 129Q682 129 768 193T854 373Q854 449 824 497T722 587T504 680Q300 753 213 853T125 1114Q125 1283 252 1383T588 1483Q806 +1483 989 1403L936 1255Q755 1331 584 1331Q449 1331 373 1273T297 1112Q297 1036 325 988T419 899T623 809Q853 727 939 633T1026 389Z" /> +<glyph unicode="T" glyph-name="T" horiz-adv-x="1133" d="M651 0H481V1311H18V1462H1114V1311H651V0Z" /> +<glyph unicode="U" glyph-name="U" horiz-adv-x="1491" d="M1305 1462V516Q1305 266 1154 123T739 -20Q475 -20 331 124T186 520V1462H356V508Q356 325 456 227T750 129Q935 129 1035 227T1135 510V1462H1305Z" /> +<glyph unicode="V" glyph-name="V" horiz-adv-x="1219" d="M1036 1462H1219L692 0H524L0 1462H180L516 516Q574 353 608 199Q644 361 702 522L1036 1462Z" /> +<glyph unicode="W" glyph-name="W" horiz-adv-x="1896" d="M1477 0H1309L1014 979Q993 1044 967 1143T940 1262Q918 1130 870 973L584 0H416L27 1462H207L438 559Q486 369 508 215Q535 398 588 573L850 1462H1030L1305 565Q1353 410 1386 215Q1405 357 1458 561L1688 +1462H1868L1477 0Z" /> +<glyph unicode="X" glyph-name="X" horiz-adv-x="1182" d="M1174 0H981L588 643L188 0H8L494 764L41 1462H229L592 883L958 1462H1139L686 770L1174 0Z" /> +<glyph unicode="Y" glyph-name="Y" horiz-adv-x="1147" d="M573 731L963 1462H1147L659 567V0H487V559L0 1462H186L573 731Z" /> +<glyph unicode="Z" glyph-name="Z" horiz-adv-x="1169" d="M1087 0H82V133L858 1309H106V1462H1065V1329L289 154H1087V0Z" /> +<glyph unicode="[" glyph-name="bracketleft" horiz-adv-x="674" d="M623 -324H166V1462H623V1321H334V-182H623V-324Z" /> +<glyph unicode="\" glyph-name="backslash" horiz-adv-x="752" d="M186 1462L733 0H567L23 1462H186Z" /> +<glyph unicode="]" glyph-name="bracketright" horiz-adv-x="674" d="M51 -182H340V1321H51V1462H508V-324H51V-182Z" /> +<glyph unicode="^" glyph-name="asciicircum" horiz-adv-x="1110" d="M49 551L483 1473H582L1059 551H907L535 1296L201 551H49Z" /> +<glyph unicode="_" glyph-name="underscore" horiz-adv-x="918" d="M922 -315H-4V-184H922V-315Z" /> +<glyph unicode="`" glyph-name="grave" horiz-adv-x="1182" d="M786 1241H676Q611 1293 522 1389T393 1548V1569H596Q628 1500 685 1410T786 1266V1241Z" /> +<glyph unicode="a" glyph-name="a" horiz-adv-x="1139" d="M850 0L817 156H809Q727 53 646 17T442 -20Q279 -20 187 64T94 303Q94 635 625 651L811 657V725Q811 854 756 915T578 977Q441 977 268 893L217 1020Q298 1064 394 1089T588 1114Q784 1114 878 1027T973 +748V0H850ZM475 117Q630 117 718 202T807 440V539L641 532Q443 525 356 471T268 301Q268 211 322 164T475 117Z" /> +<glyph unicode="b" glyph-name="b" horiz-adv-x="1255" d="M686 1114Q902 1114 1021 967T1141 549Q1141 279 1021 130T686 -20Q579 -20 491 19T342 141H330L295 0H176V1556H342V1178Q342 1051 334 950H342Q458 1114 686 1114ZM662 975Q492 975 417 878T342 549Q342 +318 419 219T666 119Q819 119 894 230T969 551Q969 765 894 870T662 975Z" /> +<glyph unicode="c" glyph-name="c" horiz-adv-x="975" d="M614 -20Q376 -20 246 126T115 541Q115 816 247 966T625 1116Q704 1116 783 1099T907 1059L856 918Q801 940 736 954T621 969Q287 969 287 543Q287 341 368 233T610 125Q747 125 891 184V37Q781 -20 614 -20Z" /> +<glyph unicode="d" glyph-name="d" horiz-adv-x="1255" d="M922 147H913Q798 -20 569 -20Q354 -20 235 127T115 545Q115 816 235 966T569 1116Q792 1116 911 954H924L917 1033L913 1110V1556H1079V0H944L922 147ZM590 119Q760 119 836 211T913 510V545Q913 778 +836 877T588 977Q442 977 365 864T287 543Q287 333 364 226T590 119Z" /> +<glyph unicode="e" glyph-name="e" horiz-adv-x="1149" d="M639 -20Q396 -20 256 128T115 539Q115 804 245 960T596 1116Q802 1116 922 981T1042 623V518H287Q292 325 384 225T645 125Q822 125 995 199V51Q907 13 829 -3T639 -20ZM594 977Q462 977 384 891T291 +653H864Q864 810 794 893T594 977Z" /> +<glyph unicode="f" glyph-name="f" horiz-adv-x="694" d="M670 967H391V0H225V967H29V1042L225 1102V1163Q225 1567 578 1567Q665 1567 782 1532L739 1399Q643 1430 575 1430Q481 1430 436 1368T391 1167V1096H670V967Z" /> +<glyph unicode="g" glyph-name="g" horiz-adv-x="1122" d="M1073 1096V991L870 967Q898 932 920 876T942 748Q942 587 832 491T530 395Q481 395 438 403Q332 347 332 262Q332 217 369 196T496 174H690Q868 174 963 99T1059 -119Q1059 -301 913 -396T487 -492Q272 +-492 156 -412T39 -186Q39 -86 103 -13T283 86Q241 105 213 145T184 238Q184 298 216 343T317 430Q232 465 179 549T125 741Q125 921 233 1018T539 1116Q625 1116 694 1096H1073ZM199 -184Q199 -273 274 -319T489 -365Q698 -365 798 -303T899 -133Q899 -44 844 +-10T637 25H438Q325 25 262 -29T199 -184ZM289 745Q289 630 354 571T535 512Q778 512 778 748Q778 995 532 995Q415 995 352 932T289 745Z" /> +<glyph unicode="h" glyph-name="h" horiz-adv-x="1257" d="M926 0V709Q926 843 865 909T674 975Q501 975 422 881T342 573V0H176V1556H342V1085Q342 1000 334 944H344Q393 1023 483 1068T690 1114Q891 1114 991 1019T1092 715V0H926Z" /> +<glyph unicode="i" glyph-name="i" horiz-adv-x="518" d="M342 0H176V1096H342V0ZM162 1393Q162 1450 190 1476T260 1503Q300 1503 329 1476T358 1393Q358 1337 329 1310T260 1282Q218 1282 190 1309T162 1393Z" /> +<glyph unicode="j" glyph-name="j" horiz-adv-x="518" d="M43 -492Q-52 -492 -111 -467V-332Q-42 -352 25 -352Q103 -352 139 -310T176 -180V1096H342V-168Q342 -492 43 -492ZM162 1393Q162 1450 190 1476T260 1503Q300 1503 329 1476T358 1393Q358 1337 329 1310T260 +1282Q218 1282 190 1309T162 1393Z" /> +<glyph unicode="k" glyph-name="k" horiz-adv-x="1075" d="M340 561Q383 622 471 721L825 1096H1022L578 629L1053 0H852L465 518L340 410V0H176V1556H340V731Q340 676 332 561H340Z" /> +<glyph unicode="l" glyph-name="l" horiz-adv-x="518" d="M342 0H176V1556H342V0Z" /> +<glyph unicode="m" glyph-name="m" horiz-adv-x="1905" d="M1573 0V713Q1573 844 1517 909T1343 975Q1188 975 1114 886T1040 612V0H874V713Q874 844 818 909T643 975Q487 975 415 882T342 575V0H176V1096H311L338 946H346Q393 1026 478 1071T670 1116Q927 1116 +1006 930H1014Q1063 1016 1156 1066T1368 1116Q1554 1116 1646 1021T1739 715V0H1573Z" /> +<glyph unicode="n" glyph-name="n" horiz-adv-x="1257" d="M926 0V709Q926 843 865 909T674 975Q502 975 422 882T342 575V0H176V1096H311L338 946H346Q397 1027 489 1071T694 1116Q892 1116 992 1021T1092 715V0H926Z" /> +<glyph unicode="o" glyph-name="o" horiz-adv-x="1237" d="M1122 549Q1122 281 987 131T614 -20Q467 -20 353 49T177 247T115 549Q115 817 249 966T621 1116Q851 1116 986 963T1122 549ZM287 549Q287 339 371 229T618 119Q781 119 865 228T950 549Q950 758 866 +866T616 975Q453 975 370 868T287 549Z" /> +<glyph unicode="p" glyph-name="p" horiz-adv-x="1255" d="M686 -20Q579 -20 491 19T342 141H330Q342 45 342 -41V-492H176V1096H311L334 946H342Q406 1036 491 1076T686 1116Q904 1116 1022 967T1141 549Q1141 279 1021 130T686 -20ZM662 975Q494 975 419 882T342 +586V549Q342 318 419 219T666 119Q808 119 888 234T969 551Q969 756 889 865T662 975Z" /> +<glyph unicode="q" glyph-name="q" horiz-adv-x="1255" d="M590 119Q756 119 832 208T913 508V545Q913 775 835 876T588 977Q442 977 365 864T287 543Q287 336 363 228T590 119ZM565 -20Q353 -20 234 129T115 545Q115 814 235 965T569 1116Q794 1116 915 946H924L948 +1096H1079V-492H913V-23Q913 77 924 147H911Q796 -20 565 -20Z" /> +<glyph unicode="r" glyph-name="r" horiz-adv-x="836" d="M676 1116Q749 1116 807 1104L784 950Q716 965 664 965Q531 965 437 857T342 588V0H176V1096H313L332 893H340Q401 1000 487 1058T676 1116Z" /> +<glyph unicode="s" glyph-name="s" horiz-adv-x="977" d="M883 299Q883 146 769 63T449 -20Q231 -20 109 49V203Q188 163 278 140T453 117Q583 117 653 158T723 285Q723 349 668 394T451 502Q298 559 234 601T138 698T106 827Q106 961 215 1038T514 1116Q691 1116 +860 1044L801 909Q636 977 502 977Q384 977 324 940T264 838Q264 794 286 763T359 704T551 623Q746 552 814 480T883 299Z" /> +<glyph unicode="t" glyph-name="t" horiz-adv-x="723" d="M530 117Q574 117 615 123T680 137V10Q653 -3 601 -11T506 -20Q188 -20 188 315V967H31V1047L188 1116L258 1350H354V1096H672V967H354V322Q354 223 401 170T530 117Z" /> +<glyph unicode="u" glyph-name="u" horiz-adv-x="1257" d="M332 1096V385Q332 251 393 185T584 119Q756 119 835 213T915 520V1096H1081V0H944L920 147H911Q860 66 770 23T563 -20Q363 -20 264 75T164 379V1096H332Z" /> +<glyph unicode="v" glyph-name="v" horiz-adv-x="1026" d="M416 0L0 1096H178L414 446Q494 218 508 150H516Q527 203 585 369T848 1096H1026L610 0H416Z" /> +<glyph unicode="w" glyph-name="w" horiz-adv-x="1593" d="M1071 0L870 643Q851 702 799 911H791Q751 736 721 641L514 0H322L23 1096H197Q303 683 358 467T422 176H430Q441 233 465 323T508 467L709 1096H889L1085 467Q1141 295 1161 178H1169Q1173 214 1190 +289T1399 1096H1571L1268 0H1071Z" /> +<glyph unicode="x" glyph-name="x" horiz-adv-x="1073" d="M440 561L59 1096H248L537 676L825 1096H1012L631 561L1032 0H844L537 444L227 0H39L440 561Z" /> +<glyph unicode="y" glyph-name="y" horiz-adv-x="1032" d="M2 1096H180L420 471Q499 257 518 162H526Q539 213 580 336T852 1096H1030L559 -152Q489 -337 396 -414T166 -492Q90 -492 16 -475V-342Q71 -354 139 -354Q310 -354 383 -162L444 -6L2 1096Z" /> +<glyph unicode="z" glyph-name="z" horiz-adv-x="958" d="M877 0H82V113L680 967H119V1096H862V967L272 129H877V0Z" /> +<glyph unicode="{" glyph-name="braceleft" horiz-adv-x="776" d="M475 12Q475 -90 533 -136T705 -184V-324Q515 -322 411 -237T307 2V305Q307 409 244 453T61 498V639Q191 641 249 687T307 829V1135Q307 1290 415 1376T705 1462V1323Q475 1317 475 1124V829Q475 +614 252 575V563Q475 524 475 309V12Z" /> +<glyph unicode="|" glyph-name="bar" horiz-adv-x="1128" d="M494 1556H635V-496H494V1556Z" /> +<glyph unicode="}" glyph-name="braceright" horiz-adv-x="776" d="M522 575Q299 614 299 829V1124Q299 1317 72 1323V1462Q256 1462 361 1375T467 1135V829Q467 732 526 687T715 639V498Q593 498 530 454T467 305V2Q467 -151 365 -236T72 -324V-184Q183 -182 +241 -136T299 12V309Q299 423 354 483T522 563V575Z" /> +<glyph unicode="~" glyph-name="asciitilde" horiz-adv-x="1171" d="M338 713Q285 713 222 680T104 592V743Q204 852 348 852Q416 852 472 838T618 786Q684 758 733 745T829 731Q883 731 947 763T1065 852V702Q963 592 821 592Q749 592 686 608T551 657Q476 689 +431 701T338 713Z" /> +<glyph unicode=" " glyph-name="nbspace" horiz-adv-x="532" /> +<glyph unicode="¡" glyph-name="exclamdown" horiz-adv-x="547" d="M219 684H324L375 -373H168L219 684ZM393 983Q393 848 272 848Q212 848 182 883T152 983Q152 1046 183 1082T272 1118Q323 1118 358 1086T393 983Z" /> +<glyph unicode="¢" glyph-name="cent" horiz-adv-x="1171" d="M971 240Q866 186 719 180V-20H586V186Q383 218 287 354T190 741Q190 1249 586 1311V1483H721V1319Q796 1316 867 1300T987 1260L938 1120Q805 1171 696 1171Q524 1171 443 1066T362 743Q362 +531 441 430T688 328Q829 328 971 387V240Z" /> +<glyph unicode="£" glyph-name="sterling" horiz-adv-x="1171" d="M682 1481Q872 1481 1042 1397L981 1264Q827 1341 684 1341Q561 1341 499 1279T436 1077V782H858V655H436V434Q436 334 404 266T297 154H1092V0H63V141Q268 188 268 432V655H70V782H268V1098Q268 +1276 380 1378T682 1481Z" /> +<glyph unicode="¤" glyph-name="currency" horiz-adv-x="1171" d="M184 723Q184 845 258 952L123 1092L217 1184L352 1051Q456 1124 586 1124Q713 1124 815 1051L952 1184L1047 1092L913 954Q987 841 987 723Q987 592 913 489L1044 354L952 262L815 395Q713 +324 586 324Q452 324 352 397L217 264L125 356L258 492Q184 599 184 723ZM313 723Q313 611 391 531T586 451Q702 451 781 530T860 723Q860 837 780 918T586 999Q470 999 392 917T313 723Z" /> +<glyph unicode="¥" glyph-name="yen" horiz-adv-x="1171" d="M584 735L963 1462H1137L721 692H983V565H666V395H983V268H666V0H502V268H186V395H502V565H186V692H442L31 1462H209L584 735Z" /> +<glyph unicode="¦" glyph-name="brokenbar" horiz-adv-x="1128" d="M494 1556H635V780H494V1556ZM494 281H635V-496H494V281Z" /> +<glyph unicode="§" glyph-name="section" horiz-adv-x="1057" d="M139 809Q139 895 182 963T303 1069Q229 1109 187 1164T145 1305Q145 1426 248 1495T549 1565Q643 1565 722 1551T899 1497L846 1366Q748 1405 681 1418T537 1432Q421 1432 363 1403T305 1309Q305 +1249 366 1207T582 1110Q768 1042 843 967T918 784Q918 694 877 624T762 512Q915 431 915 285Q915 145 798 69T469 -8Q251 -8 123 57V205Q201 168 298 146T477 123Q611 123 681 161T752 270Q752 316 728 345T650 403T481 475Q339 527 272 572T172 674T139 809ZM285 +829Q285 752 351 700T584 586L633 567Q770 647 770 758Q770 841 697 897T438 1010Q370 991 328 941T285 829Z" /> +<glyph unicode="¨" glyph-name="dieresis" horiz-adv-x="1182" d="M309 1393Q309 1445 335 1468T399 1491Q437 1491 464 1468T492 1393Q492 1343 465 1319T399 1294Q362 1294 336 1318T309 1393ZM690 1393Q690 1445 716 1468T780 1491Q817 1491 844 1468T872 +1393Q872 1343 845 1319T780 1294Q743 1294 717 1318T690 1393Z" /> +<glyph unicode="©" glyph-name="copyright" horiz-adv-x="1704" d="M893 1059Q768 1059 701 972T633 731Q633 563 696 482T891 401Q977 401 1102 446V322Q1054 302 1004 288T883 274Q689 274 585 394T481 731Q481 940 591 1063T893 1186Q1021 1186 1139 1126L1081 +1008Q973 1059 893 1059ZM100 731Q100 931 200 1106T475 1382T852 1483Q1052 1483 1227 1383T1503 1108T1604 731Q1604 534 1507 361T1235 84T852 -20Q645 -20 470 83T198 360T100 731ZM205 731Q205 558 292 408T529 171T852 84Q1026 84 1175 171T1411 406T1499 +731Q1499 905 1412 1054T1177 1290T852 1378Q678 1378 529 1291T293 1056T205 731Z" /> +<glyph unicode="ª" glyph-name="ordfeminine" horiz-adv-x="725" d="M532 801L508 885Q416 788 276 788Q181 788 126 837T70 989Q70 1091 147 1143T389 1202L506 1206V1245Q506 1378 358 1378Q258 1378 154 1327L111 1423Q225 1479 358 1479Q488 1479 556 +1427T625 1253V801H532ZM193 989Q193 889 305 889Q506 889 506 1069V1118L408 1114Q296 1110 245 1082T193 989Z" /> +<glyph unicode="«" glyph-name="guillemotleft" horiz-adv-x="1018" d="M82 551L424 958L543 889L254 539L543 188L424 117L82 524V551ZM477 551L821 958L938 889L651 539L938 188L821 117L477 524V551Z" /> +<glyph unicode="¬" glyph-name="logicalnot" horiz-adv-x="1171" d="M1065 791V264H928V653H104V791H1065Z" /> +<glyph unicode="­" glyph-name="uni00AD" horiz-adv-x="659" d="M84 473V625H575V473H84Z" /> +<glyph unicode="®" glyph-name="registered" horiz-adv-x="1704" d="M723 762H831Q911 762 959 803T1008 909Q1008 984 965 1016T829 1049H723V762ZM1157 913Q1157 833 1115 772T995 680L1233 285H1065L858 639H723V285H575V1176H836Q1002 1176 1079 1111T1157 +913ZM100 731Q100 931 200 1106T475 1382T852 1483Q1052 1483 1227 1383T1503 1108T1604 731Q1604 534 1507 361T1235 84T852 -20Q645 -20 470 83T198 360T100 731ZM205 731Q205 558 292 408T529 171T852 84Q1026 84 1175 171T1411 406T1499 731Q1499 905 1412 +1054T1177 1290T852 1378Q678 1378 529 1291T293 1056T205 731Z" /> +<glyph unicode="¯" glyph-name="overscore" horiz-adv-x="1024" d="M1030 1556H-6V1683H1030V1556Z" /> +<glyph unicode="°" glyph-name="degree" horiz-adv-x="877" d="M127 1171Q127 1301 217 1392T438 1483Q568 1483 659 1393T750 1171Q750 1087 709 1016T595 902T438 860Q308 860 218 950T127 1171ZM242 1171Q242 1089 300 1032T440 975Q520 975 577 1031T635 +1171Q635 1255 579 1311T440 1368Q357 1368 300 1311T242 1171Z" /> +<glyph unicode="±" glyph-name="plusminus" horiz-adv-x="1171" d="M653 791H1065V653H653V227H514V653H104V791H514V1219H653V791ZM104 1V139H1065V1H104Z" /> +<glyph unicode="²" glyph-name="twosuperior" horiz-adv-x="711" d="M653 586H49V690L285 920Q374 1006 415 1054T472 1141T489 1233Q489 1301 449 1335T346 1370Q294 1370 245 1351T127 1282L61 1370Q192 1481 344 1481Q476 1481 549 1416T623 1239Q623 +1159 579 1084T387 870L213 705H653V586Z" /> +<glyph unicode="³" glyph-name="threesuperior" horiz-adv-x="711" d="M627 1255Q627 1175 586 1124T477 1049Q653 1002 653 840Q653 712 561 641T301 569Q149 569 33 625V748Q180 680 303 680Q514 680 514 842Q514 987 283 987H166V1094H285Q388 1094 437 +1133T487 1241Q487 1302 447 1336T340 1370Q274 1370 218 1349T106 1292L37 1382Q100 1427 170 1454T334 1481Q470 1481 548 1422T627 1255Z" /> +<glyph unicode="´" glyph-name="acute" horiz-adv-x="1182" d="M393 1266Q441 1328 496 1416T584 1569H786V1548Q742 1483 655 1388T504 1241H393V1266Z" /> +<glyph unicode="µ" glyph-name="mu" horiz-adv-x="1268" d="M342 381Q342 119 596 119Q767 119 846 213T926 520V1096H1092V0H956L930 147H920Q809 -20 580 -20Q430 -20 342 72H332Q342 -12 342 -172V-492H176V1096H342V381Z" /> +<glyph unicode="¶" glyph-name="paragraph" horiz-adv-x="1341" d="M1120 -260H1006V1452H793V-260H678V559Q616 541 532 541Q316 541 215 666T113 1042Q113 1302 222 1429T563 1556H1120V-260Z" /> +<glyph unicode="·" glyph-name="middot" horiz-adv-x="545" d="M152 723Q152 789 183 823T270 858Q328 858 360 824T393 723Q393 658 360 623T270 588Q219 588 186 619T152 723Z" /> +<glyph unicode="¸" glyph-name="cedilla" horiz-adv-x="465" d="M436 -289Q436 -386 360 -439T133 -492Q82 -492 37 -483V-377Q82 -385 141 -385Q220 -385 260 -365T301 -291Q301 -248 262 -222T113 -178L201 0H311L256 -115Q436 -154 436 -289Z" /> +<glyph unicode="¹" glyph-name="onesuperior" horiz-adv-x="711" d="M338 1462H481V586H348V1165Q348 1256 354 1346Q332 1324 305 1302T143 1184L76 1280L338 1462Z" /> +<glyph unicode="º" glyph-name="ordmasculine" horiz-adv-x="768" d="M702 1135Q702 971 617 880T381 788Q235 788 151 881T66 1135Q66 1298 150 1388T385 1479Q537 1479 619 1388T702 1135ZM188 1135Q188 1013 233 952T383 891Q488 891 534 952T580 1135Q580 +1258 534 1317T383 1376Q280 1376 234 1317T188 1135Z" /> +<glyph unicode="»" glyph-name="guillemotright" horiz-adv-x="1018" d="M936 524L592 117L475 188L762 539L475 889L592 958L936 551V524ZM541 524L197 117L80 188L367 539L80 889L197 958L541 551V524Z" /> +<glyph unicode="¼" glyph-name="onequarter" horiz-adv-x="1597" d="M1298 1462L395 0H252L1155 1462H1298ZM593 1462H736V586H603V1165Q603 1256 609 1346Q587 1324 560 1302T398 1184L331 1280L593 1462ZM1489 203H1364V1H1219V203H817V304L1225 883H1364V320H1489V203ZM1219 +320V515Q1219 649 1225 724Q1220 712 1208 693T1181 651T1151 606T1125 566L957 320H1219Z" /> +<glyph unicode="½" glyph-name="onehalf" horiz-adv-x="1597" d="M1230 1462L327 0H184L1087 1462H1230ZM564 1462H707V586H574V1165Q574 1256 580 1346Q558 1324 531 1302T369 1184L302 1280L564 1462ZM1499 1H895V105L1131 335Q1220 421 1261 469T1318 +556T1335 648Q1335 716 1295 750T1192 785Q1140 785 1091 766T973 697L907 785Q1038 896 1190 896Q1322 896 1395 831T1469 654Q1469 574 1425 499T1233 285L1059 120H1499V1Z" /> +<glyph unicode="¾" glyph-name="threequarters" horiz-adv-x="1597" d="M876 1255Q876 1175 835 1124T726 1049Q902 1002 902 840Q902 712 810 641T550 569Q398 569 282 625V748Q429 680 552 680Q763 680 763 842Q763 987 532 987H415V1094H534Q637 1094 +686 1133T736 1241Q736 1302 696 1336T589 1370Q523 1370 467 1349T355 1292L286 1382Q349 1427 419 1454T583 1481Q719 1481 797 1422T876 1255ZM1390 1462L487 0H344L1247 1462H1390ZM1569 203H1444V1H1299V203H897V304L1305 883H1444V320H1569V203ZM1299 320V515Q1299 +649 1305 724Q1300 712 1288 693T1261 651T1231 606T1205 566L1037 320H1299Z" /> +<glyph unicode="¿" glyph-name="questiondown" horiz-adv-x="879" d="M590 684V633Q590 511 553 437T418 279Q297 173 267 136T224 60T211 -35Q211 -135 277 -191T465 -248Q545 -248 620 -229T793 -162L852 -297Q655 -393 457 -393Q267 -393 159 -300T51 +-37Q51 33 68 85T118 182T194 268T293 356Q394 444 426 502T459 653V684H590ZM639 983Q639 848 518 848Q459 848 428 882T397 983Q397 1047 430 1082T518 1118Q569 1118 604 1086T639 983Z" /> +<glyph unicode="À" glyph-name="Agrave" horiz-adv-x="1296" d="M1120 0L938 465H352L172 0H0L578 1468H721L1296 0H1120ZM885 618L715 1071Q682 1157 647 1282Q625 1186 584 1071L412 618H885ZM724 1579H614Q549 1631 460 1727T331 1886V1907H534Q566 1838 +623 1748T724 1604V1579Z" /> +<glyph unicode="Á" glyph-name="Aacute" horiz-adv-x="1296" d="M1120 0L938 465H352L172 0H0L578 1468H721L1296 0H1120ZM885 618L715 1071Q682 1157 647 1282Q625 1186 584 1071L412 618H885ZM526 1604Q574 1666 629 1754T717 1907H919V1886Q875 1821 788 +1726T637 1579H526V1604Z" /> +<glyph unicode="Â" glyph-name="Acircumflex" horiz-adv-x="1296" d="M1120 0L938 465H352L172 0H0L578 1468H721L1296 0H1120ZM885 618L715 1071Q682 1157 647 1282Q625 1186 584 1071L412 618H885ZM303 1602Q430 1738 481 1802T555 1907H721Q743 1865 797 +1799T977 1602V1579H858Q770 1634 637 1765Q501 1631 418 1579H303V1602Z" /> +<glyph unicode="Ã" glyph-name="Atilde" horiz-adv-x="1296" d="M1120 0L938 465H352L172 0H0L578 1468H721L1296 0H1120ZM885 618L715 1071Q682 1157 647 1282Q625 1186 584 1071L412 618H885ZM792 1581Q749 1581 708 1599T628 1640T552 1681T481 1700Q431 +1700 406 1670T366 1579H268Q281 1700 338 1768T487 1837Q533 1837 576 1819T658 1778T733 1737T801 1718Q850 1718 874 1747T913 1839H1012Q999 1718 943 1650T792 1581Z" /> +<glyph unicode="Ä" glyph-name="Adieresis" horiz-adv-x="1296" d="M1120 0L938 465H352L172 0H0L578 1468H721L1296 0H1120ZM885 618L715 1071Q682 1157 647 1282Q625 1186 584 1071L412 618H885ZM364 1731Q364 1783 390 1806T454 1829Q492 1829 519 1806T547 +1731Q547 1681 520 1657T454 1632Q417 1632 391 1656T364 1731ZM745 1731Q745 1783 771 1806T835 1829Q872 1829 899 1806T927 1731Q927 1681 900 1657T835 1632Q798 1632 772 1656T745 1731Z" /> +<glyph unicode="Å" glyph-name="Aring" horiz-adv-x="1296" d="M1120 0L938 465H352L172 0H0L578 1468H721L1296 0H1120ZM885 618L715 1071Q682 1157 647 1282Q625 1186 584 1071L412 618H885ZM870 1587Q870 1489 809 1430T645 1370Q544 1370 484 1428T424 +1585Q424 1683 484 1740T645 1798Q746 1798 808 1739T870 1587ZM762 1585Q762 1641 729 1671T645 1702Q594 1702 561 1672T528 1585Q528 1529 558 1499T645 1468Q697 1468 729 1498T762 1585Z" /> +<glyph unicode="Æ" glyph-name="AE" horiz-adv-x="1788" d="M1665 0H915V465H401L174 0H-2L696 1462H1665V1311H1085V840H1626V690H1085V152H1665V0ZM469 618H915V1311H797L469 618Z" /> +<glyph unicode="Ç" glyph-name="Ccedilla" horiz-adv-x="1292" d="M827 1331Q586 1331 447 1171T307 731Q307 444 441 288T825 131Q978 131 1174 186V37Q1022 -20 799 -20Q476 -20 301 176T125 733Q125 959 209 1129T453 1391T829 1483Q1059 1483 1231 1399L1159 +1253Q993 1331 827 1331ZM950 -289Q950 -386 874 -439T647 -492Q596 -492 551 -483V-377Q596 -385 655 -385Q734 -385 774 -365T815 -291Q815 -248 776 -222T627 -178L715 0H825L770 -115Q950 -154 950 -289Z" /> +<glyph unicode="È" glyph-name="Egrave" horiz-adv-x="1139" d="M1016 0H201V1462H1016V1311H371V840H977V690H371V152H1016V0ZM713 1579H603Q538 1631 449 1727T320 1886V1907H523Q555 1838 612 1748T713 1604V1579Z" /> +<glyph unicode="É" glyph-name="Eacute" horiz-adv-x="1139" d="M1016 0H201V1462H1016V1311H371V840H977V690H371V152H1016V0ZM456 1604Q504 1666 559 1754T647 1907H849V1886Q805 1821 718 1726T567 1579H456V1604Z" /> +<glyph unicode="Ê" glyph-name="Ecircumflex" horiz-adv-x="1139" d="M1016 0H201V1462H1016V1311H371V840H977V690H371V152H1016V0ZM263 1602Q390 1738 441 1802T515 1907H681Q703 1865 757 1799T937 1602V1579H818Q730 1634 597 1765Q461 1631 378 1579H263V1602Z" /> +<glyph unicode="Ë" glyph-name="Edieresis" horiz-adv-x="1139" d="M1016 0H201V1462H1016V1311H371V840H977V690H371V152H1016V0ZM327 1731Q327 1783 353 1806T417 1829Q455 1829 482 1806T510 1731Q510 1681 483 1657T417 1632Q380 1632 354 1656T327 1731ZM708 +1731Q708 1783 734 1806T798 1829Q835 1829 862 1806T890 1731Q890 1681 863 1657T798 1632Q761 1632 735 1656T708 1731Z" /> +<glyph unicode="Ì" glyph-name="Igrave" horiz-adv-x="571" d="M201 0V1462H371V0H201ZM398 1579H288Q223 1631 134 1727T5 1886V1907H208Q240 1838 297 1748T398 1604V1579Z" /> +<glyph unicode="Í" glyph-name="Iacute" horiz-adv-x="571" d="M201 0V1462H371V0H201ZM179 1604Q227 1666 282 1754T370 1907H572V1886Q528 1821 441 1726T290 1579H179V1604Z" /> +<glyph unicode="Î" glyph-name="Icircumflex" horiz-adv-x="571" d="M201 0V1462H371V0H201ZM-57 1602Q70 1738 121 1802T195 1907H361Q383 1865 437 1799T617 1602V1579H498Q410 1634 277 1765Q141 1631 58 1579H-57V1602Z" /> +<glyph unicode="Ï" glyph-name="Idieresis" horiz-adv-x="571" d="M201 0V1462H371V0H201ZM5 1731Q5 1783 31 1806T95 1829Q133 1829 160 1806T188 1731Q188 1681 161 1657T95 1632Q58 1632 32 1656T5 1731ZM386 1731Q386 1783 412 1806T476 1829Q513 1829 +540 1806T568 1731Q568 1681 541 1657T476 1632Q439 1632 413 1656T386 1731Z" /> +<glyph unicode="Ð" glyph-name="Eth" horiz-adv-x="1479" d="M1352 745Q1352 383 1156 192T590 0H201V649H47V799H201V1462H635Q972 1462 1162 1275T1352 745ZM1171 739Q1171 1315 602 1315H371V799H750V649H371V147H561Q1171 147 1171 739Z" /> +<glyph unicode="Ñ" glyph-name="Ntilde" horiz-adv-x="1544" d="M1343 0H1149L350 1227H342Q358 1011 358 831V0H201V1462H393L1190 240H1198Q1196 267 1189 413T1184 623V1462H1343V0ZM935 1581Q892 1581 851 1599T771 1640T695 1681T624 1700Q574 1700 +549 1670T509 1579H411Q424 1700 481 1768T630 1837Q676 1837 719 1819T801 1778T876 1737T944 1718Q993 1718 1017 1747T1056 1839H1155Q1142 1718 1086 1650T935 1581Z" /> +<glyph unicode="Ò" glyph-name="Ograve" horiz-adv-x="1595" d="M1470 733Q1470 382 1293 181T799 -20Q476 -20 301 177T125 735Q125 1092 301 1288T801 1485Q1116 1485 1293 1285T1470 733ZM305 733Q305 436 431 283T799 129Q1042 129 1166 282T1290 733Q1290 +1028 1167 1180T801 1333Q558 1333 432 1180T305 733ZM907 1579H797Q732 1631 643 1727T514 1886V1907H717Q749 1838 806 1748T907 1604V1579Z" /> +<glyph unicode="Ó" glyph-name="Oacute" horiz-adv-x="1595" d="M1470 733Q1470 382 1293 181T799 -20Q476 -20 301 177T125 735Q125 1092 301 1288T801 1485Q1116 1485 1293 1285T1470 733ZM305 733Q305 436 431 283T799 129Q1042 129 1166 282T1290 733Q1290 +1028 1167 1180T801 1333Q558 1333 432 1180T305 733ZM659 1604Q707 1666 762 1754T850 1907H1052V1886Q1008 1821 921 1726T770 1579H659V1604Z" /> +<glyph unicode="Ô" glyph-name="Ocircumflex" horiz-adv-x="1595" d="M1470 733Q1470 382 1293 181T799 -20Q476 -20 301 177T125 735Q125 1092 301 1288T801 1485Q1116 1485 1293 1285T1470 733ZM305 733Q305 436 431 283T799 129Q1042 129 1166 282T1290 +733Q1290 1028 1167 1180T801 1333Q558 1333 432 1180T305 733ZM448 1602Q575 1738 626 1802T700 1907H866Q888 1865 942 1799T1122 1602V1579H1003Q915 1634 782 1765Q646 1631 563 1579H448V1602Z" /> +<glyph unicode="Õ" glyph-name="Otilde" horiz-adv-x="1595" d="M1470 733Q1470 382 1293 181T799 -20Q476 -20 301 177T125 735Q125 1092 301 1288T801 1485Q1116 1485 1293 1285T1470 733ZM305 733Q305 436 431 283T799 129Q1042 129 1166 282T1290 733Q1290 +1028 1167 1180T801 1333Q558 1333 432 1180T305 733ZM942 1581Q899 1581 858 1599T778 1640T702 1681T631 1700Q581 1700 556 1670T516 1579H418Q431 1700 488 1768T637 1837Q683 1837 726 1819T808 1778T883 1737T951 1718Q1000 1718 1024 1747T1063 1839H1162Q1149 +1718 1093 1650T942 1581Z" /> +<glyph unicode="Ö" glyph-name="Odieresis" horiz-adv-x="1595" d="M1470 733Q1470 382 1293 181T799 -20Q476 -20 301 177T125 735Q125 1092 301 1288T801 1485Q1116 1485 1293 1285T1470 733ZM305 733Q305 436 431 283T799 129Q1042 129 1166 282T1290 +733Q1290 1028 1167 1180T801 1333Q558 1333 432 1180T305 733ZM522 1731Q522 1783 548 1806T612 1829Q650 1829 677 1806T705 1731Q705 1681 678 1657T612 1632Q575 1632 549 1656T522 1731ZM903 1731Q903 1783 929 1806T993 1829Q1030 1829 1057 1806T1085 1731Q1085 +1681 1058 1657T993 1632Q956 1632 930 1656T903 1731Z" /> +<glyph unicode="×" glyph-name="multiply" horiz-adv-x="1171" d="M940 1176L1036 1077L684 723L1034 371L938 272L584 623L236 272L135 371L485 723L133 1075L233 1176L586 821L940 1176Z" /> +<glyph unicode="Ø" glyph-name="Oslash" horiz-adv-x="1595" d="M1470 733Q1470 382 1293 181T799 -20Q564 -20 416 80L315 -61L195 18L303 172Q125 370 125 735Q125 1092 301 1288T801 1485Q1010 1485 1167 1391L1264 1526L1384 1446L1278 1298Q1470 1096 +1470 733ZM1290 733Q1290 1005 1180 1159L508 211Q623 129 799 129Q1042 129 1166 282T1290 733ZM305 733Q305 471 406 317L1075 1260Q969 1333 801 1333Q558 1333 432 1180T305 733Z" /> +<glyph unicode="Ù" glyph-name="Ugrave" horiz-adv-x="1491" d="M1305 1462V516Q1305 266 1154 123T739 -20Q475 -20 331 124T186 520V1462H356V508Q356 325 456 227T750 129Q935 129 1035 227T1135 510V1462H1305ZM856 1579H746Q681 1631 592 1727T463 1886V1907H666Q698 +1838 755 1748T856 1604V1579Z" /> +<glyph unicode="Ú" glyph-name="Uacute" horiz-adv-x="1491" d="M1305 1462V516Q1305 266 1154 123T739 -20Q475 -20 331 124T186 520V1462H356V508Q356 325 456 227T750 129Q935 129 1035 227T1135 510V1462H1305ZM600 1604Q648 1666 703 1754T791 1907H993V1886Q949 +1821 862 1726T711 1579H600V1604Z" /> +<glyph unicode="Û" glyph-name="Ucircumflex" horiz-adv-x="1491" d="M1305 1462V516Q1305 266 1154 123T739 -20Q475 -20 331 124T186 520V1462H356V508Q356 325 456 227T750 129Q935 129 1035 227T1135 510V1462H1305ZM393 1602Q520 1738 571 1802T645 +1907H811Q833 1865 887 1799T1067 1602V1579H948Q860 1634 727 1765Q591 1631 508 1579H393V1602Z" /> +<glyph unicode="Ü" glyph-name="Udieresis" horiz-adv-x="1491" d="M1305 1462V516Q1305 266 1154 123T739 -20Q475 -20 331 124T186 520V1462H356V508Q356 325 456 227T750 129Q935 129 1035 227T1135 510V1462H1305ZM461 1731Q461 1783 487 1806T551 1829Q589 +1829 616 1806T644 1731Q644 1681 617 1657T551 1632Q514 1632 488 1656T461 1731ZM842 1731Q842 1783 868 1806T932 1829Q969 1829 996 1806T1024 1731Q1024 1681 997 1657T932 1632Q895 1632 869 1656T842 1731Z" /> +<glyph unicode="Ý" glyph-name="Yacute" horiz-adv-x="1147" d="M573 731L963 1462H1147L659 567V0H487V559L0 1462H186L573 731ZM442 1604Q490 1666 545 1754T633 1907H835V1886Q791 1821 704 1726T553 1579H442V1604Z" /> +<glyph unicode="Þ" glyph-name="Thorn" horiz-adv-x="1251" d="M1145 784Q1145 557 994 438T555 319H371V0H201V1462H371V1206H586Q867 1206 1006 1103T1145 784ZM371 465H539Q765 465 866 536T967 772Q967 921 872 990T575 1059H371V465Z" /> +<glyph unicode="ß" glyph-name="germandbls" horiz-adv-x="1274" d="M1049 1266Q1049 1131 906 1016Q818 946 790 913T762 846Q762 814 775 793T824 744T938 664Q1078 569 1129 491T1180 311Q1180 151 1083 66T807 -20Q619 -20 512 49V203Q575 164 653 141T803 +117Q1018 117 1018 299Q1018 374 977 427T825 551Q698 633 650 694T602 840Q602 903 636 956T742 1062Q817 1119 849 1164T881 1262Q881 1342 813 1384T618 1427Q342 1427 342 1204V0H176V1202Q176 1380 286 1473T618 1567Q824 1567 936 1489T1049 1266Z" /> +<glyph unicode="à" glyph-name="agrave" horiz-adv-x="1139" d="M850 0L817 156H809Q727 53 646 17T442 -20Q279 -20 187 64T94 303Q94 635 625 651L811 657V725Q811 854 756 915T578 977Q441 977 268 893L217 1020Q298 1064 394 1089T588 1114Q784 1114 +878 1027T973 748V0H850ZM475 117Q630 117 718 202T807 440V539L641 532Q443 525 356 471T268 301Q268 211 322 164T475 117ZM928 1241H818Q753 1293 664 1389T535 1548V1569H738Q770 1500 827 1410T928 1266V1241Z" /> +<glyph unicode="á" glyph-name="aacute" horiz-adv-x="1139" d="M850 0L817 156H809Q727 53 646 17T442 -20Q279 -20 187 64T94 303Q94 635 625 651L811 657V725Q811 854 756 915T578 977Q441 977 268 893L217 1020Q298 1064 394 1089T588 1114Q784 1114 +878 1027T973 748V0H850ZM475 117Q630 117 718 202T807 440V539L641 532Q443 525 356 471T268 301Q268 211 322 164T475 117ZM436 1266Q484 1328 539 1416T627 1569H829V1548Q785 1483 698 1388T547 1241H436V1266Z" /> +<glyph unicode="â" glyph-name="acircumflex" horiz-adv-x="1139" d="M850 0L817 156H809Q727 53 646 17T442 -20Q279 -20 187 64T94 303Q94 635 625 651L811 657V725Q811 854 756 915T578 977Q441 977 268 893L217 1020Q298 1064 394 1089T588 1114Q784 +1114 878 1027T973 748V0H850ZM475 117Q630 117 718 202T807 440V539L641 532Q443 525 356 471T268 301Q268 211 322 164T475 117ZM484 1264Q611 1400 662 1464T736 1569H902Q924 1527 978 1461T1158 1264V1241H1039Q951 1296 818 1427Q682 1293 599 1241H484V1264Z" +/> +<glyph unicode="ã" glyph-name="atilde" horiz-adv-x="1139" d="M850 0L817 156H809Q727 53 646 17T442 -20Q279 -20 187 64T94 303Q94 635 625 651L811 657V725Q811 854 756 915T578 977Q441 977 268 893L217 1020Q298 1064 394 1089T588 1114Q784 1114 +878 1027T973 748V0H850ZM475 117Q630 117 718 202T807 440V539L641 532Q443 525 356 471T268 301Q268 211 322 164T475 117ZM977 1243Q934 1243 893 1261T813 1302T737 1343T666 1362Q616 1362 591 1332T551 1241H453Q466 1362 523 1430T672 1499Q718 1499 761 +1481T843 1440T918 1399T986 1380Q1035 1380 1059 1409T1098 1501H1197Q1184 1380 1128 1312T977 1243Z" /> +<glyph unicode="ä" glyph-name="adieresis" horiz-adv-x="1139" d="M850 0L817 156H809Q727 53 646 17T442 -20Q279 -20 187 64T94 303Q94 635 625 651L811 657V725Q811 854 756 915T578 977Q441 977 268 893L217 1020Q298 1064 394 1089T588 1114Q784 1114 +878 1027T973 748V0H850ZM475 117Q630 117 718 202T807 440V539L641 532Q443 525 356 471T268 301Q268 211 322 164T475 117ZM535 1393Q535 1445 561 1468T625 1491Q663 1491 690 1468T718 1393Q718 1343 691 1319T625 1294Q588 1294 562 1318T535 1393ZM916 1393Q916 +1445 942 1468T1006 1491Q1043 1491 1070 1468T1098 1393Q1098 1343 1071 1319T1006 1294Q969 1294 943 1318T916 1393Z" /> +<glyph unicode="å" glyph-name="aring" horiz-adv-x="1139" d="M850 0L817 156H809Q727 53 646 17T442 -20Q279 -20 187 64T94 303Q94 635 625 651L811 657V725Q811 854 756 915T578 977Q441 977 268 893L217 1020Q298 1064 394 1089T588 1114Q784 1114 878 +1027T973 748V0H850ZM475 117Q630 117 718 202T807 440V539L641 532Q443 525 356 471T268 301Q268 211 322 164T475 117ZM1060 1458Q1060 1360 999 1301T835 1241Q734 1241 674 1299T614 1456Q614 1554 674 1611T835 1669Q936 1669 998 1610T1060 1458ZM952 1456Q952 +1512 919 1542T835 1573Q784 1573 751 1543T718 1456Q718 1400 748 1370T835 1339Q887 1339 919 1369T952 1456Z" /> +<glyph unicode="æ" glyph-name="ae" horiz-adv-x="1757" d="M94 303Q94 464 218 553T596 651L780 657V725Q780 854 722 915T545 977Q401 977 238 893L186 1020Q260 1061 359 1087T557 1114Q687 1114 769 1071T893 932Q946 1020 1031 1068T1227 1116Q1419 +1116 1535 983T1651 627V520H950Q958 125 1272 125Q1363 125 1441 142T1604 199V51Q1518 13 1444 -3T1268 -20Q979 -20 854 213Q773 86 675 33T442 -20Q279 -20 187 65T94 303ZM268 301Q268 206 321 162T463 117Q608 117 692 201T776 440V539L618 532Q432 524 350 +470T268 301ZM1225 977Q1104 977 1035 894T954 653H1473Q1473 809 1409 893T1225 977Z" /> +<glyph unicode="ç" glyph-name="ccedilla" horiz-adv-x="975" d="M614 -20Q376 -20 246 126T115 541Q115 816 247 966T625 1116Q704 1116 783 1099T907 1059L856 918Q801 940 736 954T621 969Q287 969 287 543Q287 341 368 233T610 125Q747 125 891 184V37Q781 +-20 614 -20ZM762 -289Q762 -386 686 -439T459 -492Q408 -492 363 -483V-377Q408 -385 467 -385Q546 -385 586 -365T627 -291Q627 -248 588 -222T439 -178L527 0H637L582 -115Q762 -154 762 -289Z" /> +<glyph unicode="è" glyph-name="egrave" horiz-adv-x="1149" d="M639 -20Q396 -20 256 128T115 539Q115 804 245 960T596 1116Q802 1116 922 981T1042 623V518H287Q292 325 384 225T645 125Q822 125 995 199V51Q907 13 829 -3T639 -20ZM594 977Q462 977 384 +891T291 653H864Q864 810 794 893T594 977ZM967 1241H857Q792 1293 703 1389T574 1548V1569H777Q809 1500 866 1410T967 1266V1241Z" /> +<glyph unicode="é" glyph-name="eacute" horiz-adv-x="1149" d="M639 -20Q396 -20 256 128T115 539Q115 804 245 960T596 1116Q802 1116 922 981T1042 623V518H287Q292 325 384 225T645 125Q822 125 995 199V51Q907 13 829 -3T639 -20ZM594 977Q462 977 384 +891T291 653H864Q864 810 794 893T594 977ZM471 1266Q519 1328 574 1416T662 1569H864V1548Q820 1483 733 1388T582 1241H471V1266Z" /> +<glyph unicode="ê" glyph-name="ecircumflex" horiz-adv-x="1149" d="M639 -20Q396 -20 256 128T115 539Q115 804 245 960T596 1116Q802 1116 922 981T1042 623V518H287Q292 325 384 225T645 125Q822 125 995 199V51Q907 13 829 -3T639 -20ZM594 977Q462 +977 384 891T291 653H864Q864 810 794 893T594 977ZM515 1264Q642 1400 693 1464T767 1569H933Q955 1527 1009 1461T1189 1264V1241H1070Q982 1296 849 1427Q713 1293 630 1241H515V1264Z" /> +<glyph unicode="ë" glyph-name="edieresis" horiz-adv-x="1149" d="M639 -20Q396 -20 256 128T115 539Q115 804 245 960T596 1116Q802 1116 922 981T1042 623V518H287Q292 325 384 225T645 125Q822 125 995 199V51Q907 13 829 -3T639 -20ZM594 977Q462 977 +384 891T291 653H864Q864 810 794 893T594 977ZM319 1393Q319 1445 345 1468T409 1491Q447 1491 474 1468T502 1393Q502 1343 475 1319T409 1294Q372 1294 346 1318T319 1393ZM700 1393Q700 1445 726 1468T790 1491Q827 1491 854 1468T882 1393Q882 1343 855 1319T790 +1294Q753 1294 727 1318T700 1393Z" /> +<glyph unicode="ì" glyph-name="igrave" horiz-adv-x="518" d="M342 0H176V1096H342V0ZM355 1241H245Q180 1293 91 1389T-38 1548V1569H165Q197 1500 254 1410T355 1266V1241Z" /> +<glyph unicode="í" glyph-name="iacute" horiz-adv-x="518" d="M342 0H176V1096H342V0ZM169 1266Q217 1328 272 1416T360 1569H562V1548Q518 1483 431 1388T280 1241H169V1266Z" /> +<glyph unicode="î" glyph-name="icircumflex" horiz-adv-x="518" d="M342 0H176V1096H342V0ZM-77 1264Q50 1400 101 1464T175 1569H341Q363 1527 417 1461T597 1264V1241H478Q390 1296 257 1427Q121 1293 38 1241H-77V1264Z" /> +<glyph unicode="ï" glyph-name="idieresis" horiz-adv-x="518" d="M342 0H176V1096H342V0ZM-20 1393Q-20 1445 6 1468T70 1491Q108 1491 135 1468T163 1393Q163 1343 136 1319T70 1294Q33 1294 7 1318T-20 1393ZM361 1393Q361 1445 387 1468T451 1491Q488 +1491 515 1468T543 1393Q543 1343 516 1319T451 1294Q414 1294 388 1318T361 1393Z" /> +<glyph unicode="ð" glyph-name="eth" horiz-adv-x="1221" d="M1122 563Q1122 282 992 131T614 -20Q392 -20 253 114T113 475Q113 705 244 836T596 967Q822 967 922 846L930 850Q873 1064 668 1255L397 1100L324 1208L557 1341Q465 1403 371 1452L440 1569Q596 +1496 698 1421L936 1559L1012 1452L805 1333Q957 1190 1039 991T1122 563ZM954 512Q954 659 864 744T618 829Q281 829 281 469Q281 302 368 211T618 119Q793 119 873 219T954 512Z" /> +<glyph unicode="ñ" glyph-name="ntilde" horiz-adv-x="1257" d="M926 0V709Q926 843 865 909T674 975Q502 975 422 882T342 575V0H176V1096H311L338 946H346Q397 1027 489 1071T694 1116Q892 1116 992 1021T1092 715V0H926ZM802 1243Q759 1243 718 1261T638 +1302T562 1343T491 1362Q441 1362 416 1332T376 1241H278Q291 1362 348 1430T497 1499Q543 1499 586 1481T668 1440T743 1399T811 1380Q860 1380 884 1409T923 1501H1022Q1009 1380 953 1312T802 1243Z" /> +<glyph unicode="ò" glyph-name="ograve" horiz-adv-x="1237" d="M1122 549Q1122 281 987 131T614 -20Q467 -20 353 49T177 247T115 549Q115 817 249 966T621 1116Q851 1116 986 963T1122 549ZM287 549Q287 339 371 229T618 119Q781 119 865 228T950 549Q950 +758 866 866T616 975Q453 975 370 868T287 549ZM998 1241H888Q823 1293 734 1389T605 1548V1569H808Q840 1500 897 1410T998 1266V1241Z" /> +<glyph unicode="ó" glyph-name="oacute" horiz-adv-x="1237" d="M1122 549Q1122 281 987 131T614 -20Q467 -20 353 49T177 247T115 549Q115 817 249 966T621 1116Q851 1116 986 963T1122 549ZM287 549Q287 339 371 229T618 119Q781 119 865 228T950 549Q950 +758 866 866T616 975Q453 975 370 868T287 549ZM479 1266Q527 1328 582 1416T670 1569H872V1548Q828 1483 741 1388T590 1241H479V1266Z" /> +<glyph unicode="ô" glyph-name="ocircumflex" horiz-adv-x="1237" d="M1122 549Q1122 281 987 131T614 -20Q467 -20 353 49T177 247T115 549Q115 817 249 966T621 1116Q851 1116 986 963T1122 549ZM287 549Q287 339 371 229T618 119Q781 119 865 228T950 +549Q950 758 866 866T616 975Q453 975 370 868T287 549ZM282 1264Q409 1400 460 1464T534 1569H700Q722 1527 776 1461T956 1264V1241H837Q749 1296 616 1427Q480 1293 397 1241H282V1264Z" /> +<glyph unicode="õ" glyph-name="otilde" horiz-adv-x="1237" d="M1122 549Q1122 281 987 131T614 -20Q467 -20 353 49T177 247T115 549Q115 817 249 966T621 1116Q851 1116 986 963T1122 549ZM287 549Q287 339 371 229T618 119Q781 119 865 228T950 549Q950 +758 866 866T616 975Q453 975 370 868T287 549ZM1029 1243Q986 1243 945 1261T865 1302T789 1343T718 1362Q668 1362 643 1332T603 1241H505Q518 1362 575 1430T724 1499Q770 1499 813 1481T895 1440T970 1399T1038 1380Q1087 1380 1111 1409T1150 1501H1249Q1236 +1380 1180 1312T1029 1243Z" /> +<glyph unicode="ö" glyph-name="odieresis" horiz-adv-x="1237" d="M1122 549Q1122 281 987 131T614 -20Q467 -20 353 49T177 247T115 549Q115 817 249 966T621 1116Q851 1116 986 963T1122 549ZM287 549Q287 339 371 229T618 119Q781 119 865 228T950 549Q950 +758 866 866T616 975Q453 975 370 868T287 549ZM336 1393Q336 1445 362 1468T426 1491Q464 1491 491 1468T519 1393Q519 1343 492 1319T426 1294Q389 1294 363 1318T336 1393ZM717 1393Q717 1445 743 1468T807 1491Q844 1491 871 1468T899 1393Q899 1343 872 1319T807 +1294Q770 1294 744 1318T717 1393Z" /> +<glyph unicode="÷" glyph-name="divide" horiz-adv-x="1171" d="M104 653V791H1065V653H104ZM471 373Q471 433 500 463T584 494Q636 494 665 463T694 373Q694 316 665 284T584 252Q532 252 502 283T471 373ZM471 1071Q471 1131 500 1161T584 1192Q636 1192 +665 1161T694 1071Q694 1014 665 982T584 950Q532 950 502 981T471 1071Z" /> +<glyph unicode="ø" glyph-name="oslash" horiz-adv-x="1237" d="M1122 549Q1122 281 987 131T614 -20Q460 -20 348 49L264 -68L150 10L244 141Q115 293 115 549Q115 817 249 966T621 1116Q775 1116 891 1040L975 1159L1092 1083L995 950Q1122 798 1122 549ZM287 +549Q287 378 340 276L805 922Q730 975 616 975Q453 975 370 868T287 549ZM950 549Q950 713 899 813L434 170Q505 119 618 119Q781 119 865 228T950 549Z" /> +<glyph unicode="ù" glyph-name="ugrave" horiz-adv-x="1257" d="M332 1096V385Q332 251 393 185T584 119Q756 119 835 213T915 520V1096H1081V0H944L920 147H911Q860 66 770 23T563 -20Q363 -20 264 75T164 379V1096H332ZM982 1241H872Q807 1293 718 1389T589 +1548V1569H792Q824 1500 881 1410T982 1266V1241Z" /> +<glyph unicode="ú" glyph-name="uacute" horiz-adv-x="1257" d="M332 1096V385Q332 251 393 185T584 119Q756 119 835 213T915 520V1096H1081V0H944L920 147H911Q860 66 770 23T563 -20Q363 -20 264 75T164 379V1096H332ZM506 1266Q554 1328 609 1416T697 +1569H899V1548Q855 1483 768 1388T617 1241H506V1266Z" /> +<glyph unicode="û" glyph-name="ucircumflex" horiz-adv-x="1257" d="M332 1096V385Q332 251 393 185T584 119Q756 119 835 213T915 520V1096H1081V0H944L920 147H911Q860 66 770 23T563 -20Q363 -20 264 75T164 379V1096H332ZM286 1264Q413 1400 464 1464T538 +1569H704Q726 1527 780 1461T960 1264V1241H841Q753 1296 620 1427Q484 1293 401 1241H286V1264Z" /> +<glyph unicode="ü" glyph-name="udieresis" horiz-adv-x="1257" d="M332 1096V385Q332 251 393 185T584 119Q756 119 835 213T915 520V1096H1081V0H944L920 147H911Q860 66 770 23T563 -20Q363 -20 264 75T164 379V1096H332ZM342 1393Q342 1445 368 1468T432 +1491Q470 1491 497 1468T525 1393Q525 1343 498 1319T432 1294Q395 1294 369 1318T342 1393ZM723 1393Q723 1445 749 1468T813 1491Q850 1491 877 1468T905 1393Q905 1343 878 1319T813 1294Q776 1294 750 1318T723 1393Z" /> +<glyph unicode="ý" glyph-name="yacute" horiz-adv-x="1032" d="M2 1096H180L420 471Q499 257 518 162H526Q539 213 580 336T852 1096H1030L559 -152Q489 -337 396 -414T166 -492Q90 -492 16 -475V-342Q71 -354 139 -354Q310 -354 383 -162L444 -6L2 1096ZM411 +1266Q459 1328 514 1416T602 1569H804V1548Q760 1483 673 1388T522 1241H411V1266Z" /> +<glyph unicode="þ" glyph-name="thorn" horiz-adv-x="1255" d="M344 948Q410 1037 495 1076T686 1116Q901 1116 1021 966T1141 549Q1141 281 1021 131T686 -20Q464 -20 342 141H330L334 107Q342 30 342 -33V-492H176V1556H342V1090Q342 1038 336 948H344ZM664 +975Q496 975 420 883T342 590V549Q342 318 419 219T666 119Q969 119 969 551Q969 766 895 870T664 975Z" /> +<glyph unicode="ÿ" glyph-name="ydieresis" horiz-adv-x="1032" d="M2 1096H180L420 471Q499 257 518 162H526Q539 213 580 336T852 1096H1030L559 -152Q489 -337 396 -414T166 -492Q90 -492 16 -475V-342Q71 -354 139 -354Q310 -354 383 -162L444 -6L2 1096ZM490 +1393Q490 1445 516 1468T580 1491Q618 1491 645 1468T673 1393Q673 1343 646 1319T580 1294Q543 1294 517 1318T490 1393ZM871 1393Q871 1445 897 1468T961 1491Q998 1491 1025 1468T1053 1393Q1053 1343 1026 1319T961 1294Q924 1294 898 1318T871 1393Z" /> +<glyph unicode="–" glyph-name="endash" horiz-adv-x="1024" d="M82 473V625H942V473H82Z" /> +<glyph unicode="—" glyph-name="emdash" horiz-adv-x="2048" d="M82 473V625H1966V473H82Z" /> +<glyph unicode="‘" glyph-name="quoteleft" horiz-adv-x="348" d="M37 961L25 983Q47 1073 96 1207T201 1462H324Q258 1208 221 961H37Z" /> +<glyph unicode="’" glyph-name="quoteright" horiz-adv-x="348" d="M309 1462L324 1440Q298 1340 249 1208T147 961H25Q95 1246 127 1462H309Z" /> +<glyph unicode="‚" glyph-name="quotesinglbase" horiz-adv-x="502" d="M350 238L365 215Q339 115 290 -17T188 -264H63Q90 -160 122 -7T168 238H350Z" /> +<glyph unicode="“" glyph-name="quotedblleft" horiz-adv-x="717" d="M406 961L391 983Q447 1198 569 1462H692Q662 1347 633 1203T590 961H406ZM37 961L25 983Q47 1073 96 1207T201 1462H324Q258 1208 221 961H37Z" /> +<glyph unicode="”" glyph-name="quotedblright" horiz-adv-x="717" d="M309 1462L324 1440Q298 1340 249 1208T147 961H25Q95 1246 127 1462H309ZM678 1462L692 1440Q668 1349 620 1216T516 961H391Q417 1061 450 1215T496 1462H678Z" /> +<glyph unicode="„" glyph-name="quotedblbase" horiz-adv-x="829" d="M309 238L324 216Q298 116 249 -16T147 -263H25Q95 22 127 238H309ZM678 238L692 216Q668 125 620 -8T516 -263H391Q417 -163 450 -9T496 238H678Z" /> +<glyph unicode="•" glyph-name="bullet" horiz-adv-x="770" d="M164 748Q164 869 220 932T385 995Q490 995 548 933T606 748Q606 629 549 565T385 500Q278 500 221 565T164 748Z" /> +<glyph unicode="‹" glyph-name="guilsinglleft" horiz-adv-x="623" d="M82 551L424 958L543 889L254 539L543 188L424 117L82 524V551Z" /> +<glyph unicode="›" glyph-name="guilsinglright" horiz-adv-x="623" d="M541 524L197 117L80 188L367 539L80 889L197 958L541 551V524Z" /> +</font> +</defs> +</svg> diff --git a/website/agenda/planung/fonts/open-sans-v15-latin_latin-ext-regular.ttf b/website/agenda/planung/fonts/open-sans-v15-latin_latin-ext-regular.ttf new file mode 100644 index 0000000..65a04f1 Binary files /dev/null and b/website/agenda/planung/fonts/open-sans-v15-latin_latin-ext-regular.ttf differ diff --git a/website/agenda/planung/fonts/open-sans-v15-latin_latin-ext-regular.woff b/website/agenda/planung/fonts/open-sans-v15-latin_latin-ext-regular.woff new file mode 100644 index 0000000..6ca02c4 Binary files /dev/null and b/website/agenda/planung/fonts/open-sans-v15-latin_latin-ext-regular.woff differ diff --git a/website/agenda/planung/fonts/open-sans-v15-latin_latin-ext-regular.woff2 b/website/agenda/planung/fonts/open-sans-v15-latin_latin-ext-regular.woff2 new file mode 100644 index 0000000..a337154 Binary files /dev/null and b/website/agenda/planung/fonts/open-sans-v15-latin_latin-ext-regular.woff2 differ diff --git a/website/agenda/planung/fonts/roboto-v18-latin_latin-ext-regular.eot b/website/agenda/planung/fonts/roboto-v18-latin_latin-ext-regular.eot new file mode 100644 index 0000000..748c0e6 Binary files /dev/null and b/website/agenda/planung/fonts/roboto-v18-latin_latin-ext-regular.eot differ diff --git a/website/agenda/planung/fonts/roboto-v18-latin_latin-ext-regular.svg b/website/agenda/planung/fonts/roboto-v18-latin_latin-ext-regular.svg new file mode 100644 index 0000000..627f5a3 --- /dev/null +++ b/website/agenda/planung/fonts/roboto-v18-latin_latin-ext-regular.svg @@ -0,0 +1,308 @@ +<?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"> +<defs > +<font id="Roboto" horiz-adv-x="1158" ><font-face + font-family="Roboto" + units-per-em="2048" + panose-1="2 0 0 0 0 0 0 0 0 0" + ascent="1900" + descent="-500" + alphabetic="0" /> +<glyph unicode=" " horiz-adv-x="507" /> +<glyph unicode="!" horiz-adv-x="527" d="M347 411H180L167 1456H361L347 411ZM160 93Q160 138 187 168T269 199T351 169T379 93T351 19T269 -11T188 18T160 93Z" /> +<glyph unicode=""" horiz-adv-x="655" d="M277 1400L247 1042H136L137 1536H277V1400ZM547 1400L517 1042H406L407 1536H547V1400Z" /> +<glyph unicode="#" horiz-adv-x="1261" d="M765 410H501L421 0H278L358 410H119V547H384L453 901H195V1040H480L562 1456H705L623 1040H887L969 1456H1113L1031 1040H1235V901H1004L935 547H1160V410H909L829 0H685L765 410ZM527 547H791L860 901H596L527 547Z" /> +<glyph unicode="$" horiz-adv-x="1150" d="M856 375Q856 467 792 530T574 644Q361 709 264 813T166 1079Q166 1243 261 1348T524 1473V1692H673V1472Q841 1449 934 1331T1028 1008H844Q844 1149 777 1232T596 1315Q477 1315 414 1254T351 1082Q351 980 417 920T636 +810T874 701T1000 562T1041 377Q1041 208 940 105T655 -17V-208H507V-17Q321 0 216 115T110 429H295Q295 290 368 215T575 140Q706 140 781 203T856 375Z" /> +<glyph unicode="%" horiz-adv-x="1500" d="M105 1176Q105 1307 188 1392T403 1477Q536 1477 618 1392T701 1170V1099Q701 967 618 884T405 800Q275 800 190 883T105 1106V1176ZM243 1099Q243 1021 287 971T405 920Q476 920 519 969T563 1103V1176Q563 1254 520 +1305T403 1356T286 1305T243 1172V1099ZM814 357Q814 488 897 572T1112 657T1327 573T1411 350V279Q1411 148 1328 64T1114 -21T899 62T814 285V357ZM952 279Q952 200 996 150T1114 99Q1186 99 1229 148T1272 283V357Q1272 436 1229 486T1112 536Q1041 536 997 +487T952 353V279ZM447 110L342 176L1053 1314L1158 1248L447 110Z" /> +<glyph unicode="&" horiz-adv-x="1273" d="M101 391Q101 496 159 584T383 789Q286 907 253 979T220 1122Q220 1288 318 1382T584 1476Q734 1476 832 1389T930 1168Q930 1080 886 1006T730 849L623 770L947 383Q1015 513 1015 672H1182Q1182 417 1059 249L1267 +0H1045L948 115Q874 49 775 15T572 -20Q359 -20 230 93T101 391ZM572 131Q719 131 841 243L486 668L453 644Q286 521 286 391Q286 273 362 202T572 131ZM405 1128Q405 1032 523 888L641 971Q709 1019 734 1062T759 1168Q759 1235 709 1279T583 1324Q501 1324 453 +1269T405 1128Z" /> +<glyph unicode="'" horiz-adv-x="357" d="M253 1425L232 1057H103L104 1536H253V1425Z" /> +<glyph unicode="(" horiz-adv-x="700" d="M133 591Q133 817 193 1025T374 1403T623 1643L661 1521Q515 1409 422 1179T319 664L318 579Q318 193 459 -91Q544 -261 661 -357L623 -470Q490 -396 369 -222Q133 118 133 591Z" /> +<glyph unicode=")" horiz-adv-x="712" d="M567 581Q567 358 509 154T330 -224T77 -470L38 -357Q192 -239 285 9T381 561V593Q381 803 337 983T215 1307T38 1530L77 1643Q209 1570 328 1399T507 1022T567 581Z" /> +<glyph unicode="*" horiz-adv-x="882" d="M330 983L28 1073L74 1224L376 1112L367 1456H520L510 1107L807 1217L853 1065L546 974L744 703L620 609L434 897L254 616L129 707L330 983Z" /> +<glyph unicode="+" horiz-adv-x="1161" d="M670 781H1076V606H670V146H484V606H78V781H484V1206H670V781Z" /> +<glyph unicode="," horiz-adv-x="402" d="M134 -290L29 -218Q123 -87 127 52V219H308V74Q308 -27 259 -128T134 -290Z" /> +<glyph unicode="-" horiz-adv-x="565" d="M525 543H37V694H525V543Z" /> +<glyph unicode="." horiz-adv-x="539" d="M144 97Q144 145 172 177T258 209T344 177T374 97Q374 51 345 20T258 -11T173 20T144 97Z" /> +<glyph unicode="/" horiz-adv-x="844" d="M177 -125H18L626 1456H784L177 -125Z" /> +<glyph unicode="0" horiz-adv-x="1150" d="M1034 621Q1034 296 923 138T576 -20Q343 -20 231 134T115 596V843Q115 1164 226 1320T574 1476Q809 1476 920 1326T1034 861V621ZM849 874Q849 1109 783 1216T574 1324Q432 1324 367 1217T300 888V592Q300 356 368 244T576 +131Q713 131 779 237T849 571V874Z" /> +<glyph unicode="1" horiz-adv-x="1150" d="M729 0H543V1233L170 1096V1264L700 1463H729V0Z" /> +<glyph unicode="2" horiz-adv-x="1150" d="M1075 0H121V133L625 693Q737 820 779 899T822 1064Q822 1178 753 1251T569 1324Q431 1324 355 1246T278 1027H93Q93 1228 222 1352T569 1476Q772 1476 890 1370T1008 1086Q1008 871 734 574L344 151H1075V0Z" /> +<glyph unicode="3" horiz-adv-x="1150" d="M390 818H529Q660 820 735 887T810 1068Q810 1324 555 1324Q435 1324 364 1256T292 1074H107Q107 1247 233 1361T555 1476Q761 1476 878 1367T995 1064Q995 969 934 880T766 747Q886 709 951 621T1017 406Q1017 210 889 +95T556 -20T223 91T94 384H280Q280 269 355 200T556 131Q690 131 761 201T832 402Q832 529 754 597T529 667H390V818Z" /> +<glyph unicode="4" horiz-adv-x="1150" d="M902 489H1104V338H902V0H716V338H53V447L705 1456H902V489ZM263 489H716V1203L694 1163L263 489Z" /> +<glyph unicode="5" horiz-adv-x="1150" d="M206 730L280 1456H1026V1285H437L393 888Q500 951 636 951Q835 951 952 820T1069 464Q1069 239 948 110T608 -20Q415 -20 293 87T154 383H329Q346 258 418 195T608 131Q737 131 810 219T884 462Q884 608 805 696T593 +785Q472 785 403 732L354 692L206 730Z" /> +<glyph unicode="6" horiz-adv-x="1150" d="M847 1457V1300H813Q597 1296 469 1172T321 823Q436 955 635 955Q825 955 938 821T1052 475Q1052 250 930 115T601 -20Q392 -20 262 140T132 554V625Q132 1027 303 1239T814 1457H847ZM604 801Q509 801 429 744T318 601V533Q318 +353 399 243T601 133Q726 133 797 225T869 466Q869 616 797 708T604 801Z" /> +<glyph unicode="7" horiz-adv-x="1150" d="M1061 1352L458 0H264L865 1304H77V1456H1061V1352Z" /> +<glyph unicode="8" horiz-adv-x="1150" d="M1004 1076Q1004 967 947 882T791 749Q905 700 971 606T1038 393Q1038 204 911 92T575 -20Q365 -20 239 92T112 393Q112 511 176 606T355 750Q258 798 202 883T146 1076Q146 1260 264 1368T575 1476Q767 1476 885 1368T1004 +1076ZM853 397Q853 519 776 596T573 673T373 597T297 397T370 202T575 131Q705 131 779 202T853 397ZM575 1324Q466 1324 399 1257T331 1073Q331 962 397 894T575 825T752 893T819 1073T750 1254T575 1324Z" /> +<glyph unicode="9" horiz-adv-x="1150" d="M830 640Q772 571 692 529T515 487Q389 487 296 549T151 723T100 972Q100 1118 155 1235T313 1414T551 1476Q767 1476 891 1315T1016 874V820Q1016 395 848 200T341 -1H305V155H344Q573 159 696 274T830 640ZM545 640Q638 +640 716 697T831 838V912Q831 1094 752 1208T552 1322Q430 1322 356 1229T282 982Q282 833 353 737T545 640Z" /> +<glyph unicode=":" horiz-adv-x="496" d="M390 97Q390 145 418 177T504 209T590 177T620 97Q620 51 591 20T504 -11T419 20T390 97ZM135 980Q135 1028 163 1060T249 1092T335 1060T365 980Q365 934 336 903T249 872T164 903T135 980Z" /> +<glyph unicode=";" horiz-adv-x="433" d="M111 980Q111 1028 139 1060T225 1092T311 1060T341 980Q341 934 312 903T225 872T140 903T111 980ZM146 -290L41 -218Q135 -87 139 52V219H320V74Q320 -27 271 -128T146 -290Z" /> +<glyph unicode="<" horiz-adv-x="1041" d="M264 644L890 391V195L72 574V720L890 1098V902L264 644Z" /> +<glyph unicode="=" horiz-adv-x="1124" d="M986 814H152V975H986V814ZM986 399H152V559H986V399Z" /> +<glyph unicode=">" horiz-adv-x="1070" d="M795 650L134 909V1099L988 721V575L134 196V388L795 650Z" /> +<glyph unicode="?" horiz-adv-x="967" d="M357 410Q359 529 384 598T486 751L617 886Q701 981 701 1090Q701 1195 646 1254T486 1314Q384 1314 322 1260T260 1115H75Q77 1277 190 1376T486 1476Q675 1476 780 1375T886 1096Q886 921 724 751L615 643Q542 562 542 +410H357ZM349 93Q349 138 376 168T458 199T540 169T568 93T540 19T458 -11T377 18T349 93Z" /> +<glyph unicode="@" horiz-adv-x="1839" d="M1738 502Q1726 260 1618 120T1329 -20Q1142 -20 1089 148Q1035 63 966 22T822 -20Q680 -20 607 96T553 417Q568 582 628 711T784 915T985 989Q1066 989 1130 968T1274 883L1222 329Q1203 98 1350 98Q1463 98 1533 210T1609 +502Q1628 891 1465 1095T967 1299Q766 1299 610 1200T364 912T263 478Q251 230 323 48T542 -231T899 -328Q989 -328 1079 -306T1230 -249L1267 -364Q1205 -403 1103 -428T895 -453Q645 -453 465 -341T196 -17T118 478Q130 753 241 972T542 1311T971 1431Q1220 1431 +1398 1319T1663 996T1738 502ZM712 417Q698 275 738 199T867 123Q927 123 982 174T1074 320L1075 329L1121 832Q1065 861 1001 861Q884 861 808 742T712 417Z" /> +<glyph unicode="A" horiz-adv-x="1336" d="M973 380H363L226 0H28L584 1456H752L1309 0H1112L973 380ZM421 538H916L668 1219L421 538Z" /> +<glyph unicode="B" horiz-adv-x="1275" d="M169 0V1456H645Q882 1456 1001 1358T1121 1068Q1121 966 1063 888T905 766Q1023 733 1091 641T1160 420Q1160 224 1033 112T674 0H169ZM361 681V157H678Q812 157 889 226T967 418Q967 681 681 681H361ZM361 835H651Q777 +835 852 898T928 1069Q928 1189 858 1243T645 1298H361V835Z" /> +<glyph unicode="C" horiz-adv-x="1333" d="M1240 462Q1213 231 1070 106T688 -20Q430 -20 275 165T119 660V800Q119 1003 191 1157T397 1393T705 1476Q937 1476 1077 1347T1240 988H1047Q1022 1162 939 1240T705 1318Q521 1318 417 1182T312 795V654Q312 417 411 +277T688 137Q848 137 933 209T1047 462H1240Z" /> +<glyph unicode="D" horiz-adv-x="1343" d="M169 0V1456H580Q770 1456 916 1372T1141 1133T1222 777V684Q1222 478 1143 323T916 85T572 0H169ZM361 1298V157H563Q785 157 908 295T1032 688V773Q1032 1021 916 1158T585 1298H361Z" /> +<glyph unicode="E" horiz-adv-x="1164" d="M992 673H361V157H1094V0H169V1456H1084V1298H361V830H992V673Z" /> +<glyph unicode="F" horiz-adv-x="1132" d="M972 643H361V0H169V1456H1071V1298H361V800H972V643Z" /> +<glyph unicode="G" horiz-adv-x="1395" d="M1244 191Q1170 85 1038 33T729 -20Q551 -20 413 63T200 301T122 658V785Q122 1114 275 1295T707 1476Q935 1476 1074 1360T1244 1029H1052Q998 1318 708 1318Q515 1318 416 1183T315 790V671Q315 426 427 282T730 137Q838 +137 919 161T1053 242V569H716V725H1244V191Z" /> +<glyph unicode="H" horiz-adv-x="1460" d="M1288 0H1095V673H361V0H169V1456H361V830H1095V1456H1288V0Z" /> +<glyph unicode="I" horiz-adv-x="557" d="M375 0H183V1456H375V0Z" /> +<glyph unicode="J" horiz-adv-x="1130" d="M779 1456H972V425Q972 216 847 98T512 -20Q295 -20 174 91T53 402H245Q245 277 313 207T512 137Q631 137 704 212T779 422V1456Z" /> +<glyph unicode="K" horiz-adv-x="1284" d="M539 677L361 492V0H169V1456H361V736L1008 1456H1240L667 813L1285 0H1055L539 677Z" /> +<glyph unicode="L" horiz-adv-x="1102" d="M362 157H1052V0H169V1456H362V157Z" /> +<glyph unicode="M" horiz-adv-x="1788" d="M417 1456L893 268L1369 1456H1618V0H1426V567L1444 1179L966 0H819L342 1176L361 567V0H169V1456H417Z" /> +<glyph unicode="N" horiz-adv-x="1460" d="M1288 0H1095L362 1122V0H169V1456H362L1097 329V1456H1288V0Z" /> +<glyph unicode="O" horiz-adv-x="1408" d="M1289 681Q1289 467 1217 308T1013 64T705 -20Q533 -20 400 64T194 305T118 668V773Q118 983 191 1144T397 1390T703 1476Q878 1476 1011 1392T1217 1147T1289 773V681ZM1098 775Q1098 1034 994 1172T703 1311Q521 1311 +417 1173T309 788V681Q309 430 414 287T705 143Q891 143 993 278T1098 667V775Z" /> +<glyph unicode="P" horiz-adv-x="1292" d="M361 570V0H169V1456H706Q945 1456 1080 1334T1216 1011Q1216 799 1084 685T704 570H361ZM361 727H706Q860 727 942 799T1024 1009Q1024 1139 942 1217T717 1298H361V727Z" /> +<glyph unicode="Q" horiz-adv-x="1408" d="M1281 681Q1281 470 1214 318T1026 79L1286 -125L1155 -246L848 -2Q776 -20 696 -20Q524 -20 391 64T185 305T109 668V773Q109 983 182 1144T388 1390T694 1476Q870 1476 1003 1391T1209 1147T1281 774V681ZM1089 775Q1089 +1032 987 1171T694 1311Q513 1311 409 1173T301 788V681Q301 431 405 287T696 143T984 278T1089 667V775Z" /> +<glyph unicode="R" horiz-adv-x="1261" d="M703 589H361V0H168V1456H650Q896 1456 1028 1344T1161 1018Q1161 882 1088 781T883 630L1225 12V0H1019L703 589ZM361 746H656Q799 746 883 820T968 1018Q968 1153 888 1225T655 1298H361V746Z" /> +<glyph unicode="S" horiz-adv-x="1215" d="M598 649Q351 720 239 823T126 1079Q126 1251 263 1363T621 1476Q771 1476 888 1418T1070 1258T1135 1035H942Q942 1167 858 1242T621 1318Q479 1318 400 1256T320 1082Q320 993 395 932T652 819T936 707T1088 563T1138 +370Q1138 193 1000 87T631 -20Q481 -20 351 37T151 195T80 422H273Q273 290 370 214T631 137Q783 137 864 199T945 368T870 533T598 649Z" /> +<glyph unicode="T" horiz-adv-x="1222" d="M1175 1298H707V0H516V1298H49V1456H1175V1298Z" /> +<glyph unicode="U" horiz-adv-x="1328" d="M1194 1456V466Q1193 260 1065 129T716 -18L665 -20Q426 -20 284 109T140 464V1456H330V470Q330 312 417 225T665 137Q828 137 914 224T1001 469V1456H1194Z" /> +<glyph unicode="V" horiz-adv-x="1303" d="M651 255L1067 1456H1277L737 0H567L28 1456H237L651 255Z" /> +<glyph unicode="W" horiz-adv-x="1817" d="M483 459L511 267L552 440L840 1456H1002L1283 440L1323 264L1354 460L1580 1456H1773L1420 0H1245L945 1061L922 1172L899 1061L588 0H413L61 1456H253L483 459Z" /> +<glyph unicode="X" horiz-adv-x="1284" d="M644 898L993 1456H1219L759 734L1230 0H1002L644 568L284 0H57L529 734L68 1456H293L644 898Z" /> +<glyph unicode="Y" horiz-adv-x="1230" d="M613 725L993 1456H1211L709 543V0H517V543L15 1456H235L613 725Z" /> +<glyph unicode="Z" horiz-adv-x="1226" d="M313 157H1146V0H86V144L884 1298H99V1456H1114V1315L313 157Z" /> +<glyph unicode="[" horiz-adv-x="543" d="M523 1512H332V-160H523V-312H146V1664H523V1512Z" /> +<glyph unicode="\" horiz-adv-x="840" d="M40 1456H216L824 -125H648L40 1456Z" /> +<glyph unicode="]" horiz-adv-x="543" d="M9 1664H387V-312H9V-160H202V1512H9V1664Z" /> +<glyph unicode="^" horiz-adv-x="856" d="M426 1211L236 729H64L363 1456H490L788 729H617L426 1211Z" /> +<glyph unicode="_" horiz-adv-x="924" d="M920 -151H4V0H920V-151Z" /> +<glyph unicode="`" horiz-adv-x="633" d="M474 1242H315L57 1536H280L474 1242Z" /> +<glyph unicode="a" horiz-adv-x="1114" d="M808 0Q792 32 782 114Q653 -20 474 -20Q314 -20 212 70T109 300Q109 469 237 562T599 656H779V741Q779 838 721 895T550 953Q451 953 384 903T317 782H131Q131 863 188 938T344 1058T561 1102Q748 1102 854 1009T964 +751V253Q964 104 1002 16V0H808ZM501 141Q588 141 666 186T779 303V525H634Q294 525 294 326Q294 239 352 190T501 141Z" /> +<glyph unicode="b" horiz-adv-x="1149" d="M1056 529Q1056 281 942 131T636 -20Q431 -20 319 125L310 0H140V1536H325V963Q437 1102 634 1102T943 953T1056 545V529ZM871 550Q871 739 798 842T588 945Q405 945 325 775V307Q410 137 590 137Q723 137 797 240T871 550Z" /> +<glyph unicode="c" horiz-adv-x="1072" d="M574 131Q673 131 747 191T829 341H1004Q999 248 940 164T783 30T574 -20Q353 -20 223 127T92 531V562Q92 720 150 843T316 1034T573 1102Q755 1102 875 993T1004 710H829Q821 815 750 882T573 950Q432 950 355 849T277 +555V520Q277 333 354 232T574 131Z" /> +<glyph unicode="d" horiz-adv-x="1155" d="M95 550Q95 799 213 950T522 1102Q712 1102 823 972V1536H1008V0H838L829 116Q718 -20 520 -20Q332 -20 214 134T95 536V550ZM280 529Q280 345 356 241T566 137Q742 137 823 295V792Q740 945 568 945Q432 945 356 840T280 529Z" /> +<glyph unicode="e" horiz-adv-x="1085" d="M589 -20Q369 -20 231 124T93 511V545Q93 706 154 832T326 1030T566 1102Q777 1102 894 963T1011 565V488H278Q282 328 371 230T599 131Q697 131 765 171T884 277L997 189Q861 -20 589 -20ZM566 950Q454 950 378 869T284 +640H826V654Q818 795 750 872T566 950Z" /> +<glyph unicode="f" horiz-adv-x="711" d="M231 0V939H60V1082H231V1193Q231 1367 324 1462T587 1557Q651 1557 714 1540L704 1390Q657 1399 604 1399Q514 1399 465 1347T416 1196V1082H647V939H416V0H231Z" /> +<glyph unicode="g" horiz-adv-x="1149" d="M96 550Q96 803 213 952T523 1102Q721 1102 832 962L841 1082H1010V26Q1010 -184 886 -305T551 -426Q434 -426 322 -376T151 -239L247 -128Q366 -275 538 -275Q673 -275 748 -199T824 15V108Q713 -20 521 -20Q331 -20 +214 133T96 550ZM282 529Q282 346 357 242T567 137Q742 137 824 296V790Q739 945 569 945Q434 945 358 840T282 529Z" /> +<glyph unicode="h" horiz-adv-x="1128" d="M325 951Q448 1102 645 1102Q988 1102 991 715V0H806V716Q805 833 753 889T589 945Q499 945 431 897T325 771V0H140V1536H325V951Z" /> +<glyph unicode="i" horiz-adv-x="497" d="M341 0H156V1082H341V0ZM141 1369Q141 1414 168 1445T250 1476T332 1445T360 1369T332 1294T250 1264T169 1294T141 1369Z" /> +<glyph unicode="j" horiz-adv-x="489" d="M331 1082V-125Q331 -437 48 -437Q-13 -437 -65 -419V-271Q-33 -279 19 -279Q81 -279 113 -246T146 -129V1082H331ZM127 1369Q127 1413 154 1444T235 1476Q289 1476 317 1445T345 1369T317 1294T235 1264T154 1294T127 1369Z" /> +<glyph unicode="k" horiz-adv-x="1038" d="M442 501L326 380V0H141V1536H326V607L425 726L762 1082H987L566 630L1036 0H819L442 501Z" /> +<glyph unicode="l" horiz-adv-x="497" d="M341 0H156V1536H341V0Z" /> +<glyph unicode="m" horiz-adv-x="1795" d="M314 1082L319 962Q438 1102 640 1102Q867 1102 949 928Q1003 1006 1089 1054T1294 1102Q1650 1102 1656 725V0H1471V714Q1471 830 1418 887T1240 945Q1137 945 1069 884T990 718V0H804V709Q804 945 573 945Q391 945 +324 790V0H139V1082H314Z" /> +<glyph unicode="n" horiz-adv-x="1130" d="M315 1082L321 946Q445 1102 645 1102Q988 1102 991 715V0H806V716Q805 833 753 889T589 945Q499 945 431 897T325 771V0H140V1082H315Z" /> +<glyph unicode="o" horiz-adv-x="1168" d="M91 551Q91 710 153 837T327 1033T582 1102Q803 1102 939 949T1076 542V529Q1076 371 1016 246T843 50T584 -20Q364 -20 228 133T91 538V551ZM277 529Q277 349 360 240T584 131Q725 131 808 241T891 551Q891 729 807 +839T582 950Q445 950 361 841T277 529Z" /> +<glyph unicode="p" horiz-adv-x="1149" d="M1054 529Q1054 282 941 131T635 -20Q438 -20 325 105V-416H140V1082H309L318 962Q431 1102 632 1102Q827 1102 940 955T1054 546V529ZM869 550Q869 733 791 839T577 945Q409 945 325 796V279Q408 131 579 131Q712 131 +790 236T869 550Z" /> +<glyph unicode="q" horiz-adv-x="1164" d="M95 550Q95 805 212 953T526 1102Q718 1102 829 973L837 1082H1007V-416H822V100Q710 -20 524 -20Q328 -20 212 132T95 537V550ZM280 529Q280 343 358 237T570 131Q735 131 822 277V807Q734 950 572 950Q438 950 359 +844T280 529Z" /> +<glyph unicode="r" horiz-adv-x="693" d="M663 916Q621 923 572 923Q390 923 325 768V0H140V1082H320L323 957Q414 1102 581 1102Q635 1102 663 1088V916Z" /> +<glyph unicode="s" horiz-adv-x="1056" d="M770 287Q770 362 714 403T517 475T294 547T172 647T132 785Q132 918 244 1010T532 1102Q716 1102 830 1007T945 764H759Q759 840 695 895T532 950Q431 950 374 906T317 791Q317 724 370 690T561 625T786 551T913 448T955 +300Q955 155 839 68T538 -20Q408 -20 308 26T152 154T95 333H280Q285 240 354 186T538 131Q643 131 706 173T770 287Z" /> +<glyph unicode="t" horiz-adv-x="669" d="M391 1344V1082H593V939H391V268Q391 203 418 171T510 138Q542 138 598 150V0Q525 -20 456 -20Q332 -20 269 55T206 268V939H9V1082H206V1344H391Z" /> +<glyph unicode="u" horiz-adv-x="1129" d="M808 107Q700 -20 491 -20Q318 -20 228 80T136 378V1082H321V383Q321 137 521 137Q733 137 803 295V1082H988V0H812L808 107Z" /> +<glyph unicode="v" horiz-adv-x="992" d="M497 251L765 1082H954L566 0H425L33 1082H222L497 251Z" /> +<glyph unicode="w" horiz-adv-x="1539" d="M1098 255L1306 1082H1491L1176 0H1026L763 820L507 0H357L43 1082H227L440 272L692 1082H841L1098 255Z" /> +<glyph unicode="x" horiz-adv-x="1015" d="M503 687L743 1082H959L605 547L970 0H756L506 405L256 0H41L406 547L52 1082H266L503 687Z" /> +<glyph unicode="y" horiz-adv-x="969" d="M494 271L746 1082H944L509 -167Q408 -437 188 -437L153 -434L84 -421V-271L134 -275Q228 -275 280 -237T367 -98L408 12L22 1082H224L494 271Z" /> +<glyph unicode="z" horiz-adv-x="1015" d="M314 151H947V0H88V136L685 929H97V1082H917V951L314 151Z" /> +<glyph unicode="{" horiz-adv-x="693" d="M632 -366Q455 -316 366 -202T276 101V300Q276 543 64 543V688Q276 688 276 930V1138Q278 1321 365 1433T632 1597L670 1482Q461 1415 461 1133V931Q461 704 294 615Q461 525 461 296V90Q464 -185 670 -251L632 -366Z" /> +<glyph unicode="|" horiz-adv-x="499" d="M324 -270H175V1456H324V-270Z" /> +<glyph unicode="}" horiz-adv-x="693" d="M19 -251Q222 -186 229 80V300Q229 531 410 615Q229 697 229 930V1133Q229 1415 20 1482L58 1597Q235 1547 324 1435T414 1137V927Q414 688 626 688V543Q414 543 414 300V98Q414 -90 324 -203T58 -366L19 -251Z" /> +<glyph unicode="~" horiz-adv-x="1393" d="M1263 777Q1263 619 1170 511T939 402Q867 402 803 428T655 529T533 621T454 639Q376 639 334 586T292 438L131 436Q131 596 223 699T454 802Q530 802 600 770T758 658T910 567L939 565Q1015 565 1062 623T1110 776L1263 777Z" /> +<glyph unicode=" " horiz-adv-x="507" /> +<glyph unicode="¡" horiz-adv-x="499" d="M170 684H338L351 -360H157L170 684ZM358 996Q358 951 331 920T249 889T167 920T139 996T167 1071T249 1101T330 1071T358 996Z" /> +<glyph unicode="¢" horiz-adv-x="1120" d="M586 131Q686 131 760 191T842 341H1017Q1011 215 912 115T669 -12V-245H484V-11Q305 23 205 165T105 527V562Q105 774 206 916T484 1092V1318H669V1095Q819 1072 915 966T1017 710H842Q834 815 763 882T586 950Q445 +950 368 849T290 555V520Q290 333 367 232T586 131Z" /> +<glyph unicode="£" horiz-adv-x="1190" d="M449 622L457 402Q457 248 395 157H1128L1127 0H95V157H172Q212 166 237 231T264 393V401L256 622H91V779H251L242 1039Q242 1238 364 1357T687 1476Q877 1476 988 1370T1099 1087H908Q908 1194 845 1256T670 1318Q565 +1318 500 1241T435 1039L444 779H763V622H449Z" /> +<glyph unicode="¤" horiz-adv-x="1460" d="M1103 112Q944 -20 735 -20Q528 -20 369 110L235 -26L105 109L244 250Q140 406 140 608Q140 814 252 977L105 1128L235 1264L382 1114Q540 1234 735 1234Q931 1234 1090 1113L1239 1265L1371 1128L1220 974Q1330 +811 1330 608Q1330 412 1228 253L1371 109L1239 -27L1103 112ZM311 608Q311 485 368 379T524 212T735 151T946 212T1100 379T1157 608Q1157 730 1101 835T946 1001T735 1062Q622 1062 524 1002T369 836T311 608Z" /> +<glyph unicode="¥" horiz-adv-x="1075" d="M539 793L847 1456H1060L693 736H954V611H630V446H954V322H630V0H437V322H119V446H437V611H119V736H382L15 1456H231L539 793Z" /> +<glyph unicode="¦" horiz-adv-x="491" d="M147 -270V521H333V-270H147ZM333 698H147V1456H333V698Z" /> +<glyph unicode="§" horiz-adv-x="1256" d="M1145 431Q1145 242 959 157Q1028 108 1064 40T1100 -128Q1100 -296 970 -395T612 -495Q500 -495 400 -467T229 -382Q90 -269 90 -64L276 -62Q276 -192 366 -267T612 -343Q748 -343 831 -285T914 -130Q914 -41 843 +11T563 126Q381 174 285 229T143 362T96 551Q96 737 278 825Q212 874 177 942T141 1110Q141 1276 274 1376T630 1476Q862 1476 992 1363T1122 1045H937Q937 1170 853 1247T630 1325Q488 1325 408 1268T327 1112Q327 1043 355 1003T450 931T661 858T889 782T1030 +698T1116 585T1145 431ZM602 691Q512 715 437 742Q357 723 320 673T282 553Q282 483 309 443T402 370T611 296T797 238Q875 258 917 308T959 428Q959 516 890 570T602 691Z" /> +<glyph unicode="¨" horiz-adv-x="856" d="M101 1371Q101 1416 128 1446T210 1477T292 1447T320 1371T292 1296T210 1266T129 1296T101 1371ZM531 1369Q531 1414 558 1445T640 1476T722 1445T750 1369T722 1294T640 1264T559 1294T531 1369Z" /> +<glyph unicode="©" horiz-adv-x="1609" d="M1119 597Q1119 444 1033 364T788 283Q631 283 537 388T442 676V786Q442 962 537 1067T788 1173Q948 1173 1034 1091T1120 860H974Q974 959 927 1001T788 1044Q694 1044 640 975T586 783V670Q586 550 640 481T788 +412Q880 412 926 454T973 597H1119ZM206 729Q206 557 286 411T503 181T801 98T1098 181T1315 410T1395 729Q1395 899 1316 1044T1100 1272T801 1356Q641 1356 503 1274T286 1045T206 729ZM91 729Q91 931 184 1104T443 1376T801 1476T1158 1377T1416 1104T1510 729Q1510 +532 1420 360T1165 84T801 -21Q604 -21 439 82T182 358T91 729Z" /> +<glyph unicode="ª" horiz-adv-x="915" d="M618 705Q606 739 600 777Q524 691 396 691Q277 691 212 753T147 918Q147 1029 230 1089T486 1149H594V1201Q594 1336 470 1336Q401 1336 362 1309T322 1231L161 1243Q161 1346 247 1411T470 1476Q603 1476 680 1405T757 +1199V883Q757 786 783 705H618ZM435 828Q478 828 522 848T594 895V1037H482Q399 1036 355 1005T310 922Q310 828 435 828Z" /> +<glyph unicode="«" horiz-adv-x="961" d="M536 804L794 407H653L358 795V814L653 1203H794L536 804ZM610 548L868 151H727L432 539V558L727 947H868L610 548Z" /> +<glyph unicode="¬" horiz-adv-x="1134" d="M958 375H772V639H127V800H958V375Z" /> +<glyph unicode="­" horiz-adv-x="565" d="M525 543H37V694H525V543Z" /> +<glyph unicode="®" horiz-adv-x="1610" d="M90 729Q90 931 183 1104T442 1376T800 1476T1157 1377T1415 1104T1509 729Q1509 532 1419 360T1164 84T800 -21Q603 -21 438 82T181 358T90 729ZM205 729Q205 557 285 411T502 181T800 98Q961 98 1099 182T1315 +412T1394 729Q1394 900 1316 1044T1099 1272T800 1356Q640 1356 502 1274T285 1045T205 729ZM653 654V316H512V1165H788Q941 1165 1025 1100T1110 909Q1110 786 982 721Q1104 671 1105 517V456Q1105 370 1122 332V316H977Q963 352 963 444T960 554Q944 650 829 +654H653ZM653 782H809Q881 784 925 817T969 904Q969 977 930 1007T791 1038H653V782Z" /> +<glyph unicode="¯" horiz-adv-x="938" d="M814 1302H142V1445H814V1302Z" /> +<glyph unicode="°" horiz-adv-x="765" d="M130 1216Q130 1320 204 1398T385 1476Q489 1476 562 1399T636 1216Q636 1110 563 1035T385 960Q280 960 205 1035T130 1216ZM385 1088Q439 1088 476 1123T513 1216Q513 1274 476 1311T385 1349Q330 1349 293 1310T255 +1216T292 1125T385 1088Z" /> +<glyph unicode="±" horiz-adv-x="1094" d="M649 854H1013V703H649V289H482V703H97V854H482V1267H649V854ZM970 0H135V152H970V0Z" /> +<glyph unicode="²" horiz-adv-x="751" d="M683 667H84V775L384 1057Q493 1159 493 1228Q493 1277 461 1307T369 1338Q294 1338 259 1300T223 1205H66Q66 1319 149 1393T365 1467T574 1404T651 1230Q651 1126 544 1019L460 940L284 795H683V667Z" /> +<glyph unicode="³" horiz-adv-x="751" d="M265 1126H349Q423 1126 459 1156T495 1235Q495 1280 464 1309T362 1338Q305 1338 268 1313T230 1246H73Q73 1344 154 1405T360 1467Q497 1467 575 1407T653 1242Q653 1187 618 1142T517 1071Q666 1030 666 887Q666 +781 581 719T360 656Q228 656 145 719T62 889H220Q220 844 259 814T366 784Q436 784 472 814T509 895Q509 1008 353 1010H265V1126Z" /> +<glyph unicode="´" horiz-adv-x="642" d="M316 1536H540L272 1242H123L316 1536Z" /> +<glyph unicode="µ" horiz-adv-x="1160" d="M339 1082V449Q340 286 391 208T559 130Q758 130 820 282V1082H1006V0H839L830 115Q737 -20 567 -20Q420 -20 339 53V-416H154V1082H339Z" /> +<glyph unicode="¶" horiz-adv-x="1001" d="M646 0V520H562Q332 520 200 647T67 988Q67 1201 200 1328T563 1456H832V0H646Z" /> +<glyph unicode="·" horiz-adv-x="534" d="M147 729Q147 777 175 809T261 841T347 809T377 729Q377 682 348 651T261 619T176 650T147 729Z" /> +<glyph unicode="¸" horiz-adv-x="507" d="M285 0L273 -52Q426 -79 426 -225Q426 -322 346 -378T123 -435L116 -328Q195 -328 238 -302T282 -229Q282 -185 250 -164T120 -134L152 0H285Z" /> +<glyph unicode="¹" horiz-adv-x="751" d="M495 667H338V1268L122 1211V1339L477 1456H495V667Z" /> +<glyph unicode="º" horiz-adv-x="931" d="M122 1123Q122 1281 216 1378T464 1476Q619 1476 713 1380T807 1117V1043Q807 884 714 787T466 690T217 787T122 1049V1123ZM285 1043Q285 943 333 886T466 829Q549 829 596 886T644 1045V1123Q644 1222 596 1279T464 +1336Q383 1336 335 1281T285 1129V1043Z" /> +<glyph unicode="»" horiz-adv-x="960" d="M244 949L539 560V541L244 152H102L360 550L102 949H244ZM593 949L888 560V541L593 152H451L709 550L451 949H593Z" /> +<glyph unicode="¼" horiz-adv-x="1500" d="M458 664H301V1265L85 1208V1336L440 1453H458V664ZM443 118L339 184L1050 1322L1154 1256L443 118ZM1318 299H1425V169H1318V0H1161V169H786L780 271L1157 789H1318V299ZM938 299H1161V588L1144 560L938 299Z" /> +<glyph unicode="½" horiz-adv-x="1589" d="M399 118L295 184L1006 1322L1110 1256L399 118ZM453 664H296V1265L80 1208V1336L435 1453H453V664ZM1481 0H882V108L1182 390Q1291 492 1291 561Q1291 610 1259 640T1167 671Q1092 671 1057 633T1021 538H864Q864 +652 947 726T1163 800T1372 737T1449 563Q1449 459 1342 352L1258 273L1082 128H1481V0Z" /> +<glyph unicode="¾" horiz-adv-x="1593" d="M570 118L466 184L1177 1322L1281 1256L570 118ZM1410 299H1517V169H1410V0H1253V169H878L872 271L1249 789H1410V299ZM1030 299H1253V588L1236 560L1030 299ZM314 1126H398Q472 1126 508 1156T544 1235Q544 1280 +513 1309T411 1338Q354 1338 317 1313T279 1246H122Q122 1344 203 1405T409 1467Q546 1467 624 1407T702 1242Q702 1187 667 1142T566 1071Q715 1030 715 887Q715 781 630 719T409 656Q277 656 194 719T111 889H269Q269 844 308 814T415 784Q485 784 521 814T558 +895Q558 1008 402 1010H314V1126Z" /> +<glyph unicode="¿" horiz-adv-x="969" d="M588 680Q587 574 567 511T498 388T358 233T255 37L253 0Q253 -109 311 -166T478 -224Q578 -224 640 -168T703 -20H888Q886 -181 774 -283T478 -385Q282 -385 175 -285T68 -5Q68 168 228 343L337 456Q403 534 403 +680H588ZM596 997Q596 952 569 921T487 890T405 921T377 997Q377 1041 405 1071T487 1101T568 1071T596 997Z" /> +<glyph unicode="À" horiz-adv-x="1336" d="M973 380H363L226 0H28L584 1456H752L1309 0H1112L973 380ZM421 538H916L668 1219L421 538ZM778 1552H619L361 1846H584L778 1552Z" /> +<glyph unicode="Á" horiz-adv-x="1336" d="M973 380H363L226 0H28L584 1456H752L1309 0H1112L973 380ZM421 538H916L668 1219L421 538ZM763 1846H987L719 1552H570L763 1846Z" /> +<glyph unicode="Â" horiz-adv-x="1336" d="M973 380H363L226 0H28L584 1456H752L1309 0H1112L973 380ZM421 538H916L668 1219L421 538ZM975 1572V1562H822L672 1732L523 1562H370V1574L616 1846H728L975 1572Z" /> +<glyph unicode="Ã" horiz-adv-x="1336" d="M973 380H363L226 0H28L584 1456H752L1309 0H1112L973 380ZM421 538H916L668 1219L421 538ZM1027 1814Q1027 1706 966 1639T812 1572Q771 1572 741 1582T663 1623T593 1660T543 1667Q502 1667 473 1636T444 1555L320 +1562Q320 1669 380 1739T534 1809Q569 1809 597 1799T673 1760T746 1722T803 1713Q846 1713 874 1747T903 1826L1027 1814Z" /> +<glyph unicode="Ä" horiz-adv-x="1336" d="M973 380H363L226 0H28L584 1456H752L1309 0H1112L973 380ZM421 538H916L668 1219L421 538ZM350 1681Q350 1726 377 1756T459 1787T541 1757T569 1681T541 1606T459 1576T378 1606T350 1681ZM780 1679Q780 1724 +807 1755T889 1786T971 1755T999 1679T971 1604T889 1574T808 1604T780 1679Z" /> +<glyph unicode="Å" horiz-adv-x="1336" d="M973 380H363L226 0H28L584 1456H752L1309 0H1112L973 380ZM421 538H916L668 1219L421 538ZM887 1729Q887 1642 825 1584T672 1525Q580 1525 519 1584T457 1729T518 1876T672 1937T825 1876T887 1729ZM556 1729Q556 +1682 589 1648T672 1614Q720 1614 754 1647T788 1729T755 1812T672 1847Q622 1847 589 1812T556 1729Z" /> +<glyph unicode="Æ" horiz-adv-x="1914" d="M1879 0H996L981 353H417L212 0H-14L866 1456H1817V1304H1126L1146 833H1736V682H1152L1174 151H1879V0ZM518 527H974L943 1260L518 527Z" /> +<glyph unicode="Ç" horiz-adv-x="1333" d="M1240 462Q1213 231 1070 106T688 -20Q430 -20 275 165T119 660V800Q119 1003 191 1157T397 1393T705 1476Q937 1476 1077 1347T1240 988H1047Q1022 1162 939 1240T705 1318Q521 1318 417 1182T312 795V654Q312 +417 411 277T688 137Q848 137 933 209T1047 462H1240ZM751 -9L739 -61Q892 -88 892 -234Q892 -331 812 -387T589 -444L582 -337Q661 -337 704 -311T748 -238Q748 -194 716 -173T586 -143L618 -9H751Z" /> +<glyph unicode="È" horiz-adv-x="1164" d="M992 673H361V157H1094V0H169V1456H1084V1298H361V830H992V673ZM725 1564H566L308 1858H531L725 1564Z" /> +<glyph unicode="É" horiz-adv-x="1164" d="M992 673H361V157H1094V0H169V1456H1084V1298H361V830H992V673ZM710 1858H934L666 1564H517L710 1858Z" /> +<glyph unicode="Ê" horiz-adv-x="1164" d="M992 673H361V157H1094V0H169V1456H1084V1298H361V830H992V673ZM922 1584V1574H769L619 1744L470 1574H317V1586L563 1858H675L922 1584Z" /> +<glyph unicode="Ë" horiz-adv-x="1164" d="M992 673H361V157H1094V0H169V1456H1084V1298H361V830H992V673ZM297 1693Q297 1738 324 1768T406 1799T488 1769T516 1693T488 1618T406 1588T325 1618T297 1693ZM727 1691Q727 1736 754 1767T836 1798T918 1767T946 +1691T918 1616T836 1586T755 1616T727 1691Z" /> +<glyph unicode="Ì" horiz-adv-x="557" d="M375 0H183V1456H375V0ZM385 1564H226L-32 1858H191L385 1564Z" /> +<glyph unicode="Í" horiz-adv-x="557" d="M375 0H183V1456H375V0ZM369 1858H593L325 1564H176L369 1858Z" /> +<glyph unicode="Î" horiz-adv-x="557" d="M375 0H183V1456H375V0ZM582 1584V1574H429L279 1744L130 1574H-23V1586L223 1858H335L582 1584Z" /> +<glyph unicode="Ï" horiz-adv-x="557" d="M375 0H183V1456H375V0ZM-43 1693Q-43 1738 -16 1768T66 1799T148 1769T176 1693T148 1618T66 1588T-15 1618T-43 1693ZM387 1691Q387 1736 414 1767T496 1798T578 1767T606 1691T578 1616T496 1586T415 1616T387 1691Z" /> +<glyph unicode="Ð" horiz-adv-x="1373" d="M199 0V666H7V817H199V1456H610Q800 1456 946 1372T1171 1133T1252 777V684Q1252 478 1173 323T946 85T602 0H199ZM643 666H391V157H592Q814 157 937 294T1062 680V773Q1062 1021 946 1158T615 1298H391V817H643V666Z" /> +<glyph unicode="Ñ" horiz-adv-x="1460" d="M1288 0H1095L362 1122V0H169V1456H362L1097 329V1456H1288V0ZM1081 1814Q1081 1706 1020 1639T866 1572Q825 1572 795 1582T717 1623T647 1660T597 1667Q556 1667 527 1636T498 1555L374 1562Q374 1669 434 1739T588 +1809Q623 1809 651 1799T727 1760T800 1722T857 1713Q900 1713 928 1747T957 1826L1081 1814Z" /> +<glyph unicode="Ò" horiz-adv-x="1408" d="M1289 681Q1289 467 1217 308T1013 64T705 -20Q533 -20 400 64T194 305T118 668V773Q118 983 191 1144T397 1390T703 1476Q878 1476 1011 1392T1217 1147T1289 773V681ZM1098 775Q1098 1034 994 1172T703 1311Q521 +1311 417 1173T309 788V681Q309 430 414 287T705 143Q891 143 993 278T1098 667V775ZM812 1554H653L395 1848H618L812 1554Z" /> +<glyph unicode="Ó" horiz-adv-x="1408" d="M1289 681Q1289 467 1217 308T1013 64T705 -20Q533 -20 400 64T194 305T118 668V773Q118 983 191 1144T397 1390T703 1476Q878 1476 1011 1392T1217 1147T1289 773V681ZM1098 775Q1098 1034 994 1172T703 1311Q521 +1311 417 1173T309 788V681Q309 430 414 287T705 143Q891 143 993 278T1098 667V775ZM797 1848H1021L753 1554H604L797 1848Z" /> +<glyph unicode="Ô" horiz-adv-x="1408" d="M1289 681Q1289 467 1217 308T1013 64T705 -20Q533 -20 400 64T194 305T118 668V773Q118 983 191 1144T397 1390T703 1476Q878 1476 1011 1392T1217 1147T1289 773V681ZM1098 775Q1098 1034 994 1172T703 1311Q521 +1311 417 1173T309 788V681Q309 430 414 287T705 143Q891 143 993 278T1098 667V775ZM1009 1574V1564H856L706 1734L557 1564H404V1576L650 1848H762L1009 1574Z" /> +<glyph unicode="Õ" horiz-adv-x="1408" d="M1289 681Q1289 467 1217 308T1013 64T705 -20Q533 -20 400 64T194 305T118 668V773Q118 983 191 1144T397 1390T703 1476Q878 1476 1011 1392T1217 1147T1289 773V681ZM1098 775Q1098 1034 994 1172T703 1311Q521 +1311 417 1173T309 788V681Q309 430 414 287T705 143Q891 143 993 278T1098 667V775ZM1061 1816Q1061 1708 1000 1641T846 1574Q805 1574 775 1584T697 1625T627 1662T577 1669Q536 1669 507 1638T478 1557L354 1564Q354 1671 414 1741T568 1811Q603 1811 631 1801T707 +1762T780 1724T837 1715Q880 1715 908 1749T937 1828L1061 1816Z" /> +<glyph unicode="Ö" horiz-adv-x="1408" d="M1289 681Q1289 467 1217 308T1013 64T705 -20Q533 -20 400 64T194 305T118 668V773Q118 983 191 1144T397 1390T703 1476Q878 1476 1011 1392T1217 1147T1289 773V681ZM1098 775Q1098 1034 994 1172T703 1311Q521 +1311 417 1173T309 788V681Q309 430 414 287T705 143Q891 143 993 278T1098 667V775ZM384 1683Q384 1728 411 1758T493 1789T575 1759T603 1683T575 1608T493 1578T412 1608T384 1683ZM814 1681Q814 1726 841 1757T923 1788T1005 1757T1033 1681T1005 1606T923 +1576T842 1606T814 1681Z" /> +<glyph unicode="×" horiz-adv-x="1092" d="M89 329L419 665L91 1000L210 1123L539 788L868 1123L987 1000L659 665L989 329L870 206L539 543L208 206L89 329Z" /> +<glyph unicode="Ø" horiz-adv-x="1408" d="M1289 681Q1289 467 1217 308T1013 64T705 -20Q534 -20 403 62L306 -93H164L308 138Q118 330 118 690V773Q118 983 191 1144T397 1390T703 1476Q917 1476 1065 1351L1168 1516H1309L1150 1261Q1287 1074 1289 780V681ZM309 +681Q309 437 407 296L971 1200Q869 1311 703 1311Q521 1311 417 1173T309 788V681ZM1098 775Q1098 957 1042 1088L493 207Q584 143 705 143Q891 143 993 278T1098 667V775Z" /> +<glyph unicode="Ù" horiz-adv-x="1328" d="M1194 1456V466Q1193 260 1065 129T716 -18L665 -20Q426 -20 284 109T140 464V1456H330V470Q330 312 417 225T665 137Q828 137 914 224T1001 469V1456H1194ZM773 1552H614L356 1846H579L773 1552Z" /> +<glyph unicode="Ú" horiz-adv-x="1328" d="M1194 1456V466Q1193 260 1065 129T716 -18L665 -20Q426 -20 284 109T140 464V1456H330V470Q330 312 417 225T665 137Q828 137 914 224T1001 469V1456H1194ZM758 1846H982L714 1552H565L758 1846Z" /> +<glyph unicode="Û" horiz-adv-x="1328" d="M1194 1456V466Q1193 260 1065 129T716 -18L665 -20Q426 -20 284 109T140 464V1456H330V470Q330 312 417 225T665 137Q828 137 914 224T1001 469V1456H1194ZM970 1572V1562H817L667 1732L518 1562H365V1574L611 +1846H723L970 1572Z" /> +<glyph unicode="Ü" horiz-adv-x="1328" d="M1194 1456V466Q1193 260 1065 129T716 -18L665 -20Q426 -20 284 109T140 464V1456H330V470Q330 312 417 225T665 137Q828 137 914 224T1001 469V1456H1194ZM345 1681Q345 1726 372 1756T454 1787T536 1757T564 +1681T536 1606T454 1576T373 1606T345 1681ZM775 1679Q775 1724 802 1755T884 1786T966 1755T994 1679T966 1604T884 1574T803 1604T775 1679Z" /> +<glyph unicode="Ý" horiz-adv-x="1230" d="M613 725L993 1456H1211L709 543V0H517V543L15 1456H235L613 725ZM708 1846H932L664 1552H515L708 1846Z" /> +<glyph unicode="Þ" horiz-adv-x="1210" d="M352 1456V1163H631Q778 1163 888 1111T1057 961T1117 738Q1117 544 985 429T626 313H352V0H166V1456H352ZM352 1011V465H629Q771 465 851 540T931 736Q931 859 851 934T635 1011H352Z" /> +<glyph unicode="ß" horiz-adv-x="1218" d="M324 0H139V1111Q139 1319 242 1436T532 1554Q712 1554 810 1465T909 1216Q909 1091 845 990T781 819Q781 768 818 721T950 601T1087 461T1130 317Q1130 158 1029 69T745 -20Q664 -20 574 2T445 52L488 207Q537 +175 604 153T725 131Q832 131 888 178T945 307Q945 359 908 407T777 528T639 671T595 821Q595 910 664 1013T734 1201Q734 1295 682 1348T542 1402Q324 1402 324 1109V0Z" /> +<glyph unicode="à" horiz-adv-x="1114" d="M808 0Q792 32 782 114Q653 -20 474 -20Q314 -20 212 70T109 300Q109 469 237 562T599 656H779V741Q779 838 721 895T550 953Q451 953 384 903T317 782H131Q131 863 188 938T344 1058T561 1102Q748 1102 854 1009T964 +751V253Q964 104 1002 16V0H808ZM501 141Q588 141 666 186T779 303V525H634Q294 525 294 326Q294 239 352 190T501 141ZM687 1242H528L270 1536H493L687 1242Z" /> +<glyph unicode="á" horiz-adv-x="1114" d="M808 0Q792 32 782 114Q653 -20 474 -20Q314 -20 212 70T109 300Q109 469 237 562T599 656H779V741Q779 838 721 895T550 953Q451 953 384 903T317 782H131Q131 863 188 938T344 1058T561 1102Q748 1102 854 1009T964 +751V253Q964 104 1002 16V0H808ZM501 141Q588 141 666 186T779 303V525H634Q294 525 294 326Q294 239 352 190T501 141ZM672 1536H896L628 1242H479L672 1536Z" /> +<glyph unicode="â" horiz-adv-x="1114" d="M808 0Q792 32 782 114Q653 -20 474 -20Q314 -20 212 70T109 300Q109 469 237 562T599 656H779V741Q779 838 721 895T550 953Q451 953 384 903T317 782H131Q131 863 188 938T344 1058T561 1102Q748 1102 854 1009T964 +751V253Q964 104 1002 16V0H808ZM501 141Q588 141 666 186T779 303V525H634Q294 525 294 326Q294 239 352 190T501 141ZM884 1262V1252H731L581 1422L432 1252H279V1264L525 1536H637L884 1262Z" /> +<glyph unicode="ã" horiz-adv-x="1114" d="M808 0Q792 32 782 114Q653 -20 474 -20Q314 -20 212 70T109 300Q109 469 237 562T599 656H779V741Q779 838 721 895T550 953Q451 953 384 903T317 782H131Q131 863 188 938T344 1058T561 1102Q748 1102 854 1009T964 +751V253Q964 104 1002 16V0H808ZM501 141Q588 141 666 186T779 303V525H634Q294 525 294 326Q294 239 352 190T501 141ZM936 1504Q936 1396 875 1329T721 1262Q680 1262 650 1272T572 1313T502 1350T452 1357Q411 1357 382 1326T353 1245L229 1252Q229 1359 289 +1429T443 1499Q478 1499 506 1489T582 1450T655 1412T712 1403Q755 1403 783 1437T812 1516L936 1504Z" /> +<glyph unicode="ä" horiz-adv-x="1114" d="M808 0Q792 32 782 114Q653 -20 474 -20Q314 -20 212 70T109 300Q109 469 237 562T599 656H779V741Q779 838 721 895T550 953Q451 953 384 903T317 782H131Q131 863 188 938T344 1058T561 1102Q748 1102 854 1009T964 +751V253Q964 104 1002 16V0H808ZM501 141Q588 141 666 186T779 303V525H634Q294 525 294 326Q294 239 352 190T501 141ZM259 1371Q259 1416 286 1446T368 1477T450 1447T478 1371T450 1296T368 1266T287 1296T259 1371ZM689 1369Q689 1414 716 1445T798 1476T880 +1445T908 1369T880 1294T798 1264T717 1294T689 1369Z" /> +<glyph unicode="å" horiz-adv-x="1114" d="M808 0Q792 32 782 114Q653 -20 474 -20Q314 -20 212 70T109 300Q109 469 237 562T599 656H779V741Q779 838 721 895T550 953Q451 953 384 903T317 782H131Q131 863 188 938T344 1058T561 1102Q748 1102 854 1009T964 +751V253Q964 104 1002 16V0H808ZM501 141Q588 141 666 186T779 303V525H634Q294 525 294 326Q294 239 352 190T501 141ZM796 1419Q796 1332 734 1274T581 1215Q489 1215 428 1274T366 1419T427 1566T581 1627T734 1566T796 1419ZM465 1419Q465 1372 498 1338T581 +1304Q629 1304 663 1337T697 1419T664 1502T581 1537Q531 1537 498 1502T465 1419Z" /> +<glyph unicode="æ" horiz-adv-x="1729" d="M1262 -20Q1001 -20 865 160Q800 74 687 27T433 -20Q266 -20 172 66T78 304Q78 461 191 548T526 635H749V720Q749 827 694 888T535 950Q430 950 360 895T290 759L106 778Q106 921 227 1011T535 1102Q650 1102 738 +1061T876 936Q939 1015 1026 1058T1218 1102Q1428 1102 1544 974T1660 612V497H932Q939 321 1026 226T1262 130Q1410 130 1531 206L1578 237L1642 101Q1484 -20 1262 -20ZM469 130Q541 130 620 167T749 258V495H521Q404 493 334 438T264 300Q264 223 317 177T469 +130ZM1218 950Q1103 950 1029 865T937 640H1475V671Q1475 803 1408 876T1218 950Z" /> +<glyph unicode="ç" horiz-adv-x="1072" d="M574 131Q673 131 747 191T829 341H1004Q999 248 940 164T783 30T574 -20Q353 -20 223 127T92 531V562Q92 720 150 843T316 1034T573 1102Q755 1102 875 993T1004 710H829Q821 815 750 882T573 950Q432 950 355 +849T277 555V520Q277 333 354 232T574 131ZM604 -9L592 -61Q745 -88 745 -234Q745 -331 665 -387T442 -444L435 -337Q514 -337 557 -311T601 -238Q601 -194 569 -173T439 -143L471 -9H604Z" /> +<glyph unicode="è" horiz-adv-x="1085" d="M589 -20Q369 -20 231 124T93 511V545Q93 706 154 832T326 1030T566 1102Q777 1102 894 963T1011 565V488H278Q282 328 371 230T599 131Q697 131 765 171T884 277L997 189Q861 -20 589 -20ZM566 950Q454 950 378 +869T284 640H826V654Q818 795 750 872T566 950ZM671 1242H512L254 1536H477L671 1242Z" /> +<glyph unicode="é" horiz-adv-x="1085" d="M589 -20Q369 -20 231 124T93 511V545Q93 706 154 832T326 1030T566 1102Q777 1102 894 963T1011 565V488H278Q282 328 371 230T599 131Q697 131 765 171T884 277L997 189Q861 -20 589 -20ZM566 950Q454 950 378 +869T284 640H826V654Q818 795 750 872T566 950ZM656 1536H880L612 1242H463L656 1536Z" /> +<glyph unicode="ê" horiz-adv-x="1085" d="M589 -20Q369 -20 231 124T93 511V545Q93 706 154 832T326 1030T566 1102Q777 1102 894 963T1011 565V488H278Q282 328 371 230T599 131Q697 131 765 171T884 277L997 189Q861 -20 589 -20ZM566 950Q454 950 378 +869T284 640H826V654Q818 795 750 872T566 950ZM868 1262V1252H715L565 1422L416 1252H263V1264L509 1536H621L868 1262Z" /> +<glyph unicode="ë" horiz-adv-x="1085" d="M589 -20Q369 -20 231 124T93 511V545Q93 706 154 832T326 1030T566 1102Q777 1102 894 963T1011 565V488H278Q282 328 371 230T599 131Q697 131 765 171T884 277L997 189Q861 -20 589 -20ZM566 950Q454 950 378 +869T284 640H826V654Q818 795 750 872T566 950ZM243 1371Q243 1416 270 1446T352 1477T434 1447T462 1371T434 1296T352 1266T271 1296T243 1371ZM673 1369Q673 1414 700 1445T782 1476T864 1445T892 1369T864 1294T782 1264T701 1294T673 1369Z" /> +<glyph unicode="ì" horiz-adv-x="506" d="M341 0H155V1082H341V0ZM615 1497H456L198 1791H421L615 1497Z" /> +<glyph unicode="í" horiz-adv-x="506" d="M341 0H155V1082H341V0ZM343 1791H567L299 1497H150L343 1791Z" /> +<glyph unicode="î" horiz-adv-x="506" d="M341 0H155V1082H341V0ZM556 1261V1251H403L253 1421L104 1251H-49V1263L197 1535H309L556 1261Z" /> +<glyph unicode="ï" horiz-adv-x="506" d="M341 0H155V1082H341V0ZM-69 1370Q-69 1415 -42 1445T40 1476T122 1446T150 1370T122 1295T40 1265T-41 1295T-69 1370ZM361 1368Q361 1413 388 1444T470 1475T552 1444T580 1368T552 1293T470 1263T389 1293T361 1368Z" /> +<glyph unicode="ð" horiz-adv-x="1200" d="M820 1301Q1069 1037 1069 628V535Q1069 377 1011 251T844 52T602 -20Q467 -20 357 44T187 221T126 467Q126 614 182 730T341 912T574 977Q737 977 858 863Q810 1058 669 1199L451 1051L378 1150L570 1281Q438 1372 +255 1421L312 1580Q551 1526 726 1387L915 1516L988 1416L820 1301ZM884 635L882 691Q849 752 780 788T618 825Q473 825 392 730T311 467Q311 327 394 229T606 131Q731 131 807 244T884 541V635Z" /> +<glyph unicode="ñ" horiz-adv-x="1130" d="M315 1082L321 946Q445 1102 645 1102Q988 1102 991 715V0H806V716Q805 833 753 889T589 945Q499 945 431 897T325 771V0H140V1082H315ZM927 1504Q927 1396 866 1329T712 1262Q671 1262 641 1272T563 1313T493 1350T443 +1357Q402 1357 373 1326T344 1245L220 1252Q220 1359 280 1429T434 1499Q469 1499 497 1489T573 1450T646 1412T703 1403Q746 1403 774 1437T803 1516L927 1504Z" /> +<glyph unicode="ò" horiz-adv-x="1168" d="M91 551Q91 710 153 837T327 1033T582 1102Q803 1102 939 949T1076 542V529Q1076 371 1016 246T843 50T584 -20Q364 -20 228 133T91 538V551ZM277 529Q277 349 360 240T584 131Q725 131 808 241T891 551Q891 729 +807 839T582 950Q445 950 361 841T277 529ZM681 1242H522L264 1536H487L681 1242Z" /> +<glyph unicode="ó" horiz-adv-x="1168" d="M91 551Q91 710 153 837T327 1033T582 1102Q803 1102 939 949T1076 542V529Q1076 371 1016 246T843 50T584 -20Q364 -20 228 133T91 538V551ZM277 529Q277 349 360 240T584 131Q725 131 808 241T891 551Q891 729 +807 839T582 950Q445 950 361 841T277 529ZM666 1536H890L622 1242H473L666 1536Z" /> +<glyph unicode="ô" horiz-adv-x="1168" d="M91 551Q91 710 153 837T327 1033T582 1102Q803 1102 939 949T1076 542V529Q1076 371 1016 246T843 50T584 -20Q364 -20 228 133T91 538V551ZM277 529Q277 349 360 240T584 131Q725 131 808 241T891 551Q891 729 +807 839T582 950Q445 950 361 841T277 529ZM878 1262V1252H725L575 1422L426 1252H273V1264L519 1536H631L878 1262Z" /> +<glyph unicode="õ" horiz-adv-x="1168" d="M91 551Q91 710 153 837T327 1033T582 1102Q803 1102 939 949T1076 542V529Q1076 371 1016 246T843 50T584 -20Q364 -20 228 133T91 538V551ZM277 529Q277 349 360 240T584 131Q725 131 808 241T891 551Q891 729 +807 839T582 950Q445 950 361 841T277 529ZM930 1504Q930 1396 869 1329T715 1262Q674 1262 644 1272T566 1313T496 1350T446 1357Q405 1357 376 1326T347 1245L223 1252Q223 1359 283 1429T437 1499Q472 1499 500 1489T576 1450T649 1412T706 1403Q749 1403 777 +1437T806 1516L930 1504Z" /> +<glyph unicode="ö" horiz-adv-x="1168" d="M91 551Q91 710 153 837T327 1033T582 1102Q803 1102 939 949T1076 542V529Q1076 371 1016 246T843 50T584 -20Q364 -20 228 133T91 538V551ZM277 529Q277 349 360 240T584 131Q725 131 808 241T891 551Q891 729 +807 839T582 950Q445 950 361 841T277 529ZM253 1371Q253 1416 280 1446T362 1477T444 1447T472 1371T444 1296T362 1266T281 1296T253 1371ZM683 1369Q683 1414 710 1445T792 1476T874 1445T902 1369T874 1294T792 1264T711 1294T683 1369Z" /> +<glyph unicode="÷" horiz-adv-x="1169" d="M1069 600H71V784H1069V600ZM461 1098Q461 1146 489 1178T575 1210T661 1178T691 1098Q691 1051 662 1020T575 989T490 1020T461 1098ZM461 281Q461 329 489 361T575 393T661 361T691 281Q691 235 662 204T575 172T490 +203T461 281Z" /> +<glyph unicode="ø" horiz-adv-x="1160" d="M91 551Q91 710 152 836T326 1032T582 1102Q692 1102 786 1060L859 1208H983L881 1003Q1076 849 1076 529Q1076 371 1014 244T840 49T584 -20Q480 -20 394 15L320 -134H196L296 69Q91 218 91 551ZM276 529Q276 335 +373 224L716 918Q654 950 582 950Q444 950 360 841T276 529ZM890 551Q890 733 803 844L463 156Q518 131 584 131Q723 131 806 240T890 535V551Z" /> +<glyph unicode="ù" horiz-adv-x="1129" d="M808 107Q700 -20 491 -20Q318 -20 228 80T136 378V1082H321V383Q321 137 521 137Q733 137 803 295V1082H988V0H812L808 107ZM673 1242H514L256 1536H479L673 1242Z" /> +<glyph unicode="ú" horiz-adv-x="1129" d="M808 107Q700 -20 491 -20Q318 -20 228 80T136 378V1082H321V383Q321 137 521 137Q733 137 803 295V1082H988V0H812L808 107ZM658 1536H882L614 1242H465L658 1536Z" /> +<glyph unicode="û" horiz-adv-x="1129" d="M808 107Q700 -20 491 -20Q318 -20 228 80T136 378V1082H321V383Q321 137 521 137Q733 137 803 295V1082H988V0H812L808 107ZM870 1262V1252H717L567 1422L418 1252H265V1264L511 1536H623L870 1262Z" /> +<glyph unicode="ü" horiz-adv-x="1129" d="M808 107Q700 -20 491 -20Q318 -20 228 80T136 378V1082H321V383Q321 137 521 137Q733 137 803 295V1082H988V0H812L808 107ZM245 1371Q245 1416 272 1446T354 1477T436 1447T464 1371T436 1296T354 1266T273 1296T245 +1371ZM675 1369Q675 1414 702 1445T784 1476T866 1445T894 1369T866 1294T784 1264T703 1294T675 1369Z" /> +<glyph unicode="ý" horiz-adv-x="969" d="M494 271L746 1082H944L509 -167Q408 -437 188 -437L153 -434L84 -421V-271L134 -275Q228 -275 280 -237T367 -98L408 12L22 1082H224L494 271ZM599 1536H823L555 1242H406L599 1536Z" /> +<glyph unicode="þ" horiz-adv-x="1180" d="M1063 529Q1063 282 950 131T644 -20Q447 -20 334 105V-416H149V1536H334V970Q447 1102 641 1102Q836 1102 949 955T1063 546V529ZM878 550Q878 733 800 839T586 945Q418 945 334 796V279Q417 131 588 131Q721 131 +799 236T878 550Z" /> +<glyph unicode="ÿ" horiz-adv-x="969" d="M494 271L746 1082H944L509 -167Q408 -437 188 -437L153 -434L84 -421V-271L134 -275Q228 -275 280 -237T367 -98L408 12L22 1082H224L494 271ZM186 1371Q186 1416 213 1446T295 1477T377 1447T405 1371T377 1296T295 +1266T214 1296T186 1371ZM616 1369Q616 1414 643 1445T725 1476T807 1445T835 1369T807 1294T725 1264T644 1294T616 1369Z" /> +<glyph unicode="–" horiz-adv-x="1344" d="M1421 651H419V802H1421V651Z" /> +<glyph unicode="—" horiz-adv-x="1599" d="M1737 651H401V802H1737V651Z" /> +<glyph unicode="‘" horiz-adv-x="409" d="M270 1555L376 1483Q283 1356 280 1209V1073H96V1189Q96 1291 144 1391T270 1555Z" /> +<glyph unicode="’" horiz-adv-x="409" d="M153 1046L48 1118Q141 1248 144 1392V1536H327V1406Q326 1306 278 1207T153 1046Z" /> +<glyph unicode="‚" horiz-adv-x="407" d="M141 -283L36 -210Q127 -83 130 63V181H315V81Q315 -20 266 -121T141 -283Z" /> +<glyph unicode="“" horiz-adv-x="724" d="M278 1555L384 1483Q291 1356 288 1209V1073H104V1189Q104 1291 152 1391T278 1555ZM593 1555L699 1483Q606 1356 603 1209V1073H419V1189Q419 1291 467 1391T593 1555Z" /> +<glyph unicode="”" horiz-adv-x="731" d="M165 1046L60 1118Q153 1248 156 1392V1536H339V1406Q338 1306 290 1207T165 1046ZM472 1046L367 1118Q460 1248 463 1392V1536H646V1406Q645 1306 597 1207T472 1046Z" /> +<glyph unicode="„" horiz-adv-x="705" d="M141 -301L36 -229Q127 -92 130 61V246H315V82Q315 -26 266 -131T141 -301ZM437 -301L332 -229Q423 -92 426 61V246H612V82Q612 -25 564 -129T437 -301Z" /> +<glyph unicode="•" horiz-adv-x="690" d="M138 772Q138 859 193 915T341 971Q432 971 489 917T546 769V732Q546 645 491 590T342 535Q249 535 194 590T138 734V772Z" /> +<glyph unicode="‹" horiz-adv-x="614" d="M286 550L544 153H403L108 541V560L403 949H544L286 550Z" /> +<glyph unicode="›" horiz-adv-x="614" d="M231 949L526 560V541L231 152H89L347 550L89 949H231Z" /> +</font> +</defs> +</svg> diff --git a/website/agenda/planung/fonts/roboto-v18-latin_latin-ext-regular.ttf b/website/agenda/planung/fonts/roboto-v18-latin_latin-ext-regular.ttf new file mode 100644 index 0000000..5c3b764 Binary files /dev/null and b/website/agenda/planung/fonts/roboto-v18-latin_latin-ext-regular.ttf differ diff --git a/website/agenda/planung/fonts/roboto-v18-latin_latin-ext-regular.woff b/website/agenda/planung/fonts/roboto-v18-latin_latin-ext-regular.woff new file mode 100644 index 0000000..0f128f1 Binary files /dev/null and b/website/agenda/planung/fonts/roboto-v18-latin_latin-ext-regular.woff differ diff --git a/website/agenda/planung/fonts/roboto-v18-latin_latin-ext-regular.woff2 b/website/agenda/planung/fonts/roboto-v18-latin_latin-ext-regular.woff2 new file mode 100644 index 0000000..ab076be Binary files /dev/null and b/website/agenda/planung/fonts/roboto-v18-latin_latin-ext-regular.woff2 differ diff --git a/website/agenda/planung/help.cgi b/website/agenda/planung/help.cgi index 261efbe..0089709 100755 --- a/website/agenda/planung/help.cgi +++ b/website/agenda/planung/help.cgi @@ -1,21 +1,23 @@ # !/usr/bin/perl -w -use warnings "all"; use strict; -use Data::Dumper; +use warnings; +no warnings 'redefine'; -use params; -use config; -use log; -use template; -use auth; -use uac; -use roles; -use studios; -use markup; -use URI::Escape; -use Encode; -use localization; +use Data::Dumper; +use URI::Escape(); + +use params(); +use config(); +use entry(); +use log(); +use template(); +use auth(); +use uac(); +use roles(); +use studios(); +use markup(); +use localization(); #binmode STDOUT, ":utf8"; @@ -24,39 +26,36 @@ my $r = shift; my $config = config::get('../config/config.cgi'); my $debug = $config->{system}->{debug}; -my ( $user, $expires ) = auth::get_user( $cgi, $config ); +my ( $user, $expires ) = auth::get_user( $config, $params, $cgi ); return if ( ( !defined $user ) || ( $user eq '' ) ); my $user_presets = uac::get_user_presets( - $config, - { - user => $user, - project_id => $params->{project_id}, - studio_id => $params->{studio_id} - } + $config, + { + user => $user, + project_id => $params->{project_id}, + studio_id => $params->{studio_id} + } ); $params->{default_studio_id} = $user_presets->{studio_id}; -$params->{studio_id} = $params->{default_studio_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); -$params->{project_id} = $user_presets->{project_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); +$params = uac::setDefaultStudio( $params, $user_presets ); +$params = uac::setDefaultProject( $params, $user_presets ); my $request = { - url => $ENV{QUERY_STRING} || '', - params => { - original => $params, - checked => check_params($params), - }, + url => $ENV{QUERY_STRING} || '', + params => { + original => $params, + checked => check_params( $config, $params ), + }, }; $request = uac::prepare_request( $request, $user_presets ); -log::init($request); $params = $request->{params}->{checked}; #process header my $headerParams = uac::set_template_permissions( $request->{permissions}, $params ); $headerParams->{loc} = localization::get( $config, { user => $user, file => 'menu' } ); -template::process( 'print', template::check('default.html'), $headerParams ); +template::process( $config, 'print', template::check( $config, 'default.html' ), $headerParams ); return unless uac::check( $config, $params, $user_presets ) == 1; my $toc = $headerParams->{loc}->{toc}; @@ -129,13 +128,13 @@ $( document ).ready(function() { print markup::creole_to_html( getHelp( $headerParams->{loc}->{region} ) ); sub getHelp { - my $region = shift; - return getGermanHelp() if $region eq 'de'; - return getEnglishHelp(); + my $region = shift; + return getGermanHelp() if $region eq 'de'; + return getEnglishHelp(); } sub getGermanHelp { - return q{ + return q{ <div id="toc"><h1 class="hide">Inhaltsverzeichnis</h1></div> @@ -379,7 +378,7 @@ Folgende Status-Felder gibt es: } sub getEnglishHelp { - return q{ + return q{ <div id="toc"><h1 class="hide">Table of Contents</h1></div> = Menu @@ -617,29 +616,21 @@ There are following status fields: } sub check_params { - my $params = shift; + my $config = shift; + my $params = shift; - my $checked = {}; + my $checked = {}; - my $debug = $params->{debug} || ''; - if ( $debug =~ /([a-z\_\,]+)/ ) { - $debug = $1; - } - $checked->{debug} = $debug; + $checked->{exclude} = 0; + entry::set_numbers( $checked, $params, [ + 'id', 'project_id', 'studio_id', 'default_studio_id' ]); + + if ( defined $checked->{studio_id} ) { + $checked->{default_studio_id} = $checked->{studio_id}; + } else { + $checked->{studio_id} = -1; + } - #numeric values - $checked->{exclude} = 0; - for my $param ( 'id', 'project_id', 'studio_id', 'default_studio_id' ) { - if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /^\d+$/ ) ) { - $checked->{$param} = $params->{$param}; - } - } - if ( defined $checked->{studio_id} ) { - $checked->{default_studio_id} = $checked->{studio_id}; - } else { - $checked->{studio_id} = -1; - } - - return $checked; + return $checked; } diff --git a/website/agenda/planung/image-upload.cgi b/website/agenda/planung/image-upload.cgi new file mode 100755 index 0000000..b1ed0c1 --- /dev/null +++ b/website/agenda/planung/image-upload.cgi @@ -0,0 +1,387 @@ +#!/usr/bin/perl + +use strict; +use warnings; +no warnings 'redefine'; +use utf8; +use Data::Dumper; + +use Apache2::Request; +use Apache2::Upload; + +delete $INC{CGI}; +require 'CGI.pm'; + +use Date::Calc(); +use Time::Local(); +use Image::Magick(); +use Image::Magick::Square; + +use config(); +use entry(); +use auth(); +use uac(); +use studios(); +use template(); +use images(); +use localization(); + +#binmode STDOUT, ":utf8"; #<! does not work here! +print "Content-type:text/html; charset=UTF-8;\n\n"; + +my $r = shift; +my $cgi = undef; + +my $config = config::get('../config/config.cgi'); +our $debug = $config->{system}->{debug}; +my $base_dir = $config->{locations}->{base_dir}; +my $tmp_dir = '/var/tmp'; +my $upload_limit = 2048 * 1000; + +sub upload_file { + my $config = shift; + my $cgi = shift; + my $upload = shift; + my $user = shift; + + my $result = get_filename( $cgi, $upload ); + return $result if ( $result->{error} ne '' ); + + my $file = $result->{fh}; + my $filename = $result->{filename}; + + $result = check_filename($filename); + + #print STDERR $result . "\n"; + return $result if ( $result->{error} ne '' ); + + my $extension = $result->{extension} || ''; + + #read file from handle + my $data; + my $content = ''; + + #print STDERR $file . "\n"; + + binmode $file; + while ( read $file, $data, 1024 ) { + $content .= $data; + } + + #set filename to MD5 from content + my $md5_filename = Digest::MD5::md5_base64($content); + $md5_filename =~ s/[\/\+]/_/gi; + + return process_image( $config, $filename, $extension, $md5_filename, $content ); +} + +sub update_database { + my $config = shift; + my $params = shift; + my $file_info = shift; + my $user = shift; + + $params->{upload_path} = $file_info->{upload_path}; + $params->{upload_filename} = $file_info->{upload_filename}; + $params->{filename} = $file_info->{filename}; + $params->{thumb_path} = $file_info->{thumb_path}; + $params->{image_path} = $file_info->{image_path}; + $params->{icon_path} = $file_info->{icon_path}; + $params->{local_media_url} = $config->{locations}->{local_media_url}; + + my $name = $params->{name} || ''; + $name = 'neu' unless $params =~ /\S/; + + my $image = { + filename => $params->{filename}, + name => $name, + description => $params->{description}, + modified_by => $user, + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + licence => $params->{licence} + }; + + #connect + $config->{access}->{write} = 1; + my $dbh = db::connect($config); + + my $entries = images::get( + $config, + { + filename => $image->{filename}, + project_id => $image->{project_id}, + studio_id => $image->{studio_id} + } + ); + if ( ( defined $entries ) && ( scalar(@$entries) > 0 ) ) { + print STDERR "update image\n".Dumper($image); + images::update( $dbh, $image ); + my $entry = $entries->[0]; + $params->{image_id} = $entry->{id}; + } else { + print STDERR "insert image\n"; + $image->{created_by} = $user; + $params->{image_id} = images::insert( $dbh, $image ); + } + $config->{access}->{write} = 0; + $params->{action_result} = 'done!'; + + return $params; +} + +#get filename and filehandle from upload +sub get_filename { + my $cgi = shift; + my $upload = shift; + + # try apache2 module + if ( defined $upload ) { + my $filename = $upload->filename(); + return { + filename => $filename, + fh => $upload->fh(), + error => '' + }; + } + + # fallback to CGI module + my $file = $cgi->param("image"); + if ( $file =~ /\|/ ) { + return { error => "is no file" }; + } + + my $file_info = $cgi->uploadInfo($file); + if ( defined $file_info ) { + my $filename = $file_info->{'Content-Disposition'} || ''; + if ( $filename =~ /filename=\"(.*?)\"/ ) { + $filename = $1; + return { + filename => $filename, + fh => $file, + error => '' + }; + + } + } + + #error + return { error => 'Could not detect file name!' }; +} + +sub check_filename { + my $filename = shift; + + my @valid_extensions = ( 'png', 'jpeg', 'jpg', 'gif', 'pdf', 'txt', 'bmp', 'ps', 'eps', 'wmf', 'svg' ); + if ( $filename =~ /\.([a-zA-Z]{3,5})$/ ) { + my $extension = lc $1; + unless ( grep( /$extension/, @valid_extensions ) ) { + return { error => 'Following file formats are supported: ' . join( ",", @valid_extensions ) . '!' }; + } + return { + extension => $extension, + error => '' + }; + } else { + return { error => 'Not matching file extension found! Supported are: ' . join( ",", @valid_extensions ) . '!' }; + } +} + +sub process_image { + my $config = shift; + my $filename = shift; + my $extension = shift; + my $md5_filename = shift; + my $content = shift; + + my $upload_path = + images::getInternalPath( $config, { type => 'upload', filename => $md5_filename . '.' . $extension } ); + my $thumb_path = images::getInternalPath( $config, { type => 'thumbs', filename => $md5_filename . '.jpg' } ); + my $icon_path = images::getInternalPath( $config, { type => 'icons', filename => $md5_filename . '.jpg' } ); + my $image_path = images::getInternalPath( $config, { type => 'images', filename => $md5_filename . '.jpg' } ); + + #copy file to upload space + my $result = images::writeFile( $upload_path, $content ); + return $result if defined $result->{error}; + + #write image + my $image = new Image::Magick; + $image->Read($upload_path); + my $x = $image->Get('width') || 0; + my $y = $image->Get('height') || 0; + if ( ( $x == 0 ) || ( $y == 0 ) ) { + return { error => 'Could not read image!' }; + log::error( $config, 'Cannot read image $filename!' ); + } + + #set max size image + if ( $x > 0 && $y > 0 ) { + if ( $x > $y ) { + $image->Resize( width => '600', height => int( 600 * $y / $x ) ); + } else { + $image->Resize( width => int( 600 * $x / $y ), height => '600' ); + } + } + + #$image->Normalize(); + $image->Write( 'jpg:' . $image_path ); + + #write thumb + my $thumb = $image; + $thumb->Trim2Square; + $thumb->Resize( width => 150, height => 150 ); + $thumb->Write( 'jpg:' . $thumb_path ); + + my $icon = $image; + $icon->Trim2Square; + $icon->Resize( width => 25, height => 25 ); + $icon->Write( 'jpg:' . $icon_path ); + + return { error => 'could not create thumb file!' } unless -e $thumb_path; + return { error => 'could not create icon file!' } unless -e $icon_path; + return { error => 'could not create image file!' } unless -e $image_path; + + return { + upload_filename => $filename, + filename => $md5_filename . '.jpg', + thumb_path => $thumb_path, + icon_path => $icon_path, + image_path => $image_path, + error => '' + }; +} + +sub check_params { + my $config = shift; + my $params = shift; + + my $checked = {}; + $checked->{template} = template::check( $config, $params->{template}, 'image-upload' ); + + entry::set_numbers( $checked, $params, [ + 'project_id', 'studio_id', 'default_studio_id' + ]); + + if ( defined $checked->{studio_id} ) { + $checked->{default_studio_id} = $checked->{studio_id}; + } else { + $checked->{studio_id} = -1; + } + + entry::set_strings( $checked, $params, [ 'action', 'name', 'description', 'licence' ]); + + entry::set_bools( $checked, $params, [ 'public' ] ); + return $checked; +} + + +my $params = {}; +my $upload = undef; +my $error = ''; + +#get image from multiform before anything else +if ( defined $r ) { + + #$cgi = new CGI(); + + #Apache2::Request + my $apr = Apache2::Request->new( $r, POST_MAX => $upload_limit, TEMP_DIR => $tmp_dir ); + + $params = { + studio_id => $apr->param('studio_id'), + project_id => $apr->param('project_id'), + }; + + #copy params to hash + my $body = $apr->body(); + if ( defined $body ) { + for my $key ( keys %$body ) { + $params->{ scalar($key) } = scalar( $apr->param($key) ); + } + } + + my $status = $apr->parse; + $status = '' if ( $status =~ /missing input data/i ); + if ( $status =~ /limit/i ) { + $error = $status; + } else { + $upload = $apr->upload('image') if defined $params->{image}; + } + print STDERR "apr\n"; +} else { + + #CGI fallback + $CGI::POST_MAX = $upload_limit; + $CGI::TMPDIRECTORY = $tmp_dir; + $cgi = new CGI(); + $error = $cgi->cgi_error() || $error; + my %params = $cgi->Vars(); + $params = \%params; + print STDERR "fallback\n"; +} +print STDERR Dumper($params); + +my ( $user, $expires ) = auth::get_user( $config, $params, $cgi ); +return if ( ( !defined $user ) || ( $user eq '' ) ); + +my $user_presets = uac::get_user_presets( + $config, + { + user => $user, + project_id => $params->{project_id}, + studio_id => $params->{studio_id} + } +); +$params->{default_studio_id} = $user_presets->{studio_id}; +$params = uac::setDefaultStudio( $params, $user_presets ); +$params = uac::setDefaultProject( $params, $user_presets ); + +my $request = { + url => $ENV{QUERY_STRING} || '', + params => { + original => $params, + checked => check_params( $config, $params ), + }, +}; + +$request = uac::prepare_request( $request, $user_presets ); +$params = $request->{params}->{checked}; +return unless uac::check( $config, $params, $user_presets ) == 1; + +my $permissions = $request->{permissions}; + +$params->{action} = '' unless defined $params->{action}; + +if ( $permissions->{create_image} ne '1' ) { + uac::permissions_denied("create image"); + return 0; +} + +my $file_info = undef; +if ( $error ne '' ) { + if ( $error =~ /limit/ ) { + $params->{error} .= + "Image size is limited to " + . int( $upload_limit / 1000000 ) . " MB!" + . "Please make it smaller and try again!"; + } else { + $params->{error} .= "Error:'$error'"; + } +} elsif ( $params->{action} eq 'upload' ) { + $file_info = upload_file( $config, $cgi, $upload, $user ); + $params->{error} .= $file_info->{error}; + $params = update_database( $config, $params, $file_info, $user ) if $params->{error} eq ''; +} + +print STDERR "upload error: $params->{error}\n" if $params->{error}; +$params->{loc} = localization::get( $config, { user => $params->{presets}->{user}, file => 'image' } ); +template::process( $config, 'print', $params->{template}, $params ); + +print $cgi->cgi_error() if ( defined $cgi ) && ( defined $cgi->cgi_error() ); +return if $params->{action} eq ''; + +$params->{action_result} ||= ''; +$params->{filename} ||= ''; +$params->{image_id} ||= ''; +$params->{name} ||= ''; + diff --git a/website/agenda/planung/image.cgi b/website/agenda/planung/image.cgi index 94ac593..15a3a96 100755 --- a/website/agenda/planung/image.cgi +++ b/website/agenda/planung/image.cgi @@ -1,444 +1,458 @@ -#! /usr/bin/perl -w +#!/usr/bin/perl -use warnings "all"; use strict; +use warnings; +no warnings 'redefine'; +use utf8; use Data::Dumper; -use File::stat; -use Time::localtime; -use CGI qw(header param Vars escapeHTML uploadInfo cgi_error); -use URI::Escape; +use File::stat(); +use Time::localtime(); +use URI::Escape(); -use time; -use images; -use params; -use config; -use log; -use template; -use db; -use auth; -use uac; -use project; -use time; -use markup; -use studios; -use series; -use localization; +use time(); +use images(); +use params(); +use config(); +use entry(); +use log(); +use template(); +use db(); +use auth(); +use uac(); +use project(); +use time(); +use markup(); +use studios(); +use series(); +use localization(); binmode STDOUT, ":utf8"; my $r = shift; ( my $cgi, my $params, my $error ) = params::get($r); -$CGI::POST_MAX = 1024 * 10; my $config = config::get('../config/config.cgi'); my $debug = $config->{system}->{debug}; -my ( $user, $expires ) = auth::get_user( $cgi, $config ); +my ( $user, $expires ) = auth::get_user( $config, $params, $cgi ); return if ( ( !defined $user ) || ( $user eq '' ) ); my $user_presets = uac::get_user_presets( - $config, - { - user => $user, - project_id => $params->{project_id}, - studio_id => $params->{studio_id} - } + $config, + { + user => $user, + project_id => $params->{project_id}, + studio_id => $params->{studio_id} + } ); $params->{default_studio_id} = $user_presets->{studio_id}; -$params->{studio_id} = $params->{default_studio_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); -$params->{project_id} = $user_presets->{project_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); +$params = uac::setDefaultStudio( $params, $user_presets ); +$params = uac::setDefaultProject( $params, $user_presets ); my $request = { - url => $ENV{QUERY_STRING} || '', - params => { - original => $params, - checked => check_params($params), - } + url => $ENV{QUERY_STRING} || '', + params => { + original => $params, + checked => check_params( $config, $params ), + } }; $request = uac::prepare_request( $request, $user_presets ); -log::init($request); $params = $request->{params}->{checked}; #show header my $headerParams = uac::set_template_permissions( $request->{permissions}, $params ); $headerParams->{loc} = localization::get( $config, { user => $user, file => 'menu' } ); -template::process( 'print', template::check('ajax_header.html'), $headerParams ); -return unless defined uac::check( $config, $params, $user_presets ); -#my $base_dir = $config->{locations}->{base_dir}; +if ( $params->{search} ) { + template::process( $config, 'print', template::check( $config, 'default.html' ), $headerParams ); +} else { + template::process( $config, 'print', template::check( $config, 'ajax-header.html' ), $headerParams ); +} + +return unless uac::check( $config, $params, $user_presets ) == 1; + my $local_media_dir = $config->{locations}->{local_media_dir}; my $local_media_url = $config->{locations}->{local_media_url}; -#my $local_base_url = $config->{locations}->{local_base_url}; - -log::error( $config, 'cannot locate media dir' . $local_media_dir ) unless ( -e $local_media_dir ); - -#continue on error -uac::permissions_denied('reading from local media dir') unless ( -r $local_media_dir ); -uac::permissions_denied('writing to local media dir') unless ( -w $local_media_dir ); +log::error( $config, 'cannot locate media dir ' . $local_media_dir ) unless -e $local_media_dir; +uac::permissions_denied('reading from local media dir') unless -r $local_media_dir; +uac::permissions_denied('writing to local media dir') unless -w $local_media_dir; if ( $params->{delete_image} ne '' ) { - delete_image( $config, $request, $user, $local_media_dir ); - return; + delete_image( $config, $request, $user, $local_media_dir ); + return; } elsif ( $params->{save_image} ne '' ) { - save_image( $config, $request, $user ); - return; + save_image( $config, $request, $user ); + return; } show_image( $config, $request, $user, $local_media_url ); sub show_image { - my $config = shift; - my $request = shift; - my $user = shift; - my $local_media_url = shift; + my $config = shift; + my $request = shift; + my $user = shift; + my $local_media_url = shift; - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; - unless ( defined $params->{project_id} ) { - uac::print_error("missing project id"); - return undef; - } - unless ( defined $params->{studio_id} ) { - uac::print_error("missing studio id"); - return undef; - } + unless ( defined $params->{project_id} ) { + uac::print_error("missing project id"); + return undef; + } + unless ( defined $params->{studio_id} ) { + uac::print_error("missing studio id"); + return undef; + } - if ( $permissions->{read_image} ne '1' ) { - uac::permissions_denied("read image"); - return 0; - } + if ( $permissions->{read_image} ne '1' ) { + uac::permissions_denied("read image"); + return 0; + } - $config->{access}->{write} = 0; - my $dbh = db::connect( $config, undef ); + $config->{access}->{write} = 0; + my $dbh = db::connect( $config, undef ); - my $selectedFilename = $params->{filename} || ''; - my $filenames = {}; - my $results = []; + my $projectId = $params->{project_id}; + my $studioId = $params->{studio_id}; + my $selectedFilename = $params->{filename} || ''; - # add images from series - if ( defined $params->{series_id} ) { - my $seriesImages = series::get_images( $config, $params ); + my $filenames = {}; + my $results = []; - for my $image (@$seriesImages) { - my $filename = $image->{filename}; - unless ( defined $filenames->{$filename} ) { + # add images from series + if ( defined $params->{series_id} ) { + my $seriesImages = series::get_images( + $config, + { + project_id => $projectId, + studio_id => $studioId, + series_id => $params->{series_id} + } + ); - #print STDERR "add1 $filename\n"; - push @$results, $image; - $filenames->{$filename} = $image; - } - } - } + for my $image (@$seriesImages) { + my $filename = $image->{filename}; + next if defined $filenames->{$filename}; + $filenames->{$filename} = $image; + push @$results, $image; + } + } - #load images matching by search - if ( defined $params->{search} ) { + #load images matching by search + if ( ($params->{search}//'') =~ /\S/ ) { - #remove filename from search - delete $params->{filename}; - delete $params->{series_id}; - my $searchImages = images::get( $config, $params ); + #remove filename from search + #delete $params->{filename}; + #delete $params->{series_id}; + my $searchImages = images::get( + $config, + { + project_id => $projectId, + studio_id => $studioId, + search => $params->{search} + } + ); - for my $image (@$searchImages) { - my $filename = $image->{filename}; - unless ( defined $filenames->{$filename} ) { + for my $image (@$searchImages) { + my $filename = $image->{filename}; + next if defined $filenames->{$filename}; + $filenames->{$filename} = $image; + push @$results, $image; + } + } - #print STDERR "add2 $filename\n"; - push @$results, $image; - $filenames->{$filename} = $image; - } - } - } + #load selected image, if not already loaded + my $selectedImage = undef; + if ( $selectedFilename ne '' ) { + if ( defined $filenames->{$selectedFilename} ) { + $selectedImage = $filenames->{$selectedFilename}; + } else { - #load selected image, if not already loaded - if ( $selectedFilename ne '' ) { - my $search = $params->{search} || ''; + #put selected image to the top + my $imagesByNames = images::get( + $config, + { + project_id => $projectId, + studio_id => $studioId, + filename => $selectedFilename + } + ); + $selectedImage = $imagesByNames->[0] if scalar @$imagesByNames > 0; + } - # use selected image if already loaded - my $selectedImage = undef; - if ( defined $filenames->{$selectedFilename} ) { - $selectedImage = $filenames->{$selectedFilename}; - } else { + my $finalResults = []; - #now add filename and remove search - $params->{filename} = $selectedFilename; - delete $params->{search}; + # put selected image first + $selectedFilename = 'not-found'; + if ( defined $selectedImage ) { + push @$finalResults, $selectedImage; + $selectedFilename = $selectedImage->{filename}; + } - #put selected image to the top - my $imagesByNames = images::get( $config, $params ); - $selectedImage = $imagesByNames->[0] if ( scalar(@$imagesByNames) > 0 ); - } + # then other images + for my $image (@$results) { + push @$finalResults, $image if $image->{filename} ne $selectedFilename; + } + $results = $finalResults; + } - my $finalResults = []; + if ( scalar @$results != 0 ) { + if ( $params->{template} =~ /edit/ ) { + my $result = $results->[0]; + $result->{missing_licence} = 1 if ( !defined $result->{licence} ) || ( $result->{licence} !~ /\S/ ); + $results = [$result]; + } - # put selected image first - $selectedFilename = 'not-found'; - if ( defined $selectedImage ) { - push @$finalResults, $selectedImage; - $selectedFilename = $selectedImage->{filename}; - } + $results = modify_results( $results, $permissions, $user, $local_media_url ); + } - # then other images - for my $image (@$results) { - push @$finalResults, $image if $image->{filename} ne $selectedFilename; - } - $results = $finalResults; + my $search = $params->{search} || ''; + $search =~ s/\%+/ /g; + + $params->{target} //= ''; - #add search again - $params->{search} = $search; - } + my $template_params = { + 'search' => $search, + 'images' => $results, + 'count' => scalar @$results, + 'projects' => project::get_with_dates($config), + 'project_id' => $params->{project_id}, + 'studio_id' => $params->{studio_id}, + 'series_id' => $params->{series_id}, + 'event_id' => $params->{event_id}, + 'pid' => $params->{pid}, + 'target' => $params->{target}, + 'filename' => $params->{filename} + }; - if ( $params->{template} =~ /edit/ ) { - $results = [ $results->[0] ] || undef; - } - if ( defined $results ) { - $results = modify_results( $results, $permissions, $user, $local_media_url ); - } + # print STDERR + $template_params->{loc} = localization::get( $config, { user => $params->{presets}->{user}, file => 'image' } ); - my $search = $params->{search} || ''; - $search =~ s/\%+/ /g; - my $template_params = { - 'search' => $search, - 'images' => $results, - 'count' => @$results . '', - 'projects' => project::get_with_dates($config), - 'project_id' => $params->{project_id}, - 'studio_id' => $params->{studio_id}, - 'filename' => $params->{filename} - }; + my $label_key = 'label_assign_to_'.$params->{target}; + $template_params->{label_assign_to_by_label} = $template_params->{loc}->{$label_key}; - # print STDERR - $template_params->{loc} = localization::get( $config, { user => $params->{presets}->{user}, file => 'image' } ); - $template_params = uac::set_template_permissions( $permissions, $template_params ); + $label_key = 'label_warn_not_public_'.$params->{target}; + $template_params->{label_warn_not_public_by_label} = $template_params->{loc}->{$label_key}; - #set global values for update and delete, per image values are evaluated later - $template_params->{allow}->{update_image} = - $template_params->{allow}->{update_image_own} || $template_params->{allow}->{seriesupdate_image_others}; - $template_params->{allow}->{delete_image} = - $template_params->{allow}->{delete_image_own} || $template_params->{allow}->{delete_image_others}; - template::process( 'print', $params->{template}, $template_params ); + $template_params = uac::set_template_permissions( $permissions, $template_params ); + $template_params->{no_results} = 1 if scalar @$results == 0; + + #set global values for update and delete, per image values are evaluated later + $template_params->{allow}->{update_image} = + $template_params->{allow}->{update_image_own} || $template_params->{allow}->{update_image_others}; + $template_params->{allow}->{delete_image} = + $template_params->{allow}->{delete_image_own} || $template_params->{allow}->{delete_image_others}; + template::process( $config, 'print', $params->{template}, $template_params ); } sub print_js_error { - my $message = shift; - print qq{<!-- + my $message = shift; + print qq{<!-- ERROR: $message --> }; - print STDERR $message . "\n"; + print STDERR $message . "\n"; } sub save_image { - my $config = shift; - my $request = shift; - my $user = shift; + my $config = shift; + my $request = shift; + my $user = shift; - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; - unless ( check_permission( $config, $user, $permissions, 'update_image', $params->{save_image} ) eq '1' ) { - print_js_error("missing permission to update image"); - return 0; - } + unless ( check_permission( $config, $user, $permissions, 'update_image', $params->{save_image} ) eq '1' ) { + print_js_error("missing permission to update image"); + return 0; + } - if ( ( $params->{update_name} eq '' ) && ( $params->{update_description} eq '' ) ) { - print_js_error("empty name or empty description!"); - return 0; - } + if ( ( $params->{update_name} eq '' ) && ( $params->{update_description} eq '' ) ) { + print_js_error("empty name or empty description!"); + return 0; + } - my $image = {}; - $image->{filename} = $params->{save_image}; - $image->{name} = $params->{update_name} if ( $params->{update_name} ne '' ); - $image->{description} = $params->{update_description} if ( $params->{update_description} ne '' ); - $image->{project_id} = $params->{project_id}; - $image->{studio_id} = $params->{studio_id}; - $image->{modified_by} = $user; + my $image = {}; + $image->{filename} = $params->{save_image}; + $image->{name} = $params->{update_name} if $params->{update_name} ne ''; + $image->{description} = $params->{update_description} if $params->{update_description} ne ''; + $image->{project_id} = $params->{project_id}; + $image->{studio_id} = $params->{studio_id}; + $image->{licence} = $params->{licence}; + $image->{public} = $params->{public}; + $image->{modified_by} = $user; - $image->{name} = 'new' if ( $image->{name} eq '' ); + $image->{name} = 'new' if $image->{name} eq ''; - $config->{access}->{write} = 1; - my $dbh = db::connect($config); + images::checkLicence( $config, $image ); - #print STDERR "going to save\n"; - my $entries = images::get( - $config, - { - filename => $image->{filename}, - project_id => $image->{project_id}, - studio_id => $image->{studio_id} - } - ); + $config->{access}->{write} = 1; + my $dbh = db::connect($config); - #print STDERR Dumper($entries); - if ( scalar @$entries > 1 ) { - print_js_error('more than one matching result found'); - return 0; - } - if ( scalar @$entries == 0 ) { - print_js_error('image not found in database (for this studio)'); - return 0; - } - my $entry = $entries->[0]; - if ( defined $entry ) { - images::update( $dbh, $image ); - } else { - $image->{created_by} = $user; - images::insert( $dbh, $image ); - } + my $entries = images::get( + $config, + { + filename => $image->{filename}, + project_id => $image->{project_id}, + studio_id => $image->{studio_id} + } + ); + + if ( scalar @$entries > 1 ) { + print_js_error('more than one matching result found'); + return 0; + } + if ( scalar @$entries == 0 ) { + print_js_error('image not found in database (for this studio)'); + return 0; + } + my $entry = $entries->[0]; + if ( defined $entry ) { + images::update( $dbh, $image ); + images::publish( $config, $image->{filename} ) if ( ( $image->{public} == 1 ) && ( $entry->{public} == 0 ) ); + images::depublish( $config, $image->{filename} ) if ( ( $image->{public} == 0 ) && ( $entry->{public} == 1 ) ); + } else { + $image->{created_by} = $user; + images::insert( $dbh, $image ); + } } sub delete_image { - my $config = shift; - my $request = shift; - my $user = shift; - my $local_media_dir = shift; + my $config = shift; + my $request = shift; + my $user = shift; + my $local_media_dir = shift; - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; - unless ( check_permission( $config, $user, $permissions, 'delete_image', $params->{delete_image} ) eq '1' ) { - uac::permissions_denied('delete image'); - return 0; - } + unless ( check_permission( $config, $user, $permissions, 'delete_image', $params->{delete_image} ) eq '1' ) { + uac::permissions_denied('delete image'); + return 0; + } - #print $cgi->header(); - #print "Content-type:text/html; charset=UTF-8;\n\n"; + $config->{access}->{write} = 1; + my $dbh = db::connect($config); + my $image = { + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + filename => $params->{delete_image}, + }; + my $result = images::delete( $dbh, $image ); - $config->{access}->{write} = 1; - my $dbh = db::connect($config); - my $image = { - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - filename => $params->{delete_image}, - }; - my $result = images::delete( $dbh, $image ); - print STDERR "delete result=" . Dumper($result); + return; - return; - my $action_result = ''; - my $errors = ''; - $result = images::delete_files( $config, $local_media_dir, $params->{delete_image}, $action_result, $errors ); - - #use Data::Dumper;print STDERR "delete\n".Dumper($params); - print "deleted<br />$action_result<br />$errors\n"; + #my $action_result = ''; + #my $errors = ''; + #$result = images::delete_files( $config, $local_media_dir, $params->{delete_image}, $action_result, $errors ); + #print "deleted<br />$action_result<br />$errors\n"; } sub check_permission { - my $config = shift; - my $user = shift; - my $permissions = shift; - my $permission = shift; - my $filename = shift; + my $config = shift; + my $user = shift; + my $permissions = shift; + my $permission = shift; + my $filename = shift; - return 0 unless defined $user; - return 0 if ( $user eq '' ); + return 0 unless defined $user; + return 0 if ( $user eq '' ); - if ( $permissions->{ $permission . '_others' } eq '1' ) { - print STDERR "$user has update_image_others\n"; - return 1; - } elsif ( $permissions->{ $permission . '_own' } eq '1' ) { - print STDERR "$user has update_image_own\n"; + if ( $permissions->{ $permission . '_others' } eq '1' ) { + print STDERR "$user has update_image_others\n"; + return 1; + } elsif ( $permissions->{ $permission . '_own' } eq '1' ) { + print STDERR "$user has update_image_own\n"; - #check if image was created by user - my $results = images::get( - $config, - { - filename => $filename, - created_by => $user - } - ); - return 1 if ( @$results == 1 ); - return 0; - } - return 0; + #check if image was created by user + my $results = images::get( + $config, + { + filename => $filename, + created_by => $user + } + ); + return 1 if ( @$results == 1 ); + return 0; + } + return 0; } sub modify_results { - my $results = shift; - my $permissions = shift; - my $user = shift; - my $local_media_url = shift; + my $results = shift; + my $permissions = shift; + my $user = shift; + my $local_media_url = shift; - for my $result (@$results) { - unless ( defined $result->{filename} ) { - $result = undef; - next; - } - $result->{image_url} = $local_media_url . '/images/' . $result->{filename}; - $result->{thumb_url} = $local_media_url . '/thumbs/' . $result->{filename}; - $result->{icon_url} = $local_media_url . '/icons/' . $result->{filename}; + for my $result (@$results) { + unless ( defined $result->{filename} ) { + $result = undef; + next; + } + $result->{image_url} = $local_media_url . '/images/' . $result->{filename}; + $result->{thumb_url} = $local_media_url . '/thumbs/' . $result->{filename}; + $result->{icon_url} = $local_media_url . '/icons/' . $result->{filename}; - #reduce - for my $permission ( 'update_image', 'delete_image' ) { - if ( ( defined $permissions->{ $permission . '_others' } ) && ( $permissions->{ $permission . '_others' } eq '1' ) ) { - $result->{$permission} = 1; - } elsif ( ( defined $permissions->{ $permission . '_own' } ) && ( $permissions->{ $permission . '_own' } eq '1' ) ) { - next if ( $user eq '' ); - $result->{$permission} = 1 if ( $user eq $result->{created_by} ); - } - } - } - return $results; + #reduce + for my $permission ( 'update_image', 'delete_image' ) { + if ( ( defined $permissions->{ $permission . '_others' } ) + && ( $permissions->{ $permission . '_others' } eq '1' ) ) + { + $result->{$permission} = 1; + } elsif ( ( defined $permissions->{ $permission . '_own' } ) + && ( $permissions->{ $permission . '_own' } eq '1' ) ) + { + next if ( $user eq '' ); + $result->{$permission} = 1 if ( $user eq $result->{created_by} ); + } + } + } + return $results; } sub check_params { - my $params = shift; + my $config = shift; + my $params = shift; - my $checked = { template => template::check( $params->{template}, 'image.html' ) }; + my $checked = { template => template::check( $config, $params->{template}, 'image.html' ) }; - #numeric values - $checked->{limit} = 100; - for my $param ( 'project_id', 'studio_id', 'series_id', 'default_studio_id', 'limit' ) { - if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /^\d+$/ ) ) { - $checked->{$param} = $params->{$param}; - } - } - if ( defined $checked->{studio_id} ) { - $checked->{default_studio_id} = $checked->{studio_id}; - } else { - $checked->{studio_id} = -1; - } + $checked->{limit} = 100; + entry::set_numbers( $checked, $params, [ + 'project_id', 'studio_id', 'series_id', 'event_id', 'pid', 'default_studio_id', 'limit' + ]); - $checked->{limit} = 100 unless defined $checked->{limit}; - $checked->{limit} = 100 if ( $checked->{limit} > 100 ); + if ( defined $checked->{studio_id} ) { + $checked->{default_studio_id} = $checked->{studio_id}; + } else { + $checked->{studio_id} = -1; + } - #string - $checked->{search} = ''; - if ( ( defined $params->{search} ) && ( $params->{search} =~ /^\s*(.+?)\s*$/ ) ) { - $checked->{search} = $1; - } + $checked->{limit} = 100 unless defined $checked->{limit}; + $checked->{limit} = 100 if ( $checked->{limit} > 100 ); - for my $attr ( 'update_name', 'update_description' ) { - $checked->{$attr} = ''; - if ( ( defined $params->{$attr} ) && ( $params->{$attr} =~ /^\s*(.+?)\s*$/ ) ) { - $checked->{$attr} = $params->{$attr}; - } - } + $checked->{delete_image} = ''; + $checked->{save_image} = ''; + entry::set_strings( $checked, $params, [ + 'search', + 'update_name', 'update_description', 'licence', + 'save_image', 'delete_image', 'show', 'filename', 'target' ]); - #Words - $checked->{delete_image} = ''; - $checked->{save_image} = ''; - for my $attr ( 'save_image', 'delete_image', 'show', 'filename' ) { - $checked->{$attr} = ''; - if ( ( defined $params->{$attr} ) && ( $params->{$attr} =~ /(\S+)/ ) ) { - $checked->{$attr} = $params->{$attr}; - } - } + #checkboxes + entry::set_bools( $checked, $params, [ 'public']); - #map show to filename, but overwrite if filename given - if ( $checked->{show} ne '' ) { - $checked->{filename} = $checked->{show}; - delete $checked->{show}; - $checked->{limit} = 1; - } elsif ( $checked->{filename} ne '' ) { - delete $checked->{show}; - } + #map show to filename, but overwrite if filename given + if ( ($checked->{show}//'') ne '' ) { + $checked->{filename} = $checked->{show}; + delete $checked->{show}; + $checked->{limit} = 1; + } elsif ( ($checked->{filename}//'') ne '' ) { + delete $checked->{show}; + } - $checked->{from} = time::check_date( $params->{from} ); - $checked->{till} = time::check_date( $params->{till} ); + $checked->{from} = time::check_date( $params->{from} ); + $checked->{till} = time::check_date( $params->{till} ); - return $checked; + return $checked; } diff --git a/website/agenda/planung/image/16/archived.png b/website/agenda/planung/image/16/archived.png deleted file mode 100644 index 629bea3..0000000 Binary files a/website/agenda/planung/image/16/archived.png and /dev/null differ diff --git a/website/agenda/planung/image/16/comment.png b/website/agenda/planung/image/16/comment.png deleted file mode 100644 index ce337ac..0000000 Binary files a/website/agenda/planung/image/16/comment.png and /dev/null differ diff --git a/website/agenda/planung/image/16/deleted.png b/website/agenda/planung/image/16/deleted.png deleted file mode 100644 index 42304d2..0000000 Binary files a/website/agenda/planung/image/16/deleted.png and /dev/null differ diff --git a/website/agenda/planung/image/16/draft.png b/website/agenda/planung/image/16/draft.png deleted file mode 100644 index 415ea8b..0000000 Binary files a/website/agenda/planung/image/16/draft.png and /dev/null differ diff --git a/website/agenda/planung/image/16/live.png b/website/agenda/planung/image/16/live.png deleted file mode 100644 index cd3901c..0000000 Binary files a/website/agenda/planung/image/16/live.png and /dev/null differ diff --git a/website/agenda/planung/image/16/playout.png b/website/agenda/planung/image/16/playout.png deleted file mode 100644 index 14780c6..0000000 Binary files a/website/agenda/planung/image/16/playout.png and /dev/null differ diff --git a/website/agenda/planung/image/16/preproduced.png b/website/agenda/planung/image/16/preproduced.png deleted file mode 100644 index 8903ee4..0000000 Binary files a/website/agenda/planung/image/16/preproduced.png and /dev/null differ diff --git a/website/agenda/planung/image/16/published.png b/website/agenda/planung/image/16/published.png deleted file mode 100644 index 8b629b7..0000000 Binary files a/website/agenda/planung/image/16/published.png and /dev/null differ diff --git a/website/agenda/planung/image/16/rerun.png b/website/agenda/planung/image/16/rerun.png deleted file mode 100644 index 215dcf5..0000000 Binary files a/website/agenda/planung/image/16/rerun.png and /dev/null differ diff --git a/website/agenda/planung/image/32/archived.png b/website/agenda/planung/image/32/archived.png deleted file mode 100644 index 61fb266..0000000 Binary files a/website/agenda/planung/image/32/archived.png and /dev/null differ diff --git a/website/agenda/planung/image/32/calendar.png b/website/agenda/planung/image/32/calendar.png deleted file mode 100644 index 968325d..0000000 Binary files a/website/agenda/planung/image/32/calendar.png and /dev/null differ diff --git a/website/agenda/planung/image/32/comment.png b/website/agenda/planung/image/32/comment.png deleted file mode 100644 index 5284953..0000000 Binary files a/website/agenda/planung/image/32/comment.png and /dev/null differ diff --git a/website/agenda/planung/image/32/deleted.png b/website/agenda/planung/image/32/deleted.png deleted file mode 100644 index ee255d5..0000000 Binary files a/website/agenda/planung/image/32/deleted.png and /dev/null differ diff --git a/website/agenda/planung/image/32/draft.png b/website/agenda/planung/image/32/draft.png deleted file mode 100644 index 16357dd..0000000 Binary files a/website/agenda/planung/image/32/draft.png and /dev/null differ diff --git a/website/agenda/planung/image/32/live.png b/website/agenda/planung/image/32/live.png deleted file mode 100644 index c5bfe2e..0000000 Binary files a/website/agenda/planung/image/32/live.png and /dev/null differ diff --git a/website/agenda/planung/image/32/no_sync.png b/website/agenda/planung/image/32/no_sync.png deleted file mode 100644 index 4632b0e..0000000 Binary files a/website/agenda/planung/image/32/no_sync.png and /dev/null differ diff --git a/website/agenda/planung/image/32/playout.png b/website/agenda/planung/image/32/playout.png deleted file mode 100644 index ddcaaae..0000000 Binary files a/website/agenda/planung/image/32/playout.png and /dev/null differ diff --git a/website/agenda/planung/image/32/preproduced.png b/website/agenda/planung/image/32/preproduced.png deleted file mode 100644 index f770f15..0000000 Binary files a/website/agenda/planung/image/32/preproduced.png and /dev/null differ diff --git a/website/agenda/planung/image/32/published.png b/website/agenda/planung/image/32/published.png deleted file mode 100644 index 6f17a33..0000000 Binary files a/website/agenda/planung/image/32/published.png and /dev/null differ diff --git a/website/agenda/planung/image/32/rerun.png b/website/agenda/planung/image/32/rerun.png deleted file mode 100644 index 25bd5a5..0000000 Binary files a/website/agenda/planung/image/32/rerun.png and /dev/null differ diff --git a/website/agenda/planung/image/accounts.svg b/website/agenda/planung/image/accounts.svg new file mode 100644 index 0000000..83f7ebc --- /dev/null +++ b/website/agenda/planung/image/accounts.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="18px" viewBox="0 0 24 24" width="18px" fill="#FFFFFF"><g><path d="M0,0h24v24H0V0z" fill="none"/></g><g><g><path d="M4,18v-0.65c0-0.34,0.16-0.66,0.41-0.81C6.1,15.53,8.03,15,10,15c0.03,0,0.05,0,0.08,0.01c0.1-0.7,0.3-1.37,0.59-1.98 C10.45,13.01,10.23,13,10,13c-2.42,0-4.68,0.67-6.61,1.82C2.51,15.34,2,16.32,2,17.35V20h9.26c-0.42-0.6-0.75-1.28-0.97-2H4z"/><path d="M10,12c2.21,0,4-1.79,4-4s-1.79-4-4-4C7.79,4,6,5.79,6,8S7.79,12,10,12z M10,6c1.1,0,2,0.9,2,2s-0.9,2-2,2 c-1.1,0-2-0.9-2-2S8.9,6,10,6z"/><path d="M20.75,16c0-0.22-0.03-0.42-0.06-0.63l1.14-1.01l-1-1.73l-1.45,0.49c-0.32-0.27-0.68-0.48-1.08-0.63L18,11h-2l-0.3,1.49 c-0.4,0.15-0.76,0.36-1.08,0.63l-1.45-0.49l-1,1.73l1.14,1.01c-0.03,0.21-0.06,0.41-0.06,0.63s0.03,0.42,0.06,0.63l-1.14,1.01 l1,1.73l1.45-0.49c0.32,0.27,0.68,0.48,1.08,0.63L16,21h2l0.3-1.49c0.4-0.15,0.76-0.36,1.08-0.63l1.45,0.49l1-1.73l-1.14-1.01 C20.72,16.42,20.75,16.22,20.75,16z M17,18c-1.1,0-2-0.9-2-2s0.9-2,2-2s2,0.9,2,2S18.1,18,17,18z"/></g></g></svg> \ No newline at end of file diff --git a/website/agenda/planung/image/activity.svg b/website/agenda/planung/image/activity.svg new file mode 100644 index 0000000..e384fc6 --- /dev/null +++ b/website/agenda/planung/image/activity.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="18px" viewBox="0 0 24 24" width="18px" fill="#FFFFFF"><path d="M0 0h24v24H0z" fill="none"/><path d="M8.5 14.5L4 19l1.5 1.5L9 17h2l-2.5-2.5zM15 1c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm6 20.01L18 24l-2.99-3.01V19.5l-7.1-7.09c-.31.05-.61.07-.91.07v-2.16c1.66.03 3.61-.87 4.67-2.04l1.4-1.55c.19-.21.43-.38.69-.5.29-.14.62-.23.96-.23h.03C15.99 6.01 17 7.02 17 8.26v5.75c0 .84-.35 1.61-.92 2.16l-3.58-3.58v-2.27c-.63.52-1.43 1.02-2.29 1.39L16.5 18H18l3 3.01z"/></svg> \ No newline at end of file diff --git a/website/agenda/planung/image/alert.svg b/website/agenda/planung/image/alert.svg new file mode 100644 index 0000000..aa3f3ca --- /dev/null +++ b/website/agenda/planung/image/alert.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"/></svg> \ No newline at end of file diff --git a/website/agenda/planung/image/antenna.svg b/website/agenda/planung/image/antenna.svg new file mode 100644 index 0000000..976bd5c --- /dev/null +++ b/website/agenda/planung/image/antenna.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="18px" viewBox="0 0 24 24" width="18px" fill="#FFFFFF"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M12 5c-3.87 0-7 3.13-7 7h2c0-2.76 2.24-5 5-5s5 2.24 5 5h2c0-3.87-3.13-7-7-7zm1 9.29c.88-.39 1.5-1.26 1.5-2.29 0-1.38-1.12-2.5-2.5-2.5S9.5 10.62 9.5 12c0 1.02.62 1.9 1.5 2.29v3.3L7.59 21 9 22.41l3-3 3 3L16.41 21 13 17.59v-3.3zM12 1C5.93 1 1 5.93 1 12h2c0-4.97 4.03-9 9-9s9 4.03 9 9h2c0-6.07-4.93-11-11-11z"/></svg> \ No newline at end of file diff --git a/website/agenda/planung/image/archive.svg b/website/agenda/planung/image/archive.svg new file mode 100644 index 0000000..6d6ed4a --- /dev/null +++ b/website/agenda/planung/image/archive.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M20.54 5.23l-1.39-1.68C18.88 3.21 18.47 3 18 3H6c-.47 0-.88.21-1.16.55L3.46 5.23C3.17 5.57 3 6.02 3 6.5V19c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V6.5c0-.48-.17-.93-.46-1.27zM6.24 5h11.52l.81.97H5.44l.8-.97zM5 19V8h14v11H5zm8.45-9h-2.9v3H8l4 4 4-4h-2.55z"/></svg> \ No newline at end of file diff --git a/website/agenda/planung/image/archived.png b/website/agenda/planung/image/archived.png deleted file mode 100644 index 629bea3..0000000 Binary files a/website/agenda/planung/image/archived.png and /dev/null differ diff --git a/website/agenda/planung/image/arrow-down.svg b/website/agenda/planung/image/arrow-down.svg new file mode 100644 index 0000000..67ed999 --- /dev/null +++ b/website/agenda/planung/image/arrow-down.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="18px" viewBox="0 0 24 24" width="18px" fill="#FFFFFF"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6 1.41-1.41z"/></svg> \ No newline at end of file diff --git a/website/agenda/planung/image/back.svg b/website/agenda/planung/image/back.svg new file mode 100644 index 0000000..0b6a46b --- /dev/null +++ b/website/agenda/planung/image/back.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="18px" viewBox="0 0 24 24" width="18px" fill="#FFFFFF"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"/></svg> \ No newline at end of file diff --git a/website/agenda/planung/image/calendar.png b/website/agenda/planung/image/calendar.png deleted file mode 100644 index 968325d..0000000 Binary files a/website/agenda/planung/image/calendar.png and /dev/null differ diff --git a/website/agenda/planung/image/calendar.svg b/website/agenda/planung/image/calendar.svg new file mode 100644 index 0000000..befab08 --- /dev/null +++ b/website/agenda/planung/image/calendar.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="18px" viewBox="0 0 24 24" width="18px" fill="#FFFFFF"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M19 4h-1V2h-2v2H8V2H6v2H5c-1.11 0-1.99.9-1.99 2L3 20c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 16H5V10h14v10zm0-12H5V6h14v2zm-7 5h5v5h-5z"/></svg> \ No newline at end of file diff --git a/website/agenda/planung/image/chess.gif b/website/agenda/planung/image/chess.gif deleted file mode 100644 index 2a65a2b..0000000 Binary files a/website/agenda/planung/image/chess.gif and /dev/null differ diff --git a/website/agenda/planung/image/deleted.png b/website/agenda/planung/image/deleted.png deleted file mode 100644 index 42304d2..0000000 Binary files a/website/agenda/planung/image/deleted.png and /dev/null differ diff --git a/website/agenda/planung/image/draft.png b/website/agenda/planung/image/draft.png deleted file mode 100644 index 16357dd..0000000 Binary files a/website/agenda/planung/image/draft.png and /dev/null differ diff --git a/website/agenda/planung/image/draft.svg b/website/agenda/planung/image/draft.svg new file mode 100644 index 0000000..34e92c8 --- /dev/null +++ b/website/agenda/planung/image/draft.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM5.92 19H5v-.92l9.06-9.06.92.92L5.92 19zM20.71 5.63l-2.34-2.34c-.2-.2-.45-.29-.71-.29s-.51.1-.7.29l-1.83 1.83 3.75 3.75 1.83-1.83c.39-.39.39-1.02 0-1.41z"/></svg> \ No newline at end of file diff --git a/website/agenda/planung/image/error.svg b/website/agenda/planung/image/error.svg new file mode 100644 index 0000000..8c61b7a --- /dev/null +++ b/website/agenda/planung/image/error.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/></svg> \ No newline at end of file diff --git a/website/agenda/planung/image/group.svg b/website/agenda/planung/image/group.svg new file mode 100644 index 0000000..dd0702e --- /dev/null +++ b/website/agenda/planung/image/group.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="18px" viewBox="0 0 24 24" width="18px" fill="#FFFFFF"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M9 13.75c-2.34 0-7 1.17-7 3.5V19h14v-1.75c0-2.33-4.66-3.5-7-3.5zM4.34 17c.84-.58 2.87-1.25 4.66-1.25s3.82.67 4.66 1.25H4.34zM9 12c1.93 0 3.5-1.57 3.5-3.5S10.93 5 9 5 5.5 6.57 5.5 8.5 7.07 12 9 12zm0-5c.83 0 1.5.67 1.5 1.5S9.83 10 9 10s-1.5-.67-1.5-1.5S8.17 7 9 7zm7.04 6.81c1.16.84 1.96 1.96 1.96 3.44V19h4v-1.75c0-2.02-3.5-3.17-5.96-3.44zM15 12c1.93 0 3.5-1.57 3.5-3.5S16.93 5 15 5c-.54 0-1.04.13-1.5.35.63.89 1 1.98 1 3.15s-.37 2.26-1 3.15c.46.22.96.35 1.5.35z"/></svg> \ No newline at end of file diff --git a/website/agenda/planung/image/help.svg b/website/agenda/planung/image/help.svg new file mode 100644 index 0000000..3631070 --- /dev/null +++ b/website/agenda/planung/image/help.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="18px" viewBox="0 0 24 24" width="18px" fill="#FFFFFF"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M11 18h2v-2h-2v2zm1-16C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm0-14c-2.21 0-4 1.79-4 4h2c0-1.1.9-2 2-2s2 .9 2 2c0 2-3 1.75-3 5h2c0-2.25 3-2.5 3-5 0-2.21-1.79-4-4-4z"/></svg> \ No newline at end of file diff --git a/website/agenda/planung/image/home.svg b/website/agenda/planung/image/home.svg new file mode 100644 index 0000000..b65fb18 --- /dev/null +++ b/website/agenda/planung/image/home.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="18px" viewBox="0 0 24 24" width="18px" fill="#FFFFFF"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M12 5.69l5 4.5V18h-2v-6H9v6H7v-7.81l5-4.5M12 3L2 12h3v8h6v-6h2v6h6v-8h3L12 3z"/></svg> \ No newline at end of file diff --git a/website/agenda/planung/image/image.svg b/website/agenda/planung/image/image.svg new file mode 100644 index 0000000..0d5e331 --- /dev/null +++ b/website/agenda/planung/image/image.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="18px" viewBox="0 0 24 24" width="18px" fill="#FFFFFF"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-4.86 8.86l-3 3.87L9 13.14 6 17h12l-3.86-5.14z"/></svg> \ No newline at end of file diff --git a/website/agenda/planung/image/list.svg b/website/agenda/planung/image/list.svg new file mode 100644 index 0000000..f4ad9e5 --- /dev/null +++ b/website/agenda/planung/image/list.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="18px" viewBox="0 0 24 24" width="18px" fill="#FFFFFF"><g fill="none"><path d="M0 0h24v24H0V0z"/><path d="M0 0h24v24H0V0z" opacity=".87"/></g><path d="M3 13h2v-2H3v2zm0 4h2v-2H3v2zm0-8h2V7H3v2zm4 4h14v-2H7v2zm0 4h14v-2H7v2zM7 7v2h14V7H7zm-4 6h2v-2H3v2zm0 4h2v-2H3v2zm0-8h2V7H3v2zm4 4h14v-2H7v2zm0 4h14v-2H7v2zM7 7v2h14V7H7z"/></svg> \ No newline at end of file diff --git a/website/agenda/planung/image/live.png b/website/agenda/planung/image/live.png deleted file mode 100644 index cd3901c..0000000 Binary files a/website/agenda/planung/image/live.png and /dev/null differ diff --git a/website/agenda/planung/image/logout.svg b/website/agenda/planung/image/logout.svg new file mode 100644 index 0000000..0179f70 --- /dev/null +++ b/website/agenda/planung/image/logout.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="18px" viewBox="0 0 24 24" width="18px" fill="#FFFFFF"><g><path d="M0,0h24v24H0V0z" fill="none"/></g><g><path d="M17,8l-1.41,1.41L17.17,11H9v2h8.17l-1.58,1.58L17,16l4-4L17,8z M5,5h7V3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h7v-2H5V5z"/></g></svg> \ No newline at end of file diff --git a/website/agenda/planung/image/mic.svg b/website/agenda/planung/image/mic.svg new file mode 100644 index 0000000..f179d8a --- /dev/null +++ b/website/agenda/planung/image/mic.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><g><rect fill="none" height="24" width="24"/><rect fill="none" height="24" width="24"/><rect fill="none" height="24" width="24"/></g><g><g/><g><path d="M12,14c1.66,0,3-1.34,3-3V5c0-1.66-1.34-3-3-3S9,3.34,9,5v6C9,12.66,10.34,14,12,14z"/><path d="M17,11c0,2.76-2.24,5-5,5s-5-2.24-5-5H5c0,3.53,2.61,6.43,6,6.92V21h2v-3.08c3.39-0.49,6-3.39,6-6.92H17z"/></g></g></svg> \ No newline at end of file diff --git a/website/agenda/planung/image/mic_off.svg b/website/agenda/planung/image/mic_off.svg new file mode 100644 index 0000000..137b840 --- /dev/null +++ b/website/agenda/planung/image/mic_off.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M10.8 4.9c0-.66.54-1.2 1.2-1.2s1.2.54 1.2 1.2l-.01 3.91L15 10.6V5c0-1.66-1.34-3-3-3-1.54 0-2.79 1.16-2.96 2.65l1.76 1.76V4.9zM19 11h-1.7c0 .58-.1 1.13-.27 1.64l1.27 1.27c.44-.88.7-1.87.7-2.91zM4.41 2.86L3 4.27l6 6V11c0 1.66 1.34 3 3 3 .23 0 .44-.03.65-.08l1.66 1.66c-.71.33-1.5.52-2.31.52-2.76 0-5.3-2.1-5.3-5.1H5c0 3.41 2.72 6.23 6 6.72V21h2v-3.28c.91-.13 1.77-.45 2.55-.9l4.2 4.2 1.41-1.41L4.41 2.86z"/></svg> \ No newline at end of file diff --git a/website/agenda/planung/image/more.svg b/website/agenda/planung/image/more.svg new file mode 100644 index 0000000..cd51287 --- /dev/null +++ b/website/agenda/planung/image/more.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="18px" viewBox="0 0 24 24" width="18px" fill="#FFFFFF"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/></svg> \ No newline at end of file diff --git a/website/agenda/planung/image/navigate_before.svg b/website/agenda/planung/image/navigate_before.svg new file mode 100644 index 0000000..5943bdf --- /dev/null +++ b/website/agenda/planung/image/navigate_before.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M15.61 7.41L14.2 6l-6 6 6 6 1.41-1.41L11.03 12l4.58-4.59z"/></svg> \ No newline at end of file diff --git a/website/agenda/planung/image/navigate_next.svg b/website/agenda/planung/image/navigate_next.svg new file mode 100644 index 0000000..2b7b602 --- /dev/null +++ b/website/agenda/planung/image/navigate_next.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M10.02 6L8.61 7.41 13.19 12l-4.58 4.59L10.02 18l6-6-6-6z"/></svg> \ No newline at end of file diff --git a/website/agenda/planung/image/no_sync.png b/website/agenda/planung/image/no_sync.png deleted file mode 100644 index 4632b0e..0000000 Binary files a/website/agenda/planung/image/no_sync.png and /dev/null differ diff --git a/website/agenda/planung/image/play-circle.svg b/website/agenda/planung/image/play-circle.svg new file mode 100644 index 0000000..8eae31b --- /dev/null +++ b/website/agenda/planung/image/play-circle.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="18px" viewBox="0 0 24 24" width="18px" fill="#FFFFFF"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 14.5v-9l6 4.5-6 4.5z"/></svg> \ No newline at end of file diff --git a/website/agenda/planung/image/play.svg b/website/agenda/planung/image/play.svg new file mode 100644 index 0000000..1a7780c --- /dev/null +++ b/website/agenda/planung/image/play.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M10 8.64L15.27 12 10 15.36V8.64M8 5v14l11-7L8 5z"/></svg> \ No newline at end of file diff --git a/website/agenda/planung/image/playout.png b/website/agenda/planung/image/playout.png deleted file mode 100644 index 14780c6..0000000 Binary files a/website/agenda/planung/image/playout.png and /dev/null differ diff --git a/website/agenda/planung/image/prepared.svg b/website/agenda/planung/image/prepared.svg new file mode 100644 index 0000000..97a1214 --- /dev/null +++ b/website/agenda/planung/image/prepared.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm4.59-12.42L10 14.17l-2.59-2.58L6 13l4 4 8-8z"/></svg> \ No newline at end of file diff --git a/website/agenda/planung/image/preproduced.png b/website/agenda/planung/image/preproduced.png deleted file mode 100644 index 8903ee4..0000000 Binary files a/website/agenda/planung/image/preproduced.png and /dev/null differ diff --git a/website/agenda/planung/image/preview.svg b/website/agenda/planung/image/preview.svg new file mode 100644 index 0000000..91ddec7 --- /dev/null +++ b/website/agenda/planung/image/preview.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="18px" viewBox="0 0 24 24" width="18px" fill="#FFFFFF"><g><rect fill="none" height="24" width="24"/><path d="M19,3H5C3.89,3,3,3.9,3,5v14c0,1.1,0.89,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.11,3,19,3z M19,19H5V7h14V19z M12,10.5 c1.84,0,3.48,0.96,4.34,2.5c-0.86,1.54-2.5,2.5-4.34,2.5S8.52,14.54,7.66,13C8.52,11.46,10.16,10.5,12,10.5 M12,9 c-2.73,0-5.06,1.66-6,4c0.94,2.34,3.27,4,6,4s5.06-1.66,6-4C17.06,10.66,14.73,9,12,9L12,9z M12,14.5c-0.83,0-1.5-0.67-1.5-1.5 s0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5S12.83,14.5,12,14.5z"/></g></svg> \ No newline at end of file diff --git a/website/agenda/planung/image/processing.svg b/website/agenda/planung/image/processing.svg new file mode 100644 index 0000000..b5a44dd --- /dev/null +++ b/website/agenda/planung/image/processing.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><g><rect fill="none" height="24" width="24"/><path d="M17,12c-2.76,0-5,2.24-5,5s2.24,5,5,5c2.76,0,5-2.24,5-5S19.76,12,17,12z M18.65,19.35l-2.15-2.15V14h1v2.79l1.85,1.85 L18.65,19.35z M18,3h-3.18C14.4,1.84,13.3,1,12,1S9.6,1.84,9.18,3H6C4.9,3,4,3.9,4,5v15c0,1.1,0.9,2,2,2h6.11 c-0.59-0.57-1.07-1.25-1.42-2H6V5h2v3h8V5h2v5.08c0.71,0.1,1.38,0.31,2,0.6V5C20,3.9,19.1,3,18,3z M12,5c-0.55,0-1-0.45-1-1 c0-0.55,0.45-1,1-1c0.55,0,1,0.45,1,1C13,4.55,12.55,5,12,5z"/></g></svg> \ No newline at end of file diff --git a/website/agenda/planung/image/published.png b/website/agenda/planung/image/published.png deleted file mode 100644 index ae75d23..0000000 Binary files a/website/agenda/planung/image/published.png and /dev/null differ diff --git a/website/agenda/planung/image/radio.svg b/website/agenda/planung/image/radio.svg new file mode 100644 index 0000000..c2b319c --- /dev/null +++ b/website/agenda/planung/image/radio.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="18px" viewBox="0 0 24 24" width="18px" fill="#FFFFFF"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M20 6H8.3l8.26-3.34L15.88 1 3.24 6.15C2.51 6.43 2 7.17 2 8v12c0 1.1.89 2 2 2h16c1.11 0 2-.9 2-2V8c0-1.11-.89-2-2-2zm0 2v3h-2V9h-2v2H4V8h16zM4 20v-7h16v7H4z"/><circle cx="8" cy="16.48" r="2.5"/></svg> \ No newline at end of file diff --git a/website/agenda/planung/image/replay.svg b/website/agenda/planung/image/replay.svg new file mode 100644 index 0000000..9a3e3d0 --- /dev/null +++ b/website/agenda/planung/image/replay.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><g><rect fill="none" height="24" width="24"/><rect fill="none" height="24" width="24"/><rect fill="none" height="24" width="24"/></g><g><g/><path d="M12,5V1L7,6l5,5V7c3.31,0,6,2.69,6,6s-2.69,6-6,6s-6-2.69-6-6H4c0,4.42,3.58,8,8,8s8-3.58,8-8S16.42,5,12,5z"/></g></svg> \ No newline at end of file diff --git a/website/agenda/planung/image/rerun.png b/website/agenda/planung/image/rerun.png deleted file mode 100644 index 215dcf5..0000000 Binary files a/website/agenda/planung/image/rerun.png and /dev/null differ diff --git a/website/agenda/planung/image/rule.svg b/website/agenda/planung/image/rule.svg new file mode 100644 index 0000000..3a4b58c --- /dev/null +++ b/website/agenda/planung/image/rule.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="18px" viewBox="0 0 24 24" width="18px" fill="#FFFFFF"><g><rect fill="none" height="24" width="24"/><path d="M16.54,11L13,7.46l1.41-1.41l2.12,2.12l4.24-4.24l1.41,1.41L16.54,11z M11,7H2v2h9V7z M21,13.41L19.59,12L17,14.59 L14.41,12L13,13.41L15.59,16L13,18.59L14.41,20L17,17.41L19.59,20L21,18.59L18.41,16L21,13.41z M11,15H2v2h9V15z"/></g></svg> \ No newline at end of file diff --git a/website/agenda/planung/image/schedule.svg b/website/agenda/planung/image/schedule.svg new file mode 100644 index 0000000..ff11560 --- /dev/null +++ b/website/agenda/planung/image/schedule.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="18px" viewBox="0 0 24 24" width="18px" fill="#FFFFFF"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67z"/></svg> \ No newline at end of file diff --git a/website/agenda/planung/image/settings.svg b/website/agenda/planung/image/settings.svg new file mode 100644 index 0000000..55bfba8 --- /dev/null +++ b/website/agenda/planung/image/settings.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="18px" viewBox="0 0 24 24" width="18px" fill="#FFFFFF"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M19.43 12.98c.04-.32.07-.64.07-.98 0-.34-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.09-.16-.26-.25-.44-.25-.06 0-.12.01-.17.03l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.06-.02-.12-.03-.18-.03-.17 0-.34.09-.43.25l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98 0 .33.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.09.16.26.25.44.25.06 0 .12-.01.17-.03l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.06.02.12.03.18.03.17 0 .34-.09.43-.25l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zm-1.98-1.71c.04.31.05.52.05.73 0 .21-.02.43-.05.73l-.14 1.13.89.7 1.08.84-.7 1.21-1.27-.51-1.04-.42-.9.68c-.43.32-.84.56-1.25.73l-1.06.43-.16 1.13-.2 1.35h-1.4l-.19-1.35-.16-1.13-1.06-.43c-.43-.18-.83-.41-1.23-.71l-.91-.7-1.06.43-1.27.51-.7-1.21 1.08-.84.89-.7-.14-1.13c-.03-.31-.05-.54-.05-.74s.02-.43.05-.73l.14-1.13-.89-.7-1.08-.84.7-1.21 1.27.51 1.04.42.9-.68c.43-.32.84-.56 1.25-.73l1.06-.43.16-1.13.2-1.35h1.39l.19 1.35.16 1.13 1.06.43c.43.18.83.41 1.23.71l.91.7 1.06-.43 1.27-.51.7 1.21-1.07.85-.89.7.14 1.13zM12 8c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 6c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"/></svg> \ No newline at end of file diff --git a/website/agenda/planung/imageUpload.cgi b/website/agenda/planung/imageUpload.cgi deleted file mode 100755 index f30c3d6..0000000 --- a/website/agenda/planung/imageUpload.cgi +++ /dev/null @@ -1,420 +0,0 @@ -#! /usr/bin/perl - -use warnings "all"; -use strict; -use Data::Dumper; - -use Apache2::Request; -use Apache2::Upload; - -delete $INC{CGI}; -require 'CGI.pm'; -use Date::Calc; -use Time::Local; -use Image::Magick; -use Image::Magick::Square; - -use config; -use auth; -use uac; -use studios; -use template; -use images; - -binmode STDOUT, ":utf8"; - -my $r = shift; -my $cgi = undef; - -my $config = config::get('../config/config.cgi'); -our $debug = $config->{system}->{debug}; -my $base_dir = $config->{locations}->{base_dir}; -my $tmp_dir = '/var/tmp'; -my $upload_limit = 2048 * 1000; - -#binmode STDOUT, ":utf8"; -#binmode STDOUT, ":encoding(UTF-8)"; - -my $params = {}; -my $upload = undef; -my $error = ''; - -#get image from multiform before anything else -if ( defined $r ) { - - #Apache2::Request - # print "Content-type:text/html; charset=UTF-8; \n\n<br><br><br>Apache2::Request<br>\n"; - my $apr = Apache2::Request->new( $r, POST_MAX => $upload_limit, TEMP_DIR => $tmp_dir ); - - #copy params to hash - my $body = $apr->body(); - if ( defined $body ) { - for my $key ( keys %$body ) { - - # print "$key=".$apr->param($key)."<br>\n"; - $params->{ scalar($key) } = scalar( $apr->param($key) ); # unless ($key eq'image'); - } - } - - # print Dumper($params); - - # print Dumper($apr); - my $status = $apr->parse; - - # print "Status:$status<br>"; - $status = '' if ( $status =~ /missing input data/i ); - if ( $status =~ /limit/i ) { - $error = $status; - } else { - $upload = $apr->upload('image') if ( defined $params->{image} ); - } - - #dont get params parsed - # $CGI::POST_MAX = $upload_limit; - # $CGI::TMPDIRECTORY=$tmp_dir; - $cgi = new CGI(); - - # my %params=$cgi->Vars(); - # $params=\%params; - # $error=$cgi->cgi_error()||$error; -} else { - - #CGI fallback - # print "Content-type:text/html; charset=UTF-8; \n\n<br><br><br>CGI<br>\n"; - $CGI::POST_MAX = $upload_limit; - $CGI::TMPDIRECTORY = $tmp_dir; - $cgi = new CGI(); - $error = $cgi->cgi_error() || $error; - my %params = $cgi->Vars(); - $params = \%params; -} -print "Content-type:text/html; charset=UTF-8;\n\n"; -my ( $user, $expires ) = auth::get_user( $cgi, $config ); -return if ( ( !defined $user ) || ( $user eq '' ) ); - -my $user_presets = uac::get_user_presets( - $config, - { - user => $user, - project_id => $params->{project_id}, - studio_id => $params->{studio_id} - } -); -$params->{default_studio_id} = $user_presets->{studio_id}; -$params->{studio_id} = $params->{default_studio_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); -$params->{project_id} = $user_presets->{project_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); - -my $request = { - url => $ENV{QUERY_STRING} || '', - params => { - original => $params, - checked => check_params($params), - }, -}; - -$request = uac::prepare_request( $request, $user_presets ); -$params = $request->{params}->{checked}; -return unless defined uac::check( $config, $params, $user_presets ); - -my $permissions = $request->{permissions}; - -$params->{action} = '' unless ( defined $params->{action} ); - -if ( $permissions->{create_image} ne '1' ) { - uac::permissions_denied("create image"); - return 0; -} - -my $file_info = undef; -if ( $error ne '' ) { - if ( $error =~ /limit/ ) { - $params->{error} .= "Image size is limited to " . int( $upload_limit / 1000000 ) . " MB!" . "Please make it smaller and try again!"; - } else { - $params->{error} .= "Error:'$error'"; - } -} elsif ( $params->{action} eq 'upload' ) { - $file_info = upload_file( $config, $cgi, $upload, $user ); - $params->{error} .= $file_info->{error}; - $params = update_database( $config, $params, $file_info, $user ) if ( $params->{error} eq '' ); -} -print STDERR $params->{error} . "\n" if defined $params->{error}; -my $out = ''; -template::process( 'print', $params->{template}, $params ); - -print $cgi->cgi_error() if defined $cgi; - -#return; - -return if ( $params->{action} eq '' ); - -if ( $params->{error} eq '' ) { - print qq{ - <div id="output">success</div> - <div id="message"> - $params->{action_result} - {{thumbs//$params->{filename}}} - <button onclick="selectThisImage('$params->{filename}')">assign to event</button> - </div> - <div id="upload_image_id">$params->{image_id}</div> - <div id="upload_image_filename">$params->{filename}</div> - <div id="upload_image_title">$params->{name}</div> - <div id="upload_image_link">{{thumbs//$params->{filename}}}</div> - - }; -} else { - print qq{ - <div id="output">failed</div> - <div id="message">$params->{error}</div> - }; - -} - -sub upload_file { - my $config = shift; - my $cgi = shift; - my $upload = shift; - my $user = shift; - - my $result = get_filename( $cgi, $upload ); - return $result if ( $result->{error} ne '' ); - - my $file = $result->{fh}; - my $filename = $result->{filename}; - - $result = check_filename($filename); - print STDERR $result . "\n"; - return $result if ( $result->{error} ne '' ); - - my $extension = $result->{extension} || ''; - - #read file from handle - my $data; - my $content = ''; - print STDERR $file . "\n"; - - #unless (-e $file){} - binmode $file; - while ( read $file, $data, 1024 ) { - $content .= $data; - } - - #set filename to MD5 from content - my $md5_filename = Digest::MD5::md5_base64($content); - $md5_filename =~ s/[\/\+]/_/gi; - - return process_image( $config, $filename, $extension, $md5_filename, $content ); -} - -sub update_database { - my $config = shift; - my $params = shift; - my $file_info = shift; - my $user = shift; - - $params->{upload_path} = $file_info->{upload_path}; - $params->{upload_filename} = $file_info->{upload_filename}; - $params->{filename} = $file_info->{filename}; - $params->{thumb_path} = $file_info->{thumb_path}; - $params->{image_path} = $file_info->{image_path}; - $params->{icon_path} = $file_info->{icon_path}; - $params->{local_media_url} = $config->{locations}->{local_media_url}; - - my $name = $params->{name} || ''; - $name = 'neu' unless $params =~ /\S/; - - my $image = { - filename => $params->{filename}, - name => $params->{name} || 'new', - description => $params->{description}, - modified_by => $user, - project_id => $params->{project_id}, - studio_id => $params->{studio_id} - }; - - #connect - $config->{access}->{write} = 1; - my $dbh = db::connect($config); - - my $entries = images::get( $config, { filename => $image->{filename} } ); - if ( ( defined $entries ) && ( @$entries > 0 ) ) { - images::update( $dbh, $image ); - my $entry = $entries->[0]; - $params->{image_id} = $entry->{id}; - } else { - $image->{created_by} = $user; - $params->{image_id} = images::insert( $dbh, $image ); - } - $config->{access}->{write} = 0; - $params->{action_result} = 'done!'; - - return $params; -} - -#get filename and filehandle from upload -sub get_filename { - my $cgi = shift; - my $upload = shift; - - if ( defined $upload ) { - - # try apache2 module - my $filename = $upload->filename(); - return { - filename => $filename, - fh => $upload->fh(), - error => '' - }; - - } - - # fallback to CGI module - my $file = $cgi->param("image"); - if ( $file =~ /\|/ ) { - return { error => "is no file" }; - } - - my $file_info = $cgi->uploadInfo($file); - if ( defined $file_info ) { - my $filename = $file_info->{'Content-Disposition'} || ''; - if ( $filename =~ /filename=\"(.*?)\"/ ) { - $filename = $1; - return { - filename => $filename, - fh => $file, - error => '' - }; - - } - } - - #error - return { error => 'Could not detect file name!' }; -} - -sub check_filename { - my $filename = shift; - - my @valid_extensions = ( 'png', 'jpeg', 'jpg', 'gif', 'pdf', 'txt', 'bmp', 'ps', 'eps', 'wmf' ); - if ( $filename =~ /\.([a-zA-Z]{3,5})$/ ) { - my $extension = lc $1; - unless ( grep( /$extension/, @valid_extensions ) ) { - return { error => 'Following file formats are supported: ' . join( ",", @valid_extensions ) . '!' }; - } - return { - extension => $extension, - error => '' - }; - } else { - return { error => 'Not matching file extension found! Supported are: ' . join( ",", @valid_extensions ) . '!' }; - } -} - -sub process_image { - my $config = shift; - my $filename = shift; - my $extension = shift; - my $md5_filename = shift; - my $content = shift; - - my $upload_path = $config->{locations}->{local_media_dir} . 'upload/' . $md5_filename . '.' . $extension; - my $thumb_path = $config->{locations}->{local_media_dir} . 'thumbs/' . $md5_filename . '.jpg'; - my $icon_path = $config->{locations}->{local_media_dir} . 'icons/' . $md5_filename . '.jpg'; - my $image_path = $config->{locations}->{local_media_dir} . 'images/' . $md5_filename . '.jpg'; - - #copy file to upload space - open DAT, '>' . $upload_path or return { error => 'could not save image. ' . $! . " $upload_path" }; - binmode DAT; - print DAT $content; - close DAT; - - #write image - my $image = new Image::Magick; - $image->Read($upload_path); - my $x = $image->Get('width') || 0; - my $y = $image->Get('height') || 0; - if ( ( $x == 0 ) || ( $y == 0 ) ) { - return { error => 'Could not read image!' }; - log::error( $config, 'Cannot read image $filename!' ); - } - - #set max size image - if ( $x > 0 && $y > 0 ) { - if ( $x > $y ) { - $image->Resize( width => '600', height => int( 600 * $y / $x ) ); - } else { - $image->Resize( width => int( 600 * $x / $y ), height => '600' ); - } - } - - #$image->Normalize(); - $image->Write( 'jpg:' . $image_path ); - - #write thumb - my $thumb = $image; - $thumb->Trim2Square; - $thumb->Resize( width => 150, height => 150 ); - $thumb->Write( 'jpg:' . $thumb_path ); - - my $icon = $image; - $icon->Trim2Square; - $icon->Resize( width => 25, height => 25 ); - $icon->Write( 'jpg:' . $icon_path ); - - unless ( -e $thumb_path ) { - return { error => 'could not create thumb nail file!' }; - } - unless ( -e $icon_path ) { - return { error => 'could not create icon file!' }; - } - unless ( -e $image_path ) { - return { error => 'could not create image file!' }; - } - - return { - upload_filename => $filename, - - filename => $md5_filename . '.jpg', - thumb_path => $thumb_path, - icon_path => $icon_path, - image_path => $image_path, - - error => '' - }; -} - -sub check_params { - my $params = shift; - - my $checked = {}; - $checked->{template} = template::check( $params->{template}, 'imageUpload' ); - - #numeric values - for my $param ( 'project_id', 'studio_id', 'default_studio_id' ) { - if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /^\d+$/ ) ) { - $checked->{$param} = $params->{$param}; - } - } - if ( defined $checked->{studio_id} ) { - $checked->{default_studio_id} = $checked->{studio_id}; - } else { - $checked->{studio_id} = -1; - } - - #string - for my $param ( 'debug', 'name', 'description' ) { - if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /^\s*(.+?)\s*$/ ) ) { - $checked->{$param} = $1; - } - } - - #Words - for my $attr ('action') { - if ( ( defined $params->{$attr} ) && ( $params->{$attr} =~ /(\S+)/ ) ) { - $checked->{$attr} = $params->{$attr}; - } - } - return $checked; -} - diff --git a/website/agenda/planung/images/ui-bg_flat_75_ffffff_40x100.png b/website/agenda/planung/images/ui-bg_flat_75_ffffff_40x100.png deleted file mode 100644 index d104ec9..0000000 Binary files a/website/agenda/planung/images/ui-bg_flat_75_ffffff_40x100.png and /dev/null differ diff --git a/website/agenda/planung/js/archive.js b/website/agenda/planung/js/archive.js index 8d41ebe..ec6040f 100644 --- a/website/agenda/planung/js/archive.js +++ b/website/agenda/planung/js/archive.js @@ -1,15 +1,14 @@ function download(id, name){ - //alert(id +" "+ name); - $.getJSON( - 'archive.cgi?get_link='+name, - function(data){ - //alert(data); - $.each(data, - function(key, val) { - $('#'+id).html(val); - } - ); - } - ); -} - + //alert(id +" "+ name); + $.getJSON( + 'archive.cgi?get_link='+name, + function(data){ + //alert(data); + $.each(data, + function(key, val) { + $('#'+id).html(val); + } + ); + } + ); +} \ No newline at end of file diff --git a/website/agenda/planung/js/audio-recordings.js b/website/agenda/planung/js/audio-recordings.js new file mode 100644 index 0000000..f925e0d --- /dev/null +++ b/website/agenda/planung/js/audio-recordings.js @@ -0,0 +1,157 @@ + +function showProgress(){ + $('#progress').slideDown(); + return false; +} + +function hideProgress(){ + $('#progress').slideUp(); + return false; +} + +function playAudio(path){ + var url='recordings/'+path; + var win = window.open(url, '_blank'); +} + +function changeFile(fileInput){ + var file = fileInput.files[0]; + var size = file.size / (1000*1000); + $('#uploadSize').html(size + " MB"); + if (size > 700){ + $('#uploadButton').hide(); + showError("file is too large. maximum size is 700 MB!"); + }else{ + $('#uploadButton').show(); + $('#uploadButton').focus(); + } +} + +function showError(error){ + $('#error').html(error); + $('#error').show(); +} + +function hideError(){ + $('#error').hide(); +} + +function showFinished(){ + $('#info').html("upload finished"); + $('#info').show(); +} + +function hideFinished(){ + $('#info').hide(); +} + +function roundSize(size){ + const MB = 1000*1000; + var value= Math.round(size/MB); + value += ''; + //if (value.indexOf('.')<0)value+='.0'; + return value; +} + +function formatTime(duration){ + if (duration > 3600) return Math.ceil(duration/3600) + " hours"; + if (duration > 60) return Math.ceil(duration/60) + " minutes"; + return duration += " seconds"; +} + +function uploadFile(uploadButton){ + hideFinished(); + hideError(); + showProgress(); + var request=$.ajax({ + url: 'audio-recordings.cgi', + type: 'POST', + data: new FormData($('#audio_recordings_upload')[0]), + cache: false, + contentType: false, + processData: false, + xhr: function() { + var start = Math.floor(Date.now()/1000); + var update = start; + var xhr = new window.XMLHttpRequest(); + $('#uploadButton').hide(); + if (xhr.upload) { + $('#progress_done').html(0); + $('#progress_todo').html(100); + $('#progress_done').css("width", 0 + "%") + $('#progress_todo').css("width", (100)+ "%") + $('#progress_container').show(); + + xhr.upload.addEventListener( + 'progress', + function(data) { + if (!data.lengthComputable) return; + let now = Math.floor(Date.now()/1000); + if (now == update) return; + update = now; + + let loaded = roundSize(data.loaded); + if (loaded == 0) return; + let total = roundSize(data.total); + let duration = now - start; + if (duration == 0) return; + let remaining = Math.round( (duration * data.total / data.loaded) - duration ); + remaining = formatTime(remaining); + duration = formatTime(duration); + + var perc = Math.round(100*loaded/total); + $('#progress_done').css("width", perc + "%") + $('#progress_todo').css("width", (100-perc)+ "%") + $('#progress_done').html(loaded + " MB"); + $('#progress_todo').html(remaining+" left"); + + let content = total + " MB<br>"; + $('#progressLabel').html(content); + } , + false + ); + } + return xhr; + } + }); + + request.fail( + function(jqXHR, textStatus, errorThrown ){ + showError("error: "+errorThrown); + hideProgress(); + hideFinished(); + $('#uploadButton').show(); + } + ); + + request.done( + function(data){ + showFinished(); + hideProgress(); + hideError(); + $('#uploadButton').show(); + } + ); +} + + +$( document ).ready( + function() { + $('#file').on( 'change', + function(){ + changeFile( this ); + return false; + } + ); + + $('#uploadButton').on( 'click', + function(){ + uploadFile( this ); + return false; + } + ); + + var number = 1+Math.floor(11 * Math.random()); + $('#progress img').attr("src", "/agenda/planung/image/upload/bird"+number+".gif"); + } +); diff --git a/website/agenda/planung/js/audio_recordings.js b/website/agenda/planung/js/audio_recordings.js deleted file mode 100644 index 5d75555..0000000 --- a/website/agenda/planung/js/audio_recordings.js +++ /dev/null @@ -1,127 +0,0 @@ - -function showProgress(){ - $('#progress').slideDown(); - return false; -} - -function hideProgress(){ - $('#progress').slideUp(); - return false; -} - -function playAudio(path){ - var url='../../agenda_files/recordings/'+path; - var win = window.open(url, '_blank'); -} - -function changeFile(fileInput){ - var file = fileInput.files[0]; - var size = file.size / (1000*1000); - $('#uploadSize').html(size + " MB"); - if (size > 200){ - $('#uploadButton').hide(); - showError("file is too large. maximum size is 200 MB! Please use MP3, 192 kHz, CBR, 44100 Hz, 16bit"); - }else{ - $('#uploadButton').show(); - } -} - -function showError(error){ - $('#error').html(error); - $('#error').show(); -} - -function hideError(){ - $('#error').hide(); -} - -function showFinished(){ - $('#info').html("upload finished"); - $('#info').show(); -} - -function hideFinished(){ - $('#info').hide(); -} - -function roundSize(size){ - var MB=1000*1000; - return Math.round(size*10/MB)/10; -} - -function uploadFile(uploadButton){ - hideFinished(); - hideError(); - showProgress(); - $.ajax({ - url: 'audio_recordings.cgi', - type: 'POST', - data: new FormData($('#audio_recordings_upload')[0]), - cache: false, - contentType: false, - processData: false, - xhr: function() { - var start = new Date(); - var myXhr = $.ajaxSettings.xhr(); - if (myXhr.upload) { - myXhr.upload.addEventListener( - 'progress', - function(data) { - if (data.lengthComputable) { - var loaded=roundSize(data.loaded); - var total=roundSize(data.total); - $('#progressBar').attr("value", loaded); - $('#progressBar').attr("max", total); - var duration=(new Date().getTime() - start.getTime()) / 1000 ; - var bitrate = loaded / duration; - var remaining = Math.round(100 * bitrate * ( total - loaded) ); - var content = loaded + " of " + total + " MB<br>"; - content += '<div class="thin">'; - content += "finished in " + remaining + " seconds<br>"; - content += "took " + Math.round(duration) + " seconds<br>"; - content += '</div>' - $('#progressLabel').html(content); - } - } , - false - ); - } - return myXhr; - }, - }).error( - function(jqXHR, textStatus, errorThrown ){ - showError("error: "+errorThrown); - hideProgress(); - hideFinished(); - } - ).done( - function(data){ - showFinished(); - hideProgress(); - hideError(); - //setTimeout(function() { location.reload() }, 1000); - } - ); -} - - -$( document ).ready( - function() { - $('#file').on( 'change', - function(){ - changeFile( this ); - return false; - } - ); - - $('#uploadButton').on( 'click', - function(){ - uploadFile( this ); - return false; - } - ); - - var number = 1+Math.floor(11 * Math.random()); - $('#progress img').attr("src", "/agenda/image/upload/bird"+number+".gif"); - } -); diff --git a/website/agenda/planung/js/calendar.js b/website/agenda/planung/js/calendar.js index b5ccfd2..9688718 100644 --- a/website/agenda/planung/js/calendar.js +++ b/website/agenda/planung/js/calendar.js @@ -8,9 +8,6 @@ function openNewTab(url){ window.open(url, '_blank'); } -var effect=null; -var effect_duration=null; - function selectCheckbox(selector){ $(selector).each(function(){ $(this).prop('checked', 'checked'); @@ -28,89 +25,68 @@ function isChecked(selector){ } function cancel_edit_event(){ - $('#calendar').show(effect,null,effect_duration); - $('#calendar_weekdays').show(effect,null,effect_duration); - $('#event_editor').hide(effect,null,effect_duration); - resizeCalendarMenu(); - return false; + $('#calendar').show(); + $('#calendar_weekdays').show(); + $('#event_editor').hide(); + resizeCalendarMenu(); + return false; } function setupMenuHeight(){ if ($('#calendar').length>0){ - // calendar table - console.log('setupMenuHeight') - var top=$('#calcms_admin_menu').height(); + var top=$('#calcms_nav').height(); $('#toolbar').css("top", top); $('#toolbar').css("position", "absolute"); top+=$('#toolbar').height()+2; + var weekdays = document.querySelector("#calendar_weekdays"); $('#calendar_weekdays').css("top", top); + var weekday_height=30; - $('#calendar_weekdays table td div').each( - function(){ - var height=$(this).height()+14; + weekdays.querySelectorAll("table td div").forEach( + function(div) { + var height = div.offsetHeight + 14; if (height>weekday_height) weekday_height=height; - //console.log(weekday_height+" "+height); - } + } ); - //console.log(weekday_height) - top+=weekday_height+1; - + + top+=weekday_height+1-10; $('#calendar').css("top", top); - return top; - } else { - // calendar list - //console.log('found calendar list') - - var top = $('#calcms_admin_menu').height(); + var top = $('#calcms_nav').height(); $('#content').css("top", top); - - top = $('#calcms_admin_menu').height(); - $('#content').css("top", top); - return top; } } -function hideCalendar(){ - $('#calendar').css("display","none"); - $('#calendar_weekdays').css("visibility","hidden"); -} - -function showCalendar(){ - $('#calendar').show(); - $('#calendar_weekdays').css("visibility","visible"); -} - function resizeCalendarMenu(){ - hideCalendar(); + $('#calendar').hide(); + $('#calendar_weekdays').css("visibility","hidden"); //after getting menu heigth, hide calendar again - var menuHeight=setupMenuHeight(); + var menuHeight = setupMenuHeight(); - var width= $(window).width()-0; - var height= $(window).height()-menuHeight; + var width = $(window).width()-0; + var height = $(window).height()-menuHeight; - if($('#calendar').css('display')=='none'){ - $('body #content').css('max-width', '960'); - }else{ - $('body #content').css('max-width', width); - } - $('div#calendar').css('width', width); - $('div#calendar_weekdays').css('width', width); - $('div#calendar').css('height', height); + if($('#calendar').css('display')=='none'){ + $('body #content').css('max-width', '960'); + }else{ + $('body #content').css('max-width', width); + } + $('div#calendar').css('width', width); + $('div#calendar_weekdays').css('width', width); + $('div#calendar').css('height', height); // remove border for scroll - $('#calendar table').css('width', width-20); - $('#calendar_weekdays table').css('width', width-20); - $('#calendar table').css('height', height); - + $('#calendar table').css('width', width-20); + $('#calendar_weekdays table').css('width', width-20); + $('#calendar table').css('height', height); + //set spacing between table columns var columnSpacing=Math.round($(window).width()/72); - //if(columnSpacing>16)columnSpacing=16; if(columnSpacing<0) columnSpacing=0; columnSpacing=Math.ceil(columnSpacing); @@ -118,45 +94,24 @@ function resizeCalendarMenu(){ $('div.week').css('margin-left',-columnSpacing); //calculate cell-width - var cell_width=(width-100)/(days-1); + var cell_width=(width-100)/(days-1); if($(window).width()<720){ $('#calendar td.week').hide(); - cell_width=(width-100)/(days)-4; - //$('#calendar div.text').css('padding-right','0'); + cell_width=(width-100)/(days)-4; }else{ $('#calendar td.week').show(); - cell_width=(width-100)/(days)-columnSpacing; - //$('#calendar div.text').css('padding-right','16px'); + cell_width=(width-100)/(days)-columnSpacing; } var with_param='width'; var cw=cell_width.toFixed(); - - /* - $('#calendar div.work').css(with_param, cw); - $('#calendar div.play').css(with_param, cw); - $('#calendar div.grid').css(with_param, cw); - $('#calendar div.event').css(with_param, cw); - $('#calendar div.schedule').css(with_param, cw); - $('#calendar div.date').css(with_param, cw); - $('#calendar_weekdays div.date').css(with_param, cw); - $('#calendar div.time').css(with_param, cw); - $('#calendar_weekdays div.time').css(with_param, cw); - */ + menuHeight = setupMenuHeight(); - //now - //$('#calendar div.time.now').css(with_param, '100%'); + //var theight=$('#calendar table tr').last().find('td').first().find('div').last().css("top") + //$('td.week').css("height",theight) - //collisions - /* - $('#calendar div.event.error').css( with_param, cw/2.2); - $('#calendar div.schedule.error').css(with_param, cw/2.2); - - //shift right - $('#calendar div.event.error.x2').css( 'margin-left', cw/2+6); - $('#calendar div.schedule.error.x2').css('margin-left', cw/2+6); - */ - showCalendar(); + $('#calendar').show(); + $('#calendar_weekdays').css("visibility","visible"); } @@ -174,10 +129,6 @@ function setFilter(){ } }); } - - //var url=updateUrlParameters(window.location.href); - //url=setUrlParameter(url,'filter',filter); - //updateUrls(url); } // preselect options in select boxes @@ -242,6 +193,12 @@ function updateUrlParameters(url){ url=setUrlParameter(url, 'p', 0); } + if(isChecked('#show_descriptions')){ + url=setUrlParameter(url, 'd', 1); + }else{ + url=setUrlParameter(url, 'd', 0); + } + var filter=$('#filter').val(); if(filter!='no markup') url=setUrlParameter(url, 'filter', $filter); @@ -288,6 +245,14 @@ function show_playout(){ } } +function show_descriptions(){ + if(isChecked('#show_descriptions')){ + $('#calendar .excerpt').css("display",''); + }else{ + $('#calendar .excerpt').css("display",'none'); + } +} + //get date and time from column and row to select a timeslot function getNearestDatetime(){ var date="test"; @@ -320,7 +285,7 @@ function getNearestDatetime(){ var distance=Math.abs(delta); if (distance<yMin){ yMin=delta; - hour= $(this).attr('date'); + hour= $(this).attr('time'); minute='30'; if(delta<0) minute='00'; } @@ -328,12 +293,9 @@ function getNearestDatetime(){ ); //add a day, if time < startOfDay - //console.log(date+" "+hour+" "+minute+" "+startOfDay) if(hour<startOfDay){ date=addDays(date,1); - //console.log("+1: "+date) date=formatDate(date); - //alert(date) } var minute=0; @@ -346,18 +308,16 @@ function getNearestDatetime(){ var distance=Math.abs(delta); if (distance<yMin){ yMin=delta; - hour= $(this).attr('date'); + hour= $(this).attr('time'); var height=$(this).height()+14; var m=((delta+height*1.5)-8) % height; m=m*60/height; minute=Math.floor(m/5)*5; if (minute<10)minute='0'+minute; - //minute='30'; - //if(delta<0) minute='00'; } } ); - return date+" "+hour+":"+minute+ " "; + return date+" "+hour+":"+minute+ ":00"; } var mouseX=0; @@ -395,95 +355,52 @@ function showMouse(){ function checkStudio(){ if($('#studio_id').val()=='-1'){ - $("#no_studio_selected").dialog({ - modal: true, - title: "please select a studio", - }); + showDialog({ title: "please select a studio" }); return 0; } return 1; } -function setIcons(){ - var img=''; - - img='<img class="img_live" src="image/live.png" title="live">' - $('#calendar div.event.live.no_rerun div.icons').append(img); - - img='<img class="img_preproduced" src="image/preproduced.png" title="preproduced">' - $('#calendar div.event.preproduced.no_rerun div.icons').append(img); - - img='<img class="img_rerun" src="image/rerun.png" title="rerun">' - $('#calendar div.event.rerun div.icons').append(img); - - img='<img class="img_playout" src="image/playout.png" title="playout">' - $('#calendar div.event.playout div.icons').append(img); - - img='<img class="img_archived" src="image/archived.png" title="archived">' - $('#calendar div.event.archived div.icons').append(img); -} - function show_not_assigned_to_series_dialog(){ - $("#event_no_series").dialog({ - resizable: false, - width:800, - height:340, - modal: true, - title: loc['label_event_not_assigned_to_series'], - buttons: { - Cancel: function() { - $( this ).dialog( "close" ); - } + showDialog({ + title : loc['label_event_not_assigned_to_series'], + buttons : { + Cancel : function() { $(this).parent().remove(); } } }); } function show_schedule_series_dialog(project_id, studio_id, series_id, start_date){ - $("#series").dialog({ - resizable: false, - width:800, - height:340, - modal: true, - title: loc['label_schedule_series'], - buttons: { + showDialog({ + title : loc['label_schedule_series'], + content : $('#series').html(), + width : "50rem", + height : "15rem", + buttons : { "Schedule": function() { - //add schedule - var series_id=$('#series_select').val(); - var duration=$('#series_duration').val(); - var start_date=$('#series_date').val(); - //var url='event.cgi?action=show_new_event_from_schedule&studio_id='+studio_id+'&series_id='+series_id+'&start_date='+start_date; + var series_id = $('#dialog #series_select').val(); + var duration = $('#dialog #series_duration').val(); + var start_date = $('#dialog #series_date').val(); var url='series.cgi?project_id='+project_id+'&studio_id='+studio_id+'&series_id='+series_id+'&start='+escape(start_date)+'&duration='+duration+'&show_hint_to_add_schedule=1#tabs-schedule'; - //alert(url); load(url); }, - "Cancel" : function() { - $( this ).dialog( "close" ); - } + Cancel : function() { $(this).parent().remove(); } } }); + showDateTimePicker('#dialog #series_date'); } function setDatePicker(){ - - initRegions(region); - - registerDatePicker( - '#start_date', { - //showOn: "button", - //buttonImageOnly: true, - //buttonImage: "image/calendar.png", - //buttonText: "cal", - showWeek: true, - onSelect : function(dateText, inst) { - var url=setUrlParameter(window.location.href,'date',dateText); - loadCalendar(url); - } + var datePicker=showDatePicker('#selectDate', { + wrap:true, + onSelect : function(dates, inst) { + var date = dates[0]; + var url = setUrlParameter(window.location.href, 'date', formatDate(date)); + loadCalendar(url); } - ); - - var date=getUrlParameter("date"); - //console.log("set date: "+date); - $('#start_date').datepicker("setDate", date); + }); + datePicker.setDate(parseDateTime(getUrlParameter("date"))); + $('#selectDate').on('click', () => datePicker.toggle() ); } // add name=value to current url @@ -496,11 +413,20 @@ function getUrl(name,value){ return url; } +function updateDayStart(){ + var url = "set-user-day-start.cgi?"; + url += "&project_id=" + getProjectId(); + url += "&studio_id=" + getStudioId(); + url += "&day_start=" + $('#day_start').val(); + console.log(url); + $.get(url); +} + // to be called from elements directly function reloadCalendar(){ var url=window.location.href; url=updateUrlParameters(url); - loadCalendar(url); + loadCalendar(url); } function initTodayButton(){ @@ -518,51 +444,43 @@ function initTodayButton(){ return true; } -function initSelectDate(){ - $('#selectDate').on('click', function(){ - if($('#ui-datepicker-div').css("display")=="block"){ - $('#start_date').datepicker("hide"); - }else{ - $('#start_date').datepicker("show"); - } - }); +function getSwitch(id, text, active, klass){ + if (active) active = 'checked="checked"'; + var html=''; + html += '<div class="switch '+klass+'">' + html += '<label>' + html += text + html += '<input id="'+id+'" type="checkbox" '+active+'>' + html += '<span class="lever"></span>' + html += '</label>' + html += '</div>' + return html; } function initCalendarMenu(){ //add filters to header - //var html='<div style="white-space: nowrap;">'; var html=''; - html += '<div><input id="show_events" type="checkbox" checked="checked">'+label_events+'</div>'; - html += '<div><input id="show_schedule" type="checkbox" checked="checked">'+label_schedule+'</div>'; - html += '<div><input id="show_playout" type="checkbox" checked="checked">'+label_playout+'</div>'; - html += '<div><input id="show_worktime" type="checkbox" >'+label_worktime+'</div>'; - //html += '</div>'; + html += getSwitch('show_events', label_events || "label", true); + html += getSwitch('show_schedule', label_schedule || "schedule", true); + html += getSwitch('show_playout', label_playout || "playout", true); + html += getSwitch('show_descriptions', label_descriptions || "descriptions", false); + html += getSwitch('show_worktime', label_worktime || "worktime", false); + html += getSwitch('pin', label_pin || "label", false, 'right'); $('#toolbar').append(html); if(getUrlParameter('s')=='0') unselectCheckbox('#show_schedule'); if(getUrlParameter('e')=='0') unselectCheckbox('#show_events' ); if(getUrlParameter('p')=='0') unselectCheckbox('#show_playout' ); if(getUrlParameter('w')=='0') unselectCheckbox('#show_worktime'); + if(getUrlParameter('d')=='0') unselectCheckbox('#show_descriptions'); setSelectedOptions(); setFilter(); setDatePicker(); initTodayButton(); - initSelectDate(); resizeCalendarMenu(); } -$(document).ready(function(){ - // $('#calendar').hide(); - initCalendarMenu(); - - if(calendarTable==1){ - loadCalendar(); - }else{ - loadCalendarList(); - } -}); - function createId(prefix) { function s4() { return Math.floor((1 + Math.random()) * 0x10000) @@ -572,13 +490,15 @@ function createId(prefix) { return prefix+'_'+s4() + s4(); } -function showRmsPlot(id){ - $('#'+id).dialog({ +function showRmsPlot(id, project_id, studio_id, start, elem){ + showDialog({ width:940, - height:400, - open: function () { - $(this).scrollTop(0); - } + height:560, + content: elem.html(), + buttons: { + Close : function() { $(this).parent().remove(); } + }, + onOpen: function () { $(this).scrollTop(0); } }); return false; } @@ -589,15 +509,7 @@ function deleteFromPlayout(id, projectId, studioId, start){ url+='&project_id='+escape(projectId); url+='&studio_id='+escape(studioId); url+='&start_date='+escape(start); - //console.log(url); - $('#'+id).dialog({ - width:940, - height:440, - open: function () { - $(this).scrollTop(0); - $(this).load(url); - } - }); + $('#'+id).load(url); return false; } @@ -608,44 +520,43 @@ function quoteAttr(attr){ function initRmsPlot(){ $( "#calendar div.play" ).hover( function() { - var plot=$(this).attr("rms"); - - var id=$(this).attr("id"); - var field=id.split('_'); - var classname =field.shift(); - var project_id =field.shift(); - var studio_id =field.shift(); - var start=$(this).attr("start") - var html=''; + var plot = $(this).attr("rms"); + var id = $(this).attr("id"); + var field = id.split('_'); + var classname = field.shift(); + var project_id = field.shift(); + var studio_id = field.shift(); + var start = $(this).attr("start") if (project_id==null) return; if (studio_id==null) return; if (start==null) return; + if ( !$(this).hasClass("clickHandler") ){ + $(this).addClass("clickHandler"); + $(this).click( function(event){ + event.stopImmediatePropagation(); + showRmsPlot( id , project_id , studio_id , start, $(this) ); + }); + } + if ( (!$(this).hasClass("rms_image")) && (plot!=null)){ $(this).addClass("rms_image"); - var id=createId("rms_img"); - var url = '/agenda_files/playout/'+plot; - var handler = 'onclick="showRmsPlot('+quoteAttr(id)+')"'; - var img = '<img src="'+url+'" '+handler+'></img>'; - - html += '<button '+handler+'>details</button>'; - html += img; - html += '<div id="'+id+'" class="rms_detail" style="display:none">'; - html += '<div class="image">'+img+'</div>'; - html += '<div class="text">'+$(this).html()+'</div>'; - html += "</div>"; - } - - if (!$(this).hasClass("deleteHandler")){ - $(this).addClass("deleteHandler"); + var content = $(this).html(); + var id = createId("rms_img"); + var url = '/media/playout/'+plot; + var img = '<img src="'+url+'" ></img>'; var deleteHandler = 'onclick="deleteFromPlayout(' + quoteAttr(id) + ", " + quoteAttr(project_id) + ", " + quoteAttr(studio_id) + ", "+ quoteAttr(start) + ')"'; - if (start!=null) html += '<button '+deleteHandler+'>delete</button>'; - } - $(this).append(html); - + var details=''; + details += '<div id="'+id+'" class="rms_detail" style="display:none">'; + details += '<div class="image">'+img+'</div>'; + details += '<div class="text">'+content+'</div>'; + if (start!=null) details += '<button '+deleteHandler+'>delete</button>'; + details += "</div>"; + $(this).append(img + details); + } $(this).find('img').each(function(){ $(this).show(); @@ -683,13 +594,28 @@ function loadCalendar(url, mouseButton){ url=updateUrlParameters(url); } url=setUrlParameter(url, 'part', '1'); - updateContainer('calendarTable', url, function(){ - updateTable(); - $('#calendarTable').css('opacity','1.0'); - $('#current_date').html(current_date); - updateUrls(url); - initRmsPlot(); - }); + updateContainer('calendarTable', url, function(){ + updateTable(); + $('#calendarTable').css('opacity','1.0'); + $('#current_date').html(current_date); + updateUrls(url); + initRmsPlot(); + adjustColors(); + }); +} + +function getMouseOverText(elem){ + if (elem.attr('title')!=null) return elem.attr('title'); + if (elem.hasClass('event') || elem.parent().hasClass('event')) + return 'click to edit show' + if (elem.hasClass('schedule') || elem.parent().hasClass('schedule')) + return 'click to create show' + if (elem.hasClass('no_series') || elem.parent().hasClass('no_series')) + return 'please create a series for this show' + if (elem.hasClass('work') || elem.parent().hasClass('work')) + return 'edit work schedule' + if (elem.hasClass('grid') || elem.parent().hasClass('grid')) + return 'click to create schedule' } function updateTable(){ @@ -721,17 +647,17 @@ function updateTable(){ baseElement='#calendar'; resizeCalendarMenu(); - //$('body').css('background','#eee'); - - $(window).resize(function() { - resizeCalendarMenu(); - }); + $(window).resize(function() { + resizeCalendarMenu(); + setupMenu() + }); } show_schedule(); show_events(); show_playout(); show_worktime(); + show_descriptions(); $('#show_events').off(); $('#show_events').on("click", @@ -754,6 +680,13 @@ function updateTable(){ updateUrls(); } ); + $('#show_descriptions').off(); + $('#show_descriptions').on("click", + function(){ + show_descriptions(); + updateUrls(); + } + ); $('#show_worktime').off(); $('#show_worktime').on("click", function(){ @@ -777,8 +710,8 @@ function updateTable(){ //disable context menu document.oncontextmenu = function() {return false;}; - //edit existing event - $(baseElement).off(); + //edit existing event + $(baseElement).off(); $(baseElement).on("mousedown", ".event", function(event){ handleEvent($(this).attr("id"), event); }); @@ -789,8 +722,7 @@ function updateTable(){ }); $(baseElement).on("mousedown", ".schedule", function(event){ - if ( $('.ui-draggable-dragging').length>0 ) return; - handleSchedule($(this).attr("id"), $(this).attr("date"), event); + handleSchedule($(this).attr("id"), $(this).attr("start"), event); }); //create schedule within studio timeslots @@ -805,33 +737,10 @@ function updateTable(){ //add tooltips - $('#calendarTable').tooltip({ - items:'td div,img', - show: { - effect: "none", - delay: 500 - }, - hide: { - effect: "none", - delay: 500 - }, - close: function(){ - $('.ui-helper-hidden-accessible').children().first().remove(); - }, - content: function(){ - var elem=$(this); - if (elem.attr('title')!=null) return elem.attr('title'); - if (elem.hasClass('event') || elem.parent().hasClass('event')) - return 'click to edit show' - if (elem.hasClass('schedule') || elem.parent().hasClass('schedule')) - return 'click to create show' - if (elem.hasClass('no_series') || elem.parent().hasClass('no_series')) - return 'please create a series for this show' - if (elem.hasClass('work') || elem.parent().hasClass('work')) - return 'edit work schedule' - if (elem.hasClass('grid') || elem.parent().hasClass('grid')) - return 'click to create schedule' - } + $('#calendar > table > tbody > tr > td > div').mouseover( function(){ + var text = getMouseOverText($(this)); + if ($(this).attr("title") == text) return; + $(this).attr("title",text); }); if($('#event_list table').length!=0){ @@ -845,114 +754,55 @@ function updateTable(){ function(){ // get first event_list item var id = $('#event_list tbody tr').first().attr('id'); - //console.log(id); - var field=id.split('_'); - var classname =field.shift(); - var project_id =field.shift(); - var studio_id =field.shift(); - var series_id =field.shift(); - var url='series.cgi'; - url+='?project_id='+project_id; - url+='&studio_id='+studio_id; - url+='&series_id='+series_id; - url+='&action=show'; + var field=id.split('_'); + var classname =field.shift(); + var project_id =field.shift(); + var studio_id =field.shift(); + var series_id =field.shift(); + var url='series.cgi'; + url+='?project_id='+project_id; + url+='&studio_id='+studio_id; + url+='&series_id='+series_id; + url+='&action=show'; load(url); } ); + $('input#pin').off(); + $('input#pin').on( "click", function(){ + var button = $(this); + var elem = $('#content #calendar').first(); + if ( button.hasClass("pressed") ){ + button.removeClass("pressed"); + elem.removeClass("pin"); + } else { + button.addClass("pressed"); + elem.addClass("pin"); + } + }); + //set checkboxes from url parameters and update all urls - setIcons(); $('#calendar').show(); showMouse(); - - //move schedules - //addDraggable(); - -} - -function addDraggable(){ - var height=$('#calendar div.time').first().outerHeight()/12; - - $("#calendar div.schedule").draggable({ - containment: "parent", - axis: "y", - grid: [height, height], - cursorAt: { top: 0 }, - drag: function(){ - //$(this).attr("title", $("#position").text()); - $(this).parent().children(".schedule").each( - function(key, value){ - if ( isColliding($(this)) == true ){ - $(this).addClass("error"); - $(this).addClass("x2"); - }else{ - $(this).removeClass("error"); - $(this).addClass("x2"); - } - } - ); - }, - stop: function() { - console.log("move to "+$("#position").text()); - } - }); - -} - -var dragged=null; -function isColliding(div){ - dragged=div; - var intersect=false; - div.parent().children(".schedule").each( - function(key, value){ - //console.log("isColliding"); - //console.log(dragged); - //console.log($(this)); - if (dragged.is($(this))) { - return; - } - if (collision(dragged, $(this))==true){ - intersect=true; - } - //console.log(intersect); - } - ); - return intersect; -} - -function collision(div1, div2) { - var y1 = div1.offset().top; - var h1 = div1.outerHeight(true); - var b1 = y1 + h1; - - var y2 = div2.offset().top; - var h2 = div2.outerHeight(true); - var b2 = y2 + h2; - - var tolerate=6; - if (b1 - tolerate < y2) return false; - if (b2 - tolerate < y1) return false; - return true; } function handleEvent(id, event){ - var field=id.split('_'); - var classname =field.shift(); - var project_id =field.shift(); - var studio_id =field.shift(); - var series_id =field.shift(); - var event_id =field.shift(); + var field=id.split('_'); + var classname =field.shift(); + var project_id =field.shift(); + var studio_id =field.shift(); + var series_id =field.shift(); + var event_id =field.shift(); - //if(checkStudio()==0)return; if (project_id<0) {alert("please select a project");return;} if (studio_id <0) {alert("please select a studio");return;} - if (series_id <0) return; - if (event_id <0) return; + if (series_id <0) return; + if (event_id <0) return; - var url="event.cgi?action=edit&project_id="+project_id+"&studio_id="+studio_id+"&series_id="+series_id+"&event_id="+event_id; + var url="event.cgi?action=edit&project_id="+project_id+"&studio_id="+studio_id+"&series_id="+series_id+"&event_id="+event_id; if(event.which==1){ - load(url); + load(url); } if(event.which==2){ openNewTab(url); @@ -960,18 +810,17 @@ function handleEvent(id, event){ } function handleUnassignedEvent(id){ - var field=id.split('_'); - var classname =field.shift(); - var project_id =field.shift(); - var studio_id =field.shift(); - var series_id =field.shift(); - var event_id =field.shift(); + var field=id.split('_'); + var classname =field.shift(); + var project_id =field.shift(); + var studio_id =field.shift(); + var series_id =field.shift(); + var event_id =field.shift(); if(checkStudio()==0)return; if (project_id<0) return; if (studio_id<0) return; - if (event_id<0) return; - //console.log("assign series") + if (event_id<0) return; $('#assign_series_events input[name="event_id"]').attr('value',event_id); show_not_assigned_to_series_dialog(); @@ -980,9 +829,9 @@ function handleUnassignedEvent(id){ function handleSchedule(id, start_date, event){ var field=id.split('_'); var classname =field.shift(); - var project_id =field.shift(); - var studio_id =field.shift(); - var series_id =field.shift(); + var project_id =field.shift(); + var studio_id =field.shift(); + var series_id =field.shift(); if(checkStudio()==0)return; if (project_id<0) return; @@ -990,7 +839,7 @@ function handleSchedule(id, start_date, event){ if (series_id<0) return; if(event.which==1){ - //left click: create event from schedule + //left click: create event from schedule var url="event.cgi?action=show_new_event_from_schedule&project_id="+project_id+"&studio_id="+studio_id+"&series_id="+series_id+"&start_date="+start_date; load(url); } @@ -1002,20 +851,23 @@ function handleSchedule(id, start_date, event){ } function handleGrid(id){ - var field=id.split('_'); - var classname =field.shift(); - var project_id =field.shift(); - var studio_id =field.shift(); - var series_id =field.shift();//to be selected + var field=id.split('_'); + var classname =field.shift(); + var project_id =field.shift(); + var studio_id =field.shift(); + var series_id =field.shift();//to be selected if(checkStudio()==0)return; if (project_id<0) return; if (studio_id<0) return; - var start_date=getNearestDatetime(); + var start_date = getNearestDatetime(); $('#series_date').attr('value',start_date); - showDateTimePicker('#series_date'); - //alert("studio "+studio_id+" "+start_date); + var date=parseDateTime(start_date); + showDateTimePicker('#series_date', { + date: start_date + }); + show_schedule_series_dialog(project_id, studio_id, series_id, start_date); } @@ -1023,17 +875,17 @@ function handleGrid(id){ function handleWorktime(id, event){ var field=id.split('_'); var classname =field.shift(); - var project_id =field.shift(); - var studio_id =field.shift(); - var schedule_id =field.shift(); + var project_id =field.shift(); + var studio_id =field.shift(); + var schedule_id =field.shift(); if(checkStudio()==0)return; if (project_id<0) return; if (studio_id<0) return; if (schedule_id<0) return; - var start_date=$(this).attr("date"); + var start_date=$(this).attr("start"); - var url="work_time.cgi?action=show_new_event_from_schedule&project_id="+project_id+"&studio_id="+studio_id+"&schedule_id="+schedule_id+"&start_date="+start_date; + var url="work-time.cgi?action=show_new_event_from_schedule&project_id="+project_id+"&studio_id="+studio_id+"&schedule_id="+schedule_id+"&start_date="+start_date; if(event.which==1){ load(url); } @@ -1042,3 +894,36 @@ function handleWorktime(id, event){ } } + +function hexToRgbA(hex){ + var c; + if(/^#([A-Fa-f0-9]{3}){1,2}$/.test(hex)){ + c= hex.substring(1).split(''); + if(c.length== 3){ + c= [c[0], c[0], c[1], c[1], c[2], c[2]]; + } + c= '0x'+c.join(''); + return 'rgba('+[(c>>16)&255, (c>>8)&255, c&255].join(',')+',1)'; + } + throw new Error('Bad Hex'); +} + +function adjustColors(){ + var elem = $('.schedule').get(0); + if (elem == null ) return; + var color1=window.getComputedStyle(elem).backgroundColor; + var color2=color1.replace('rgb','rgba').replace(')',', 0.4)') + $('.schedule').css('background', 'repeating-linear-gradient(to right, '+color1+', '+color1+' 1px, '+color2+' 1px, '+color2+' 2px) '); +} + +$(document).ready(function(){ + initCalendarMenu(); + + if(calendarTable==1){ + loadCalendar(); + }else{ + loadCalendarList(); + } + +}); + diff --git a/website/agenda/planung/js/datetime.js b/website/agenda/planung/js/datetime.js index 04f7eae..38a1724 100644 --- a/website/agenda/planung/js/datetime.js +++ b/website/agenda/planung/js/datetime.js @@ -1,119 +1,27 @@ - -// wrapper for date time picker with callback function function showDateTimePicker(selector, options){ - $(selector).each( function(){ - // init on first select - $(this).on('click', function(){ - if ($(this).hasClass("hasDatepicker")) return; - - var defaultOptions={ - dateFormat: "yy-mm-dd", - timeFormat: "HH:mm", - stepMinute: 5, - firstDay: 1, - showOtherMonths: true, - selectOtherMonths: true, - changeMonth: true, - changeYear: true, - showWeek: true, - } - - //recursively merge options - $.extend(true, defaultOptions, options); - - $(this).datetimepicker(defaultOptions); - - // set date and time from input field - var datetime=$(this).attr('value'); - if ((datetime != null) && (datetime != "")){ - var datetime=parseDateTime(datetime); - $(this).datetimepicker('setDate', datetime); - $(this).datetimepicker('setTime', datetime); - } - - if((region !=null) && (region !='' ) && (region != 'en')){ - $(this).datetimepicker( $.timepicker.regional[ region+"" ] ); - } - //show if has been initialized on first click - $(this).focus(); - }); - }); + var defaults = { + locale: { firstDayOfWeek: 1 }, + enableTime: true, + time_24hr: true + } + if (options){ + if (options["onSelect"]) defaults["onChange"] = options["onSelect"]; + if (options["onChange"]) defaults["onChange"] = options["onChange"]; + } + var elem = $(selector).flatpickr(defaults); + if (options && options.date) elem.setDate(options.date); } -// show date picker on first select with callback function function showDatePicker(selector, options){ - - $(selector).each( function(){ - // init on first select - var activator=$(this); - if ((options!=null)&&(options.activator!=null)) activator=$(options.activator); - - activator.on('click', function(){ - if ($(this).hasClass("hasDatepicker")) return; - - var defaultOptions={ - dateFormat: "yy-mm-dd", - timeFormat: "HH:mm", - showTimePicker: false, - firstDay: 1, - showOtherMonths: true, - selectOtherMonths: true, - changeMonth: true, - changeYear: true, - showWeek: true, - } - - //recursively merge options - $.extend(true, defaultOptions, options); - $(this).datepicker(defaultOptions); - - // set date from input field - var datetime=$(this).attr('value'); - if ((datetime != null) && (datetime != "")){ - $(this).datepicker('setDate', datetime); - } - - if((region !=null) && (region !='' ) && (region != 'en')){ - $(this).datepicker( $.datepicker.regional[ region+"" ] ); - } - //show if has been initialized on first click - $(this).focus(); - }); - }); -} - -// date picker with direct registration -function registerDatePicker(selector, options){ - - $(selector).each( function(){ - var defaultOptions={ - dateFormat: "yy-mm-dd", - timeFormat: "HH:mm", - showTimePicker: false, - firstDay: 1, - showOtherMonths: true, - selectOtherMonths: true, - changeMonth: true, - changeYear: true, - showWeek: true, - } - - //recursively merge options - $.extend(true, defaultOptions, options); - $(this).datepicker(defaultOptions); - - // set date from input field - var datetime=$(this).attr('value'); - if ((datetime != null) && (datetime != "")){ - $(this).datepicker('setDate', datetime); - } - - if((region !=null) && (region !='' ) && (region != 'en')){ - $(this).datepicker( $.datepicker.regional[ region+"" ] ); - } - //show if has been initialized on first click - $(this).focus(); - }); + var defaults = { + locale: { firstDayOfWeek: 1 }, + } + if (options){ + if (options["onSelect"]) defaults["onChange"] = options["onSelect"]; + if (options["onChange"]) defaults["onChange"] = options["onChange"]; + if (options["wrap"]) defaults["wrap"] = options["wrap"]; + } + return $(selector).flatpickr(defaults); } function showYearPicker(selector, options){ @@ -135,6 +43,11 @@ function showYearPicker(selector, options){ function parseDateTime(datetime){ + if (! datetime){ + console.log("datetime.js parseDateTime() is undefined or null"); + return null; + } + var dateTime = datetime.split(/[ T]+/); var date = dateTime[0].split("-"); @@ -207,6 +120,8 @@ function addDays(datetime, days){ var weekdays=['Mo','Di','Mi','Do','Fr','Sa','So']; function getWeekday(date){ + if (!date) return '?'; + if (loc['weekday_Mo']!=null) weekdays[0]=loc['weekday_Mo']; if (loc['weekday_Tu']!=null) weekdays[1]=loc['weekday_Tu']; if (loc['weekday_We']!=null) weekdays[2]=loc['weekday_We']; @@ -214,7 +129,6 @@ function getWeekday(date){ if (loc['weekday_Fr']!=null) weekdays[4]=loc['weekday_Fr']; if (loc['weekday_Sa']!=null) weekdays[5]=loc['weekday_Sa']; if (loc['weekday_Su']!=null) weekdays[6]=loc['weekday_Su']; - //console.log(weekdays); return weekdays[(date.getDay()-1+7)%7]+',' } diff --git a/website/agenda/planung/js/admin.js b/website/agenda/planung/js/default.js similarity index 54% rename from website/agenda/planung/js/admin.js rename to website/agenda/planung/js/default.js index c6803f3..c8c05bf 100644 --- a/website/agenda/planung/js/admin.js +++ b/website/agenda/planung/js/default.js @@ -11,64 +11,64 @@ function getController(){ function set_studio(id){ - var url=window.location.href; + var url=window.location.href; //split by # var comment= url.split(/\#/); url=comment.shift(); comment=comment.join('#'); - //split by ? - var parts= url.split(/\?/); - url=parts.shift(); - //split by & - parts=parts.join('?').split(/\&+/); - var params=[]; - if (parts.length>0){ - for (index in parts){ - //add all name value pairs but studio id - var pair=parts[index]; - if(! pair.match(/^studio_id=/)) params.push(pair); - } - } - //add studio id + //split by ? + var parts= url.split(/\?/); + url=parts.shift(); + //split by & + parts=parts.join('?').split(/\&+/); + var params=[]; + if (parts.length>0){ + for (index in parts){ + //add all name value pairs but studio id + var pair=parts[index]; + if(! pair.match(/^studio_id=/)) params.push(pair); + } + } + //add studio id if(id==null)id=-1; if(id=='')id=-1; - params.push('studio_id='+id); - //append parameters to url - url+='?'+params.join('&'); + params.push('studio_id='+id); + //append parameters to url + url+='?'+params.join('&'); if ((comment!=null)&&(comment!='')) url+='#'+comment; - window.location.href=url; + window.location.href=url; } function set_project(id){ - var url=window.location.href; + var url=window.location.href; //split by # var comment= url.split(/\#/); url=comment.shift(); comment=comment.join('#'); - //split by ? - var parts= url.split(/\?/); - url=parts.shift(); - //split by & - parts=parts.join('?').split(/\&+/); - var params=[]; - if (parts.length>0){ - for (index in parts){ - //add all name value pairs but project id - var pair=parts[index]; - if( + //split by ? + var parts= url.split(/\?/); + url=parts.shift(); + //split by & + parts=parts.join('?').split(/\&+/); + var params=[]; + if (parts.length>0){ + for (index in parts){ + //add all name value pairs but project id + var pair=parts[index]; + if( (! pair.match(/^project_id=/)) && (! pair.match(/^studio_id=/)) )params.push(pair); - } - } - //add project id + } + } + //add project id if(id==null)id=-1; if(id=='')id=-1; - params.push('project_id='+id); - //append parameters to url - url+='?'+params.join('&'); + params.push('project_id='+id); + //append parameters to url + url+='?'+params.join('&'); if ((comment!=null)&&(comment!='')) url+='#'+comment; - window.location.href=url; + window.location.href=url; } function contains(s,t){ @@ -78,23 +78,18 @@ function contains(s,t){ } function updateContainer(id, url, callback){ - //alert(id+":"+url); - if (id==null) return; - if ($("#"+id).length==0) return; - $("#"+id).load(url, callback); + //alert(id+":"+url); + if (id==null) return; + if ($("#"+id).length==0) return; + $("#"+id).load(url, callback); } function load(url){ window.location=url; - //window.location.replace(url); - //document.location.href=url; - //$(window).load(url); - //$('html').load(url); } - function postContainer(url, parameters, callback){ - if (url!='') $.post(url, parameters, callback); + if (url!='') $.post(url, parameters, callback); } // init getTextWidth @@ -127,35 +122,42 @@ function setTextWidth(select, minValue){ // trigger action on commit function commitAction (title, action){ - if (action==null) {alert("missing action");return} - if (title==null) {alert("missing title");return} + if ( title == null ) { alert("missing title");return; } + if ( action == null ) { alert("missing action");return; } - if ($("#dialog-confirm").length>0) $("#dialog-confirm").remove(); - $("#content").append( - '<div id="dialog-confirm" title="'+title+'" style="min-height:2em;">' - +'<p>' - +'<span class="ui-icon ui-icon-alert" style="float:left; margin:0 7px 20px 0;"></span>' - +'Are you sure?' - +'</p>' - +'</div>' - ); - - $( "#dialog-confirm" ).dialog({ - resizable: false, - height: "200", - modal: true, - buttons: { - Okay : function() { - $(this).dialog( "close" ); - action(); - }, - Cancel: function() { - $(this).dialog( "close" ); - } + showDialog({ + title : '<img src="image/alert.svg">Are you sure?</p>', + buttons : { + OK : function(){ action(); }, + Cancel : function(){ $(this).parent().remove(); } } }); } +function showDialog(options){ + if ($("#dialog").length>0) $("#dialog").remove(); + $("#content").append( + '<div id="dialog" class="panel">' + + (options.title ? '<div>'+options.title+'</div>' :'') + + (options.content ? options.content :'') + +'</div>' + ); + var dialog = $('#content #dialog'); + if (options.width) dialog.css("width", options.width); + if (options.height) dialog.css("height", options.height); + if (options.buttons) { + Object.keys(options.buttons).forEach( function (key) { + var value = options.buttons[key]; + dialog.append("<button>"+key+"</button"); + var button=$("#content #dialog button").last(); + button.on("click", value); + button.addClass( 'dialog-'+key.toLowerCase().replace( /[^a-zA-Z0-9]/g, '-') ) + }); + } + if (options.onOpen) options.onOpen(); + return dialog; +} + // set action=<action> at form and submit the form after confirmation function commitForm ( formElement, action, title){ if (formElement==null) { alert("missing id");return } @@ -205,17 +207,58 @@ function getUrlParameter(name){ return results[1]; } +function handleBars(){ + var menu=$('#calcms_nav'); + menu.toggleClass('mobile'); + if (menu.hasClass('mobile')){ + $('#calcms_nav>div').show(); + $('#content').hide(); + }else{ + $('#content').show(); + setupMenu(1); + } +} + +var oldWidth=0; +function setupMenu(update){ + var xmax=960; + + var menu = $('#calcms_nav'); + var width = menu.width(); + + if ( (width < xmax) && (oldWidth >= xmax) ) update=1; + if ( (width >= xmax) && (oldWidth < xmax) ) update=1; + if (oldWidth==0) update=1; + + if (update == 1){ + if (menu.width() < 960){ + $('#calcms_nav>div').hide(); + $('#calcms_nav>div.mobile').show(); + }else{ + $('#calcms_nav>div').show(); + $('#calcms_nav #bars').hide(); + menu.removeClass('mobile'); + } + } + + oldWidth = width; +} + // will be overridden by calendar.js function setupMenuHeight(){ - //$('#content').css("position", "absolute"); - /* - var top = $('#calcms_admin_menu').height(); - $('#content').css("top", top); + var content=$('#content'); + content.css("position", "relative"); + var menu=$('#calcms_nav'); + var top = menu.height(); + content.css("top", top); + + /* + console.log($(window).width()+" "+$(document).width()+" "+$('#content').width()); var left=0; if( $(window).width() >= $(document).width() ){ - left=$(document).width()-$('#content').width(); + left=$(document).width() - $('#content').width(); left/=2; if (left<40)left=0; } @@ -308,12 +351,76 @@ function initLabels(){ }); }; +function copyToClipboard(text){ + if ( text.length == 0 ) return; + $('body').append('<textarea style="display:none" id="clipboard">' + text + '</textarea>'); + var copyText = document.getElementById('clipboard'); + copyText.select(); + copyText.setSelectionRange(0, 99999); + document.execCommand("copy"); +} + +function setTabs(id, callback) { + var key = id + ' ul li'; + var i = 0; + + // preselect by URL hash + var pos=0; + $(key).each( function() { + if ( window.location.hash == "#"+$(this).children(":first").attr("href").substr(1) ) + pos=i; + i++ + }) + + var i = 0; + $(key).each( function() { + var elem = $(this); + var id = elem.children(":first").attr("href").substr(1); + if ( i==pos ) { + elem.addClass("active"); + $('#'+id).show(); + } else { + $('#'+id).hide(); + elem.removeClass("active"); + } + i++; + }); + + $( key ).on( "click", function(){ + var id2 = $(this).children(":first").attr("href").substr(1); + $(key).each( function(){ + var elem = $(this); + var id = elem.children(":first").attr("href").substr(1); + if (id==id2){ + $('#'+id).show(); + elem.addClass("active"); + } else { + $('#'+id).hide(); + elem.removeClass("active"); + } + }); + if (callback) callback(); + return false; + }); + $( id+' ul' ).addClass("tabContainer"); + return false; +} + $(document).ready( function(){ + setupMenu(); checkSession(); setMissingUrlParameters(); + // will be done implicitely on adding back button + //setupMenuHeight(); + + $(window).resize(function() { + setupMenuHeight(); + setupMenu(); + }); + if(getController()=='calendar'){ //use build-in localization console.log("add back") @@ -326,11 +433,11 @@ $(document).ready( }); } initLabels(); - //setupMenuHeight(); - //$(window).resize(function() { - //setupMenuHeight(); - //}); - + let title = ''; + if (title=='') title = $('.panel-header').first().text(); + if (title=='') title = $('h2').first().text(); + document.title = title + } ); diff --git a/website/agenda/planung/js/edit_event.js b/website/agenda/planung/js/edit-event.js similarity index 80% rename from website/agenda/planung/js/edit_event.js rename to website/agenda/planung/js/edit-event.js index a3d6564..96390eb 100644 --- a/website/agenda/planung/js/edit_event.js +++ b/website/agenda/planung/js/edit-event.js @@ -21,11 +21,9 @@ function onDateModified(){ function selectRerun(resultSelector, tillDate){ $('#selectRerun').show(); - //$('#selectRerun input:radio').attr("value","0"); - //$('#selectRerun input:radio').prop("checked",false); $('#selectRerun input:radio.default').attr("value","1"); $('#selectRerun input:radio.default').prop("checked",true); - $('#selectRerun input:radio.default').click(); + $('#selectRerun input:radio.default').click(); $('.buttons').hide(); } @@ -45,7 +43,7 @@ function selectOldEventFromSeries(resultSelector, tillDate){ $('#import_rerun_header').show('slideUp'); if ($('#import_rerun_header').css('display')=='none')return; - var url='selectEvent.cgi?' + var url='select-event.cgi?' url+='project_id='+getProjectId(); url+='&studio_id='+getStudioId(); url+='&series_id='+getUrlParameter('series_id'); @@ -63,7 +61,7 @@ function selectOtherEvent(resultSelector){ $('#import_rerun_header').show('slideUp'); if ($('#import_rerun_header').css('display')=='none')return; - var url='selectEvent.cgi?' + var url='select-event.cgi?' url+='project_id='+getProjectId(); url+='&studio_id='+getStudioId(); url+='&series_id='+getUrlParameter('series_id'); @@ -90,8 +88,15 @@ function copyFromEvent(resultSelector){ var eventId = $('#selectEvent #eventId').val(); loadEvent(projectId, studioId, seriesId, eventId, function(){ + console.log("loadEvent:",projectId, studioId, seriesId, eventId) + console.log("loadEvent.callback: hideSelectRerun") hideSelectRerun(); - }); + console.log("loadEvent.callback: updateCheckbox") + updateCheckBox( "#edit_event input[name='published']", 1); + console.log("loadEvent.callback: done") + }); + console.log("copyFromEvent done") + return 1; } function loadEvent(projectId,studioId,seriesId,eventId, callback){ @@ -106,7 +111,8 @@ function loadEvent(projectId,studioId,seriesId,eventId, callback){ url+="&get_rerun=1"; console.log("loadEvent: "+url) - $.getJSON( url, function( event ) { + $.getJSON(url) + .done( function(event) { $("#edit_event input[name='title']").attr('value', event.title) $("#edit_event input[name='user_title']").attr('value', event.user_title) $("#edit_event input[name='episode']").attr('value', event.episode) @@ -129,14 +135,17 @@ function loadEvent(projectId,studioId,seriesId,eventId, callback){ updateDuration("#edit_event #duration", event.duration); - if (callback!=null) callback(); + if (callback != null) callback(); console.log("loadEvent done") + }).fail( function(jqxhr, textStatus, error) { + var err = textStatus + ", " + error; + console.log("loadEvent failed: " + err); }); } // load series selection function selectChangeSeries(resultSelector){ - var url='selectSeries.cgi?' + var url='select-series.cgi?' url+='project_id='+getProjectId(); url+='&studio_id='+getStudioId(); url+='&series_id='+getUrlParameter('series_id'); @@ -178,10 +187,11 @@ function changeSeries(seriesId){ url += '&event_id='+eventId; url += '&new_series_id='+newSeriesId; url += '&action=reassign_event'; + //alert(url); - $.post( - url, - function(data){ + $.post( + url, + function(data){ var url='event.cgi?'; url += '&project_id='+projectId; url += '&studio_id='+studioId; @@ -189,9 +199,9 @@ function changeSeries(seriesId){ url += '&event_id='+eventId; url += '&action=edit'; window.location.href = url; - } - ); - return false; + } + ); + return false; } // hide change series on abort @@ -236,8 +246,8 @@ function updateCheckBox(selector, value){ } function checkExcerptField(){ - var elem=$('textarea[name="excerpt"]'); - if (elem.length==0) return 0; + var elem=$('textarea[name="excerpt"]'); + if (elem.length==0) return 0; var length = elem.val().length; console.log("length="+length); if (length > 250){ @@ -245,12 +255,12 @@ function checkExcerptField(){ }else{ $('#excerpt_too_long').hide(); } - return 1; + return 1; } function checkExcerptExtensionField(){ - var elem=$('textarea[name="user_excerpt"]'); - if (elem.length==0) return 0; + var elem=$('textarea[name="user_excerpt"]'); + if (elem.length==0) return 0; var length = elem.val().length; console.log("length="+length); if (length > 250){ @@ -258,37 +268,51 @@ function checkExcerptExtensionField(){ }else{ $('#excerpt_extension_too_long').hide(); } - return 1; + return 1; } function checkFields(){ if (checkExcerptField()){ - $('textarea[name="excerpt"]').on("keyup", function(){ - checkExcerptField(); - }); - } + $('textarea[name="excerpt"]').on("keyup", function(){ + checkExcerptField(); + }); + } if (checkExcerptExtensionField()){ - $('textarea[name="user_excerpt"]').on("keyup", function(){ - checkExcerptExtensionField(); - }); - } + $('textarea[name="user_excerpt"]').on("keyup", function(){ + checkExcerptExtensionField(); + }); + } +} + +function copyEventToClipboard(){ + var text = $('textarea[name="excerpt"]').val()+"\n"; + text += $('textarea[name="user_excerpt"]').val()+"\n"; + text += $('textarea[name="topic"]').val()+"\n\n"; + text += $('textarea[name="content"]').val()+"\n"; + + text = '<textarea style="none" id="clipboard">' + text + '</textarea>'; + $('body').append(text); + + var copyText = document.getElementById('clipboard'); + copyText.select(); + copyText.setSelectionRange(0, 99999); + document.execCommand("copy"); } $(document).ready( function(){ - initRegions(region); showDateTimePicker('#start_date'); - $('input[type="checkbox"]').click( - function(){ - if ($(this).attr('value')=='1'){ - $(this).attr('value','0'); - }else{ - $(this).attr('value','1'); - } - } - ); + $('input[type="checkbox"]').click( + function(){ + if ($(this).attr('value')=='1'){ + $(this).attr('value','0'); + }else{ + $(this).attr('value','1'); + } + } + ); if($('#calendar').length==0){ $('#back_to_calendar').hide(); diff --git a/website/agenda/planung/js/edit-image.js b/website/agenda/planung/js/edit-image.js new file mode 100644 index 0000000..525487c --- /dev/null +++ b/website/agenda/planung/js/edit-image.js @@ -0,0 +1,36 @@ +function updateCheckBox(selector, value){ + $(selector).attr('value', value) + if (value==1){ + $(selector).prop( "checked", true ); + } else { + $(selector).prop( "checked", false ); + } +} + +function updatePublicCheckbox(elem){ + console.log(elem.prop('checked')) + if (elem.prop('checked')){ + console.log( 'set public' ); + updateCheckBox(elem, 1); + }else{ + console.log( 'unset public' ); + updateCheckBox(elem, 0); + } +} + + +$(document).ready( + function(){ + var publicCheckbox=$("#img_editor input[name='public']"); + + updatePublicCheckbox( publicCheckbox ); + publicCheckbox.change( + function(){ + updatePublicCheckbox($(this)); + } + ) + console.log("image handler initialized"); + pageLeaveHandler(); + } +); + diff --git a/website/agenda/planung/js/edit_series.js b/website/agenda/planung/js/edit-series.js similarity index 95% rename from website/agenda/planung/js/edit_series.js rename to website/agenda/planung/js/edit-series.js index d217e8f..f53388d 100644 --- a/website/agenda/planung/js/edit_series.js +++ b/website/agenda/planung/js/edit-series.js @@ -1,11 +1,11 @@ /* - show a series, its template, users and events + show a series, its template, users and events */ // set checkbox values checked depending on value function initCheckBoxes(){ - $('div.editor input[type="checkbox"]').each( + $('div.editor input[type="checkbox"]').each( function () { if ($(this).attr('value')=='1'){ $(this).attr('value','1'); @@ -14,26 +14,26 @@ function initCheckBoxes(){ $(this).attr('value','0'); $(this).attr('checked',null); } - } + } ); } // add checkbox handler to change value on click function addCheckBoxHandler(){ - $('div.editor input[type="checkbox"]').click( + $('div.editor input[type="checkbox"]').click( function () { if ($(this).attr('value')=='1'){ $(this).attr('value','0'); }else{ $(this).attr('value','1'); } - } + } ); } // show/hide series member edit function edit_series_members(series_id){ - $('.edit_series_members_'+series_id).toggle(); + $('.edit_series_members_'+series_id).toggle(); } // show/hide schedule fields depending on period type for a given schedule element @@ -208,7 +208,9 @@ function setInputWidth(){ } function checkExcerptField(){ - var length = $('textarea[name="excerpt"]').val().length; + var elem = $('textarea[name="excerpt"]'); + if (elem.length==0) return; + var length = elem.val().length; console.log("length="+length); if (length > 250){ $('#excerpt_too_long').show(); @@ -226,7 +228,7 @@ function checkFields(){ $(document).ready( - function(){ + function(){ setupLocalization( function(){ addBackButton(); @@ -234,7 +236,6 @@ $(document).ready( } ); - initRegions(region); showDateTimePicker('input.datetimepicker.start', { onSelect: function(){updateWeekdays();} }); @@ -245,8 +246,7 @@ $(document).ready( initCheckBoxes(); addCheckBoxHandler(); - $("#tabs").tabs(); - $('#tabs').removeClass('ui-widget ui-widget-content ui-corner-all'); + setTabs('#tabs'); updateScheduleButtonName(); initScheduleFields(); @@ -270,7 +270,7 @@ $(document).ready( $('table#schedule_table').tablesorter({ widgets: ["filter"], - usNumberFormat : false + usNumberFormat : false }); } diff --git a/website/agenda/planung/js/edit_image.js b/website/agenda/planung/js/edit_image.js deleted file mode 100644 index 60f377b..0000000 --- a/website/agenda/planung/js/edit_image.js +++ /dev/null @@ -1,63 +0,0 @@ -function editImage(filename){ - $("#img_editor").load('image.cgi?show='+filename+'&template=image_edit.html', - function(){ - $('#img_editor').dialog({ - width:920, - height:330 - }); - } - ); -} - -function showImage(url){ - $("#img_image").html('<img src="'+url+'" onclick="$(\'#img_image\').dialog(\'close\');return false;"/>'); - $("#img_image").dialog({ - width:640, - height:640 - }); -} - -function hideImageDetails(id,filename){ - try{$('#img_editor').dialog('close');}catch(e){} - try{$('#img_image').dialog("close");}catch(e){} - - $("#"+id).load('image.cgi?show='+filename+'&template=image_single.html'); - return false; -} - -function saveImage(id, filename) { - var url='image.cgi?save_image='+filename; - if (url!='') $.post( - url, - $("#save_img_"+id).serialize(), - function(data){ - hideImageDetails('img_'+id, filename); - - } - ); - return false; -} - -function deleteImage(id, filename) { - $("#"+id).load('image.cgi?delete_image='+filename); - hideImageDetails('img_'+id, filename); - $("#"+id).hide('drop'); - return false; -} - -function showImageUrl(id){ - var el=document.getElementById(id); - var input_id=id+'_input'; - var text='<input id="'+input_id+'" value="{{thumbs/'+id+'|title}}" title="3fach-Klick zum Markieren!">'; - if (el.innerHTML==text){ - el.innerHTML=''; - }else{ - el.innerHTML=text; - var input=document.getElementById(input_id); - input.focus(); - input.select(); - input.createTextRange().execCommand("Copy"); - } - return false; -} - diff --git a/website/agenda/planung/js/edit_work_time.js b/website/agenda/planung/js/edit_work_time.js index 7aad152..953a0ed 100644 --- a/website/agenda/planung/js/edit_work_time.js +++ b/website/agenda/planung/js/edit_work_time.js @@ -1,11 +1,11 @@ /* - show a series, its template, users and events + show a series, its template, users and events */ // set checkbox values checked depending on value function initCheckBoxes(){ - $('div.editor input[type="checkbox"]').each( + $('div.editor input[type="checkbox"]').each( function () { if ($(this).attr('value')=='1'){ $(this).attr('value','1'); @@ -14,20 +14,20 @@ function initCheckBoxes(){ $(this).attr('value','0'); $(this).attr('checked',null); } - } + } ); } // add checkbox handler to change value on click function addCheckBoxHandler(){ - $('div.editor input[type="checkbox"]').click( + $('div.editor input[type="checkbox"]').click( function () { if ($(this).attr('value')=='1'){ $(this).attr('value','0'); }else{ $(this).attr('value','1'); } - } + } ); } @@ -183,15 +183,13 @@ function setInputWidth(){ $(document).ready( - function(){ + function(){ setupLocalization( function(){ addBackButton(); updateWeekdays(); } ); - - initRegions(region); showDateTimePicker('.datetimepicker.start', { onSelect: function(){updateWeekdays();} @@ -204,8 +202,7 @@ $(document).ready( initCheckBoxes(); addCheckBoxHandler(); - $("#tabs").tabs(); - $('#tabs').removeClass('ui-widget ui-widget-content ui-corner-all'); + setTabs('#tabs'); updateScheduleButtonName(); initScheduleFields(); @@ -224,7 +221,7 @@ $(document).ready( $('table#schedule_table').tablesorter({ widgets: ["filter"], - usNumberFormat : false + usNumberFormat : false }); } diff --git a/website/agenda/planung/js/event.js b/website/agenda/planung/js/event.js index bafdc86..523a07c 100644 --- a/website/agenda/planung/js/event.js +++ b/website/agenda/planung/js/event.js @@ -1,27 +1,18 @@ // TODO: add project_id function edit_event(event_id, series_id, studio_id, project_id, hide_series){ - var elem=$('#event_'+event_id); - if(elem.hasClass('active')){ - elem.removeClass('active'); - $('#event_container_'+event_id).slideToggle( - function(){ - $('#event_details_'+event_id).html(''); - } - ); - }else{ - elem.addClass('active'); - var url="event.cgi?project_id="+project_id+"&studio_id="+studio_id+"&series_id="+series_id+"&event_id="+event_id+"&action=edit"; - if ((hide_series!=null) && (hide_series!=''))url+='&hide_series=1'; - load(url); - /* - updateContainer( - 'event_details_'+event_id, - url, - function(){ - $('#event_container_'+event_id).slideToggle(); - } - ); - */ - } + var elem=$('#event_'+event_id); + if(elem.hasClass('active')){ + elem.removeClass('active'); + $('#event_container_'+event_id).slideToggle( + function(){ + $('#event_details_'+event_id).html(''); + } + ); + }else{ + elem.addClass('active'); + var url="event.cgi?project_id="+project_id+"&studio_id="+studio_id+"&series_id="+series_id+"&event_id="+event_id+"&action=edit"; + if ((hide_series!=null) && (hide_series!=''))url+='&hide_series=1'; + load(url); + } } diff --git a/website/agenda/planung/js/fileUploader.js b/website/agenda/planung/js/fileUploader.js deleted file mode 100644 index a5f0f97..0000000 --- a/website/agenda/planung/js/fileUploader.js +++ /dev/null @@ -1,225 +0,0 @@ -/* -* Class: fileUploader -* Use: Upload multiple files the jQuery way -* Author: John Lanz (http://pixelcone.com) -* Version: 1.0 -*/ - -(function($) { - $.fileUploader = {version: '1.1'}; - $.fn.fileUploader = function(config){ - - config = $.extend({}, { - limit: '1', - imageLoader: '', - buttonUpload: '#pxUpload', - buttonClear: '#pxClear', - successOutput: 'File Uploaded', - errorOutput: 'Failed', - inputName: 'image', - inputSize: 30, - allowedExtension: 'jpg|jpeg|gif|png', - callback: function() {}, - url: window.location.href - }, config); - - var itr = 0; //number of files to uploaded - var $limit = 1; - - //public function - $.fileUploader.change = function(e){ - var fname = px.validateFile( $(e).val() ); - if (fname == -1){ - alert ("Invalid file!"); - $(e).val(""); - return false; - } - $('#px_button input').removeAttr("disabled"); - var imageLoader = ''; - if ($.trim(config.imageLoader) != ''){ - imageLoader = '<img src="'+ config.imageLoader +'" alt="uploader" />'; - } - var display = '<div class="uploadData" id="pxupload'+ itr +'_text" title="pxupload'+ itr +'">' + - '<div class="close"> </div>' + - '<span class="fname">'+ fname +'</span>' + - '<span class="loader" style="display:none">'+ imageLoader +'</span>' + - '<div class="status"></div>'+ - '</div>'; - - $("#px_display").append(display); - if (config.limit == '' || $limit < config.limit) { - px.appendForm(); - } - $limit++; - $(e).hide(); - //px.upload(); - - } - - // To exactly match $("a.foo").live("click", fn), for example, you can write $(document).on("click", "a.foo", fn). - // $(".close").live("click", function(){ - $(document).on("click", ".close", function(){ - $limit--; - if ($limit == config.limit) { - px.appendForm(); - } - var id = "#" + $(this).parent().attr("title"); - $(id+"_frame").remove(); - $(id).remove(); - $(id+"_text").fadeOut("slow",function(){ - $(this).remove(); - }); - return false; - }); - - //$(config.buttonClear).click(function(){ - $(document).on("click", "config.buttonClear", function(){ - $("#px_display").fadeOut("slow",function(){ - $("#px_display").html(""); - $("#pxupload_form").html(""); - itr = 0; - $limit = 1; - px.appendForm(); - $('#px_button input').attr("disabled","disabled"); - $(this).show(); - }); - }); - - //private function - var px = { - init: function(e){ - var form = $(e).parents('form'); - px.formAction = $(form).attr('action'); - - $(form).before(' \ - <div id="pxupload_form"></div> \ - <div id="px_display"></div> \ - <div id="px_button"></div> \ - '); - $(config.buttonUpload+','+config.buttonClear).appendTo('#px_button'); - if ( $(e).attr('name') != '' ){ - config.inputName = $(e).attr('name'); - } - if ( $(e).attr('size') != '' ){ - config.inputSize = $(e).attr('size'); - } - $(form).hide(); - $(config.buttonUpload).click(function(){ - px.upload() - }) - - this.appendForm(); - }, - appendForm: function(){ - itr++; - var formId = "pxupload" + itr; - var iframeId = "pxupload" + itr + "_frame"; - var inputId = "pxupload" + itr + "_input"; - var contents = - '<form method="post" id="'+ formId +'" action="'+ px.formAction +'" enctype="multipart/form-data" target="'+ iframeId +'">' - +'<br/>'+loc['label_name']+'<br /><input name="name" />' - +'<br/>'+loc['label_description']+'<br /><textarea name="description" rows="3" cols="40"></textarea>' - ; - if (studio_id != null) contents+='<input type="hidden" name="studio_id" value="'+studio_id+'">'; - if (project_id != null) contents+='<input type="hidden" name="project_id" value="'+project_id+'">'; - contents+= - '<input type="file" name="'+ config.inputName +'" id="'+ inputId +'" class="pxupload" size="'+ config.inputSize +'" onchange="$.fileUploader.change(this);" />' - +'<input name="action" value="upload" type="hidden"/>' - +'</form>' - +'<iframe id="'+ iframeId +'" name="'+ iframeId +'" src="about:blank" style="display:none"></iframe>'; - - $("#pxupload_form").append( contents ); - }, - validateFile: function(file) { - if (file.indexOf('/') > -1){ - file = file.substring(file.lastIndexOf('/') + 1); - }else if (file.indexOf('\\') > -1){ - file = file.substring(file.lastIndexOf('\\') + 1); - } - //var extensions = /(.jpg|.jpeg|.gif|.png)$/i; - var extensions = new RegExp(config.allowedExtension + '$', 'i'); - if (extensions.test(file)){ - return file; - } else { - return -1; - } - }, - - upload: function(){ - if (itr > 0){ - $('#px_button input').attr("disabled","disabled"); - $("#pxupload_form form").each(function(){ - e = $(this); - var id = "#" + $(e).attr("id"); - var input_id = id + "_input"; - var input_val = $(input_id).val(); - if (input_val != ""){ - $(id + "_text .status").text("Uploading..."); - $(id + "_text").css("background-color", "#FFF0E1"); - $(id + "_text .loader").show(); - $(id + "_text .close").hide(); - - $(id).submit(); - $(id +"_frame").load(function(){ - $(id + "_text .loader").hide(); - up_output = $(this).contents().find("#output").html(); - var success=0; - if (up_output == "success"){ - success=1; - $(id + "_text").css("background-color", "#F0F8FF"); - up_output = config.successOutput; - px.redirect(); - }else{ - $(id + "_text").css("background-color", "#FF0000"); - up_output = config.errorOutput; - } - - //custom code - up_output += '<br />' + $(this).contents().find("#message").html(); - //alert($(this).contents()) - //console.log(JSON.stringify($(this).contents())); - $(id + "_text .status").html(up_output); - - if(success==1){ - var image_id=$(this).contents().find("#upload_image_id").html(); - var filename=$(this).contents().find("#upload_image_filename").html(); - var title =$(this).contents().find("#upload_image_title").html(); - var quote="'"; - - //remove existing image from list - $('#imageList div.images #img_'+image_id).remove(); - //add image to list - $('#imageList div.images').prepend( - '<div id="img_'+image_id+'" class="image" ' - +' onclick="imageAction('+quote+filename+quote+');return false;" ' - +' title="'+title+'" ' - +' style="background-image:url('+quote+'/agenda_files/media/thumbs/'+filename+quote+')"' - +'>' - +' <div class="label">'+title+'</div>' - +'</div>' - ); - } - //end of custom code - $(e).remove(); - $(config.buttonClear).removeAttr("disabled"); - config.callback($(this)); - }); - } - }); - } - }, - - redirect: function(){ - //window.location.replace(config.url) - //$('#pxupload_form').append('<form id="redirect" method="GET" action="'+config.url+'" />'); - //$('#redirect').submit(); - } - - - } - - px.init(this); - - return this; - } -})(jQuery); diff --git a/website/agenda/planung/js/flatpickr.js b/website/agenda/planung/js/flatpickr.js new file mode 100644 index 0000000..345297f --- /dev/null +++ b/website/agenda/planung/js/flatpickr.js @@ -0,0 +1,2 @@ +/* flatpickr v4.6.9,, @license MIT */ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).flatpickr=t()}(this,(function(){"use strict";var e=function(){return(e=Object.assign||function(e){for(var t,n=1,a=arguments.length;n<a;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)};function t(){for(var e=0,t=0,n=arguments.length;t<n;t++)e+=arguments[t].length;var a=Array(e),i=0;for(t=0;t<n;t++)for(var o=arguments[t],r=0,l=o.length;r<l;r++,i++)a[i]=o[r];return a}var n=["onChange","onClose","onDayCreate","onDestroy","onKeyDown","onMonthChange","onOpen","onParseConfig","onReady","onValueUpdate","onYearChange","onPreCalendarPosition"],a={_disable:[],allowInput:!1,allowInvalidPreload:!1,altFormat:"F j, Y",altInput:!1,altInputClass:"form-control input",animate:"object"==typeof window&&-1===window.navigator.userAgent.indexOf("MSIE"),ariaDateFormat:"F j, Y",autoFillDefaultTime:!0,clickOpens:!0,closeOnSelect:!0,conjunction:", ",dateFormat:"Y-m-d",defaultHour:12,defaultMinute:0,defaultSeconds:0,disable:[],disableMobile:!1,enableSeconds:!1,enableTime:!1,errorHandler:function(e){return"undefined"!=typeof console&&console.warn(e)},getWeek:function(e){var t=new Date(e.getTime());t.setHours(0,0,0,0),t.setDate(t.getDate()+3-(t.getDay()+6)%7);var n=new Date(t.getFullYear(),0,4);return 1+Math.round(((t.getTime()-n.getTime())/864e5-3+(n.getDay()+6)%7)/7)},hourIncrement:1,ignoredFocusElements:[],inline:!1,locale:"default",minuteIncrement:5,mode:"single",monthSelectorType:"dropdown",nextArrow:"<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 17 17'><g></g><path d='M13.207 8.472l-7.854 7.854-0.707-0.707 7.146-7.146-7.146-7.148 0.707-0.707 7.854 7.854z' /></svg>",noCalendar:!1,now:new Date,onChange:[],onClose:[],onDayCreate:[],onDestroy:[],onKeyDown:[],onMonthChange:[],onOpen:[],onParseConfig:[],onReady:[],onValueUpdate:[],onYearChange:[],onPreCalendarPosition:[],plugins:[],position:"auto",positionElement:void 0,prevArrow:"<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 17 17'><g></g><path d='M5.207 8.471l7.146 7.147-0.707 0.707-7.853-7.854 7.854-7.853 0.707 0.707-7.147 7.146z' /></svg>",shorthandCurrentMonth:!1,showMonths:1,static:!1,time_24hr:!1,weekNumbers:!1,wrap:!1},i={weekdays:{shorthand:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],longhand:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]},months:{shorthand:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],longhand:["January","February","March","April","May","June","July","August","September","October","November","December"]},daysInMonth:[31,28,31,30,31,30,31,31,30,31,30,31],firstDayOfWeek:0,ordinal:function(e){var t=e%100;if(t>3&&t<21)return"th";switch(t%10){case 1:return"st";case 2:return"nd";case 3:return"rd";default:return"th"}},rangeSeparator:" to ",weekAbbreviation:"Wk",scrollTitle:"Scroll to increment",toggleTitle:"Click to toggle",amPM:["AM","PM"],yearAriaLabel:"Year",monthAriaLabel:"Month",hourAriaLabel:"Hour",minuteAriaLabel:"Minute",time_24hr:!1},o=function(e,t){return void 0===t&&(t=2),("000"+e).slice(-1*t)},r=function(e){return!0===e?1:0};function l(e,t){var n;return function(){var a=this;clearTimeout(n),n=setTimeout((function(){return e.apply(a,arguments)}),t)}}var c=function(e){return e instanceof Array?e:[e]};function d(e,t,n){if(!0===n)return e.classList.add(t);e.classList.remove(t)}function s(e,t,n){var a=window.document.createElement(e);return t=t||"",n=n||"",a.className=t,void 0!==n&&(a.textContent=n),a}function u(e){for(;e.firstChild;)e.removeChild(e.firstChild)}function f(e,t){return t(e)?e:e.parentNode?f(e.parentNode,t):void 0}function m(e,t){var n=s("div","numInputWrapper"),a=s("input","numInput "+e),i=s("span","arrowUp"),o=s("span","arrowDown");if(-1===navigator.userAgent.indexOf("MSIE 9.0")?a.type="number":(a.type="text",a.pattern="\\d*"),void 0!==t)for(var r in t)a.setAttribute(r,t[r]);return n.appendChild(a),n.appendChild(i),n.appendChild(o),n}function g(e){try{return"function"==typeof e.composedPath?e.composedPath()[0]:e.target}catch(t){return e.target}}var p=function(){},h=function(e,t,n){return n.months[t?"shorthand":"longhand"][e]},v={D:p,F:function(e,t,n){e.setMonth(n.months.longhand.indexOf(t))},G:function(e,t){e.setHours(parseFloat(t))},H:function(e,t){e.setHours(parseFloat(t))},J:function(e,t){e.setDate(parseFloat(t))},K:function(e,t,n){e.setHours(e.getHours()%12+12*r(new RegExp(n.amPM[1],"i").test(t)))},M:function(e,t,n){e.setMonth(n.months.shorthand.indexOf(t))},S:function(e,t){e.setSeconds(parseFloat(t))},U:function(e,t){return new Date(1e3*parseFloat(t))},W:function(e,t,n){var a=parseInt(t),i=new Date(e.getFullYear(),0,2+7*(a-1),0,0,0,0);return i.setDate(i.getDate()-i.getDay()+n.firstDayOfWeek),i},Y:function(e,t){e.setFullYear(parseFloat(t))},Z:function(e,t){return new Date(t)},d:function(e,t){e.setDate(parseFloat(t))},h:function(e,t){e.setHours(parseFloat(t))},i:function(e,t){e.setMinutes(parseFloat(t))},j:function(e,t){e.setDate(parseFloat(t))},l:p,m:function(e,t){e.setMonth(parseFloat(t)-1)},n:function(e,t){e.setMonth(parseFloat(t)-1)},s:function(e,t){e.setSeconds(parseFloat(t))},u:function(e,t){return new Date(parseFloat(t))},w:p,y:function(e,t){e.setFullYear(2e3+parseFloat(t))}},D={D:"(\\w+)",F:"(\\w+)",G:"(\\d\\d|\\d)",H:"(\\d\\d|\\d)",J:"(\\d\\d|\\d)\\w+",K:"",M:"(\\w+)",S:"(\\d\\d|\\d)",U:"(.+)",W:"(\\d\\d|\\d)",Y:"(\\d{4})",Z:"(.+)",d:"(\\d\\d|\\d)",h:"(\\d\\d|\\d)",i:"(\\d\\d|\\d)",j:"(\\d\\d|\\d)",l:"(\\w+)",m:"(\\d\\d|\\d)",n:"(\\d\\d|\\d)",s:"(\\d\\d|\\d)",u:"(.+)",w:"(\\d\\d|\\d)",y:"(\\d{2})"},w={Z:function(e){return e.toISOString()},D:function(e,t,n){return t.weekdays.shorthand[w.w(e,t,n)]},F:function(e,t,n){return h(w.n(e,t,n)-1,!1,t)},G:function(e,t,n){return o(w.h(e,t,n))},H:function(e){return o(e.getHours())},J:function(e,t){return void 0!==t.ordinal?e.getDate()+t.ordinal(e.getDate()):e.getDate()},K:function(e,t){return t.amPM[r(e.getHours()>11)]},M:function(e,t){return h(e.getMonth(),!0,t)},S:function(e){return o(e.getSeconds())},U:function(e){return e.getTime()/1e3},W:function(e,t,n){return n.getWeek(e)},Y:function(e){return o(e.getFullYear(),4)},d:function(e){return o(e.getDate())},h:function(e){return e.getHours()%12?e.getHours()%12:12},i:function(e){return o(e.getMinutes())},j:function(e){return e.getDate()},l:function(e,t){return t.weekdays.longhand[e.getDay()]},m:function(e){return o(e.getMonth()+1)},n:function(e){return e.getMonth()+1},s:function(e){return e.getSeconds()},u:function(e){return e.getTime()},w:function(e){return e.getDay()},y:function(e){return String(e.getFullYear()).substring(2)}},b=function(e){var t=e.config,n=void 0===t?a:t,o=e.l10n,r=void 0===o?i:o,l=e.isMobile,c=void 0!==l&&l;return function(e,t,a){var i=a||r;return void 0===n.formatDate||c?t.split("").map((function(t,a,o){return w[t]&&"\\"!==o[a-1]?w[t](e,i,n):"\\"!==t?t:""})).join(""):n.formatDate(e,t,i)}},C=function(e){var t=e.config,n=void 0===t?a:t,o=e.l10n,r=void 0===o?i:o;return function(e,t,i,o){if(0===e||e){var l,c=o||r,d=e;if(e instanceof Date)l=new Date(e.getTime());else if("string"!=typeof e&&void 0!==e.toFixed)l=new Date(e);else if("string"==typeof e){var s=t||(n||a).dateFormat,u=String(e).trim();if("today"===u)l=new Date,i=!0;else if(/Z$/.test(u)||/GMT$/.test(u))l=new Date(e);else if(n&&n.parseDate)l=n.parseDate(e,s);else{l=n&&n.noCalendar?new Date((new Date).setHours(0,0,0,0)):new Date((new Date).getFullYear(),0,1,0,0,0,0);for(var f=void 0,m=[],g=0,p=0,h="";g<s.length;g++){var w=s[g],b="\\"===w,C="\\"===s[g-1]||b;if(D[w]&&!C){h+=D[w];var M=new RegExp(h).exec(e);M&&(f=!0)&&m["Y"!==w?"push":"unshift"]({fn:v[w],val:M[++p]})}else b||(h+=".");m.forEach((function(e){var t=e.fn,n=e.val;return l=t(l,n,c)||l}))}l=f?l:void 0}}if(l instanceof Date&&!isNaN(l.getTime()))return!0===i&&l.setHours(0,0,0,0),l;n.errorHandler(new Error("Invalid date provided: "+d))}}};function M(e,t,n){return void 0===n&&(n=!0),!1!==n?new Date(e.getTime()).setHours(0,0,0,0)-new Date(t.getTime()).setHours(0,0,0,0):e.getTime()-t.getTime()}var y=864e5;function x(e){var t=e.defaultHour,n=e.defaultMinute,a=e.defaultSeconds;if(void 0!==e.minDate){var i=e.minDate.getHours(),o=e.minDate.getMinutes(),r=e.minDate.getSeconds();t<i&&(t=i),t===i&&n<o&&(n=o),t===i&&n===o&&a<r&&(a=e.minDate.getSeconds())}if(void 0!==e.maxDate){var l=e.maxDate.getHours(),c=e.maxDate.getMinutes();(t=Math.min(t,l))===l&&(n=Math.min(c,n)),t===l&&n===c&&(a=e.maxDate.getSeconds())}return{hours:t,minutes:n,seconds:a}}"function"!=typeof Object.assign&&(Object.assign=function(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];if(!e)throw TypeError("Cannot convert undefined or null to object");for(var a=function(t){t&&Object.keys(t).forEach((function(n){return e[n]=t[n]}))},i=0,o=t;i<o.length;i++){var r=o[i];a(r)}return e});function E(p,v){var w={config:e(e({},a),T.defaultConfig),l10n:i};function E(e){return e.bind(w)}function k(){var e=w.config;!1===e.weekNumbers&&1===e.showMonths||!0!==e.noCalendar&&window.requestAnimationFrame((function(){if(void 0!==w.calendarContainer&&(w.calendarContainer.style.visibility="hidden",w.calendarContainer.style.display="block"),void 0!==w.daysContainer){var t=(w.days.offsetWidth+1)*e.showMonths;w.daysContainer.style.width=t+"px",w.calendarContainer.style.width=t+(void 0!==w.weekWrapper?w.weekWrapper.offsetWidth:0)+"px",w.calendarContainer.style.removeProperty("visibility"),w.calendarContainer.style.removeProperty("display")}}))}function I(e){if(0===w.selectedDates.length){var t=void 0===w.config.minDate||M(new Date,w.config.minDate)>=0?new Date:new Date(w.config.minDate.getTime()),n=x(w.config);t.setHours(n.hours,n.minutes,n.seconds,t.getMilliseconds()),w.selectedDates=[t],w.latestSelectedDateObj=t}void 0!==e&&"blur"!==e.type&&function(e){e.preventDefault();var t="keydown"===e.type,n=g(e),a=n;void 0!==w.amPM&&n===w.amPM&&(w.amPM.textContent=w.l10n.amPM[r(w.amPM.textContent===w.l10n.amPM[0])]);var i=parseFloat(a.getAttribute("min")),l=parseFloat(a.getAttribute("max")),c=parseFloat(a.getAttribute("step")),d=parseInt(a.value,10),s=e.delta||(t?38===e.which?1:-1:0),u=d+c*s;if(void 0!==a.value&&2===a.value.length){var f=a===w.hourElement,m=a===w.minuteElement;u<i?(u=l+u+r(!f)+(r(f)&&r(!w.amPM)),m&&j(void 0,-1,w.hourElement)):u>l&&(u=a===w.hourElement?u-l-r(!w.amPM):i,m&&j(void 0,1,w.hourElement)),w.amPM&&f&&(1===c?u+d===23:Math.abs(u-d)>c)&&(w.amPM.textContent=w.l10n.amPM[r(w.amPM.textContent===w.l10n.amPM[0])]),a.value=o(u)}}(e);var a=w._input.value;S(),be(),w._input.value!==a&&w._debouncedChange()}function S(){if(void 0!==w.hourElement&&void 0!==w.minuteElement){var e,t,n=(parseInt(w.hourElement.value.slice(-2),10)||0)%24,a=(parseInt(w.minuteElement.value,10)||0)%60,i=void 0!==w.secondElement?(parseInt(w.secondElement.value,10)||0)%60:0;void 0!==w.amPM&&(e=n,t=w.amPM.textContent,n=e%12+12*r(t===w.l10n.amPM[1]));var o=void 0!==w.config.minTime||w.config.minDate&&w.minDateHasTime&&w.latestSelectedDateObj&&0===M(w.latestSelectedDateObj,w.config.minDate,!0);if(void 0!==w.config.maxTime||w.config.maxDate&&w.maxDateHasTime&&w.latestSelectedDateObj&&0===M(w.latestSelectedDateObj,w.config.maxDate,!0)){var l=void 0!==w.config.maxTime?w.config.maxTime:w.config.maxDate;(n=Math.min(n,l.getHours()))===l.getHours()&&(a=Math.min(a,l.getMinutes())),a===l.getMinutes()&&(i=Math.min(i,l.getSeconds()))}if(o){var c=void 0!==w.config.minTime?w.config.minTime:w.config.minDate;(n=Math.max(n,c.getHours()))===c.getHours()&&a<c.getMinutes()&&(a=c.getMinutes()),a===c.getMinutes()&&(i=Math.max(i,c.getSeconds()))}O(n,a,i)}}function _(e){var t=e||w.latestSelectedDateObj;t&&O(t.getHours(),t.getMinutes(),t.getSeconds())}function O(e,t,n){void 0!==w.latestSelectedDateObj&&w.latestSelectedDateObj.setHours(e%24,t,n||0,0),w.hourElement&&w.minuteElement&&!w.isMobile&&(w.hourElement.value=o(w.config.time_24hr?e:(12+e)%12+12*r(e%12==0)),w.minuteElement.value=o(t),void 0!==w.amPM&&(w.amPM.textContent=w.l10n.amPM[r(e>=12)]),void 0!==w.secondElement&&(w.secondElement.value=o(n)))}function F(e){var t=g(e),n=parseInt(t.value)+(e.delta||0);(n/1e3>1||"Enter"===e.key&&!/[^\d]/.test(n.toString()))&&Q(n)}function A(e,t,n,a){return t instanceof Array?t.forEach((function(t){return A(e,t,n,a)})):e instanceof Array?e.forEach((function(e){return A(e,t,n,a)})):(e.addEventListener(t,n,a),void w._handlers.push({remove:function(){return e.removeEventListener(t,n)}}))}function N(){pe("onChange")}function P(e,t){var n=void 0!==e?w.parseDate(e):w.latestSelectedDateObj||(w.config.minDate&&w.config.minDate>w.now?w.config.minDate:w.config.maxDate&&w.config.maxDate<w.now?w.config.maxDate:w.now),a=w.currentYear,i=w.currentMonth;try{void 0!==n&&(w.currentYear=n.getFullYear(),w.currentMonth=n.getMonth())}catch(e){e.message="Invalid date supplied: "+n,w.config.errorHandler(e)}t&&w.currentYear!==a&&(pe("onYearChange"),K()),!t||w.currentYear===a&&w.currentMonth===i||pe("onMonthChange"),w.redraw()}function Y(e){var t=g(e);~t.className.indexOf("arrow")&&j(e,t.classList.contains("arrowUp")?1:-1)}function j(e,t,n){var a=e&&g(e),i=n||a&&a.parentNode&&a.parentNode.firstChild,o=he("increment");o.delta=t,i&&i.dispatchEvent(o)}function H(e,t,n,a){var i=X(t,!0),o=s("span","flatpickr-day "+e,t.getDate().toString());return o.dateObj=t,o.$i=a,o.setAttribute("aria-label",w.formatDate(t,w.config.ariaDateFormat)),-1===e.indexOf("hidden")&&0===M(t,w.now)&&(w.todayDateElem=o,o.classList.add("today"),o.setAttribute("aria-current","date")),i?(o.tabIndex=-1,ve(t)&&(o.classList.add("selected"),w.selectedDateElem=o,"range"===w.config.mode&&(d(o,"startRange",w.selectedDates[0]&&0===M(t,w.selectedDates[0],!0)),d(o,"endRange",w.selectedDates[1]&&0===M(t,w.selectedDates[1],!0)),"nextMonthDay"===e&&o.classList.add("inRange")))):o.classList.add("flatpickr-disabled"),"range"===w.config.mode&&function(e){return!("range"!==w.config.mode||w.selectedDates.length<2)&&(M(e,w.selectedDates[0])>=0&&M(e,w.selectedDates[1])<=0)}(t)&&!ve(t)&&o.classList.add("inRange"),w.weekNumbers&&1===w.config.showMonths&&"prevMonthDay"!==e&&n%7==1&&w.weekNumbers.insertAdjacentHTML("beforeend","<span class='flatpickr-day'>"+w.config.getWeek(t)+"</span>"),pe("onDayCreate",o),o}function L(e){e.focus(),"range"===w.config.mode&&ae(e)}function W(e){for(var t=e>0?0:w.config.showMonths-1,n=e>0?w.config.showMonths:-1,a=t;a!=n;a+=e)for(var i=w.daysContainer.children[a],o=e>0?0:i.children.length-1,r=e>0?i.children.length:-1,l=o;l!=r;l+=e){var c=i.children[l];if(-1===c.className.indexOf("hidden")&&X(c.dateObj))return c}}function R(e,t){var n=ee(document.activeElement||document.body),a=void 0!==e?e:n?document.activeElement:void 0!==w.selectedDateElem&&ee(w.selectedDateElem)?w.selectedDateElem:void 0!==w.todayDateElem&&ee(w.todayDateElem)?w.todayDateElem:W(t>0?1:-1);void 0===a?w._input.focus():n?function(e,t){for(var n=-1===e.className.indexOf("Month")?e.dateObj.getMonth():w.currentMonth,a=t>0?w.config.showMonths:-1,i=t>0?1:-1,o=n-w.currentMonth;o!=a;o+=i)for(var r=w.daysContainer.children[o],l=n-w.currentMonth===o?e.$i+t:t<0?r.children.length-1:0,c=r.children.length,d=l;d>=0&&d<c&&d!=(t>0?c:-1);d+=i){var s=r.children[d];if(-1===s.className.indexOf("hidden")&&X(s.dateObj)&&Math.abs(e.$i-d)>=Math.abs(t))return L(s)}w.changeMonth(i),R(W(i),0)}(a,t):L(a)}function B(e,t){for(var n=(new Date(e,t,1).getDay()-w.l10n.firstDayOfWeek+7)%7,a=w.utils.getDaysInMonth((t-1+12)%12,e),i=w.utils.getDaysInMonth(t,e),o=window.document.createDocumentFragment(),r=w.config.showMonths>1,l=r?"prevMonthDay hidden":"prevMonthDay",c=r?"nextMonthDay hidden":"nextMonthDay",d=a+1-n,u=0;d<=a;d++,u++)o.appendChild(H(l,new Date(e,t-1,d),d,u));for(d=1;d<=i;d++,u++)o.appendChild(H("",new Date(e,t,d),d,u));for(var f=i+1;f<=42-n&&(1===w.config.showMonths||u%7!=0);f++,u++)o.appendChild(H(c,new Date(e,t+1,f%i),f,u));var m=s("div","dayContainer");return m.appendChild(o),m}function J(){if(void 0!==w.daysContainer){u(w.daysContainer),w.weekNumbers&&u(w.weekNumbers);for(var e=document.createDocumentFragment(),t=0;t<w.config.showMonths;t++){var n=new Date(w.currentYear,w.currentMonth,1);n.setMonth(w.currentMonth+t),e.appendChild(B(n.getFullYear(),n.getMonth()))}w.daysContainer.appendChild(e),w.days=w.daysContainer.firstChild,"range"===w.config.mode&&1===w.selectedDates.length&&ae()}}function K(){if(!(w.config.showMonths>1||"dropdown"!==w.config.monthSelectorType)){var e=function(e){return!(void 0!==w.config.minDate&&w.currentYear===w.config.minDate.getFullYear()&&e<w.config.minDate.getMonth())&&!(void 0!==w.config.maxDate&&w.currentYear===w.config.maxDate.getFullYear()&&e>w.config.maxDate.getMonth())};w.monthsDropdownContainer.tabIndex=-1,w.monthsDropdownContainer.innerHTML="";for(var t=0;t<12;t++)if(e(t)){var n=s("option","flatpickr-monthDropdown-month");n.value=new Date(w.currentYear,t).getMonth().toString(),n.textContent=h(t,w.config.shorthandCurrentMonth,w.l10n),n.tabIndex=-1,w.currentMonth===t&&(n.selected=!0),w.monthsDropdownContainer.appendChild(n)}}}function U(){var e,t=s("div","flatpickr-month"),n=window.document.createDocumentFragment();w.config.showMonths>1||"static"===w.config.monthSelectorType?e=s("span","cur-month"):(w.monthsDropdownContainer=s("select","flatpickr-monthDropdown-months"),w.monthsDropdownContainer.setAttribute("aria-label",w.l10n.monthAriaLabel),A(w.monthsDropdownContainer,"change",(function(e){var t=g(e),n=parseInt(t.value,10);w.changeMonth(n-w.currentMonth),pe("onMonthChange")})),K(),e=w.monthsDropdownContainer);var a=m("cur-year",{tabindex:"-1"}),i=a.getElementsByTagName("input")[0];i.setAttribute("aria-label",w.l10n.yearAriaLabel),w.config.minDate&&i.setAttribute("min",w.config.minDate.getFullYear().toString()),w.config.maxDate&&(i.setAttribute("max",w.config.maxDate.getFullYear().toString()),i.disabled=!!w.config.minDate&&w.config.minDate.getFullYear()===w.config.maxDate.getFullYear());var o=s("div","flatpickr-current-month");return o.appendChild(e),o.appendChild(a),n.appendChild(o),t.appendChild(n),{container:t,yearElement:i,monthElement:e}}function q(){u(w.monthNav),w.monthNav.appendChild(w.prevMonthNav),w.config.showMonths&&(w.yearElements=[],w.monthElements=[]);for(var e=w.config.showMonths;e--;){var t=U();w.yearElements.push(t.yearElement),w.monthElements.push(t.monthElement),w.monthNav.appendChild(t.container)}w.monthNav.appendChild(w.nextMonthNav)}function $(){w.weekdayContainer?u(w.weekdayContainer):w.weekdayContainer=s("div","flatpickr-weekdays");for(var e=w.config.showMonths;e--;){var t=s("div","flatpickr-weekdaycontainer");w.weekdayContainer.appendChild(t)}return z(),w.weekdayContainer}function z(){if(w.weekdayContainer){var e=w.l10n.firstDayOfWeek,n=t(w.l10n.weekdays.shorthand);e>0&&e<n.length&&(n=t(n.splice(e,n.length),n.splice(0,e)));for(var a=w.config.showMonths;a--;)w.weekdayContainer.children[a].innerHTML="\n <span class='flatpickr-weekday'>\n "+n.join("</span><span class='flatpickr-weekday'>")+"\n </span>\n "}}function G(e,t){void 0===t&&(t=!0);var n=t?e:e-w.currentMonth;n<0&&!0===w._hidePrevMonthArrow||n>0&&!0===w._hideNextMonthArrow||(w.currentMonth+=n,(w.currentMonth<0||w.currentMonth>11)&&(w.currentYear+=w.currentMonth>11?1:-1,w.currentMonth=(w.currentMonth+12)%12,pe("onYearChange"),K()),J(),pe("onMonthChange"),De())}function V(e){return!(!w.config.appendTo||!w.config.appendTo.contains(e))||w.calendarContainer.contains(e)}function Z(e){if(w.isOpen&&!w.config.inline){var t=g(e),n=V(t),a=t===w.input||t===w.altInput||w.element.contains(t)||e.path&&e.path.indexOf&&(~e.path.indexOf(w.input)||~e.path.indexOf(w.altInput)),i="blur"===e.type?a&&e.relatedTarget&&!V(e.relatedTarget):!a&&!n&&!V(e.relatedTarget),o=!w.config.ignoredFocusElements.some((function(e){return e.contains(t)}));i&&o&&(void 0!==w.timeContainer&&void 0!==w.minuteElement&&void 0!==w.hourElement&&""!==w.input.value&&void 0!==w.input.value&&I(),w.close(),w.config&&"range"===w.config.mode&&1===w.selectedDates.length&&(w.clear(!1),w.redraw()))}}function Q(e){if(!(!e||w.config.minDate&&e<w.config.minDate.getFullYear()||w.config.maxDate&&e>w.config.maxDate.getFullYear())){var t=e,n=w.currentYear!==t;w.currentYear=t||w.currentYear,w.config.maxDate&&w.currentYear===w.config.maxDate.getFullYear()?w.currentMonth=Math.min(w.config.maxDate.getMonth(),w.currentMonth):w.config.minDate&&w.currentYear===w.config.minDate.getFullYear()&&(w.currentMonth=Math.max(w.config.minDate.getMonth(),w.currentMonth)),n&&(w.redraw(),pe("onYearChange"),K())}}function X(e,t){var n;void 0===t&&(t=!0);var a=w.parseDate(e,void 0,t);if(w.config.minDate&&a&&M(a,w.config.minDate,void 0!==t?t:!w.minDateHasTime)<0||w.config.maxDate&&a&&M(a,w.config.maxDate,void 0!==t?t:!w.maxDateHasTime)>0)return!1;if(!w.config.enable&&0===w.config.disable.length)return!0;if(void 0===a)return!1;for(var i=!!w.config.enable,o=null!==(n=w.config.enable)&&void 0!==n?n:w.config.disable,r=0,l=void 0;r<o.length;r++){if("function"==typeof(l=o[r])&&l(a))return i;if(l instanceof Date&&void 0!==a&&l.getTime()===a.getTime())return i;if("string"==typeof l){var c=w.parseDate(l,void 0,!0);return c&&c.getTime()===a.getTime()?i:!i}if("object"==typeof l&&void 0!==a&&l.from&&l.to&&a.getTime()>=l.from.getTime()&&a.getTime()<=l.to.getTime())return i}return!i}function ee(e){return void 0!==w.daysContainer&&(-1===e.className.indexOf("hidden")&&-1===e.className.indexOf("flatpickr-disabled")&&w.daysContainer.contains(e))}function te(e){!(e.target===w._input)||!(w.selectedDates.length>0||w._input.value.length>0)||e.relatedTarget&&V(e.relatedTarget)||w.setDate(w._input.value,!0,e.target===w.altInput?w.config.altFormat:w.config.dateFormat)}function ne(e){var t=g(e),n=w.config.wrap?p.contains(t):t===w._input,a=w.config.allowInput,i=w.isOpen&&(!a||!n),o=w.config.inline&&n&&!a;if(13===e.keyCode&&n){if(a)return w.setDate(w._input.value,!0,t===w.altInput?w.config.altFormat:w.config.dateFormat),t.blur();w.open()}else if(V(t)||i||o){var r=!!w.timeContainer&&w.timeContainer.contains(t);switch(e.keyCode){case 13:r?(e.preventDefault(),I(),se()):ue(e);break;case 27:e.preventDefault(),se();break;case 8:case 46:n&&!w.config.allowInput&&(e.preventDefault(),w.clear());break;case 37:case 39:if(r||n)w.hourElement&&w.hourElement.focus();else if(e.preventDefault(),void 0!==w.daysContainer&&(!1===a||document.activeElement&&ee(document.activeElement))){var l=39===e.keyCode?1:-1;e.ctrlKey?(e.stopPropagation(),G(l),R(W(1),0)):R(void 0,l)}break;case 38:case 40:e.preventDefault();var c=40===e.keyCode?1:-1;w.daysContainer&&void 0!==t.$i||t===w.input||t===w.altInput?e.ctrlKey?(e.stopPropagation(),Q(w.currentYear-c),R(W(1),0)):r||R(void 0,7*c):t===w.currentYearElement?Q(w.currentYear-c):w.config.enableTime&&(!r&&w.hourElement&&w.hourElement.focus(),I(e),w._debouncedChange());break;case 9:if(r){var d=[w.hourElement,w.minuteElement,w.secondElement,w.amPM].concat(w.pluginElements).filter((function(e){return e})),s=d.indexOf(t);if(-1!==s){var u=d[s+(e.shiftKey?-1:1)];e.preventDefault(),(u||w._input).focus()}}else!w.config.noCalendar&&w.daysContainer&&w.daysContainer.contains(t)&&e.shiftKey&&(e.preventDefault(),w._input.focus())}}if(void 0!==w.amPM&&t===w.amPM)switch(e.key){case w.l10n.amPM[0].charAt(0):case w.l10n.amPM[0].charAt(0).toLowerCase():w.amPM.textContent=w.l10n.amPM[0],S(),be();break;case w.l10n.amPM[1].charAt(0):case w.l10n.amPM[1].charAt(0).toLowerCase():w.amPM.textContent=w.l10n.amPM[1],S(),be()}(n||V(t))&&pe("onKeyDown",e)}function ae(e){if(1===w.selectedDates.length&&(!e||e.classList.contains("flatpickr-day")&&!e.classList.contains("flatpickr-disabled"))){for(var t=e?e.dateObj.getTime():w.days.firstElementChild.dateObj.getTime(),n=w.parseDate(w.selectedDates[0],void 0,!0).getTime(),a=Math.min(t,w.selectedDates[0].getTime()),i=Math.max(t,w.selectedDates[0].getTime()),o=!1,r=0,l=0,c=a;c<i;c+=y)X(new Date(c),!0)||(o=o||c>a&&c<i,c<n&&(!r||c>r)?r=c:c>n&&(!l||c<l)&&(l=c));for(var d=0;d<w.config.showMonths;d++)for(var s=w.daysContainer.children[d],u=function(a,i){var c,d,u,f=s.children[a],m=f.dateObj.getTime(),g=r>0&&m<r||l>0&&m>l;return g?(f.classList.add("notAllowed"),["inRange","startRange","endRange"].forEach((function(e){f.classList.remove(e)})),"continue"):o&&!g?"continue":(["startRange","inRange","endRange","notAllowed"].forEach((function(e){f.classList.remove(e)})),void(void 0!==e&&(e.classList.add(t<=w.selectedDates[0].getTime()?"startRange":"endRange"),n<t&&m===n?f.classList.add("startRange"):n>t&&m===n&&f.classList.add("endRange"),m>=r&&(0===l||m<=l)&&(d=n,u=t,(c=m)>Math.min(d,u)&&c<Math.max(d,u))&&f.classList.add("inRange"))))},f=0,m=s.children.length;f<m;f++)u(f)}}function ie(){!w.isOpen||w.config.static||w.config.inline||ce()}function oe(e){return function(t){var n=w.config["_"+e+"Date"]=w.parseDate(t,w.config.dateFormat),a=w.config["_"+("min"===e?"max":"min")+"Date"];void 0!==n&&(w["min"===e?"minDateHasTime":"maxDateHasTime"]=n.getHours()>0||n.getMinutes()>0||n.getSeconds()>0),w.selectedDates&&(w.selectedDates=w.selectedDates.filter((function(e){return X(e)})),w.selectedDates.length||"min"!==e||_(n),be()),w.daysContainer&&(de(),void 0!==n?w.currentYearElement[e]=n.getFullYear().toString():w.currentYearElement.removeAttribute(e),w.currentYearElement.disabled=!!a&&void 0!==n&&a.getFullYear()===n.getFullYear())}}function re(){return w.config.wrap?p.querySelector("[data-input]"):p}function le(){"object"!=typeof w.config.locale&&void 0===T.l10ns[w.config.locale]&&w.config.errorHandler(new Error("flatpickr: invalid locale "+w.config.locale)),w.l10n=e(e({},T.l10ns.default),"object"==typeof w.config.locale?w.config.locale:"default"!==w.config.locale?T.l10ns[w.config.locale]:void 0),D.K="("+w.l10n.amPM[0]+"|"+w.l10n.amPM[1]+"|"+w.l10n.amPM[0].toLowerCase()+"|"+w.l10n.amPM[1].toLowerCase()+")",void 0===e(e({},v),JSON.parse(JSON.stringify(p.dataset||{}))).time_24hr&&void 0===T.defaultConfig.time_24hr&&(w.config.time_24hr=w.l10n.time_24hr),w.formatDate=b(w),w.parseDate=C({config:w.config,l10n:w.l10n})}function ce(e){if("function"!=typeof w.config.position){if(void 0!==w.calendarContainer){pe("onPreCalendarPosition");var t=e||w._positionElement,n=Array.prototype.reduce.call(w.calendarContainer.children,(function(e,t){return e+t.offsetHeight}),0),a=w.calendarContainer.offsetWidth,i=w.config.position.split(" "),o=i[0],r=i.length>1?i[1]:null,l=t.getBoundingClientRect(),c=window.innerHeight-l.bottom,s="above"===o||"below"!==o&&c<n&&l.top>n,u=window.pageYOffset+l.top+(s?-n-2:t.offsetHeight+2);if(d(w.calendarContainer,"arrowTop",!s),d(w.calendarContainer,"arrowBottom",s),!w.config.inline){var f=window.pageXOffset+l.left,m=!1,g=!1;"center"===r?(f-=(a-l.width)/2,m=!0):"right"===r&&(f-=a-l.width,g=!0),d(w.calendarContainer,"arrowLeft",!m&&!g),d(w.calendarContainer,"arrowCenter",m),d(w.calendarContainer,"arrowRight",g);var p=window.document.body.offsetWidth-(window.pageXOffset+l.right),h=f+a>window.document.body.offsetWidth,v=p+a>window.document.body.offsetWidth;if(d(w.calendarContainer,"rightMost",h),!w.config.static)if(w.calendarContainer.style.top=u+"px",h)if(v){var D=function(){for(var e=null,t=0;t<document.styleSheets.length;t++){var n=document.styleSheets[t];try{n.cssRules}catch(e){continue}e=n;break}return null!=e?e:(a=document.createElement("style"),document.head.appendChild(a),a.sheet);var a}();if(void 0===D)return;var b=window.document.body.offsetWidth,C=Math.max(0,b/2-a/2),M=D.cssRules.length,y="{left:"+l.left+"px;right:auto;}";d(w.calendarContainer,"rightMost",!1),d(w.calendarContainer,"centerMost",!0),D.insertRule(".flatpickr-calendar.centerMost:before,.flatpickr-calendar.centerMost:after"+y,M),w.calendarContainer.style.left=C+"px",w.calendarContainer.style.right="auto"}else w.calendarContainer.style.left="auto",w.calendarContainer.style.right=p+"px";else w.calendarContainer.style.left=f+"px",w.calendarContainer.style.right="auto"}}}else w.config.position(w,e)}function de(){w.config.noCalendar||w.isMobile||(K(),De(),J())}function se(){w._input.focus(),-1!==window.navigator.userAgent.indexOf("MSIE")||void 0!==navigator.msMaxTouchPoints?setTimeout(w.close,0):w.close()}function ue(e){e.preventDefault(),e.stopPropagation();var t=f(g(e),(function(e){return e.classList&&e.classList.contains("flatpickr-day")&&!e.classList.contains("flatpickr-disabled")&&!e.classList.contains("notAllowed")}));if(void 0!==t){var n=t,a=w.latestSelectedDateObj=new Date(n.dateObj.getTime()),i=(a.getMonth()<w.currentMonth||a.getMonth()>w.currentMonth+w.config.showMonths-1)&&"range"!==w.config.mode;if(w.selectedDateElem=n,"single"===w.config.mode)w.selectedDates=[a];else if("multiple"===w.config.mode){var o=ve(a);o?w.selectedDates.splice(parseInt(o),1):w.selectedDates.push(a)}else"range"===w.config.mode&&(2===w.selectedDates.length&&w.clear(!1,!1),w.latestSelectedDateObj=a,w.selectedDates.push(a),0!==M(a,w.selectedDates[0],!0)&&w.selectedDates.sort((function(e,t){return e.getTime()-t.getTime()})));if(S(),i){var r=w.currentYear!==a.getFullYear();w.currentYear=a.getFullYear(),w.currentMonth=a.getMonth(),r&&(pe("onYearChange"),K()),pe("onMonthChange")}if(De(),J(),be(),i||"range"===w.config.mode||1!==w.config.showMonths?void 0!==w.selectedDateElem&&void 0===w.hourElement&&w.selectedDateElem&&w.selectedDateElem.focus():L(n),void 0!==w.hourElement&&void 0!==w.hourElement&&w.hourElement.focus(),w.config.closeOnSelect){var l="single"===w.config.mode&&!w.config.enableTime,c="range"===w.config.mode&&2===w.selectedDates.length&&!w.config.enableTime;(l||c)&&se()}N()}}w.parseDate=C({config:w.config,l10n:w.l10n}),w._handlers=[],w.pluginElements=[],w.loadedPlugins=[],w._bind=A,w._setHoursFromDate=_,w._positionCalendar=ce,w.changeMonth=G,w.changeYear=Q,w.clear=function(e,t){void 0===e&&(e=!0);void 0===t&&(t=!0);w.input.value="",void 0!==w.altInput&&(w.altInput.value="");void 0!==w.mobileInput&&(w.mobileInput.value="");w.selectedDates=[],w.latestSelectedDateObj=void 0,!0===t&&(w.currentYear=w._initialDate.getFullYear(),w.currentMonth=w._initialDate.getMonth());if(!0===w.config.enableTime){var n=x(w.config),a=n.hours,i=n.minutes,o=n.seconds;O(a,i,o)}w.redraw(),e&&pe("onChange")},w.close=function(){w.isOpen=!1,w.isMobile||(void 0!==w.calendarContainer&&w.calendarContainer.classList.remove("open"),void 0!==w._input&&w._input.classList.remove("active"));pe("onClose")},w._createElement=s,w.destroy=function(){void 0!==w.config&&pe("onDestroy");for(var e=w._handlers.length;e--;)w._handlers[e].remove();if(w._handlers=[],w.mobileInput)w.mobileInput.parentNode&&w.mobileInput.parentNode.removeChild(w.mobileInput),w.mobileInput=void 0;else if(w.calendarContainer&&w.calendarContainer.parentNode)if(w.config.static&&w.calendarContainer.parentNode){var t=w.calendarContainer.parentNode;if(t.lastChild&&t.removeChild(t.lastChild),t.parentNode){for(;t.firstChild;)t.parentNode.insertBefore(t.firstChild,t);t.parentNode.removeChild(t)}}else w.calendarContainer.parentNode.removeChild(w.calendarContainer);w.altInput&&(w.input.type="text",w.altInput.parentNode&&w.altInput.parentNode.removeChild(w.altInput),delete w.altInput);w.input&&(w.input.type=w.input._type,w.input.classList.remove("flatpickr-input"),w.input.removeAttribute("readonly"));["_showTimeInput","latestSelectedDateObj","_hideNextMonthArrow","_hidePrevMonthArrow","__hideNextMonthArrow","__hidePrevMonthArrow","isMobile","isOpen","selectedDateElem","minDateHasTime","maxDateHasTime","days","daysContainer","_input","_positionElement","innerContainer","rContainer","monthNav","todayDateElem","calendarContainer","weekdayContainer","prevMonthNav","nextMonthNav","monthsDropdownContainer","currentMonthElement","currentYearElement","navigationCurrentMonth","selectedDateElem","config"].forEach((function(e){try{delete w[e]}catch(e){}}))},w.isEnabled=X,w.jumpToDate=P,w.open=function(e,t){void 0===t&&(t=w._positionElement);if(!0===w.isMobile){if(e){e.preventDefault();var n=g(e);n&&n.blur()}return void 0!==w.mobileInput&&(w.mobileInput.focus(),w.mobileInput.click()),void pe("onOpen")}if(w._input.disabled||w.config.inline)return;var a=w.isOpen;w.isOpen=!0,a||(w.calendarContainer.classList.add("open"),w._input.classList.add("active"),pe("onOpen"),ce(t));!0===w.config.enableTime&&!0===w.config.noCalendar&&(!1!==w.config.allowInput||void 0!==e&&w.timeContainer.contains(e.relatedTarget)||setTimeout((function(){return w.hourElement.select()}),50))},w.redraw=de,w.set=function(e,t){if(null!==e&&"object"==typeof e)for(var a in Object.assign(w.config,e),e)void 0!==fe[a]&&fe[a].forEach((function(e){return e()}));else w.config[e]=t,void 0!==fe[e]?fe[e].forEach((function(e){return e()})):n.indexOf(e)>-1&&(w.config[e]=c(t));w.redraw(),be(!0)},w.setDate=function(e,t,n){void 0===t&&(t=!1);void 0===n&&(n=w.config.dateFormat);if(0!==e&&!e||e instanceof Array&&0===e.length)return w.clear(t);me(e,n),w.latestSelectedDateObj=w.selectedDates[w.selectedDates.length-1],w.redraw(),P(void 0,t),_(),0===w.selectedDates.length&&w.clear(!1);be(t),t&&pe("onChange")},w.toggle=function(e){if(!0===w.isOpen)return w.close();w.open(e)};var fe={locale:[le,z],showMonths:[q,k,$],minDate:[P],maxDate:[P],clickOpens:[function(){!0===w.config.clickOpens?(A(w._input,"focus",w.open),A(w._input,"click",w.open)):(w._input.removeEventListener("focus",w.open),w._input.removeEventListener("click",w.open))}]};function me(e,t){var n=[];if(e instanceof Array)n=e.map((function(e){return w.parseDate(e,t)}));else if(e instanceof Date||"number"==typeof e)n=[w.parseDate(e,t)];else if("string"==typeof e)switch(w.config.mode){case"single":case"time":n=[w.parseDate(e,t)];break;case"multiple":n=e.split(w.config.conjunction).map((function(e){return w.parseDate(e,t)}));break;case"range":n=e.split(w.l10n.rangeSeparator).map((function(e){return w.parseDate(e,t)}))}else w.config.errorHandler(new Error("Invalid date supplied: "+JSON.stringify(e)));w.selectedDates=w.config.allowInvalidPreload?n:n.filter((function(e){return e instanceof Date&&X(e,!1)})),"range"===w.config.mode&&w.selectedDates.sort((function(e,t){return e.getTime()-t.getTime()}))}function ge(e){return e.slice().map((function(e){return"string"==typeof e||"number"==typeof e||e instanceof Date?w.parseDate(e,void 0,!0):e&&"object"==typeof e&&e.from&&e.to?{from:w.parseDate(e.from,void 0),to:w.parseDate(e.to,void 0)}:e})).filter((function(e){return e}))}function pe(e,t){if(void 0!==w.config){var n=w.config[e];if(void 0!==n&&n.length>0)for(var a=0;n[a]&&a<n.length;a++)n[a](w.selectedDates,w.input.value,w,t);"onChange"===e&&(w.input.dispatchEvent(he("change")),w.input.dispatchEvent(he("input")))}}function he(e){var t=document.createEvent("Event");return t.initEvent(e,!0,!0),t}function ve(e){for(var t=0;t<w.selectedDates.length;t++)if(0===M(w.selectedDates[t],e))return""+t;return!1}function De(){w.config.noCalendar||w.isMobile||!w.monthNav||(w.yearElements.forEach((function(e,t){var n=new Date(w.currentYear,w.currentMonth,1);n.setMonth(w.currentMonth+t),w.config.showMonths>1||"static"===w.config.monthSelectorType?w.monthElements[t].textContent=h(n.getMonth(),w.config.shorthandCurrentMonth,w.l10n)+" ":w.monthsDropdownContainer.value=n.getMonth().toString(),e.value=n.getFullYear().toString()})),w._hidePrevMonthArrow=void 0!==w.config.minDate&&(w.currentYear===w.config.minDate.getFullYear()?w.currentMonth<=w.config.minDate.getMonth():w.currentYear<w.config.minDate.getFullYear()),w._hideNextMonthArrow=void 0!==w.config.maxDate&&(w.currentYear===w.config.maxDate.getFullYear()?w.currentMonth+1>w.config.maxDate.getMonth():w.currentYear>w.config.maxDate.getFullYear()))}function we(e){return w.selectedDates.map((function(t){return w.formatDate(t,e)})).filter((function(e,t,n){return"range"!==w.config.mode||w.config.enableTime||n.indexOf(e)===t})).join("range"!==w.config.mode?w.config.conjunction:w.l10n.rangeSeparator)}function be(e){void 0===e&&(e=!0),void 0!==w.mobileInput&&w.mobileFormatStr&&(w.mobileInput.value=void 0!==w.latestSelectedDateObj?w.formatDate(w.latestSelectedDateObj,w.mobileFormatStr):""),w.input.value=we(w.config.dateFormat),void 0!==w.altInput&&(w.altInput.value=we(w.config.altFormat)),!1!==e&&pe("onValueUpdate")}function Ce(e){var t=g(e),n=w.prevMonthNav.contains(t),a=w.nextMonthNav.contains(t);n||a?G(n?-1:1):w.yearElements.indexOf(t)>=0?t.select():t.classList.contains("arrowUp")?w.changeYear(w.currentYear+1):t.classList.contains("arrowDown")&&w.changeYear(w.currentYear-1)}return function(){w.element=w.input=p,w.isOpen=!1,function(){var t=["wrap","weekNumbers","allowInput","allowInvalidPreload","clickOpens","time_24hr","enableTime","noCalendar","altInput","shorthandCurrentMonth","inline","static","enableSeconds","disableMobile"],i=e(e({},JSON.parse(JSON.stringify(p.dataset||{}))),v),o={};w.config.parseDate=i.parseDate,w.config.formatDate=i.formatDate,Object.defineProperty(w.config,"enable",{get:function(){return w.config._enable},set:function(e){w.config._enable=ge(e)}}),Object.defineProperty(w.config,"disable",{get:function(){return w.config._disable},set:function(e){w.config._disable=ge(e)}});var r="time"===i.mode;if(!i.dateFormat&&(i.enableTime||r)){var l=T.defaultConfig.dateFormat||a.dateFormat;o.dateFormat=i.noCalendar||r?"H:i"+(i.enableSeconds?":S":""):l+" H:i"+(i.enableSeconds?":S":"")}if(i.altInput&&(i.enableTime||r)&&!i.altFormat){var d=T.defaultConfig.altFormat||a.altFormat;o.altFormat=i.noCalendar||r?"h:i"+(i.enableSeconds?":S K":" K"):d+" h:i"+(i.enableSeconds?":S":"")+" K"}Object.defineProperty(w.config,"minDate",{get:function(){return w.config._minDate},set:oe("min")}),Object.defineProperty(w.config,"maxDate",{get:function(){return w.config._maxDate},set:oe("max")});var s=function(e){return function(t){w.config["min"===e?"_minTime":"_maxTime"]=w.parseDate(t,"H:i:S")}};Object.defineProperty(w.config,"minTime",{get:function(){return w.config._minTime},set:s("min")}),Object.defineProperty(w.config,"maxTime",{get:function(){return w.config._maxTime},set:s("max")}),"time"===i.mode&&(w.config.noCalendar=!0,w.config.enableTime=!0);Object.assign(w.config,o,i);for(var u=0;u<t.length;u++)w.config[t[u]]=!0===w.config[t[u]]||"true"===w.config[t[u]];n.filter((function(e){return void 0!==w.config[e]})).forEach((function(e){w.config[e]=c(w.config[e]||[]).map(E)})),w.isMobile=!w.config.disableMobile&&!w.config.inline&&"single"===w.config.mode&&!w.config.disable.length&&!w.config.enable&&!w.config.weekNumbers&&/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);for(u=0;u<w.config.plugins.length;u++){var f=w.config.plugins[u](w)||{};for(var m in f)n.indexOf(m)>-1?w.config[m]=c(f[m]).map(E).concat(w.config[m]):void 0===i[m]&&(w.config[m]=f[m])}i.altInputClass||(w.config.altInputClass=re().className+" "+w.config.altInputClass);pe("onParseConfig")}(),le(),function(){if(w.input=re(),!w.input)return void w.config.errorHandler(new Error("Invalid input element specified"));w.input._type=w.input.type,w.input.type="text",w.input.classList.add("flatpickr-input"),w._input=w.input,w.config.altInput&&(w.altInput=s(w.input.nodeName,w.config.altInputClass),w._input=w.altInput,w.altInput.placeholder=w.input.placeholder,w.altInput.disabled=w.input.disabled,w.altInput.required=w.input.required,w.altInput.tabIndex=w.input.tabIndex,w.altInput.type="text",w.input.setAttribute("type","hidden"),!w.config.static&&w.input.parentNode&&w.input.parentNode.insertBefore(w.altInput,w.input.nextSibling));w.config.allowInput||w._input.setAttribute("readonly","readonly");w._positionElement=w.config.positionElement||w._input}(),function(){w.selectedDates=[],w.now=w.parseDate(w.config.now)||new Date;var e=w.config.defaultDate||("INPUT"!==w.input.nodeName&&"TEXTAREA"!==w.input.nodeName||!w.input.placeholder||w.input.value!==w.input.placeholder?w.input.value:null);e&&me(e,w.config.dateFormat);w._initialDate=w.selectedDates.length>0?w.selectedDates[0]:w.config.minDate&&w.config.minDate.getTime()>w.now.getTime()?w.config.minDate:w.config.maxDate&&w.config.maxDate.getTime()<w.now.getTime()?w.config.maxDate:w.now,w.currentYear=w._initialDate.getFullYear(),w.currentMonth=w._initialDate.getMonth(),w.selectedDates.length>0&&(w.latestSelectedDateObj=w.selectedDates[0]);void 0!==w.config.minTime&&(w.config.minTime=w.parseDate(w.config.minTime,"H:i"));void 0!==w.config.maxTime&&(w.config.maxTime=w.parseDate(w.config.maxTime,"H:i"));w.minDateHasTime=!!w.config.minDate&&(w.config.minDate.getHours()>0||w.config.minDate.getMinutes()>0||w.config.minDate.getSeconds()>0),w.maxDateHasTime=!!w.config.maxDate&&(w.config.maxDate.getHours()>0||w.config.maxDate.getMinutes()>0||w.config.maxDate.getSeconds()>0)}(),w.utils={getDaysInMonth:function(e,t){return void 0===e&&(e=w.currentMonth),void 0===t&&(t=w.currentYear),1===e&&(t%4==0&&t%100!=0||t%400==0)?29:w.l10n.daysInMonth[e]}},w.isMobile||function(){var e=window.document.createDocumentFragment();if(w.calendarContainer=s("div","flatpickr-calendar"),w.calendarContainer.tabIndex=-1,!w.config.noCalendar){if(e.appendChild((w.monthNav=s("div","flatpickr-months"),w.yearElements=[],w.monthElements=[],w.prevMonthNav=s("span","flatpickr-prev-month"),w.prevMonthNav.innerHTML=w.config.prevArrow,w.nextMonthNav=s("span","flatpickr-next-month"),w.nextMonthNav.innerHTML=w.config.nextArrow,q(),Object.defineProperty(w,"_hidePrevMonthArrow",{get:function(){return w.__hidePrevMonthArrow},set:function(e){w.__hidePrevMonthArrow!==e&&(d(w.prevMonthNav,"flatpickr-disabled",e),w.__hidePrevMonthArrow=e)}}),Object.defineProperty(w,"_hideNextMonthArrow",{get:function(){return w.__hideNextMonthArrow},set:function(e){w.__hideNextMonthArrow!==e&&(d(w.nextMonthNav,"flatpickr-disabled",e),w.__hideNextMonthArrow=e)}}),w.currentYearElement=w.yearElements[0],De(),w.monthNav)),w.innerContainer=s("div","flatpickr-innerContainer"),w.config.weekNumbers){var t=function(){w.calendarContainer.classList.add("hasWeeks");var e=s("div","flatpickr-weekwrapper");e.appendChild(s("span","flatpickr-weekday",w.l10n.weekAbbreviation));var t=s("div","flatpickr-weeks");return e.appendChild(t),{weekWrapper:e,weekNumbers:t}}(),n=t.weekWrapper,a=t.weekNumbers;w.innerContainer.appendChild(n),w.weekNumbers=a,w.weekWrapper=n}w.rContainer=s("div","flatpickr-rContainer"),w.rContainer.appendChild($()),w.daysContainer||(w.daysContainer=s("div","flatpickr-days"),w.daysContainer.tabIndex=-1),J(),w.rContainer.appendChild(w.daysContainer),w.innerContainer.appendChild(w.rContainer),e.appendChild(w.innerContainer)}w.config.enableTime&&e.appendChild(function(){w.calendarContainer.classList.add("hasTime"),w.config.noCalendar&&w.calendarContainer.classList.add("noCalendar");var e=x(w.config);w.timeContainer=s("div","flatpickr-time"),w.timeContainer.tabIndex=-1;var t=s("span","flatpickr-time-separator",":"),n=m("flatpickr-hour",{"aria-label":w.l10n.hourAriaLabel});w.hourElement=n.getElementsByTagName("input")[0];var a=m("flatpickr-minute",{"aria-label":w.l10n.minuteAriaLabel});w.minuteElement=a.getElementsByTagName("input")[0],w.hourElement.tabIndex=w.minuteElement.tabIndex=-1,w.hourElement.value=o(w.latestSelectedDateObj?w.latestSelectedDateObj.getHours():w.config.time_24hr?e.hours:function(e){switch(e%24){case 0:case 12:return 12;default:return e%12}}(e.hours)),w.minuteElement.value=o(w.latestSelectedDateObj?w.latestSelectedDateObj.getMinutes():e.minutes),w.hourElement.setAttribute("step",w.config.hourIncrement.toString()),w.minuteElement.setAttribute("step",w.config.minuteIncrement.toString()),w.hourElement.setAttribute("min",w.config.time_24hr?"0":"1"),w.hourElement.setAttribute("max",w.config.time_24hr?"23":"12"),w.hourElement.setAttribute("maxlength","2"),w.minuteElement.setAttribute("min","0"),w.minuteElement.setAttribute("max","59"),w.minuteElement.setAttribute("maxlength","2"),w.timeContainer.appendChild(n),w.timeContainer.appendChild(t),w.timeContainer.appendChild(a),w.config.time_24hr&&w.timeContainer.classList.add("time24hr");if(w.config.enableSeconds){w.timeContainer.classList.add("hasSeconds");var i=m("flatpickr-second");w.secondElement=i.getElementsByTagName("input")[0],w.secondElement.value=o(w.latestSelectedDateObj?w.latestSelectedDateObj.getSeconds():e.seconds),w.secondElement.setAttribute("step",w.minuteElement.getAttribute("step")),w.secondElement.setAttribute("min","0"),w.secondElement.setAttribute("max","59"),w.secondElement.setAttribute("maxlength","2"),w.timeContainer.appendChild(s("span","flatpickr-time-separator",":")),w.timeContainer.appendChild(i)}w.config.time_24hr||(w.amPM=s("span","flatpickr-am-pm",w.l10n.amPM[r((w.latestSelectedDateObj?w.hourElement.value:w.config.defaultHour)>11)]),w.amPM.title=w.l10n.toggleTitle,w.amPM.tabIndex=-1,w.timeContainer.appendChild(w.amPM));return w.timeContainer}());d(w.calendarContainer,"rangeMode","range"===w.config.mode),d(w.calendarContainer,"animate",!0===w.config.animate),d(w.calendarContainer,"multiMonth",w.config.showMonths>1),w.calendarContainer.appendChild(e);var i=void 0!==w.config.appendTo&&void 0!==w.config.appendTo.nodeType;if((w.config.inline||w.config.static)&&(w.calendarContainer.classList.add(w.config.inline?"inline":"static"),w.config.inline&&(!i&&w.element.parentNode?w.element.parentNode.insertBefore(w.calendarContainer,w._input.nextSibling):void 0!==w.config.appendTo&&w.config.appendTo.appendChild(w.calendarContainer)),w.config.static)){var l=s("div","flatpickr-wrapper");w.element.parentNode&&w.element.parentNode.insertBefore(l,w.element),l.appendChild(w.element),w.altInput&&l.appendChild(w.altInput),l.appendChild(w.calendarContainer)}w.config.static||w.config.inline||(void 0!==w.config.appendTo?w.config.appendTo:window.document.body).appendChild(w.calendarContainer)}(),function(){w.config.wrap&&["open","close","toggle","clear"].forEach((function(e){Array.prototype.forEach.call(w.element.querySelectorAll("[data-"+e+"]"),(function(t){return A(t,"click",w[e])}))}));if(w.isMobile)return void function(){var e=w.config.enableTime?w.config.noCalendar?"time":"datetime-local":"date";w.mobileInput=s("input",w.input.className+" flatpickr-mobile"),w.mobileInput.tabIndex=1,w.mobileInput.type=e,w.mobileInput.disabled=w.input.disabled,w.mobileInput.required=w.input.required,w.mobileInput.placeholder=w.input.placeholder,w.mobileFormatStr="datetime-local"===e?"Y-m-d\\TH:i:S":"date"===e?"Y-m-d":"H:i:S",w.selectedDates.length>0&&(w.mobileInput.defaultValue=w.mobileInput.value=w.formatDate(w.selectedDates[0],w.mobileFormatStr));w.config.minDate&&(w.mobileInput.min=w.formatDate(w.config.minDate,"Y-m-d"));w.config.maxDate&&(w.mobileInput.max=w.formatDate(w.config.maxDate,"Y-m-d"));w.input.getAttribute("step")&&(w.mobileInput.step=String(w.input.getAttribute("step")));w.input.type="hidden",void 0!==w.altInput&&(w.altInput.type="hidden");try{w.input.parentNode&&w.input.parentNode.insertBefore(w.mobileInput,w.input.nextSibling)}catch(e){}A(w.mobileInput,"change",(function(e){w.setDate(g(e).value,!1,w.mobileFormatStr),pe("onChange"),pe("onClose")}))}();var e=l(ie,50);w._debouncedChange=l(N,300),w.daysContainer&&!/iPhone|iPad|iPod/i.test(navigator.userAgent)&&A(w.daysContainer,"mouseover",(function(e){"range"===w.config.mode&&ae(g(e))}));A(window.document.body,"keydown",ne),w.config.inline||w.config.static||A(window,"resize",e);void 0!==window.ontouchstart?A(window.document,"touchstart",Z):A(window.document,"mousedown",Z);A(window.document,"focus",Z,{capture:!0}),!0===w.config.clickOpens&&(A(w._input,"focus",w.open),A(w._input,"click",w.open));void 0!==w.daysContainer&&(A(w.monthNav,"click",Ce),A(w.monthNav,["keyup","increment"],F),A(w.daysContainer,"click",ue));if(void 0!==w.timeContainer&&void 0!==w.minuteElement&&void 0!==w.hourElement){var t=function(e){return g(e).select()};A(w.timeContainer,["increment"],I),A(w.timeContainer,"blur",I,{capture:!0}),A(w.timeContainer,"click",Y),A([w.hourElement,w.minuteElement],["focus","click"],t),void 0!==w.secondElement&&A(w.secondElement,"focus",(function(){return w.secondElement&&w.secondElement.select()})),void 0!==w.amPM&&A(w.amPM,"click",(function(e){I(e),N()}))}w.config.allowInput&&A(w._input,"blur",te)}(),(w.selectedDates.length||w.config.noCalendar)&&(w.config.enableTime&&_(w.config.noCalendar?w.latestSelectedDateObj:void 0),be(!1)),k();var t=/^((?!chrome|android).)*safari/i.test(navigator.userAgent);!w.isMobile&&t&&ce(),pe("onReady")}(),w}function k(e,t){for(var n=Array.prototype.slice.call(e).filter((function(e){return e instanceof HTMLElement})),a=[],i=0;i<n.length;i++){var o=n[i];try{if(null!==o.getAttribute("data-fp-omit"))continue;void 0!==o._flatpickr&&(o._flatpickr.destroy(),o._flatpickr=void 0),o._flatpickr=E(o,t||{}),a.push(o._flatpickr)}catch(e){console.error(e)}}return 1===a.length?a[0]:a}"undefined"!=typeof HTMLElement&&"undefined"!=typeof HTMLCollection&&"undefined"!=typeof NodeList&&(HTMLCollection.prototype.flatpickr=NodeList.prototype.flatpickr=function(e){return k(this,e)},HTMLElement.prototype.flatpickr=function(e){return k([this],e)});var T=function(e,t){return"string"==typeof e?k(window.document.querySelectorAll(e),t):e instanceof Node?k([e],t):k(e,t)};return T.defaultConfig={},T.l10ns={en:e({},i),default:e({},i)},T.localize=function(t){T.l10ns.default=e(e({},T.l10ns.default),t)},T.setDefaults=function(t){T.defaultConfig=e(e({},T.defaultConfig),t)},T.parseDate=C({}),T.formatDate=b({}),T.compareDates=M,"undefined"!=typeof jQuery&&void 0!==jQuery.fn&&(jQuery.fn.flatpickr=function(e){return k(this,e)}),Date.prototype.fp_incr=function(e){return new Date(this.getFullYear(),this.getMonth(),this.getDate()+("string"==typeof e?parseInt(e,10):e))},"undefined"!=typeof window&&(window.flatpickr=T),T})); \ No newline at end of file diff --git a/website/agenda/planung/js/history.js b/website/agenda/planung/js/history.js index 7a44b44..0b79ce6 100644 --- a/website/agenda/planung/js/history.js +++ b/website/agenda/planung/js/history.js @@ -1,5 +1,5 @@ function setCookie(name, value) { - document.cookie = name + "=" + value + "; " + document.cookie = name + "=" + value + "; SameSite=strict;" } function clearCookie(name) { @@ -32,43 +32,20 @@ function comeFromCalendar(){ //return history or null, if url should not be appended to history function isNewToHistory(url){ - //if (window.location.search=='')return null; - - /* - if (contains(url,"action")){ - //action defined but not show...,edit... - if ( - (!contains(url,"action=show")) - && (!contains(url,"action=edit")) - ){ - //alert("return"); - //return null; - } - } - */ var params=window.location.search; var history = getHistory(); //last page already in history - if (history[0] == url) return null; + if ( history[0] == url) return null; + //replace url in history by current one, if controller is the same var urlController=url.split('.cgi').shift(); var historyController=history[0].split('.cgi').shift(); - //remove last entry on same controller if(urlController==historyController){ - var ignore=0; - //provide back to series from series details - if(contains(url,'series')){ - //console.log(url); - //console.log(history[0]); - if( (contains(url,'series_id')==true) && (contains(history[0],'series_id')==false)) ignore=1; - //console.log(ignore); - } - if (ignore==0) history.shift(); + return null; } - return history; } @@ -101,22 +78,22 @@ function appendHistory(url, rewrite){ function showHistory(){ var history=getHistory(); - var s='<pre style="z-index:110;position:absolute;right:0;top:0">'; + var s='<pre style="z-index:110;position:absolute;right:0;top:0;padding:0">'; for (var i=5; i>=0;i--){ if(history[i]!=null) s+=i+" "+history[i]+"\n"; } s+='</pre>'; - //alert(s) $('#content').prepend(s); } function getBack(){ var history=getHistory(); - //alert("getBack") if (history.length==0)return; + //remove current page - history.shift(); + var url=history.shift(); if (history.length==0)return; + //remove previous page var url=history.shift(); setCookie("history", history.join("|")); @@ -133,11 +110,16 @@ function addBackButton(){ // add back button if history exists var history=getHistory(); //console.log(history.length); - if (history.length>1) $('#calcms_admin_menu').first().prepend( - '<div><a id="backButton" href="#" onclick="getBack();">' - +loc['button_back'] - +'</a></div>' - ); + if (history.length>1){ + $('#calcms_nav').first().prepend( + '<div><a id="backButton" href="#" onclick="getBack();">' + +'<img src="image/back.svg">' + +' ' + +loc['button_back'] + +'</a></div>' + ); + } + setupMenuHeight(); //showHistory(); } diff --git a/website/agenda/planung/js/image-upload.js b/website/agenda/planung/js/image-upload.js new file mode 100644 index 0000000..c036d17 --- /dev/null +++ b/website/agenda/planung/js/image-upload.js @@ -0,0 +1,55 @@ +function initUploadDialog(){ + var url='image-upload.cgi?project_id='+ getProjectId()+"&studio_id="+getStudioId(); + updateContainer("image-tabs-upload", url, pageLeaveHandler); +} + +function uploadImage(){ + console.log("upload") + var form=$("#img_upload"); + var fd = new FormData(form[0]); + var rq = $.ajax({ + url: 'image-upload.cgi', + type: 'POST', + data: fd, + cache: false, + contentType: false, + processData: false + }); + + rq.done( function(data){ + $("#image-tabs-upload").html(data); + + var image_id = $("#upload_image_id").html(); + var filename = $("#upload_image_filename").html(); + var title = $("#upload_image_title").html(); + var quote = "'"; + + //remove existing image from list + $('#imageList div.images #img_'+image_id).remove(); + + var url='show-image.cgi?project_id='+getProjectId()+'&studio_id='+getStudioId()+'&type=icon&filename='+filename; + + var html = '<div'; + html += ' id="img_' + image_id + '"'; + html += ' class="image" '; + html += ' title="' + title + '" '; + html += ' style="background-image:url(' + url + ')"'; + html += ' filename="' + filename + '"'; + html += '>'; + html += ' <div class="label">'+title+'</div>'; + html += '</div>'; + + //add image to list + $('#imageList div.images').prepend(html); + + console.log("done") + return false; + }); + + rq.fail( function(){ + console.log("Fail") + }); + + return false; +}; + diff --git a/website/agenda/planung/js/image.js b/website/agenda/planung/js/image.js index 2aa02b1..bec0eba 100644 --- a/website/agenda/planung/js/image.js +++ b/website/agenda/planung/js/image.js @@ -1,202 +1,208 @@ - -// choose action depending on selected tab -function imageAction(filename){ - if(selectedImageTab=='select'){ - selectThisImage(filename); - return false; - } - if(selectedImageTab=='edit'){ - editImage(filename); - return false; - } -} - // get current selected tab by tabs-id function getSelectedTab(id){ - var selector='#'+id+" li.ui-tabs-active a"; - var tabValue=$(selector).attr("value"); + var selector = '#'+id+" li.active a"; + var tabValue = $(selector).attr("value"); return tabValue; } - -//select image load into selectImage box -function selectImage(project_id, studio_id, id, value, imageUrl, series_id){ - selectImageId=id; - value=value.replace(/[^a-zA-Z0-9]/g,'%'); - var url="image.cgi?search="+encodeURIComponent(value)+'&project_id='+project_id+'&studio_id='+studio_id; - if((series_id!=null)&&(series_id != '')){ - url+='&series_id='+series_id; - } - if(imageUrl!=null){ - var filename=imageUrl.split('%2F').pop(); - url+='&filename='+filename; - } - $('#selectImage').load(url); - $('#selectImage').dialog({ - appendTo: "#content", - title:"select image", - width:"980", - height:640 - }); - return false; +function setActiveImage(elem){ + if ( !elem ) elem = $('div.images div.image').first(); + $('div.image').removeClass("active"); + $('div.image').addClass("inactive"); + elem.addClass("active"); + elem.removeClass("inactive"); } -// set editor image and image url to selected image -function selectThisImage(filename){ - var url=('/agenda_files/media/thumbs/'+filename); - $('#'+selectImageId).val(url); - $('#imagePreview').prop('src',url); - - try{ - $('#selectImage').dialog('close'); - }catch(e){ - $('#selectImage').parent().remove(); - $('html').append('<div id="selectImage"></div>'); - }; - return false; +function updateActiveImage(){ + $('div.images div.image.active').click(); } -// update selectImage container by images matching to search -function searchImage(){ - var url='image.cgi?project_id='+project_id+'&studio_id='+studio_id; +// show or edit image properties +function updateImageEditor(elem, filename, target, project_id, studio_id, series_id, event_id, pid){ + var url='image.cgi?show='+filename; + url += '&template=edit-image.html'; + url += '&target=' + target; + url += '&project_id='+project_id; + url += '&studio_id='+studio_id; + if ( (series_id != null) && (series_id != '') ) url += '&series_id='+series_id; + if ( (event_id != null) && (event_id != '') ) url += '&event_id='+event_id; + if ( (pid != null) && (pid != '') ) url += '&pid='+pid; + + console.log("updateImageEditor "+url); + + $("#img_editor").load( + url, + function(){ + setActiveImage(elem); + } + ); +} + +// build search url and load +function searchImage(target, project_id, studio_id, series_id, event_id, pid){ + var url='image.cgi?'; var value=$('#image_manager input[name=search]').val(); value=value.replace(/[^a-zA-Z0-9]/g,'%'); if (value!=null) url+='&search='+encodeURIComponent(value) - value=$('#image_manager input[name=filename]').val(); - if (value!=null) url+='&filename='+encodeURIComponent(value); + var filename=$('#image_manager input[name=filename]').val(); + var filename = filename.replace(/^.*[\\\/]/, '') + if (filename!=null) url+='&filename='+encodeURIComponent(filename); - if(selectedImageTab=='edit'){ - url+='#image-tabs-edit' - } - updateContainer('selectImage',url, function(){ - $( "#image-tabs" ).tabs(); - $( "#image-tabs" ).tabs( "option", "active", 1 ); - }); - // - return false; + url += '&target=' + target; + url += '&project_id='+project_id; + url += '&studio_id='+studio_id; + if ( (series_id != null) && (series_id != '') ) url += '&series_id='+series_id; + if ( (event_id != null) && (event_id != '') ) url += '&event_id='+event_id; + if ( (pid != null) && (pid != '') ) url += '&pid='+pid; + + + load(url); +} + +// disable public, save and update form on success +function depublishImage(id, filename){ + $('#save_img_'+id+' input[name="public"]').val("0"); + saveImage(id, filename); } -// open dialog to edit image properties -function editImage(filename){ - $("#img_editor").load( - 'image.cgi?show='+filename+'&template=image_edit.html&project_id='+project_id+'&studio_id='+studio_id, - function(){ - $('#img_editor').dialog({ - appendTo: "#content", - width:"100%", - height:430 - }); - } - ); -} - -// open dialog to show image preview -function showImage(url){ - $("#img_image").html('<img src="'+url+'" onclick="$(\'#img_image\').dialog(\'close\');return false;"/>'); - $("#img_image").dialog({ - appendTo: "#content", - width:"100%", - height:660 - }); +// enable public and save and update form on success +function publishImage(id, filename){ + $('#save_img_'+id+' input[name="public"]').val("1"); + saveImage(id, filename); } // save image function saveImage(id, filename) { - var url='image.cgi?save_image='+filename+'&project_id='+project_id+'&studio_id='+studio_id; - //remove error field - if($('#image-tabs .error').length>0){ - $('#image-tabs div.error').remove(); - } + $('#imageEditor #status').html(''); + console.log("save image "+id+" "); - if (url!='') $.post( - url, - $("#save_img_"+id).serialize(), - function(data){ - var lines=data.split(/\n/); - for (index in lines){ - var line=lines[index]; - if(contains(line,'ERROR:')){ - //add error field - if($('#image-tabs .error').length==0){ - $('#image-tabs').append('<div class="error"></div>'); + var url='image.cgi?save_image='+filename+'&project_id='+project_id+'&studio_id='+studio_id; + $.post( + url, + $("#save_img_"+id).serialize(), + function(data){ + var errorFound=0; + data.split(/\n/).forEach( + function(line){ + if(contains(line, 'ERROR:')){ + //add error field + if( $('#imageEditor #status .error').length==0 ){ + $('#imageEditor #status').append('<div class="error"></div>'); + } + $('#imageEditor #status div.error').append(line); + errorFound++; } - $('#image-tabs div.error').append(line); - } - }; - //console.log(data); - console.log("save "+id); - hideImageDetails('img_'+id, filename); - } - ); - return false; + } + ); + if (errorFound==0){ + $('#imageEditor #status').append('<div class="ok">saved</div>'); + updateActiveImage(); + } + hideImageDetails('img_'+id, filename); + } + ); + return false; } // delete image function askDeleteImage(id, filename) { - commitAction("delete image", function(){ deleteImage(id, filename) } ); + commitAction("delete image", + function(){ + deleteImage(id, filename) + } + ); } // delete image function deleteImage(id, filename) { //alert("deleteImage");return; - $("#"+id).load('image.cgi?delete_image='+filename+'&project_id='+project_id+'&studio_id='+studio_id); - hideImageDetails('img_'+id, filename); - $("#"+id).hide('drop'); - return false; + $("#"+id).load('image.cgi?delete_image='+filename+'&project_id='+project_id+'&studio_id='+studio_id); + hideImageDetails('img_'+id, filename); + $("#"+id).hide('drop'); + return false; } -// close all open dialogs -function hideImageDetails(id,filename){ - try{$('#img_editor').dialog('close');}catch(e){} - try{$('#img_image').dialog("close");}catch(e){} - - $("#"+id).load('image.cgi?show='+filename+'&template=image_single.html&project_id='+project_id+'&studio_id='+studio_id); - return false; +function hideImageDetails(id, filename){ + var url='image.cgi?show='+filename+'&template=image-single.html&project_id='+project_id+'&studio_id='+studio_id; + console.log("hideImageDetails, load url="+url) + $("#"+id).load(url); + return false; } -// show image url -function showImageUrl(id){ - var el=document.getElementById(id); - var input_id=id+'_input'; - var text='<input id="'+input_id+'" value="{{thumbs/'+id+'|title}}" title="3fach-Klick zum Markieren!">'; - if (el.innerHTML==text){ - el.innerHTML=''; - }else{ - el.innerHTML=text; - var input=document.getElementById(input_id); - input.focus(); - input.select(); - input.createTextRange().execCommand("Copy"); - } - return false; +function selectImage( searchValue, imageUrl, target, project_id, studio_id, series_id, event_id, pid){ + searchValue = searchValue.replace(/[^a-zA-Z0-9]/g,'%'); + + var url="image.cgi"; + url += "?target="+target; + url += '&project_id='+project_id + url += '&studio_id='+studio_id; + + if( (series_id!=null) && (series_id != '') ){ + url+='&series_id='+series_id; + } + if( (event_id!=null) && (event_id != '') ){ + url+='&event_id='+event_id; + } + if( (pid!=null) && (pid != '') ){ + url+='&pid='+pid; + } + + url += "&search="+encodeURIComponent(searchValue) + + if(imageUrl!=null){ + var filename=imageUrl.split('%2F').pop(); + url+='&filename='+filename; + } + load(url); } -// zoom all images in -function increaseImageSize(){ - var value=$('#content div.image').css('width'); - value=value.replace(/[^0-9]/g,''); - if(value>200)return; - value=parseInt(value*1.3); - $('#content div.image').css('width', value+'px'); - $('#content div.image div').css('width', (value-12)+'px'); - $('#content div.image').css('height', value+'px'); - $('#content div.image').css('background-size', value+'px'); +function assignImage(filename, target, project_id, studio_id, series_id, event_id, pid){ + var url = target +".cgi"; + url += "?setImage=" + filename; + url += '&project_id=' + project_id; + url += '&studio_id=' + studio_id; + + if( (series_id != null) && (series_id != '') ){ + url += '&series_id=' + series_id; + } + + if( (event_id != null) && (event_id != '') ){ + url += '&event_id=' + event_id; + } + + if( (pid!=null) && (pid != '') ){ + url+='&pid='+pid; + } + + load(url); } -// zoom all images out -function decreaseImageSize(){ - var value=$('#content div.image').css('width'); - value=value.replace(/[^0-9]/g,''); - if(value<50)return; - value=parseInt(value/1.3); - $('#content div.image').css('width', value+'px'); - $('#content div.image div').css('width', (value-12)+'px'); - $('#content div.image').css('height', value+'px'); - $('#content div.image').css('background-size', value+'px'); -} +$(document).ready( + function(){ + + $('div.images').on( 'click', 'div.image', function(){ + var elem = $(this); + var filename = elem.attr("filename"); + elem = elem.parent(); + var target = elem.attr("target"); + var projectId = elem.attr("projectId"); + var studioId = elem.attr("studioId"); + var seriesId = elem.attr("seriesId"); + var eventId = elem.attr("eventId"); + var pid = elem.attr("pid"); + + updateImageEditor($(this), filename, target, projectId, studioId, seriesId, eventId, pid); + return false; + }); + + if ( window.location.href.indexOf("&filename=") > 0) + setActiveImage(); + updateActiveImage(); + } +); diff --git a/website/agenda/planung/js/image_upload.js b/website/agenda/planung/js/image_upload.js deleted file mode 100644 index 203c8f8..0000000 --- a/website/agenda/planung/js/image_upload.js +++ /dev/null @@ -1,67 +0,0 @@ -// init upload -function initUploadDialog(){ - //console.log("init upload dialog") - if(!$('#uploader').hasClass("init")){ - $('#uploader').fileUploader(); - $('#uploader').addClass("init"); - //remove multiple buttons - var c=0; - $('#img_upload #px_button').each( - function(){ - if (c>0){ - $(this).remove(); - } - c++; - } - ); - } - return false; -} - -// prepare for new init -function closeImageUpload(){ - $('#uploader').removeClass("init"); - $('#pxupload_form').remove(); - $('#pxupload1_frame').remove(); - $('#px_display').remove(); -} - - -function insertPicture(name, description, filename) { - try { - markup='{{ thumbs//'+filename; - if (description !=''){ - markup+=' | '+description; - }else{ - if (name !='') markup+=' | '+name - } - markup+=' }}' - markup+="\n" - parent.$.markItUp( { replaceWith:markup } ); - parent.$('#images').dialog("close"); - } catch(e) { - alert("No markItUp! Editor found"); - } -} - -function image_upload_dialog(){ - $('#img_upload').dialog({ - title:"image upload", - width:600, - height:320 - }); - return false; -} - -function image_upload_callback(result){ - result.contents().find("#message").html(); - var output = '<br />' + $(this).contents().find("#message").html(); - $(id + "_text .status").html(output); -} - -$(document).ready( - function() { - //$('#uploader').fileUploader(); - } -) - diff --git a/website/agenda/planung/js/jquery-ui-timepicker.js b/website/agenda/planung/js/jquery-ui-timepicker.js deleted file mode 100644 index 9b9d97d..0000000 --- a/website/agenda/planung/js/jquery-ui-timepicker.js +++ /dev/null @@ -1,5 +0,0 @@ -/*! jQuery Timepicker Addon - v1.6.1 - 2015-11-14 -* http://trentrichardson.com/examples/timepicker -* Copyright (c) 2015 Trent Richardson; Licensed MIT */ -!function(a){"function"==typeof define&&define.amd?define(["jquery","jquery-ui"],a):a(jQuery)}(function($){if($.ui.timepicker=$.ui.timepicker||{},!$.ui.timepicker.version){$.extend($.ui,{timepicker:{version:"1.6.1"}});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",oneLine:!1,defaultValue:null,parse:"strict",afterInject:null},$.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(a){return extendRemove(this._defaults,a||{}),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(a,b){return $.isFunction(tp_inst._defaults.evnts.beforeShow)?tp_inst._defaults.evnts.beforeShow.call($input[0],a,b,tp_inst):void 0},onChangeMonthYear:function(a,b,c){$.isFunction(tp_inst._defaults.evnts.onChangeMonthYear)&&tp_inst._defaults.evnts.onChangeMonthYear.call($input[0],a,b,c,tp_inst)},onClose:function(a,b){tp_inst.timeDefined===!0&&""!==$input.val()&&tp_inst._updateDateTime(b),$.isFunction(tp_inst._defaults.evnts.onClose)&&tp_inst._defaults.evnts.onClose.call($input[0],a,b,tp_inst)}};for(i in overrides)overrides.hasOwnProperty(i)&&(fns[i]=opts[i]||this._defaults[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(a){return a.toUpperCase()}),tp_inst.pmNames=$.map(tp_inst._defaults.pmNames,function(a){return a.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&&"undefined"==typeof $.ui.slider&&(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(a){var b=$.trim(this.$altInput&&this._defaults.altFieldTimeOnly?this.$input.val()+" "+this.$altInput.val():this.$input.val());this.timeDefined=this._parseTime(b),this._limitMinMaxDateTime(a,!1),this._injectTimePicker(),this._afterInject()},_parseTime:function(a,b){if(this.inst||(this.inst=$.datepicker._getInst(this.$input[0])),b||!this._defaults.timeOnly){var c=$.datepicker._get(this.inst,"dateFormat");try{var d=parseDateTimeInternal(c,this._defaults.timeFormat,a,$.datepicker._getFormatConfig(this.inst),this._defaults);if(!d.timeObj)return!1;$.extend(this,d.timeObj)}catch(e){return $.timepicker.log("Error parsing the date/time string: "+e+"\ndate/time string = "+a+"\ntimeFormat = "+this._defaults.timeFormat+"\ndateFormat = "+c),!1}return!0}var f=$.datepicker.parseTime(this._defaults.timeFormat,a,this._defaults);return f?($.extend(this,f),!0):!1},_afterInject:function(){var a=this.inst.settings;$.isFunction(a.afterInject)&&a.afterInject.call(this)},_injectTimePicker:function(){var a=this.inst.dpDiv,b=this.inst.settings,c=this,d="",e="",f=null,g={},h={},i=null,j=0,k=0;if(0===a.find("div.ui-timepicker-div").length&&b.showTimepicker){var l=" ui_tpicker_unit_hide",m='<div class="ui-timepicker-div'+(b.isRTL?" ui-timepicker-rtl":"")+(b.oneLine&&"select"===b.controlType?" ui-timepicker-oneLine":"")+'"><dl><dt class="ui_tpicker_time_label'+(b.showTime?"":l)+'">'+b.timeText+'</dt><dd class="ui_tpicker_time '+(b.showTime?"":l)+'"><input class="ui_tpicker_time_input" '+(b.timeInput?"":"disabled")+"/></dd>";for(j=0,k=this.units.length;k>j;j++){if(d=this.units[j],e=d.substr(0,1).toUpperCase()+d.substr(1),f=null!==b["show"+e]?b["show"+e]:this.support[d],g[d]=parseInt(b[d+"Max"]-(b[d+"Max"]-b[d+"Min"])%b["step"+e],10),h[d]=0,m+='<dt class="ui_tpicker_'+d+"_label"+(f?"":l)+'">'+b[d+"Text"]+'</dt><dd class="ui_tpicker_'+d+(f?"":l)+'"><div class="ui_tpicker_'+d+"_slider"+(f?"":l)+'"></div>',f&&b[d+"Grid"]>0){if(m+='<div style="padding-left: 1px"><table class="ui-tpicker-grid-label"><tr>',"hour"===d)for(var n=b[d+"Min"];n<=g[d];n+=parseInt(b[d+"Grid"],10)){h[d]++;var o=$.datepicker.formatTime(this.support.ampm?"hht":"HH",{hour:n},b);m+='<td data-for="'+d+'">'+o+"</td>"}else for(var p=b[d+"Min"];p<=g[d];p+=parseInt(b[d+"Grid"],10))h[d]++,m+='<td data-for="'+d+'">'+(10>p?"0":"")+p+"</td>";m+="</tr></table></div>"}m+="</dd>"}var q=null!==b.showTimezone?b.showTimezone:this.support.timezone;m+='<dt class="ui_tpicker_timezone_label'+(q?"":l)+'">'+b.timezoneText+"</dt>",m+='<dd class="ui_tpicker_timezone'+(q?"":l)+'"></dd>',m+="</dl></div>";var r=$(m);for(b.timeOnly===!0&&(r.prepend('<div class="ui-widget-header ui-helper-clearfix ui-corner-all"><div class="ui-datepicker-title">'+b.timeOnlyTitle+"</div></div>"),a.find(".ui-datepicker-header, .ui-datepicker-calendar").hide()),j=0,k=c.units.length;k>j;j++)d=c.units[j],e=d.substr(0,1).toUpperCase()+d.substr(1),f=null!==b["show"+e]?b["show"+e]:this.support[d],c[d+"_slider"]=c.control.create(c,r.find(".ui_tpicker_"+d+"_slider"),d,c[d],b[d+"Min"],g[d],b["step"+e]),f&&b[d+"Grid"]>0&&(i=100*h[d]*b[d+"Grid"]/(g[d]-b[d+"Min"]),r.find(".ui_tpicker_"+d+" table").css({width:i+"%",marginLeft:b.isRTL?"0":i/(-2*h[d])+"%",marginRight:b.isRTL?i/(-2*h[d])+"%":"0",borderCollapse:"collapse"}).find("td").click(function(a){var b=$(this),e=b.html(),f=parseInt(e.replace(/[^0-9]/g),10),g=e.replace(/[^apm]/gi),h=b.data("for");"hour"===h&&(-1!==g.indexOf("p")&&12>f?f+=12:-1!==g.indexOf("a")&&12===f&&(f=0)),c.control.value(c,c[h+"_slider"],d,f),c._onTimeChange(),c._onSelectHandler()}).css({cursor:"pointer",width:100/h[d]+"%",textAlign:"center",overflow:"hidden"}));if(this.timezone_select=r.find(".ui_tpicker_timezone").append("<select></select>").find("select"),$.fn.append.apply(this.timezone_select,$.map(b.timezoneList,function(a,b){return $("<option />").val("object"==typeof a?a.value:a).text("object"==typeof a?a.label:a)})),"undefined"!=typeof this.timezone&&null!==this.timezone&&""!==this.timezone){var s=-1*new Date(this.inst.selectedYear,this.inst.selectedMonth,this.inst.selectedDay,12).getTimezoneOffset();s===this.timezone?selectLocalTimezone(c):this.timezone_select.val(this.timezone)}else"undefined"!=typeof this.hour&&null!==this.hour&&""!==this.hour?this.timezone_select.val(b.timezone):selectLocalTimezone(c);this.timezone_select.change(function(){c._onTimeChange(),c._onSelectHandler(),c._afterInject()});var t=a.find(".ui-datepicker-buttonpane");if(t.length?t.before(r):a.append(r),this.$timeObj=r.find(".ui_tpicker_time_input"),this.$timeObj.change(function(){var a=c.inst.settings.timeFormat,b=$.datepicker.parseTime(a,this.value),d=new Date;b?(d.setHours(b.hour),d.setMinutes(b.minute),d.setSeconds(b.second),$.datepicker._setTime(c.inst,d)):(this.value=c.formattedTime,this.blur())}),null!==this.inst){var u=this.timeDefined;this._onTimeChange(),this.timeDefined=u}if(this._defaults.addSliderAccess){var v=this._defaults.sliderAccessArgs,w=this._defaults.isRTL;v.isRTL=w,setTimeout(function(){if(0===r.find(".ui-slider-access").length){r.find(".ui-slider:visible").sliderAccess(v);var a=r.find(".ui-slider-access:eq(0)").outerWidth(!0);a&&r.find("table:visible").each(function(){var b=$(this),c=b.outerWidth(),d=b.css(w?"marginRight":"marginLeft").toString().replace("%",""),e=c-a,f=d*e/c+"%",g={width:e,marginRight:0,marginLeft:0};g[w?"marginRight":"marginLeft"]=f,b.css(g)})}},10)}c._limitMinMaxDateTime(this.inst,!0)}},_limitMinMaxDateTime:function(a,b){var c=this._defaults,d=new Date(a.selectedYear,a.selectedMonth,a.selectedDay);if(this._defaults.showTimepicker){if(null!==$.datepicker._get(a,"minDateTime")&&void 0!==$.datepicker._get(a,"minDateTime")&&d){var e=$.datepicker._get(a,"minDateTime"),f=new Date(e.getFullYear(),e.getMonth(),e.getDate(),0,0,0,0);(null===this.hourMinOriginal||null===this.minuteMinOriginal||null===this.secondMinOriginal||null===this.millisecMinOriginal||null===this.microsecMinOriginal)&&(this.hourMinOriginal=c.hourMin,this.minuteMinOriginal=c.minuteMin,this.secondMinOriginal=c.secondMin,this.millisecMinOriginal=c.millisecMin,this.microsecMinOriginal=c.microsecMin),a.settings.timeOnly||f.getTime()===d.getTime()?(this._defaults.hourMin=e.getHours(),this.hour<=this._defaults.hourMin?(this.hour=this._defaults.hourMin,this._defaults.minuteMin=e.getMinutes(),this.minute<=this._defaults.minuteMin?(this.minute=this._defaults.minuteMin,this._defaults.secondMin=e.getSeconds(),this.second<=this._defaults.secondMin?(this.second=this._defaults.secondMin,this._defaults.millisecMin=e.getMilliseconds(),this.millisec<=this._defaults.millisecMin?(this.millisec=this._defaults.millisecMin,this._defaults.microsecMin=e.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(a,"maxDateTime")&&void 0!==$.datepicker._get(a,"maxDateTime")&&d){var g=$.datepicker._get(a,"maxDateTime"),h=new Date(g.getFullYear(),g.getMonth(),g.getDate(),0,0,0,0);(null===this.hourMaxOriginal||null===this.minuteMaxOriginal||null===this.secondMaxOriginal||null===this.millisecMaxOriginal)&&(this.hourMaxOriginal=c.hourMax,this.minuteMaxOriginal=c.minuteMax,this.secondMaxOriginal=c.secondMax,this.millisecMaxOriginal=c.millisecMax,this.microsecMaxOriginal=c.microsecMax),a.settings.timeOnly||h.getTime()===d.getTime()?(this._defaults.hourMax=g.getHours(),this.hour>=this._defaults.hourMax?(this.hour=this._defaults.hourMax,this._defaults.minuteMax=g.getMinutes(),this.minute>=this._defaults.minuteMax?(this.minute=this._defaults.minuteMax,this._defaults.secondMax=g.getSeconds(),this.second>=this._defaults.secondMax?(this.second=this._defaults.secondMax,this._defaults.millisecMax=g.getMilliseconds(),this.millisec>=this._defaults.millisecMax?(this.millisec=this._defaults.millisecMax,this._defaults.microsecMax=g.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!==a.settings.minTime){var i=new Date("01/01/1970 "+a.settings.minTime);this.hour<i.getHours()?(this.hour=this._defaults.hourMin=i.getHours(),this.minute=this._defaults.minuteMin=i.getMinutes()):this.hour===i.getHours()&&this.minute<i.getMinutes()?this.minute=this._defaults.minuteMin=i.getMinutes():this._defaults.hourMin<i.getHours()?(this._defaults.hourMin=i.getHours(),this._defaults.minuteMin=i.getMinutes()):this._defaults.hourMin===i.getHours()===this.hour&&this._defaults.minuteMin<i.getMinutes()?this._defaults.minuteMin=i.getMinutes():this._defaults.minuteMin=0}if(null!==a.settings.maxTime){var j=new Date("01/01/1970 "+a.settings.maxTime);this.hour>j.getHours()?(this.hour=this._defaults.hourMax=j.getHours(),this.minute=this._defaults.minuteMax=j.getMinutes()):this.hour===j.getHours()&&this.minute>j.getMinutes()?this.minute=this._defaults.minuteMax=j.getMinutes():this._defaults.hourMax>j.getHours()?(this._defaults.hourMax=j.getHours(),this._defaults.minuteMax=j.getMinutes()):this._defaults.hourMax===j.getHours()===this.hour&&this._defaults.minuteMax>j.getMinutes()?this._defaults.minuteMax=j.getMinutes():this._defaults.minuteMax=59}if(void 0!==b&&b===!0){var k=parseInt(this._defaults.hourMax-(this._defaults.hourMax-this._defaults.hourMin)%this._defaults.stepHour,10),l=parseInt(this._defaults.minuteMax-(this._defaults.minuteMax-this._defaults.minuteMin)%this._defaults.stepMinute,10),m=parseInt(this._defaults.secondMax-(this._defaults.secondMax-this._defaults.secondMin)%this._defaults.stepSecond,10),n=parseInt(this._defaults.millisecMax-(this._defaults.millisecMax-this._defaults.millisecMin)%this._defaults.stepMillisec,10),o=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:k,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:l,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:m,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:n,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:o,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 a=this.hour_slider?this.control.value(this,this.hour_slider,"hour"):!1,b=this.minute_slider?this.control.value(this,this.minute_slider,"minute"):!1,c=this.second_slider?this.control.value(this,this.second_slider,"second"):!1,d=this.millisec_slider?this.control.value(this,this.millisec_slider,"millisec"):!1,e=this.microsec_slider?this.control.value(this,this.microsec_slider,"microsec"):!1,f=this.timezone_select?this.timezone_select.val():!1,g=this._defaults,h=g.pickerTimeFormat||g.timeFormat,i=g.pickerTimeSuffix||g.timeSuffix;"object"==typeof a&&(a=!1),"object"==typeof b&&(b=!1),"object"==typeof c&&(c=!1),"object"==typeof d&&(d=!1),"object"==typeof e&&(e=!1),"object"==typeof f&&(f=!1),a!==!1&&(a=parseInt(a,10)),b!==!1&&(b=parseInt(b,10)),c!==!1&&(c=parseInt(c,10)),d!==!1&&(d=parseInt(d,10)),e!==!1&&(e=parseInt(e,10)),f!==!1&&(f=f.toString());var j=g[12>a?"amNames":"pmNames"][0],k=a!==parseInt(this.hour,10)||b!==parseInt(this.minute,10)||c!==parseInt(this.second,10)||d!==parseInt(this.millisec,10)||e!==parseInt(this.microsec,10)||this.ampm.length>0&&12>a!=(-1!==$.inArray(this.ampm.toUpperCase(),this.amNames))||null!==this.timezone&&f!==this.timezone.toString();if(k&&(a!==!1&&(this.hour=a),b!==!1&&(this.minute=b),c!==!1&&(this.second=c),d!==!1&&(this.millisec=d),e!==!1&&(this.microsec=e),f!==!1&&(this.timezone=f),this.inst||(this.inst=$.datepicker._getInst(this.$input[0])),this._limitMinMaxDateTime(this.inst,!0)),this.support.ampm&&(this.ampm=j),this.formattedTime=$.datepicker.formatTime(g.timeFormat,this,g),this.$timeObj){var l=this.$timeObj[0].selectionStart,m=this.$timeObj[0].selectionEnd;h===g.timeFormat?this.$timeObj.val(this.formattedTime+i):this.$timeObj.val($.datepicker.formatTime(h,this,g)+i),this.$timeObj[0].setSelectionRange(l,m)}this.timeDefined=!0,k&&this._updateDateTime()}},_onSelectHandler:function(){var a=this._defaults.onSelect||this.inst.settings.onSelect,b=this.$input?this.$input[0]:null;a&&b&&a.apply(b,[this.formattedDateTime,this])},_updateDateTime:function(a){a=this.inst||a;var b=a.currentYear>0?new Date(a.currentYear,a.currentMonth,a.currentDay):new Date(a.selectedYear,a.selectedMonth,a.selectedDay),c=$.datepicker._daylightSavingAdjust(b),d=$.datepicker._get(a,"dateFormat"),e=$.datepicker._getFormatConfig(a),f=null!==c&&this.timeDefined;this.formattedDate=$.datepicker.formatDate(d,null===c?new Date:c,e);var g=this.formattedDate;if(""===a.lastVal&&(a.currentYear=a.selectedYear,a.currentMonth=a.selectedMonth,a.currentDay=a.selectedDay),this._defaults.timeOnly===!0&&this._defaults.timeOnlyShowDate===!1?g=this.formattedTime:(this._defaults.timeOnly!==!0&&(this._defaults.alwaysSetTime||f)||this._defaults.timeOnly===!0&&this._defaults.timeOnlyShowDate===!0)&&(g+=this._defaults.separator+this.formattedTime+this._defaults.timeSuffix),this.formattedDateTime=g,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(g);var h="",i=null!==this._defaults.altSeparator?this._defaults.altSeparator:this._defaults.separator,j=null!==this._defaults.altTimeSuffix?this._defaults.altTimeSuffix:this._defaults.timeSuffix;this._defaults.timeOnly||(h=this._defaults.altFormat?$.datepicker.formatDate(this._defaults.altFormat,null===c?new Date:c,e):this.formattedDate,h&&(h+=i)),h+=null!==this._defaults.altTimeFormat?$.datepicker.formatTime(this._defaults.altTimeFormat,this,this._defaults)+j:this.formattedTime+j,this.$altInput.val(h)}else this.$input.val(g);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 a=$.datepicker._getInst(this.$input.get(0)),b=$.datepicker._get(a,"timepicker");if(b&&b._defaults.timeOnly&&a.input.val()!==a.lastVal)try{$.datepicker._updateDatepicker(a)}catch(c){$.timepicker.log(c)}}},_controls:{slider:{create:function(a,b,c,d,e,f,g){var h=a._defaults.isRTL;return b.prop("slide",null).slider({orientation:"horizontal",value:h?-1*d:d,min:h?-1*f:e,max:h?-1*e:f,step:g,slide:function(b,d){a.control.value(a,$(this),c,h?-1*d.value:d.value),a._onTimeChange()},stop:function(b,c){a._onSelectHandler()}})},options:function(a,b,c,d,e){if(a._defaults.isRTL){if("string"==typeof d)return"min"===d||"max"===d?void 0!==e?b.slider(d,-1*e):Math.abs(b.slider(d)):b.slider(d);var f=d.min,g=d.max;return d.min=d.max=null,void 0!==f&&(d.max=-1*f),void 0!==g&&(d.min=-1*g),b.slider(d)}return"string"==typeof d&&void 0!==e?b.slider(d,e):b.slider(d)},value:function(a,b,c,d){return a._defaults.isRTL?void 0!==d?b.slider("value",-1*d):Math.abs(b.slider("value")):void 0!==d?b.slider("value",d):b.slider("value")}},select:{create:function(a,b,c,d,e,f,g){for(var h='<select class="ui-timepicker-select ui-state-default ui-corner-all" data-unit="'+c+'" data-min="'+e+'" data-max="'+f+'" data-step="'+g+'">',i=a._defaults.pickerTimeFormat||a._defaults.timeFormat,j=e;f>=j;j+=g)h+='<option value="'+j+'"'+(j===d?" selected":"")+">",h+="hour"===c?$.datepicker.formatTime($.trim(i.replace(/[^ht ]/gi,"")),{hour:j},a._defaults):"millisec"===c||"microsec"===c||j>=10?j:"0"+j.toString(),h+="</option>";return h+="</select>",b.children("select").remove(),$(h).appendTo(b).change(function(b){a._onTimeChange(),a._onSelectHandler(),a._afterInject()}),b},options:function(a,b,c,d,e){var f={},g=b.children("select");if("string"==typeof d){if(void 0===e)return g.data(d);f[d]=e}else f=d;return a.control.create(a,b,g.data("unit"),g.val(),f.min>=0?f.min:g.data("min"),f.max||g.data("max"),f.step||g.data("step"))},value:function(a,b,c,d){var e=b.children("select");return void 0!==d?e.val(d):e.val()}}}}),$.fn.extend({timepicker:function(a){a=a||{};var b=Array.prototype.slice.call(arguments);return"object"==typeof a&&(b[0]=$.extend(a,{timeOnly:!0})),$(this).each(function(){$.fn.datetimepicker.apply($(this),b)})},datetimepicker:function(a){a=a||{};var b=arguments;return"string"==typeof a?"getDate"===a||"option"===a&&2===b.length&&"string"==typeof b[1]?$.fn.datepicker.apply($(this[0]),b):this.each(function(){var a=$(this);a.datepicker.apply(a,b)}):this.each(function(){var b=$(this);b.datepicker($.timepicker._newInst(b,a)._defaults)})}}),$.datepicker.parseDateTime=function(a,b,c,d,e){var f=parseDateTimeInternal(a,b,c,d,e);if(f.timeObj){var g=f.timeObj;f.date.setHours(g.hour,g.minute,g.second,g.millisec),f.date.setMicroseconds(g.microsec)}return f.date},$.datepicker.parseTime=function(a,b,c){var d=extendRemove(extendRemove({},$.timepicker._defaults),c||{}),e=(-1!==a.replace(/\'.*?\'/g,"").indexOf("Z"),function(a,b,c){var d,e=function(a,b){var c=[];return a&&$.merge(c,a),b&&$.merge(c,b),c=$.map(c,function(a){return a.replace(/[.*+?|()\[\]{}\\]/g,"\\$&")}),"("+c.join("|")+")?"},f=function(a){var b=a.toLowerCase().match(/(h{1,2}|m{1,2}|s{1,2}|l{1}|c{1}|t{1,2}|z|'.*?')/g),c={h:-1,m:-1,s:-1,l:-1,c:-1,t:-1,z:-1};if(b)for(var d=0;d<b.length;d++)-1===c[b[d].toString().charAt(0)]&&(c[b[d].toString().charAt(0)]=d+1);return c},g="^"+a.toString().replace(/([hH]{1,2}|mm?|ss?|[tT]{1,2}|[zZ]|[lc]|'.*?')/g,function(a){var b=a.length;switch(a.charAt(0).toLowerCase()){case"h":return 1===b?"(\\d?\\d)":"(\\d{"+b+"})";case"m":return 1===b?"(\\d?\\d)":"(\\d{"+b+"})";case"s":return 1===b?"(\\d?\\d)":"(\\d{"+b+"})";case"l":return"(\\d?\\d?\\d)";case"c":return"(\\d?\\d?\\d)";case"z":return"(z|[-+]\\d\\d:?\\d\\d|\\S+)?";case"t":return e(c.amNames,c.pmNames);default:return"("+a.replace(/\'/g,"").replace(/(\.|\$|\^|\\|\/|\(|\)|\[|\]|\?|\+|\*)/g,function(a){return"\\"+a})+")?"}}).replace(/\s/g,"\\s?")+c.timeSuffix+"$",h=f(a),i="";d=b.match(new RegExp(g,"i"));var j={hour:0,minute:0,second:0,millisec:0,microsec:0};return d?(-1!==h.t&&(void 0===d[h.t]||0===d[h.t].length?(i="",j.ampm=""):(i=-1!==$.inArray(d[h.t].toUpperCase(),$.map(c.amNames,function(a,b){return a.toUpperCase()}))?"AM":"PM",j.ampm=c["AM"===i?"amNames":"pmNames"][0])),-1!==h.h&&("AM"===i&&"12"===d[h.h]?j.hour=0:"PM"===i&&"12"!==d[h.h]?j.hour=parseInt(d[h.h],10)+12:j.hour=Number(d[h.h])),-1!==h.m&&(j.minute=Number(d[h.m])),-1!==h.s&&(j.second=Number(d[h.s])),-1!==h.l&&(j.millisec=Number(d[h.l])),-1!==h.c&&(j.microsec=Number(d[h.c])),-1!==h.z&&void 0!==d[h.z]&&(j.timezone=$.timepicker.timezoneOffsetNumber(d[h.z])),j):!1}),f=function(a,b,c){try{var d=new Date("2012-01-01 "+b);if(isNaN(d.getTime())&&(d=new Date("2012-01-01T"+b),isNaN(d.getTime())&&(d=new Date("01/01/2012 "+b),isNaN(d.getTime()))))throw"Unable to parse time with native Date: "+b;return{hour:d.getHours(),minute:d.getMinutes(),second:d.getSeconds(),millisec:d.getMilliseconds(),microsec:d.getMicroseconds(),timezone:-1*d.getTimezoneOffset()}}catch(f){try{return e(a,b,c)}catch(g){$.timepicker.log("Unable to parse \ntimeString: "+b+"\ntimeFormat: "+a)}}return!1};return"function"==typeof d.parse?d.parse(a,b,d):"loose"===d.parse?f(a,b,d):e(a,b,d)},$.datepicker.formatTime=function(a,b,c){c=c||{},c=$.extend({},$.timepicker._defaults,c),b=$.extend({hour:0,minute:0,second:0,millisec:0,microsec:0,timezone:null},b);var d=a,e=c.amNames[0],f=parseInt(b.hour,10);return f>11&&(e=c.pmNames[0]),d=d.replace(/(?:HH?|hh?|mm?|ss?|[tT]{1,2}|[zZ]|[lc]|'.*?')/g,function(a){switch(a){case"HH":return("0"+f).slice(-2);case"H":return f;case"hh":return("0"+convert24to12(f)).slice(-2);case"h":return convert24to12(f);case"mm":return("0"+b.minute).slice(-2);case"m":return b.minute;case"ss":return("0"+b.second).slice(-2);case"s":return b.second;case"l":return("00"+b.millisec).slice(-3);case"c":return("00"+b.microsec).slice(-3);case"z":return $.timepicker.timezoneOffsetString(null===b.timezone?c.timezone:b.timezone,!1);case"Z":return $.timepicker.timezoneOffsetString(null===b.timezone?c.timezone:b.timezone,!0);case"T":return e.charAt(0).toUpperCase();case"TT":return e.toUpperCase();case"t":return e.charAt(0).toLowerCase();case"tt":return e.toLowerCase();default:return a.replace(/'/g,"")}})},$.datepicker._base_selectDate=$.datepicker._selectDate,$.datepicker._selectDate=function(a,b){var c,d=this._getInst($(a)[0]),e=this._get(d,"timepicker");e&&d.settings.showTimepicker?(e._limitMinMaxDateTime(d,!0),c=d.inline,d.inline=d.stay_open=!0,this._base_selectDate(a,b),d.inline=c,d.stay_open=!1,this._notifyChange(d),this._updateDatepicker(d)):this._base_selectDate(a,b)},$.datepicker._base_updateDatepicker=$.datepicker._updateDatepicker,$.datepicker._updateDatepicker=function(a){var b=a.input[0];if(!($.datepicker._curInst&&$.datepicker._curInst!==a&&$.datepicker._datepickerShowing&&$.datepicker._lastInput!==b||"boolean"==typeof a.stay_open&&a.stay_open!==!1)){this._base_updateDatepicker(a);var c=this._get(a,"timepicker");c&&c._addTimePicker(a)}},$.datepicker._base_doKeyPress=$.datepicker._doKeyPress,$.datepicker._doKeyPress=function(a){var b=$.datepicker._getInst(a.target),c=$.datepicker._get(b,"timepicker");if(c&&$.datepicker._get(b,"constrainInput")){var d=c.support.ampm,e=null!==c._defaults.showTimezone?c._defaults.showTimezone:c.support.timezone,f=$.datepicker._possibleChars($.datepicker._get(b,"dateFormat")),g=c._defaults.timeFormat.toString().replace(/[hms]/g,"").replace(/TT/g,d?"APM":"").replace(/Tt/g,d?"AaPpMm":"").replace(/tT/g,d?"AaPpMm":"").replace(/T/g,d?"AP":"").replace(/tt/g,d?"apm":"").replace(/t/g,d?"ap":"")+" "+c._defaults.separator+c._defaults.timeSuffix+(e?c._defaults.timezoneList.join(""):"")+c._defaults.amNames.join("")+c._defaults.pmNames.join("")+f,h=String.fromCharCode(void 0===a.charCode?a.keyCode:a.charCode);return a.ctrlKey||" ">h||!f||g.indexOf(h)>-1}return $.datepicker._base_doKeyPress(a)},$.datepicker._base_updateAlternate=$.datepicker._updateAlternate,$.datepicker._updateAlternate=function(a){var b=this._get(a,"timepicker");if(b){var c=b._defaults.altField;if(c){var d=(b._defaults.altFormat||b._defaults.dateFormat,this._getDate(a)),e=$.datepicker._getFormatConfig(a),f="",g=b._defaults.altSeparator?b._defaults.altSeparator:b._defaults.separator,h=b._defaults.altTimeSuffix?b._defaults.altTimeSuffix:b._defaults.timeSuffix,i=null!==b._defaults.altTimeFormat?b._defaults.altTimeFormat:b._defaults.timeFormat;f+=$.datepicker.formatTime(i,b,b._defaults)+h,b._defaults.timeOnly||b._defaults.altFieldTimeOnly||null===d||(f=b._defaults.altFormat?$.datepicker.formatDate(b._defaults.altFormat,d,e)+g+f:b.formattedDate+g+f),$(c).val(a.input.val()?f:"")}}else $.datepicker._base_updateAlternate(a)},$.datepicker._base_doKeyUp=$.datepicker._doKeyUp,$.datepicker._doKeyUp=function(a){var b=$.datepicker._getInst(a.target),c=$.datepicker._get(b,"timepicker"); -if(c&&c._defaults.timeOnly&&b.input.val()!==b.lastVal)try{$.datepicker._updateDatepicker(b)}catch(d){$.timepicker.log(d)}return $.datepicker._base_doKeyUp(a)},$.datepicker._base_gotoToday=$.datepicker._gotoToday,$.datepicker._gotoToday=function(a){var b=this._getInst($(a)[0]);this._base_gotoToday(a);var c=this._get(b,"timepicker"),d=$.timepicker.timezoneOffsetNumber(c.timezone),e=new Date;e.setMinutes(e.getMinutes()+e.getTimezoneOffset()+d),this._setTime(b,e),this._setDate(b,e),c._onSelectHandler()},$.datepicker._disableTimepickerDatepicker=function(a){var b=this._getInst(a);if(b){var c=this._get(b,"timepicker");$(a).datepicker("getDate"),c&&(b.settings.showTimepicker=!1,c._defaults.showTimepicker=!1,c._updateDateTime(b))}},$.datepicker._enableTimepickerDatepicker=function(a){var b=this._getInst(a);if(b){var c=this._get(b,"timepicker");$(a).datepicker("getDate"),c&&(b.settings.showTimepicker=!0,c._defaults.showTimepicker=!0,c._addTimePicker(b),c._updateDateTime(b))}},$.datepicker._setTime=function(a,b){var c=this._get(a,"timepicker");if(c){var d=c._defaults;c.hour=b?b.getHours():d.hour,c.minute=b?b.getMinutes():d.minute,c.second=b?b.getSeconds():d.second,c.millisec=b?b.getMilliseconds():d.millisec,c.microsec=b?b.getMicroseconds():d.microsec,c._limitMinMaxDateTime(a,!0),c._onTimeChange(),c._updateDateTime(a)}},$.datepicker._setTimeDatepicker=function(a,b,c){var d=this._getInst(a);if(d){var e=this._get(d,"timepicker");if(e){this._setDateFromField(d);var f;b&&("string"==typeof b?(e._parseTime(b,c),f=new Date,f.setHours(e.hour,e.minute,e.second,e.millisec),f.setMicroseconds(e.microsec)):(f=new Date(b.getTime()),f.setMicroseconds(b.getMicroseconds())),"Invalid Date"===f.toString()&&(f=void 0),this._setTime(d,f))}}},$.datepicker._base_setDateDatepicker=$.datepicker._setDateDatepicker,$.datepicker._setDateDatepicker=function(a,b){var c=this._getInst(a),d=b;if(c){"string"==typeof b&&(d=new Date(b),d.getTime()||(this._base_setDateDatepicker.apply(this,arguments),d=$(a).datepicker("getDate")));var e,f=this._get(c,"timepicker");d instanceof Date?(e=new Date(d.getTime()),e.setMicroseconds(d.getMicroseconds())):e=d,f&&e&&(f.support.timezone||null!==f._defaults.timezone||(f.timezone=-1*e.getTimezoneOffset()),d=$.timepicker.timezoneAdjust(d,f.timezone),e=$.timepicker.timezoneAdjust(e,f.timezone)),this._updateDatepicker(c),this._base_setDateDatepicker.apply(this,arguments),this._setTimeDatepicker(a,e,!0)}},$.datepicker._base_getDateDatepicker=$.datepicker._getDateDatepicker,$.datepicker._getDateDatepicker=function(a,b){var c=this._getInst(a);if(c){var d=this._get(c,"timepicker");if(d){void 0===c.lastVal&&this._setDateFromField(c,b);var e=this._getDate(c),f=$.trim(d.$altInput&&d._defaults.altFieldTimeOnly?d.$input.val()+" "+d.$altInput.val():d.$input.val());return e&&d._parseTime(f,!c.settings.timeOnly)&&(e.setHours(d.hour,d.minute,d.second,d.millisec),e.setMicroseconds(d.microsec),null!=d.timezone&&(d.support.timezone||null!==d._defaults.timezone||(d.timezone=-1*e.getTimezoneOffset()),e=$.timepicker.timezoneAdjust(e,d.timezone))),e}return this._base_getDateDatepicker(a,b)}},$.datepicker._base_parseDate=$.datepicker.parseDate,$.datepicker.parseDate=function(a,b,c){var d;try{d=this._base_parseDate(a,b,c)}catch(e){if(!(e.indexOf(":")>=0))throw e;d=this._base_parseDate(a,b.substring(0,b.length-(e.length-e.indexOf(":")-2)),c),$.timepicker.log("Error parsing the date string: "+e+"\ndate string = "+b+"\ndate format = "+a)}return d},$.datepicker._base_formatDate=$.datepicker._formatDate,$.datepicker._formatDate=function(a,b,c,d){var e=this._get(a,"timepicker");return e?(e._updateDateTime(a),e.$input.val()):this._base_formatDate(a)},$.datepicker._base_optionDatepicker=$.datepicker._optionDatepicker,$.datepicker._optionDatepicker=function(a,b,c){var d,e=this._getInst(a);if(!e)return null;var f=this._get(e,"timepicker");if(f){var g,h,i,j,k=null,l=null,m=null,n=f._defaults.evnts,o={};if("string"==typeof b){if("minDate"===b||"minDateTime"===b)k=c;else if("maxDate"===b||"maxDateTime"===b)l=c;else if("onSelect"===b)m=c;else if(n.hasOwnProperty(b)){if("undefined"==typeof c)return n[b];o[b]=c,d={}}}else if("object"==typeof b){b.minDate?k=b.minDate:b.minDateTime?k=b.minDateTime:b.maxDate?l=b.maxDate:b.maxDateTime&&(l=b.maxDateTime);for(g in n)n.hasOwnProperty(g)&&b[g]&&(o[g]=b[g])}for(g in o)o.hasOwnProperty(g)&&(n[g]=o[g],d||(d=$.extend({},b)),delete d[g]);if(d&&isEmptyObject(d))return;if(k?(k=0===k?new Date:new Date(k),f._defaults.minDate=k,f._defaults.minDateTime=k):l?(l=0===l?new Date:new Date(l),f._defaults.maxDate=l,f._defaults.maxDateTime=l):m&&(f._defaults.onSelect=m),k||l)return j=$(a),i=j.datetimepicker("getDate"),h=this._base_optionDatepicker.call($.datepicker,a,d||b,c),j.datetimepicker("setDate",i),h}return void 0===c?this._base_optionDatepicker.call($.datepicker,a,b):this._base_optionDatepicker.call($.datepicker,a,d||b,c)};var isEmptyObject=function(a){var b;for(b in a)if(a.hasOwnProperty(b))return!1;return!0},extendRemove=function(a,b){$.extend(a,b);for(var c in b)(null===b[c]||void 0===b[c])&&(a[c]=b[c]);return a},detectSupport=function(a){var b=a.replace(/'.*?'/g,"").toLowerCase(),c=function(a,b){return-1!==a.indexOf(b)?!0:!1};return{hour:c(b,"h"),minute:c(b,"m"),second:c(b,"s"),millisec:c(b,"l"),microsec:c(b,"c"),timezone:c(b,"z"),ampm:c(b,"t")&&c(a,"h"),iso8601:c(a,"Z")}},convert24to12=function(a){return a%=12,0===a&&(a=12),String(a)},computeEffectiveSetting=function(a,b){return a&&a[b]?a[b]:$.timepicker._defaults[b]},splitDateTime=function(a,b){var c=computeEffectiveSetting(b,"separator"),d=computeEffectiveSetting(b,"timeFormat"),e=d.split(c),f=e.length,g=a.split(c),h=g.length;return h>1?{dateString:g.splice(0,h-f).join(c),timeString:g.splice(0,f).join(c)}:{dateString:a,timeString:""}},parseDateTimeInternal=function(a,b,c,d,e){var f,g,h;if(g=splitDateTime(c,e),f=$.datepicker._base_parseDate(a,g.dateString,d),""===g.timeString)return{date:f};if(h=$.datepicker.parseTime(b,g.timeString,e),!h)throw"Wrong time format";return{date:f,timeObj:h}},selectLocalTimezone=function(a,b){if(a&&a.timezone_select){var c=b||new Date;a.timezone_select.val(-c.getTimezoneOffset())}};$.timepicker=new Timepicker,$.timepicker.timezoneOffsetString=function(a,b){if(isNaN(a)||a>840||-720>a)return a;var c=a,d=c%60,e=(c-d)/60,f=b?":":"",g=(c>=0?"+":"-")+("0"+Math.abs(e)).slice(-2)+f+("0"+Math.abs(d)).slice(-2);return"+00:00"===g?"Z":g},$.timepicker.timezoneOffsetNumber=function(a){var b=a.toString().replace(":","");return"Z"===b.toUpperCase()?0:/^(\-|\+)\d{4}$/.test(b)?("-"===b.substr(0,1)?-1:1)*(60*parseInt(b.substr(1,2),10)+parseInt(b.substr(3,2),10)):a},$.timepicker.timezoneAdjust=function(a,b){var c=$.timepicker.timezoneOffsetNumber(b);return isNaN(c)||a.setMinutes(a.getMinutes()+-a.getTimezoneOffset()-c),a},$.timepicker.timeRange=function(a,b,c){return $.timepicker.handleRange("timepicker",a,b,c)},$.timepicker.datetimeRange=function(a,b,c){$.timepicker.handleRange("datetimepicker",a,b,c)},$.timepicker.dateRange=function(a,b,c){$.timepicker.handleRange("datepicker",a,b,c)},$.timepicker.handleRange=function(a,b,c,d){function e(e,f){var g=b[a]("getDate"),h=c[a]("getDate"),i=e[a]("getDate");if(null!==g){var j=new Date(g.getTime()),k=new Date(g.getTime());j.setMilliseconds(j.getMilliseconds()+d.minInterval),k.setMilliseconds(k.getMilliseconds()+d.maxInterval),d.minInterval>0&&j>h?c[a]("setDate",j):d.maxInterval>0&&h>k?c[a]("setDate",k):g>h&&f[a]("setDate",i)}}function f(b,c,e){if(b.val()){var f=b[a].call(b,"getDate");null!==f&&d.minInterval>0&&("minDate"===e&&f.setMilliseconds(f.getMilliseconds()+d.minInterval),"maxDate"===e&&f.setMilliseconds(f.getMilliseconds()-d.minInterval)),f.getTime&&c[a].call(c,"option",e,f)}}d=$.extend({},{minInterval:0,maxInterval:0,start:{},end:{}},d);var g=!1;return"timepicker"===a&&(g=!0,a="datetimepicker"),$.fn[a].call(b,$.extend({timeOnly:g,onClose:function(a,b){e($(this),c)},onSelect:function(a){f($(this),c,"minDate")}},d,d.start)),$.fn[a].call(c,$.extend({timeOnly:g,onClose:function(a,c){e($(this),b)},onSelect:function(a){f($(this),b,"maxDate")}},d,d.end)),e(b,c),f(b,c,"minDate"),f(c,b,"maxDate"),$([b.get(0),c.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(a){return this.setMilliseconds(this.getMilliseconds()+Math.floor(a/1e3)),this.microseconds=a%1e3,this}),$.timepicker.version="1.6.1"}}); diff --git a/website/agenda/planung/js/jquery-ui.js b/website/agenda/planung/js/jquery-ui.js deleted file mode 100644 index 487c214..0000000 --- a/website/agenda/planung/js/jquery-ui.js +++ /dev/null @@ -1,16617 +0,0 @@ -/*! jQuery UI - v1.11.4 - 2016-01-24 -* http://jqueryui.com -* Includes: core.js, widget.js, mouse.js, position.js, draggable.js, droppable.js, resizable.js, selectable.js, sortable.js, accordion.js, autocomplete.js, button.js, datepicker.js, dialog.js, menu.js, progressbar.js, selectmenu.js, slider.js, spinner.js, tabs.js, tooltip.js, effect.js, effect-blind.js, effect-bounce.js, effect-clip.js, effect-drop.js, effect-explode.js, effect-fade.js, effect-fold.js, effect-highlight.js, effect-puff.js, effect-pulsate.js, effect-scale.js, effect-shake.js, effect-size.js, effect-slide.js, effect-transfer.js -* Copyright jQuery Foundation and other contributors; Licensed MIT */ - -(function( factory ) { - if ( typeof define === "function" && define.amd ) { - - // AMD. Register as an anonymous module. - define([ "jquery" ], factory ); - } else { - - // Browser globals - factory( jQuery ); - } -}(function( $ ) { -/*! - * jQuery UI Core 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/category/ui-core/ - */ - - -// $.ui might exist from components with no dependencies, e.g., $.ui.position -$.ui = $.ui || {}; - -$.extend( $.ui, { - version: "1.11.4", - - keyCode: { - BACKSPACE: 8, - COMMA: 188, - DELETE: 46, - DOWN: 40, - END: 35, - ENTER: 13, - ESCAPE: 27, - HOME: 36, - LEFT: 37, - PAGE_DOWN: 34, - PAGE_UP: 33, - PERIOD: 190, - RIGHT: 39, - SPACE: 32, - TAB: 9, - UP: 38 - } -}); - -// plugins -$.fn.extend({ - scrollParent: function( includeHidden ) { - var position = this.css( "position" ), - excludeStaticParent = position === "absolute", - overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/, - scrollParent = this.parents().filter( function() { - var parent = $( this ); - if ( excludeStaticParent && parent.css( "position" ) === "static" ) { - return false; - } - return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) + parent.css( "overflow-x" ) ); - }).eq( 0 ); - - return position === "fixed" || !scrollParent.length ? $( this[ 0 ].ownerDocument || document ) : scrollParent; - }, - - uniqueId: (function() { - var uuid = 0; - - return function() { - return this.each(function() { - if ( !this.id ) { - this.id = "ui-id-" + ( ++uuid ); - } - }); - }; - })(), - - removeUniqueId: function() { - return this.each(function() { - if ( /^ui-id-\d+$/.test( this.id ) ) { - $( this ).removeAttr( "id" ); - } - }); - } -}); - -// selectors -function focusable( element, isTabIndexNotNaN ) { - var map, mapName, img, - nodeName = element.nodeName.toLowerCase(); - if ( "area" === nodeName ) { - map = element.parentNode; - mapName = map.name; - if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) { - return false; - } - img = $( "img[usemap='#" + mapName + "']" )[ 0 ]; - return !!img && visible( img ); - } - return ( /^(input|select|textarea|button|object)$/.test( nodeName ) ? - !element.disabled : - "a" === nodeName ? - element.href || isTabIndexNotNaN : - isTabIndexNotNaN) && - // the element and all of its ancestors must be visible - visible( element ); -} - -function visible( element ) { - return $.expr.filters.visible( element ) && - !$( element ).parents().addBack().filter(function() { - return $.css( this, "visibility" ) === "hidden"; - }).length; -} - -$.extend( $.expr[ ":" ], { - data: $.expr.createPseudo ? - $.expr.createPseudo(function( dataName ) { - return function( elem ) { - return !!$.data( elem, dataName ); - }; - }) : - // support: jQuery <1.8 - function( elem, i, match ) { - return !!$.data( elem, match[ 3 ] ); - }, - - focusable: function( element ) { - return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) ); - }, - - tabbable: function( element ) { - var tabIndex = $.attr( element, "tabindex" ), - isTabIndexNaN = isNaN( tabIndex ); - return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN ); - } -}); - -// support: jQuery <1.8 -if ( !$( "<a>" ).outerWidth( 1 ).jquery ) { - $.each( [ "Width", "Height" ], function( i, name ) { - var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ], - type = name.toLowerCase(), - orig = { - innerWidth: $.fn.innerWidth, - innerHeight: $.fn.innerHeight, - outerWidth: $.fn.outerWidth, - outerHeight: $.fn.outerHeight - }; - - function reduce( elem, size, border, margin ) { - $.each( side, function() { - size -= parseFloat( $.css( elem, "padding" + this ) ) || 0; - if ( border ) { - size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0; - } - if ( margin ) { - size -= parseFloat( $.css( elem, "margin" + this ) ) || 0; - } - }); - return size; - } - - $.fn[ "inner" + name ] = function( size ) { - if ( size === undefined ) { - return orig[ "inner" + name ].call( this ); - } - - return this.each(function() { - $( this ).css( type, reduce( this, size ) + "px" ); - }); - }; - - $.fn[ "outer" + name] = function( size, margin ) { - if ( typeof size !== "number" ) { - return orig[ "outer" + name ].call( this, size ); - } - - return this.each(function() { - $( this).css( type, reduce( this, size, true, margin ) + "px" ); - }); - }; - }); -} - -// support: jQuery <1.8 -if ( !$.fn.addBack ) { - $.fn.addBack = function( selector ) { - return this.add( selector == null ? - this.prevObject : this.prevObject.filter( selector ) - ); - }; -} - -// support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413) -if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) { - $.fn.removeData = (function( removeData ) { - return function( key ) { - if ( arguments.length ) { - return removeData.call( this, $.camelCase( key ) ); - } else { - return removeData.call( this ); - } - }; - })( $.fn.removeData ); -} - -// deprecated -$.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() ); - -$.fn.extend({ - focus: (function( orig ) { - return function( delay, fn ) { - return typeof delay === "number" ? - this.each(function() { - var elem = this; - setTimeout(function() { - $( elem ).focus(); - if ( fn ) { - fn.call( elem ); - } - }, delay ); - }) : - orig.apply( this, arguments ); - }; - })( $.fn.focus ), - - disableSelection: (function() { - var eventType = "onselectstart" in document.createElement( "div" ) ? - "selectstart" : - "mousedown"; - - return function() { - return this.bind( eventType + ".ui-disableSelection", function( event ) { - event.preventDefault(); - }); - }; - })(), - - enableSelection: function() { - return this.unbind( ".ui-disableSelection" ); - }, - - zIndex: function( zIndex ) { - if ( zIndex !== undefined ) { - return this.css( "zIndex", zIndex ); - } - - if ( this.length ) { - var elem = $( this[ 0 ] ), position, value; - while ( elem.length && elem[ 0 ] !== document ) { - // Ignore z-index if position is set to a value where z-index is ignored by the browser - // This makes behavior of this function consistent across browsers - // WebKit always returns auto if the element is positioned - position = elem.css( "position" ); - if ( position === "absolute" || position === "relative" || position === "fixed" ) { - // IE returns 0 when zIndex is not specified - // other browsers return a string - // we ignore the case of nested elements with an explicit value of 0 - // <div style="z-index: -10;"><div style="z-index: 0;"></div></div> - value = parseInt( elem.css( "zIndex" ), 10 ); - if ( !isNaN( value ) && value !== 0 ) { - return value; - } - } - elem = elem.parent(); - } - } - - return 0; - } -}); - -// $.ui.plugin is deprecated. Use $.widget() extensions instead. -$.ui.plugin = { - add: function( module, option, set ) { - var i, - proto = $.ui[ module ].prototype; - for ( i in set ) { - proto.plugins[ i ] = proto.plugins[ i ] || []; - proto.plugins[ i ].push( [ option, set[ i ] ] ); - } - }, - call: function( instance, name, args, allowDisconnected ) { - var i, - set = instance.plugins[ name ]; - - if ( !set ) { - return; - } - - if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) ) { - return; - } - - for ( i = 0; i < set.length; i++ ) { - if ( instance.options[ set[ i ][ 0 ] ] ) { - set[ i ][ 1 ].apply( instance.element, args ); - } - } - } -}; - - -/*! - * jQuery UI Widget 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/jQuery.widget/ - */ - - -var widget_uuid = 0, - widget_slice = Array.prototype.slice; - -$.cleanData = (function( orig ) { - return function( elems ) { - var events, elem, i; - for ( i = 0; (elem = elems[i]) != null; i++ ) { - try { - - // Only trigger remove when necessary to save time - events = $._data( elem, "events" ); - if ( events && events.remove ) { - $( elem ).triggerHandler( "remove" ); - } - - // http://bugs.jquery.com/ticket/8235 - } catch ( e ) {} - } - orig( elems ); - }; -})( $.cleanData ); - -$.widget = function( name, base, prototype ) { - var fullName, existingConstructor, constructor, basePrototype, - // proxiedPrototype allows the provided prototype to remain unmodified - // so that it can be used as a mixin for multiple widgets (#8876) - proxiedPrototype = {}, - namespace = name.split( "." )[ 0 ]; - - name = name.split( "." )[ 1 ]; - fullName = namespace + "-" + name; - - if ( !prototype ) { - prototype = base; - base = $.Widget; - } - - // create selector for plugin - $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) { - return !!$.data( elem, fullName ); - }; - - $[ namespace ] = $[ namespace ] || {}; - existingConstructor = $[ namespace ][ name ]; - constructor = $[ namespace ][ name ] = function( options, element ) { - // allow instantiation without "new" keyword - if ( !this._createWidget ) { - return new constructor( options, element ); - } - - // allow instantiation without initializing for simple inheritance - // must use "new" keyword (the code above always passes args) - if ( arguments.length ) { - this._createWidget( options, element ); - } - }; - // extend with the existing constructor to carry over any static properties - $.extend( constructor, existingConstructor, { - version: prototype.version, - // copy the object used to create the prototype in case we need to - // redefine the widget later - _proto: $.extend( {}, prototype ), - // track widgets that inherit from this widget in case this widget is - // redefined after a widget inherits from it - _childConstructors: [] - }); - - basePrototype = new base(); - // we need to make the options hash a property directly on the new instance - // otherwise we'll modify the options hash on the prototype that we're - // inheriting from - basePrototype.options = $.widget.extend( {}, basePrototype.options ); - $.each( prototype, function( prop, value ) { - if ( !$.isFunction( value ) ) { - proxiedPrototype[ prop ] = value; - return; - } - proxiedPrototype[ prop ] = (function() { - var _super = function() { - return base.prototype[ prop ].apply( this, arguments ); - }, - _superApply = function( args ) { - return base.prototype[ prop ].apply( this, args ); - }; - return function() { - var __super = this._super, - __superApply = this._superApply, - returnValue; - - this._super = _super; - this._superApply = _superApply; - - returnValue = value.apply( this, arguments ); - - this._super = __super; - this._superApply = __superApply; - - return returnValue; - }; - })(); - }); - constructor.prototype = $.widget.extend( basePrototype, { - // TODO: remove support for widgetEventPrefix - // always use the name + a colon as the prefix, e.g., draggable:start - // don't prefix for widgets that aren't DOM-based - widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name - }, proxiedPrototype, { - constructor: constructor, - namespace: namespace, - widgetName: name, - widgetFullName: fullName - }); - - // If this widget is being redefined then we need to find all widgets that - // are inheriting from it and redefine all of them so that they inherit from - // the new version of this widget. We're essentially trying to replace one - // level in the prototype chain. - if ( existingConstructor ) { - $.each( existingConstructor._childConstructors, function( i, child ) { - var childPrototype = child.prototype; - - // redefine the child widget using the same prototype that was - // originally used, but inherit from the new version of the base - $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto ); - }); - // remove the list of existing child constructors from the old constructor - // so the old child constructors can be garbage collected - delete existingConstructor._childConstructors; - } else { - base._childConstructors.push( constructor ); - } - - $.widget.bridge( name, constructor ); - - return constructor; -}; - -$.widget.extend = function( target ) { - var input = widget_slice.call( arguments, 1 ), - inputIndex = 0, - inputLength = input.length, - key, - value; - for ( ; inputIndex < inputLength; inputIndex++ ) { - for ( key in input[ inputIndex ] ) { - value = input[ inputIndex ][ key ]; - if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) { - // Clone objects - if ( $.isPlainObject( value ) ) { - target[ key ] = $.isPlainObject( target[ key ] ) ? - $.widget.extend( {}, target[ key ], value ) : - // Don't extend strings, arrays, etc. with objects - $.widget.extend( {}, value ); - // Copy everything else by reference - } else { - target[ key ] = value; - } - } - } - } - return target; -}; - -$.widget.bridge = function( name, object ) { - var fullName = object.prototype.widgetFullName || name; - $.fn[ name ] = function( options ) { - var isMethodCall = typeof options === "string", - args = widget_slice.call( arguments, 1 ), - returnValue = this; - - if ( isMethodCall ) { - this.each(function() { - var methodValue, - instance = $.data( this, fullName ); - if ( options === "instance" ) { - returnValue = instance; - return false; - } - if ( !instance ) { - return $.error( "cannot call methods on " + name + " prior to initialization; " + - "attempted to call method '" + options + "'" ); - } - if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) { - return $.error( "no such method '" + options + "' for " + name + " widget instance" ); - } - methodValue = instance[ options ].apply( instance, args ); - if ( methodValue !== instance && methodValue !== undefined ) { - returnValue = methodValue && methodValue.jquery ? - returnValue.pushStack( methodValue.get() ) : - methodValue; - return false; - } - }); - } else { - - // Allow multiple hashes to be passed on init - if ( args.length ) { - options = $.widget.extend.apply( null, [ options ].concat(args) ); - } - - this.each(function() { - var instance = $.data( this, fullName ); - if ( instance ) { - instance.option( options || {} ); - if ( instance._init ) { - instance._init(); - } - } else { - $.data( this, fullName, new object( options, this ) ); - } - }); - } - - return returnValue; - }; -}; - -$.Widget = function( /* options, element */ ) {}; -$.Widget._childConstructors = []; - -$.Widget.prototype = { - widgetName: "widget", - widgetEventPrefix: "", - defaultElement: "<div>", - options: { - disabled: false, - - // callbacks - create: null - }, - _createWidget: function( options, element ) { - element = $( element || this.defaultElement || this )[ 0 ]; - this.element = $( element ); - this.uuid = widget_uuid++; - this.eventNamespace = "." + this.widgetName + this.uuid; - - this.bindings = $(); - this.hoverable = $(); - this.focusable = $(); - - if ( element !== this ) { - $.data( element, this.widgetFullName, this ); - this._on( true, this.element, { - remove: function( event ) { - if ( event.target === element ) { - this.destroy(); - } - } - }); - this.document = $( element.style ? - // element within the document - element.ownerDocument : - // element is window or document - element.document || element ); - this.window = $( this.document[0].defaultView || this.document[0].parentWindow ); - } - - this.options = $.widget.extend( {}, - this.options, - this._getCreateOptions(), - options ); - - this._create(); - this._trigger( "create", null, this._getCreateEventData() ); - this._init(); - }, - _getCreateOptions: $.noop, - _getCreateEventData: $.noop, - _create: $.noop, - _init: $.noop, - - destroy: function() { - this._destroy(); - // we can probably remove the unbind calls in 2.0 - // all event bindings should go through this._on() - this.element - .unbind( this.eventNamespace ) - .removeData( this.widgetFullName ) - // support: jquery <1.6.3 - // http://bugs.jquery.com/ticket/9413 - .removeData( $.camelCase( this.widgetFullName ) ); - this.widget() - .unbind( this.eventNamespace ) - .removeAttr( "aria-disabled" ) - .removeClass( - this.widgetFullName + "-disabled " + - "ui-state-disabled" ); - - // clean up events and states - this.bindings.unbind( this.eventNamespace ); - this.hoverable.removeClass( "ui-state-hover" ); - this.focusable.removeClass( "ui-state-focus" ); - }, - _destroy: $.noop, - - widget: function() { - return this.element; - }, - - option: function( key, value ) { - var options = key, - parts, - curOption, - i; - - if ( arguments.length === 0 ) { - // don't return a reference to the internal hash - return $.widget.extend( {}, this.options ); - } - - if ( typeof key === "string" ) { - // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } - options = {}; - parts = key.split( "." ); - key = parts.shift(); - if ( parts.length ) { - curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] ); - for ( i = 0; i < parts.length - 1; i++ ) { - curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {}; - curOption = curOption[ parts[ i ] ]; - } - key = parts.pop(); - if ( arguments.length === 1 ) { - return curOption[ key ] === undefined ? null : curOption[ key ]; - } - curOption[ key ] = value; - } else { - if ( arguments.length === 1 ) { - return this.options[ key ] === undefined ? null : this.options[ key ]; - } - options[ key ] = value; - } - } - - this._setOptions( options ); - - return this; - }, - _setOptions: function( options ) { - var key; - - for ( key in options ) { - this._setOption( key, options[ key ] ); - } - - return this; - }, - _setOption: function( key, value ) { - this.options[ key ] = value; - - if ( key === "disabled" ) { - this.widget() - .toggleClass( this.widgetFullName + "-disabled", !!value ); - - // If the widget is becoming disabled, then nothing is interactive - if ( value ) { - this.hoverable.removeClass( "ui-state-hover" ); - this.focusable.removeClass( "ui-state-focus" ); - } - } - - return this; - }, - - enable: function() { - return this._setOptions({ disabled: false }); - }, - disable: function() { - return this._setOptions({ disabled: true }); - }, - - _on: function( suppressDisabledCheck, element, handlers ) { - var delegateElement, - instance = this; - - // no suppressDisabledCheck flag, shuffle arguments - if ( typeof suppressDisabledCheck !== "boolean" ) { - handlers = element; - element = suppressDisabledCheck; - suppressDisabledCheck = false; - } - - // no element argument, shuffle and use this.element - if ( !handlers ) { - handlers = element; - element = this.element; - delegateElement = this.widget(); - } else { - element = delegateElement = $( element ); - this.bindings = this.bindings.add( element ); - } - - $.each( handlers, function( event, handler ) { - function handlerProxy() { - // allow widgets to customize the disabled handling - // - disabled as an array instead of boolean - // - disabled class as method for disabling individual parts - if ( !suppressDisabledCheck && - ( instance.options.disabled === true || - $( this ).hasClass( "ui-state-disabled" ) ) ) { - return; - } - return ( typeof handler === "string" ? instance[ handler ] : handler ) - .apply( instance, arguments ); - } - - // copy the guid so direct unbinding works - if ( typeof handler !== "string" ) { - handlerProxy.guid = handler.guid = - handler.guid || handlerProxy.guid || $.guid++; - } - - var match = event.match( /^([\w:-]*)\s*(.*)$/ ), - eventName = match[1] + instance.eventNamespace, - selector = match[2]; - if ( selector ) { - delegateElement.delegate( selector, eventName, handlerProxy ); - } else { - element.bind( eventName, handlerProxy ); - } - }); - }, - - _off: function( element, eventName ) { - eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + - this.eventNamespace; - element.unbind( eventName ).undelegate( eventName ); - - // Clear the stack to avoid memory leaks (#10056) - this.bindings = $( this.bindings.not( element ).get() ); - this.focusable = $( this.focusable.not( element ).get() ); - this.hoverable = $( this.hoverable.not( element ).get() ); - }, - - _delay: function( handler, delay ) { - function handlerProxy() { - return ( typeof handler === "string" ? instance[ handler ] : handler ) - .apply( instance, arguments ); - } - var instance = this; - return setTimeout( handlerProxy, delay || 0 ); - }, - - _hoverable: function( element ) { - this.hoverable = this.hoverable.add( element ); - this._on( element, { - mouseenter: function( event ) { - $( event.currentTarget ).addClass( "ui-state-hover" ); - }, - mouseleave: function( event ) { - $( event.currentTarget ).removeClass( "ui-state-hover" ); - } - }); - }, - - _focusable: function( element ) { - this.focusable = this.focusable.add( element ); - this._on( element, { - focusin: function( event ) { - $( event.currentTarget ).addClass( "ui-state-focus" ); - }, - focusout: function( event ) { - $( event.currentTarget ).removeClass( "ui-state-focus" ); - } - }); - }, - - _trigger: function( type, event, data ) { - var prop, orig, - callback = this.options[ type ]; - - data = data || {}; - event = $.Event( event ); - event.type = ( type === this.widgetEventPrefix ? - type : - this.widgetEventPrefix + type ).toLowerCase(); - // the original event may come from any element - // so we need to reset the target on the new event - event.target = this.element[ 0 ]; - - // copy original event properties over to the new event - orig = event.originalEvent; - if ( orig ) { - for ( prop in orig ) { - if ( !( prop in event ) ) { - event[ prop ] = orig[ prop ]; - } - } - } - - this.element.trigger( event, data ); - return !( $.isFunction( callback ) && - callback.apply( this.element[0], [ event ].concat( data ) ) === false || - event.isDefaultPrevented() ); - } -}; - -$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) { - $.Widget.prototype[ "_" + method ] = function( element, options, callback ) { - if ( typeof options === "string" ) { - options = { effect: options }; - } - var hasOptions, - effectName = !options ? - method : - options === true || typeof options === "number" ? - defaultEffect : - options.effect || defaultEffect; - options = options || {}; - if ( typeof options === "number" ) { - options = { duration: options }; - } - hasOptions = !$.isEmptyObject( options ); - options.complete = callback; - if ( options.delay ) { - element.delay( options.delay ); - } - if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) { - element[ method ]( options ); - } else if ( effectName !== method && element[ effectName ] ) { - element[ effectName ]( options.duration, options.easing, callback ); - } else { - element.queue(function( next ) { - $( this )[ method ](); - if ( callback ) { - callback.call( element[ 0 ] ); - } - next(); - }); - } - }; -}); - -var widget = $.widget; - - -/*! - * jQuery UI Mouse 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/mouse/ - */ - - -var mouseHandled = false; -$( document ).mouseup( function() { - mouseHandled = false; -}); - -var mouse = $.widget("ui.mouse", { - version: "1.11.4", - options: { - cancel: "input,textarea,button,select,option", - distance: 1, - delay: 0 - }, - _mouseInit: function() { - var that = this; - - this.element - .bind("mousedown." + this.widgetName, function(event) { - return that._mouseDown(event); - }) - .bind("click." + this.widgetName, function(event) { - if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) { - $.removeData(event.target, that.widgetName + ".preventClickEvent"); - event.stopImmediatePropagation(); - return false; - } - }); - - this.started = false; - }, - - // TODO: make sure destroying one instance of mouse doesn't mess with - // other instances of mouse - _mouseDestroy: function() { - this.element.unbind("." + this.widgetName); - if ( this._mouseMoveDelegate ) { - this.document - .unbind("mousemove." + this.widgetName, this._mouseMoveDelegate) - .unbind("mouseup." + this.widgetName, this._mouseUpDelegate); - } - }, - - _mouseDown: function(event) { - // don't let more than one widget handle mouseStart - if ( mouseHandled ) { - return; - } - - this._mouseMoved = false; - - // we may have missed mouseup (out of window) - (this._mouseStarted && this._mouseUp(event)); - - this._mouseDownEvent = event; - - var that = this, - btnIsLeft = (event.which === 1), - // event.target.nodeName works around a bug in IE 8 with - // disabled inputs (#7620) - elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false); - if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) { - return true; - } - - this.mouseDelayMet = !this.options.delay; - if (!this.mouseDelayMet) { - this._mouseDelayTimer = setTimeout(function() { - that.mouseDelayMet = true; - }, this.options.delay); - } - - if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { - this._mouseStarted = (this._mouseStart(event) !== false); - if (!this._mouseStarted) { - event.preventDefault(); - return true; - } - } - - // Click event may never have fired (Gecko & Opera) - if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) { - $.removeData(event.target, this.widgetName + ".preventClickEvent"); - } - - // these delegates are required to keep context - this._mouseMoveDelegate = function(event) { - return that._mouseMove(event); - }; - this._mouseUpDelegate = function(event) { - return that._mouseUp(event); - }; - - this.document - .bind( "mousemove." + this.widgetName, this._mouseMoveDelegate ) - .bind( "mouseup." + this.widgetName, this._mouseUpDelegate ); - - event.preventDefault(); - - mouseHandled = true; - return true; - }, - - _mouseMove: function(event) { - // Only check for mouseups outside the document if you've moved inside the document - // at least once. This prevents the firing of mouseup in the case of IE<9, which will - // fire a mousemove event if content is placed under the cursor. See #7778 - // Support: IE <9 - if ( this._mouseMoved ) { - // IE mouseup check - mouseup happened when mouse was out of window - if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) { - return this._mouseUp(event); - - // Iframe mouseup check - mouseup occurred in another document - } else if ( !event.which ) { - return this._mouseUp( event ); - } - } - - if ( event.which || event.button ) { - this._mouseMoved = true; - } - - if (this._mouseStarted) { - this._mouseDrag(event); - return event.preventDefault(); - } - - if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { - this._mouseStarted = - (this._mouseStart(this._mouseDownEvent, event) !== false); - (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event)); - } - - return !this._mouseStarted; - }, - - _mouseUp: function(event) { - this.document - .unbind( "mousemove." + this.widgetName, this._mouseMoveDelegate ) - .unbind( "mouseup." + this.widgetName, this._mouseUpDelegate ); - - if (this._mouseStarted) { - this._mouseStarted = false; - - if (event.target === this._mouseDownEvent.target) { - $.data(event.target, this.widgetName + ".preventClickEvent", true); - } - - this._mouseStop(event); - } - - mouseHandled = false; - return false; - }, - - _mouseDistanceMet: function(event) { - return (Math.max( - Math.abs(this._mouseDownEvent.pageX - event.pageX), - Math.abs(this._mouseDownEvent.pageY - event.pageY) - ) >= this.options.distance - ); - }, - - _mouseDelayMet: function(/* event */) { - return this.mouseDelayMet; - }, - - // These are placeholder methods, to be overriden by extending plugin - _mouseStart: function(/* event */) {}, - _mouseDrag: function(/* event */) {}, - _mouseStop: function(/* event */) {}, - _mouseCapture: function(/* event */) { return true; } -}); - - -/*! - * jQuery UI Position 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/position/ - */ - -(function() { - -$.ui = $.ui || {}; - -var cachedScrollbarWidth, supportsOffsetFractions, - max = Math.max, - abs = Math.abs, - round = Math.round, - rhorizontal = /left|center|right/, - rvertical = /top|center|bottom/, - roffset = /[\+\-]\d+(\.[\d]+)?%?/, - rposition = /^\w+/, - rpercent = /%$/, - _position = $.fn.position; - -function getOffsets( offsets, width, height ) { - return [ - parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ), - parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 ) - ]; -} - -function parseCss( element, property ) { - return parseInt( $.css( element, property ), 10 ) || 0; -} - -function getDimensions( elem ) { - var raw = elem[0]; - if ( raw.nodeType === 9 ) { - return { - width: elem.width(), - height: elem.height(), - offset: { top: 0, left: 0 } - }; - } - if ( $.isWindow( raw ) ) { - return { - width: elem.width(), - height: elem.height(), - offset: { top: elem.scrollTop(), left: elem.scrollLeft() } - }; - } - if ( raw.preventDefault ) { - return { - width: 0, - height: 0, - offset: { top: raw.pageY, left: raw.pageX } - }; - } - return { - width: elem.outerWidth(), - height: elem.outerHeight(), - offset: elem.offset() - }; -} - -$.position = { - scrollbarWidth: function() { - if ( cachedScrollbarWidth !== undefined ) { - return cachedScrollbarWidth; - } - var w1, w2, - div = $( "<div style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ), - innerDiv = div.children()[0]; - - $( "body" ).append( div ); - w1 = innerDiv.offsetWidth; - div.css( "overflow", "scroll" ); - - w2 = innerDiv.offsetWidth; - - if ( w1 === w2 ) { - w2 = div[0].clientWidth; - } - - div.remove(); - - return (cachedScrollbarWidth = w1 - w2); - }, - getScrollInfo: function( within ) { - var overflowX = within.isWindow || within.isDocument ? "" : - within.element.css( "overflow-x" ), - overflowY = within.isWindow || within.isDocument ? "" : - within.element.css( "overflow-y" ), - hasOverflowX = overflowX === "scroll" || - ( overflowX === "auto" && within.width < within.element[0].scrollWidth ), - hasOverflowY = overflowY === "scroll" || - ( overflowY === "auto" && within.height < within.element[0].scrollHeight ); - return { - width: hasOverflowY ? $.position.scrollbarWidth() : 0, - height: hasOverflowX ? $.position.scrollbarWidth() : 0 - }; - }, - getWithinInfo: function( element ) { - var withinElement = $( element || window ), - isWindow = $.isWindow( withinElement[0] ), - isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9; - return { - element: withinElement, - isWindow: isWindow, - isDocument: isDocument, - offset: withinElement.offset() || { left: 0, top: 0 }, - scrollLeft: withinElement.scrollLeft(), - scrollTop: withinElement.scrollTop(), - - // support: jQuery 1.6.x - // jQuery 1.6 doesn't support .outerWidth/Height() on documents or windows - width: isWindow || isDocument ? withinElement.width() : withinElement.outerWidth(), - height: isWindow || isDocument ? withinElement.height() : withinElement.outerHeight() - }; - } -}; - -$.fn.position = function( options ) { - if ( !options || !options.of ) { - return _position.apply( this, arguments ); - } - - // make a copy, we don't want to modify arguments - options = $.extend( {}, options ); - - var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions, - target = $( options.of ), - within = $.position.getWithinInfo( options.within ), - scrollInfo = $.position.getScrollInfo( within ), - collision = ( options.collision || "flip" ).split( " " ), - offsets = {}; - - dimensions = getDimensions( target ); - if ( target[0].preventDefault ) { - // force left top to allow flipping - options.at = "left top"; - } - targetWidth = dimensions.width; - targetHeight = dimensions.height; - targetOffset = dimensions.offset; - // clone to reuse original targetOffset later - basePosition = $.extend( {}, targetOffset ); - - // force my and at to have valid horizontal and vertical positions - // if a value is missing or invalid, it will be converted to center - $.each( [ "my", "at" ], function() { - var pos = ( options[ this ] || "" ).split( " " ), - horizontalOffset, - verticalOffset; - - if ( pos.length === 1) { - pos = rhorizontal.test( pos[ 0 ] ) ? - pos.concat( [ "center" ] ) : - rvertical.test( pos[ 0 ] ) ? - [ "center" ].concat( pos ) : - [ "center", "center" ]; - } - pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center"; - pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center"; - - // calculate offsets - horizontalOffset = roffset.exec( pos[ 0 ] ); - verticalOffset = roffset.exec( pos[ 1 ] ); - offsets[ this ] = [ - horizontalOffset ? horizontalOffset[ 0 ] : 0, - verticalOffset ? verticalOffset[ 0 ] : 0 - ]; - - // reduce to just the positions without the offsets - options[ this ] = [ - rposition.exec( pos[ 0 ] )[ 0 ], - rposition.exec( pos[ 1 ] )[ 0 ] - ]; - }); - - // normalize collision option - if ( collision.length === 1 ) { - collision[ 1 ] = collision[ 0 ]; - } - - if ( options.at[ 0 ] === "right" ) { - basePosition.left += targetWidth; - } else if ( options.at[ 0 ] === "center" ) { - basePosition.left += targetWidth / 2; - } - - if ( options.at[ 1 ] === "bottom" ) { - basePosition.top += targetHeight; - } else if ( options.at[ 1 ] === "center" ) { - basePosition.top += targetHeight / 2; - } - - atOffset = getOffsets( offsets.at, targetWidth, targetHeight ); - basePosition.left += atOffset[ 0 ]; - basePosition.top += atOffset[ 1 ]; - - return this.each(function() { - var collisionPosition, using, - elem = $( this ), - elemWidth = elem.outerWidth(), - elemHeight = elem.outerHeight(), - marginLeft = parseCss( this, "marginLeft" ), - marginTop = parseCss( this, "marginTop" ), - collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width, - collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height, - position = $.extend( {}, basePosition ), - myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() ); - - if ( options.my[ 0 ] === "right" ) { - position.left -= elemWidth; - } else if ( options.my[ 0 ] === "center" ) { - position.left -= elemWidth / 2; - } - - if ( options.my[ 1 ] === "bottom" ) { - position.top -= elemHeight; - } else if ( options.my[ 1 ] === "center" ) { - position.top -= elemHeight / 2; - } - - position.left += myOffset[ 0 ]; - position.top += myOffset[ 1 ]; - - // if the browser doesn't support fractions, then round for consistent results - if ( !supportsOffsetFractions ) { - position.left = round( position.left ); - position.top = round( position.top ); - } - - collisionPosition = { - marginLeft: marginLeft, - marginTop: marginTop - }; - - $.each( [ "left", "top" ], function( i, dir ) { - if ( $.ui.position[ collision[ i ] ] ) { - $.ui.position[ collision[ i ] ][ dir ]( position, { - targetWidth: targetWidth, - targetHeight: targetHeight, - elemWidth: elemWidth, - elemHeight: elemHeight, - collisionPosition: collisionPosition, - collisionWidth: collisionWidth, - collisionHeight: collisionHeight, - offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ], - my: options.my, - at: options.at, - within: within, - elem: elem - }); - } - }); - - if ( options.using ) { - // adds feedback as second argument to using callback, if present - using = function( props ) { - var left = targetOffset.left - position.left, - right = left + targetWidth - elemWidth, - top = targetOffset.top - position.top, - bottom = top + targetHeight - elemHeight, - feedback = { - target: { - element: target, - left: targetOffset.left, - top: targetOffset.top, - width: targetWidth, - height: targetHeight - }, - element: { - element: elem, - left: position.left, - top: position.top, - width: elemWidth, - height: elemHeight - }, - horizontal: right < 0 ? "left" : left > 0 ? "right" : "center", - vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle" - }; - if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) { - feedback.horizontal = "center"; - } - if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) { - feedback.vertical = "middle"; - } - if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) { - feedback.important = "horizontal"; - } else { - feedback.important = "vertical"; - } - options.using.call( this, props, feedback ); - }; - } - - elem.offset( $.extend( position, { using: using } ) ); - }); -}; - -$.ui.position = { - fit: { - left: function( position, data ) { - var within = data.within, - withinOffset = within.isWindow ? within.scrollLeft : within.offset.left, - outerWidth = within.width, - collisionPosLeft = position.left - data.collisionPosition.marginLeft, - overLeft = withinOffset - collisionPosLeft, - overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset, - newOverRight; - - // element is wider than within - if ( data.collisionWidth > outerWidth ) { - // element is initially over the left side of within - if ( overLeft > 0 && overRight <= 0 ) { - newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset; - position.left += overLeft - newOverRight; - // element is initially over right side of within - } else if ( overRight > 0 && overLeft <= 0 ) { - position.left = withinOffset; - // element is initially over both left and right sides of within - } else { - if ( overLeft > overRight ) { - position.left = withinOffset + outerWidth - data.collisionWidth; - } else { - position.left = withinOffset; - } - } - // too far left -> align with left edge - } else if ( overLeft > 0 ) { - position.left += overLeft; - // too far right -> align with right edge - } else if ( overRight > 0 ) { - position.left -= overRight; - // adjust based on position and margin - } else { - position.left = max( position.left - collisionPosLeft, position.left ); - } - }, - top: function( position, data ) { - var within = data.within, - withinOffset = within.isWindow ? within.scrollTop : within.offset.top, - outerHeight = data.within.height, - collisionPosTop = position.top - data.collisionPosition.marginTop, - overTop = withinOffset - collisionPosTop, - overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset, - newOverBottom; - - // element is taller than within - if ( data.collisionHeight > outerHeight ) { - // element is initially over the top of within - if ( overTop > 0 && overBottom <= 0 ) { - newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset; - position.top += overTop - newOverBottom; - // element is initially over bottom of within - } else if ( overBottom > 0 && overTop <= 0 ) { - position.top = withinOffset; - // element is initially over both top and bottom of within - } else { - if ( overTop > overBottom ) { - position.top = withinOffset + outerHeight - data.collisionHeight; - } else { - position.top = withinOffset; - } - } - // too far up -> align with top - } else if ( overTop > 0 ) { - position.top += overTop; - // too far down -> align with bottom edge - } else if ( overBottom > 0 ) { - position.top -= overBottom; - // adjust based on position and margin - } else { - position.top = max( position.top - collisionPosTop, position.top ); - } - } - }, - flip: { - left: function( position, data ) { - var within = data.within, - withinOffset = within.offset.left + within.scrollLeft, - outerWidth = within.width, - offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left, - collisionPosLeft = position.left - data.collisionPosition.marginLeft, - overLeft = collisionPosLeft - offsetLeft, - overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft, - myOffset = data.my[ 0 ] === "left" ? - -data.elemWidth : - data.my[ 0 ] === "right" ? - data.elemWidth : - 0, - atOffset = data.at[ 0 ] === "left" ? - data.targetWidth : - data.at[ 0 ] === "right" ? - -data.targetWidth : - 0, - offset = -2 * data.offset[ 0 ], - newOverRight, - newOverLeft; - - if ( overLeft < 0 ) { - newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset; - if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) { - position.left += myOffset + atOffset + offset; - } - } else if ( overRight > 0 ) { - newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft; - if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) { - position.left += myOffset + atOffset + offset; - } - } - }, - top: function( position, data ) { - var within = data.within, - withinOffset = within.offset.top + within.scrollTop, - outerHeight = within.height, - offsetTop = within.isWindow ? within.scrollTop : within.offset.top, - collisionPosTop = position.top - data.collisionPosition.marginTop, - overTop = collisionPosTop - offsetTop, - overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop, - top = data.my[ 1 ] === "top", - myOffset = top ? - -data.elemHeight : - data.my[ 1 ] === "bottom" ? - data.elemHeight : - 0, - atOffset = data.at[ 1 ] === "top" ? - data.targetHeight : - data.at[ 1 ] === "bottom" ? - -data.targetHeight : - 0, - offset = -2 * data.offset[ 1 ], - newOverTop, - newOverBottom; - if ( overTop < 0 ) { - newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset; - if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) { - position.top += myOffset + atOffset + offset; - } - } else if ( overBottom > 0 ) { - newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop; - if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) { - position.top += myOffset + atOffset + offset; - } - } - } - }, - flipfit: { - left: function() { - $.ui.position.flip.left.apply( this, arguments ); - $.ui.position.fit.left.apply( this, arguments ); - }, - top: function() { - $.ui.position.flip.top.apply( this, arguments ); - $.ui.position.fit.top.apply( this, arguments ); - } - } -}; - -// fraction support test -(function() { - var testElement, testElementParent, testElementStyle, offsetLeft, i, - body = document.getElementsByTagName( "body" )[ 0 ], - div = document.createElement( "div" ); - - //Create a "fake body" for testing based on method used in jQuery.support - testElement = document.createElement( body ? "div" : "body" ); - testElementStyle = { - visibility: "hidden", - width: 0, - height: 0, - border: 0, - margin: 0, - background: "none" - }; - if ( body ) { - $.extend( testElementStyle, { - position: "absolute", - left: "-1000px", - top: "-1000px" - }); - } - for ( i in testElementStyle ) { - testElement.style[ i ] = testElementStyle[ i ]; - } - testElement.appendChild( div ); - testElementParent = body || document.documentElement; - testElementParent.insertBefore( testElement, testElementParent.firstChild ); - - div.style.cssText = "position: absolute; left: 10.7432222px;"; - - offsetLeft = $( div ).offset().left; - supportsOffsetFractions = offsetLeft > 10 && offsetLeft < 11; - - testElement.innerHTML = ""; - testElementParent.removeChild( testElement ); -})(); - -})(); - -var position = $.ui.position; - - -/*! - * jQuery UI Draggable 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/draggable/ - */ - - -$.widget("ui.draggable", $.ui.mouse, { - version: "1.11.4", - widgetEventPrefix: "drag", - options: { - addClasses: true, - appendTo: "parent", - axis: false, - connectToSortable: false, - containment: false, - cursor: "auto", - cursorAt: false, - grid: false, - handle: false, - helper: "original", - iframeFix: false, - opacity: false, - refreshPositions: false, - revert: false, - revertDuration: 500, - scope: "default", - scroll: true, - scrollSensitivity: 20, - scrollSpeed: 20, - snap: false, - snapMode: "both", - snapTolerance: 20, - stack: false, - zIndex: false, - - // callbacks - drag: null, - start: null, - stop: null - }, - _create: function() { - - if ( this.options.helper === "original" ) { - this._setPositionRelative(); - } - if (this.options.addClasses){ - this.element.addClass("ui-draggable"); - } - if (this.options.disabled){ - this.element.addClass("ui-draggable-disabled"); - } - this._setHandleClassName(); - - this._mouseInit(); - }, - - _setOption: function( key, value ) { - this._super( key, value ); - if ( key === "handle" ) { - this._removeHandleClassName(); - this._setHandleClassName(); - } - }, - - _destroy: function() { - if ( ( this.helper || this.element ).is( ".ui-draggable-dragging" ) ) { - this.destroyOnClear = true; - return; - } - this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" ); - this._removeHandleClassName(); - this._mouseDestroy(); - }, - - _mouseCapture: function(event) { - var o = this.options; - - this._blurActiveElement( event ); - - // among others, prevent a drag on a resizable-handle - if (this.helper || o.disabled || $(event.target).closest(".ui-resizable-handle").length > 0) { - return false; - } - - //Quit if we're not on a valid handle - this.handle = this._getHandle(event); - if (!this.handle) { - return false; - } - - this._blockFrames( o.iframeFix === true ? "iframe" : o.iframeFix ); - - return true; - - }, - - _blockFrames: function( selector ) { - this.iframeBlocks = this.document.find( selector ).map(function() { - var iframe = $( this ); - - return $( "<div>" ) - .css( "position", "absolute" ) - .appendTo( iframe.parent() ) - .outerWidth( iframe.outerWidth() ) - .outerHeight( iframe.outerHeight() ) - .offset( iframe.offset() )[ 0 ]; - }); - }, - - _unblockFrames: function() { - if ( this.iframeBlocks ) { - this.iframeBlocks.remove(); - delete this.iframeBlocks; - } - }, - - _blurActiveElement: function( event ) { - var document = this.document[ 0 ]; - - // Only need to blur if the event occurred on the draggable itself, see #10527 - if ( !this.handleElement.is( event.target ) ) { - return; - } - - // support: IE9 - // IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe> - try { - - // Support: IE9, IE10 - // If the <body> is blurred, IE will switch windows, see #9520 - if ( document.activeElement && document.activeElement.nodeName.toLowerCase() !== "body" ) { - - // Blur any element that currently has focus, see #4261 - $( document.activeElement ).blur(); - } - } catch ( error ) {} - }, - - _mouseStart: function(event) { - - var o = this.options; - - //Create and append the visible helper - this.helper = this._createHelper(event); - - this.helper.addClass("ui-draggable-dragging"); - - //Cache the helper size - this._cacheHelperProportions(); - - //If ddmanager is used for droppables, set the global draggable - if ($.ui.ddmanager) { - $.ui.ddmanager.current = this; - } - - /* - * - Position generation - - * This block generates everything position related - it's the core of draggables. - */ - - //Cache the margins of the original element - this._cacheMargins(); - - //Store the helper's css position - this.cssPosition = this.helper.css( "position" ); - this.scrollParent = this.helper.scrollParent( true ); - this.offsetParent = this.helper.offsetParent(); - this.hasFixedAncestor = this.helper.parents().filter(function() { - return $( this ).css( "position" ) === "fixed"; - }).length > 0; - - //The element's absolute position on the page minus margins - this.positionAbs = this.element.offset(); - this._refreshOffsets( event ); - - //Generate the original position - this.originalPosition = this.position = this._generatePosition( event, false ); - this.originalPageX = event.pageX; - this.originalPageY = event.pageY; - - //Adjust the mouse offset relative to the helper if "cursorAt" is supplied - (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); - - //Set a containment if given in the options - this._setContainment(); - - //Trigger event + callbacks - if (this._trigger("start", event) === false) { - this._clear(); - return false; - } - - //Recache the helper size - this._cacheHelperProportions(); - - //Prepare the droppable offsets - if ($.ui.ddmanager && !o.dropBehaviour) { - $.ui.ddmanager.prepareOffsets(this, event); - } - - // Reset helper's right/bottom css if they're set and set explicit width/height instead - // as this prevents resizing of elements with right/bottom set (see #7772) - this._normalizeRightBottom(); - - this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position - - //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003) - if ( $.ui.ddmanager ) { - $.ui.ddmanager.dragStart(this, event); - } - - return true; - }, - - _refreshOffsets: function( event ) { - this.offset = { - top: this.positionAbs.top - this.margins.top, - left: this.positionAbs.left - this.margins.left, - scroll: false, - parent: this._getParentOffset(), - relative: this._getRelativeOffset() - }; - - this.offset.click = { - left: event.pageX - this.offset.left, - top: event.pageY - this.offset.top - }; - }, - - _mouseDrag: function(event, noPropagation) { - // reset any necessary cached properties (see #5009) - if ( this.hasFixedAncestor ) { - this.offset.parent = this._getParentOffset(); - } - - //Compute the helpers position - this.position = this._generatePosition( event, true ); - this.positionAbs = this._convertPositionTo("absolute"); - - //Call plugins and callbacks and use the resulting position if something is returned - if (!noPropagation) { - var ui = this._uiHash(); - if (this._trigger("drag", event, ui) === false) { - this._mouseUp({}); - return false; - } - this.position = ui.position; - } - - this.helper[ 0 ].style.left = this.position.left + "px"; - this.helper[ 0 ].style.top = this.position.top + "px"; - - if ($.ui.ddmanager) { - $.ui.ddmanager.drag(this, event); - } - - return false; - }, - - _mouseStop: function(event) { - - //If we are using droppables, inform the manager about the drop - var that = this, - dropped = false; - if ($.ui.ddmanager && !this.options.dropBehaviour) { - dropped = $.ui.ddmanager.drop(this, event); - } - - //if a drop comes from outside (a sortable) - if (this.dropped) { - dropped = this.dropped; - this.dropped = false; - } - - if ((this.options.revert === "invalid" && !dropped) || (this.options.revert === "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) { - $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() { - if (that._trigger("stop", event) !== false) { - that._clear(); - } - }); - } else { - if (this._trigger("stop", event) !== false) { - this._clear(); - } - } - - return false; - }, - - _mouseUp: function( event ) { - this._unblockFrames(); - - //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003) - if ( $.ui.ddmanager ) { - $.ui.ddmanager.dragStop(this, event); - } - - // Only need to focus if the event occurred on the draggable itself, see #10527 - if ( this.handleElement.is( event.target ) ) { - // The interaction is over; whether or not the click resulted in a drag, focus the element - this.element.focus(); - } - - return $.ui.mouse.prototype._mouseUp.call(this, event); - }, - - cancel: function() { - - if (this.helper.is(".ui-draggable-dragging")) { - this._mouseUp({}); - } else { - this._clear(); - } - - return this; - - }, - - _getHandle: function(event) { - return this.options.handle ? - !!$( event.target ).closest( this.element.find( this.options.handle ) ).length : - true; - }, - - _setHandleClassName: function() { - this.handleElement = this.options.handle ? - this.element.find( this.options.handle ) : this.element; - this.handleElement.addClass( "ui-draggable-handle" ); - }, - - _removeHandleClassName: function() { - this.handleElement.removeClass( "ui-draggable-handle" ); - }, - - _createHelper: function(event) { - - var o = this.options, - helperIsFunction = $.isFunction( o.helper ), - helper = helperIsFunction ? - $( o.helper.apply( this.element[ 0 ], [ event ] ) ) : - ( o.helper === "clone" ? - this.element.clone().removeAttr( "id" ) : - this.element ); - - if (!helper.parents("body").length) { - helper.appendTo((o.appendTo === "parent" ? this.element[0].parentNode : o.appendTo)); - } - - // http://bugs.jqueryui.com/ticket/9446 - // a helper function can return the original element - // which wouldn't have been set to relative in _create - if ( helperIsFunction && helper[ 0 ] === this.element[ 0 ] ) { - this._setPositionRelative(); - } - - if (helper[0] !== this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) { - helper.css("position", "absolute"); - } - - return helper; - - }, - - _setPositionRelative: function() { - if ( !( /^(?:r|a|f)/ ).test( this.element.css( "position" ) ) ) { - this.element[ 0 ].style.position = "relative"; - } - }, - - _adjustOffsetFromHelper: function(obj) { - if (typeof obj === "string") { - obj = obj.split(" "); - } - if ($.isArray(obj)) { - obj = { left: +obj[0], top: +obj[1] || 0 }; - } - if ("left" in obj) { - this.offset.click.left = obj.left + this.margins.left; - } - if ("right" in obj) { - this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; - } - if ("top" in obj) { - this.offset.click.top = obj.top + this.margins.top; - } - if ("bottom" in obj) { - this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; - } - }, - - _isRootNode: function( element ) { - return ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ]; - }, - - _getParentOffset: function() { - - //Get the offsetParent and cache its position - var po = this.offsetParent.offset(), - document = this.document[ 0 ]; - - // This is a special case where we need to modify a offset calculated on start, since the following happened: - // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent - // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that - // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag - if (this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) { - po.left += this.scrollParent.scrollLeft(); - po.top += this.scrollParent.scrollTop(); - } - - if ( this._isRootNode( this.offsetParent[ 0 ] ) ) { - po = { top: 0, left: 0 }; - } - - return { - top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"), 10) || 0), - left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"), 10) || 0) - }; - - }, - - _getRelativeOffset: function() { - if ( this.cssPosition !== "relative" ) { - return { top: 0, left: 0 }; - } - - var p = this.element.position(), - scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ); - - return { - top: p.top - ( parseInt(this.helper.css( "top" ), 10) || 0 ) + ( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ), - left: p.left - ( parseInt(this.helper.css( "left" ), 10) || 0 ) + ( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 ) - }; - - }, - - _cacheMargins: function() { - this.margins = { - left: (parseInt(this.element.css("marginLeft"), 10) || 0), - top: (parseInt(this.element.css("marginTop"), 10) || 0), - right: (parseInt(this.element.css("marginRight"), 10) || 0), - bottom: (parseInt(this.element.css("marginBottom"), 10) || 0) - }; - }, - - _cacheHelperProportions: function() { - this.helperProportions = { - width: this.helper.outerWidth(), - height: this.helper.outerHeight() - }; - }, - - _setContainment: function() { - - var isUserScrollable, c, ce, - o = this.options, - document = this.document[ 0 ]; - - this.relativeContainer = null; - - if ( !o.containment ) { - this.containment = null; - return; - } - - if ( o.containment === "window" ) { - this.containment = [ - $( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left, - $( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top, - $( window ).scrollLeft() + $( window ).width() - this.helperProportions.width - this.margins.left, - $( window ).scrollTop() + ( $( window ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top - ]; - return; - } - - if ( o.containment === "document") { - this.containment = [ - 0, - 0, - $( document ).width() - this.helperProportions.width - this.margins.left, - ( $( document ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top - ]; - return; - } - - if ( o.containment.constructor === Array ) { - this.containment = o.containment; - return; - } - - if ( o.containment === "parent" ) { - o.containment = this.helper[ 0 ].parentNode; - } - - c = $( o.containment ); - ce = c[ 0 ]; - - if ( !ce ) { - return; - } - - isUserScrollable = /(scroll|auto)/.test( c.css( "overflow" ) ); - - this.containment = [ - ( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ), - ( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ), - ( isUserScrollable ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) - - ( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) - - ( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) - - this.helperProportions.width - - this.margins.left - - this.margins.right, - ( isUserScrollable ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) - - ( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) - - ( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) - - this.helperProportions.height - - this.margins.top - - this.margins.bottom - ]; - this.relativeContainer = c; - }, - - _convertPositionTo: function(d, pos) { - - if (!pos) { - pos = this.position; - } - - var mod = d === "absolute" ? 1 : -1, - scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ); - - return { - top: ( - pos.top + // The absolute mouse position - this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent - this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border) - ( ( this.cssPosition === "fixed" ? -this.offset.scroll.top : ( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod) - ), - left: ( - pos.left + // The absolute mouse position - this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent - this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border) - ( ( this.cssPosition === "fixed" ? -this.offset.scroll.left : ( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod) - ) - }; - - }, - - _generatePosition: function( event, constrainPosition ) { - - var containment, co, top, left, - o = this.options, - scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ), - pageX = event.pageX, - pageY = event.pageY; - - // Cache the scroll - if ( !scrollIsRootNode || !this.offset.scroll ) { - this.offset.scroll = { - top: this.scrollParent.scrollTop(), - left: this.scrollParent.scrollLeft() - }; - } - - /* - * - Position constraining - - * Constrain the position to a mix of grid, containment. - */ - - // If we are not dragging yet, we won't check for options - if ( constrainPosition ) { - if ( this.containment ) { - if ( this.relativeContainer ){ - co = this.relativeContainer.offset(); - containment = [ - this.containment[ 0 ] + co.left, - this.containment[ 1 ] + co.top, - this.containment[ 2 ] + co.left, - this.containment[ 3 ] + co.top - ]; - } else { - containment = this.containment; - } - - if (event.pageX - this.offset.click.left < containment[0]) { - pageX = containment[0] + this.offset.click.left; - } - if (event.pageY - this.offset.click.top < containment[1]) { - pageY = containment[1] + this.offset.click.top; - } - if (event.pageX - this.offset.click.left > containment[2]) { - pageX = containment[2] + this.offset.click.left; - } - if (event.pageY - this.offset.click.top > containment[3]) { - pageY = containment[3] + this.offset.click.top; - } - } - - if (o.grid) { - //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950) - top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY; - pageY = containment ? ((top - this.offset.click.top >= containment[1] || top - this.offset.click.top > containment[3]) ? top : ((top - this.offset.click.top >= containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top; - - left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX; - pageX = containment ? ((left - this.offset.click.left >= containment[0] || left - this.offset.click.left > containment[2]) ? left : ((left - this.offset.click.left >= containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left; - } - - if ( o.axis === "y" ) { - pageX = this.originalPageX; - } - - if ( o.axis === "x" ) { - pageY = this.originalPageY; - } - } - - return { - top: ( - pageY - // The absolute mouse position - this.offset.click.top - // Click offset (relative to the element) - this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent - this.offset.parent.top + // The offsetParent's offset without borders (offset + border) - ( this.cssPosition === "fixed" ? -this.offset.scroll.top : ( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) - ), - left: ( - pageX - // The absolute mouse position - this.offset.click.left - // Click offset (relative to the element) - this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent - this.offset.parent.left + // The offsetParent's offset without borders (offset + border) - ( this.cssPosition === "fixed" ? -this.offset.scroll.left : ( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) - ) - }; - - }, - - _clear: function() { - this.helper.removeClass("ui-draggable-dragging"); - if (this.helper[0] !== this.element[0] && !this.cancelHelperRemoval) { - this.helper.remove(); - } - this.helper = null; - this.cancelHelperRemoval = false; - if ( this.destroyOnClear ) { - this.destroy(); - } - }, - - _normalizeRightBottom: function() { - if ( this.options.axis !== "y" && this.helper.css( "right" ) !== "auto" ) { - this.helper.width( this.helper.width() ); - this.helper.css( "right", "auto" ); - } - if ( this.options.axis !== "x" && this.helper.css( "bottom" ) !== "auto" ) { - this.helper.height( this.helper.height() ); - this.helper.css( "bottom", "auto" ); - } - }, - - // From now on bulk stuff - mainly helpers - - _trigger: function( type, event, ui ) { - ui = ui || this._uiHash(); - $.ui.plugin.call( this, type, [ event, ui, this ], true ); - - // Absolute position and offset (see #6884 ) have to be recalculated after plugins - if ( /^(drag|start|stop)/.test( type ) ) { - this.positionAbs = this._convertPositionTo( "absolute" ); - ui.offset = this.positionAbs; - } - return $.Widget.prototype._trigger.call( this, type, event, ui ); - }, - - plugins: {}, - - _uiHash: function() { - return { - helper: this.helper, - position: this.position, - originalPosition: this.originalPosition, - offset: this.positionAbs - }; - } - -}); - -$.ui.plugin.add( "draggable", "connectToSortable", { - start: function( event, ui, draggable ) { - var uiSortable = $.extend( {}, ui, { - item: draggable.element - }); - - draggable.sortables = []; - $( draggable.options.connectToSortable ).each(function() { - var sortable = $( this ).sortable( "instance" ); - - if ( sortable && !sortable.options.disabled ) { - draggable.sortables.push( sortable ); - - // refreshPositions is called at drag start to refresh the containerCache - // which is used in drag. This ensures it's initialized and synchronized - // with any changes that might have happened on the page since initialization. - sortable.refreshPositions(); - sortable._trigger("activate", event, uiSortable); - } - }); - }, - stop: function( event, ui, draggable ) { - var uiSortable = $.extend( {}, ui, { - item: draggable.element - }); - - draggable.cancelHelperRemoval = false; - - $.each( draggable.sortables, function() { - var sortable = this; - - if ( sortable.isOver ) { - sortable.isOver = 0; - - // Allow this sortable to handle removing the helper - draggable.cancelHelperRemoval = true; - sortable.cancelHelperRemoval = false; - - // Use _storedCSS To restore properties in the sortable, - // as this also handles revert (#9675) since the draggable - // may have modified them in unexpected ways (#8809) - sortable._storedCSS = { - position: sortable.placeholder.css( "position" ), - top: sortable.placeholder.css( "top" ), - left: sortable.placeholder.css( "left" ) - }; - - sortable._mouseStop(event); - - // Once drag has ended, the sortable should return to using - // its original helper, not the shared helper from draggable - sortable.options.helper = sortable.options._helper; - } else { - // Prevent this Sortable from removing the helper. - // However, don't set the draggable to remove the helper - // either as another connected Sortable may yet handle the removal. - sortable.cancelHelperRemoval = true; - - sortable._trigger( "deactivate", event, uiSortable ); - } - }); - }, - drag: function( event, ui, draggable ) { - $.each( draggable.sortables, function() { - var innermostIntersecting = false, - sortable = this; - - // Copy over variables that sortable's _intersectsWith uses - sortable.positionAbs = draggable.positionAbs; - sortable.helperProportions = draggable.helperProportions; - sortable.offset.click = draggable.offset.click; - - if ( sortable._intersectsWith( sortable.containerCache ) ) { - innermostIntersecting = true; - - $.each( draggable.sortables, function() { - // Copy over variables that sortable's _intersectsWith uses - this.positionAbs = draggable.positionAbs; - this.helperProportions = draggable.helperProportions; - this.offset.click = draggable.offset.click; - - if ( this !== sortable && - this._intersectsWith( this.containerCache ) && - $.contains( sortable.element[ 0 ], this.element[ 0 ] ) ) { - innermostIntersecting = false; - } - - return innermostIntersecting; - }); - } - - if ( innermostIntersecting ) { - // If it intersects, we use a little isOver variable and set it once, - // so that the move-in stuff gets fired only once. - if ( !sortable.isOver ) { - sortable.isOver = 1; - - // Store draggable's parent in case we need to reappend to it later. - draggable._parent = ui.helper.parent(); - - sortable.currentItem = ui.helper - .appendTo( sortable.element ) - .data( "ui-sortable-item", true ); - - // Store helper option to later restore it - sortable.options._helper = sortable.options.helper; - - sortable.options.helper = function() { - return ui.helper[ 0 ]; - }; - - // Fire the start events of the sortable with our passed browser event, - // and our own helper (so it doesn't create a new one) - event.target = sortable.currentItem[ 0 ]; - sortable._mouseCapture( event, true ); - sortable._mouseStart( event, true, true ); - - // Because the browser event is way off the new appended portlet, - // modify necessary variables to reflect the changes - sortable.offset.click.top = draggable.offset.click.top; - sortable.offset.click.left = draggable.offset.click.left; - sortable.offset.parent.left -= draggable.offset.parent.left - - sortable.offset.parent.left; - sortable.offset.parent.top -= draggable.offset.parent.top - - sortable.offset.parent.top; - - draggable._trigger( "toSortable", event ); - - // Inform draggable that the helper is in a valid drop zone, - // used solely in the revert option to handle "valid/invalid". - draggable.dropped = sortable.element; - - // Need to refreshPositions of all sortables in the case that - // adding to one sortable changes the location of the other sortables (#9675) - $.each( draggable.sortables, function() { - this.refreshPositions(); - }); - - // hack so receive/update callbacks work (mostly) - draggable.currentItem = draggable.element; - sortable.fromOutside = draggable; - } - - if ( sortable.currentItem ) { - sortable._mouseDrag( event ); - // Copy the sortable's position because the draggable's can potentially reflect - // a relative position, while sortable is always absolute, which the dragged - // element has now become. (#8809) - ui.position = sortable.position; - } - } else { - // If it doesn't intersect with the sortable, and it intersected before, - // we fake the drag stop of the sortable, but make sure it doesn't remove - // the helper by using cancelHelperRemoval. - if ( sortable.isOver ) { - - sortable.isOver = 0; - sortable.cancelHelperRemoval = true; - - // Calling sortable's mouseStop would trigger a revert, - // so revert must be temporarily false until after mouseStop is called. - sortable.options._revert = sortable.options.revert; - sortable.options.revert = false; - - sortable._trigger( "out", event, sortable._uiHash( sortable ) ); - sortable._mouseStop( event, true ); - - // restore sortable behaviors that were modfied - // when the draggable entered the sortable area (#9481) - sortable.options.revert = sortable.options._revert; - sortable.options.helper = sortable.options._helper; - - if ( sortable.placeholder ) { - sortable.placeholder.remove(); - } - - // Restore and recalculate the draggable's offset considering the sortable - // may have modified them in unexpected ways. (#8809, #10669) - ui.helper.appendTo( draggable._parent ); - draggable._refreshOffsets( event ); - ui.position = draggable._generatePosition( event, true ); - - draggable._trigger( "fromSortable", event ); - - // Inform draggable that the helper is no longer in a valid drop zone - draggable.dropped = false; - - // Need to refreshPositions of all sortables just in case removing - // from one sortable changes the location of other sortables (#9675) - $.each( draggable.sortables, function() { - this.refreshPositions(); - }); - } - } - }); - } -}); - -$.ui.plugin.add("draggable", "cursor", { - start: function( event, ui, instance ) { - var t = $( "body" ), - o = instance.options; - - if (t.css("cursor")) { - o._cursor = t.css("cursor"); - } - t.css("cursor", o.cursor); - }, - stop: function( event, ui, instance ) { - var o = instance.options; - if (o._cursor) { - $("body").css("cursor", o._cursor); - } - } -}); - -$.ui.plugin.add("draggable", "opacity", { - start: function( event, ui, instance ) { - var t = $( ui.helper ), - o = instance.options; - if (t.css("opacity")) { - o._opacity = t.css("opacity"); - } - t.css("opacity", o.opacity); - }, - stop: function( event, ui, instance ) { - var o = instance.options; - if (o._opacity) { - $(ui.helper).css("opacity", o._opacity); - } - } -}); - -$.ui.plugin.add("draggable", "scroll", { - start: function( event, ui, i ) { - if ( !i.scrollParentNotHidden ) { - i.scrollParentNotHidden = i.helper.scrollParent( false ); - } - - if ( i.scrollParentNotHidden[ 0 ] !== i.document[ 0 ] && i.scrollParentNotHidden[ 0 ].tagName !== "HTML" ) { - i.overflowOffset = i.scrollParentNotHidden.offset(); - } - }, - drag: function( event, ui, i ) { - - var o = i.options, - scrolled = false, - scrollParent = i.scrollParentNotHidden[ 0 ], - document = i.document[ 0 ]; - - if ( scrollParent !== document && scrollParent.tagName !== "HTML" ) { - if ( !o.axis || o.axis !== "x" ) { - if ( ( i.overflowOffset.top + scrollParent.offsetHeight ) - event.pageY < o.scrollSensitivity ) { - scrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed; - } else if ( event.pageY - i.overflowOffset.top < o.scrollSensitivity ) { - scrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed; - } - } - - if ( !o.axis || o.axis !== "y" ) { - if ( ( i.overflowOffset.left + scrollParent.offsetWidth ) - event.pageX < o.scrollSensitivity ) { - scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed; - } else if ( event.pageX - i.overflowOffset.left < o.scrollSensitivity ) { - scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed; - } - } - - } else { - - if (!o.axis || o.axis !== "x") { - if (event.pageY - $(document).scrollTop() < o.scrollSensitivity) { - scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); - } else if ($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) { - scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); - } - } - - if (!o.axis || o.axis !== "y") { - if (event.pageX - $(document).scrollLeft() < o.scrollSensitivity) { - scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); - } else if ($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) { - scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); - } - } - - } - - if (scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) { - $.ui.ddmanager.prepareOffsets(i, event); - } - - } -}); - -$.ui.plugin.add("draggable", "snap", { - start: function( event, ui, i ) { - - var o = i.options; - - i.snapElements = []; - - $(o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap).each(function() { - var $t = $(this), - $o = $t.offset(); - if (this !== i.element[0]) { - i.snapElements.push({ - item: this, - width: $t.outerWidth(), height: $t.outerHeight(), - top: $o.top, left: $o.left - }); - } - }); - - }, - drag: function( event, ui, inst ) { - - var ts, bs, ls, rs, l, r, t, b, i, first, - o = inst.options, - d = o.snapTolerance, - x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width, - y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height; - - for (i = inst.snapElements.length - 1; i >= 0; i--){ - - l = inst.snapElements[i].left - inst.margins.left; - r = l + inst.snapElements[i].width; - t = inst.snapElements[i].top - inst.margins.top; - b = t + inst.snapElements[i].height; - - if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d || !$.contains( inst.snapElements[ i ].item.ownerDocument, inst.snapElements[ i ].item ) ) { - if (inst.snapElements[i].snapping) { - (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); - } - inst.snapElements[i].snapping = false; - continue; - } - - if (o.snapMode !== "inner") { - ts = Math.abs(t - y2) <= d; - bs = Math.abs(b - y1) <= d; - ls = Math.abs(l - x2) <= d; - rs = Math.abs(r - x1) <= d; - if (ts) { - ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top; - } - if (bs) { - ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top; - } - if (ls) { - ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left; - } - if (rs) { - ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left; - } - } - - first = (ts || bs || ls || rs); - - if (o.snapMode !== "outer") { - ts = Math.abs(t - y1) <= d; - bs = Math.abs(b - y2) <= d; - ls = Math.abs(l - x1) <= d; - rs = Math.abs(r - x2) <= d; - if (ts) { - ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top; - } - if (bs) { - ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top; - } - if (ls) { - ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left; - } - if (rs) { - ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left; - } - } - - if (!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) { - (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); - } - inst.snapElements[i].snapping = (ts || bs || ls || rs || first); - - } - - } -}); - -$.ui.plugin.add("draggable", "stack", { - start: function( event, ui, instance ) { - var min, - o = instance.options, - group = $.makeArray($(o.stack)).sort(function(a, b) { - return (parseInt($(a).css("zIndex"), 10) || 0) - (parseInt($(b).css("zIndex"), 10) || 0); - }); - - if (!group.length) { return; } - - min = parseInt($(group[0]).css("zIndex"), 10) || 0; - $(group).each(function(i) { - $(this).css("zIndex", min + i); - }); - this.css("zIndex", (min + group.length)); - } -}); - -$.ui.plugin.add("draggable", "zIndex", { - start: function( event, ui, instance ) { - var t = $( ui.helper ), - o = instance.options; - - if (t.css("zIndex")) { - o._zIndex = t.css("zIndex"); - } - t.css("zIndex", o.zIndex); - }, - stop: function( event, ui, instance ) { - var o = instance.options; - - if (o._zIndex) { - $(ui.helper).css("zIndex", o._zIndex); - } - } -}); - -var draggable = $.ui.draggable; - - -/*! - * jQuery UI Droppable 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/droppable/ - */ - - -$.widget( "ui.droppable", { - version: "1.11.4", - widgetEventPrefix: "drop", - options: { - accept: "*", - activeClass: false, - addClasses: true, - greedy: false, - hoverClass: false, - scope: "default", - tolerance: "intersect", - - // callbacks - activate: null, - deactivate: null, - drop: null, - out: null, - over: null - }, - _create: function() { - - var proportions, - o = this.options, - accept = o.accept; - - this.isover = false; - this.isout = true; - - this.accept = $.isFunction( accept ) ? accept : function( d ) { - return d.is( accept ); - }; - - this.proportions = function( /* valueToWrite */ ) { - if ( arguments.length ) { - // Store the droppable's proportions - proportions = arguments[ 0 ]; - } else { - // Retrieve or derive the droppable's proportions - return proportions ? - proportions : - proportions = { - width: this.element[ 0 ].offsetWidth, - height: this.element[ 0 ].offsetHeight - }; - } - }; - - this._addToManager( o.scope ); - - o.addClasses && this.element.addClass( "ui-droppable" ); - - }, - - _addToManager: function( scope ) { - // Add the reference and positions to the manager - $.ui.ddmanager.droppables[ scope ] = $.ui.ddmanager.droppables[ scope ] || []; - $.ui.ddmanager.droppables[ scope ].push( this ); - }, - - _splice: function( drop ) { - var i = 0; - for ( ; i < drop.length; i++ ) { - if ( drop[ i ] === this ) { - drop.splice( i, 1 ); - } - } - }, - - _destroy: function() { - var drop = $.ui.ddmanager.droppables[ this.options.scope ]; - - this._splice( drop ); - - this.element.removeClass( "ui-droppable ui-droppable-disabled" ); - }, - - _setOption: function( key, value ) { - - if ( key === "accept" ) { - this.accept = $.isFunction( value ) ? value : function( d ) { - return d.is( value ); - }; - } else if ( key === "scope" ) { - var drop = $.ui.ddmanager.droppables[ this.options.scope ]; - - this._splice( drop ); - this._addToManager( value ); - } - - this._super( key, value ); - }, - - _activate: function( event ) { - var draggable = $.ui.ddmanager.current; - if ( this.options.activeClass ) { - this.element.addClass( this.options.activeClass ); - } - if ( draggable ){ - this._trigger( "activate", event, this.ui( draggable ) ); - } - }, - - _deactivate: function( event ) { - var draggable = $.ui.ddmanager.current; - if ( this.options.activeClass ) { - this.element.removeClass( this.options.activeClass ); - } - if ( draggable ){ - this._trigger( "deactivate", event, this.ui( draggable ) ); - } - }, - - _over: function( event ) { - - var draggable = $.ui.ddmanager.current; - - // Bail if draggable and droppable are same element - if ( !draggable || ( draggable.currentItem || draggable.element )[ 0 ] === this.element[ 0 ] ) { - return; - } - - if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) { - if ( this.options.hoverClass ) { - this.element.addClass( this.options.hoverClass ); - } - this._trigger( "over", event, this.ui( draggable ) ); - } - - }, - - _out: function( event ) { - - var draggable = $.ui.ddmanager.current; - - // Bail if draggable and droppable are same element - if ( !draggable || ( draggable.currentItem || draggable.element )[ 0 ] === this.element[ 0 ] ) { - return; - } - - if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) { - if ( this.options.hoverClass ) { - this.element.removeClass( this.options.hoverClass ); - } - this._trigger( "out", event, this.ui( draggable ) ); - } - - }, - - _drop: function( event, custom ) { - - var draggable = custom || $.ui.ddmanager.current, - childrenIntersection = false; - - // Bail if draggable and droppable are same element - if ( !draggable || ( draggable.currentItem || draggable.element )[ 0 ] === this.element[ 0 ] ) { - return false; - } - - this.element.find( ":data(ui-droppable)" ).not( ".ui-draggable-dragging" ).each(function() { - var inst = $( this ).droppable( "instance" ); - if ( - inst.options.greedy && - !inst.options.disabled && - inst.options.scope === draggable.options.scope && - inst.accept.call( inst.element[ 0 ], ( draggable.currentItem || draggable.element ) ) && - $.ui.intersect( draggable, $.extend( inst, { offset: inst.element.offset() } ), inst.options.tolerance, event ) - ) { childrenIntersection = true; return false; } - }); - if ( childrenIntersection ) { - return false; - } - - if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) { - if ( this.options.activeClass ) { - this.element.removeClass( this.options.activeClass ); - } - if ( this.options.hoverClass ) { - this.element.removeClass( this.options.hoverClass ); - } - this._trigger( "drop", event, this.ui( draggable ) ); - return this.element; - } - - return false; - - }, - - ui: function( c ) { - return { - draggable: ( c.currentItem || c.element ), - helper: c.helper, - position: c.position, - offset: c.positionAbs - }; - } - -}); - -$.ui.intersect = (function() { - function isOverAxis( x, reference, size ) { - return ( x >= reference ) && ( x < ( reference + size ) ); - } - - return function( draggable, droppable, toleranceMode, event ) { - - if ( !droppable.offset ) { - return false; - } - - var x1 = ( draggable.positionAbs || draggable.position.absolute ).left + draggable.margins.left, - y1 = ( draggable.positionAbs || draggable.position.absolute ).top + draggable.margins.top, - x2 = x1 + draggable.helperProportions.width, - y2 = y1 + draggable.helperProportions.height, - l = droppable.offset.left, - t = droppable.offset.top, - r = l + droppable.proportions().width, - b = t + droppable.proportions().height; - - switch ( toleranceMode ) { - case "fit": - return ( l <= x1 && x2 <= r && t <= y1 && y2 <= b ); - case "intersect": - return ( l < x1 + ( draggable.helperProportions.width / 2 ) && // Right Half - x2 - ( draggable.helperProportions.width / 2 ) < r && // Left Half - t < y1 + ( draggable.helperProportions.height / 2 ) && // Bottom Half - y2 - ( draggable.helperProportions.height / 2 ) < b ); // Top Half - case "pointer": - return isOverAxis( event.pageY, t, droppable.proportions().height ) && isOverAxis( event.pageX, l, droppable.proportions().width ); - case "touch": - return ( - ( y1 >= t && y1 <= b ) || // Top edge touching - ( y2 >= t && y2 <= b ) || // Bottom edge touching - ( y1 < t && y2 > b ) // Surrounded vertically - ) && ( - ( x1 >= l && x1 <= r ) || // Left edge touching - ( x2 >= l && x2 <= r ) || // Right edge touching - ( x1 < l && x2 > r ) // Surrounded horizontally - ); - default: - return false; - } - }; -})(); - -/* - This manager tracks offsets of draggables and droppables -*/ -$.ui.ddmanager = { - current: null, - droppables: { "default": [] }, - prepareOffsets: function( t, event ) { - - var i, j, - m = $.ui.ddmanager.droppables[ t.options.scope ] || [], - type = event ? event.type : null, // workaround for #2317 - list = ( t.currentItem || t.element ).find( ":data(ui-droppable)" ).addBack(); - - droppablesLoop: for ( i = 0; i < m.length; i++ ) { - - // No disabled and non-accepted - if ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ], ( t.currentItem || t.element ) ) ) ) { - continue; - } - - // Filter out elements in the current dragged item - for ( j = 0; j < list.length; j++ ) { - if ( list[ j ] === m[ i ].element[ 0 ] ) { - m[ i ].proportions().height = 0; - continue droppablesLoop; - } - } - - m[ i ].visible = m[ i ].element.css( "display" ) !== "none"; - if ( !m[ i ].visible ) { - continue; - } - - // Activate the droppable if used directly from draggables - if ( type === "mousedown" ) { - m[ i ]._activate.call( m[ i ], event ); - } - - m[ i ].offset = m[ i ].element.offset(); - m[ i ].proportions({ width: m[ i ].element[ 0 ].offsetWidth, height: m[ i ].element[ 0 ].offsetHeight }); - - } - - }, - drop: function( draggable, event ) { - - var dropped = false; - // Create a copy of the droppables in case the list changes during the drop (#9116) - $.each( ( $.ui.ddmanager.droppables[ draggable.options.scope ] || [] ).slice(), function() { - - if ( !this.options ) { - return; - } - if ( !this.options.disabled && this.visible && $.ui.intersect( draggable, this, this.options.tolerance, event ) ) { - dropped = this._drop.call( this, event ) || dropped; - } - - if ( !this.options.disabled && this.visible && this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) { - this.isout = true; - this.isover = false; - this._deactivate.call( this, event ); - } - - }); - return dropped; - - }, - dragStart: function( draggable, event ) { - // Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003) - draggable.element.parentsUntil( "body" ).bind( "scroll.droppable", function() { - if ( !draggable.options.refreshPositions ) { - $.ui.ddmanager.prepareOffsets( draggable, event ); - } - }); - }, - drag: function( draggable, event ) { - - // If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse. - if ( draggable.options.refreshPositions ) { - $.ui.ddmanager.prepareOffsets( draggable, event ); - } - - // Run through all droppables and check their positions based on specific tolerance options - $.each( $.ui.ddmanager.droppables[ draggable.options.scope ] || [], function() { - - if ( this.options.disabled || this.greedyChild || !this.visible ) { - return; - } - - var parentInstance, scope, parent, - intersects = $.ui.intersect( draggable, this, this.options.tolerance, event ), - c = !intersects && this.isover ? "isout" : ( intersects && !this.isover ? "isover" : null ); - if ( !c ) { - return; - } - - if ( this.options.greedy ) { - // find droppable parents with same scope - scope = this.options.scope; - parent = this.element.parents( ":data(ui-droppable)" ).filter(function() { - return $( this ).droppable( "instance" ).options.scope === scope; - }); - - if ( parent.length ) { - parentInstance = $( parent[ 0 ] ).droppable( "instance" ); - parentInstance.greedyChild = ( c === "isover" ); - } - } - - // we just moved into a greedy child - if ( parentInstance && c === "isover" ) { - parentInstance.isover = false; - parentInstance.isout = true; - parentInstance._out.call( parentInstance, event ); - } - - this[ c ] = true; - this[c === "isout" ? "isover" : "isout"] = false; - this[c === "isover" ? "_over" : "_out"].call( this, event ); - - // we just moved out of a greedy child - if ( parentInstance && c === "isout" ) { - parentInstance.isout = false; - parentInstance.isover = true; - parentInstance._over.call( parentInstance, event ); - } - }); - - }, - dragStop: function( draggable, event ) { - draggable.element.parentsUntil( "body" ).unbind( "scroll.droppable" ); - // Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003) - if ( !draggable.options.refreshPositions ) { - $.ui.ddmanager.prepareOffsets( draggable, event ); - } - } -}; - -var droppable = $.ui.droppable; - - -/*! - * jQuery UI Resizable 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/resizable/ - */ - - -$.widget("ui.resizable", $.ui.mouse, { - version: "1.11.4", - widgetEventPrefix: "resize", - options: { - alsoResize: false, - animate: false, - animateDuration: "slow", - animateEasing: "swing", - aspectRatio: false, - autoHide: false, - containment: false, - ghost: false, - grid: false, - handles: "e,s,se", - helper: false, - maxHeight: null, - maxWidth: null, - minHeight: 10, - minWidth: 10, - // See #7960 - zIndex: 90, - - // callbacks - resize: null, - start: null, - stop: null - }, - - _num: function( value ) { - return parseInt( value, 10 ) || 0; - }, - - _isNumber: function( value ) { - return !isNaN( parseInt( value, 10 ) ); - }, - - _hasScroll: function( el, a ) { - - if ( $( el ).css( "overflow" ) === "hidden") { - return false; - } - - var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop", - has = false; - - if ( el[ scroll ] > 0 ) { - return true; - } - - // TODO: determine which cases actually cause this to happen - // if the element doesn't have the scroll set, see if it's possible to - // set the scroll - el[ scroll ] = 1; - has = ( el[ scroll ] > 0 ); - el[ scroll ] = 0; - return has; - }, - - _create: function() { - - var n, i, handle, axis, hname, - that = this, - o = this.options; - this.element.addClass("ui-resizable"); - - $.extend(this, { - _aspectRatio: !!(o.aspectRatio), - aspectRatio: o.aspectRatio, - originalElement: this.element, - _proportionallyResizeElements: [], - _helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null - }); - - // Wrap the element if it cannot hold child nodes - if (this.element[0].nodeName.match(/^(canvas|textarea|input|select|button|img)$/i)) { - - this.element.wrap( - $("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({ - position: this.element.css("position"), - width: this.element.outerWidth(), - height: this.element.outerHeight(), - top: this.element.css("top"), - left: this.element.css("left") - }) - ); - - this.element = this.element.parent().data( - "ui-resizable", this.element.resizable( "instance" ) - ); - - this.elementIsWrapper = true; - - this.element.css({ - marginLeft: this.originalElement.css("marginLeft"), - marginTop: this.originalElement.css("marginTop"), - marginRight: this.originalElement.css("marginRight"), - marginBottom: this.originalElement.css("marginBottom") - }); - this.originalElement.css({ - marginLeft: 0, - marginTop: 0, - marginRight: 0, - marginBottom: 0 - }); - // support: Safari - // Prevent Safari textarea resize - this.originalResizeStyle = this.originalElement.css("resize"); - this.originalElement.css("resize", "none"); - - this._proportionallyResizeElements.push( this.originalElement.css({ - position: "static", - zoom: 1, - display: "block" - }) ); - - // support: IE9 - // avoid IE jump (hard set the margin) - this.originalElement.css({ margin: this.originalElement.css("margin") }); - - this._proportionallyResize(); - } - - this.handles = o.handles || - ( !$(".ui-resizable-handle", this.element).length ? - "e,s,se" : { - n: ".ui-resizable-n", - e: ".ui-resizable-e", - s: ".ui-resizable-s", - w: ".ui-resizable-w", - se: ".ui-resizable-se", - sw: ".ui-resizable-sw", - ne: ".ui-resizable-ne", - nw: ".ui-resizable-nw" - } ); - - this._handles = $(); - if ( this.handles.constructor === String ) { - - if ( this.handles === "all") { - this.handles = "n,e,s,w,se,sw,ne,nw"; - } - - n = this.handles.split(","); - this.handles = {}; - - for (i = 0; i < n.length; i++) { - - handle = $.trim(n[i]); - hname = "ui-resizable-" + handle; - axis = $("<div class='ui-resizable-handle " + hname + "'></div>"); - - axis.css({ zIndex: o.zIndex }); - - // TODO : What's going on here? - if ("se" === handle) { - axis.addClass("ui-icon ui-icon-gripsmall-diagonal-se"); - } - - this.handles[handle] = ".ui-resizable-" + handle; - this.element.append(axis); - } - - } - - this._renderAxis = function(target) { - - var i, axis, padPos, padWrapper; - - target = target || this.element; - - for (i in this.handles) { - - if (this.handles[i].constructor === String) { - this.handles[i] = this.element.children( this.handles[ i ] ).first().show(); - } else if ( this.handles[ i ].jquery || this.handles[ i ].nodeType ) { - this.handles[ i ] = $( this.handles[ i ] ); - this._on( this.handles[ i ], { "mousedown": that._mouseDown }); - } - - if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/^(textarea|input|select|button)$/i)) { - - axis = $(this.handles[i], this.element); - - padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth(); - - padPos = [ "padding", - /ne|nw|n/.test(i) ? "Top" : - /se|sw|s/.test(i) ? "Bottom" : - /^e$/.test(i) ? "Right" : "Left" ].join(""); - - target.css(padPos, padWrapper); - - this._proportionallyResize(); - } - - this._handles = this._handles.add( this.handles[ i ] ); - } - }; - - // TODO: make renderAxis a prototype function - this._renderAxis(this.element); - - this._handles = this._handles.add( this.element.find( ".ui-resizable-handle" ) ); - this._handles.disableSelection(); - - this._handles.mouseover(function() { - if (!that.resizing) { - if (this.className) { - axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i); - } - that.axis = axis && axis[1] ? axis[1] : "se"; - } - }); - - if (o.autoHide) { - this._handles.hide(); - $(this.element) - .addClass("ui-resizable-autohide") - .mouseenter(function() { - if (o.disabled) { - return; - } - $(this).removeClass("ui-resizable-autohide"); - that._handles.show(); - }) - .mouseleave(function() { - if (o.disabled) { - return; - } - if (!that.resizing) { - $(this).addClass("ui-resizable-autohide"); - that._handles.hide(); - } - }); - } - - this._mouseInit(); - }, - - _destroy: function() { - - this._mouseDestroy(); - - var wrapper, - _destroy = function(exp) { - $(exp) - .removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing") - .removeData("resizable") - .removeData("ui-resizable") - .unbind(".resizable") - .find(".ui-resizable-handle") - .remove(); - }; - - // TODO: Unwrap at same DOM position - if (this.elementIsWrapper) { - _destroy(this.element); - wrapper = this.element; - this.originalElement.css({ - position: wrapper.css("position"), - width: wrapper.outerWidth(), - height: wrapper.outerHeight(), - top: wrapper.css("top"), - left: wrapper.css("left") - }).insertAfter( wrapper ); - wrapper.remove(); - } - - this.originalElement.css("resize", this.originalResizeStyle); - _destroy(this.originalElement); - - return this; - }, - - _mouseCapture: function(event) { - var i, handle, - capture = false; - - for (i in this.handles) { - handle = $(this.handles[i])[0]; - if (handle === event.target || $.contains(handle, event.target)) { - capture = true; - } - } - - return !this.options.disabled && capture; - }, - - _mouseStart: function(event) { - - var curleft, curtop, cursor, - o = this.options, - el = this.element; - - this.resizing = true; - - this._renderProxy(); - - curleft = this._num(this.helper.css("left")); - curtop = this._num(this.helper.css("top")); - - if (o.containment) { - curleft += $(o.containment).scrollLeft() || 0; - curtop += $(o.containment).scrollTop() || 0; - } - - this.offset = this.helper.offset(); - this.position = { left: curleft, top: curtop }; - - this.size = this._helper ? { - width: this.helper.width(), - height: this.helper.height() - } : { - width: el.width(), - height: el.height() - }; - - this.originalSize = this._helper ? { - width: el.outerWidth(), - height: el.outerHeight() - } : { - width: el.width(), - height: el.height() - }; - - this.sizeDiff = { - width: el.outerWidth() - el.width(), - height: el.outerHeight() - el.height() - }; - - this.originalPosition = { left: curleft, top: curtop }; - this.originalMousePosition = { left: event.pageX, top: event.pageY }; - - this.aspectRatio = (typeof o.aspectRatio === "number") ? - o.aspectRatio : - ((this.originalSize.width / this.originalSize.height) || 1); - - cursor = $(".ui-resizable-" + this.axis).css("cursor"); - $("body").css("cursor", cursor === "auto" ? this.axis + "-resize" : cursor); - - el.addClass("ui-resizable-resizing"); - this._propagate("start", event); - return true; - }, - - _mouseDrag: function(event) { - - var data, props, - smp = this.originalMousePosition, - a = this.axis, - dx = (event.pageX - smp.left) || 0, - dy = (event.pageY - smp.top) || 0, - trigger = this._change[a]; - - this._updatePrevProperties(); - - if (!trigger) { - return false; - } - - data = trigger.apply(this, [ event, dx, dy ]); - - this._updateVirtualBoundaries(event.shiftKey); - if (this._aspectRatio || event.shiftKey) { - data = this._updateRatio(data, event); - } - - data = this._respectSize(data, event); - - this._updateCache(data); - - this._propagate("resize", event); - - props = this._applyChanges(); - - if ( !this._helper && this._proportionallyResizeElements.length ) { - this._proportionallyResize(); - } - - if ( !$.isEmptyObject( props ) ) { - this._updatePrevProperties(); - this._trigger( "resize", event, this.ui() ); - this._applyChanges(); - } - - return false; - }, - - _mouseStop: function(event) { - - this.resizing = false; - var pr, ista, soffseth, soffsetw, s, left, top, - o = this.options, that = this; - - if (this._helper) { - - pr = this._proportionallyResizeElements; - ista = pr.length && (/textarea/i).test(pr[0].nodeName); - soffseth = ista && this._hasScroll(pr[0], "left") ? 0 : that.sizeDiff.height; - soffsetw = ista ? 0 : that.sizeDiff.width; - - s = { - width: (that.helper.width() - soffsetw), - height: (that.helper.height() - soffseth) - }; - left = (parseInt(that.element.css("left"), 10) + - (that.position.left - that.originalPosition.left)) || null; - top = (parseInt(that.element.css("top"), 10) + - (that.position.top - that.originalPosition.top)) || null; - - if (!o.animate) { - this.element.css($.extend(s, { top: top, left: left })); - } - - that.helper.height(that.size.height); - that.helper.width(that.size.width); - - if (this._helper && !o.animate) { - this._proportionallyResize(); - } - } - - $("body").css("cursor", "auto"); - - this.element.removeClass("ui-resizable-resizing"); - - this._propagate("stop", event); - - if (this._helper) { - this.helper.remove(); - } - - return false; - - }, - - _updatePrevProperties: function() { - this.prevPosition = { - top: this.position.top, - left: this.position.left - }; - this.prevSize = { - width: this.size.width, - height: this.size.height - }; - }, - - _applyChanges: function() { - var props = {}; - - if ( this.position.top !== this.prevPosition.top ) { - props.top = this.position.top + "px"; - } - if ( this.position.left !== this.prevPosition.left ) { - props.left = this.position.left + "px"; - } - if ( this.size.width !== this.prevSize.width ) { - props.width = this.size.width + "px"; - } - if ( this.size.height !== this.prevSize.height ) { - props.height = this.size.height + "px"; - } - - this.helper.css( props ); - - return props; - }, - - _updateVirtualBoundaries: function(forceAspectRatio) { - var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b, - o = this.options; - - b = { - minWidth: this._isNumber(o.minWidth) ? o.minWidth : 0, - maxWidth: this._isNumber(o.maxWidth) ? o.maxWidth : Infinity, - minHeight: this._isNumber(o.minHeight) ? o.minHeight : 0, - maxHeight: this._isNumber(o.maxHeight) ? o.maxHeight : Infinity - }; - - if (this._aspectRatio || forceAspectRatio) { - pMinWidth = b.minHeight * this.aspectRatio; - pMinHeight = b.minWidth / this.aspectRatio; - pMaxWidth = b.maxHeight * this.aspectRatio; - pMaxHeight = b.maxWidth / this.aspectRatio; - - if (pMinWidth > b.minWidth) { - b.minWidth = pMinWidth; - } - if (pMinHeight > b.minHeight) { - b.minHeight = pMinHeight; - } - if (pMaxWidth < b.maxWidth) { - b.maxWidth = pMaxWidth; - } - if (pMaxHeight < b.maxHeight) { - b.maxHeight = pMaxHeight; - } - } - this._vBoundaries = b; - }, - - _updateCache: function(data) { - this.offset = this.helper.offset(); - if (this._isNumber(data.left)) { - this.position.left = data.left; - } - if (this._isNumber(data.top)) { - this.position.top = data.top; - } - if (this._isNumber(data.height)) { - this.size.height = data.height; - } - if (this._isNumber(data.width)) { - this.size.width = data.width; - } - }, - - _updateRatio: function( data ) { - - var cpos = this.position, - csize = this.size, - a = this.axis; - - if (this._isNumber(data.height)) { - data.width = (data.height * this.aspectRatio); - } else if (this._isNumber(data.width)) { - data.height = (data.width / this.aspectRatio); - } - - if (a === "sw") { - data.left = cpos.left + (csize.width - data.width); - data.top = null; - } - if (a === "nw") { - data.top = cpos.top + (csize.height - data.height); - data.left = cpos.left + (csize.width - data.width); - } - - return data; - }, - - _respectSize: function( data ) { - - var o = this._vBoundaries, - a = this.axis, - ismaxw = this._isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), - ismaxh = this._isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height), - isminw = this._isNumber(data.width) && o.minWidth && (o.minWidth > data.width), - isminh = this._isNumber(data.height) && o.minHeight && (o.minHeight > data.height), - dw = this.originalPosition.left + this.originalSize.width, - dh = this.position.top + this.size.height, - cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a); - if (isminw) { - data.width = o.minWidth; - } - if (isminh) { - data.height = o.minHeight; - } - if (ismaxw) { - data.width = o.maxWidth; - } - if (ismaxh) { - data.height = o.maxHeight; - } - - if (isminw && cw) { - data.left = dw - o.minWidth; - } - if (ismaxw && cw) { - data.left = dw - o.maxWidth; - } - if (isminh && ch) { - data.top = dh - o.minHeight; - } - if (ismaxh && ch) { - data.top = dh - o.maxHeight; - } - - // Fixing jump error on top/left - bug #2330 - if (!data.width && !data.height && !data.left && data.top) { - data.top = null; - } else if (!data.width && !data.height && !data.top && data.left) { - data.left = null; - } - - return data; - }, - - _getPaddingPlusBorderDimensions: function( element ) { - var i = 0, - widths = [], - borders = [ - element.css( "borderTopWidth" ), - element.css( "borderRightWidth" ), - element.css( "borderBottomWidth" ), - element.css( "borderLeftWidth" ) - ], - paddings = [ - element.css( "paddingTop" ), - element.css( "paddingRight" ), - element.css( "paddingBottom" ), - element.css( "paddingLeft" ) - ]; - - for ( ; i < 4; i++ ) { - widths[ i ] = ( parseInt( borders[ i ], 10 ) || 0 ); - widths[ i ] += ( parseInt( paddings[ i ], 10 ) || 0 ); - } - - return { - height: widths[ 0 ] + widths[ 2 ], - width: widths[ 1 ] + widths[ 3 ] - }; - }, - - _proportionallyResize: function() { - - if (!this._proportionallyResizeElements.length) { - return; - } - - var prel, - i = 0, - element = this.helper || this.element; - - for ( ; i < this._proportionallyResizeElements.length; i++) { - - prel = this._proportionallyResizeElements[i]; - - // TODO: Seems like a bug to cache this.outerDimensions - // considering that we are in a loop. - if (!this.outerDimensions) { - this.outerDimensions = this._getPaddingPlusBorderDimensions( prel ); - } - - prel.css({ - height: (element.height() - this.outerDimensions.height) || 0, - width: (element.width() - this.outerDimensions.width) || 0 - }); - - } - - }, - - _renderProxy: function() { - - var el = this.element, o = this.options; - this.elementOffset = el.offset(); - - if (this._helper) { - - this.helper = this.helper || $("<div style='overflow:hidden;'></div>"); - - this.helper.addClass(this._helper).css({ - width: this.element.outerWidth() - 1, - height: this.element.outerHeight() - 1, - position: "absolute", - left: this.elementOffset.left + "px", - top: this.elementOffset.top + "px", - zIndex: ++o.zIndex //TODO: Don't modify option - }); - - this.helper - .appendTo("body") - .disableSelection(); - - } else { - this.helper = this.element; - } - - }, - - _change: { - e: function(event, dx) { - return { width: this.originalSize.width + dx }; - }, - w: function(event, dx) { - var cs = this.originalSize, sp = this.originalPosition; - return { left: sp.left + dx, width: cs.width - dx }; - }, - n: function(event, dx, dy) { - var cs = this.originalSize, sp = this.originalPosition; - return { top: sp.top + dy, height: cs.height - dy }; - }, - s: function(event, dx, dy) { - return { height: this.originalSize.height + dy }; - }, - se: function(event, dx, dy) { - return $.extend(this._change.s.apply(this, arguments), - this._change.e.apply(this, [ event, dx, dy ])); - }, - sw: function(event, dx, dy) { - return $.extend(this._change.s.apply(this, arguments), - this._change.w.apply(this, [ event, dx, dy ])); - }, - ne: function(event, dx, dy) { - return $.extend(this._change.n.apply(this, arguments), - this._change.e.apply(this, [ event, dx, dy ])); - }, - nw: function(event, dx, dy) { - return $.extend(this._change.n.apply(this, arguments), - this._change.w.apply(this, [ event, dx, dy ])); - } - }, - - _propagate: function(n, event) { - $.ui.plugin.call(this, n, [ event, this.ui() ]); - (n !== "resize" && this._trigger(n, event, this.ui())); - }, - - plugins: {}, - - ui: function() { - return { - originalElement: this.originalElement, - element: this.element, - helper: this.helper, - position: this.position, - size: this.size, - originalSize: this.originalSize, - originalPosition: this.originalPosition - }; - } - -}); - -/* - * Resizable Extensions - */ - -$.ui.plugin.add("resizable", "animate", { - - stop: function( event ) { - var that = $(this).resizable( "instance" ), - o = that.options, - pr = that._proportionallyResizeElements, - ista = pr.length && (/textarea/i).test(pr[0].nodeName), - soffseth = ista && that._hasScroll(pr[0], "left") ? 0 : that.sizeDiff.height, - soffsetw = ista ? 0 : that.sizeDiff.width, - style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) }, - left = (parseInt(that.element.css("left"), 10) + - (that.position.left - that.originalPosition.left)) || null, - top = (parseInt(that.element.css("top"), 10) + - (that.position.top - that.originalPosition.top)) || null; - - that.element.animate( - $.extend(style, top && left ? { top: top, left: left } : {}), { - duration: o.animateDuration, - easing: o.animateEasing, - step: function() { - - var data = { - width: parseInt(that.element.css("width"), 10), - height: parseInt(that.element.css("height"), 10), - top: parseInt(that.element.css("top"), 10), - left: parseInt(that.element.css("left"), 10) - }; - - if (pr && pr.length) { - $(pr[0]).css({ width: data.width, height: data.height }); - } - - // propagating resize, and updating values for each animation step - that._updateCache(data); - that._propagate("resize", event); - - } - } - ); - } - -}); - -$.ui.plugin.add( "resizable", "containment", { - - start: function() { - var element, p, co, ch, cw, width, height, - that = $( this ).resizable( "instance" ), - o = that.options, - el = that.element, - oc = o.containment, - ce = ( oc instanceof $ ) ? oc.get( 0 ) : ( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc; - - if ( !ce ) { - return; - } - - that.containerElement = $( ce ); - - if ( /document/.test( oc ) || oc === document ) { - that.containerOffset = { - left: 0, - top: 0 - }; - that.containerPosition = { - left: 0, - top: 0 - }; - - that.parentData = { - element: $( document ), - left: 0, - top: 0, - width: $( document ).width(), - height: $( document ).height() || document.body.parentNode.scrollHeight - }; - } else { - element = $( ce ); - p = []; - $([ "Top", "Right", "Left", "Bottom" ]).each(function( i, name ) { - p[ i ] = that._num( element.css( "padding" + name ) ); - }); - - that.containerOffset = element.offset(); - that.containerPosition = element.position(); - that.containerSize = { - height: ( element.innerHeight() - p[ 3 ] ), - width: ( element.innerWidth() - p[ 1 ] ) - }; - - co = that.containerOffset; - ch = that.containerSize.height; - cw = that.containerSize.width; - width = ( that._hasScroll ( ce, "left" ) ? ce.scrollWidth : cw ); - height = ( that._hasScroll ( ce ) ? ce.scrollHeight : ch ) ; - - that.parentData = { - element: ce, - left: co.left, - top: co.top, - width: width, - height: height - }; - } - }, - - resize: function( event ) { - var woset, hoset, isParent, isOffsetRelative, - that = $( this ).resizable( "instance" ), - o = that.options, - co = that.containerOffset, - cp = that.position, - pRatio = that._aspectRatio || event.shiftKey, - cop = { - top: 0, - left: 0 - }, - ce = that.containerElement, - continueResize = true; - - if ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( "position" ) ) ) { - cop = co; - } - - if ( cp.left < ( that._helper ? co.left : 0 ) ) { - that.size.width = that.size.width + - ( that._helper ? - ( that.position.left - co.left ) : - ( that.position.left - cop.left ) ); - - if ( pRatio ) { - that.size.height = that.size.width / that.aspectRatio; - continueResize = false; - } - that.position.left = o.helper ? co.left : 0; - } - - if ( cp.top < ( that._helper ? co.top : 0 ) ) { - that.size.height = that.size.height + - ( that._helper ? - ( that.position.top - co.top ) : - that.position.top ); - - if ( pRatio ) { - that.size.width = that.size.height * that.aspectRatio; - continueResize = false; - } - that.position.top = that._helper ? co.top : 0; - } - - isParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 ); - isOffsetRelative = /relative|absolute/.test( that.containerElement.css( "position" ) ); - - if ( isParent && isOffsetRelative ) { - that.offset.left = that.parentData.left + that.position.left; - that.offset.top = that.parentData.top + that.position.top; - } else { - that.offset.left = that.element.offset().left; - that.offset.top = that.element.offset().top; - } - - woset = Math.abs( that.sizeDiff.width + - (that._helper ? - that.offset.left - cop.left : - (that.offset.left - co.left)) ); - - hoset = Math.abs( that.sizeDiff.height + - (that._helper ? - that.offset.top - cop.top : - (that.offset.top - co.top)) ); - - if ( woset + that.size.width >= that.parentData.width ) { - that.size.width = that.parentData.width - woset; - if ( pRatio ) { - that.size.height = that.size.width / that.aspectRatio; - continueResize = false; - } - } - - if ( hoset + that.size.height >= that.parentData.height ) { - that.size.height = that.parentData.height - hoset; - if ( pRatio ) { - that.size.width = that.size.height * that.aspectRatio; - continueResize = false; - } - } - - if ( !continueResize ) { - that.position.left = that.prevPosition.left; - that.position.top = that.prevPosition.top; - that.size.width = that.prevSize.width; - that.size.height = that.prevSize.height; - } - }, - - stop: function() { - var that = $( this ).resizable( "instance" ), - o = that.options, - co = that.containerOffset, - cop = that.containerPosition, - ce = that.containerElement, - helper = $( that.helper ), - ho = helper.offset(), - w = helper.outerWidth() - that.sizeDiff.width, - h = helper.outerHeight() - that.sizeDiff.height; - - if ( that._helper && !o.animate && ( /relative/ ).test( ce.css( "position" ) ) ) { - $( this ).css({ - left: ho.left - cop.left - co.left, - width: w, - height: h - }); - } - - if ( that._helper && !o.animate && ( /static/ ).test( ce.css( "position" ) ) ) { - $( this ).css({ - left: ho.left - cop.left - co.left, - width: w, - height: h - }); - } - } -}); - -$.ui.plugin.add("resizable", "alsoResize", { - - start: function() { - var that = $(this).resizable( "instance" ), - o = that.options; - - $(o.alsoResize).each(function() { - var el = $(this); - el.data("ui-resizable-alsoresize", { - width: parseInt(el.width(), 10), height: parseInt(el.height(), 10), - left: parseInt(el.css("left"), 10), top: parseInt(el.css("top"), 10) - }); - }); - }, - - resize: function(event, ui) { - var that = $(this).resizable( "instance" ), - o = that.options, - os = that.originalSize, - op = that.originalPosition, - delta = { - height: (that.size.height - os.height) || 0, - width: (that.size.width - os.width) || 0, - top: (that.position.top - op.top) || 0, - left: (that.position.left - op.left) || 0 - }; - - $(o.alsoResize).each(function() { - var el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {}, - css = el.parents(ui.originalElement[0]).length ? - [ "width", "height" ] : - [ "width", "height", "top", "left" ]; - - $.each(css, function(i, prop) { - var sum = (start[prop] || 0) + (delta[prop] || 0); - if (sum && sum >= 0) { - style[prop] = sum || null; - } - }); - - el.css(style); - }); - }, - - stop: function() { - $(this).removeData("resizable-alsoresize"); - } -}); - -$.ui.plugin.add("resizable", "ghost", { - - start: function() { - - var that = $(this).resizable( "instance" ), o = that.options, cs = that.size; - - that.ghost = that.originalElement.clone(); - that.ghost - .css({ - opacity: 0.25, - display: "block", - position: "relative", - height: cs.height, - width: cs.width, - margin: 0, - left: 0, - top: 0 - }) - .addClass("ui-resizable-ghost") - .addClass(typeof o.ghost === "string" ? o.ghost : ""); - - that.ghost.appendTo(that.helper); - - }, - - resize: function() { - var that = $(this).resizable( "instance" ); - if (that.ghost) { - that.ghost.css({ - position: "relative", - height: that.size.height, - width: that.size.width - }); - } - }, - - stop: function() { - var that = $(this).resizable( "instance" ); - if (that.ghost && that.helper) { - that.helper.get(0).removeChild(that.ghost.get(0)); - } - } - -}); - -$.ui.plugin.add("resizable", "grid", { - - resize: function() { - var outerDimensions, - that = $(this).resizable( "instance" ), - o = that.options, - cs = that.size, - os = that.originalSize, - op = that.originalPosition, - a = that.axis, - grid = typeof o.grid === "number" ? [ o.grid, o.grid ] : o.grid, - gridX = (grid[0] || 1), - gridY = (grid[1] || 1), - ox = Math.round((cs.width - os.width) / gridX) * gridX, - oy = Math.round((cs.height - os.height) / gridY) * gridY, - newWidth = os.width + ox, - newHeight = os.height + oy, - isMaxWidth = o.maxWidth && (o.maxWidth < newWidth), - isMaxHeight = o.maxHeight && (o.maxHeight < newHeight), - isMinWidth = o.minWidth && (o.minWidth > newWidth), - isMinHeight = o.minHeight && (o.minHeight > newHeight); - - o.grid = grid; - - if (isMinWidth) { - newWidth += gridX; - } - if (isMinHeight) { - newHeight += gridY; - } - if (isMaxWidth) { - newWidth -= gridX; - } - if (isMaxHeight) { - newHeight -= gridY; - } - - if (/^(se|s|e)$/.test(a)) { - that.size.width = newWidth; - that.size.height = newHeight; - } else if (/^(ne)$/.test(a)) { - that.size.width = newWidth; - that.size.height = newHeight; - that.position.top = op.top - oy; - } else if (/^(sw)$/.test(a)) { - that.size.width = newWidth; - that.size.height = newHeight; - that.position.left = op.left - ox; - } else { - if ( newHeight - gridY <= 0 || newWidth - gridX <= 0) { - outerDimensions = that._getPaddingPlusBorderDimensions( this ); - } - - if ( newHeight - gridY > 0 ) { - that.size.height = newHeight; - that.position.top = op.top - oy; - } else { - newHeight = gridY - outerDimensions.height; - that.size.height = newHeight; - that.position.top = op.top + os.height - newHeight; - } - if ( newWidth - gridX > 0 ) { - that.size.width = newWidth; - that.position.left = op.left - ox; - } else { - newWidth = gridX - outerDimensions.width; - that.size.width = newWidth; - that.position.left = op.left + os.width - newWidth; - } - } - } - -}); - -var resizable = $.ui.resizable; - - -/*! - * jQuery UI Selectable 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/selectable/ - */ - - -var selectable = $.widget("ui.selectable", $.ui.mouse, { - version: "1.11.4", - options: { - appendTo: "body", - autoRefresh: true, - distance: 0, - filter: "*", - tolerance: "touch", - - // callbacks - selected: null, - selecting: null, - start: null, - stop: null, - unselected: null, - unselecting: null - }, - _create: function() { - var selectees, - that = this; - - this.element.addClass("ui-selectable"); - - this.dragged = false; - - // cache selectee children based on filter - this.refresh = function() { - selectees = $(that.options.filter, that.element[0]); - selectees.addClass("ui-selectee"); - selectees.each(function() { - var $this = $(this), - pos = $this.offset(); - $.data(this, "selectable-item", { - element: this, - $element: $this, - left: pos.left, - top: pos.top, - right: pos.left + $this.outerWidth(), - bottom: pos.top + $this.outerHeight(), - startselected: false, - selected: $this.hasClass("ui-selected"), - selecting: $this.hasClass("ui-selecting"), - unselecting: $this.hasClass("ui-unselecting") - }); - }); - }; - this.refresh(); - - this.selectees = selectees.addClass("ui-selectee"); - - this._mouseInit(); - - this.helper = $("<div class='ui-selectable-helper'></div>"); - }, - - _destroy: function() { - this.selectees - .removeClass("ui-selectee") - .removeData("selectable-item"); - this.element - .removeClass("ui-selectable ui-selectable-disabled"); - this._mouseDestroy(); - }, - - _mouseStart: function(event) { - var that = this, - options = this.options; - - this.opos = [ event.pageX, event.pageY ]; - - if (this.options.disabled) { - return; - } - - this.selectees = $(options.filter, this.element[0]); - - this._trigger("start", event); - - $(options.appendTo).append(this.helper); - // position helper (lasso) - this.helper.css({ - "left": event.pageX, - "top": event.pageY, - "width": 0, - "height": 0 - }); - - if (options.autoRefresh) { - this.refresh(); - } - - this.selectees.filter(".ui-selected").each(function() { - var selectee = $.data(this, "selectable-item"); - selectee.startselected = true; - if (!event.metaKey && !event.ctrlKey) { - selectee.$element.removeClass("ui-selected"); - selectee.selected = false; - selectee.$element.addClass("ui-unselecting"); - selectee.unselecting = true; - // selectable UNSELECTING callback - that._trigger("unselecting", event, { - unselecting: selectee.element - }); - } - }); - - $(event.target).parents().addBack().each(function() { - var doSelect, - selectee = $.data(this, "selectable-item"); - if (selectee) { - doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass("ui-selected"); - selectee.$element - .removeClass(doSelect ? "ui-unselecting" : "ui-selected") - .addClass(doSelect ? "ui-selecting" : "ui-unselecting"); - selectee.unselecting = !doSelect; - selectee.selecting = doSelect; - selectee.selected = doSelect; - // selectable (UN)SELECTING callback - if (doSelect) { - that._trigger("selecting", event, { - selecting: selectee.element - }); - } else { - that._trigger("unselecting", event, { - unselecting: selectee.element - }); - } - return false; - } - }); - - }, - - _mouseDrag: function(event) { - - this.dragged = true; - - if (this.options.disabled) { - return; - } - - var tmp, - that = this, - options = this.options, - x1 = this.opos[0], - y1 = this.opos[1], - x2 = event.pageX, - y2 = event.pageY; - - if (x1 > x2) { tmp = x2; x2 = x1; x1 = tmp; } - if (y1 > y2) { tmp = y2; y2 = y1; y1 = tmp; } - this.helper.css({ left: x1, top: y1, width: x2 - x1, height: y2 - y1 }); - - this.selectees.each(function() { - var selectee = $.data(this, "selectable-item"), - hit = false; - - //prevent helper from being selected if appendTo: selectable - if (!selectee || selectee.element === that.element[0]) { - return; - } - - if (options.tolerance === "touch") { - hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) ); - } else if (options.tolerance === "fit") { - hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2); - } - - if (hit) { - // SELECT - if (selectee.selected) { - selectee.$element.removeClass("ui-selected"); - selectee.selected = false; - } - if (selectee.unselecting) { - selectee.$element.removeClass("ui-unselecting"); - selectee.unselecting = false; - } - if (!selectee.selecting) { - selectee.$element.addClass("ui-selecting"); - selectee.selecting = true; - // selectable SELECTING callback - that._trigger("selecting", event, { - selecting: selectee.element - }); - } - } else { - // UNSELECT - if (selectee.selecting) { - if ((event.metaKey || event.ctrlKey) && selectee.startselected) { - selectee.$element.removeClass("ui-selecting"); - selectee.selecting = false; - selectee.$element.addClass("ui-selected"); - selectee.selected = true; - } else { - selectee.$element.removeClass("ui-selecting"); - selectee.selecting = false; - if (selectee.startselected) { - selectee.$element.addClass("ui-unselecting"); - selectee.unselecting = true; - } - // selectable UNSELECTING callback - that._trigger("unselecting", event, { - unselecting: selectee.element - }); - } - } - if (selectee.selected) { - if (!event.metaKey && !event.ctrlKey && !selectee.startselected) { - selectee.$element.removeClass("ui-selected"); - selectee.selected = false; - - selectee.$element.addClass("ui-unselecting"); - selectee.unselecting = true; - // selectable UNSELECTING callback - that._trigger("unselecting", event, { - unselecting: selectee.element - }); - } - } - } - }); - - return false; - }, - - _mouseStop: function(event) { - var that = this; - - this.dragged = false; - - $(".ui-unselecting", this.element[0]).each(function() { - var selectee = $.data(this, "selectable-item"); - selectee.$element.removeClass("ui-unselecting"); - selectee.unselecting = false; - selectee.startselected = false; - that._trigger("unselected", event, { - unselected: selectee.element - }); - }); - $(".ui-selecting", this.element[0]).each(function() { - var selectee = $.data(this, "selectable-item"); - selectee.$element.removeClass("ui-selecting").addClass("ui-selected"); - selectee.selecting = false; - selectee.selected = true; - selectee.startselected = true; - that._trigger("selected", event, { - selected: selectee.element - }); - }); - this._trigger("stop", event); - - this.helper.remove(); - - return false; - } - -}); - - -/*! - * jQuery UI Sortable 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/sortable/ - */ - - -var sortable = $.widget("ui.sortable", $.ui.mouse, { - version: "1.11.4", - widgetEventPrefix: "sort", - ready: false, - options: { - appendTo: "parent", - axis: false, - connectWith: false, - containment: false, - cursor: "auto", - cursorAt: false, - dropOnEmpty: true, - forcePlaceholderSize: false, - forceHelperSize: false, - grid: false, - handle: false, - helper: "original", - items: "> *", - opacity: false, - placeholder: false, - revert: false, - scroll: true, - scrollSensitivity: 20, - scrollSpeed: 20, - scope: "default", - tolerance: "intersect", - zIndex: 1000, - - // callbacks - activate: null, - beforeStop: null, - change: null, - deactivate: null, - out: null, - over: null, - receive: null, - remove: null, - sort: null, - start: null, - stop: null, - update: null - }, - - _isOverAxis: function( x, reference, size ) { - return ( x >= reference ) && ( x < ( reference + size ) ); - }, - - _isFloating: function( item ) { - return (/left|right/).test(item.css("float")) || (/inline|table-cell/).test(item.css("display")); - }, - - _create: function() { - this.containerCache = {}; - this.element.addClass("ui-sortable"); - - //Get the items - this.refresh(); - - //Let's determine the parent's offset - this.offset = this.element.offset(); - - //Initialize mouse events for interaction - this._mouseInit(); - - this._setHandleClassName(); - - //We're ready to go - this.ready = true; - - }, - - _setOption: function( key, value ) { - this._super( key, value ); - - if ( key === "handle" ) { - this._setHandleClassName(); - } - }, - - _setHandleClassName: function() { - this.element.find( ".ui-sortable-handle" ).removeClass( "ui-sortable-handle" ); - $.each( this.items, function() { - ( this.instance.options.handle ? - this.item.find( this.instance.options.handle ) : this.item ) - .addClass( "ui-sortable-handle" ); - }); - }, - - _destroy: function() { - this.element - .removeClass( "ui-sortable ui-sortable-disabled" ) - .find( ".ui-sortable-handle" ) - .removeClass( "ui-sortable-handle" ); - this._mouseDestroy(); - - for ( var i = this.items.length - 1; i >= 0; i-- ) { - this.items[i].item.removeData(this.widgetName + "-item"); - } - - return this; - }, - - _mouseCapture: function(event, overrideHandle) { - var currentItem = null, - validHandle = false, - that = this; - - if (this.reverting) { - return false; - } - - if(this.options.disabled || this.options.type === "static") { - return false; - } - - //We have to refresh the items data once first - this._refreshItems(event); - - //Find out if the clicked node (or one of its parents) is a actual item in this.items - $(event.target).parents().each(function() { - if($.data(this, that.widgetName + "-item") === that) { - currentItem = $(this); - return false; - } - }); - if($.data(event.target, that.widgetName + "-item") === that) { - currentItem = $(event.target); - } - - if(!currentItem) { - return false; - } - if(this.options.handle && !overrideHandle) { - $(this.options.handle, currentItem).find("*").addBack().each(function() { - if(this === event.target) { - validHandle = true; - } - }); - if(!validHandle) { - return false; - } - } - - this.currentItem = currentItem; - this._removeCurrentsFromItems(); - return true; - - }, - - _mouseStart: function(event, overrideHandle, noActivation) { - - var i, body, - o = this.options; - - this.currentContainer = this; - - //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture - this.refreshPositions(); - - //Create and append the visible helper - this.helper = this._createHelper(event); - - //Cache the helper size - this._cacheHelperProportions(); - - /* - * - Position generation - - * This block generates everything position related - it's the core of draggables. - */ - - //Cache the margins of the original element - this._cacheMargins(); - - //Get the next scrolling parent - this.scrollParent = this.helper.scrollParent(); - - //The element's absolute position on the page minus margins - this.offset = this.currentItem.offset(); - this.offset = { - top: this.offset.top - this.margins.top, - left: this.offset.left - this.margins.left - }; - - $.extend(this.offset, { - click: { //Where the click happened, relative to the element - left: event.pageX - this.offset.left, - top: event.pageY - this.offset.top - }, - parent: this._getParentOffset(), - relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper - }); - - // Only after we got the offset, we can change the helper's position to absolute - // TODO: Still need to figure out a way to make relative sorting possible - this.helper.css("position", "absolute"); - this.cssPosition = this.helper.css("position"); - - //Generate the original position - this.originalPosition = this._generatePosition(event); - this.originalPageX = event.pageX; - this.originalPageY = event.pageY; - - //Adjust the mouse offset relative to the helper if "cursorAt" is supplied - (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); - - //Cache the former DOM position - this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] }; - - //If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way - if(this.helper[0] !== this.currentItem[0]) { - this.currentItem.hide(); - } - - //Create the placeholder - this._createPlaceholder(); - - //Set a containment if given in the options - if(o.containment) { - this._setContainment(); - } - - if( o.cursor && o.cursor !== "auto" ) { // cursor option - body = this.document.find( "body" ); - - // support: IE - this.storedCursor = body.css( "cursor" ); - body.css( "cursor", o.cursor ); - - this.storedStylesheet = $( "<style>*{ cursor: "+o.cursor+" !important; }</style>" ).appendTo( body ); - } - - if(o.opacity) { // opacity option - if (this.helper.css("opacity")) { - this._storedOpacity = this.helper.css("opacity"); - } - this.helper.css("opacity", o.opacity); - } - - if(o.zIndex) { // zIndex option - if (this.helper.css("zIndex")) { - this._storedZIndex = this.helper.css("zIndex"); - } - this.helper.css("zIndex", o.zIndex); - } - - //Prepare scrolling - if(this.scrollParent[0] !== this.document[0] && this.scrollParent[0].tagName !== "HTML") { - this.overflowOffset = this.scrollParent.offset(); - } - - //Call callbacks - this._trigger("start", event, this._uiHash()); - - //Recache the helper size - if(!this._preserveHelperProportions) { - this._cacheHelperProportions(); - } - - - //Post "activate" events to possible containers - if( !noActivation ) { - for ( i = this.containers.length - 1; i >= 0; i-- ) { - this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) ); - } - } - - //Prepare possible droppables - if($.ui.ddmanager) { - $.ui.ddmanager.current = this; - } - - if ($.ui.ddmanager && !o.dropBehaviour) { - $.ui.ddmanager.prepareOffsets(this, event); - } - - this.dragging = true; - - this.helper.addClass("ui-sortable-helper"); - this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position - return true; - - }, - - _mouseDrag: function(event) { - var i, item, itemElement, intersection, - o = this.options, - scrolled = false; - - //Compute the helpers position - this.position = this._generatePosition(event); - this.positionAbs = this._convertPositionTo("absolute"); - - if (!this.lastPositionAbs) { - this.lastPositionAbs = this.positionAbs; - } - - //Do scrolling - if(this.options.scroll) { - if(this.scrollParent[0] !== this.document[0] && this.scrollParent[0].tagName !== "HTML") { - - if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) { - this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed; - } else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) { - this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed; - } - - if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) { - this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed; - } else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) { - this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed; - } - - } else { - - if(event.pageY - this.document.scrollTop() < o.scrollSensitivity) { - scrolled = this.document.scrollTop(this.document.scrollTop() - o.scrollSpeed); - } else if(this.window.height() - (event.pageY - this.document.scrollTop()) < o.scrollSensitivity) { - scrolled = this.document.scrollTop(this.document.scrollTop() + o.scrollSpeed); - } - - if(event.pageX - this.document.scrollLeft() < o.scrollSensitivity) { - scrolled = this.document.scrollLeft(this.document.scrollLeft() - o.scrollSpeed); - } else if(this.window.width() - (event.pageX - this.document.scrollLeft()) < o.scrollSensitivity) { - scrolled = this.document.scrollLeft(this.document.scrollLeft() + o.scrollSpeed); - } - - } - - if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) { - $.ui.ddmanager.prepareOffsets(this, event); - } - } - - //Regenerate the absolute position used for position checks - this.positionAbs = this._convertPositionTo("absolute"); - - //Set the helper position - if(!this.options.axis || this.options.axis !== "y") { - this.helper[0].style.left = this.position.left+"px"; - } - if(!this.options.axis || this.options.axis !== "x") { - this.helper[0].style.top = this.position.top+"px"; - } - - //Rearrange - for (i = this.items.length - 1; i >= 0; i--) { - - //Cache variables and intersection, continue if no intersection - item = this.items[i]; - itemElement = item.item[0]; - intersection = this._intersectsWithPointer(item); - if (!intersection) { - continue; - } - - // Only put the placeholder inside the current Container, skip all - // items from other containers. This works because when moving - // an item from one container to another the - // currentContainer is switched before the placeholder is moved. - // - // Without this, moving items in "sub-sortables" can cause - // the placeholder to jitter between the outer and inner container. - if (item.instance !== this.currentContainer) { - continue; - } - - // cannot intersect with itself - // no useless actions that have been done before - // no action if the item moved is the parent of the item checked - if (itemElement !== this.currentItem[0] && - this.placeholder[intersection === 1 ? "next" : "prev"]()[0] !== itemElement && - !$.contains(this.placeholder[0], itemElement) && - (this.options.type === "semi-dynamic" ? !$.contains(this.element[0], itemElement) : true) - ) { - - this.direction = intersection === 1 ? "down" : "up"; - - if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) { - this._rearrange(event, item); - } else { - break; - } - - this._trigger("change", event, this._uiHash()); - break; - } - } - - //Post events to containers - this._contactContainers(event); - - //Interconnect with droppables - if($.ui.ddmanager) { - $.ui.ddmanager.drag(this, event); - } - - //Call callbacks - this._trigger("sort", event, this._uiHash()); - - this.lastPositionAbs = this.positionAbs; - return false; - - }, - - _mouseStop: function(event, noPropagation) { - - if(!event) { - return; - } - - //If we are using droppables, inform the manager about the drop - if ($.ui.ddmanager && !this.options.dropBehaviour) { - $.ui.ddmanager.drop(this, event); - } - - if(this.options.revert) { - var that = this, - cur = this.placeholder.offset(), - axis = this.options.axis, - animation = {}; - - if ( !axis || axis === "x" ) { - animation.left = cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] === this.document[0].body ? 0 : this.offsetParent[0].scrollLeft); - } - if ( !axis || axis === "y" ) { - animation.top = cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === this.document[0].body ? 0 : this.offsetParent[0].scrollTop); - } - this.reverting = true; - $(this.helper).animate( animation, parseInt(this.options.revert, 10) || 500, function() { - that._clear(event); - }); - } else { - this._clear(event, noPropagation); - } - - return false; - - }, - - cancel: function() { - - if(this.dragging) { - - this._mouseUp({ target: null }); - - if(this.options.helper === "original") { - this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); - } else { - this.currentItem.show(); - } - - //Post deactivating events to containers - for (var i = this.containers.length - 1; i >= 0; i--){ - this.containers[i]._trigger("deactivate", null, this._uiHash(this)); - if(this.containers[i].containerCache.over) { - this.containers[i]._trigger("out", null, this._uiHash(this)); - this.containers[i].containerCache.over = 0; - } - } - - } - - if (this.placeholder) { - //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! - if(this.placeholder[0].parentNode) { - this.placeholder[0].parentNode.removeChild(this.placeholder[0]); - } - if(this.options.helper !== "original" && this.helper && this.helper[0].parentNode) { - this.helper.remove(); - } - - $.extend(this, { - helper: null, - dragging: false, - reverting: false, - _noFinalSort: null - }); - - if(this.domPosition.prev) { - $(this.domPosition.prev).after(this.currentItem); - } else { - $(this.domPosition.parent).prepend(this.currentItem); - } - } - - return this; - - }, - - serialize: function(o) { - - var items = this._getItemsAsjQuery(o && o.connected), - str = []; - o = o || {}; - - $(items).each(function() { - var res = ($(o.item || this).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[\-=_](.+)/)); - if (res) { - str.push((o.key || res[1]+"[]")+"="+(o.key && o.expression ? res[1] : res[2])); - } - }); - - if(!str.length && o.key) { - str.push(o.key + "="); - } - - return str.join("&"); - - }, - - toArray: function(o) { - - var items = this._getItemsAsjQuery(o && o.connected), - ret = []; - - o = o || {}; - - items.each(function() { ret.push($(o.item || this).attr(o.attribute || "id") || ""); }); - return ret; - - }, - - /* Be careful with the following core functions */ - _intersectsWith: function(item) { - - var x1 = this.positionAbs.left, - x2 = x1 + this.helperProportions.width, - y1 = this.positionAbs.top, - y2 = y1 + this.helperProportions.height, - l = item.left, - r = l + item.width, - t = item.top, - b = t + item.height, - dyClick = this.offset.click.top, - dxClick = this.offset.click.left, - isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t && ( y1 + dyClick ) < b ), - isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l && ( x1 + dxClick ) < r ), - isOverElement = isOverElementHeight && isOverElementWidth; - - if ( this.options.tolerance === "pointer" || - this.options.forcePointerForContainers || - (this.options.tolerance !== "pointer" && this.helperProportions[this.floating ? "width" : "height"] > item[this.floating ? "width" : "height"]) - ) { - return isOverElement; - } else { - - return (l < x1 + (this.helperProportions.width / 2) && // Right Half - x2 - (this.helperProportions.width / 2) < r && // Left Half - t < y1 + (this.helperProportions.height / 2) && // Bottom Half - y2 - (this.helperProportions.height / 2) < b ); // Top Half - - } - }, - - _intersectsWithPointer: function(item) { - - var isOverElementHeight = (this.options.axis === "x") || this._isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height), - isOverElementWidth = (this.options.axis === "y") || this._isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width), - isOverElement = isOverElementHeight && isOverElementWidth, - verticalDirection = this._getDragVerticalDirection(), - horizontalDirection = this._getDragHorizontalDirection(); - - if (!isOverElement) { - return false; - } - - return this.floating ? - ( ((horizontalDirection && horizontalDirection === "right") || verticalDirection === "down") ? 2 : 1 ) - : ( verticalDirection && (verticalDirection === "down" ? 2 : 1) ); - - }, - - _intersectsWithSides: function(item) { - - var isOverBottomHalf = this._isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height), - isOverRightHalf = this._isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width), - verticalDirection = this._getDragVerticalDirection(), - horizontalDirection = this._getDragHorizontalDirection(); - - if (this.floating && horizontalDirection) { - return ((horizontalDirection === "right" && isOverRightHalf) || (horizontalDirection === "left" && !isOverRightHalf)); - } else { - return verticalDirection && ((verticalDirection === "down" && isOverBottomHalf) || (verticalDirection === "up" && !isOverBottomHalf)); - } - - }, - - _getDragVerticalDirection: function() { - var delta = this.positionAbs.top - this.lastPositionAbs.top; - return delta !== 0 && (delta > 0 ? "down" : "up"); - }, - - _getDragHorizontalDirection: function() { - var delta = this.positionAbs.left - this.lastPositionAbs.left; - return delta !== 0 && (delta > 0 ? "right" : "left"); - }, - - refresh: function(event) { - this._refreshItems(event); - this._setHandleClassName(); - this.refreshPositions(); - return this; - }, - - _connectWith: function() { - var options = this.options; - return options.connectWith.constructor === String ? [options.connectWith] : options.connectWith; - }, - - _getItemsAsjQuery: function(connected) { - - var i, j, cur, inst, - items = [], - queries = [], - connectWith = this._connectWith(); - - if(connectWith && connected) { - for (i = connectWith.length - 1; i >= 0; i--){ - cur = $(connectWith[i], this.document[0]); - for ( j = cur.length - 1; j >= 0; j--){ - inst = $.data(cur[j], this.widgetFullName); - if(inst && inst !== this && !inst.options.disabled) { - queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), inst]); - } - } - } - } - - queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), this]); - - function addItems() { - items.push( this ); - } - for (i = queries.length - 1; i >= 0; i--){ - queries[i][0].each( addItems ); - } - - return $(items); - - }, - - _removeCurrentsFromItems: function() { - - var list = this.currentItem.find(":data(" + this.widgetName + "-item)"); - - this.items = $.grep(this.items, function (item) { - for (var j=0; j < list.length; j++) { - if(list[j] === item.item[0]) { - return false; - } - } - return true; - }); - - }, - - _refreshItems: function(event) { - - this.items = []; - this.containers = [this]; - - var i, j, cur, inst, targetData, _queries, item, queriesLength, - items = this.items, - queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]], - connectWith = this._connectWith(); - - if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down - for (i = connectWith.length - 1; i >= 0; i--){ - cur = $(connectWith[i], this.document[0]); - for (j = cur.length - 1; j >= 0; j--){ - inst = $.data(cur[j], this.widgetFullName); - if(inst && inst !== this && !inst.options.disabled) { - queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]); - this.containers.push(inst); - } - } - } - } - - for (i = queries.length - 1; i >= 0; i--) { - targetData = queries[i][1]; - _queries = queries[i][0]; - - for (j=0, queriesLength = _queries.length; j < queriesLength; j++) { - item = $(_queries[j]); - - item.data(this.widgetName + "-item", targetData); // Data for target checking (mouse manager) - - items.push({ - item: item, - instance: targetData, - width: 0, height: 0, - left: 0, top: 0 - }); - } - } - - }, - - refreshPositions: function(fast) { - - // Determine whether items are being displayed horizontally - this.floating = this.items.length ? - this.options.axis === "x" || this._isFloating( this.items[ 0 ].item ) : - false; - - //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change - if(this.offsetParent && this.helper) { - this.offset.parent = this._getParentOffset(); - } - - var i, item, t, p; - - for (i = this.items.length - 1; i >= 0; i--){ - item = this.items[i]; - - //We ignore calculating positions of all connected containers when we're not over them - if(item.instance !== this.currentContainer && this.currentContainer && item.item[0] !== this.currentItem[0]) { - continue; - } - - t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item; - - if (!fast) { - item.width = t.outerWidth(); - item.height = t.outerHeight(); - } - - p = t.offset(); - item.left = p.left; - item.top = p.top; - } - - if(this.options.custom && this.options.custom.refreshContainers) { - this.options.custom.refreshContainers.call(this); - } else { - for (i = this.containers.length - 1; i >= 0; i--){ - p = this.containers[i].element.offset(); - this.containers[i].containerCache.left = p.left; - this.containers[i].containerCache.top = p.top; - this.containers[i].containerCache.width = this.containers[i].element.outerWidth(); - this.containers[i].containerCache.height = this.containers[i].element.outerHeight(); - } - } - - return this; - }, - - _createPlaceholder: function(that) { - that = that || this; - var className, - o = that.options; - - if(!o.placeholder || o.placeholder.constructor === String) { - className = o.placeholder; - o.placeholder = { - element: function() { - - var nodeName = that.currentItem[0].nodeName.toLowerCase(), - element = $( "<" + nodeName + ">", that.document[0] ) - .addClass(className || that.currentItem[0].className+" ui-sortable-placeholder") - .removeClass("ui-sortable-helper"); - - if ( nodeName === "tbody" ) { - that._createTrPlaceholder( - that.currentItem.find( "tr" ).eq( 0 ), - $( "<tr>", that.document[ 0 ] ).appendTo( element ) - ); - } else if ( nodeName === "tr" ) { - that._createTrPlaceholder( that.currentItem, element ); - } else if ( nodeName === "img" ) { - element.attr( "src", that.currentItem.attr( "src" ) ); - } - - if ( !className ) { - element.css( "visibility", "hidden" ); - } - - return element; - }, - update: function(container, p) { - - // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that - // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified - if(className && !o.forcePlaceholderSize) { - return; - } - - //If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item - if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css("paddingTop")||0, 10) - parseInt(that.currentItem.css("paddingBottom")||0, 10)); } - if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css("paddingLeft")||0, 10) - parseInt(that.currentItem.css("paddingRight")||0, 10)); } - } - }; - } - - //Create the placeholder - that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem)); - - //Append it after the actual current item - that.currentItem.after(that.placeholder); - - //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317) - o.placeholder.update(that, that.placeholder); - - }, - - _createTrPlaceholder: function( sourceTr, targetTr ) { - var that = this; - - sourceTr.children().each(function() { - $( "<td> </td>", that.document[ 0 ] ) - .attr( "colspan", $( this ).attr( "colspan" ) || 1 ) - .appendTo( targetTr ); - }); - }, - - _contactContainers: function(event) { - var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom, floating, axis, - innermostContainer = null, - innermostIndex = null; - - // get innermost container that intersects with item - for (i = this.containers.length - 1; i >= 0; i--) { - - // never consider a container that's located within the item itself - if($.contains(this.currentItem[0], this.containers[i].element[0])) { - continue; - } - - if(this._intersectsWith(this.containers[i].containerCache)) { - - // if we've already found a container and it's more "inner" than this, then continue - if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0])) { - continue; - } - - innermostContainer = this.containers[i]; - innermostIndex = i; - - } else { - // container doesn't intersect. trigger "out" event if necessary - if(this.containers[i].containerCache.over) { - this.containers[i]._trigger("out", event, this._uiHash(this)); - this.containers[i].containerCache.over = 0; - } - } - - } - - // if no intersecting containers found, return - if(!innermostContainer) { - return; - } - - // move the item into the container if it's not there already - if(this.containers.length === 1) { - if (!this.containers[innermostIndex].containerCache.over) { - this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); - this.containers[innermostIndex].containerCache.over = 1; - } - } else { - - //When entering a new container, we will find the item with the least distance and append our item near it - dist = 10000; - itemWithLeastDistance = null; - floating = innermostContainer.floating || this._isFloating(this.currentItem); - posProperty = floating ? "left" : "top"; - sizeProperty = floating ? "width" : "height"; - axis = floating ? "clientX" : "clientY"; - - for (j = this.items.length - 1; j >= 0; j--) { - if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) { - continue; - } - if(this.items[j].item[0] === this.currentItem[0]) { - continue; - } - - cur = this.items[j].item.offset()[posProperty]; - nearBottom = false; - if ( event[ axis ] - cur > this.items[ j ][ sizeProperty ] / 2 ) { - nearBottom = true; - } - - if ( Math.abs( event[ axis ] - cur ) < dist ) { - dist = Math.abs( event[ axis ] - cur ); - itemWithLeastDistance = this.items[ j ]; - this.direction = nearBottom ? "up": "down"; - } - } - - //Check if dropOnEmpty is enabled - if(!itemWithLeastDistance && !this.options.dropOnEmpty) { - return; - } - - if(this.currentContainer === this.containers[innermostIndex]) { - if ( !this.currentContainer.containerCache.over ) { - this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash() ); - this.currentContainer.containerCache.over = 1; - } - return; - } - - itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); - this._trigger("change", event, this._uiHash()); - this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); - this.currentContainer = this.containers[innermostIndex]; - - //Update the placeholder - this.options.placeholder.update(this.currentContainer, this.placeholder); - - this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); - this.containers[innermostIndex].containerCache.over = 1; - } - - - }, - - _createHelper: function(event) { - - var o = this.options, - helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper === "clone" ? this.currentItem.clone() : this.currentItem); - - //Add the helper to the DOM if that didn't happen already - if(!helper.parents("body").length) { - $(o.appendTo !== "parent" ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]); - } - - if(helper[0] === this.currentItem[0]) { - this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") }; - } - - if(!helper[0].style.width || o.forceHelperSize) { - helper.width(this.currentItem.width()); - } - if(!helper[0].style.height || o.forceHelperSize) { - helper.height(this.currentItem.height()); - } - - return helper; - - }, - - _adjustOffsetFromHelper: function(obj) { - if (typeof obj === "string") { - obj = obj.split(" "); - } - if ($.isArray(obj)) { - obj = {left: +obj[0], top: +obj[1] || 0}; - } - if ("left" in obj) { - this.offset.click.left = obj.left + this.margins.left; - } - if ("right" in obj) { - this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; - } - if ("top" in obj) { - this.offset.click.top = obj.top + this.margins.top; - } - if ("bottom" in obj) { - this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; - } - }, - - _getParentOffset: function() { - - - //Get the offsetParent and cache its position - this.offsetParent = this.helper.offsetParent(); - var po = this.offsetParent.offset(); - - // This is a special case where we need to modify a offset calculated on start, since the following happened: - // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent - // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that - // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag - if(this.cssPosition === "absolute" && this.scrollParent[0] !== this.document[0] && $.contains(this.scrollParent[0], this.offsetParent[0])) { - po.left += this.scrollParent.scrollLeft(); - po.top += this.scrollParent.scrollTop(); - } - - // This needs to be actually done for all browsers, since pageX/pageY includes this information - // with an ugly IE fix - if( this.offsetParent[0] === this.document[0].body || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) { - po = { top: 0, left: 0 }; - } - - return { - top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), - left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) - }; - - }, - - _getRelativeOffset: function() { - - if(this.cssPosition === "relative") { - var p = this.currentItem.position(); - return { - top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), - left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() - }; - } else { - return { top: 0, left: 0 }; - } - - }, - - _cacheMargins: function() { - this.margins = { - left: (parseInt(this.currentItem.css("marginLeft"),10) || 0), - top: (parseInt(this.currentItem.css("marginTop"),10) || 0) - }; - }, - - _cacheHelperProportions: function() { - this.helperProportions = { - width: this.helper.outerWidth(), - height: this.helper.outerHeight() - }; - }, - - _setContainment: function() { - - var ce, co, over, - o = this.options; - if(o.containment === "parent") { - o.containment = this.helper[0].parentNode; - } - if(o.containment === "document" || o.containment === "window") { - this.containment = [ - 0 - this.offset.relative.left - this.offset.parent.left, - 0 - this.offset.relative.top - this.offset.parent.top, - o.containment === "document" ? this.document.width() : this.window.width() - this.helperProportions.width - this.margins.left, - (o.containment === "document" ? this.document.width() : this.window.height() || this.document[0].body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top - ]; - } - - if(!(/^(document|window|parent)$/).test(o.containment)) { - ce = $(o.containment)[0]; - co = $(o.containment).offset(); - over = ($(ce).css("overflow") !== "hidden"); - - this.containment = [ - co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left, - co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top, - co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left, - co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top - ]; - } - - }, - - _convertPositionTo: function(d, pos) { - - if(!pos) { - pos = this.position; - } - var mod = d === "absolute" ? 1 : -1, - scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== this.document[0] && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, - scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); - - return { - top: ( - pos.top + // The absolute mouse position - this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent - this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border) - ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) - ), - left: ( - pos.left + // The absolute mouse position - this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent - this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border) - ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) - ) - }; - - }, - - _generatePosition: function(event) { - - var top, left, - o = this.options, - pageX = event.pageX, - pageY = event.pageY, - scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== this.document[0] && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); - - // This is another very weird special case that only happens for relative elements: - // 1. If the css position is relative - // 2. and the scroll parent is the document or similar to the offset parent - // we have to refresh the relative offset during the scroll so there are no jumps - if(this.cssPosition === "relative" && !(this.scrollParent[0] !== this.document[0] && this.scrollParent[0] !== this.offsetParent[0])) { - this.offset.relative = this._getRelativeOffset(); - } - - /* - * - Position constraining - - * Constrain the position to a mix of grid, containment. - */ - - if(this.originalPosition) { //If we are not dragging yet, we won't check for options - - if(this.containment) { - if(event.pageX - this.offset.click.left < this.containment[0]) { - pageX = this.containment[0] + this.offset.click.left; - } - if(event.pageY - this.offset.click.top < this.containment[1]) { - pageY = this.containment[1] + this.offset.click.top; - } - if(event.pageX - this.offset.click.left > this.containment[2]) { - pageX = this.containment[2] + this.offset.click.left; - } - if(event.pageY - this.offset.click.top > this.containment[3]) { - pageY = this.containment[3] + this.offset.click.top; - } - } - - if(o.grid) { - top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1]; - pageY = this.containment ? ( (top - this.offset.click.top >= this.containment[1] && top - this.offset.click.top <= this.containment[3]) ? top : ((top - this.offset.click.top >= this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top; - - left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0]; - pageX = this.containment ? ( (left - this.offset.click.left >= this.containment[0] && left - this.offset.click.left <= this.containment[2]) ? left : ((left - this.offset.click.left >= this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left; - } - - } - - return { - top: ( - pageY - // The absolute mouse position - this.offset.click.top - // Click offset (relative to the element) - this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent - this.offset.parent.top + // The offsetParent's offset without borders (offset + border) - ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) - ), - left: ( - pageX - // The absolute mouse position - this.offset.click.left - // Click offset (relative to the element) - this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent - this.offset.parent.left + // The offsetParent's offset without borders (offset + border) - ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) - ) - }; - - }, - - _rearrange: function(event, i, a, hardRefresh) { - - a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction === "down" ? i.item[0] : i.item[0].nextSibling)); - - //Various things done here to improve the performance: - // 1. we create a setTimeout, that calls refreshPositions - // 2. on the instance, we have a counter variable, that get's higher after every append - // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same - // 4. this lets only the last addition to the timeout stack through - this.counter = this.counter ? ++this.counter : 1; - var counter = this.counter; - - this._delay(function() { - if(counter === this.counter) { - this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove - } - }); - - }, - - _clear: function(event, noPropagation) { - - this.reverting = false; - // We delay all events that have to be triggered to after the point where the placeholder has been removed and - // everything else normalized again - var i, - delayedTriggers = []; - - // We first have to update the dom position of the actual currentItem - // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088) - if(!this._noFinalSort && this.currentItem.parent().length) { - this.placeholder.before(this.currentItem); - } - this._noFinalSort = null; - - if(this.helper[0] === this.currentItem[0]) { - for(i in this._storedCSS) { - if(this._storedCSS[i] === "auto" || this._storedCSS[i] === "static") { - this._storedCSS[i] = ""; - } - } - this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); - } else { - this.currentItem.show(); - } - - if(this.fromOutside && !noPropagation) { - delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); }); - } - if((this.fromOutside || this.domPosition.prev !== this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent !== this.currentItem.parent()[0]) && !noPropagation) { - delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed - } - - // Check if the items Container has Changed and trigger appropriate - // events. - if (this !== this.currentContainer) { - if(!noPropagation) { - delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); }); - delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.currentContainer)); - delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.currentContainer)); - } - } - - - //Post events to containers - function delayEvent( type, instance, container ) { - return function( event ) { - container._trigger( type, event, instance._uiHash( instance ) ); - }; - } - for (i = this.containers.length - 1; i >= 0; i--){ - if (!noPropagation) { - delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) ); - } - if(this.containers[i].containerCache.over) { - delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) ); - this.containers[i].containerCache.over = 0; - } - } - - //Do what was originally in plugins - if ( this.storedCursor ) { - this.document.find( "body" ).css( "cursor", this.storedCursor ); - this.storedStylesheet.remove(); - } - if(this._storedOpacity) { - this.helper.css("opacity", this._storedOpacity); - } - if(this._storedZIndex) { - this.helper.css("zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex); - } - - this.dragging = false; - - if(!noPropagation) { - this._trigger("beforeStop", event, this._uiHash()); - } - - //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! - this.placeholder[0].parentNode.removeChild(this.placeholder[0]); - - if ( !this.cancelHelperRemoval ) { - if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) { - this.helper.remove(); - } - this.helper = null; - } - - if(!noPropagation) { - for (i=0; i < delayedTriggers.length; i++) { - delayedTriggers[i].call(this, event); - } //Trigger all delayed events - this._trigger("stop", event, this._uiHash()); - } - - this.fromOutside = false; - return !this.cancelHelperRemoval; - - }, - - _trigger: function() { - if ($.Widget.prototype._trigger.apply(this, arguments) === false) { - this.cancel(); - } - }, - - _uiHash: function(_inst) { - var inst = _inst || this; - return { - helper: inst.helper, - placeholder: inst.placeholder || $([]), - position: inst.position, - originalPosition: inst.originalPosition, - offset: inst.positionAbs, - item: inst.currentItem, - sender: _inst ? _inst.element : null - }; - } - -}); - - -/*! - * jQuery UI Accordion 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/accordion/ - */ - - -var accordion = $.widget( "ui.accordion", { - version: "1.11.4", - options: { - active: 0, - animate: {}, - collapsible: false, - event: "click", - header: "> li > :first-child,> :not(li):even", - heightStyle: "auto", - icons: { - activeHeader: "ui-icon-triangle-1-s", - header: "ui-icon-triangle-1-e" - }, - - // callbacks - activate: null, - beforeActivate: null - }, - - hideProps: { - borderTopWidth: "hide", - borderBottomWidth: "hide", - paddingTop: "hide", - paddingBottom: "hide", - height: "hide" - }, - - showProps: { - borderTopWidth: "show", - borderBottomWidth: "show", - paddingTop: "show", - paddingBottom: "show", - height: "show" - }, - - _create: function() { - var options = this.options; - this.prevShow = this.prevHide = $(); - this.element.addClass( "ui-accordion ui-widget ui-helper-reset" ) - // ARIA - .attr( "role", "tablist" ); - - // don't allow collapsible: false and active: false / null - if ( !options.collapsible && (options.active === false || options.active == null) ) { - options.active = 0; - } - - this._processPanels(); - // handle negative values - if ( options.active < 0 ) { - options.active += this.headers.length; - } - this._refresh(); - }, - - _getCreateEventData: function() { - return { - header: this.active, - panel: !this.active.length ? $() : this.active.next() - }; - }, - - _createIcons: function() { - var icons = this.options.icons; - if ( icons ) { - $( "<span>" ) - .addClass( "ui-accordion-header-icon ui-icon " + icons.header ) - .prependTo( this.headers ); - this.active.children( ".ui-accordion-header-icon" ) - .removeClass( icons.header ) - .addClass( icons.activeHeader ); - this.headers.addClass( "ui-accordion-icons" ); - } - }, - - _destroyIcons: function() { - this.headers - .removeClass( "ui-accordion-icons" ) - .children( ".ui-accordion-header-icon" ) - .remove(); - }, - - _destroy: function() { - var contents; - - // clean up main element - this.element - .removeClass( "ui-accordion ui-widget ui-helper-reset" ) - .removeAttr( "role" ); - - // clean up headers - this.headers - .removeClass( "ui-accordion-header ui-accordion-header-active ui-state-default " + - "ui-corner-all ui-state-active ui-state-disabled ui-corner-top" ) - .removeAttr( "role" ) - .removeAttr( "aria-expanded" ) - .removeAttr( "aria-selected" ) - .removeAttr( "aria-controls" ) - .removeAttr( "tabIndex" ) - .removeUniqueId(); - - this._destroyIcons(); - - // clean up content panels - contents = this.headers.next() - .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom " + - "ui-accordion-content ui-accordion-content-active ui-state-disabled" ) - .css( "display", "" ) - .removeAttr( "role" ) - .removeAttr( "aria-hidden" ) - .removeAttr( "aria-labelledby" ) - .removeUniqueId(); - - if ( this.options.heightStyle !== "content" ) { - contents.css( "height", "" ); - } - }, - - _setOption: function( key, value ) { - if ( key === "active" ) { - // _activate() will handle invalid values and update this.options - this._activate( value ); - return; - } - - if ( key === "event" ) { - if ( this.options.event ) { - this._off( this.headers, this.options.event ); - } - this._setupEvents( value ); - } - - this._super( key, value ); - - // setting collapsible: false while collapsed; open first panel - if ( key === "collapsible" && !value && this.options.active === false ) { - this._activate( 0 ); - } - - if ( key === "icons" ) { - this._destroyIcons(); - if ( value ) { - this._createIcons(); - } - } - - // #5332 - opacity doesn't cascade to positioned elements in IE - // so we need to add the disabled class to the headers and panels - if ( key === "disabled" ) { - this.element - .toggleClass( "ui-state-disabled", !!value ) - .attr( "aria-disabled", value ); - this.headers.add( this.headers.next() ) - .toggleClass( "ui-state-disabled", !!value ); - } - }, - - _keydown: function( event ) { - if ( event.altKey || event.ctrlKey ) { - return; - } - - var keyCode = $.ui.keyCode, - length = this.headers.length, - currentIndex = this.headers.index( event.target ), - toFocus = false; - - switch ( event.keyCode ) { - case keyCode.RIGHT: - case keyCode.DOWN: - toFocus = this.headers[ ( currentIndex + 1 ) % length ]; - break; - case keyCode.LEFT: - case keyCode.UP: - toFocus = this.headers[ ( currentIndex - 1 + length ) % length ]; - break; - case keyCode.SPACE: - case keyCode.ENTER: - this._eventHandler( event ); - break; - case keyCode.HOME: - toFocus = this.headers[ 0 ]; - break; - case keyCode.END: - toFocus = this.headers[ length - 1 ]; - break; - } - - if ( toFocus ) { - $( event.target ).attr( "tabIndex", -1 ); - $( toFocus ).attr( "tabIndex", 0 ); - toFocus.focus(); - event.preventDefault(); - } - }, - - _panelKeyDown: function( event ) { - if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) { - $( event.currentTarget ).prev().focus(); - } - }, - - refresh: function() { - var options = this.options; - this._processPanels(); - - // was collapsed or no panel - if ( ( options.active === false && options.collapsible === true ) || !this.headers.length ) { - options.active = false; - this.active = $(); - // active false only when collapsible is true - } else if ( options.active === false ) { - this._activate( 0 ); - // was active, but active panel is gone - } else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { - // all remaining panel are disabled - if ( this.headers.length === this.headers.find(".ui-state-disabled").length ) { - options.active = false; - this.active = $(); - // activate previous panel - } else { - this._activate( Math.max( 0, options.active - 1 ) ); - } - // was active, active panel still exists - } else { - // make sure active index is correct - options.active = this.headers.index( this.active ); - } - - this._destroyIcons(); - - this._refresh(); - }, - - _processPanels: function() { - var prevHeaders = this.headers, - prevPanels = this.panels; - - this.headers = this.element.find( this.options.header ) - .addClass( "ui-accordion-header ui-state-default ui-corner-all" ); - - this.panels = this.headers.next() - .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" ) - .filter( ":not(.ui-accordion-content-active)" ) - .hide(); - - // Avoid memory leaks (#10056) - if ( prevPanels ) { - this._off( prevHeaders.not( this.headers ) ); - this._off( prevPanels.not( this.panels ) ); - } - }, - - _refresh: function() { - var maxHeight, - options = this.options, - heightStyle = options.heightStyle, - parent = this.element.parent(); - - this.active = this._findActive( options.active ) - .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" ) - .removeClass( "ui-corner-all" ); - this.active.next() - .addClass( "ui-accordion-content-active" ) - .show(); - - this.headers - .attr( "role", "tab" ) - .each(function() { - var header = $( this ), - headerId = header.uniqueId().attr( "id" ), - panel = header.next(), - panelId = panel.uniqueId().attr( "id" ); - header.attr( "aria-controls", panelId ); - panel.attr( "aria-labelledby", headerId ); - }) - .next() - .attr( "role", "tabpanel" ); - - this.headers - .not( this.active ) - .attr({ - "aria-selected": "false", - "aria-expanded": "false", - tabIndex: -1 - }) - .next() - .attr({ - "aria-hidden": "true" - }) - .hide(); - - // make sure at least one header is in the tab order - if ( !this.active.length ) { - this.headers.eq( 0 ).attr( "tabIndex", 0 ); - } else { - this.active.attr({ - "aria-selected": "true", - "aria-expanded": "true", - tabIndex: 0 - }) - .next() - .attr({ - "aria-hidden": "false" - }); - } - - this._createIcons(); - - this._setupEvents( options.event ); - - if ( heightStyle === "fill" ) { - maxHeight = parent.height(); - this.element.siblings( ":visible" ).each(function() { - var elem = $( this ), - position = elem.css( "position" ); - - if ( position === "absolute" || position === "fixed" ) { - return; - } - maxHeight -= elem.outerHeight( true ); - }); - - this.headers.each(function() { - maxHeight -= $( this ).outerHeight( true ); - }); - - this.headers.next() - .each(function() { - $( this ).height( Math.max( 0, maxHeight - - $( this ).innerHeight() + $( this ).height() ) ); - }) - .css( "overflow", "auto" ); - } else if ( heightStyle === "auto" ) { - maxHeight = 0; - this.headers.next() - .each(function() { - maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() ); - }) - .height( maxHeight ); - } - }, - - _activate: function( index ) { - var active = this._findActive( index )[ 0 ]; - - // trying to activate the already active panel - if ( active === this.active[ 0 ] ) { - return; - } - - // trying to collapse, simulate a click on the currently active header - active = active || this.active[ 0 ]; - - this._eventHandler({ - target: active, - currentTarget: active, - preventDefault: $.noop - }); - }, - - _findActive: function( selector ) { - return typeof selector === "number" ? this.headers.eq( selector ) : $(); - }, - - _setupEvents: function( event ) { - var events = { - keydown: "_keydown" - }; - if ( event ) { - $.each( event.split( " " ), function( index, eventName ) { - events[ eventName ] = "_eventHandler"; - }); - } - - this._off( this.headers.add( this.headers.next() ) ); - this._on( this.headers, events ); - this._on( this.headers.next(), { keydown: "_panelKeyDown" }); - this._hoverable( this.headers ); - this._focusable( this.headers ); - }, - - _eventHandler: function( event ) { - var options = this.options, - active = this.active, - clicked = $( event.currentTarget ), - clickedIsActive = clicked[ 0 ] === active[ 0 ], - collapsing = clickedIsActive && options.collapsible, - toShow = collapsing ? $() : clicked.next(), - toHide = active.next(), - eventData = { - oldHeader: active, - oldPanel: toHide, - newHeader: collapsing ? $() : clicked, - newPanel: toShow - }; - - event.preventDefault(); - - if ( - // click on active header, but not collapsible - ( clickedIsActive && !options.collapsible ) || - // allow canceling activation - ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { - return; - } - - options.active = collapsing ? false : this.headers.index( clicked ); - - // when the call to ._toggle() comes after the class changes - // it causes a very odd bug in IE 8 (see #6720) - this.active = clickedIsActive ? $() : clicked; - this._toggle( eventData ); - - // switch classes - // corner classes on the previously active header stay after the animation - active.removeClass( "ui-accordion-header-active ui-state-active" ); - if ( options.icons ) { - active.children( ".ui-accordion-header-icon" ) - .removeClass( options.icons.activeHeader ) - .addClass( options.icons.header ); - } - - if ( !clickedIsActive ) { - clicked - .removeClass( "ui-corner-all" ) - .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" ); - if ( options.icons ) { - clicked.children( ".ui-accordion-header-icon" ) - .removeClass( options.icons.header ) - .addClass( options.icons.activeHeader ); - } - - clicked - .next() - .addClass( "ui-accordion-content-active" ); - } - }, - - _toggle: function( data ) { - var toShow = data.newPanel, - toHide = this.prevShow.length ? this.prevShow : data.oldPanel; - - // handle activating a panel during the animation for another activation - this.prevShow.add( this.prevHide ).stop( true, true ); - this.prevShow = toShow; - this.prevHide = toHide; - - if ( this.options.animate ) { - this._animate( toShow, toHide, data ); - } else { - toHide.hide(); - toShow.show(); - this._toggleComplete( data ); - } - - toHide.attr({ - "aria-hidden": "true" - }); - toHide.prev().attr({ - "aria-selected": "false", - "aria-expanded": "false" - }); - // if we're switching panels, remove the old header from the tab order - // if we're opening from collapsed state, remove the previous header from the tab order - // if we're collapsing, then keep the collapsing header in the tab order - if ( toShow.length && toHide.length ) { - toHide.prev().attr({ - "tabIndex": -1, - "aria-expanded": "false" - }); - } else if ( toShow.length ) { - this.headers.filter(function() { - return parseInt( $( this ).attr( "tabIndex" ), 10 ) === 0; - }) - .attr( "tabIndex", -1 ); - } - - toShow - .attr( "aria-hidden", "false" ) - .prev() - .attr({ - "aria-selected": "true", - "aria-expanded": "true", - tabIndex: 0 - }); - }, - - _animate: function( toShow, toHide, data ) { - var total, easing, duration, - that = this, - adjust = 0, - boxSizing = toShow.css( "box-sizing" ), - down = toShow.length && - ( !toHide.length || ( toShow.index() < toHide.index() ) ), - animate = this.options.animate || {}, - options = down && animate.down || animate, - complete = function() { - that._toggleComplete( data ); - }; - - if ( typeof options === "number" ) { - duration = options; - } - if ( typeof options === "string" ) { - easing = options; - } - // fall back from options to animation in case of partial down settings - easing = easing || options.easing || animate.easing; - duration = duration || options.duration || animate.duration; - - if ( !toHide.length ) { - return toShow.animate( this.showProps, duration, easing, complete ); - } - if ( !toShow.length ) { - return toHide.animate( this.hideProps, duration, easing, complete ); - } - - total = toShow.show().outerHeight(); - toHide.animate( this.hideProps, { - duration: duration, - easing: easing, - step: function( now, fx ) { - fx.now = Math.round( now ); - } - }); - toShow - .hide() - .animate( this.showProps, { - duration: duration, - easing: easing, - complete: complete, - step: function( now, fx ) { - fx.now = Math.round( now ); - if ( fx.prop !== "height" ) { - if ( boxSizing === "content-box" ) { - adjust += fx.now; - } - } else if ( that.options.heightStyle !== "content" ) { - fx.now = Math.round( total - toHide.outerHeight() - adjust ); - adjust = 0; - } - } - }); - }, - - _toggleComplete: function( data ) { - var toHide = data.oldPanel; - - toHide - .removeClass( "ui-accordion-content-active" ) - .prev() - .removeClass( "ui-corner-top" ) - .addClass( "ui-corner-all" ); - - // Work around for rendering bug in IE (#5421) - if ( toHide.length ) { - toHide.parent()[ 0 ].className = toHide.parent()[ 0 ].className; - } - this._trigger( "activate", null, data ); - } -}); - - -/*! - * jQuery UI Menu 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/menu/ - */ - - -var menu = $.widget( "ui.menu", { - version: "1.11.4", - defaultElement: "<ul>", - delay: 300, - options: { - icons: { - submenu: "ui-icon-carat-1-e" - }, - items: "> *", - menus: "ul", - position: { - my: "left-1 top", - at: "right top" - }, - role: "menu", - - // callbacks - blur: null, - focus: null, - select: null - }, - - _create: function() { - this.activeMenu = this.element; - - // Flag used to prevent firing of the click handler - // as the event bubbles up through nested menus - this.mouseHandled = false; - this.element - .uniqueId() - .addClass( "ui-menu ui-widget ui-widget-content" ) - .toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length ) - .attr({ - role: this.options.role, - tabIndex: 0 - }); - - if ( this.options.disabled ) { - this.element - .addClass( "ui-state-disabled" ) - .attr( "aria-disabled", "true" ); - } - - this._on({ - // Prevent focus from sticking to links inside menu after clicking - // them (focus should always stay on UL during navigation). - "mousedown .ui-menu-item": function( event ) { - event.preventDefault(); - }, - "click .ui-menu-item": function( event ) { - var target = $( event.target ); - if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) { - this.select( event ); - - // Only set the mouseHandled flag if the event will bubble, see #9469. - if ( !event.isPropagationStopped() ) { - this.mouseHandled = true; - } - - // Open submenu on click - if ( target.has( ".ui-menu" ).length ) { - this.expand( event ); - } else if ( !this.element.is( ":focus" ) && $( this.document[ 0 ].activeElement ).closest( ".ui-menu" ).length ) { - - // Redirect focus to the menu - this.element.trigger( "focus", [ true ] ); - - // If the active item is on the top level, let it stay active. - // Otherwise, blur the active item since it is no longer visible. - if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) { - clearTimeout( this.timer ); - } - } - } - }, - "mouseenter .ui-menu-item": function( event ) { - // Ignore mouse events while typeahead is active, see #10458. - // Prevents focusing the wrong item when typeahead causes a scroll while the mouse - // is over an item in the menu - if ( this.previousFilter ) { - return; - } - var target = $( event.currentTarget ); - // Remove ui-state-active class from siblings of the newly focused menu item - // to avoid a jump caused by adjacent elements both having a class with a border - target.siblings( ".ui-state-active" ).removeClass( "ui-state-active" ); - this.focus( event, target ); - }, - mouseleave: "collapseAll", - "mouseleave .ui-menu": "collapseAll", - focus: function( event, keepActiveItem ) { - // If there's already an active item, keep it active - // If not, activate the first item - var item = this.active || this.element.find( this.options.items ).eq( 0 ); - - if ( !keepActiveItem ) { - this.focus( event, item ); - } - }, - blur: function( event ) { - this._delay(function() { - if ( !$.contains( this.element[0], this.document[0].activeElement ) ) { - this.collapseAll( event ); - } - }); - }, - keydown: "_keydown" - }); - - this.refresh(); - - // Clicks outside of a menu collapse any open menus - this._on( this.document, { - click: function( event ) { - if ( this._closeOnDocumentClick( event ) ) { - this.collapseAll( event ); - } - - // Reset the mouseHandled flag - this.mouseHandled = false; - } - }); - }, - - _destroy: function() { - // Destroy (sub)menus - this.element - .removeAttr( "aria-activedescendant" ) - .find( ".ui-menu" ).addBack() - .removeClass( "ui-menu ui-widget ui-widget-content ui-menu-icons ui-front" ) - .removeAttr( "role" ) - .removeAttr( "tabIndex" ) - .removeAttr( "aria-labelledby" ) - .removeAttr( "aria-expanded" ) - .removeAttr( "aria-hidden" ) - .removeAttr( "aria-disabled" ) - .removeUniqueId() - .show(); - - // Destroy menu items - this.element.find( ".ui-menu-item" ) - .removeClass( "ui-menu-item" ) - .removeAttr( "role" ) - .removeAttr( "aria-disabled" ) - .removeUniqueId() - .removeClass( "ui-state-hover" ) - .removeAttr( "tabIndex" ) - .removeAttr( "role" ) - .removeAttr( "aria-haspopup" ) - .children().each( function() { - var elem = $( this ); - if ( elem.data( "ui-menu-submenu-carat" ) ) { - elem.remove(); - } - }); - - // Destroy menu dividers - this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" ); - }, - - _keydown: function( event ) { - var match, prev, character, skip, - preventDefault = true; - - switch ( event.keyCode ) { - case $.ui.keyCode.PAGE_UP: - this.previousPage( event ); - break; - case $.ui.keyCode.PAGE_DOWN: - this.nextPage( event ); - break; - case $.ui.keyCode.HOME: - this._move( "first", "first", event ); - break; - case $.ui.keyCode.END: - this._move( "last", "last", event ); - break; - case $.ui.keyCode.UP: - this.previous( event ); - break; - case $.ui.keyCode.DOWN: - this.next( event ); - break; - case $.ui.keyCode.LEFT: - this.collapse( event ); - break; - case $.ui.keyCode.RIGHT: - if ( this.active && !this.active.is( ".ui-state-disabled" ) ) { - this.expand( event ); - } - break; - case $.ui.keyCode.ENTER: - case $.ui.keyCode.SPACE: - this._activate( event ); - break; - case $.ui.keyCode.ESCAPE: - this.collapse( event ); - break; - default: - preventDefault = false; - prev = this.previousFilter || ""; - character = String.fromCharCode( event.keyCode ); - skip = false; - - clearTimeout( this.filterTimer ); - - if ( character === prev ) { - skip = true; - } else { - character = prev + character; - } - - match = this._filterMenuItems( character ); - match = skip && match.index( this.active.next() ) !== -1 ? - this.active.nextAll( ".ui-menu-item" ) : - match; - - // If no matches on the current filter, reset to the last character pressed - // to move down the menu to the first item that starts with that character - if ( !match.length ) { - character = String.fromCharCode( event.keyCode ); - match = this._filterMenuItems( character ); - } - - if ( match.length ) { - this.focus( event, match ); - this.previousFilter = character; - this.filterTimer = this._delay(function() { - delete this.previousFilter; - }, 1000 ); - } else { - delete this.previousFilter; - } - } - - if ( preventDefault ) { - event.preventDefault(); - } - }, - - _activate: function( event ) { - if ( !this.active.is( ".ui-state-disabled" ) ) { - if ( this.active.is( "[aria-haspopup='true']" ) ) { - this.expand( event ); - } else { - this.select( event ); - } - } - }, - - refresh: function() { - var menus, items, - that = this, - icon = this.options.icons.submenu, - submenus = this.element.find( this.options.menus ); - - this.element.toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length ); - - // Initialize nested menus - submenus.filter( ":not(.ui-menu)" ) - .addClass( "ui-menu ui-widget ui-widget-content ui-front" ) - .hide() - .attr({ - role: this.options.role, - "aria-hidden": "true", - "aria-expanded": "false" - }) - .each(function() { - var menu = $( this ), - item = menu.parent(), - submenuCarat = $( "<span>" ) - .addClass( "ui-menu-icon ui-icon " + icon ) - .data( "ui-menu-submenu-carat", true ); - - item - .attr( "aria-haspopup", "true" ) - .prepend( submenuCarat ); - menu.attr( "aria-labelledby", item.attr( "id" ) ); - }); - - menus = submenus.add( this.element ); - items = menus.find( this.options.items ); - - // Initialize menu-items containing spaces and/or dashes only as dividers - items.not( ".ui-menu-item" ).each(function() { - var item = $( this ); - if ( that._isDivider( item ) ) { - item.addClass( "ui-widget-content ui-menu-divider" ); - } - }); - - // Don't refresh list items that are already adapted - items.not( ".ui-menu-item, .ui-menu-divider" ) - .addClass( "ui-menu-item" ) - .uniqueId() - .attr({ - tabIndex: -1, - role: this._itemRole() - }); - - // Add aria-disabled attribute to any disabled menu item - items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" ); - - // If the active item has been removed, blur the menu - if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { - this.blur(); - } - }, - - _itemRole: function() { - return { - menu: "menuitem", - listbox: "option" - }[ this.options.role ]; - }, - - _setOption: function( key, value ) { - if ( key === "icons" ) { - this.element.find( ".ui-menu-icon" ) - .removeClass( this.options.icons.submenu ) - .addClass( value.submenu ); - } - if ( key === "disabled" ) { - this.element - .toggleClass( "ui-state-disabled", !!value ) - .attr( "aria-disabled", value ); - } - this._super( key, value ); - }, - - focus: function( event, item ) { - var nested, focused; - this.blur( event, event && event.type === "focus" ); - - this._scrollIntoView( item ); - - this.active = item.first(); - focused = this.active.addClass( "ui-state-focus" ).removeClass( "ui-state-active" ); - // Only update aria-activedescendant if there's a role - // otherwise we assume focus is managed elsewhere - if ( this.options.role ) { - this.element.attr( "aria-activedescendant", focused.attr( "id" ) ); - } - - // Highlight active parent menu item, if any - this.active - .parent() - .closest( ".ui-menu-item" ) - .addClass( "ui-state-active" ); - - if ( event && event.type === "keydown" ) { - this._close(); - } else { - this.timer = this._delay(function() { - this._close(); - }, this.delay ); - } - - nested = item.children( ".ui-menu" ); - if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) { - this._startOpening(nested); - } - this.activeMenu = item.parent(); - - this._trigger( "focus", event, { item: item } ); - }, - - _scrollIntoView: function( item ) { - var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight; - if ( this._hasScroll() ) { - borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0; - paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0; - offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop; - scroll = this.activeMenu.scrollTop(); - elementHeight = this.activeMenu.height(); - itemHeight = item.outerHeight(); - - if ( offset < 0 ) { - this.activeMenu.scrollTop( scroll + offset ); - } else if ( offset + itemHeight > elementHeight ) { - this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight ); - } - } - }, - - blur: function( event, fromFocus ) { - if ( !fromFocus ) { - clearTimeout( this.timer ); - } - - if ( !this.active ) { - return; - } - - this.active.removeClass( "ui-state-focus" ); - this.active = null; - - this._trigger( "blur", event, { item: this.active } ); - }, - - _startOpening: function( submenu ) { - clearTimeout( this.timer ); - - // Don't open if already open fixes a Firefox bug that caused a .5 pixel - // shift in the submenu position when mousing over the carat icon - if ( submenu.attr( "aria-hidden" ) !== "true" ) { - return; - } - - this.timer = this._delay(function() { - this._close(); - this._open( submenu ); - }, this.delay ); - }, - - _open: function( submenu ) { - var position = $.extend({ - of: this.active - }, this.options.position ); - - clearTimeout( this.timer ); - this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) ) - .hide() - .attr( "aria-hidden", "true" ); - - submenu - .show() - .removeAttr( "aria-hidden" ) - .attr( "aria-expanded", "true" ) - .position( position ); - }, - - collapseAll: function( event, all ) { - clearTimeout( this.timer ); - this.timer = this._delay(function() { - // If we were passed an event, look for the submenu that contains the event - var currentMenu = all ? this.element : - $( event && event.target ).closest( this.element.find( ".ui-menu" ) ); - - // If we found no valid submenu ancestor, use the main menu to close all sub menus anyway - if ( !currentMenu.length ) { - currentMenu = this.element; - } - - this._close( currentMenu ); - - this.blur( event ); - this.activeMenu = currentMenu; - }, this.delay ); - }, - - // With no arguments, closes the currently active menu - if nothing is active - // it closes all menus. If passed an argument, it will search for menus BELOW - _close: function( startMenu ) { - if ( !startMenu ) { - startMenu = this.active ? this.active.parent() : this.element; - } - - startMenu - .find( ".ui-menu" ) - .hide() - .attr( "aria-hidden", "true" ) - .attr( "aria-expanded", "false" ) - .end() - .find( ".ui-state-active" ).not( ".ui-state-focus" ) - .removeClass( "ui-state-active" ); - }, - - _closeOnDocumentClick: function( event ) { - return !$( event.target ).closest( ".ui-menu" ).length; - }, - - _isDivider: function( item ) { - - // Match hyphen, em dash, en dash - return !/[^\-\u2014\u2013\s]/.test( item.text() ); - }, - - collapse: function( event ) { - var newItem = this.active && - this.active.parent().closest( ".ui-menu-item", this.element ); - if ( newItem && newItem.length ) { - this._close(); - this.focus( event, newItem ); - } - }, - - expand: function( event ) { - var newItem = this.active && - this.active - .children( ".ui-menu " ) - .find( this.options.items ) - .first(); - - if ( newItem && newItem.length ) { - this._open( newItem.parent() ); - - // Delay so Firefox will not hide activedescendant change in expanding submenu from AT - this._delay(function() { - this.focus( event, newItem ); - }); - } - }, - - next: function( event ) { - this._move( "next", "first", event ); - }, - - previous: function( event ) { - this._move( "prev", "last", event ); - }, - - isFirstItem: function() { - return this.active && !this.active.prevAll( ".ui-menu-item" ).length; - }, - - isLastItem: function() { - return this.active && !this.active.nextAll( ".ui-menu-item" ).length; - }, - - _move: function( direction, filter, event ) { - var next; - if ( this.active ) { - if ( direction === "first" || direction === "last" ) { - next = this.active - [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" ) - .eq( -1 ); - } else { - next = this.active - [ direction + "All" ]( ".ui-menu-item" ) - .eq( 0 ); - } - } - if ( !next || !next.length || !this.active ) { - next = this.activeMenu.find( this.options.items )[ filter ](); - } - - this.focus( event, next ); - }, - - nextPage: function( event ) { - var item, base, height; - - if ( !this.active ) { - this.next( event ); - return; - } - if ( this.isLastItem() ) { - return; - } - if ( this._hasScroll() ) { - base = this.active.offset().top; - height = this.element.height(); - this.active.nextAll( ".ui-menu-item" ).each(function() { - item = $( this ); - return item.offset().top - base - height < 0; - }); - - this.focus( event, item ); - } else { - this.focus( event, this.activeMenu.find( this.options.items ) - [ !this.active ? "first" : "last" ]() ); - } - }, - - previousPage: function( event ) { - var item, base, height; - if ( !this.active ) { - this.next( event ); - return; - } - if ( this.isFirstItem() ) { - return; - } - if ( this._hasScroll() ) { - base = this.active.offset().top; - height = this.element.height(); - this.active.prevAll( ".ui-menu-item" ).each(function() { - item = $( this ); - return item.offset().top - base + height > 0; - }); - - this.focus( event, item ); - } else { - this.focus( event, this.activeMenu.find( this.options.items ).first() ); - } - }, - - _hasScroll: function() { - return this.element.outerHeight() < this.element.prop( "scrollHeight" ); - }, - - select: function( event ) { - // TODO: It should never be possible to not have an active item at this - // point, but the tests don't trigger mouseenter before click. - this.active = this.active || $( event.target ).closest( ".ui-menu-item" ); - var ui = { item: this.active }; - if ( !this.active.has( ".ui-menu" ).length ) { - this.collapseAll( event, true ); - } - this._trigger( "select", event, ui ); - }, - - _filterMenuItems: function(character) { - var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ), - regex = new RegExp( "^" + escapedCharacter, "i" ); - - return this.activeMenu - .find( this.options.items ) - - // Only match on items, not dividers or other content (#10571) - .filter( ".ui-menu-item" ) - .filter(function() { - return regex.test( $.trim( $( this ).text() ) ); - }); - } -}); - - -/*! - * jQuery UI Autocomplete 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/autocomplete/ - */ - - -$.widget( "ui.autocomplete", { - version: "1.11.4", - defaultElement: "<input>", - options: { - appendTo: null, - autoFocus: false, - delay: 300, - minLength: 1, - position: { - my: "left top", - at: "left bottom", - collision: "none" - }, - source: null, - - // callbacks - change: null, - close: null, - focus: null, - open: null, - response: null, - search: null, - select: null - }, - - requestIndex: 0, - pending: 0, - - _create: function() { - // Some browsers only repeat keydown events, not keypress events, - // so we use the suppressKeyPress flag to determine if we've already - // handled the keydown event. #7269 - // Unfortunately the code for & in keypress is the same as the up arrow, - // so we use the suppressKeyPressRepeat flag to avoid handling keypress - // events when we know the keydown event was used to modify the - // search term. #7799 - var suppressKeyPress, suppressKeyPressRepeat, suppressInput, - nodeName = this.element[ 0 ].nodeName.toLowerCase(), - isTextarea = nodeName === "textarea", - isInput = nodeName === "input"; - - this.isMultiLine = - // Textareas are always multi-line - isTextarea ? true : - // Inputs are always single-line, even if inside a contentEditable element - // IE also treats inputs as contentEditable - isInput ? false : - // All other element types are determined by whether or not they're contentEditable - this.element.prop( "isContentEditable" ); - - this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ]; - this.isNewMenu = true; - - this.element - .addClass( "ui-autocomplete-input" ) - .attr( "autocomplete", "off" ); - - this._on( this.element, { - keydown: function( event ) { - if ( this.element.prop( "readOnly" ) ) { - suppressKeyPress = true; - suppressInput = true; - suppressKeyPressRepeat = true; - return; - } - - suppressKeyPress = false; - suppressInput = false; - suppressKeyPressRepeat = false; - var keyCode = $.ui.keyCode; - switch ( event.keyCode ) { - case keyCode.PAGE_UP: - suppressKeyPress = true; - this._move( "previousPage", event ); - break; - case keyCode.PAGE_DOWN: - suppressKeyPress = true; - this._move( "nextPage", event ); - break; - case keyCode.UP: - suppressKeyPress = true; - this._keyEvent( "previous", event ); - break; - case keyCode.DOWN: - suppressKeyPress = true; - this._keyEvent( "next", event ); - break; - case keyCode.ENTER: - // when menu is open and has focus - if ( this.menu.active ) { - // #6055 - Opera still allows the keypress to occur - // which causes forms to submit - suppressKeyPress = true; - event.preventDefault(); - this.menu.select( event ); - } - break; - case keyCode.TAB: - if ( this.menu.active ) { - this.menu.select( event ); - } - break; - case keyCode.ESCAPE: - if ( this.menu.element.is( ":visible" ) ) { - if ( !this.isMultiLine ) { - this._value( this.term ); - } - this.close( event ); - // Different browsers have different default behavior for escape - // Single press can mean undo or clear - // Double press in IE means clear the whole form - event.preventDefault(); - } - break; - default: - suppressKeyPressRepeat = true; - // search timeout should be triggered before the input value is changed - this._searchTimeout( event ); - break; - } - }, - keypress: function( event ) { - if ( suppressKeyPress ) { - suppressKeyPress = false; - if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) { - event.preventDefault(); - } - return; - } - if ( suppressKeyPressRepeat ) { - return; - } - - // replicate some key handlers to allow them to repeat in Firefox and Opera - var keyCode = $.ui.keyCode; - switch ( event.keyCode ) { - case keyCode.PAGE_UP: - this._move( "previousPage", event ); - break; - case keyCode.PAGE_DOWN: - this._move( "nextPage", event ); - break; - case keyCode.UP: - this._keyEvent( "previous", event ); - break; - case keyCode.DOWN: - this._keyEvent( "next", event ); - break; - } - }, - input: function( event ) { - if ( suppressInput ) { - suppressInput = false; - event.preventDefault(); - return; - } - this._searchTimeout( event ); - }, - focus: function() { - this.selectedItem = null; - this.previous = this._value(); - }, - blur: function( event ) { - if ( this.cancelBlur ) { - delete this.cancelBlur; - return; - } - - clearTimeout( this.searching ); - this.close( event ); - this._change( event ); - } - }); - - this._initSource(); - this.menu = $( "<ul>" ) - .addClass( "ui-autocomplete ui-front" ) - .appendTo( this._appendTo() ) - .menu({ - // disable ARIA support, the live region takes care of that - role: null - }) - .hide() - .menu( "instance" ); - - this._on( this.menu.element, { - mousedown: function( event ) { - // prevent moving focus out of the text field - event.preventDefault(); - - // IE doesn't prevent moving focus even with event.preventDefault() - // so we set a flag to know when we should ignore the blur event - this.cancelBlur = true; - this._delay(function() { - delete this.cancelBlur; - }); - - // clicking on the scrollbar causes focus to shift to the body - // but we can't detect a mouseup or a click immediately afterward - // so we have to track the next mousedown and close the menu if - // the user clicks somewhere outside of the autocomplete - var menuElement = this.menu.element[ 0 ]; - if ( !$( event.target ).closest( ".ui-menu-item" ).length ) { - this._delay(function() { - var that = this; - this.document.one( "mousedown", function( event ) { - if ( event.target !== that.element[ 0 ] && - event.target !== menuElement && - !$.contains( menuElement, event.target ) ) { - that.close(); - } - }); - }); - } - }, - menufocus: function( event, ui ) { - var label, item; - // support: Firefox - // Prevent accidental activation of menu items in Firefox (#7024 #9118) - if ( this.isNewMenu ) { - this.isNewMenu = false; - if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) { - this.menu.blur(); - - this.document.one( "mousemove", function() { - $( event.target ).trigger( event.originalEvent ); - }); - - return; - } - } - - item = ui.item.data( "ui-autocomplete-item" ); - if ( false !== this._trigger( "focus", event, { item: item } ) ) { - // use value to match what will end up in the input, if it was a key event - if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) { - this._value( item.value ); - } - } - - // Announce the value in the liveRegion - label = ui.item.attr( "aria-label" ) || item.value; - if ( label && $.trim( label ).length ) { - this.liveRegion.children().hide(); - $( "<div>" ).text( label ).appendTo( this.liveRegion ); - } - }, - menuselect: function( event, ui ) { - var item = ui.item.data( "ui-autocomplete-item" ), - previous = this.previous; - - // only trigger when focus was lost (click on menu) - if ( this.element[ 0 ] !== this.document[ 0 ].activeElement ) { - this.element.focus(); - this.previous = previous; - // #6109 - IE triggers two focus events and the second - // is asynchronous, so we need to reset the previous - // term synchronously and asynchronously :-( - this._delay(function() { - this.previous = previous; - this.selectedItem = item; - }); - } - - if ( false !== this._trigger( "select", event, { item: item } ) ) { - this._value( item.value ); - } - // reset the term after the select event - // this allows custom select handling to work properly - this.term = this._value(); - - this.close( event ); - this.selectedItem = item; - } - }); - - this.liveRegion = $( "<span>", { - role: "status", - "aria-live": "assertive", - "aria-relevant": "additions" - }) - .addClass( "ui-helper-hidden-accessible" ) - .appendTo( this.document[ 0 ].body ); - - // turning off autocomplete prevents the browser from remembering the - // value when navigating through history, so we re-enable autocomplete - // if the page is unloaded before the widget is destroyed. #7790 - this._on( this.window, { - beforeunload: function() { - this.element.removeAttr( "autocomplete" ); - } - }); - }, - - _destroy: function() { - clearTimeout( this.searching ); - this.element - .removeClass( "ui-autocomplete-input" ) - .removeAttr( "autocomplete" ); - this.menu.element.remove(); - this.liveRegion.remove(); - }, - - _setOption: function( key, value ) { - this._super( key, value ); - if ( key === "source" ) { - this._initSource(); - } - if ( key === "appendTo" ) { - this.menu.element.appendTo( this._appendTo() ); - } - if ( key === "disabled" && value && this.xhr ) { - this.xhr.abort(); - } - }, - - _appendTo: function() { - var element = this.options.appendTo; - - if ( element ) { - element = element.jquery || element.nodeType ? - $( element ) : - this.document.find( element ).eq( 0 ); - } - - if ( !element || !element[ 0 ] ) { - element = this.element.closest( ".ui-front" ); - } - - if ( !element.length ) { - element = this.document[ 0 ].body; - } - - return element; - }, - - _initSource: function() { - var array, url, - that = this; - if ( $.isArray( this.options.source ) ) { - array = this.options.source; - this.source = function( request, response ) { - response( $.ui.autocomplete.filter( array, request.term ) ); - }; - } else if ( typeof this.options.source === "string" ) { - url = this.options.source; - this.source = function( request, response ) { - if ( that.xhr ) { - that.xhr.abort(); - } - that.xhr = $.ajax({ - url: url, - data: request, - dataType: "json", - success: function( data ) { - response( data ); - }, - error: function() { - response([]); - } - }); - }; - } else { - this.source = this.options.source; - } - }, - - _searchTimeout: function( event ) { - clearTimeout( this.searching ); - this.searching = this._delay(function() { - - // Search if the value has changed, or if the user retypes the same value (see #7434) - var equalValues = this.term === this._value(), - menuVisible = this.menu.element.is( ":visible" ), - modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey; - - if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) { - this.selectedItem = null; - this.search( null, event ); - } - }, this.options.delay ); - }, - - search: function( value, event ) { - value = value != null ? value : this._value(); - - // always save the actual value, not the one passed as an argument - this.term = this._value(); - - if ( value.length < this.options.minLength ) { - return this.close( event ); - } - - if ( this._trigger( "search", event ) === false ) { - return; - } - - return this._search( value ); - }, - - _search: function( value ) { - this.pending++; - this.element.addClass( "ui-autocomplete-loading" ); - this.cancelSearch = false; - - this.source( { term: value }, this._response() ); - }, - - _response: function() { - var index = ++this.requestIndex; - - return $.proxy(function( content ) { - if ( index === this.requestIndex ) { - this.__response( content ); - } - - this.pending--; - if ( !this.pending ) { - this.element.removeClass( "ui-autocomplete-loading" ); - } - }, this ); - }, - - __response: function( content ) { - if ( content ) { - content = this._normalize( content ); - } - this._trigger( "response", null, { content: content } ); - if ( !this.options.disabled && content && content.length && !this.cancelSearch ) { - this._suggest( content ); - this._trigger( "open" ); - } else { - // use ._close() instead of .close() so we don't cancel future searches - this._close(); - } - }, - - close: function( event ) { - this.cancelSearch = true; - this._close( event ); - }, - - _close: function( event ) { - if ( this.menu.element.is( ":visible" ) ) { - this.menu.element.hide(); - this.menu.blur(); - this.isNewMenu = true; - this._trigger( "close", event ); - } - }, - - _change: function( event ) { - if ( this.previous !== this._value() ) { - this._trigger( "change", event, { item: this.selectedItem } ); - } - }, - - _normalize: function( items ) { - // assume all items have the right format when the first item is complete - if ( items.length && items[ 0 ].label && items[ 0 ].value ) { - return items; - } - return $.map( items, function( item ) { - if ( typeof item === "string" ) { - return { - label: item, - value: item - }; - } - return $.extend( {}, item, { - label: item.label || item.value, - value: item.value || item.label - }); - }); - }, - - _suggest: function( items ) { - var ul = this.menu.element.empty(); - this._renderMenu( ul, items ); - this.isNewMenu = true; - this.menu.refresh(); - - // size and position menu - ul.show(); - this._resizeMenu(); - ul.position( $.extend({ - of: this.element - }, this.options.position ) ); - - if ( this.options.autoFocus ) { - this.menu.next(); - } - }, - - _resizeMenu: function() { - var ul = this.menu.element; - ul.outerWidth( Math.max( - // Firefox wraps long text (possibly a rounding bug) - // so we add 1px to avoid the wrapping (#7513) - ul.width( "" ).outerWidth() + 1, - this.element.outerWidth() - ) ); - }, - - _renderMenu: function( ul, items ) { - var that = this; - $.each( items, function( index, item ) { - that._renderItemData( ul, item ); - }); - }, - - _renderItemData: function( ul, item ) { - return this._renderItem( ul, item ).data( "ui-autocomplete-item", item ); - }, - - _renderItem: function( ul, item ) { - return $( "<li>" ).text( item.label ).appendTo( ul ); - }, - - _move: function( direction, event ) { - if ( !this.menu.element.is( ":visible" ) ) { - this.search( null, event ); - return; - } - if ( this.menu.isFirstItem() && /^previous/.test( direction ) || - this.menu.isLastItem() && /^next/.test( direction ) ) { - - if ( !this.isMultiLine ) { - this._value( this.term ); - } - - this.menu.blur(); - return; - } - this.menu[ direction ]( event ); - }, - - widget: function() { - return this.menu.element; - }, - - _value: function() { - return this.valueMethod.apply( this.element, arguments ); - }, - - _keyEvent: function( keyEvent, event ) { - if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) { - this._move( keyEvent, event ); - - // prevents moving cursor to beginning/end of the text field in some browsers - event.preventDefault(); - } - } -}); - -$.extend( $.ui.autocomplete, { - escapeRegex: function( value ) { - return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ); - }, - filter: function( array, term ) { - var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" ); - return $.grep( array, function( value ) { - return matcher.test( value.label || value.value || value ); - }); - } -}); - -// live region extension, adding a `messages` option -// NOTE: This is an experimental API. We are still investigating -// a full solution for string manipulation and internationalization. -$.widget( "ui.autocomplete", $.ui.autocomplete, { - options: { - messages: { - noResults: "No search results.", - results: function( amount ) { - return amount + ( amount > 1 ? " results are" : " result is" ) + - " available, use up and down arrow keys to navigate."; - } - } - }, - - __response: function( content ) { - var message; - this._superApply( arguments ); - if ( this.options.disabled || this.cancelSearch ) { - return; - } - if ( content && content.length ) { - message = this.options.messages.results( content.length ); - } else { - message = this.options.messages.noResults; - } - this.liveRegion.children().hide(); - $( "<div>" ).text( message ).appendTo( this.liveRegion ); - } -}); - -var autocomplete = $.ui.autocomplete; - - -/*! - * jQuery UI Button 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/button/ - */ - - -var lastActive, - baseClasses = "ui-button ui-widget ui-state-default ui-corner-all", - typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only", - formResetHandler = function() { - var form = $( this ); - setTimeout(function() { - form.find( ":ui-button" ).button( "refresh" ); - }, 1 ); - }, - radioGroup = function( radio ) { - var name = radio.name, - form = radio.form, - radios = $( [] ); - if ( name ) { - name = name.replace( /'/g, "\\'" ); - if ( form ) { - radios = $( form ).find( "[name='" + name + "'][type=radio]" ); - } else { - radios = $( "[name='" + name + "'][type=radio]", radio.ownerDocument ) - .filter(function() { - return !this.form; - }); - } - } - return radios; - }; - -$.widget( "ui.button", { - version: "1.11.4", - defaultElement: "<button>", - options: { - disabled: null, - text: true, - label: null, - icons: { - primary: null, - secondary: null - } - }, - _create: function() { - this.element.closest( "form" ) - .unbind( "reset" + this.eventNamespace ) - .bind( "reset" + this.eventNamespace, formResetHandler ); - - if ( typeof this.options.disabled !== "boolean" ) { - this.options.disabled = !!this.element.prop( "disabled" ); - } else { - this.element.prop( "disabled", this.options.disabled ); - } - - this._determineButtonType(); - this.hasTitle = !!this.buttonElement.attr( "title" ); - - var that = this, - options = this.options, - toggleButton = this.type === "checkbox" || this.type === "radio", - activeClass = !toggleButton ? "ui-state-active" : ""; - - if ( options.label === null ) { - options.label = (this.type === "input" ? this.buttonElement.val() : this.buttonElement.html()); - } - - this._hoverable( this.buttonElement ); - - this.buttonElement - .addClass( baseClasses ) - .attr( "role", "button" ) - .bind( "mouseenter" + this.eventNamespace, function() { - if ( options.disabled ) { - return; - } - if ( this === lastActive ) { - $( this ).addClass( "ui-state-active" ); - } - }) - .bind( "mouseleave" + this.eventNamespace, function() { - if ( options.disabled ) { - return; - } - $( this ).removeClass( activeClass ); - }) - .bind( "click" + this.eventNamespace, function( event ) { - if ( options.disabled ) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }); - - // Can't use _focusable() because the element that receives focus - // and the element that gets the ui-state-focus class are different - this._on({ - focus: function() { - this.buttonElement.addClass( "ui-state-focus" ); - }, - blur: function() { - this.buttonElement.removeClass( "ui-state-focus" ); - } - }); - - if ( toggleButton ) { - this.element.bind( "change" + this.eventNamespace, function() { - that.refresh(); - }); - } - - if ( this.type === "checkbox" ) { - this.buttonElement.bind( "click" + this.eventNamespace, function() { - if ( options.disabled ) { - return false; - } - }); - } else if ( this.type === "radio" ) { - this.buttonElement.bind( "click" + this.eventNamespace, function() { - if ( options.disabled ) { - return false; - } - $( this ).addClass( "ui-state-active" ); - that.buttonElement.attr( "aria-pressed", "true" ); - - var radio = that.element[ 0 ]; - radioGroup( radio ) - .not( radio ) - .map(function() { - return $( this ).button( "widget" )[ 0 ]; - }) - .removeClass( "ui-state-active" ) - .attr( "aria-pressed", "false" ); - }); - } else { - this.buttonElement - .bind( "mousedown" + this.eventNamespace, function() { - if ( options.disabled ) { - return false; - } - $( this ).addClass( "ui-state-active" ); - lastActive = this; - that.document.one( "mouseup", function() { - lastActive = null; - }); - }) - .bind( "mouseup" + this.eventNamespace, function() { - if ( options.disabled ) { - return false; - } - $( this ).removeClass( "ui-state-active" ); - }) - .bind( "keydown" + this.eventNamespace, function(event) { - if ( options.disabled ) { - return false; - } - if ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) { - $( this ).addClass( "ui-state-active" ); - } - }) - // see #8559, we bind to blur here in case the button element loses - // focus between keydown and keyup, it would be left in an "active" state - .bind( "keyup" + this.eventNamespace + " blur" + this.eventNamespace, function() { - $( this ).removeClass( "ui-state-active" ); - }); - - if ( this.buttonElement.is("a") ) { - this.buttonElement.keyup(function(event) { - if ( event.keyCode === $.ui.keyCode.SPACE ) { - // TODO pass through original event correctly (just as 2nd argument doesn't work) - $( this ).click(); - } - }); - } - } - - this._setOption( "disabled", options.disabled ); - this._resetButton(); - }, - - _determineButtonType: function() { - var ancestor, labelSelector, checked; - - if ( this.element.is("[type=checkbox]") ) { - this.type = "checkbox"; - } else if ( this.element.is("[type=radio]") ) { - this.type = "radio"; - } else if ( this.element.is("input") ) { - this.type = "input"; - } else { - this.type = "button"; - } - - if ( this.type === "checkbox" || this.type === "radio" ) { - // we don't search against the document in case the element - // is disconnected from the DOM - ancestor = this.element.parents().last(); - labelSelector = "label[for='" + this.element.attr("id") + "']"; - this.buttonElement = ancestor.find( labelSelector ); - if ( !this.buttonElement.length ) { - ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings(); - this.buttonElement = ancestor.filter( labelSelector ); - if ( !this.buttonElement.length ) { - this.buttonElement = ancestor.find( labelSelector ); - } - } - this.element.addClass( "ui-helper-hidden-accessible" ); - - checked = this.element.is( ":checked" ); - if ( checked ) { - this.buttonElement.addClass( "ui-state-active" ); - } - this.buttonElement.prop( "aria-pressed", checked ); - } else { - this.buttonElement = this.element; - } - }, - - widget: function() { - return this.buttonElement; - }, - - _destroy: function() { - this.element - .removeClass( "ui-helper-hidden-accessible" ); - this.buttonElement - .removeClass( baseClasses + " ui-state-active " + typeClasses ) - .removeAttr( "role" ) - .removeAttr( "aria-pressed" ) - .html( this.buttonElement.find(".ui-button-text").html() ); - - if ( !this.hasTitle ) { - this.buttonElement.removeAttr( "title" ); - } - }, - - _setOption: function( key, value ) { - this._super( key, value ); - if ( key === "disabled" ) { - this.widget().toggleClass( "ui-state-disabled", !!value ); - this.element.prop( "disabled", !!value ); - if ( value ) { - if ( this.type === "checkbox" || this.type === "radio" ) { - this.buttonElement.removeClass( "ui-state-focus" ); - } else { - this.buttonElement.removeClass( "ui-state-focus ui-state-active" ); - } - } - return; - } - this._resetButton(); - }, - - refresh: function() { - //See #8237 & #8828 - var isDisabled = this.element.is( "input, button" ) ? this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" ); - - if ( isDisabled !== this.options.disabled ) { - this._setOption( "disabled", isDisabled ); - } - if ( this.type === "radio" ) { - radioGroup( this.element[0] ).each(function() { - if ( $( this ).is( ":checked" ) ) { - $( this ).button( "widget" ) - .addClass( "ui-state-active" ) - .attr( "aria-pressed", "true" ); - } else { - $( this ).button( "widget" ) - .removeClass( "ui-state-active" ) - .attr( "aria-pressed", "false" ); - } - }); - } else if ( this.type === "checkbox" ) { - if ( this.element.is( ":checked" ) ) { - this.buttonElement - .addClass( "ui-state-active" ) - .attr( "aria-pressed", "true" ); - } else { - this.buttonElement - .removeClass( "ui-state-active" ) - .attr( "aria-pressed", "false" ); - } - } - }, - - _resetButton: function() { - if ( this.type === "input" ) { - if ( this.options.label ) { - this.element.val( this.options.label ); - } - return; - } - var buttonElement = this.buttonElement.removeClass( typeClasses ), - buttonText = $( "<span></span>", this.document[0] ) - .addClass( "ui-button-text" ) - .html( this.options.label ) - .appendTo( buttonElement.empty() ) - .text(), - icons = this.options.icons, - multipleIcons = icons.primary && icons.secondary, - buttonClasses = []; - - if ( icons.primary || icons.secondary ) { - if ( this.options.text ) { - buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) ); - } - - if ( icons.primary ) { - buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" ); - } - - if ( icons.secondary ) { - buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" ); - } - - if ( !this.options.text ) { - buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" ); - - if ( !this.hasTitle ) { - buttonElement.attr( "title", $.trim( buttonText ) ); - } - } - } else { - buttonClasses.push( "ui-button-text-only" ); - } - buttonElement.addClass( buttonClasses.join( " " ) ); - } -}); - -$.widget( "ui.buttonset", { - version: "1.11.4", - options: { - items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)" - }, - - _create: function() { - this.element.addClass( "ui-buttonset" ); - }, - - _init: function() { - this.refresh(); - }, - - _setOption: function( key, value ) { - if ( key === "disabled" ) { - this.buttons.button( "option", key, value ); - } - - this._super( key, value ); - }, - - refresh: function() { - var rtl = this.element.css( "direction" ) === "rtl", - allButtons = this.element.find( this.options.items ), - existingButtons = allButtons.filter( ":ui-button" ); - - // Initialize new buttons - allButtons.not( ":ui-button" ).button(); - - // Refresh existing buttons - existingButtons.button( "refresh" ); - - this.buttons = allButtons - .map(function() { - return $( this ).button( "widget" )[ 0 ]; - }) - .removeClass( "ui-corner-all ui-corner-left ui-corner-right" ) - .filter( ":first" ) - .addClass( rtl ? "ui-corner-right" : "ui-corner-left" ) - .end() - .filter( ":last" ) - .addClass( rtl ? "ui-corner-left" : "ui-corner-right" ) - .end() - .end(); - }, - - _destroy: function() { - this.element.removeClass( "ui-buttonset" ); - this.buttons - .map(function() { - return $( this ).button( "widget" )[ 0 ]; - }) - .removeClass( "ui-corner-left ui-corner-right" ) - .end() - .button( "destroy" ); - } -}); - -var button = $.ui.button; - - -/*! - * jQuery UI Datepicker 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/datepicker/ - */ - - -$.extend($.ui, { datepicker: { version: "1.11.4" } }); - -var datepicker_instActive; - -function datepicker_getZindex( elem ) { - var position, value; - while ( elem.length && elem[ 0 ] !== document ) { - // Ignore z-index if position is set to a value where z-index is ignored by the browser - // This makes behavior of this function consistent across browsers - // WebKit always returns auto if the element is positioned - position = elem.css( "position" ); - if ( position === "absolute" || position === "relative" || position === "fixed" ) { - // IE returns 0 when zIndex is not specified - // other browsers return a string - // we ignore the case of nested elements with an explicit value of 0 - // <div style="z-index: -10;"><div style="z-index: 0;"></div></div> - value = parseInt( elem.css( "zIndex" ), 10 ); - if ( !isNaN( value ) && value !== 0 ) { - return value; - } - } - elem = elem.parent(); - } - - return 0; -} -/* Date picker manager. - Use the singleton instance of this class, $.datepicker, to interact with the date picker. - Settings for (groups of) date pickers are maintained in an instance object, - allowing multiple different settings on the same page. */ - -function Datepicker() { - this._curInst = null; // The current instance in use - this._keyEvent = false; // If the last event was a key event - this._disabledInputs = []; // List of date picker inputs that have been disabled - this._datepickerShowing = false; // True if the popup picker is showing , false if not - this._inDialog = false; // True if showing within a "dialog", false if not - this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division - this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class - this._appendClass = "ui-datepicker-append"; // The name of the append marker class - this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class - this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class - this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class - this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class - this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class - this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class - this.regional = []; // Available regional settings, indexed by language code - this.regional[""] = { // Default regional settings - closeText: "Done", // Display text for close link - prevText: "Prev", // Display text for previous month link - nextText: "Next", // Display text for next month link - currentText: "Today", // Display text for current month link - monthNames: ["January","February","March","April","May","June", - "July","August","September","October","November","December"], // Names of months for drop-down and formatting - monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // For formatting - dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], // For formatting - dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], // For formatting - dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], // Column headings for days starting at Sunday - weekHeader: "Wk", // Column header for week of the year - dateFormat: "mm/dd/yy", // See format options on parseDate - firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ... - isRTL: false, // True if right-to-left language, false if left-to-right - showMonthAfterYear: false, // True if the year select precedes month, false for month then year - yearSuffix: "" // Additional text to append to the year in the month headers - }; - this._defaults = { // Global defaults for all the date picker instances - showOn: "focus", // "focus" for popup on focus, - // "button" for trigger button, or "both" for either - showAnim: "fadeIn", // Name of jQuery animation for popup - showOptions: {}, // Options for enhanced animations - defaultDate: null, // Used when field is blank: actual date, - // +/-number for offset from today, null for today - appendText: "", // Display text following the input box, e.g. showing the format - buttonText: "...", // Text for trigger button - buttonImage: "", // URL for trigger button image - buttonImageOnly: false, // True if the image appears alone, false if it appears on a button - hideIfNoPrevNext: false, // True to hide next/previous month links - // if not applicable, false to just disable them - navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links - gotoCurrent: false, // True if today link goes back to current selection instead - changeMonth: false, // True if month can be selected directly, false if only prev/next - changeYear: false, // True if year can be selected directly, false if only prev/next - yearRange: "c-10:c+10", // Range of years to display in drop-down, - // either relative to today's year (-nn:+nn), relative to currently displayed year - // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n) - showOtherMonths: false, // True to show dates in other months, false to leave blank - selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable - showWeek: false, // True to show week of the year, false to not show it - calculateWeek: this.iso8601Week, // How to calculate the week of the year, - // takes a Date and returns the number of the week for it - shortYearCutoff: "+10", // Short year values < this are in the current century, - // > this are in the previous century, - // string value starting with "+" for current year + value - minDate: null, // The earliest selectable date, or null for no limit - maxDate: null, // The latest selectable date, or null for no limit - duration: "fast", // Duration of display/closure - beforeShowDay: null, // Function that takes a date and returns an array with - // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "", - // [2] = cell title (optional), e.g. $.datepicker.noWeekends - beforeShow: null, // Function that takes an input field and - // returns a set of custom settings for the date picker - onSelect: null, // Define a callback function when a date is selected - onChangeMonthYear: null, // Define a callback function when the month or year is changed - onClose: null, // Define a callback function when the datepicker is closed - numberOfMonths: 1, // Number of months to show at a time - showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0) - stepMonths: 1, // Number of months to step back/forward - stepBigMonths: 12, // Number of months to step back/forward for the big links - altField: "", // Selector for an alternate field to store selected dates into - altFormat: "", // The date format to use for the alternate field - constrainInput: true, // The input is constrained by the current date format - showButtonPanel: false, // True to show button panel, false to not show it - autoSize: false, // True to size the input for the date format, false to leave as is - disabled: false // The initial disabled state - }; - $.extend(this._defaults, this.regional[""]); - this.regional.en = $.extend( true, {}, this.regional[ "" ]); - this.regional[ "en-US" ] = $.extend( true, {}, this.regional.en ); - this.dpDiv = datepicker_bindHover($("<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")); -} - -$.extend(Datepicker.prototype, { - /* Class name added to elements to indicate already configured with a date picker. */ - markerClassName: "hasDatepicker", - - //Keep track of the maximum number of rows displayed (see #7043) - maxRows: 4, - - // TODO rename to "widget" when switching to widget factory - _widgetDatepicker: function() { - return this.dpDiv; - }, - - /* Override the default settings for all instances of the date picker. - * @param settings object - the new settings to use as defaults (anonymous object) - * @return the manager object - */ - setDefaults: function(settings) { - datepicker_extendRemove(this._defaults, settings || {}); - return this; - }, - - /* Attach the date picker to a jQuery selection. - * @param target element - the target input field or division or span - * @param settings object - the new settings to use for this date picker instance (anonymous) - */ - _attachDatepicker: function(target, settings) { - var nodeName, inline, inst; - nodeName = target.nodeName.toLowerCase(); - inline = (nodeName === "div" || nodeName === "span"); - if (!target.id) { - this.uuid += 1; - target.id = "dp" + this.uuid; - } - inst = this._newInst($(target), inline); - inst.settings = $.extend({}, settings || {}); - if (nodeName === "input") { - this._connectDatepicker(target, inst); - } else if (inline) { - this._inlineDatepicker(target, inst); - } - }, - - /* Create a new instance object. */ - _newInst: function(target, inline) { - var id = target[0].id.replace(/([^A-Za-z0-9_\-])/g, "\\\\$1"); // escape jQuery meta chars - return {id: id, input: target, // associated target - selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection - drawMonth: 0, drawYear: 0, // month being drawn - inline: inline, // is datepicker inline or not - dpDiv: (!inline ? this.dpDiv : // presentation div - datepicker_bindHover($("<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")))}; - }, - - /* Attach the date picker to an input field. */ - _connectDatepicker: function(target, inst) { - var input = $(target); - inst.append = $([]); - inst.trigger = $([]); - if (input.hasClass(this.markerClassName)) { - return; - } - this._attachments(input, inst); - input.addClass(this.markerClassName).keydown(this._doKeyDown). - keypress(this._doKeyPress).keyup(this._doKeyUp); - this._autoSize(inst); - $.data(target, "datepicker", inst); - //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665) - if( inst.settings.disabled ) { - this._disableDatepicker( target ); - } - }, - - /* Make attachments based on settings. */ - _attachments: function(input, inst) { - var showOn, buttonText, buttonImage, - appendText = this._get(inst, "appendText"), - isRTL = this._get(inst, "isRTL"); - - if (inst.append) { - inst.append.remove(); - } - if (appendText) { - inst.append = $("<span class='" + this._appendClass + "'>" + appendText + "</span>"); - input[isRTL ? "before" : "after"](inst.append); - } - - input.unbind("focus", this._showDatepicker); - - if (inst.trigger) { - inst.trigger.remove(); - } - - showOn = this._get(inst, "showOn"); - if (showOn === "focus" || showOn === "both") { // pop-up date picker when in the marked field - input.focus(this._showDatepicker); - } - if (showOn === "button" || showOn === "both") { // pop-up date picker when button clicked - buttonText = this._get(inst, "buttonText"); - buttonImage = this._get(inst, "buttonImage"); - inst.trigger = $(this._get(inst, "buttonImageOnly") ? - $("<img/>").addClass(this._triggerClass). - attr({ src: buttonImage, alt: buttonText, title: buttonText }) : - $("<button type='button'></button>").addClass(this._triggerClass). - html(!buttonImage ? buttonText : $("<img/>").attr( - { src:buttonImage, alt:buttonText, title:buttonText }))); - input[isRTL ? "before" : "after"](inst.trigger); - inst.trigger.click(function() { - if ($.datepicker._datepickerShowing && $.datepicker._lastInput === input[0]) { - $.datepicker._hideDatepicker(); - } else if ($.datepicker._datepickerShowing && $.datepicker._lastInput !== input[0]) { - $.datepicker._hideDatepicker(); - $.datepicker._showDatepicker(input[0]); - } else { - $.datepicker._showDatepicker(input[0]); - } - return false; - }); - } - }, - - /* Apply the maximum length for the date format. */ - _autoSize: function(inst) { - if (this._get(inst, "autoSize") && !inst.inline) { - var findMax, max, maxI, i, - date = new Date(2009, 12 - 1, 20), // Ensure double digits - dateFormat = this._get(inst, "dateFormat"); - - if (dateFormat.match(/[DM]/)) { - findMax = function(names) { - max = 0; - maxI = 0; - for (i = 0; i < names.length; i++) { - if (names[i].length > max) { - max = names[i].length; - maxI = i; - } - } - return maxI; - }; - date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ? - "monthNames" : "monthNamesShort")))); - date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ? - "dayNames" : "dayNamesShort"))) + 20 - date.getDay()); - } - inst.input.attr("size", this._formatDate(inst, date).length); - } - }, - - /* Attach an inline date picker to a div. */ - _inlineDatepicker: function(target, inst) { - var divSpan = $(target); - if (divSpan.hasClass(this.markerClassName)) { - return; - } - divSpan.addClass(this.markerClassName).append(inst.dpDiv); - $.data(target, "datepicker", inst); - this._setDate(inst, this._getDefaultDate(inst), true); - this._updateDatepicker(inst); - this._updateAlternate(inst); - //If disabled option is true, disable the datepicker before showing it (see ticket #5665) - if( inst.settings.disabled ) { - this._disableDatepicker( target ); - } - // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements - // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height - inst.dpDiv.css( "display", "block" ); - }, - - /* Pop-up the date picker in a "dialog" box. - * @param input element - ignored - * @param date string or Date - the initial date to display - * @param onSelect function - the function to call when a date is selected - * @param settings object - update the dialog date picker instance's settings (anonymous object) - * @param pos int[2] - coordinates for the dialog's position within the screen or - * event - with x/y coordinates or - * leave empty for default (screen centre) - * @return the manager object - */ - _dialogDatepicker: function(input, date, onSelect, settings, pos) { - var id, browserWidth, browserHeight, scrollX, scrollY, - inst = this._dialogInst; // internal instance - - if (!inst) { - this.uuid += 1; - id = "dp" + this.uuid; - this._dialogInput = $("<input type='text' id='" + id + - "' style='position: absolute; top: -100px; width: 0px;'/>"); - this._dialogInput.keydown(this._doKeyDown); - $("body").append(this._dialogInput); - inst = this._dialogInst = this._newInst(this._dialogInput, false); - inst.settings = {}; - $.data(this._dialogInput[0], "datepicker", inst); - } - datepicker_extendRemove(inst.settings, settings || {}); - date = (date && date.constructor === Date ? this._formatDate(inst, date) : date); - this._dialogInput.val(date); - - this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null); - if (!this._pos) { - browserWidth = document.documentElement.clientWidth; - browserHeight = document.documentElement.clientHeight; - scrollX = document.documentElement.scrollLeft || document.body.scrollLeft; - scrollY = document.documentElement.scrollTop || document.body.scrollTop; - this._pos = // should use actual width/height below - [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY]; - } - - // move input on screen for focus, but hidden behind dialog - this._dialogInput.css("left", (this._pos[0] + 20) + "px").css("top", this._pos[1] + "px"); - inst.settings.onSelect = onSelect; - this._inDialog = true; - this.dpDiv.addClass(this._dialogClass); - this._showDatepicker(this._dialogInput[0]); - if ($.blockUI) { - $.blockUI(this.dpDiv); - } - $.data(this._dialogInput[0], "datepicker", inst); - return this; - }, - - /* Detach a datepicker from its control. - * @param target element - the target input field or division or span - */ - _destroyDatepicker: function(target) { - var nodeName, - $target = $(target), - inst = $.data(target, "datepicker"); - - if (!$target.hasClass(this.markerClassName)) { - return; - } - - nodeName = target.nodeName.toLowerCase(); - $.removeData(target, "datepicker"); - if (nodeName === "input") { - inst.append.remove(); - inst.trigger.remove(); - $target.removeClass(this.markerClassName). - unbind("focus", this._showDatepicker). - unbind("keydown", this._doKeyDown). - unbind("keypress", this._doKeyPress). - unbind("keyup", this._doKeyUp); - } else if (nodeName === "div" || nodeName === "span") { - $target.removeClass(this.markerClassName).empty(); - } - - if ( datepicker_instActive === inst ) { - datepicker_instActive = null; - } - }, - - /* Enable the date picker to a jQuery selection. - * @param target element - the target input field or division or span - */ - _enableDatepicker: function(target) { - var nodeName, inline, - $target = $(target), - inst = $.data(target, "datepicker"); - - if (!$target.hasClass(this.markerClassName)) { - return; - } - - nodeName = target.nodeName.toLowerCase(); - if (nodeName === "input") { - target.disabled = false; - inst.trigger.filter("button"). - each(function() { this.disabled = false; }).end(). - filter("img").css({opacity: "1.0", cursor: ""}); - } else if (nodeName === "div" || nodeName === "span") { - inline = $target.children("." + this._inlineClass); - inline.children().removeClass("ui-state-disabled"); - inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). - prop("disabled", false); - } - this._disabledInputs = $.map(this._disabledInputs, - function(value) { return (value === target ? null : value); }); // delete entry - }, - - /* Disable the date picker to a jQuery selection. - * @param target element - the target input field or division or span - */ - _disableDatepicker: function(target) { - var nodeName, inline, - $target = $(target), - inst = $.data(target, "datepicker"); - - if (!$target.hasClass(this.markerClassName)) { - return; - } - - nodeName = target.nodeName.toLowerCase(); - if (nodeName === "input") { - target.disabled = true; - inst.trigger.filter("button"). - each(function() { this.disabled = true; }).end(). - filter("img").css({opacity: "0.5", cursor: "default"}); - } else if (nodeName === "div" || nodeName === "span") { - inline = $target.children("." + this._inlineClass); - inline.children().addClass("ui-state-disabled"); - inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). - prop("disabled", true); - } - this._disabledInputs = $.map(this._disabledInputs, - function(value) { return (value === target ? null : value); }); // delete entry - this._disabledInputs[this._disabledInputs.length] = target; - }, - - /* Is the first field in a jQuery collection disabled as a datepicker? - * @param target element - the target input field or division or span - * @return boolean - true if disabled, false if enabled - */ - _isDisabledDatepicker: function(target) { - if (!target) { - return false; - } - for (var i = 0; i < this._disabledInputs.length; i++) { - if (this._disabledInputs[i] === target) { - return true; - } - } - return false; - }, - - /* Retrieve the instance data for the target control. - * @param target element - the target input field or division or span - * @return object - the associated instance data - * @throws error if a jQuery problem getting data - */ - _getInst: function(target) { - try { - return $.data(target, "datepicker"); - } - catch (err) { - throw "Missing instance data for this datepicker"; - } - }, - - /* Update or retrieve the settings for a date picker attached to an input field or division. - * @param target element - the target input field or division or span - * @param name object - the new settings to update or - * string - the name of the setting to change or retrieve, - * when retrieving also "all" for all instance settings or - * "defaults" for all global defaults - * @param value any - the new value for the setting - * (omit if above is an object or to retrieve a value) - */ - _optionDatepicker: function(target, name, value) { - var settings, date, minDate, maxDate, - inst = this._getInst(target); - - if (arguments.length === 2 && typeof name === "string") { - return (name === "defaults" ? $.extend({}, $.datepicker._defaults) : - (inst ? (name === "all" ? $.extend({}, inst.settings) : - this._get(inst, name)) : null)); - } - - settings = name || {}; - if (typeof name === "string") { - settings = {}; - settings[name] = value; - } - - if (inst) { - if (this._curInst === inst) { - this._hideDatepicker(); - } - - date = this._getDateDatepicker(target, true); - minDate = this._getMinMaxDate(inst, "min"); - maxDate = this._getMinMaxDate(inst, "max"); - datepicker_extendRemove(inst.settings, settings); - // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided - if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) { - inst.settings.minDate = this._formatDate(inst, minDate); - } - if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) { - inst.settings.maxDate = this._formatDate(inst, maxDate); - } - if ( "disabled" in settings ) { - if ( settings.disabled ) { - this._disableDatepicker(target); - } else { - this._enableDatepicker(target); - } - } - this._attachments($(target), inst); - this._autoSize(inst); - this._setDate(inst, date); - this._updateAlternate(inst); - this._updateDatepicker(inst); - } - }, - - // change method deprecated - _changeDatepicker: function(target, name, value) { - this._optionDatepicker(target, name, value); - }, - - /* Redraw the date picker attached to an input field or division. - * @param target element - the target input field or division or span - */ - _refreshDatepicker: function(target) { - var inst = this._getInst(target); - if (inst) { - this._updateDatepicker(inst); - } - }, - - /* Set the dates for a jQuery selection. - * @param target element - the target input field or division or span - * @param date Date - the new date - */ - _setDateDatepicker: function(target, date) { - var inst = this._getInst(target); - if (inst) { - this._setDate(inst, date); - this._updateDatepicker(inst); - this._updateAlternate(inst); - } - }, - - /* Get the date(s) for the first entry in a jQuery selection. - * @param target element - the target input field or division or span - * @param noDefault boolean - true if no default date is to be used - * @return Date - the current date - */ - _getDateDatepicker: function(target, noDefault) { - var inst = this._getInst(target); - if (inst && !inst.inline) { - this._setDateFromField(inst, noDefault); - } - return (inst ? this._getDate(inst) : null); - }, - - /* Handle keystrokes. */ - _doKeyDown: function(event) { - var onSelect, dateStr, sel, - inst = $.datepicker._getInst(event.target), - handled = true, - isRTL = inst.dpDiv.is(".ui-datepicker-rtl"); - - inst._keyEvent = true; - if ($.datepicker._datepickerShowing) { - switch (event.keyCode) { - case 9: $.datepicker._hideDatepicker(); - handled = false; - break; // hide on tab out - case 13: sel = $("td." + $.datepicker._dayOverClass + ":not(." + - $.datepicker._currentClass + ")", inst.dpDiv); - if (sel[0]) { - $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]); - } - - onSelect = $.datepicker._get(inst, "onSelect"); - if (onSelect) { - dateStr = $.datepicker._formatDate(inst); - - // trigger custom callback - onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); - } else { - $.datepicker._hideDatepicker(); - } - - return false; // don't submit the form - case 27: $.datepicker._hideDatepicker(); - break; // hide on escape - case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ? - -$.datepicker._get(inst, "stepBigMonths") : - -$.datepicker._get(inst, "stepMonths")), "M"); - break; // previous month/year on page up/+ ctrl - case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ? - +$.datepicker._get(inst, "stepBigMonths") : - +$.datepicker._get(inst, "stepMonths")), "M"); - break; // next month/year on page down/+ ctrl - case 35: if (event.ctrlKey || event.metaKey) { - $.datepicker._clearDate(event.target); - } - handled = event.ctrlKey || event.metaKey; - break; // clear on ctrl or command +end - case 36: if (event.ctrlKey || event.metaKey) { - $.datepicker._gotoToday(event.target); - } - handled = event.ctrlKey || event.metaKey; - break; // current on ctrl or command +home - case 37: if (event.ctrlKey || event.metaKey) { - $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), "D"); - } - handled = event.ctrlKey || event.metaKey; - // -1 day on ctrl or command +left - if (event.originalEvent.altKey) { - $.datepicker._adjustDate(event.target, (event.ctrlKey ? - -$.datepicker._get(inst, "stepBigMonths") : - -$.datepicker._get(inst, "stepMonths")), "M"); - } - // next month/year on alt +left on Mac - break; - case 38: if (event.ctrlKey || event.metaKey) { - $.datepicker._adjustDate(event.target, -7, "D"); - } - handled = event.ctrlKey || event.metaKey; - break; // -1 week on ctrl or command +up - case 39: if (event.ctrlKey || event.metaKey) { - $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), "D"); - } - handled = event.ctrlKey || event.metaKey; - // +1 day on ctrl or command +right - if (event.originalEvent.altKey) { - $.datepicker._adjustDate(event.target, (event.ctrlKey ? - +$.datepicker._get(inst, "stepBigMonths") : - +$.datepicker._get(inst, "stepMonths")), "M"); - } - // next month/year on alt +right - break; - case 40: if (event.ctrlKey || event.metaKey) { - $.datepicker._adjustDate(event.target, +7, "D"); - } - handled = event.ctrlKey || event.metaKey; - break; // +1 week on ctrl or command +down - default: handled = false; - } - } else if (event.keyCode === 36 && event.ctrlKey) { // display the date picker on ctrl+home - $.datepicker._showDatepicker(this); - } else { - handled = false; - } - - if (handled) { - event.preventDefault(); - event.stopPropagation(); - } - }, - - /* Filter entered characters - based on date format. */ - _doKeyPress: function(event) { - var chars, chr, - inst = $.datepicker._getInst(event.target); - - if ($.datepicker._get(inst, "constrainInput")) { - chars = $.datepicker._possibleChars($.datepicker._get(inst, "dateFormat")); - chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode); - return event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1); - } - }, - - /* Synchronise manual entry and field/alternate field. */ - _doKeyUp: function(event) { - var date, - inst = $.datepicker._getInst(event.target); - - if (inst.input.val() !== inst.lastVal) { - try { - date = $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"), - (inst.input ? inst.input.val() : null), - $.datepicker._getFormatConfig(inst)); - - if (date) { // only if valid - $.datepicker._setDateFromField(inst); - $.datepicker._updateAlternate(inst); - $.datepicker._updateDatepicker(inst); - } - } - catch (err) { - } - } - return true; - }, - - /* Pop-up the date picker for a given input field. - * If false returned from beforeShow event handler do not show. - * @param input element - the input field attached to the date picker or - * event - if triggered by focus - */ - _showDatepicker: function(input) { - input = input.target || input; - if (input.nodeName.toLowerCase() !== "input") { // find from button/image trigger - input = $("input", input.parentNode)[0]; - } - - if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput === input) { // already here - return; - } - - var inst, beforeShow, beforeShowSettings, isFixed, - offset, showAnim, duration; - - inst = $.datepicker._getInst(input); - if ($.datepicker._curInst && $.datepicker._curInst !== inst) { - $.datepicker._curInst.dpDiv.stop(true, true); - if ( inst && $.datepicker._datepickerShowing ) { - $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] ); - } - } - - beforeShow = $.datepicker._get(inst, "beforeShow"); - beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {}; - if(beforeShowSettings === false){ - return; - } - datepicker_extendRemove(inst.settings, beforeShowSettings); - - inst.lastVal = null; - $.datepicker._lastInput = input; - $.datepicker._setDateFromField(inst); - - if ($.datepicker._inDialog) { // hide cursor - input.value = ""; - } - if (!$.datepicker._pos) { // position below input - $.datepicker._pos = $.datepicker._findPos(input); - $.datepicker._pos[1] += input.offsetHeight; // add the height - } - - isFixed = false; - $(input).parents().each(function() { - isFixed |= $(this).css("position") === "fixed"; - return !isFixed; - }); - - offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]}; - $.datepicker._pos = null; - //to avoid flashes on Firefox - inst.dpDiv.empty(); - // determine sizing offscreen - inst.dpDiv.css({position: "absolute", display: "block", top: "-1000px"}); - $.datepicker._updateDatepicker(inst); - // fix width for dynamic number of date pickers - // and adjust position before showing - offset = $.datepicker._checkOffset(inst, offset, isFixed); - inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ? - "static" : (isFixed ? "fixed" : "absolute")), display: "none", - left: offset.left + "px", top: offset.top + "px"}); - - if (!inst.inline) { - showAnim = $.datepicker._get(inst, "showAnim"); - duration = $.datepicker._get(inst, "duration"); - inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 ); - $.datepicker._datepickerShowing = true; - - if ( $.effects && $.effects.effect[ showAnim ] ) { - inst.dpDiv.show(showAnim, $.datepicker._get(inst, "showOptions"), duration); - } else { - inst.dpDiv[showAnim || "show"](showAnim ? duration : null); - } - - if ( $.datepicker._shouldFocusInput( inst ) ) { - inst.input.focus(); - } - - $.datepicker._curInst = inst; - } - }, - - /* Generate the date picker content. */ - _updateDatepicker: function(inst) { - this.maxRows = 4; //Reset the max number of rows being displayed (see #7043) - datepicker_instActive = inst; // for delegate hover events - inst.dpDiv.empty().append(this._generateHTML(inst)); - this._attachHandlers(inst); - - var origyearshtml, - numMonths = this._getNumberOfMonths(inst), - cols = numMonths[1], - width = 17, - activeCell = inst.dpDiv.find( "." + this._dayOverClass + " a" ); - - if ( activeCell.length > 0 ) { - datepicker_handleMouseover.apply( activeCell.get( 0 ) ); - } - - inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""); - if (cols > 1) { - inst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", (width * cols) + "em"); - } - inst.dpDiv[(numMonths[0] !== 1 || numMonths[1] !== 1 ? "add" : "remove") + - "Class"]("ui-datepicker-multi"); - inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") + - "Class"]("ui-datepicker-rtl"); - - if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) { - inst.input.focus(); - } - - // deffered render of the years select (to avoid flashes on Firefox) - if( inst.yearshtml ){ - origyearshtml = inst.yearshtml; - setTimeout(function(){ - //assure that inst.yearshtml didn't change. - if( origyearshtml === inst.yearshtml && inst.yearshtml ){ - inst.dpDiv.find("select.ui-datepicker-year:first").replaceWith(inst.yearshtml); - } - origyearshtml = inst.yearshtml = null; - }, 0); - } - }, - - // #6694 - don't focus the input if it's already focused - // this breaks the change event in IE - // Support: IE and jQuery <1.9 - _shouldFocusInput: function( inst ) { - return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" ); - }, - - /* Check positioning to remain on screen. */ - _checkOffset: function(inst, offset, isFixed) { - var dpWidth = inst.dpDiv.outerWidth(), - dpHeight = inst.dpDiv.outerHeight(), - inputWidth = inst.input ? inst.input.outerWidth() : 0, - inputHeight = inst.input ? inst.input.outerHeight() : 0, - viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()), - viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop()); - - offset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0); - offset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0; - offset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0; - - // now check if datepicker is showing outside window viewport - move to a better place if so. - offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ? - Math.abs(offset.left + dpWidth - viewWidth) : 0); - offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ? - Math.abs(dpHeight + inputHeight) : 0); - - return offset; - }, - - /* Find an object's position on the screen. */ - _findPos: function(obj) { - var position, - inst = this._getInst(obj), - isRTL = this._get(inst, "isRTL"); - - while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden(obj))) { - obj = obj[isRTL ? "previousSibling" : "nextSibling"]; - } - - position = $(obj).offset(); - return [position.left, position.top]; - }, - - /* Hide the date picker from view. - * @param input element - the input field attached to the date picker - */ - _hideDatepicker: function(input) { - var showAnim, duration, postProcess, onClose, - inst = this._curInst; - - if (!inst || (input && inst !== $.data(input, "datepicker"))) { - return; - } - - if (this._datepickerShowing) { - showAnim = this._get(inst, "showAnim"); - duration = this._get(inst, "duration"); - postProcess = function() { - $.datepicker._tidyDialog(inst); - }; - - // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed - if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) { - inst.dpDiv.hide(showAnim, $.datepicker._get(inst, "showOptions"), duration, postProcess); - } else { - inst.dpDiv[(showAnim === "slideDown" ? "slideUp" : - (showAnim === "fadeIn" ? "fadeOut" : "hide"))]((showAnim ? duration : null), postProcess); - } - - if (!showAnim) { - postProcess(); - } - this._datepickerShowing = false; - - onClose = this._get(inst, "onClose"); - if (onClose) { - onClose.apply((inst.input ? inst.input[0] : null), [(inst.input ? inst.input.val() : ""), inst]); - } - - this._lastInput = null; - if (this._inDialog) { - this._dialogInput.css({ position: "absolute", left: "0", top: "-100px" }); - if ($.blockUI) { - $.unblockUI(); - $("body").append(this.dpDiv); - } - } - this._inDialog = false; - } - }, - - /* Tidy up after a dialog display. */ - _tidyDialog: function(inst) { - inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar"); - }, - - /* Close date picker if clicked elsewhere. */ - _checkExternalClick: function(event) { - if (!$.datepicker._curInst) { - return; - } - - var $target = $(event.target), - inst = $.datepicker._getInst($target[0]); - - if ( ( ( $target[0].id !== $.datepicker._mainDivId && - $target.parents("#" + $.datepicker._mainDivId).length === 0 && - !$target.hasClass($.datepicker.markerClassName) && - !$target.closest("." + $.datepicker._triggerClass).length && - $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) || - ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst !== inst ) ) { - $.datepicker._hideDatepicker(); - } - }, - - /* Adjust one of the date sub-fields. */ - _adjustDate: function(id, offset, period) { - var target = $(id), - inst = this._getInst(target[0]); - - if (this._isDisabledDatepicker(target[0])) { - return; - } - this._adjustInstDate(inst, offset + - (period === "M" ? this._get(inst, "showCurrentAtPos") : 0), // undo positioning - period); - this._updateDatepicker(inst); - }, - - /* Action for current link. */ - _gotoToday: function(id) { - var date, - target = $(id), - inst = this._getInst(target[0]); - - if (this._get(inst, "gotoCurrent") && inst.currentDay) { - inst.selectedDay = inst.currentDay; - inst.drawMonth = inst.selectedMonth = inst.currentMonth; - inst.drawYear = inst.selectedYear = inst.currentYear; - } else { - date = new Date(); - inst.selectedDay = date.getDate(); - inst.drawMonth = inst.selectedMonth = date.getMonth(); - inst.drawYear = inst.selectedYear = date.getFullYear(); - } - this._notifyChange(inst); - this._adjustDate(target); - }, - - /* Action for selecting a new month/year. */ - _selectMonthYear: function(id, select, period) { - var target = $(id), - inst = this._getInst(target[0]); - - inst["selected" + (period === "M" ? "Month" : "Year")] = - inst["draw" + (period === "M" ? "Month" : "Year")] = - parseInt(select.options[select.selectedIndex].value,10); - - this._notifyChange(inst); - this._adjustDate(target); - }, - - /* Action for selecting a day. */ - _selectDay: function(id, month, year, td) { - var inst, - target = $(id); - - if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) { - return; - } - - inst = this._getInst(target[0]); - inst.selectedDay = inst.currentDay = $("a", td).html(); - inst.selectedMonth = inst.currentMonth = month; - inst.selectedYear = inst.currentYear = year; - this._selectDate(id, this._formatDate(inst, - inst.currentDay, inst.currentMonth, inst.currentYear)); - }, - - /* Erase the input field and hide the date picker. */ - _clearDate: function(id) { - var target = $(id); - this._selectDate(target, ""); - }, - - /* Update the input field with the selected date. */ - _selectDate: function(id, dateStr) { - var onSelect, - target = $(id), - inst = this._getInst(target[0]); - - dateStr = (dateStr != null ? dateStr : this._formatDate(inst)); - if (inst.input) { - inst.input.val(dateStr); - } - this._updateAlternate(inst); - - onSelect = this._get(inst, "onSelect"); - if (onSelect) { - onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback - } else if (inst.input) { - inst.input.trigger("change"); // fire the change event - } - - if (inst.inline){ - this._updateDatepicker(inst); - } else { - this._hideDatepicker(); - this._lastInput = inst.input[0]; - if (typeof(inst.input[0]) !== "object") { - inst.input.focus(); // restore focus - } - this._lastInput = null; - } - }, - - /* Update any alternate field to synchronise with the main field. */ - _updateAlternate: function(inst) { - var altFormat, date, dateStr, - altField = this._get(inst, "altField"); - - if (altField) { // update alternate field too - altFormat = this._get(inst, "altFormat") || this._get(inst, "dateFormat"); - date = this._getDate(inst); - dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst)); - $(altField).each(function() { $(this).val(dateStr); }); - } - }, - - /* Set as beforeShowDay function to prevent selection of weekends. - * @param date Date - the date to customise - * @return [boolean, string] - is this date selectable?, what is its CSS class? - */ - noWeekends: function(date) { - var day = date.getDay(); - return [(day > 0 && day < 6), ""]; - }, - - /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition. - * @param date Date - the date to get the week for - * @return number - the number of the week within the year that contains this date - */ - iso8601Week: function(date) { - var time, - checkDate = new Date(date.getTime()); - - // Find Thursday of this week starting on Monday - checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); - - time = checkDate.getTime(); - checkDate.setMonth(0); // Compare with Jan 1 - checkDate.setDate(1); - return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1; - }, - - /* Parse a string value into a date object. - * See formatDate below for the possible formats. - * - * @param format string - the expected format of the date - * @param value string - the date in the above format - * @param settings Object - attributes include: - * shortYearCutoff number - the cutoff year for determining the century (optional) - * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) - * dayNames string[7] - names of the days from Sunday (optional) - * monthNamesShort string[12] - abbreviated names of the months (optional) - * monthNames string[12] - names of the months (optional) - * @return Date - the extracted date value or null if value is blank - */ - parseDate: function (format, value, settings) { - if (format == null || value == null) { - throw "Invalid arguments"; - } - - value = (typeof value === "object" ? value.toString() : value + ""); - if (value === "") { - return null; - } - - var iFormat, dim, extra, - iValue = 0, - shortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff, - shortYearCutoff = (typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp : - new Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10)), - dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort, - dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames, - monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort, - monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames, - year = -1, - month = -1, - day = -1, - doy = -1, - literal = false, - date, - // Check whether a format character is doubled - lookAhead = function(match) { - var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); - if (matches) { - iFormat++; - } - return matches; - }, - // Extract a number from the string value - getNumber = function(match) { - var isDoubled = lookAhead(match), - size = (match === "@" ? 14 : (match === "!" ? 20 : - (match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))), - minSize = (match === "y" ? size : 1), - digits = new RegExp("^\\d{" + minSize + "," + size + "}"), - num = value.substring(iValue).match(digits); - if (!num) { - throw "Missing number at position " + iValue; - } - iValue += num[0].length; - return parseInt(num[0], 10); - }, - // Extract a name from the string value and convert to an index - getName = function(match, shortNames, longNames) { - var index = -1, - names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) { - return [ [k, v] ]; - }).sort(function (a, b) { - return -(a[1].length - b[1].length); - }); - - $.each(names, function (i, pair) { - var name = pair[1]; - if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) { - index = pair[0]; - iValue += name.length; - return false; - } - }); - if (index !== -1) { - return index + 1; - } else { - throw "Unknown name at position " + iValue; - } - }, - // Confirm that a literal character matches the string value - checkLiteral = function() { - if (value.charAt(iValue) !== format.charAt(iFormat)) { - throw "Unexpected literal at position " + iValue; - } - iValue++; - }; - - for (iFormat = 0; iFormat < format.length; iFormat++) { - if (literal) { - if (format.charAt(iFormat) === "'" && !lookAhead("'")) { - literal = false; - } else { - checkLiteral(); - } - } else { - switch (format.charAt(iFormat)) { - case "d": - day = getNumber("d"); - break; - case "D": - getName("D", dayNamesShort, dayNames); - break; - case "o": - doy = getNumber("o"); - break; - case "m": - month = getNumber("m"); - break; - case "M": - month = getName("M", monthNamesShort, monthNames); - break; - case "y": - year = getNumber("y"); - break; - case "@": - date = new Date(getNumber("@")); - year = date.getFullYear(); - month = date.getMonth() + 1; - day = date.getDate(); - break; - case "!": - date = new Date((getNumber("!") - this._ticksTo1970) / 10000); - year = date.getFullYear(); - month = date.getMonth() + 1; - day = date.getDate(); - break; - case "'": - if (lookAhead("'")){ - checkLiteral(); - } else { - literal = true; - } - break; - default: - checkLiteral(); - } - } - } - - if (iValue < value.length){ - extra = value.substr(iValue); - if (!/^\s+/.test(extra)) { - throw "Extra/unparsed characters found in date: " + extra; - } - } - - if (year === -1) { - year = new Date().getFullYear(); - } else if (year < 100) { - year += new Date().getFullYear() - new Date().getFullYear() % 100 + - (year <= shortYearCutoff ? 0 : -100); - } - - if (doy > -1) { - month = 1; - day = doy; - do { - dim = this._getDaysInMonth(year, month - 1); - if (day <= dim) { - break; - } - month++; - day -= dim; - } while (true); - } - - date = this._daylightSavingAdjust(new Date(year, month - 1, day)); - if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) { - throw "Invalid date"; // E.g. 31/02/00 - } - return date; - }, - - /* Standard date formats. */ - ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601) - COOKIE: "D, dd M yy", - ISO_8601: "yy-mm-dd", - RFC_822: "D, d M y", - RFC_850: "DD, dd-M-y", - RFC_1036: "D, d M y", - RFC_1123: "D, d M yy", - RFC_2822: "D, d M yy", - RSS: "D, d M y", // RFC 822 - TICKS: "!", - TIMESTAMP: "@", - W3C: "yy-mm-dd", // ISO 8601 - - _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) + - Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000), - - /* Format a date object into a string value. - * The format can be combinations of the following: - * d - day of month (no leading zero) - * dd - day of month (two digit) - * o - day of year (no leading zeros) - * oo - day of year (three digit) - * D - day name short - * DD - day name long - * m - month of year (no leading zero) - * mm - month of year (two digit) - * M - month name short - * MM - month name long - * y - year (two digit) - * yy - year (four digit) - * @ - Unix timestamp (ms since 01/01/1970) - * ! - Windows ticks (100ns since 01/01/0001) - * "..." - literal text - * '' - single quote - * - * @param format string - the desired format of the date - * @param date Date - the date value to format - * @param settings Object - attributes include: - * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) - * dayNames string[7] - names of the days from Sunday (optional) - * monthNamesShort string[12] - abbreviated names of the months (optional) - * monthNames string[12] - names of the months (optional) - * @return string - the date in the above format - */ - formatDate: function (format, date, settings) { - if (!date) { - return ""; - } - - var iFormat, - dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort, - dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames, - monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort, - monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames, - // Check whether a format character is doubled - lookAhead = function(match) { - var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); - if (matches) { - iFormat++; - } - return matches; - }, - // Format a number, with leading zero if necessary - formatNumber = function(match, value, len) { - var num = "" + value; - if (lookAhead(match)) { - while (num.length < len) { - num = "0" + num; - } - } - return num; - }, - // Format a name, short or long as requested - formatName = function(match, value, shortNames, longNames) { - return (lookAhead(match) ? longNames[value] : shortNames[value]); - }, - output = "", - literal = false; - - if (date) { - for (iFormat = 0; iFormat < format.length; iFormat++) { - if (literal) { - if (format.charAt(iFormat) === "'" && !lookAhead("'")) { - literal = false; - } else { - output += format.charAt(iFormat); - } - } else { - switch (format.charAt(iFormat)) { - case "d": - output += formatNumber("d", date.getDate(), 2); - break; - case "D": - output += formatName("D", date.getDay(), dayNamesShort, dayNames); - break; - case "o": - output += formatNumber("o", - Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3); - break; - case "m": - output += formatNumber("m", date.getMonth() + 1, 2); - break; - case "M": - output += formatName("M", date.getMonth(), monthNamesShort, monthNames); - break; - case "y": - output += (lookAhead("y") ? date.getFullYear() : - (date.getYear() % 100 < 10 ? "0" : "") + date.getYear() % 100); - break; - case "@": - output += date.getTime(); - break; - case "!": - output += date.getTime() * 10000 + this._ticksTo1970; - break; - case "'": - if (lookAhead("'")) { - output += "'"; - } else { - literal = true; - } - break; - default: - output += format.charAt(iFormat); - } - } - } - } - return output; - }, - - /* Extract all possible characters from the date format. */ - _possibleChars: function (format) { - var iFormat, - chars = "", - literal = false, - // Check whether a format character is doubled - lookAhead = function(match) { - var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); - if (matches) { - iFormat++; - } - return matches; - }; - - for (iFormat = 0; iFormat < format.length; iFormat++) { - if (literal) { - if (format.charAt(iFormat) === "'" && !lookAhead("'")) { - literal = false; - } else { - chars += format.charAt(iFormat); - } - } else { - switch (format.charAt(iFormat)) { - case "d": case "m": case "y": case "@": - chars += "0123456789"; - break; - case "D": case "M": - return null; // Accept anything - case "'": - if (lookAhead("'")) { - chars += "'"; - } else { - literal = true; - } - break; - default: - chars += format.charAt(iFormat); - } - } - } - return chars; - }, - - /* Get a setting value, defaulting if necessary. */ - _get: function(inst, name) { - return inst.settings[name] !== undefined ? - inst.settings[name] : this._defaults[name]; - }, - - /* Parse existing date and initialise date picker. */ - _setDateFromField: function(inst, noDefault) { - if (inst.input.val() === inst.lastVal) { - return; - } - - var dateFormat = this._get(inst, "dateFormat"), - dates = inst.lastVal = inst.input ? inst.input.val() : null, - defaultDate = this._getDefaultDate(inst), - date = defaultDate, - settings = this._getFormatConfig(inst); - - try { - date = this.parseDate(dateFormat, dates, settings) || defaultDate; - } catch (event) { - dates = (noDefault ? "" : dates); - } - inst.selectedDay = date.getDate(); - inst.drawMonth = inst.selectedMonth = date.getMonth(); - inst.drawYear = inst.selectedYear = date.getFullYear(); - inst.currentDay = (dates ? date.getDate() : 0); - inst.currentMonth = (dates ? date.getMonth() : 0); - inst.currentYear = (dates ? date.getFullYear() : 0); - this._adjustInstDate(inst); - }, - - /* Retrieve the default date shown on opening. */ - _getDefaultDate: function(inst) { - return this._restrictMinMax(inst, - this._determineDate(inst, this._get(inst, "defaultDate"), new Date())); - }, - - /* A date may be specified as an exact value or a relative one. */ - _determineDate: function(inst, date, defaultDate) { - var offsetNumeric = function(offset) { - var date = new Date(); - date.setDate(date.getDate() + offset); - return date; - }, - offsetString = function(offset) { - try { - return $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"), - offset, $.datepicker._getFormatConfig(inst)); - } - catch (e) { - // Ignore - } - - var date = (offset.toLowerCase().match(/^c/) ? - $.datepicker._getDate(inst) : null) || new Date(), - year = date.getFullYear(), - month = date.getMonth(), - day = date.getDate(), - pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g, - matches = pattern.exec(offset); - - while (matches) { - switch (matches[2] || "d") { - case "d" : case "D" : - day += parseInt(matches[1],10); break; - case "w" : case "W" : - day += parseInt(matches[1],10) * 7; break; - case "m" : case "M" : - month += parseInt(matches[1],10); - day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); - break; - case "y": case "Y" : - year += parseInt(matches[1],10); - day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); - break; - } - matches = pattern.exec(offset); - } - return new Date(year, month, day); - }, - newDate = (date == null || date === "" ? defaultDate : (typeof date === "string" ? offsetString(date) : - (typeof date === "number" ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime())))); - - newDate = (newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate); - if (newDate) { - newDate.setHours(0); - newDate.setMinutes(0); - newDate.setSeconds(0); - newDate.setMilliseconds(0); - } - return this._daylightSavingAdjust(newDate); - }, - - /* Handle switch to/from daylight saving. - * Hours may be non-zero on daylight saving cut-over: - * > 12 when midnight changeover, but then cannot generate - * midnight datetime, so jump to 1AM, otherwise reset. - * @param date (Date) the date to check - * @return (Date) the corrected date - */ - _daylightSavingAdjust: function(date) { - if (!date) { - return null; - } - date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0); - return date; - }, - - /* Set the date(s) directly. */ - _setDate: function(inst, date, noChange) { - var clear = !date, - origMonth = inst.selectedMonth, - origYear = inst.selectedYear, - newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date())); - - inst.selectedDay = inst.currentDay = newDate.getDate(); - inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth(); - inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear(); - if ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange) { - this._notifyChange(inst); - } - this._adjustInstDate(inst); - if (inst.input) { - inst.input.val(clear ? "" : this._formatDate(inst)); - } - }, - - /* Retrieve the date(s) directly. */ - _getDate: function(inst) { - var startDate = (!inst.currentYear || (inst.input && inst.input.val() === "") ? null : - this._daylightSavingAdjust(new Date( - inst.currentYear, inst.currentMonth, inst.currentDay))); - return startDate; - }, - - /* Attach the onxxx handlers. These are declared statically so - * they work with static code transformers like Caja. - */ - _attachHandlers: function(inst) { - var stepMonths = this._get(inst, "stepMonths"), - id = "#" + inst.id.replace( /\\\\/g, "\\" ); - inst.dpDiv.find("[data-handler]").map(function () { - var handler = { - prev: function () { - $.datepicker._adjustDate(id, -stepMonths, "M"); - }, - next: function () { - $.datepicker._adjustDate(id, +stepMonths, "M"); - }, - hide: function () { - $.datepicker._hideDatepicker(); - }, - today: function () { - $.datepicker._gotoToday(id); - }, - selectDay: function () { - $.datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this); - return false; - }, - selectMonth: function () { - $.datepicker._selectMonthYear(id, this, "M"); - return false; - }, - selectYear: function () { - $.datepicker._selectMonthYear(id, this, "Y"); - return false; - } - }; - $(this).bind(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]); - }); - }, - - /* Generate the HTML for the current state of the date picker. */ - _generateHTML: function(inst) { - var maxDraw, prevText, prev, nextText, next, currentText, gotoDate, - controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin, - monthNames, monthNamesShort, beforeShowDay, showOtherMonths, - selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate, - cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows, - printDate, dRow, tbody, daySettings, otherMonth, unselectable, - tempDate = new Date(), - today = this._daylightSavingAdjust( - new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time - isRTL = this._get(inst, "isRTL"), - showButtonPanel = this._get(inst, "showButtonPanel"), - hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"), - navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"), - numMonths = this._getNumberOfMonths(inst), - showCurrentAtPos = this._get(inst, "showCurrentAtPos"), - stepMonths = this._get(inst, "stepMonths"), - isMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1), - currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) : - new Date(inst.currentYear, inst.currentMonth, inst.currentDay))), - minDate = this._getMinMaxDate(inst, "min"), - maxDate = this._getMinMaxDate(inst, "max"), - drawMonth = inst.drawMonth - showCurrentAtPos, - drawYear = inst.drawYear; - - if (drawMonth < 0) { - drawMonth += 12; - drawYear--; - } - if (maxDate) { - maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(), - maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate())); - maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw); - while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) { - drawMonth--; - if (drawMonth < 0) { - drawMonth = 11; - drawYear--; - } - } - } - inst.drawMonth = drawMonth; - inst.drawYear = drawYear; - - prevText = this._get(inst, "prevText"); - prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText, - this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)), - this._getFormatConfig(inst))); - - prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ? - "<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" + - " title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>" : - (hideIfNoPrevNext ? "" : "<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='"+ prevText +"'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>")); - - nextText = this._get(inst, "nextText"); - nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText, - this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)), - this._getFormatConfig(inst))); - - next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ? - "<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" + - " title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>" : - (hideIfNoPrevNext ? "" : "<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='"+ nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>")); - - currentText = this._get(inst, "currentText"); - gotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today); - currentText = (!navigationAsDateFormat ? currentText : - this.formatDate(currentText, gotoDate, this._getFormatConfig(inst))); - - controls = (!inst.inline ? "<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>" + - this._get(inst, "closeText") + "</button>" : ""); - - buttonPanel = (showButtonPanel) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + (isRTL ? controls : "") + - (this._isInRange(inst, gotoDate) ? "<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'" + - ">" + currentText + "</button>" : "") + (isRTL ? "" : controls) + "</div>" : ""; - - firstDay = parseInt(this._get(inst, "firstDay"),10); - firstDay = (isNaN(firstDay) ? 0 : firstDay); - - showWeek = this._get(inst, "showWeek"); - dayNames = this._get(inst, "dayNames"); - dayNamesMin = this._get(inst, "dayNamesMin"); - monthNames = this._get(inst, "monthNames"); - monthNamesShort = this._get(inst, "monthNamesShort"); - beforeShowDay = this._get(inst, "beforeShowDay"); - showOtherMonths = this._get(inst, "showOtherMonths"); - selectOtherMonths = this._get(inst, "selectOtherMonths"); - defaultDate = this._getDefaultDate(inst); - html = ""; - dow; - for (row = 0; row < numMonths[0]; row++) { - group = ""; - this.maxRows = 4; - for (col = 0; col < numMonths[1]; col++) { - selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay)); - cornerClass = " ui-corner-all"; - calender = ""; - if (isMultiMonth) { - calender += "<div class='ui-datepicker-group"; - if (numMonths[1] > 1) { - switch (col) { - case 0: calender += " ui-datepicker-group-first"; - cornerClass = " ui-corner-" + (isRTL ? "right" : "left"); break; - case numMonths[1]-1: calender += " ui-datepicker-group-last"; - cornerClass = " ui-corner-" + (isRTL ? "left" : "right"); break; - default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break; - } - } - calender += "'>"; - } - calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" + - (/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : "") + - (/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : "") + - this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate, - row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers - "</div><table class='ui-datepicker-calendar'><thead>" + - "<tr>"; - thead = (showWeek ? "<th class='ui-datepicker-week-col'>" + this._get(inst, "weekHeader") + "</th>" : ""); - for (dow = 0; dow < 7; dow++) { // days of the week - day = (dow + firstDay) % 7; - thead += "<th scope='col'" + ((dow + firstDay + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + ">" + - "<span title='" + dayNames[day] + "'>" + dayNamesMin[day] + "</span></th>"; - } - calender += thead + "</tr></thead><tbody>"; - daysInMonth = this._getDaysInMonth(drawYear, drawMonth); - if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) { - inst.selectedDay = Math.min(inst.selectedDay, daysInMonth); - } - leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7; - curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate - numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043) - this.maxRows = numRows; - printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays)); - for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows - calender += "<tr>"; - tbody = (!showWeek ? "" : "<td class='ui-datepicker-week-col'>" + - this._get(inst, "calculateWeek")(printDate) + "</td>"); - for (dow = 0; dow < 7; dow++) { // create date picker days - daySettings = (beforeShowDay ? - beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]); - otherMonth = (printDate.getMonth() !== drawMonth); - unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] || - (minDate && printDate < minDate) || (maxDate && printDate > maxDate); - tbody += "<td class='" + - ((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + // highlight weekends - (otherMonth ? " ui-datepicker-other-month" : "") + // highlight days from other months - ((printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent) || // user pressed key - (defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime()) ? - // or defaultDate is current printedDate and defaultDate is selectedDate - " " + this._dayOverClass : "") + // highlight selected day - (unselectable ? " " + this._unselectableClass + " ui-state-disabled": "") + // highlight unselectable days - (otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + // highlight custom dates - (printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + // highlight selected day - (printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "'" + // highlight today (if different) - ((!otherMonth || showOtherMonths) && daySettings[2] ? " title='" + daySettings[2].replace(/'/g, "'") + "'" : "") + // cell title - (unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'") + ">" + // actions - (otherMonth && !showOtherMonths ? " " : // display for other months - (unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" + - (printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") + - (printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + // highlight selected day - (otherMonth ? " ui-priority-secondary" : "") + // distinguish dates from other months - "' href='#'>" + printDate.getDate() + "</a>")) + "</td>"; // display selectable date - printDate.setDate(printDate.getDate() + 1); - printDate = this._daylightSavingAdjust(printDate); - } - calender += tbody + "</tr>"; - } - drawMonth++; - if (drawMonth > 11) { - drawMonth = 0; - drawYear++; - } - calender += "</tbody></table>" + (isMultiMonth ? "</div>" + - ((numMonths[0] > 0 && col === numMonths[1]-1) ? "<div class='ui-datepicker-row-break'></div>" : "") : ""); - group += calender; - } - html += group; - } - html += buttonPanel; - inst._keyEvent = false; - return html; - }, - - /* Generate the month and year header. */ - _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate, - secondary, monthNames, monthNamesShort) { - - var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear, - changeMonth = this._get(inst, "changeMonth"), - changeYear = this._get(inst, "changeYear"), - showMonthAfterYear = this._get(inst, "showMonthAfterYear"), - html = "<div class='ui-datepicker-title'>", - monthHtml = ""; - - // month selection - if (secondary || !changeMonth) { - monthHtml += "<span class='ui-datepicker-month'>" + monthNames[drawMonth] + "</span>"; - } else { - inMinYear = (minDate && minDate.getFullYear() === drawYear); - inMaxYear = (maxDate && maxDate.getFullYear() === drawYear); - monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>"; - for ( month = 0; month < 12; month++) { - if ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) { - monthHtml += "<option value='" + month + "'" + - (month === drawMonth ? " selected='selected'" : "") + - ">" + monthNamesShort[month] + "</option>"; - } - } - monthHtml += "</select>"; - } - - if (!showMonthAfterYear) { - html += monthHtml + (secondary || !(changeMonth && changeYear) ? " " : ""); - } - - // year selection - if ( !inst.yearshtml ) { - inst.yearshtml = ""; - if (secondary || !changeYear) { - html += "<span class='ui-datepicker-year'>" + drawYear + "</span>"; - } else { - // determine range of years to display - years = this._get(inst, "yearRange").split(":"); - thisYear = new Date().getFullYear(); - determineYear = function(value) { - var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) : - (value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) : - parseInt(value, 10))); - return (isNaN(year) ? thisYear : year); - }; - year = determineYear(years[0]); - endYear = Math.max(year, determineYear(years[1] || "")); - year = (minDate ? Math.max(year, minDate.getFullYear()) : year); - endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear); - inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>"; - for (; year <= endYear; year++) { - inst.yearshtml += "<option value='" + year + "'" + - (year === drawYear ? " selected='selected'" : "") + - ">" + year + "</option>"; - } - inst.yearshtml += "</select>"; - - html += inst.yearshtml; - inst.yearshtml = null; - } - } - - html += this._get(inst, "yearSuffix"); - if (showMonthAfterYear) { - html += (secondary || !(changeMonth && changeYear) ? " " : "") + monthHtml; - } - html += "</div>"; // Close datepicker_header - return html; - }, - - /* Adjust one of the date sub-fields. */ - _adjustInstDate: function(inst, offset, period) { - var year = inst.drawYear + (period === "Y" ? offset : 0), - month = inst.drawMonth + (period === "M" ? offset : 0), - day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period === "D" ? offset : 0), - date = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day))); - - inst.selectedDay = date.getDate(); - inst.drawMonth = inst.selectedMonth = date.getMonth(); - inst.drawYear = inst.selectedYear = date.getFullYear(); - if (period === "M" || period === "Y") { - this._notifyChange(inst); - } - }, - - /* Ensure a date is within any min/max bounds. */ - _restrictMinMax: function(inst, date) { - var minDate = this._getMinMaxDate(inst, "min"), - maxDate = this._getMinMaxDate(inst, "max"), - newDate = (minDate && date < minDate ? minDate : date); - return (maxDate && newDate > maxDate ? maxDate : newDate); - }, - - /* Notify change of month/year. */ - _notifyChange: function(inst) { - var onChange = this._get(inst, "onChangeMonthYear"); - if (onChange) { - onChange.apply((inst.input ? inst.input[0] : null), - [inst.selectedYear, inst.selectedMonth + 1, inst]); - } - }, - - /* Determine the number of months to show. */ - _getNumberOfMonths: function(inst) { - var numMonths = this._get(inst, "numberOfMonths"); - return (numMonths == null ? [1, 1] : (typeof numMonths === "number" ? [1, numMonths] : numMonths)); - }, - - /* Determine the current maximum date - ensure no time components are set. */ - _getMinMaxDate: function(inst, minMax) { - return this._determineDate(inst, this._get(inst, minMax + "Date"), null); - }, - - /* Find the number of days in a given month. */ - _getDaysInMonth: function(year, month) { - return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate(); - }, - - /* Find the day of the week of the first of a month. */ - _getFirstDayOfMonth: function(year, month) { - return new Date(year, month, 1).getDay(); - }, - - /* Determines if we should allow a "next/prev" month display change. */ - _canAdjustMonth: function(inst, offset, curYear, curMonth) { - var numMonths = this._getNumberOfMonths(inst), - date = this._daylightSavingAdjust(new Date(curYear, - curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1)); - - if (offset < 0) { - date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth())); - } - return this._isInRange(inst, date); - }, - - /* Is the given date in the accepted range? */ - _isInRange: function(inst, date) { - var yearSplit, currentYear, - minDate = this._getMinMaxDate(inst, "min"), - maxDate = this._getMinMaxDate(inst, "max"), - minYear = null, - maxYear = null, - years = this._get(inst, "yearRange"); - if (years){ - yearSplit = years.split(":"); - currentYear = new Date().getFullYear(); - minYear = parseInt(yearSplit[0], 10); - maxYear = parseInt(yearSplit[1], 10); - if ( yearSplit[0].match(/[+\-].*/) ) { - minYear += currentYear; - } - if ( yearSplit[1].match(/[+\-].*/) ) { - maxYear += currentYear; - } - } - - return ((!minDate || date.getTime() >= minDate.getTime()) && - (!maxDate || date.getTime() <= maxDate.getTime()) && - (!minYear || date.getFullYear() >= minYear) && - (!maxYear || date.getFullYear() <= maxYear)); - }, - - /* Provide the configuration settings for formatting/parsing. */ - _getFormatConfig: function(inst) { - var shortYearCutoff = this._get(inst, "shortYearCutoff"); - shortYearCutoff = (typeof shortYearCutoff !== "string" ? shortYearCutoff : - new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)); - return {shortYearCutoff: shortYearCutoff, - dayNamesShort: this._get(inst, "dayNamesShort"), dayNames: this._get(inst, "dayNames"), - monthNamesShort: this._get(inst, "monthNamesShort"), monthNames: this._get(inst, "monthNames")}; - }, - - /* Format the given date for display. */ - _formatDate: function(inst, day, month, year) { - if (!day) { - inst.currentDay = inst.selectedDay; - inst.currentMonth = inst.selectedMonth; - inst.currentYear = inst.selectedYear; - } - var date = (day ? (typeof day === "object" ? day : - this._daylightSavingAdjust(new Date(year, month, day))) : - this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay))); - return this.formatDate(this._get(inst, "dateFormat"), date, this._getFormatConfig(inst)); - } -}); - -/* - * Bind hover events for datepicker elements. - * Done via delegate so the binding only occurs once in the lifetime of the parent div. - * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker. - */ -function datepicker_bindHover(dpDiv) { - var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a"; - return dpDiv.delegate(selector, "mouseout", function() { - $(this).removeClass("ui-state-hover"); - if (this.className.indexOf("ui-datepicker-prev") !== -1) { - $(this).removeClass("ui-datepicker-prev-hover"); - } - if (this.className.indexOf("ui-datepicker-next") !== -1) { - $(this).removeClass("ui-datepicker-next-hover"); - } - }) - .delegate( selector, "mouseover", datepicker_handleMouseover ); -} - -function datepicker_handleMouseover() { - if (!$.datepicker._isDisabledDatepicker( datepicker_instActive.inline? datepicker_instActive.dpDiv.parent()[0] : datepicker_instActive.input[0])) { - $(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"); - $(this).addClass("ui-state-hover"); - if (this.className.indexOf("ui-datepicker-prev") !== -1) { - $(this).addClass("ui-datepicker-prev-hover"); - } - if (this.className.indexOf("ui-datepicker-next") !== -1) { - $(this).addClass("ui-datepicker-next-hover"); - } - } -} - -/* jQuery extend now ignores nulls! */ -function datepicker_extendRemove(target, props) { - $.extend(target, props); - for (var name in props) { - if (props[name] == null) { - target[name] = props[name]; - } - } - return target; -} - -/* Invoke the datepicker functionality. - @param options string - a command, optionally followed by additional parameters or - Object - settings for attaching new datepicker functionality - @return jQuery object */ -$.fn.datepicker = function(options){ - - /* Verify an empty collection wasn't passed - Fixes #6976 */ - if ( !this.length ) { - return this; - } - - /* Initialise the date picker. */ - if (!$.datepicker.initialized) { - $(document).mousedown($.datepicker._checkExternalClick); - $.datepicker.initialized = true; - } - - /* Append datepicker main container to body if not exist. */ - if ($("#"+$.datepicker._mainDivId).length === 0) { - $("body").append($.datepicker.dpDiv); - } - - var otherArgs = Array.prototype.slice.call(arguments, 1); - if (typeof options === "string" && (options === "isDisabled" || options === "getDate" || options === "widget")) { - return $.datepicker["_" + options + "Datepicker"]. - apply($.datepicker, [this[0]].concat(otherArgs)); - } - if (options === "option" && arguments.length === 2 && typeof arguments[1] === "string") { - return $.datepicker["_" + options + "Datepicker"]. - apply($.datepicker, [this[0]].concat(otherArgs)); - } - return this.each(function() { - typeof options === "string" ? - $.datepicker["_" + options + "Datepicker"]. - apply($.datepicker, [this].concat(otherArgs)) : - $.datepicker._attachDatepicker(this, options); - }); -}; - -$.datepicker = new Datepicker(); // singleton instance -$.datepicker.initialized = false; -$.datepicker.uuid = new Date().getTime(); -$.datepicker.version = "1.11.4"; - -var datepicker = $.datepicker; - - -/*! - * jQuery UI Dialog 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/dialog/ - */ - - -var dialog = $.widget( "ui.dialog", { - version: "1.11.4", - options: { - appendTo: "body", - autoOpen: true, - buttons: [], - closeOnEscape: true, - closeText: "Close", - dialogClass: "", - draggable: true, - hide: null, - height: "auto", - maxHeight: null, - maxWidth: null, - minHeight: 150, - minWidth: 150, - modal: false, - position: { - my: "center", - at: "center", - of: window, - collision: "fit", - // Ensure the titlebar is always visible - using: function( pos ) { - var topOffset = $( this ).css( pos ).offset().top; - if ( topOffset < 0 ) { - $( this ).css( "top", pos.top - topOffset ); - } - } - }, - resizable: true, - show: null, - title: null, - width: 300, - - // callbacks - beforeClose: null, - close: null, - drag: null, - dragStart: null, - dragStop: null, - focus: null, - open: null, - resize: null, - resizeStart: null, - resizeStop: null - }, - - sizeRelatedOptions: { - buttons: true, - height: true, - maxHeight: true, - maxWidth: true, - minHeight: true, - minWidth: true, - width: true - }, - - resizableRelatedOptions: { - maxHeight: true, - maxWidth: true, - minHeight: true, - minWidth: true - }, - - _create: function() { - this.originalCss = { - display: this.element[ 0 ].style.display, - width: this.element[ 0 ].style.width, - minHeight: this.element[ 0 ].style.minHeight, - maxHeight: this.element[ 0 ].style.maxHeight, - height: this.element[ 0 ].style.height - }; - this.originalPosition = { - parent: this.element.parent(), - index: this.element.parent().children().index( this.element ) - }; - this.originalTitle = this.element.attr( "title" ); - this.options.title = this.options.title || this.originalTitle; - - this._createWrapper(); - - this.element - .show() - .removeAttr( "title" ) - .addClass( "ui-dialog-content ui-widget-content" ) - .appendTo( this.uiDialog ); - - this._createTitlebar(); - this._createButtonPane(); - - if ( this.options.draggable && $.fn.draggable ) { - this._makeDraggable(); - } - if ( this.options.resizable && $.fn.resizable ) { - this._makeResizable(); - } - - this._isOpen = false; - - this._trackFocus(); - }, - - _init: function() { - if ( this.options.autoOpen ) { - this.open(); - } - }, - - _appendTo: function() { - var element = this.options.appendTo; - if ( element && (element.jquery || element.nodeType) ) { - return $( element ); - } - return this.document.find( element || "body" ).eq( 0 ); - }, - - _destroy: function() { - var next, - originalPosition = this.originalPosition; - - this._untrackInstance(); - this._destroyOverlay(); - - this.element - .removeUniqueId() - .removeClass( "ui-dialog-content ui-widget-content" ) - .css( this.originalCss ) - // Without detaching first, the following becomes really slow - .detach(); - - this.uiDialog.stop( true, true ).remove(); - - if ( this.originalTitle ) { - this.element.attr( "title", this.originalTitle ); - } - - next = originalPosition.parent.children().eq( originalPosition.index ); - // Don't try to place the dialog next to itself (#8613) - if ( next.length && next[ 0 ] !== this.element[ 0 ] ) { - next.before( this.element ); - } else { - originalPosition.parent.append( this.element ); - } - }, - - widget: function() { - return this.uiDialog; - }, - - disable: $.noop, - enable: $.noop, - - close: function( event ) { - var activeElement, - that = this; - - if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) { - return; - } - - this._isOpen = false; - this._focusedElement = null; - this._destroyOverlay(); - this._untrackInstance(); - - if ( !this.opener.filter( ":focusable" ).focus().length ) { - - // support: IE9 - // IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe> - try { - activeElement = this.document[ 0 ].activeElement; - - // Support: IE9, IE10 - // If the <body> is blurred, IE will switch windows, see #4520 - if ( activeElement && activeElement.nodeName.toLowerCase() !== "body" ) { - - // Hiding a focused element doesn't trigger blur in WebKit - // so in case we have nothing to focus on, explicitly blur the active element - // https://bugs.webkit.org/show_bug.cgi?id=47182 - $( activeElement ).blur(); - } - } catch ( error ) {} - } - - this._hide( this.uiDialog, this.options.hide, function() { - that._trigger( "close", event ); - }); - }, - - isOpen: function() { - return this._isOpen; - }, - - moveToTop: function() { - this._moveToTop(); - }, - - _moveToTop: function( event, silent ) { - var moved = false, - zIndices = this.uiDialog.siblings( ".ui-front:visible" ).map(function() { - return +$( this ).css( "z-index" ); - }).get(), - zIndexMax = Math.max.apply( null, zIndices ); - - if ( zIndexMax >= +this.uiDialog.css( "z-index" ) ) { - this.uiDialog.css( "z-index", zIndexMax + 1 ); - moved = true; - } - - if ( moved && !silent ) { - this._trigger( "focus", event ); - } - return moved; - }, - - open: function() { - var that = this; - if ( this._isOpen ) { - if ( this._moveToTop() ) { - this._focusTabbable(); - } - return; - } - - this._isOpen = true; - this.opener = $( this.document[ 0 ].activeElement ); - - this._size(); - this._position(); - this._createOverlay(); - this._moveToTop( null, true ); - - // Ensure the overlay is moved to the top with the dialog, but only when - // opening. The overlay shouldn't move after the dialog is open so that - // modeless dialogs opened after the modal dialog stack properly. - if ( this.overlay ) { - this.overlay.css( "z-index", this.uiDialog.css( "z-index" ) - 1 ); - } - - this._show( this.uiDialog, this.options.show, function() { - that._focusTabbable(); - that._trigger( "focus" ); - }); - - // Track the dialog immediately upon openening in case a focus event - // somehow occurs outside of the dialog before an element inside the - // dialog is focused (#10152) - this._makeFocusTarget(); - - this._trigger( "open" ); - }, - - _focusTabbable: function() { - // Set focus to the first match: - // 1. An element that was focused previously - // 2. First element inside the dialog matching [autofocus] - // 3. Tabbable element inside the content element - // 4. Tabbable element inside the buttonpane - // 5. The close button - // 6. The dialog itself - var hasFocus = this._focusedElement; - if ( !hasFocus ) { - hasFocus = this.element.find( "[autofocus]" ); - } - if ( !hasFocus.length ) { - hasFocus = this.element.find( ":tabbable" ); - } - if ( !hasFocus.length ) { - hasFocus = this.uiDialogButtonPane.find( ":tabbable" ); - } - if ( !hasFocus.length ) { - hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" ); - } - if ( !hasFocus.length ) { - hasFocus = this.uiDialog; - } - hasFocus.eq( 0 ).focus(); - }, - - _keepFocus: function( event ) { - function checkFocus() { - var activeElement = this.document[0].activeElement, - isActive = this.uiDialog[0] === activeElement || - $.contains( this.uiDialog[0], activeElement ); - if ( !isActive ) { - this._focusTabbable(); - } - } - event.preventDefault(); - checkFocus.call( this ); - // support: IE - // IE <= 8 doesn't prevent moving focus even with event.preventDefault() - // so we check again later - this._delay( checkFocus ); - }, - - _createWrapper: function() { - this.uiDialog = $("<div>") - .addClass( "ui-dialog ui-widget ui-widget-content ui-corner-all ui-front " + - this.options.dialogClass ) - .hide() - .attr({ - // Setting tabIndex makes the div focusable - tabIndex: -1, - role: "dialog" - }) - .appendTo( this._appendTo() ); - - this._on( this.uiDialog, { - keydown: function( event ) { - if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && - event.keyCode === $.ui.keyCode.ESCAPE ) { - event.preventDefault(); - this.close( event ); - return; - } - - // prevent tabbing out of dialogs - if ( event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented() ) { - return; - } - var tabbables = this.uiDialog.find( ":tabbable" ), - first = tabbables.filter( ":first" ), - last = tabbables.filter( ":last" ); - - if ( ( event.target === last[0] || event.target === this.uiDialog[0] ) && !event.shiftKey ) { - this._delay(function() { - first.focus(); - }); - event.preventDefault(); - } else if ( ( event.target === first[0] || event.target === this.uiDialog[0] ) && event.shiftKey ) { - this._delay(function() { - last.focus(); - }); - event.preventDefault(); - } - }, - mousedown: function( event ) { - if ( this._moveToTop( event ) ) { - this._focusTabbable(); - } - } - }); - - // We assume that any existing aria-describedby attribute means - // that the dialog content is marked up properly - // otherwise we brute force the content as the description - if ( !this.element.find( "[aria-describedby]" ).length ) { - this.uiDialog.attr({ - "aria-describedby": this.element.uniqueId().attr( "id" ) - }); - } - }, - - _createTitlebar: function() { - var uiDialogTitle; - - this.uiDialogTitlebar = $( "<div>" ) - .addClass( "ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix" ) - .prependTo( this.uiDialog ); - this._on( this.uiDialogTitlebar, { - mousedown: function( event ) { - // Don't prevent click on close button (#8838) - // Focusing a dialog that is partially scrolled out of view - // causes the browser to scroll it into view, preventing the click event - if ( !$( event.target ).closest( ".ui-dialog-titlebar-close" ) ) { - // Dialog isn't getting focus when dragging (#8063) - this.uiDialog.focus(); - } - } - }); - - // support: IE - // Use type="button" to prevent enter keypresses in textboxes from closing the - // dialog in IE (#9312) - this.uiDialogTitlebarClose = $( "<button type='button'></button>" ) - .button({ - label: this.options.closeText, - icons: { - primary: "ui-icon-closethick" - }, - text: false - }) - .addClass( "ui-dialog-titlebar-close" ) - .appendTo( this.uiDialogTitlebar ); - this._on( this.uiDialogTitlebarClose, { - click: function( event ) { - event.preventDefault(); - this.close( event ); - } - }); - - uiDialogTitle = $( "<span>" ) - .uniqueId() - .addClass( "ui-dialog-title" ) - .prependTo( this.uiDialogTitlebar ); - this._title( uiDialogTitle ); - - this.uiDialog.attr({ - "aria-labelledby": uiDialogTitle.attr( "id" ) - }); - }, - - _title: function( title ) { - if ( !this.options.title ) { - title.html( " " ); - } - title.text( this.options.title ); - }, - - _createButtonPane: function() { - this.uiDialogButtonPane = $( "<div>" ) - .addClass( "ui-dialog-buttonpane ui-widget-content ui-helper-clearfix" ); - - this.uiButtonSet = $( "<div>" ) - .addClass( "ui-dialog-buttonset" ) - .appendTo( this.uiDialogButtonPane ); - - this._createButtons(); - }, - - _createButtons: function() { - var that = this, - buttons = this.options.buttons; - - // if we already have a button pane, remove it - this.uiDialogButtonPane.remove(); - this.uiButtonSet.empty(); - - if ( $.isEmptyObject( buttons ) || ($.isArray( buttons ) && !buttons.length) ) { - this.uiDialog.removeClass( "ui-dialog-buttons" ); - return; - } - - $.each( buttons, function( name, props ) { - var click, buttonOptions; - props = $.isFunction( props ) ? - { click: props, text: name } : - props; - // Default to a non-submitting button - props = $.extend( { type: "button" }, props ); - // Change the context for the click callback to be the main element - click = props.click; - props.click = function() { - click.apply( that.element[ 0 ], arguments ); - }; - buttonOptions = { - icons: props.icons, - text: props.showText - }; - delete props.icons; - delete props.showText; - $( "<button></button>", props ) - .button( buttonOptions ) - .appendTo( that.uiButtonSet ); - }); - this.uiDialog.addClass( "ui-dialog-buttons" ); - this.uiDialogButtonPane.appendTo( this.uiDialog ); - }, - - _makeDraggable: function() { - var that = this, - options = this.options; - - function filteredUi( ui ) { - return { - position: ui.position, - offset: ui.offset - }; - } - - this.uiDialog.draggable({ - cancel: ".ui-dialog-content, .ui-dialog-titlebar-close", - handle: ".ui-dialog-titlebar", - containment: "document", - start: function( event, ui ) { - $( this ).addClass( "ui-dialog-dragging" ); - that._blockFrames(); - that._trigger( "dragStart", event, filteredUi( ui ) ); - }, - drag: function( event, ui ) { - that._trigger( "drag", event, filteredUi( ui ) ); - }, - stop: function( event, ui ) { - var left = ui.offset.left - that.document.scrollLeft(), - top = ui.offset.top - that.document.scrollTop(); - - options.position = { - my: "left top", - at: "left" + (left >= 0 ? "+" : "") + left + " " + - "top" + (top >= 0 ? "+" : "") + top, - of: that.window - }; - $( this ).removeClass( "ui-dialog-dragging" ); - that._unblockFrames(); - that._trigger( "dragStop", event, filteredUi( ui ) ); - } - }); - }, - - _makeResizable: function() { - var that = this, - options = this.options, - handles = options.resizable, - // .ui-resizable has position: relative defined in the stylesheet - // but dialogs have to use absolute or fixed positioning - position = this.uiDialog.css("position"), - resizeHandles = typeof handles === "string" ? - handles : - "n,e,s,w,se,sw,ne,nw"; - - function filteredUi( ui ) { - return { - originalPosition: ui.originalPosition, - originalSize: ui.originalSize, - position: ui.position, - size: ui.size - }; - } - - this.uiDialog.resizable({ - cancel: ".ui-dialog-content", - containment: "document", - alsoResize: this.element, - maxWidth: options.maxWidth, - maxHeight: options.maxHeight, - minWidth: options.minWidth, - minHeight: this._minHeight(), - handles: resizeHandles, - start: function( event, ui ) { - $( this ).addClass( "ui-dialog-resizing" ); - that._blockFrames(); - that._trigger( "resizeStart", event, filteredUi( ui ) ); - }, - resize: function( event, ui ) { - that._trigger( "resize", event, filteredUi( ui ) ); - }, - stop: function( event, ui ) { - var offset = that.uiDialog.offset(), - left = offset.left - that.document.scrollLeft(), - top = offset.top - that.document.scrollTop(); - - options.height = that.uiDialog.height(); - options.width = that.uiDialog.width(); - options.position = { - my: "left top", - at: "left" + (left >= 0 ? "+" : "") + left + " " + - "top" + (top >= 0 ? "+" : "") + top, - of: that.window - }; - $( this ).removeClass( "ui-dialog-resizing" ); - that._unblockFrames(); - that._trigger( "resizeStop", event, filteredUi( ui ) ); - } - }) - .css( "position", position ); - }, - - _trackFocus: function() { - this._on( this.widget(), { - focusin: function( event ) { - this._makeFocusTarget(); - this._focusedElement = $( event.target ); - } - }); - }, - - _makeFocusTarget: function() { - this._untrackInstance(); - this._trackingInstances().unshift( this ); - }, - - _untrackInstance: function() { - var instances = this._trackingInstances(), - exists = $.inArray( this, instances ); - if ( exists !== -1 ) { - instances.splice( exists, 1 ); - } - }, - - _trackingInstances: function() { - var instances = this.document.data( "ui-dialog-instances" ); - if ( !instances ) { - instances = []; - this.document.data( "ui-dialog-instances", instances ); - } - return instances; - }, - - _minHeight: function() { - var options = this.options; - - return options.height === "auto" ? - options.minHeight : - Math.min( options.minHeight, options.height ); - }, - - _position: function() { - // Need to show the dialog to get the actual offset in the position plugin - var isVisible = this.uiDialog.is( ":visible" ); - if ( !isVisible ) { - this.uiDialog.show(); - } - this.uiDialog.position( this.options.position ); - if ( !isVisible ) { - this.uiDialog.hide(); - } - }, - - _setOptions: function( options ) { - var that = this, - resize = false, - resizableOptions = {}; - - $.each( options, function( key, value ) { - that._setOption( key, value ); - - if ( key in that.sizeRelatedOptions ) { - resize = true; - } - if ( key in that.resizableRelatedOptions ) { - resizableOptions[ key ] = value; - } - }); - - if ( resize ) { - this._size(); - this._position(); - } - if ( this.uiDialog.is( ":data(ui-resizable)" ) ) { - this.uiDialog.resizable( "option", resizableOptions ); - } - }, - - _setOption: function( key, value ) { - var isDraggable, isResizable, - uiDialog = this.uiDialog; - - if ( key === "dialogClass" ) { - uiDialog - .removeClass( this.options.dialogClass ) - .addClass( value ); - } - - if ( key === "disabled" ) { - return; - } - - this._super( key, value ); - - if ( key === "appendTo" ) { - this.uiDialog.appendTo( this._appendTo() ); - } - - if ( key === "buttons" ) { - this._createButtons(); - } - - if ( key === "closeText" ) { - this.uiDialogTitlebarClose.button({ - // Ensure that we always pass a string - label: "" + value - }); - } - - if ( key === "draggable" ) { - isDraggable = uiDialog.is( ":data(ui-draggable)" ); - if ( isDraggable && !value ) { - uiDialog.draggable( "destroy" ); - } - - if ( !isDraggable && value ) { - this._makeDraggable(); - } - } - - if ( key === "position" ) { - this._position(); - } - - if ( key === "resizable" ) { - // currently resizable, becoming non-resizable - isResizable = uiDialog.is( ":data(ui-resizable)" ); - if ( isResizable && !value ) { - uiDialog.resizable( "destroy" ); - } - - // currently resizable, changing handles - if ( isResizable && typeof value === "string" ) { - uiDialog.resizable( "option", "handles", value ); - } - - // currently non-resizable, becoming resizable - if ( !isResizable && value !== false ) { - this._makeResizable(); - } - } - - if ( key === "title" ) { - this._title( this.uiDialogTitlebar.find( ".ui-dialog-title" ) ); - } - }, - - _size: function() { - // If the user has resized the dialog, the .ui-dialog and .ui-dialog-content - // divs will both have width and height set, so we need to reset them - var nonContentHeight, minContentHeight, maxContentHeight, - options = this.options; - - // Reset content sizing - this.element.show().css({ - width: "auto", - minHeight: 0, - maxHeight: "none", - height: 0 - }); - - if ( options.minWidth > options.width ) { - options.width = options.minWidth; - } - - // reset wrapper sizing - // determine the height of all the non-content elements - nonContentHeight = this.uiDialog.css({ - height: "auto", - width: options.width - }) - .outerHeight(); - minContentHeight = Math.max( 0, options.minHeight - nonContentHeight ); - maxContentHeight = typeof options.maxHeight === "number" ? - Math.max( 0, options.maxHeight - nonContentHeight ) : - "none"; - - if ( options.height === "auto" ) { - this.element.css({ - minHeight: minContentHeight, - maxHeight: maxContentHeight, - height: "auto" - }); - } else { - this.element.height( Math.max( 0, options.height - nonContentHeight ) ); - } - - if ( this.uiDialog.is( ":data(ui-resizable)" ) ) { - this.uiDialog.resizable( "option", "minHeight", this._minHeight() ); - } - }, - - _blockFrames: function() { - this.iframeBlocks = this.document.find( "iframe" ).map(function() { - var iframe = $( this ); - - return $( "<div>" ) - .css({ - position: "absolute", - width: iframe.outerWidth(), - height: iframe.outerHeight() - }) - .appendTo( iframe.parent() ) - .offset( iframe.offset() )[0]; - }); - }, - - _unblockFrames: function() { - if ( this.iframeBlocks ) { - this.iframeBlocks.remove(); - delete this.iframeBlocks; - } - }, - - _allowInteraction: function( event ) { - if ( $( event.target ).closest( ".ui-dialog" ).length ) { - return true; - } - - // TODO: Remove hack when datepicker implements - // the .ui-front logic (#8989) - return !!$( event.target ).closest( ".ui-datepicker" ).length; - }, - - _createOverlay: function() { - if ( !this.options.modal ) { - return; - } - - // We use a delay in case the overlay is created from an - // event that we're going to be cancelling (#2804) - var isOpening = true; - this._delay(function() { - isOpening = false; - }); - - if ( !this.document.data( "ui-dialog-overlays" ) ) { - - // Prevent use of anchors and inputs - // Using _on() for an event handler shared across many instances is - // safe because the dialogs stack and must be closed in reverse order - this._on( this.document, { - focusin: function( event ) { - if ( isOpening ) { - return; - } - - if ( !this._allowInteraction( event ) ) { - event.preventDefault(); - this._trackingInstances()[ 0 ]._focusTabbable(); - } - } - }); - } - - this.overlay = $( "<div>" ) - .addClass( "ui-widget-overlay ui-front" ) - .appendTo( this._appendTo() ); - this._on( this.overlay, { - mousedown: "_keepFocus" - }); - this.document.data( "ui-dialog-overlays", - (this.document.data( "ui-dialog-overlays" ) || 0) + 1 ); - }, - - _destroyOverlay: function() { - if ( !this.options.modal ) { - return; - } - - if ( this.overlay ) { - var overlays = this.document.data( "ui-dialog-overlays" ) - 1; - - if ( !overlays ) { - this.document - .unbind( "focusin" ) - .removeData( "ui-dialog-overlays" ); - } else { - this.document.data( "ui-dialog-overlays", overlays ); - } - - this.overlay.remove(); - this.overlay = null; - } - } -}); - - -/*! - * jQuery UI Progressbar 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/progressbar/ - */ - - -var progressbar = $.widget( "ui.progressbar", { - version: "1.11.4", - options: { - max: 100, - value: 0, - - change: null, - complete: null - }, - - min: 0, - - _create: function() { - // Constrain initial value - this.oldValue = this.options.value = this._constrainedValue(); - - this.element - .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) - .attr({ - // Only set static values, aria-valuenow and aria-valuemax are - // set inside _refreshValue() - role: "progressbar", - "aria-valuemin": this.min - }); - - this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" ) - .appendTo( this.element ); - - this._refreshValue(); - }, - - _destroy: function() { - this.element - .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) - .removeAttr( "role" ) - .removeAttr( "aria-valuemin" ) - .removeAttr( "aria-valuemax" ) - .removeAttr( "aria-valuenow" ); - - this.valueDiv.remove(); - }, - - value: function( newValue ) { - if ( newValue === undefined ) { - return this.options.value; - } - - this.options.value = this._constrainedValue( newValue ); - this._refreshValue(); - }, - - _constrainedValue: function( newValue ) { - if ( newValue === undefined ) { - newValue = this.options.value; - } - - this.indeterminate = newValue === false; - - // sanitize value - if ( typeof newValue !== "number" ) { - newValue = 0; - } - - return this.indeterminate ? false : - Math.min( this.options.max, Math.max( this.min, newValue ) ); - }, - - _setOptions: function( options ) { - // Ensure "value" option is set after other values (like max) - var value = options.value; - delete options.value; - - this._super( options ); - - this.options.value = this._constrainedValue( value ); - this._refreshValue(); - }, - - _setOption: function( key, value ) { - if ( key === "max" ) { - // Don't allow a max less than min - value = Math.max( this.min, value ); - } - if ( key === "disabled" ) { - this.element - .toggleClass( "ui-state-disabled", !!value ) - .attr( "aria-disabled", value ); - } - this._super( key, value ); - }, - - _percentage: function() { - return this.indeterminate ? 100 : 100 * ( this.options.value - this.min ) / ( this.options.max - this.min ); - }, - - _refreshValue: function() { - var value = this.options.value, - percentage = this._percentage(); - - this.valueDiv - .toggle( this.indeterminate || value > this.min ) - .toggleClass( "ui-corner-right", value === this.options.max ) - .width( percentage.toFixed(0) + "%" ); - - this.element.toggleClass( "ui-progressbar-indeterminate", this.indeterminate ); - - if ( this.indeterminate ) { - this.element.removeAttr( "aria-valuenow" ); - if ( !this.overlayDiv ) { - this.overlayDiv = $( "<div class='ui-progressbar-overlay'></div>" ).appendTo( this.valueDiv ); - } - } else { - this.element.attr({ - "aria-valuemax": this.options.max, - "aria-valuenow": value - }); - if ( this.overlayDiv ) { - this.overlayDiv.remove(); - this.overlayDiv = null; - } - } - - if ( this.oldValue !== value ) { - this.oldValue = value; - this._trigger( "change" ); - } - if ( value === this.options.max ) { - this._trigger( "complete" ); - } - } -}); - - -/*! - * jQuery UI Selectmenu 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/selectmenu - */ - - -var selectmenu = $.widget( "ui.selectmenu", { - version: "1.11.4", - defaultElement: "<select>", - options: { - appendTo: null, - disabled: null, - icons: { - button: "ui-icon-triangle-1-s" - }, - position: { - my: "left top", - at: "left bottom", - collision: "none" - }, - width: null, - - // callbacks - change: null, - close: null, - focus: null, - open: null, - select: null - }, - - _create: function() { - var selectmenuId = this.element.uniqueId().attr( "id" ); - this.ids = { - element: selectmenuId, - button: selectmenuId + "-button", - menu: selectmenuId + "-menu" - }; - - this._drawButton(); - this._drawMenu(); - - if ( this.options.disabled ) { - this.disable(); - } - }, - - _drawButton: function() { - var that = this; - - // Associate existing label with the new button - this.label = $( "label[for='" + this.ids.element + "']" ).attr( "for", this.ids.button ); - this._on( this.label, { - click: function( event ) { - this.button.focus(); - event.preventDefault(); - } - }); - - // Hide original select element - this.element.hide(); - - // Create button - this.button = $( "<span>", { - "class": "ui-selectmenu-button ui-widget ui-state-default ui-corner-all", - tabindex: this.options.disabled ? -1 : 0, - id: this.ids.button, - role: "combobox", - "aria-expanded": "false", - "aria-autocomplete": "list", - "aria-owns": this.ids.menu, - "aria-haspopup": "true" - }) - .insertAfter( this.element ); - - $( "<span>", { - "class": "ui-icon " + this.options.icons.button - }) - .prependTo( this.button ); - - this.buttonText = $( "<span>", { - "class": "ui-selectmenu-text" - }) - .appendTo( this.button ); - - this._setText( this.buttonText, this.element.find( "option:selected" ).text() ); - this._resizeButton(); - - this._on( this.button, this._buttonEvents ); - this.button.one( "focusin", function() { - - // Delay rendering the menu items until the button receives focus. - // The menu may have already been rendered via a programmatic open. - if ( !that.menuItems ) { - that._refreshMenu(); - } - }); - this._hoverable( this.button ); - this._focusable( this.button ); - }, - - _drawMenu: function() { - var that = this; - - // Create menu - this.menu = $( "<ul>", { - "aria-hidden": "true", - "aria-labelledby": this.ids.button, - id: this.ids.menu - }); - - // Wrap menu - this.menuWrap = $( "<div>", { - "class": "ui-selectmenu-menu ui-front" - }) - .append( this.menu ) - .appendTo( this._appendTo() ); - - // Initialize menu widget - this.menuInstance = this.menu - .menu({ - role: "listbox", - select: function( event, ui ) { - event.preventDefault(); - - // support: IE8 - // If the item was selected via a click, the text selection - // will be destroyed in IE - that._setSelection(); - - that._select( ui.item.data( "ui-selectmenu-item" ), event ); - }, - focus: function( event, ui ) { - var item = ui.item.data( "ui-selectmenu-item" ); - - // Prevent inital focus from firing and check if its a newly focused item - if ( that.focusIndex != null && item.index !== that.focusIndex ) { - that._trigger( "focus", event, { item: item } ); - if ( !that.isOpen ) { - that._select( item, event ); - } - } - that.focusIndex = item.index; - - that.button.attr( "aria-activedescendant", - that.menuItems.eq( item.index ).attr( "id" ) ); - } - }) - .menu( "instance" ); - - // Adjust menu styles to dropdown - this.menu - .addClass( "ui-corner-bottom" ) - .removeClass( "ui-corner-all" ); - - // Don't close the menu on mouseleave - this.menuInstance._off( this.menu, "mouseleave" ); - - // Cancel the menu's collapseAll on document click - this.menuInstance._closeOnDocumentClick = function() { - return false; - }; - - // Selects often contain empty items, but never contain dividers - this.menuInstance._isDivider = function() { - return false; - }; - }, - - refresh: function() { - this._refreshMenu(); - this._setText( this.buttonText, this._getSelectedItem().text() ); - if ( !this.options.width ) { - this._resizeButton(); - } - }, - - _refreshMenu: function() { - this.menu.empty(); - - var item, - options = this.element.find( "option" ); - - if ( !options.length ) { - return; - } - - this._parseOptions( options ); - this._renderMenu( this.menu, this.items ); - - this.menuInstance.refresh(); - this.menuItems = this.menu.find( "li" ).not( ".ui-selectmenu-optgroup" ); - - item = this._getSelectedItem(); - - // Update the menu to have the correct item focused - this.menuInstance.focus( null, item ); - this._setAria( item.data( "ui-selectmenu-item" ) ); - - // Set disabled state - this._setOption( "disabled", this.element.prop( "disabled" ) ); - }, - - open: function( event ) { - if ( this.options.disabled ) { - return; - } - - // If this is the first time the menu is being opened, render the items - if ( !this.menuItems ) { - this._refreshMenu(); - } else { - - // Menu clears focus on close, reset focus to selected item - this.menu.find( ".ui-state-focus" ).removeClass( "ui-state-focus" ); - this.menuInstance.focus( null, this._getSelectedItem() ); - } - - this.isOpen = true; - this._toggleAttr(); - this._resizeMenu(); - this._position(); - - this._on( this.document, this._documentClick ); - - this._trigger( "open", event ); - }, - - _position: function() { - this.menuWrap.position( $.extend( { of: this.button }, this.options.position ) ); - }, - - close: function( event ) { - if ( !this.isOpen ) { - return; - } - - this.isOpen = false; - this._toggleAttr(); - - this.range = null; - this._off( this.document ); - - this._trigger( "close", event ); - }, - - widget: function() { - return this.button; - }, - - menuWidget: function() { - return this.menu; - }, - - _renderMenu: function( ul, items ) { - var that = this, - currentOptgroup = ""; - - $.each( items, function( index, item ) { - if ( item.optgroup !== currentOptgroup ) { - $( "<li>", { - "class": "ui-selectmenu-optgroup ui-menu-divider" + - ( item.element.parent( "optgroup" ).prop( "disabled" ) ? - " ui-state-disabled" : - "" ), - text: item.optgroup - }) - .appendTo( ul ); - - currentOptgroup = item.optgroup; - } - - that._renderItemData( ul, item ); - }); - }, - - _renderItemData: function( ul, item ) { - return this._renderItem( ul, item ).data( "ui-selectmenu-item", item ); - }, - - _renderItem: function( ul, item ) { - var li = $( "<li>" ); - - if ( item.disabled ) { - li.addClass( "ui-state-disabled" ); - } - this._setText( li, item.label ); - - return li.appendTo( ul ); - }, - - _setText: function( element, value ) { - if ( value ) { - element.text( value ); - } else { - element.html( " " ); - } - }, - - _move: function( direction, event ) { - var item, next, - filter = ".ui-menu-item"; - - if ( this.isOpen ) { - item = this.menuItems.eq( this.focusIndex ); - } else { - item = this.menuItems.eq( this.element[ 0 ].selectedIndex ); - filter += ":not(.ui-state-disabled)"; - } - - if ( direction === "first" || direction === "last" ) { - next = item[ direction === "first" ? "prevAll" : "nextAll" ]( filter ).eq( -1 ); - } else { - next = item[ direction + "All" ]( filter ).eq( 0 ); - } - - if ( next.length ) { - this.menuInstance.focus( event, next ); - } - }, - - _getSelectedItem: function() { - return this.menuItems.eq( this.element[ 0 ].selectedIndex ); - }, - - _toggle: function( event ) { - this[ this.isOpen ? "close" : "open" ]( event ); - }, - - _setSelection: function() { - var selection; - - if ( !this.range ) { - return; - } - - if ( window.getSelection ) { - selection = window.getSelection(); - selection.removeAllRanges(); - selection.addRange( this.range ); - - // support: IE8 - } else { - this.range.select(); - } - - // support: IE - // Setting the text selection kills the button focus in IE, but - // restoring the focus doesn't kill the selection. - this.button.focus(); - }, - - _documentClick: { - mousedown: function( event ) { - if ( !this.isOpen ) { - return; - } - - if ( !$( event.target ).closest( ".ui-selectmenu-menu, #" + this.ids.button ).length ) { - this.close( event ); - } - } - }, - - _buttonEvents: { - - // Prevent text selection from being reset when interacting with the selectmenu (#10144) - mousedown: function() { - var selection; - - if ( window.getSelection ) { - selection = window.getSelection(); - if ( selection.rangeCount ) { - this.range = selection.getRangeAt( 0 ); - } - - // support: IE8 - } else { - this.range = document.selection.createRange(); - } - }, - - click: function( event ) { - this._setSelection(); - this._toggle( event ); - }, - - keydown: function( event ) { - var preventDefault = true; - switch ( event.keyCode ) { - case $.ui.keyCode.TAB: - case $.ui.keyCode.ESCAPE: - this.close( event ); - preventDefault = false; - break; - case $.ui.keyCode.ENTER: - if ( this.isOpen ) { - this._selectFocusedItem( event ); - } - break; - case $.ui.keyCode.UP: - if ( event.altKey ) { - this._toggle( event ); - } else { - this._move( "prev", event ); - } - break; - case $.ui.keyCode.DOWN: - if ( event.altKey ) { - this._toggle( event ); - } else { - this._move( "next", event ); - } - break; - case $.ui.keyCode.SPACE: - if ( this.isOpen ) { - this._selectFocusedItem( event ); - } else { - this._toggle( event ); - } - break; - case $.ui.keyCode.LEFT: - this._move( "prev", event ); - break; - case $.ui.keyCode.RIGHT: - this._move( "next", event ); - break; - case $.ui.keyCode.HOME: - case $.ui.keyCode.PAGE_UP: - this._move( "first", event ); - break; - case $.ui.keyCode.END: - case $.ui.keyCode.PAGE_DOWN: - this._move( "last", event ); - break; - default: - this.menu.trigger( event ); - preventDefault = false; - } - - if ( preventDefault ) { - event.preventDefault(); - } - } - }, - - _selectFocusedItem: function( event ) { - var item = this.menuItems.eq( this.focusIndex ); - if ( !item.hasClass( "ui-state-disabled" ) ) { - this._select( item.data( "ui-selectmenu-item" ), event ); - } - }, - - _select: function( item, event ) { - var oldIndex = this.element[ 0 ].selectedIndex; - - // Change native select element - this.element[ 0 ].selectedIndex = item.index; - this._setText( this.buttonText, item.label ); - this._setAria( item ); - this._trigger( "select", event, { item: item } ); - - if ( item.index !== oldIndex ) { - this._trigger( "change", event, { item: item } ); - } - - this.close( event ); - }, - - _setAria: function( item ) { - var id = this.menuItems.eq( item.index ).attr( "id" ); - - this.button.attr({ - "aria-labelledby": id, - "aria-activedescendant": id - }); - this.menu.attr( "aria-activedescendant", id ); - }, - - _setOption: function( key, value ) { - if ( key === "icons" ) { - this.button.find( "span.ui-icon" ) - .removeClass( this.options.icons.button ) - .addClass( value.button ); - } - - this._super( key, value ); - - if ( key === "appendTo" ) { - this.menuWrap.appendTo( this._appendTo() ); - } - - if ( key === "disabled" ) { - this.menuInstance.option( "disabled", value ); - this.button - .toggleClass( "ui-state-disabled", value ) - .attr( "aria-disabled", value ); - - this.element.prop( "disabled", value ); - if ( value ) { - this.button.attr( "tabindex", -1 ); - this.close(); - } else { - this.button.attr( "tabindex", 0 ); - } - } - - if ( key === "width" ) { - this._resizeButton(); - } - }, - - _appendTo: function() { - var element = this.options.appendTo; - - if ( element ) { - element = element.jquery || element.nodeType ? - $( element ) : - this.document.find( element ).eq( 0 ); - } - - if ( !element || !element[ 0 ] ) { - element = this.element.closest( ".ui-front" ); - } - - if ( !element.length ) { - element = this.document[ 0 ].body; - } - - return element; - }, - - _toggleAttr: function() { - this.button - .toggleClass( "ui-corner-top", this.isOpen ) - .toggleClass( "ui-corner-all", !this.isOpen ) - .attr( "aria-expanded", this.isOpen ); - this.menuWrap.toggleClass( "ui-selectmenu-open", this.isOpen ); - this.menu.attr( "aria-hidden", !this.isOpen ); - }, - - _resizeButton: function() { - var width = this.options.width; - - if ( !width ) { - width = this.element.show().outerWidth(); - this.element.hide(); - } - - this.button.outerWidth( width ); - }, - - _resizeMenu: function() { - this.menu.outerWidth( Math.max( - this.button.outerWidth(), - - // support: IE10 - // IE10 wraps long text (possibly a rounding bug) - // so we add 1px to avoid the wrapping - this.menu.width( "" ).outerWidth() + 1 - ) ); - }, - - _getCreateOptions: function() { - return { disabled: this.element.prop( "disabled" ) }; - }, - - _parseOptions: function( options ) { - var data = []; - options.each(function( index, item ) { - var option = $( item ), - optgroup = option.parent( "optgroup" ); - data.push({ - element: option, - index: index, - value: option.val(), - label: option.text(), - optgroup: optgroup.attr( "label" ) || "", - disabled: optgroup.prop( "disabled" ) || option.prop( "disabled" ) - }); - }); - this.items = data; - }, - - _destroy: function() { - this.menuWrap.remove(); - this.button.remove(); - this.element.show(); - this.element.removeUniqueId(); - this.label.attr( "for", this.ids.element ); - } -}); - - -/*! - * jQuery UI Slider 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/slider/ - */ - - -var slider = $.widget( "ui.slider", $.ui.mouse, { - version: "1.11.4", - widgetEventPrefix: "slide", - - options: { - animate: false, - distance: 0, - max: 100, - min: 0, - orientation: "horizontal", - range: false, - step: 1, - value: 0, - values: null, - - // callbacks - change: null, - slide: null, - start: null, - stop: null - }, - - // number of pages in a slider - // (how many times can you page up/down to go through the whole range) - numPages: 5, - - _create: function() { - this._keySliding = false; - this._mouseSliding = false; - this._animateOff = true; - this._handleIndex = null; - this._detectOrientation(); - this._mouseInit(); - this._calculateNewMax(); - - this.element - .addClass( "ui-slider" + - " ui-slider-" + this.orientation + - " ui-widget" + - " ui-widget-content" + - " ui-corner-all"); - - this._refresh(); - this._setOption( "disabled", this.options.disabled ); - - this._animateOff = false; - }, - - _refresh: function() { - this._createRange(); - this._createHandles(); - this._setupEvents(); - this._refreshValue(); - }, - - _createHandles: function() { - var i, handleCount, - options = this.options, - existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ), - handle = "<span class='ui-slider-handle ui-state-default ui-corner-all' tabindex='0'></span>", - handles = []; - - handleCount = ( options.values && options.values.length ) || 1; - - if ( existingHandles.length > handleCount ) { - existingHandles.slice( handleCount ).remove(); - existingHandles = existingHandles.slice( 0, handleCount ); - } - - for ( i = existingHandles.length; i < handleCount; i++ ) { - handles.push( handle ); - } - - this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) ); - - this.handle = this.handles.eq( 0 ); - - this.handles.each(function( i ) { - $( this ).data( "ui-slider-handle-index", i ); - }); - }, - - _createRange: function() { - var options = this.options, - classes = ""; - - if ( options.range ) { - if ( options.range === true ) { - if ( !options.values ) { - options.values = [ this._valueMin(), this._valueMin() ]; - } else if ( options.values.length && options.values.length !== 2 ) { - options.values = [ options.values[0], options.values[0] ]; - } else if ( $.isArray( options.values ) ) { - options.values = options.values.slice(0); - } - } - - if ( !this.range || !this.range.length ) { - this.range = $( "<div></div>" ) - .appendTo( this.element ); - - classes = "ui-slider-range" + - // note: this isn't the most fittingly semantic framework class for this element, - // but worked best visually with a variety of themes - " ui-widget-header ui-corner-all"; - } else { - this.range.removeClass( "ui-slider-range-min ui-slider-range-max" ) - // Handle range switching from true to min/max - .css({ - "left": "", - "bottom": "" - }); - } - - this.range.addClass( classes + - ( ( options.range === "min" || options.range === "max" ) ? " ui-slider-range-" + options.range : "" ) ); - } else { - if ( this.range ) { - this.range.remove(); - } - this.range = null; - } - }, - - _setupEvents: function() { - this._off( this.handles ); - this._on( this.handles, this._handleEvents ); - this._hoverable( this.handles ); - this._focusable( this.handles ); - }, - - _destroy: function() { - this.handles.remove(); - if ( this.range ) { - this.range.remove(); - } - - this.element - .removeClass( "ui-slider" + - " ui-slider-horizontal" + - " ui-slider-vertical" + - " ui-widget" + - " ui-widget-content" + - " ui-corner-all" ); - - this._mouseDestroy(); - }, - - _mouseCapture: function( event ) { - var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle, - that = this, - o = this.options; - - if ( o.disabled ) { - return false; - } - - this.elementSize = { - width: this.element.outerWidth(), - height: this.element.outerHeight() - }; - this.elementOffset = this.element.offset(); - - position = { x: event.pageX, y: event.pageY }; - normValue = this._normValueFromMouse( position ); - distance = this._valueMax() - this._valueMin() + 1; - this.handles.each(function( i ) { - var thisDistance = Math.abs( normValue - that.values(i) ); - if (( distance > thisDistance ) || - ( distance === thisDistance && - (i === that._lastChangedValue || that.values(i) === o.min ))) { - distance = thisDistance; - closestHandle = $( this ); - index = i; - } - }); - - allowed = this._start( event, index ); - if ( allowed === false ) { - return false; - } - this._mouseSliding = true; - - this._handleIndex = index; - - closestHandle - .addClass( "ui-state-active" ) - .focus(); - - offset = closestHandle.offset(); - mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" ); - this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : { - left: event.pageX - offset.left - ( closestHandle.width() / 2 ), - top: event.pageY - offset.top - - ( closestHandle.height() / 2 ) - - ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) - - ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) + - ( parseInt( closestHandle.css("marginTop"), 10 ) || 0) - }; - - if ( !this.handles.hasClass( "ui-state-hover" ) ) { - this._slide( event, index, normValue ); - } - this._animateOff = true; - return true; - }, - - _mouseStart: function() { - return true; - }, - - _mouseDrag: function( event ) { - var position = { x: event.pageX, y: event.pageY }, - normValue = this._normValueFromMouse( position ); - - this._slide( event, this._handleIndex, normValue ); - - return false; - }, - - _mouseStop: function( event ) { - this.handles.removeClass( "ui-state-active" ); - this._mouseSliding = false; - - this._stop( event, this._handleIndex ); - this._change( event, this._handleIndex ); - - this._handleIndex = null; - this._clickOffset = null; - this._animateOff = false; - - return false; - }, - - _detectOrientation: function() { - this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal"; - }, - - _normValueFromMouse: function( position ) { - var pixelTotal, - pixelMouse, - percentMouse, - valueTotal, - valueMouse; - - if ( this.orientation === "horizontal" ) { - pixelTotal = this.elementSize.width; - pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 ); - } else { - pixelTotal = this.elementSize.height; - pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 ); - } - - percentMouse = ( pixelMouse / pixelTotal ); - if ( percentMouse > 1 ) { - percentMouse = 1; - } - if ( percentMouse < 0 ) { - percentMouse = 0; - } - if ( this.orientation === "vertical" ) { - percentMouse = 1 - percentMouse; - } - - valueTotal = this._valueMax() - this._valueMin(); - valueMouse = this._valueMin() + percentMouse * valueTotal; - - return this._trimAlignValue( valueMouse ); - }, - - _start: function( event, index ) { - var uiHash = { - handle: this.handles[ index ], - value: this.value() - }; - if ( this.options.values && this.options.values.length ) { - uiHash.value = this.values( index ); - uiHash.values = this.values(); - } - return this._trigger( "start", event, uiHash ); - }, - - _slide: function( event, index, newVal ) { - var otherVal, - newValues, - allowed; - - if ( this.options.values && this.options.values.length ) { - otherVal = this.values( index ? 0 : 1 ); - - if ( ( this.options.values.length === 2 && this.options.range === true ) && - ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) ) - ) { - newVal = otherVal; - } - - if ( newVal !== this.values( index ) ) { - newValues = this.values(); - newValues[ index ] = newVal; - // A slide can be canceled by returning false from the slide callback - allowed = this._trigger( "slide", event, { - handle: this.handles[ index ], - value: newVal, - values: newValues - } ); - otherVal = this.values( index ? 0 : 1 ); - if ( allowed !== false ) { - this.values( index, newVal ); - } - } - } else { - if ( newVal !== this.value() ) { - // A slide can be canceled by returning false from the slide callback - allowed = this._trigger( "slide", event, { - handle: this.handles[ index ], - value: newVal - } ); - if ( allowed !== false ) { - this.value( newVal ); - } - } - } - }, - - _stop: function( event, index ) { - var uiHash = { - handle: this.handles[ index ], - value: this.value() - }; - if ( this.options.values && this.options.values.length ) { - uiHash.value = this.values( index ); - uiHash.values = this.values(); - } - - this._trigger( "stop", event, uiHash ); - }, - - _change: function( event, index ) { - if ( !this._keySliding && !this._mouseSliding ) { - var uiHash = { - handle: this.handles[ index ], - value: this.value() - }; - if ( this.options.values && this.options.values.length ) { - uiHash.value = this.values( index ); - uiHash.values = this.values(); - } - - //store the last changed value index for reference when handles overlap - this._lastChangedValue = index; - - this._trigger( "change", event, uiHash ); - } - }, - - value: function( newValue ) { - if ( arguments.length ) { - this.options.value = this._trimAlignValue( newValue ); - this._refreshValue(); - this._change( null, 0 ); - return; - } - - return this._value(); - }, - - values: function( index, newValue ) { - var vals, - newValues, - i; - - if ( arguments.length > 1 ) { - this.options.values[ index ] = this._trimAlignValue( newValue ); - this._refreshValue(); - this._change( null, index ); - return; - } - - if ( arguments.length ) { - if ( $.isArray( arguments[ 0 ] ) ) { - vals = this.options.values; - newValues = arguments[ 0 ]; - for ( i = 0; i < vals.length; i += 1 ) { - vals[ i ] = this._trimAlignValue( newValues[ i ] ); - this._change( null, i ); - } - this._refreshValue(); - } else { - if ( this.options.values && this.options.values.length ) { - return this._values( index ); - } else { - return this.value(); - } - } - } else { - return this._values(); - } - }, - - _setOption: function( key, value ) { - var i, - valsLength = 0; - - if ( key === "range" && this.options.range === true ) { - if ( value === "min" ) { - this.options.value = this._values( 0 ); - this.options.values = null; - } else if ( value === "max" ) { - this.options.value = this._values( this.options.values.length - 1 ); - this.options.values = null; - } - } - - if ( $.isArray( this.options.values ) ) { - valsLength = this.options.values.length; - } - - if ( key === "disabled" ) { - this.element.toggleClass( "ui-state-disabled", !!value ); - } - - this._super( key, value ); - - switch ( key ) { - case "orientation": - this._detectOrientation(); - this.element - .removeClass( "ui-slider-horizontal ui-slider-vertical" ) - .addClass( "ui-slider-" + this.orientation ); - this._refreshValue(); - - // Reset positioning from previous orientation - this.handles.css( value === "horizontal" ? "bottom" : "left", "" ); - break; - case "value": - this._animateOff = true; - this._refreshValue(); - this._change( null, 0 ); - this._animateOff = false; - break; - case "values": - this._animateOff = true; - this._refreshValue(); - for ( i = 0; i < valsLength; i += 1 ) { - this._change( null, i ); - } - this._animateOff = false; - break; - case "step": - case "min": - case "max": - this._animateOff = true; - this._calculateNewMax(); - this._refreshValue(); - this._animateOff = false; - break; - case "range": - this._animateOff = true; - this._refresh(); - this._animateOff = false; - break; - } - }, - - //internal value getter - // _value() returns value trimmed by min and max, aligned by step - _value: function() { - var val = this.options.value; - val = this._trimAlignValue( val ); - - return val; - }, - - //internal values getter - // _values() returns array of values trimmed by min and max, aligned by step - // _values( index ) returns single value trimmed by min and max, aligned by step - _values: function( index ) { - var val, - vals, - i; - - if ( arguments.length ) { - val = this.options.values[ index ]; - val = this._trimAlignValue( val ); - - return val; - } else if ( this.options.values && this.options.values.length ) { - // .slice() creates a copy of the array - // this copy gets trimmed by min and max and then returned - vals = this.options.values.slice(); - for ( i = 0; i < vals.length; i += 1) { - vals[ i ] = this._trimAlignValue( vals[ i ] ); - } - - return vals; - } else { - return []; - } - }, - - // returns the step-aligned value that val is closest to, between (inclusive) min and max - _trimAlignValue: function( val ) { - if ( val <= this._valueMin() ) { - return this._valueMin(); - } - if ( val >= this._valueMax() ) { - return this._valueMax(); - } - var step = ( this.options.step > 0 ) ? this.options.step : 1, - valModStep = (val - this._valueMin()) % step, - alignValue = val - valModStep; - - if ( Math.abs(valModStep) * 2 >= step ) { - alignValue += ( valModStep > 0 ) ? step : ( -step ); - } - - // Since JavaScript has problems with large floats, round - // the final value to 5 digits after the decimal point (see #4124) - return parseFloat( alignValue.toFixed(5) ); - }, - - _calculateNewMax: function() { - var max = this.options.max, - min = this._valueMin(), - step = this.options.step, - aboveMin = Math.floor( ( +( max - min ).toFixed( this._precision() ) ) / step ) * step; - max = aboveMin + min; - this.max = parseFloat( max.toFixed( this._precision() ) ); - }, - - _precision: function() { - var precision = this._precisionOf( this.options.step ); - if ( this.options.min !== null ) { - precision = Math.max( precision, this._precisionOf( this.options.min ) ); - } - return precision; - }, - - _precisionOf: function( num ) { - var str = num.toString(), - decimal = str.indexOf( "." ); - return decimal === -1 ? 0 : str.length - decimal - 1; - }, - - _valueMin: function() { - return this.options.min; - }, - - _valueMax: function() { - return this.max; - }, - - _refreshValue: function() { - var lastValPercent, valPercent, value, valueMin, valueMax, - oRange = this.options.range, - o = this.options, - that = this, - animate = ( !this._animateOff ) ? o.animate : false, - _set = {}; - - if ( this.options.values && this.options.values.length ) { - this.handles.each(function( i ) { - valPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100; - _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; - $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); - if ( that.options.range === true ) { - if ( that.orientation === "horizontal" ) { - if ( i === 0 ) { - that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate ); - } - if ( i === 1 ) { - that.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); - } - } else { - if ( i === 0 ) { - that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate ); - } - if ( i === 1 ) { - that.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); - } - } - } - lastValPercent = valPercent; - }); - } else { - value = this.value(); - valueMin = this._valueMin(); - valueMax = this._valueMax(); - valPercent = ( valueMax !== valueMin ) ? - ( value - valueMin ) / ( valueMax - valueMin ) * 100 : - 0; - _set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; - this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); - - if ( oRange === "min" && this.orientation === "horizontal" ) { - this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate ); - } - if ( oRange === "max" && this.orientation === "horizontal" ) { - this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); - } - if ( oRange === "min" && this.orientation === "vertical" ) { - this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate ); - } - if ( oRange === "max" && this.orientation === "vertical" ) { - this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); - } - } - }, - - _handleEvents: { - keydown: function( event ) { - var allowed, curVal, newVal, step, - index = $( event.target ).data( "ui-slider-handle-index" ); - - switch ( event.keyCode ) { - case $.ui.keyCode.HOME: - case $.ui.keyCode.END: - case $.ui.keyCode.PAGE_UP: - case $.ui.keyCode.PAGE_DOWN: - case $.ui.keyCode.UP: - case $.ui.keyCode.RIGHT: - case $.ui.keyCode.DOWN: - case $.ui.keyCode.LEFT: - event.preventDefault(); - if ( !this._keySliding ) { - this._keySliding = true; - $( event.target ).addClass( "ui-state-active" ); - allowed = this._start( event, index ); - if ( allowed === false ) { - return; - } - } - break; - } - - step = this.options.step; - if ( this.options.values && this.options.values.length ) { - curVal = newVal = this.values( index ); - } else { - curVal = newVal = this.value(); - } - - switch ( event.keyCode ) { - case $.ui.keyCode.HOME: - newVal = this._valueMin(); - break; - case $.ui.keyCode.END: - newVal = this._valueMax(); - break; - case $.ui.keyCode.PAGE_UP: - newVal = this._trimAlignValue( - curVal + ( ( this._valueMax() - this._valueMin() ) / this.numPages ) - ); - break; - case $.ui.keyCode.PAGE_DOWN: - newVal = this._trimAlignValue( - curVal - ( (this._valueMax() - this._valueMin()) / this.numPages ) ); - break; - case $.ui.keyCode.UP: - case $.ui.keyCode.RIGHT: - if ( curVal === this._valueMax() ) { - return; - } - newVal = this._trimAlignValue( curVal + step ); - break; - case $.ui.keyCode.DOWN: - case $.ui.keyCode.LEFT: - if ( curVal === this._valueMin() ) { - return; - } - newVal = this._trimAlignValue( curVal - step ); - break; - } - - this._slide( event, index, newVal ); - }, - keyup: function( event ) { - var index = $( event.target ).data( "ui-slider-handle-index" ); - - if ( this._keySliding ) { - this._keySliding = false; - this._stop( event, index ); - this._change( event, index ); - $( event.target ).removeClass( "ui-state-active" ); - } - } - } -}); - - -/*! - * jQuery UI Spinner 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/spinner/ - */ - - -function spinner_modifier( fn ) { - return function() { - var previous = this.element.val(); - fn.apply( this, arguments ); - this._refresh(); - if ( previous !== this.element.val() ) { - this._trigger( "change" ); - } - }; -} - -var spinner = $.widget( "ui.spinner", { - version: "1.11.4", - defaultElement: "<input>", - widgetEventPrefix: "spin", - options: { - culture: null, - icons: { - down: "ui-icon-triangle-1-s", - up: "ui-icon-triangle-1-n" - }, - incremental: true, - max: null, - min: null, - numberFormat: null, - page: 10, - step: 1, - - change: null, - spin: null, - start: null, - stop: null - }, - - _create: function() { - // handle string values that need to be parsed - this._setOption( "max", this.options.max ); - this._setOption( "min", this.options.min ); - this._setOption( "step", this.options.step ); - - // Only format if there is a value, prevents the field from being marked - // as invalid in Firefox, see #9573. - if ( this.value() !== "" ) { - // Format the value, but don't constrain. - this._value( this.element.val(), true ); - } - - this._draw(); - this._on( this._events ); - this._refresh(); - - // turning off autocomplete prevents the browser from remembering the - // value when navigating through history, so we re-enable autocomplete - // if the page is unloaded before the widget is destroyed. #7790 - this._on( this.window, { - beforeunload: function() { - this.element.removeAttr( "autocomplete" ); - } - }); - }, - - _getCreateOptions: function() { - var options = {}, - element = this.element; - - $.each( [ "min", "max", "step" ], function( i, option ) { - var value = element.attr( option ); - if ( value !== undefined && value.length ) { - options[ option ] = value; - } - }); - - return options; - }, - - _events: { - keydown: function( event ) { - if ( this._start( event ) && this._keydown( event ) ) { - event.preventDefault(); - } - }, - keyup: "_stop", - focus: function() { - this.previous = this.element.val(); - }, - blur: function( event ) { - if ( this.cancelBlur ) { - delete this.cancelBlur; - return; - } - - this._stop(); - this._refresh(); - if ( this.previous !== this.element.val() ) { - this._trigger( "change", event ); - } - }, - mousewheel: function( event, delta ) { - if ( !delta ) { - return; - } - if ( !this.spinning && !this._start( event ) ) { - return false; - } - - this._spin( (delta > 0 ? 1 : -1) * this.options.step, event ); - clearTimeout( this.mousewheelTimer ); - this.mousewheelTimer = this._delay(function() { - if ( this.spinning ) { - this._stop( event ); - } - }, 100 ); - event.preventDefault(); - }, - "mousedown .ui-spinner-button": function( event ) { - var previous; - - // We never want the buttons to have focus; whenever the user is - // interacting with the spinner, the focus should be on the input. - // If the input is focused then this.previous is properly set from - // when the input first received focus. If the input is not focused - // then we need to set this.previous based on the value before spinning. - previous = this.element[0] === this.document[0].activeElement ? - this.previous : this.element.val(); - function checkFocus() { - var isActive = this.element[0] === this.document[0].activeElement; - if ( !isActive ) { - this.element.focus(); - this.previous = previous; - // support: IE - // IE sets focus asynchronously, so we need to check if focus - // moved off of the input because the user clicked on the button. - this._delay(function() { - this.previous = previous; - }); - } - } - - // ensure focus is on (or stays on) the text field - event.preventDefault(); - checkFocus.call( this ); - - // support: IE - // IE doesn't prevent moving focus even with event.preventDefault() - // so we set a flag to know when we should ignore the blur event - // and check (again) if focus moved off of the input. - this.cancelBlur = true; - this._delay(function() { - delete this.cancelBlur; - checkFocus.call( this ); - }); - - if ( this._start( event ) === false ) { - return; - } - - this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event ); - }, - "mouseup .ui-spinner-button": "_stop", - "mouseenter .ui-spinner-button": function( event ) { - // button will add ui-state-active if mouse was down while mouseleave and kept down - if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) { - return; - } - - if ( this._start( event ) === false ) { - return false; - } - this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event ); - }, - // TODO: do we really want to consider this a stop? - // shouldn't we just stop the repeater and wait until mouseup before - // we trigger the stop event? - "mouseleave .ui-spinner-button": "_stop" - }, - - _draw: function() { - var uiSpinner = this.uiSpinner = this.element - .addClass( "ui-spinner-input" ) - .attr( "autocomplete", "off" ) - .wrap( this._uiSpinnerHtml() ) - .parent() - // add buttons - .append( this._buttonHtml() ); - - this.element.attr( "role", "spinbutton" ); - - // button bindings - this.buttons = uiSpinner.find( ".ui-spinner-button" ) - .attr( "tabIndex", -1 ) - .button() - .removeClass( "ui-corner-all" ); - - // IE 6 doesn't understand height: 50% for the buttons - // unless the wrapper has an explicit height - if ( this.buttons.height() > Math.ceil( uiSpinner.height() * 0.5 ) && - uiSpinner.height() > 0 ) { - uiSpinner.height( uiSpinner.height() ); - } - - // disable spinner if element was already disabled - if ( this.options.disabled ) { - this.disable(); - } - }, - - _keydown: function( event ) { - var options = this.options, - keyCode = $.ui.keyCode; - - switch ( event.keyCode ) { - case keyCode.UP: - this._repeat( null, 1, event ); - return true; - case keyCode.DOWN: - this._repeat( null, -1, event ); - return true; - case keyCode.PAGE_UP: - this._repeat( null, options.page, event ); - return true; - case keyCode.PAGE_DOWN: - this._repeat( null, -options.page, event ); - return true; - } - - return false; - }, - - _uiSpinnerHtml: function() { - return "<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>"; - }, - - _buttonHtml: function() { - return "" + - "<a class='ui-spinner-button ui-spinner-up ui-corner-tr'>" + - "<span class='ui-icon " + this.options.icons.up + "'>▲</span>" + - "</a>" + - "<a class='ui-spinner-button ui-spinner-down ui-corner-br'>" + - "<span class='ui-icon " + this.options.icons.down + "'>▼</span>" + - "</a>"; - }, - - _start: function( event ) { - if ( !this.spinning && this._trigger( "start", event ) === false ) { - return false; - } - - if ( !this.counter ) { - this.counter = 1; - } - this.spinning = true; - return true; - }, - - _repeat: function( i, steps, event ) { - i = i || 500; - - clearTimeout( this.timer ); - this.timer = this._delay(function() { - this._repeat( 40, steps, event ); - }, i ); - - this._spin( steps * this.options.step, event ); - }, - - _spin: function( step, event ) { - var value = this.value() || 0; - - if ( !this.counter ) { - this.counter = 1; - } - - value = this._adjustValue( value + step * this._increment( this.counter ) ); - - if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false) { - this._value( value ); - this.counter++; - } - }, - - _increment: function( i ) { - var incremental = this.options.incremental; - - if ( incremental ) { - return $.isFunction( incremental ) ? - incremental( i ) : - Math.floor( i * i * i / 50000 - i * i / 500 + 17 * i / 200 + 1 ); - } - - return 1; - }, - - _precision: function() { - var precision = this._precisionOf( this.options.step ); - if ( this.options.min !== null ) { - precision = Math.max( precision, this._precisionOf( this.options.min ) ); - } - return precision; - }, - - _precisionOf: function( num ) { - var str = num.toString(), - decimal = str.indexOf( "." ); - return decimal === -1 ? 0 : str.length - decimal - 1; - }, - - _adjustValue: function( value ) { - var base, aboveMin, - options = this.options; - - // make sure we're at a valid step - // - find out where we are relative to the base (min or 0) - base = options.min !== null ? options.min : 0; - aboveMin = value - base; - // - round to the nearest step - aboveMin = Math.round(aboveMin / options.step) * options.step; - // - rounding is based on 0, so adjust back to our base - value = base + aboveMin; - - // fix precision from bad JS floating point math - value = parseFloat( value.toFixed( this._precision() ) ); - - // clamp the value - if ( options.max !== null && value > options.max) { - return options.max; - } - if ( options.min !== null && value < options.min ) { - return options.min; - } - - return value; - }, - - _stop: function( event ) { - if ( !this.spinning ) { - return; - } - - clearTimeout( this.timer ); - clearTimeout( this.mousewheelTimer ); - this.counter = 0; - this.spinning = false; - this._trigger( "stop", event ); - }, - - _setOption: function( key, value ) { - if ( key === "culture" || key === "numberFormat" ) { - var prevValue = this._parse( this.element.val() ); - this.options[ key ] = value; - this.element.val( this._format( prevValue ) ); - return; - } - - if ( key === "max" || key === "min" || key === "step" ) { - if ( typeof value === "string" ) { - value = this._parse( value ); - } - } - if ( key === "icons" ) { - this.buttons.first().find( ".ui-icon" ) - .removeClass( this.options.icons.up ) - .addClass( value.up ); - this.buttons.last().find( ".ui-icon" ) - .removeClass( this.options.icons.down ) - .addClass( value.down ); - } - - this._super( key, value ); - - if ( key === "disabled" ) { - this.widget().toggleClass( "ui-state-disabled", !!value ); - this.element.prop( "disabled", !!value ); - this.buttons.button( value ? "disable" : "enable" ); - } - }, - - _setOptions: spinner_modifier(function( options ) { - this._super( options ); - }), - - _parse: function( val ) { - if ( typeof val === "string" && val !== "" ) { - val = window.Globalize && this.options.numberFormat ? - Globalize.parseFloat( val, 10, this.options.culture ) : +val; - } - return val === "" || isNaN( val ) ? null : val; - }, - - _format: function( value ) { - if ( value === "" ) { - return ""; - } - return window.Globalize && this.options.numberFormat ? - Globalize.format( value, this.options.numberFormat, this.options.culture ) : - value; - }, - - _refresh: function() { - this.element.attr({ - "aria-valuemin": this.options.min, - "aria-valuemax": this.options.max, - // TODO: what should we do with values that can't be parsed? - "aria-valuenow": this._parse( this.element.val() ) - }); - }, - - isValid: function() { - var value = this.value(); - - // null is invalid - if ( value === null ) { - return false; - } - - // if value gets adjusted, it's invalid - return value === this._adjustValue( value ); - }, - - // update the value without triggering change - _value: function( value, allowAny ) { - var parsed; - if ( value !== "" ) { - parsed = this._parse( value ); - if ( parsed !== null ) { - if ( !allowAny ) { - parsed = this._adjustValue( parsed ); - } - value = this._format( parsed ); - } - } - this.element.val( value ); - this._refresh(); - }, - - _destroy: function() { - this.element - .removeClass( "ui-spinner-input" ) - .prop( "disabled", false ) - .removeAttr( "autocomplete" ) - .removeAttr( "role" ) - .removeAttr( "aria-valuemin" ) - .removeAttr( "aria-valuemax" ) - .removeAttr( "aria-valuenow" ); - this.uiSpinner.replaceWith( this.element ); - }, - - stepUp: spinner_modifier(function( steps ) { - this._stepUp( steps ); - }), - _stepUp: function( steps ) { - if ( this._start() ) { - this._spin( (steps || 1) * this.options.step ); - this._stop(); - } - }, - - stepDown: spinner_modifier(function( steps ) { - this._stepDown( steps ); - }), - _stepDown: function( steps ) { - if ( this._start() ) { - this._spin( (steps || 1) * -this.options.step ); - this._stop(); - } - }, - - pageUp: spinner_modifier(function( pages ) { - this._stepUp( (pages || 1) * this.options.page ); - }), - - pageDown: spinner_modifier(function( pages ) { - this._stepDown( (pages || 1) * this.options.page ); - }), - - value: function( newVal ) { - if ( !arguments.length ) { - return this._parse( this.element.val() ); - } - spinner_modifier( this._value ).call( this, newVal ); - }, - - widget: function() { - return this.uiSpinner; - } -}); - - -/*! - * jQuery UI Tabs 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/tabs/ - */ - - -var tabs = $.widget( "ui.tabs", { - version: "1.11.4", - delay: 300, - options: { - active: null, - collapsible: false, - event: "click", - heightStyle: "content", - hide: null, - show: null, - - // callbacks - activate: null, - beforeActivate: null, - beforeLoad: null, - load: null - }, - - _isLocal: (function() { - var rhash = /#.*$/; - - return function( anchor ) { - var anchorUrl, locationUrl; - - // support: IE7 - // IE7 doesn't normalize the href property when set via script (#9317) - anchor = anchor.cloneNode( false ); - - anchorUrl = anchor.href.replace( rhash, "" ); - locationUrl = location.href.replace( rhash, "" ); - - // decoding may throw an error if the URL isn't UTF-8 (#9518) - try { - anchorUrl = decodeURIComponent( anchorUrl ); - } catch ( error ) {} - try { - locationUrl = decodeURIComponent( locationUrl ); - } catch ( error ) {} - - return anchor.hash.length > 1 && anchorUrl === locationUrl; - }; - })(), - - _create: function() { - var that = this, - options = this.options; - - this.running = false; - - this.element - .addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" ) - .toggleClass( "ui-tabs-collapsible", options.collapsible ); - - this._processTabs(); - options.active = this._initialActive(); - - // Take disabling tabs via class attribute from HTML - // into account and update option properly. - if ( $.isArray( options.disabled ) ) { - options.disabled = $.unique( options.disabled.concat( - $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) { - return that.tabs.index( li ); - }) - ) ).sort(); - } - - // check for length avoids error when initializing empty list - if ( this.options.active !== false && this.anchors.length ) { - this.active = this._findActive( options.active ); - } else { - this.active = $(); - } - - this._refresh(); - - if ( this.active.length ) { - this.load( options.active ); - } - }, - - _initialActive: function() { - var active = this.options.active, - collapsible = this.options.collapsible, - locationHash = location.hash.substring( 1 ); - - if ( active === null ) { - // check the fragment identifier in the URL - if ( locationHash ) { - this.tabs.each(function( i, tab ) { - if ( $( tab ).attr( "aria-controls" ) === locationHash ) { - active = i; - return false; - } - }); - } - - // check for a tab marked active via a class - if ( active === null ) { - active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) ); - } - - // no active tab, set to false - if ( active === null || active === -1 ) { - active = this.tabs.length ? 0 : false; - } - } - - // handle numbers: negative, out of range - if ( active !== false ) { - active = this.tabs.index( this.tabs.eq( active ) ); - if ( active === -1 ) { - active = collapsible ? false : 0; - } - } - - // don't allow collapsible: false and active: false - if ( !collapsible && active === false && this.anchors.length ) { - active = 0; - } - - return active; - }, - - _getCreateEventData: function() { - return { - tab: this.active, - panel: !this.active.length ? $() : this._getPanelForTab( this.active ) - }; - }, - - _tabKeydown: function( event ) { - var focusedTab = $( this.document[0].activeElement ).closest( "li" ), - selectedIndex = this.tabs.index( focusedTab ), - goingForward = true; - - if ( this._handlePageNav( event ) ) { - return; - } - - switch ( event.keyCode ) { - case $.ui.keyCode.RIGHT: - case $.ui.keyCode.DOWN: - selectedIndex++; - break; - case $.ui.keyCode.UP: - case $.ui.keyCode.LEFT: - goingForward = false; - selectedIndex--; - break; - case $.ui.keyCode.END: - selectedIndex = this.anchors.length - 1; - break; - case $.ui.keyCode.HOME: - selectedIndex = 0; - break; - case $.ui.keyCode.SPACE: - // Activate only, no collapsing - event.preventDefault(); - clearTimeout( this.activating ); - this._activate( selectedIndex ); - return; - case $.ui.keyCode.ENTER: - // Toggle (cancel delayed activation, allow collapsing) - event.preventDefault(); - clearTimeout( this.activating ); - // Determine if we should collapse or activate - this._activate( selectedIndex === this.options.active ? false : selectedIndex ); - return; - default: - return; - } - - // Focus the appropriate tab, based on which key was pressed - event.preventDefault(); - clearTimeout( this.activating ); - selectedIndex = this._focusNextTab( selectedIndex, goingForward ); - - // Navigating with control/command key will prevent automatic activation - if ( !event.ctrlKey && !event.metaKey ) { - - // Update aria-selected immediately so that AT think the tab is already selected. - // Otherwise AT may confuse the user by stating that they need to activate the tab, - // but the tab will already be activated by the time the announcement finishes. - focusedTab.attr( "aria-selected", "false" ); - this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" ); - - this.activating = this._delay(function() { - this.option( "active", selectedIndex ); - }, this.delay ); - } - }, - - _panelKeydown: function( event ) { - if ( this._handlePageNav( event ) ) { - return; - } - - // Ctrl+up moves focus to the current tab - if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) { - event.preventDefault(); - this.active.focus(); - } - }, - - // Alt+page up/down moves focus to the previous/next tab (and activates) - _handlePageNav: function( event ) { - if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) { - this._activate( this._focusNextTab( this.options.active - 1, false ) ); - return true; - } - if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) { - this._activate( this._focusNextTab( this.options.active + 1, true ) ); - return true; - } - }, - - _findNextTab: function( index, goingForward ) { - var lastTabIndex = this.tabs.length - 1; - - function constrain() { - if ( index > lastTabIndex ) { - index = 0; - } - if ( index < 0 ) { - index = lastTabIndex; - } - return index; - } - - while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) { - index = goingForward ? index + 1 : index - 1; - } - - return index; - }, - - _focusNextTab: function( index, goingForward ) { - index = this._findNextTab( index, goingForward ); - this.tabs.eq( index ).focus(); - return index; - }, - - _setOption: function( key, value ) { - if ( key === "active" ) { - // _activate() will handle invalid values and update this.options - this._activate( value ); - return; - } - - if ( key === "disabled" ) { - // don't use the widget factory's disabled handling - this._setupDisabled( value ); - return; - } - - this._super( key, value); - - if ( key === "collapsible" ) { - this.element.toggleClass( "ui-tabs-collapsible", value ); - // Setting collapsible: false while collapsed; open first panel - if ( !value && this.options.active === false ) { - this._activate( 0 ); - } - } - - if ( key === "event" ) { - this._setupEvents( value ); - } - - if ( key === "heightStyle" ) { - this._setupHeightStyle( value ); - } - }, - - _sanitizeSelector: function( hash ) { - return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : ""; - }, - - refresh: function() { - var options = this.options, - lis = this.tablist.children( ":has(a[href])" ); - - // get disabled tabs from class attribute from HTML - // this will get converted to a boolean if needed in _refresh() - options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) { - return lis.index( tab ); - }); - - this._processTabs(); - - // was collapsed or no tabs - if ( options.active === false || !this.anchors.length ) { - options.active = false; - this.active = $(); - // was active, but active tab is gone - } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) { - // all remaining tabs are disabled - if ( this.tabs.length === options.disabled.length ) { - options.active = false; - this.active = $(); - // activate previous tab - } else { - this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) ); - } - // was active, active tab still exists - } else { - // make sure active index is correct - options.active = this.tabs.index( this.active ); - } - - this._refresh(); - }, - - _refresh: function() { - this._setupDisabled( this.options.disabled ); - this._setupEvents( this.options.event ); - this._setupHeightStyle( this.options.heightStyle ); - - this.tabs.not( this.active ).attr({ - "aria-selected": "false", - "aria-expanded": "false", - tabIndex: -1 - }); - this.panels.not( this._getPanelForTab( this.active ) ) - .hide() - .attr({ - "aria-hidden": "true" - }); - - // Make sure one tab is in the tab order - if ( !this.active.length ) { - this.tabs.eq( 0 ).attr( "tabIndex", 0 ); - } else { - this.active - .addClass( "ui-tabs-active ui-state-active" ) - .attr({ - "aria-selected": "true", - "aria-expanded": "true", - tabIndex: 0 - }); - this._getPanelForTab( this.active ) - .show() - .attr({ - "aria-hidden": "false" - }); - } - }, - - _processTabs: function() { - var that = this, - prevTabs = this.tabs, - prevAnchors = this.anchors, - prevPanels = this.panels; - - this.tablist = this._getList() - .addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ) - .attr( "role", "tablist" ) - - // Prevent users from focusing disabled tabs via click - .delegate( "> li", "mousedown" + this.eventNamespace, function( event ) { - if ( $( this ).is( ".ui-state-disabled" ) ) { - event.preventDefault(); - } - }) - - // support: IE <9 - // Preventing the default action in mousedown doesn't prevent IE - // from focusing the element, so if the anchor gets focused, blur. - // We don't have to worry about focusing the previously focused - // element since clicking on a non-focusable element should focus - // the body anyway. - .delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() { - if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) { - this.blur(); - } - }); - - this.tabs = this.tablist.find( "> li:has(a[href])" ) - .addClass( "ui-state-default ui-corner-top" ) - .attr({ - role: "tab", - tabIndex: -1 - }); - - this.anchors = this.tabs.map(function() { - return $( "a", this )[ 0 ]; - }) - .addClass( "ui-tabs-anchor" ) - .attr({ - role: "presentation", - tabIndex: -1 - }); - - this.panels = $(); - - this.anchors.each(function( i, anchor ) { - var selector, panel, panelId, - anchorId = $( anchor ).uniqueId().attr( "id" ), - tab = $( anchor ).closest( "li" ), - originalAriaControls = tab.attr( "aria-controls" ); - - // inline tab - if ( that._isLocal( anchor ) ) { - selector = anchor.hash; - panelId = selector.substring( 1 ); - panel = that.element.find( that._sanitizeSelector( selector ) ); - // remote tab - } else { - // If the tab doesn't already have aria-controls, - // generate an id by using a throw-away element - panelId = tab.attr( "aria-controls" ) || $( {} ).uniqueId()[ 0 ].id; - selector = "#" + panelId; - panel = that.element.find( selector ); - if ( !panel.length ) { - panel = that._createPanel( panelId ); - panel.insertAfter( that.panels[ i - 1 ] || that.tablist ); - } - panel.attr( "aria-live", "polite" ); - } - - if ( panel.length) { - that.panels = that.panels.add( panel ); - } - if ( originalAriaControls ) { - tab.data( "ui-tabs-aria-controls", originalAriaControls ); - } - tab.attr({ - "aria-controls": panelId, - "aria-labelledby": anchorId - }); - panel.attr( "aria-labelledby", anchorId ); - }); - - this.panels - .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) - .attr( "role", "tabpanel" ); - - // Avoid memory leaks (#10056) - if ( prevTabs ) { - this._off( prevTabs.not( this.tabs ) ); - this._off( prevAnchors.not( this.anchors ) ); - this._off( prevPanels.not( this.panels ) ); - } - }, - - // allow overriding how to find the list for rare usage scenarios (#7715) - _getList: function() { - return this.tablist || this.element.find( "ol,ul" ).eq( 0 ); - }, - - _createPanel: function( id ) { - return $( "<div>" ) - .attr( "id", id ) - .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) - .data( "ui-tabs-destroy", true ); - }, - - _setupDisabled: function( disabled ) { - if ( $.isArray( disabled ) ) { - if ( !disabled.length ) { - disabled = false; - } else if ( disabled.length === this.anchors.length ) { - disabled = true; - } - } - - // disable tabs - for ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) { - if ( disabled === true || $.inArray( i, disabled ) !== -1 ) { - $( li ) - .addClass( "ui-state-disabled" ) - .attr( "aria-disabled", "true" ); - } else { - $( li ) - .removeClass( "ui-state-disabled" ) - .removeAttr( "aria-disabled" ); - } - } - - this.options.disabled = disabled; - }, - - _setupEvents: function( event ) { - var events = {}; - if ( event ) { - $.each( event.split(" "), function( index, eventName ) { - events[ eventName ] = "_eventHandler"; - }); - } - - this._off( this.anchors.add( this.tabs ).add( this.panels ) ); - // Always prevent the default action, even when disabled - this._on( true, this.anchors, { - click: function( event ) { - event.preventDefault(); - } - }); - this._on( this.anchors, events ); - this._on( this.tabs, { keydown: "_tabKeydown" } ); - this._on( this.panels, { keydown: "_panelKeydown" } ); - - this._focusable( this.tabs ); - this._hoverable( this.tabs ); - }, - - _setupHeightStyle: function( heightStyle ) { - var maxHeight, - parent = this.element.parent(); - - if ( heightStyle === "fill" ) { - maxHeight = parent.height(); - maxHeight -= this.element.outerHeight() - this.element.height(); - - this.element.siblings( ":visible" ).each(function() { - var elem = $( this ), - position = elem.css( "position" ); - - if ( position === "absolute" || position === "fixed" ) { - return; - } - maxHeight -= elem.outerHeight( true ); - }); - - this.element.children().not( this.panels ).each(function() { - maxHeight -= $( this ).outerHeight( true ); - }); - - this.panels.each(function() { - $( this ).height( Math.max( 0, maxHeight - - $( this ).innerHeight() + $( this ).height() ) ); - }) - .css( "overflow", "auto" ); - } else if ( heightStyle === "auto" ) { - maxHeight = 0; - this.panels.each(function() { - maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() ); - }).height( maxHeight ); - } - }, - - _eventHandler: function( event ) { - var options = this.options, - active = this.active, - anchor = $( event.currentTarget ), - tab = anchor.closest( "li" ), - clickedIsActive = tab[ 0 ] === active[ 0 ], - collapsing = clickedIsActive && options.collapsible, - toShow = collapsing ? $() : this._getPanelForTab( tab ), - toHide = !active.length ? $() : this._getPanelForTab( active ), - eventData = { - oldTab: active, - oldPanel: toHide, - newTab: collapsing ? $() : tab, - newPanel: toShow - }; - - event.preventDefault(); - - if ( tab.hasClass( "ui-state-disabled" ) || - // tab is already loading - tab.hasClass( "ui-tabs-loading" ) || - // can't switch durning an animation - this.running || - // click on active header, but not collapsible - ( clickedIsActive && !options.collapsible ) || - // allow canceling activation - ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { - return; - } - - options.active = collapsing ? false : this.tabs.index( tab ); - - this.active = clickedIsActive ? $() : tab; - if ( this.xhr ) { - this.xhr.abort(); - } - - if ( !toHide.length && !toShow.length ) { - $.error( "jQuery UI Tabs: Mismatching fragment identifier." ); - } - - if ( toShow.length ) { - this.load( this.tabs.index( tab ), event ); - } - this._toggle( event, eventData ); - }, - - // handles show/hide for selecting tabs - _toggle: function( event, eventData ) { - var that = this, - toShow = eventData.newPanel, - toHide = eventData.oldPanel; - - this.running = true; - - function complete() { - that.running = false; - that._trigger( "activate", event, eventData ); - } - - function show() { - eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" ); - - if ( toShow.length && that.options.show ) { - that._show( toShow, that.options.show, complete ); - } else { - toShow.show(); - complete(); - } - } - - // start out by hiding, then showing, then completing - if ( toHide.length && this.options.hide ) { - this._hide( toHide, this.options.hide, function() { - eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); - show(); - }); - } else { - eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); - toHide.hide(); - show(); - } - - toHide.attr( "aria-hidden", "true" ); - eventData.oldTab.attr({ - "aria-selected": "false", - "aria-expanded": "false" - }); - // If we're switching tabs, remove the old tab from the tab order. - // If we're opening from collapsed state, remove the previous tab from the tab order. - // If we're collapsing, then keep the collapsing tab in the tab order. - if ( toShow.length && toHide.length ) { - eventData.oldTab.attr( "tabIndex", -1 ); - } else if ( toShow.length ) { - this.tabs.filter(function() { - return $( this ).attr( "tabIndex" ) === 0; - }) - .attr( "tabIndex", -1 ); - } - - toShow.attr( "aria-hidden", "false" ); - eventData.newTab.attr({ - "aria-selected": "true", - "aria-expanded": "true", - tabIndex: 0 - }); - }, - - _activate: function( index ) { - var anchor, - active = this._findActive( index ); - - // trying to activate the already active panel - if ( active[ 0 ] === this.active[ 0 ] ) { - return; - } - - // trying to collapse, simulate a click on the current active header - if ( !active.length ) { - active = this.active; - } - - anchor = active.find( ".ui-tabs-anchor" )[ 0 ]; - this._eventHandler({ - target: anchor, - currentTarget: anchor, - preventDefault: $.noop - }); - }, - - _findActive: function( index ) { - return index === false ? $() : this.tabs.eq( index ); - }, - - _getIndex: function( index ) { - // meta-function to give users option to provide a href string instead of a numerical index. - if ( typeof index === "string" ) { - index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) ); - } - - return index; - }, - - _destroy: function() { - if ( this.xhr ) { - this.xhr.abort(); - } - - this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" ); - - this.tablist - .removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ) - .removeAttr( "role" ); - - this.anchors - .removeClass( "ui-tabs-anchor" ) - .removeAttr( "role" ) - .removeAttr( "tabIndex" ) - .removeUniqueId(); - - this.tablist.unbind( this.eventNamespace ); - - this.tabs.add( this.panels ).each(function() { - if ( $.data( this, "ui-tabs-destroy" ) ) { - $( this ).remove(); - } else { - $( this ) - .removeClass( "ui-state-default ui-state-active ui-state-disabled " + - "ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" ) - .removeAttr( "tabIndex" ) - .removeAttr( "aria-live" ) - .removeAttr( "aria-busy" ) - .removeAttr( "aria-selected" ) - .removeAttr( "aria-labelledby" ) - .removeAttr( "aria-hidden" ) - .removeAttr( "aria-expanded" ) - .removeAttr( "role" ); - } - }); - - this.tabs.each(function() { - var li = $( this ), - prev = li.data( "ui-tabs-aria-controls" ); - if ( prev ) { - li - .attr( "aria-controls", prev ) - .removeData( "ui-tabs-aria-controls" ); - } else { - li.removeAttr( "aria-controls" ); - } - }); - - this.panels.show(); - - if ( this.options.heightStyle !== "content" ) { - this.panels.css( "height", "" ); - } - }, - - enable: function( index ) { - var disabled = this.options.disabled; - if ( disabled === false ) { - return; - } - - if ( index === undefined ) { - disabled = false; - } else { - index = this._getIndex( index ); - if ( $.isArray( disabled ) ) { - disabled = $.map( disabled, function( num ) { - return num !== index ? num : null; - }); - } else { - disabled = $.map( this.tabs, function( li, num ) { - return num !== index ? num : null; - }); - } - } - this._setupDisabled( disabled ); - }, - - disable: function( index ) { - var disabled = this.options.disabled; - if ( disabled === true ) { - return; - } - - if ( index === undefined ) { - disabled = true; - } else { - index = this._getIndex( index ); - if ( $.inArray( index, disabled ) !== -1 ) { - return; - } - if ( $.isArray( disabled ) ) { - disabled = $.merge( [ index ], disabled ).sort(); - } else { - disabled = [ index ]; - } - } - this._setupDisabled( disabled ); - }, - - load: function( index, event ) { - index = this._getIndex( index ); - var that = this, - tab = this.tabs.eq( index ), - anchor = tab.find( ".ui-tabs-anchor" ), - panel = this._getPanelForTab( tab ), - eventData = { - tab: tab, - panel: panel - }, - complete = function( jqXHR, status ) { - if ( status === "abort" ) { - that.panels.stop( false, true ); - } - - tab.removeClass( "ui-tabs-loading" ); - panel.removeAttr( "aria-busy" ); - - if ( jqXHR === that.xhr ) { - delete that.xhr; - } - }; - - // not remote - if ( this._isLocal( anchor[ 0 ] ) ) { - return; - } - - this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) ); - - // support: jQuery <1.8 - // jQuery <1.8 returns false if the request is canceled in beforeSend, - // but as of 1.8, $.ajax() always returns a jqXHR object. - if ( this.xhr && this.xhr.statusText !== "canceled" ) { - tab.addClass( "ui-tabs-loading" ); - panel.attr( "aria-busy", "true" ); - - this.xhr - .done(function( response, status, jqXHR ) { - // support: jQuery <1.8 - // http://bugs.jquery.com/ticket/11778 - setTimeout(function() { - panel.html( response ); - that._trigger( "load", event, eventData ); - - complete( jqXHR, status ); - }, 1 ); - }) - .fail(function( jqXHR, status ) { - // support: jQuery <1.8 - // http://bugs.jquery.com/ticket/11778 - setTimeout(function() { - complete( jqXHR, status ); - }, 1 ); - }); - } - }, - - _ajaxSettings: function( anchor, event, eventData ) { - var that = this; - return { - url: anchor.attr( "href" ), - beforeSend: function( jqXHR, settings ) { - return that._trigger( "beforeLoad", event, - $.extend( { jqXHR: jqXHR, ajaxSettings: settings }, eventData ) ); - } - }; - }, - - _getPanelForTab: function( tab ) { - var id = $( tab ).attr( "aria-controls" ); - return this.element.find( this._sanitizeSelector( "#" + id ) ); - } -}); - - -/*! - * jQuery UI Tooltip 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/tooltip/ - */ - - -var tooltip = $.widget( "ui.tooltip", { - version: "1.11.4", - options: { - content: function() { - // support: IE<9, Opera in jQuery <1.7 - // .text() can't accept undefined, so coerce to a string - var title = $( this ).attr( "title" ) || ""; - // Escape title, since we're going from an attribute to raw HTML - return $( "<a>" ).text( title ).html(); - }, - hide: true, - // Disabled elements have inconsistent behavior across browsers (#8661) - items: "[title]:not([disabled])", - position: { - my: "left top+15", - at: "left bottom", - collision: "flipfit flip" - }, - show: true, - tooltipClass: null, - track: false, - - // callbacks - close: null, - open: null - }, - - _addDescribedBy: function( elem, id ) { - var describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ); - describedby.push( id ); - elem - .data( "ui-tooltip-id", id ) - .attr( "aria-describedby", $.trim( describedby.join( " " ) ) ); - }, - - _removeDescribedBy: function( elem ) { - var id = elem.data( "ui-tooltip-id" ), - describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ), - index = $.inArray( id, describedby ); - - if ( index !== -1 ) { - describedby.splice( index, 1 ); - } - - elem.removeData( "ui-tooltip-id" ); - describedby = $.trim( describedby.join( " " ) ); - if ( describedby ) { - elem.attr( "aria-describedby", describedby ); - } else { - elem.removeAttr( "aria-describedby" ); - } - }, - - _create: function() { - this._on({ - mouseover: "open", - focusin: "open" - }); - - // IDs of generated tooltips, needed for destroy - this.tooltips = {}; - - // IDs of parent tooltips where we removed the title attribute - this.parents = {}; - - if ( this.options.disabled ) { - this._disable(); - } - - // Append the aria-live region so tooltips announce correctly - this.liveRegion = $( "<div>" ) - .attr({ - role: "log", - "aria-live": "assertive", - "aria-relevant": "additions" - }) - .addClass( "ui-helper-hidden-accessible" ) - .appendTo( this.document[ 0 ].body ); - }, - - _setOption: function( key, value ) { - var that = this; - - if ( key === "disabled" ) { - this[ value ? "_disable" : "_enable" ](); - this.options[ key ] = value; - // disable element style changes - return; - } - - this._super( key, value ); - - if ( key === "content" ) { - $.each( this.tooltips, function( id, tooltipData ) { - that._updateContent( tooltipData.element ); - }); - } - }, - - _disable: function() { - var that = this; - - // close open tooltips - $.each( this.tooltips, function( id, tooltipData ) { - var event = $.Event( "blur" ); - event.target = event.currentTarget = tooltipData.element[ 0 ]; - that.close( event, true ); - }); - - // remove title attributes to prevent native tooltips - this.element.find( this.options.items ).addBack().each(function() { - var element = $( this ); - if ( element.is( "[title]" ) ) { - element - .data( "ui-tooltip-title", element.attr( "title" ) ) - .removeAttr( "title" ); - } - }); - }, - - _enable: function() { - // restore title attributes - this.element.find( this.options.items ).addBack().each(function() { - var element = $( this ); - if ( element.data( "ui-tooltip-title" ) ) { - element.attr( "title", element.data( "ui-tooltip-title" ) ); - } - }); - }, - - open: function( event ) { - var that = this, - target = $( event ? event.target : this.element ) - // we need closest here due to mouseover bubbling, - // but always pointing at the same event target - .closest( this.options.items ); - - // No element to show a tooltip for or the tooltip is already open - if ( !target.length || target.data( "ui-tooltip-id" ) ) { - return; - } - - if ( target.attr( "title" ) ) { - target.data( "ui-tooltip-title", target.attr( "title" ) ); - } - - target.data( "ui-tooltip-open", true ); - - // kill parent tooltips, custom or native, for hover - if ( event && event.type === "mouseover" ) { - target.parents().each(function() { - var parent = $( this ), - blurEvent; - if ( parent.data( "ui-tooltip-open" ) ) { - blurEvent = $.Event( "blur" ); - blurEvent.target = blurEvent.currentTarget = this; - that.close( blurEvent, true ); - } - if ( parent.attr( "title" ) ) { - parent.uniqueId(); - that.parents[ this.id ] = { - element: this, - title: parent.attr( "title" ) - }; - parent.attr( "title", "" ); - } - }); - } - - this._registerCloseHandlers( event, target ); - this._updateContent( target, event ); - }, - - _updateContent: function( target, event ) { - var content, - contentOption = this.options.content, - that = this, - eventType = event ? event.type : null; - - if ( typeof contentOption === "string" ) { - return this._open( event, target, contentOption ); - } - - content = contentOption.call( target[0], function( response ) { - - // IE may instantly serve a cached response for ajax requests - // delay this call to _open so the other call to _open runs first - that._delay(function() { - - // Ignore async response if tooltip was closed already - if ( !target.data( "ui-tooltip-open" ) ) { - return; - } - - // jQuery creates a special event for focusin when it doesn't - // exist natively. To improve performance, the native event - // object is reused and the type is changed. Therefore, we can't - // rely on the type being correct after the event finished - // bubbling, so we set it back to the previous value. (#8740) - if ( event ) { - event.type = eventType; - } - this._open( event, target, response ); - }); - }); - if ( content ) { - this._open( event, target, content ); - } - }, - - _open: function( event, target, content ) { - var tooltipData, tooltip, delayedShow, a11yContent, - positionOption = $.extend( {}, this.options.position ); - - if ( !content ) { - return; - } - - // Content can be updated multiple times. If the tooltip already - // exists, then just update the content and bail. - tooltipData = this._find( target ); - if ( tooltipData ) { - tooltipData.tooltip.find( ".ui-tooltip-content" ).html( content ); - return; - } - - // if we have a title, clear it to prevent the native tooltip - // we have to check first to avoid defining a title if none exists - // (we don't want to cause an element to start matching [title]) - // - // We use removeAttr only for key events, to allow IE to export the correct - // accessible attributes. For mouse events, set to empty string to avoid - // native tooltip showing up (happens only when removing inside mouseover). - if ( target.is( "[title]" ) ) { - if ( event && event.type === "mouseover" ) { - target.attr( "title", "" ); - } else { - target.removeAttr( "title" ); - } - } - - tooltipData = this._tooltip( target ); - tooltip = tooltipData.tooltip; - this._addDescribedBy( target, tooltip.attr( "id" ) ); - tooltip.find( ".ui-tooltip-content" ).html( content ); - - // Support: Voiceover on OS X, JAWS on IE <= 9 - // JAWS announces deletions even when aria-relevant="additions" - // Voiceover will sometimes re-read the entire log region's contents from the beginning - this.liveRegion.children().hide(); - if ( content.clone ) { - a11yContent = content.clone(); - a11yContent.removeAttr( "id" ).find( "[id]" ).removeAttr( "id" ); - } else { - a11yContent = content; - } - $( "<div>" ).html( a11yContent ).appendTo( this.liveRegion ); - - function position( event ) { - positionOption.of = event; - if ( tooltip.is( ":hidden" ) ) { - return; - } - tooltip.position( positionOption ); - } - if ( this.options.track && event && /^mouse/.test( event.type ) ) { - this._on( this.document, { - mousemove: position - }); - // trigger once to override element-relative positioning - position( event ); - } else { - tooltip.position( $.extend({ - of: target - }, this.options.position ) ); - } - - tooltip.hide(); - - this._show( tooltip, this.options.show ); - // Handle tracking tooltips that are shown with a delay (#8644). As soon - // as the tooltip is visible, position the tooltip using the most recent - // event. - if ( this.options.show && this.options.show.delay ) { - delayedShow = this.delayedShow = setInterval(function() { - if ( tooltip.is( ":visible" ) ) { - position( positionOption.of ); - clearInterval( delayedShow ); - } - }, $.fx.interval ); - } - - this._trigger( "open", event, { tooltip: tooltip } ); - }, - - _registerCloseHandlers: function( event, target ) { - var events = { - keyup: function( event ) { - if ( event.keyCode === $.ui.keyCode.ESCAPE ) { - var fakeEvent = $.Event(event); - fakeEvent.currentTarget = target[0]; - this.close( fakeEvent, true ); - } - } - }; - - // Only bind remove handler for delegated targets. Non-delegated - // tooltips will handle this in destroy. - if ( target[ 0 ] !== this.element[ 0 ] ) { - events.remove = function() { - this._removeTooltip( this._find( target ).tooltip ); - }; - } - - if ( !event || event.type === "mouseover" ) { - events.mouseleave = "close"; - } - if ( !event || event.type === "focusin" ) { - events.focusout = "close"; - } - this._on( true, target, events ); - }, - - close: function( event ) { - var tooltip, - that = this, - target = $( event ? event.currentTarget : this.element ), - tooltipData = this._find( target ); - - // The tooltip may already be closed - if ( !tooltipData ) { - - // We set ui-tooltip-open immediately upon open (in open()), but only set the - // additional data once there's actually content to show (in _open()). So even if the - // tooltip doesn't have full data, we always remove ui-tooltip-open in case we're in - // the period between open() and _open(). - target.removeData( "ui-tooltip-open" ); - return; - } - - tooltip = tooltipData.tooltip; - - // disabling closes the tooltip, so we need to track when we're closing - // to avoid an infinite loop in case the tooltip becomes disabled on close - if ( tooltipData.closing ) { - return; - } - - // Clear the interval for delayed tracking tooltips - clearInterval( this.delayedShow ); - - // only set title if we had one before (see comment in _open()) - // If the title attribute has changed since open(), don't restore - if ( target.data( "ui-tooltip-title" ) && !target.attr( "title" ) ) { - target.attr( "title", target.data( "ui-tooltip-title" ) ); - } - - this._removeDescribedBy( target ); - - tooltipData.hiding = true; - tooltip.stop( true ); - this._hide( tooltip, this.options.hide, function() { - that._removeTooltip( $( this ) ); - }); - - target.removeData( "ui-tooltip-open" ); - this._off( target, "mouseleave focusout keyup" ); - - // Remove 'remove' binding only on delegated targets - if ( target[ 0 ] !== this.element[ 0 ] ) { - this._off( target, "remove" ); - } - this._off( this.document, "mousemove" ); - - if ( event && event.type === "mouseleave" ) { - $.each( this.parents, function( id, parent ) { - $( parent.element ).attr( "title", parent.title ); - delete that.parents[ id ]; - }); - } - - tooltipData.closing = true; - this._trigger( "close", event, { tooltip: tooltip } ); - if ( !tooltipData.hiding ) { - tooltipData.closing = false; - } - }, - - _tooltip: function( element ) { - var tooltip = $( "<div>" ) - .attr( "role", "tooltip" ) - .addClass( "ui-tooltip ui-widget ui-corner-all ui-widget-content " + - ( this.options.tooltipClass || "" ) ), - id = tooltip.uniqueId().attr( "id" ); - - $( "<div>" ) - .addClass( "ui-tooltip-content" ) - .appendTo( tooltip ); - - tooltip.appendTo( this.document[0].body ); - - return this.tooltips[ id ] = { - element: element, - tooltip: tooltip - }; - }, - - _find: function( target ) { - var id = target.data( "ui-tooltip-id" ); - return id ? this.tooltips[ id ] : null; - }, - - _removeTooltip: function( tooltip ) { - tooltip.remove(); - delete this.tooltips[ tooltip.attr( "id" ) ]; - }, - - _destroy: function() { - var that = this; - - // close open tooltips - $.each( this.tooltips, function( id, tooltipData ) { - // Delegate to close method to handle common cleanup - var event = $.Event( "blur" ), - element = tooltipData.element; - event.target = event.currentTarget = element[ 0 ]; - that.close( event, true ); - - // Remove immediately; destroying an open tooltip doesn't use the - // hide animation - $( "#" + id ).remove(); - - // Restore the title - if ( element.data( "ui-tooltip-title" ) ) { - // If the title attribute has changed since open(), don't restore - if ( !element.attr( "title" ) ) { - element.attr( "title", element.data( "ui-tooltip-title" ) ); - } - element.removeData( "ui-tooltip-title" ); - } - }); - this.liveRegion.remove(); - } -}); - - -/*! - * jQuery UI Effects 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/category/effects-core/ - */ - - -var dataSpace = "ui-effects-", - - // Create a local jQuery because jQuery Color relies on it and the - // global may not exist with AMD and a custom build (#10199) - jQuery = $; - -$.effects = { - effect: {} -}; - -/*! - * jQuery Color Animations v2.1.2 - * https://github.com/jquery/jquery-color - * - * Copyright 2014 jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * Date: Wed Jan 16 08:47:09 2013 -0600 - */ -(function( jQuery, undefined ) { - - var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor", - - // plusequals test for += 100 -= 100 - rplusequals = /^([\-+])=\s*(\d+\.?\d*)/, - // a set of RE's that can match strings and generate color tuples. - stringParsers = [ { - re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, - parse: function( execResult ) { - return [ - execResult[ 1 ], - execResult[ 2 ], - execResult[ 3 ], - execResult[ 4 ] - ]; - } - }, { - re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, - parse: function( execResult ) { - return [ - execResult[ 1 ] * 2.55, - execResult[ 2 ] * 2.55, - execResult[ 3 ] * 2.55, - execResult[ 4 ] - ]; - } - }, { - // this regex ignores A-F because it's compared against an already lowercased string - re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/, - parse: function( execResult ) { - return [ - parseInt( execResult[ 1 ], 16 ), - parseInt( execResult[ 2 ], 16 ), - parseInt( execResult[ 3 ], 16 ) - ]; - } - }, { - // this regex ignores A-F because it's compared against an already lowercased string - re: /#([a-f0-9])([a-f0-9])([a-f0-9])/, - parse: function( execResult ) { - return [ - parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ), - parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ), - parseInt( execResult[ 3 ] + execResult[ 3 ], 16 ) - ]; - } - }, { - re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, - space: "hsla", - parse: function( execResult ) { - return [ - execResult[ 1 ], - execResult[ 2 ] / 100, - execResult[ 3 ] / 100, - execResult[ 4 ] - ]; - } - } ], - - // jQuery.Color( ) - color = jQuery.Color = function( color, green, blue, alpha ) { - return new jQuery.Color.fn.parse( color, green, blue, alpha ); - }, - spaces = { - rgba: { - props: { - red: { - idx: 0, - type: "byte" - }, - green: { - idx: 1, - type: "byte" - }, - blue: { - idx: 2, - type: "byte" - } - } - }, - - hsla: { - props: { - hue: { - idx: 0, - type: "degrees" - }, - saturation: { - idx: 1, - type: "percent" - }, - lightness: { - idx: 2, - type: "percent" - } - } - } - }, - propTypes = { - "byte": { - floor: true, - max: 255 - }, - "percent": { - max: 1 - }, - "degrees": { - mod: 360, - floor: true - } - }, - support = color.support = {}, - - // element for support tests - supportElem = jQuery( "<p>" )[ 0 ], - - // colors = jQuery.Color.names - colors, - - // local aliases of functions called often - each = jQuery.each; - -// determine rgba support immediately -supportElem.style.cssText = "background-color:rgba(1,1,1,.5)"; -support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1; - -// define cache name and alpha properties -// for rgba and hsla spaces -each( spaces, function( spaceName, space ) { - space.cache = "_" + spaceName; - space.props.alpha = { - idx: 3, - type: "percent", - def: 1 - }; -}); - -function clamp( value, prop, allowEmpty ) { - var type = propTypes[ prop.type ] || {}; - - if ( value == null ) { - return (allowEmpty || !prop.def) ? null : prop.def; - } - - // ~~ is an short way of doing floor for positive numbers - value = type.floor ? ~~value : parseFloat( value ); - - // IE will pass in empty strings as value for alpha, - // which will hit this case - if ( isNaN( value ) ) { - return prop.def; - } - - if ( type.mod ) { - // we add mod before modding to make sure that negatives values - // get converted properly: -10 -> 350 - return (value + type.mod) % type.mod; - } - - // for now all property types without mod have min and max - return 0 > value ? 0 : type.max < value ? type.max : value; -} - -function stringParse( string ) { - var inst = color(), - rgba = inst._rgba = []; - - string = string.toLowerCase(); - - each( stringParsers, function( i, parser ) { - var parsed, - match = parser.re.exec( string ), - values = match && parser.parse( match ), - spaceName = parser.space || "rgba"; - - if ( values ) { - parsed = inst[ spaceName ]( values ); - - // if this was an rgba parse the assignment might happen twice - // oh well.... - inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ]; - rgba = inst._rgba = parsed._rgba; - - // exit each( stringParsers ) here because we matched - return false; - } - }); - - // Found a stringParser that handled it - if ( rgba.length ) { - - // if this came from a parsed string, force "transparent" when alpha is 0 - // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0) - if ( rgba.join() === "0,0,0,0" ) { - jQuery.extend( rgba, colors.transparent ); - } - return inst; - } - - // named colors - return colors[ string ]; -} - -color.fn = jQuery.extend( color.prototype, { - parse: function( red, green, blue, alpha ) { - if ( red === undefined ) { - this._rgba = [ null, null, null, null ]; - return this; - } - if ( red.jquery || red.nodeType ) { - red = jQuery( red ).css( green ); - green = undefined; - } - - var inst = this, - type = jQuery.type( red ), - rgba = this._rgba = []; - - // more than 1 argument specified - assume ( red, green, blue, alpha ) - if ( green !== undefined ) { - red = [ red, green, blue, alpha ]; - type = "array"; - } - - if ( type === "string" ) { - return this.parse( stringParse( red ) || colors._default ); - } - - if ( type === "array" ) { - each( spaces.rgba.props, function( key, prop ) { - rgba[ prop.idx ] = clamp( red[ prop.idx ], prop ); - }); - return this; - } - - if ( type === "object" ) { - if ( red instanceof color ) { - each( spaces, function( spaceName, space ) { - if ( red[ space.cache ] ) { - inst[ space.cache ] = red[ space.cache ].slice(); - } - }); - } else { - each( spaces, function( spaceName, space ) { - var cache = space.cache; - each( space.props, function( key, prop ) { - - // if the cache doesn't exist, and we know how to convert - if ( !inst[ cache ] && space.to ) { - - // if the value was null, we don't need to copy it - // if the key was alpha, we don't need to copy it either - if ( key === "alpha" || red[ key ] == null ) { - return; - } - inst[ cache ] = space.to( inst._rgba ); - } - - // this is the only case where we allow nulls for ALL properties. - // call clamp with alwaysAllowEmpty - inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true ); - }); - - // everything defined but alpha? - if ( inst[ cache ] && jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) { - // use the default of 1 - inst[ cache ][ 3 ] = 1; - if ( space.from ) { - inst._rgba = space.from( inst[ cache ] ); - } - } - }); - } - return this; - } - }, - is: function( compare ) { - var is = color( compare ), - same = true, - inst = this; - - each( spaces, function( _, space ) { - var localCache, - isCache = is[ space.cache ]; - if (isCache) { - localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || []; - each( space.props, function( _, prop ) { - if ( isCache[ prop.idx ] != null ) { - same = ( isCache[ prop.idx ] === localCache[ prop.idx ] ); - return same; - } - }); - } - return same; - }); - return same; - }, - _space: function() { - var used = [], - inst = this; - each( spaces, function( spaceName, space ) { - if ( inst[ space.cache ] ) { - used.push( spaceName ); - } - }); - return used.pop(); - }, - transition: function( other, distance ) { - var end = color( other ), - spaceName = end._space(), - space = spaces[ spaceName ], - startColor = this.alpha() === 0 ? color( "transparent" ) : this, - start = startColor[ space.cache ] || space.to( startColor._rgba ), - result = start.slice(); - - end = end[ space.cache ]; - each( space.props, function( key, prop ) { - var index = prop.idx, - startValue = start[ index ], - endValue = end[ index ], - type = propTypes[ prop.type ] || {}; - - // if null, don't override start value - if ( endValue === null ) { - return; - } - // if null - use end - if ( startValue === null ) { - result[ index ] = endValue; - } else { - if ( type.mod ) { - if ( endValue - startValue > type.mod / 2 ) { - startValue += type.mod; - } else if ( startValue - endValue > type.mod / 2 ) { - startValue -= type.mod; - } - } - result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop ); - } - }); - return this[ spaceName ]( result ); - }, - blend: function( opaque ) { - // if we are already opaque - return ourself - if ( this._rgba[ 3 ] === 1 ) { - return this; - } - - var rgb = this._rgba.slice(), - a = rgb.pop(), - blend = color( opaque )._rgba; - - return color( jQuery.map( rgb, function( v, i ) { - return ( 1 - a ) * blend[ i ] + a * v; - })); - }, - toRgbaString: function() { - var prefix = "rgba(", - rgba = jQuery.map( this._rgba, function( v, i ) { - return v == null ? ( i > 2 ? 1 : 0 ) : v; - }); - - if ( rgba[ 3 ] === 1 ) { - rgba.pop(); - prefix = "rgb("; - } - - return prefix + rgba.join() + ")"; - }, - toHslaString: function() { - var prefix = "hsla(", - hsla = jQuery.map( this.hsla(), function( v, i ) { - if ( v == null ) { - v = i > 2 ? 1 : 0; - } - - // catch 1 and 2 - if ( i && i < 3 ) { - v = Math.round( v * 100 ) + "%"; - } - return v; - }); - - if ( hsla[ 3 ] === 1 ) { - hsla.pop(); - prefix = "hsl("; - } - return prefix + hsla.join() + ")"; - }, - toHexString: function( includeAlpha ) { - var rgba = this._rgba.slice(), - alpha = rgba.pop(); - - if ( includeAlpha ) { - rgba.push( ~~( alpha * 255 ) ); - } - - return "#" + jQuery.map( rgba, function( v ) { - - // default to 0 when nulls exist - v = ( v || 0 ).toString( 16 ); - return v.length === 1 ? "0" + v : v; - }).join(""); - }, - toString: function() { - return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString(); - } -}); -color.fn.parse.prototype = color.fn; - -// hsla conversions adapted from: -// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021 - -function hue2rgb( p, q, h ) { - h = ( h + 1 ) % 1; - if ( h * 6 < 1 ) { - return p + ( q - p ) * h * 6; - } - if ( h * 2 < 1) { - return q; - } - if ( h * 3 < 2 ) { - return p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6; - } - return p; -} - -spaces.hsla.to = function( rgba ) { - if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) { - return [ null, null, null, rgba[ 3 ] ]; - } - var r = rgba[ 0 ] / 255, - g = rgba[ 1 ] / 255, - b = rgba[ 2 ] / 255, - a = rgba[ 3 ], - max = Math.max( r, g, b ), - min = Math.min( r, g, b ), - diff = max - min, - add = max + min, - l = add * 0.5, - h, s; - - if ( min === max ) { - h = 0; - } else if ( r === max ) { - h = ( 60 * ( g - b ) / diff ) + 360; - } else if ( g === max ) { - h = ( 60 * ( b - r ) / diff ) + 120; - } else { - h = ( 60 * ( r - g ) / diff ) + 240; - } - - // chroma (diff) == 0 means greyscale which, by definition, saturation = 0% - // otherwise, saturation is based on the ratio of chroma (diff) to lightness (add) - if ( diff === 0 ) { - s = 0; - } else if ( l <= 0.5 ) { - s = diff / add; - } else { - s = diff / ( 2 - add ); - } - return [ Math.round(h) % 360, s, l, a == null ? 1 : a ]; -}; - -spaces.hsla.from = function( hsla ) { - if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) { - return [ null, null, null, hsla[ 3 ] ]; - } - var h = hsla[ 0 ] / 360, - s = hsla[ 1 ], - l = hsla[ 2 ], - a = hsla[ 3 ], - q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s, - p = 2 * l - q; - - return [ - Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ), - Math.round( hue2rgb( p, q, h ) * 255 ), - Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ), - a - ]; -}; - -each( spaces, function( spaceName, space ) { - var props = space.props, - cache = space.cache, - to = space.to, - from = space.from; - - // makes rgba() and hsla() - color.fn[ spaceName ] = function( value ) { - - // generate a cache for this space if it doesn't exist - if ( to && !this[ cache ] ) { - this[ cache ] = to( this._rgba ); - } - if ( value === undefined ) { - return this[ cache ].slice(); - } - - var ret, - type = jQuery.type( value ), - arr = ( type === "array" || type === "object" ) ? value : arguments, - local = this[ cache ].slice(); - - each( props, function( key, prop ) { - var val = arr[ type === "object" ? key : prop.idx ]; - if ( val == null ) { - val = local[ prop.idx ]; - } - local[ prop.idx ] = clamp( val, prop ); - }); - - if ( from ) { - ret = color( from( local ) ); - ret[ cache ] = local; - return ret; - } else { - return color( local ); - } - }; - - // makes red() green() blue() alpha() hue() saturation() lightness() - each( props, function( key, prop ) { - // alpha is included in more than one space - if ( color.fn[ key ] ) { - return; - } - color.fn[ key ] = function( value ) { - var vtype = jQuery.type( value ), - fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ), - local = this[ fn ](), - cur = local[ prop.idx ], - match; - - if ( vtype === "undefined" ) { - return cur; - } - - if ( vtype === "function" ) { - value = value.call( this, cur ); - vtype = jQuery.type( value ); - } - if ( value == null && prop.empty ) { - return this; - } - if ( vtype === "string" ) { - match = rplusequals.exec( value ); - if ( match ) { - value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 ); - } - } - local[ prop.idx ] = value; - return this[ fn ]( local ); - }; - }); -}); - -// add cssHook and .fx.step function for each named hook. -// accept a space separated string of properties -color.hook = function( hook ) { - var hooks = hook.split( " " ); - each( hooks, function( i, hook ) { - jQuery.cssHooks[ hook ] = { - set: function( elem, value ) { - var parsed, curElem, - backgroundColor = ""; - - if ( value !== "transparent" && ( jQuery.type( value ) !== "string" || ( parsed = stringParse( value ) ) ) ) { - value = color( parsed || value ); - if ( !support.rgba && value._rgba[ 3 ] !== 1 ) { - curElem = hook === "backgroundColor" ? elem.parentNode : elem; - while ( - (backgroundColor === "" || backgroundColor === "transparent") && - curElem && curElem.style - ) { - try { - backgroundColor = jQuery.css( curElem, "backgroundColor" ); - curElem = curElem.parentNode; - } catch ( e ) { - } - } - - value = value.blend( backgroundColor && backgroundColor !== "transparent" ? - backgroundColor : - "_default" ); - } - - value = value.toRgbaString(); - } - try { - elem.style[ hook ] = value; - } catch ( e ) { - // wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit' - } - } - }; - jQuery.fx.step[ hook ] = function( fx ) { - if ( !fx.colorInit ) { - fx.start = color( fx.elem, hook ); - fx.end = color( fx.end ); - fx.colorInit = true; - } - jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) ); - }; - }); - -}; - -color.hook( stepHooks ); - -jQuery.cssHooks.borderColor = { - expand: function( value ) { - var expanded = {}; - - each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) { - expanded[ "border" + part + "Color" ] = value; - }); - return expanded; - } -}; - -// Basic color names only. -// Usage of any of the other color names requires adding yourself or including -// jquery.color.svg-names.js. -colors = jQuery.Color.names = { - // 4.1. Basic color keywords - aqua: "#00ffff", - black: "#000000", - blue: "#0000ff", - fuchsia: "#ff00ff", - gray: "#808080", - green: "#008000", - lime: "#00ff00", - maroon: "#800000", - navy: "#000080", - olive: "#808000", - purple: "#800080", - red: "#ff0000", - silver: "#c0c0c0", - teal: "#008080", - white: "#ffffff", - yellow: "#ffff00", - - // 4.2.3. "transparent" color keyword - transparent: [ null, null, null, 0 ], - - _default: "#ffffff" -}; - -})( jQuery ); - -/******************************************************************************/ -/****************************** CLASS ANIMATIONS ******************************/ -/******************************************************************************/ -(function() { - -var classAnimationActions = [ "add", "remove", "toggle" ], - shorthandStyles = { - border: 1, - borderBottom: 1, - borderColor: 1, - borderLeft: 1, - borderRight: 1, - borderTop: 1, - borderWidth: 1, - margin: 1, - padding: 1 - }; - -$.each([ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], function( _, prop ) { - $.fx.step[ prop ] = function( fx ) { - if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) { - jQuery.style( fx.elem, prop, fx.end ); - fx.setAttr = true; - } - }; -}); - -function getElementStyles( elem ) { - var key, len, - style = elem.ownerDocument.defaultView ? - elem.ownerDocument.defaultView.getComputedStyle( elem, null ) : - elem.currentStyle, - styles = {}; - - if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) { - len = style.length; - while ( len-- ) { - key = style[ len ]; - if ( typeof style[ key ] === "string" ) { - styles[ $.camelCase( key ) ] = style[ key ]; - } - } - // support: Opera, IE <9 - } else { - for ( key in style ) { - if ( typeof style[ key ] === "string" ) { - styles[ key ] = style[ key ]; - } - } - } - - return styles; -} - -function styleDifference( oldStyle, newStyle ) { - var diff = {}, - name, value; - - for ( name in newStyle ) { - value = newStyle[ name ]; - if ( oldStyle[ name ] !== value ) { - if ( !shorthandStyles[ name ] ) { - if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) { - diff[ name ] = value; - } - } - } - } - - return diff; -} - -// support: jQuery <1.8 -if ( !$.fn.addBack ) { - $.fn.addBack = function( selector ) { - return this.add( selector == null ? - this.prevObject : this.prevObject.filter( selector ) - ); - }; -} - -$.effects.animateClass = function( value, duration, easing, callback ) { - var o = $.speed( duration, easing, callback ); - - return this.queue( function() { - var animated = $( this ), - baseClass = animated.attr( "class" ) || "", - applyClassChange, - allAnimations = o.children ? animated.find( "*" ).addBack() : animated; - - // map the animated objects to store the original styles. - allAnimations = allAnimations.map(function() { - var el = $( this ); - return { - el: el, - start: getElementStyles( this ) - }; - }); - - // apply class change - applyClassChange = function() { - $.each( classAnimationActions, function(i, action) { - if ( value[ action ] ) { - animated[ action + "Class" ]( value[ action ] ); - } - }); - }; - applyClassChange(); - - // map all animated objects again - calculate new styles and diff - allAnimations = allAnimations.map(function() { - this.end = getElementStyles( this.el[ 0 ] ); - this.diff = styleDifference( this.start, this.end ); - return this; - }); - - // apply original class - animated.attr( "class", baseClass ); - - // map all animated objects again - this time collecting a promise - allAnimations = allAnimations.map(function() { - var styleInfo = this, - dfd = $.Deferred(), - opts = $.extend({}, o, { - queue: false, - complete: function() { - dfd.resolve( styleInfo ); - } - }); - - this.el.animate( this.diff, opts ); - return dfd.promise(); - }); - - // once all animations have completed: - $.when.apply( $, allAnimations.get() ).done(function() { - - // set the final class - applyClassChange(); - - // for each animated element, - // clear all css properties that were animated - $.each( arguments, function() { - var el = this.el; - $.each( this.diff, function(key) { - el.css( key, "" ); - }); - }); - - // this is guarnteed to be there if you use jQuery.speed() - // it also handles dequeuing the next anim... - o.complete.call( animated[ 0 ] ); - }); - }); -}; - -$.fn.extend({ - addClass: (function( orig ) { - return function( classNames, speed, easing, callback ) { - return speed ? - $.effects.animateClass.call( this, - { add: classNames }, speed, easing, callback ) : - orig.apply( this, arguments ); - }; - })( $.fn.addClass ), - - removeClass: (function( orig ) { - return function( classNames, speed, easing, callback ) { - return arguments.length > 1 ? - $.effects.animateClass.call( this, - { remove: classNames }, speed, easing, callback ) : - orig.apply( this, arguments ); - }; - })( $.fn.removeClass ), - - toggleClass: (function( orig ) { - return function( classNames, force, speed, easing, callback ) { - if ( typeof force === "boolean" || force === undefined ) { - if ( !speed ) { - // without speed parameter - return orig.apply( this, arguments ); - } else { - return $.effects.animateClass.call( this, - (force ? { add: classNames } : { remove: classNames }), - speed, easing, callback ); - } - } else { - // without force parameter - return $.effects.animateClass.call( this, - { toggle: classNames }, force, speed, easing ); - } - }; - })( $.fn.toggleClass ), - - switchClass: function( remove, add, speed, easing, callback) { - return $.effects.animateClass.call( this, { - add: add, - remove: remove - }, speed, easing, callback ); - } -}); - -})(); - -/******************************************************************************/ -/*********************************** EFFECTS **********************************/ -/******************************************************************************/ - -(function() { - -$.extend( $.effects, { - version: "1.11.4", - - // Saves a set of properties in a data storage - save: function( element, set ) { - for ( var i = 0; i < set.length; i++ ) { - if ( set[ i ] !== null ) { - element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] ); - } - } - }, - - // Restores a set of previously saved properties from a data storage - restore: function( element, set ) { - var val, i; - for ( i = 0; i < set.length; i++ ) { - if ( set[ i ] !== null ) { - val = element.data( dataSpace + set[ i ] ); - // support: jQuery 1.6.2 - // http://bugs.jquery.com/ticket/9917 - // jQuery 1.6.2 incorrectly returns undefined for any falsy value. - // We can't differentiate between "" and 0 here, so we just assume - // empty string since it's likely to be a more common value... - if ( val === undefined ) { - val = ""; - } - element.css( set[ i ], val ); - } - } - }, - - setMode: function( el, mode ) { - if (mode === "toggle") { - mode = el.is( ":hidden" ) ? "show" : "hide"; - } - return mode; - }, - - // Translates a [top,left] array into a baseline value - // this should be a little more flexible in the future to handle a string & hash - getBaseline: function( origin, original ) { - var y, x; - switch ( origin[ 0 ] ) { - case "top": y = 0; break; - case "middle": y = 0.5; break; - case "bottom": y = 1; break; - default: y = origin[ 0 ] / original.height; - } - switch ( origin[ 1 ] ) { - case "left": x = 0; break; - case "center": x = 0.5; break; - case "right": x = 1; break; - default: x = origin[ 1 ] / original.width; - } - return { - x: x, - y: y - }; - }, - - // Wraps the element around a wrapper that copies position properties - createWrapper: function( element ) { - - // if the element is already wrapped, return it - if ( element.parent().is( ".ui-effects-wrapper" )) { - return element.parent(); - } - - // wrap the element - var props = { - width: element.outerWidth(true), - height: element.outerHeight(true), - "float": element.css( "float" ) - }, - wrapper = $( "<div></div>" ) - .addClass( "ui-effects-wrapper" ) - .css({ - fontSize: "100%", - background: "transparent", - border: "none", - margin: 0, - padding: 0 - }), - // Store the size in case width/height are defined in % - Fixes #5245 - size = { - width: element.width(), - height: element.height() - }, - active = document.activeElement; - - // support: Firefox - // Firefox incorrectly exposes anonymous content - // https://bugzilla.mozilla.org/show_bug.cgi?id=561664 - try { - active.id; - } catch ( e ) { - active = document.body; - } - - element.wrap( wrapper ); - - // Fixes #7595 - Elements lose focus when wrapped. - if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { - $( active ).focus(); - } - - wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually lose the reference to the wrapped element - - // transfer positioning properties to the wrapper - if ( element.css( "position" ) === "static" ) { - wrapper.css({ position: "relative" }); - element.css({ position: "relative" }); - } else { - $.extend( props, { - position: element.css( "position" ), - zIndex: element.css( "z-index" ) - }); - $.each([ "top", "left", "bottom", "right" ], function(i, pos) { - props[ pos ] = element.css( pos ); - if ( isNaN( parseInt( props[ pos ], 10 ) ) ) { - props[ pos ] = "auto"; - } - }); - element.css({ - position: "relative", - top: 0, - left: 0, - right: "auto", - bottom: "auto" - }); - } - element.css(size); - - return wrapper.css( props ).show(); - }, - - removeWrapper: function( element ) { - var active = document.activeElement; - - if ( element.parent().is( ".ui-effects-wrapper" ) ) { - element.parent().replaceWith( element ); - - // Fixes #7595 - Elements lose focus when wrapped. - if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { - $( active ).focus(); - } - } - - return element; - }, - - setTransition: function( element, list, factor, value ) { - value = value || {}; - $.each( list, function( i, x ) { - var unit = element.cssUnit( x ); - if ( unit[ 0 ] > 0 ) { - value[ x ] = unit[ 0 ] * factor + unit[ 1 ]; - } - }); - return value; - } -}); - -// return an effect options object for the given parameters: -function _normalizeArguments( effect, options, speed, callback ) { - - // allow passing all options as the first parameter - if ( $.isPlainObject( effect ) ) { - options = effect; - effect = effect.effect; - } - - // convert to an object - effect = { effect: effect }; - - // catch (effect, null, ...) - if ( options == null ) { - options = {}; - } - - // catch (effect, callback) - if ( $.isFunction( options ) ) { - callback = options; - speed = null; - options = {}; - } - - // catch (effect, speed, ?) - if ( typeof options === "number" || $.fx.speeds[ options ] ) { - callback = speed; - speed = options; - options = {}; - } - - // catch (effect, options, callback) - if ( $.isFunction( speed ) ) { - callback = speed; - speed = null; - } - - // add options to effect - if ( options ) { - $.extend( effect, options ); - } - - speed = speed || options.duration; - effect.duration = $.fx.off ? 0 : - typeof speed === "number" ? speed : - speed in $.fx.speeds ? $.fx.speeds[ speed ] : - $.fx.speeds._default; - - effect.complete = callback || options.complete; - - return effect; -} - -function standardAnimationOption( option ) { - // Valid standard speeds (nothing, number, named speed) - if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) { - return true; - } - - // Invalid strings - treat as "normal" speed - if ( typeof option === "string" && !$.effects.effect[ option ] ) { - return true; - } - - // Complete callback - if ( $.isFunction( option ) ) { - return true; - } - - // Options hash (but not naming an effect) - if ( typeof option === "object" && !option.effect ) { - return true; - } - - // Didn't match any standard API - return false; -} - -$.fn.extend({ - effect: function( /* effect, options, speed, callback */ ) { - var args = _normalizeArguments.apply( this, arguments ), - mode = args.mode, - queue = args.queue, - effectMethod = $.effects.effect[ args.effect ]; - - if ( $.fx.off || !effectMethod ) { - // delegate to the original method (e.g., .show()) if possible - if ( mode ) { - return this[ mode ]( args.duration, args.complete ); - } else { - return this.each( function() { - if ( args.complete ) { - args.complete.call( this ); - } - }); - } - } - - function run( next ) { - var elem = $( this ), - complete = args.complete, - mode = args.mode; - - function done() { - if ( $.isFunction( complete ) ) { - complete.call( elem[0] ); - } - if ( $.isFunction( next ) ) { - next(); - } - } - - // If the element already has the correct final state, delegate to - // the core methods so the internal tracking of "olddisplay" works. - if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) { - elem[ mode ](); - done(); - } else { - effectMethod.call( elem[0], args, done ); - } - } - - return queue === false ? this.each( run ) : this.queue( queue || "fx", run ); - }, - - show: (function( orig ) { - return function( option ) { - if ( standardAnimationOption( option ) ) { - return orig.apply( this, arguments ); - } else { - var args = _normalizeArguments.apply( this, arguments ); - args.mode = "show"; - return this.effect.call( this, args ); - } - }; - })( $.fn.show ), - - hide: (function( orig ) { - return function( option ) { - if ( standardAnimationOption( option ) ) { - return orig.apply( this, arguments ); - } else { - var args = _normalizeArguments.apply( this, arguments ); - args.mode = "hide"; - return this.effect.call( this, args ); - } - }; - })( $.fn.hide ), - - toggle: (function( orig ) { - return function( option ) { - if ( standardAnimationOption( option ) || typeof option === "boolean" ) { - return orig.apply( this, arguments ); - } else { - var args = _normalizeArguments.apply( this, arguments ); - args.mode = "toggle"; - return this.effect.call( this, args ); - } - }; - })( $.fn.toggle ), - - // helper functions - cssUnit: function(key) { - var style = this.css( key ), - val = []; - - $.each( [ "em", "px", "%", "pt" ], function( i, unit ) { - if ( style.indexOf( unit ) > 0 ) { - val = [ parseFloat( style ), unit ]; - } - }); - return val; - } -}); - -})(); - -/******************************************************************************/ -/*********************************** EASING ***********************************/ -/******************************************************************************/ - -(function() { - -// based on easing equations from Robert Penner (http://www.robertpenner.com/easing) - -var baseEasings = {}; - -$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) { - baseEasings[ name ] = function( p ) { - return Math.pow( p, i + 2 ); - }; -}); - -$.extend( baseEasings, { - Sine: function( p ) { - return 1 - Math.cos( p * Math.PI / 2 ); - }, - Circ: function( p ) { - return 1 - Math.sqrt( 1 - p * p ); - }, - Elastic: function( p ) { - return p === 0 || p === 1 ? p : - -Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 ); - }, - Back: function( p ) { - return p * p * ( 3 * p - 2 ); - }, - Bounce: function( p ) { - var pow2, - bounce = 4; - - while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {} - return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 ); - } -}); - -$.each( baseEasings, function( name, easeIn ) { - $.easing[ "easeIn" + name ] = easeIn; - $.easing[ "easeOut" + name ] = function( p ) { - return 1 - easeIn( 1 - p ); - }; - $.easing[ "easeInOut" + name ] = function( p ) { - return p < 0.5 ? - easeIn( p * 2 ) / 2 : - 1 - easeIn( p * -2 + 2 ) / 2; - }; -}); - -})(); - -var effect = $.effects; - - -/*! - * jQuery UI Effects Blind 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/blind-effect/ - */ - - -var effectBlind = $.effects.effect.blind = function( o, done ) { - // Create element - var el = $( this ), - rvertical = /up|down|vertical/, - rpositivemotion = /up|left|vertical|horizontal/, - props = [ "position", "top", "bottom", "left", "right", "height", "width" ], - mode = $.effects.setMode( el, o.mode || "hide" ), - direction = o.direction || "up", - vertical = rvertical.test( direction ), - ref = vertical ? "height" : "width", - ref2 = vertical ? "top" : "left", - motion = rpositivemotion.test( direction ), - animation = {}, - show = mode === "show", - wrapper, distance, margin; - - // if already wrapped, the wrapper's properties are my property. #6245 - if ( el.parent().is( ".ui-effects-wrapper" ) ) { - $.effects.save( el.parent(), props ); - } else { - $.effects.save( el, props ); - } - el.show(); - wrapper = $.effects.createWrapper( el ).css({ - overflow: "hidden" - }); - - distance = wrapper[ ref ](); - margin = parseFloat( wrapper.css( ref2 ) ) || 0; - - animation[ ref ] = show ? distance : 0; - if ( !motion ) { - el - .css( vertical ? "bottom" : "right", 0 ) - .css( vertical ? "top" : "left", "auto" ) - .css({ position: "absolute" }); - - animation[ ref2 ] = show ? margin : distance + margin; - } - - // start at 0 if we are showing - if ( show ) { - wrapper.css( ref, 0 ); - if ( !motion ) { - wrapper.css( ref2, margin + distance ); - } - } - - // Animate - wrapper.animate( animation, { - duration: o.duration, - easing: o.easing, - queue: false, - complete: function() { - if ( mode === "hide" ) { - el.hide(); - } - $.effects.restore( el, props ); - $.effects.removeWrapper( el ); - done(); - } - }); -}; - - -/*! - * jQuery UI Effects Bounce 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/bounce-effect/ - */ - - -var effectBounce = $.effects.effect.bounce = function( o, done ) { - var el = $( this ), - props = [ "position", "top", "bottom", "left", "right", "height", "width" ], - - // defaults: - mode = $.effects.setMode( el, o.mode || "effect" ), - hide = mode === "hide", - show = mode === "show", - direction = o.direction || "up", - distance = o.distance, - times = o.times || 5, - - // number of internal animations - anims = times * 2 + ( show || hide ? 1 : 0 ), - speed = o.duration / anims, - easing = o.easing, - - // utility: - ref = ( direction === "up" || direction === "down" ) ? "top" : "left", - motion = ( direction === "up" || direction === "left" ), - i, - upAnim, - downAnim, - - // we will need to re-assemble the queue to stack our animations in place - queue = el.queue(), - queuelen = queue.length; - - // Avoid touching opacity to prevent clearType and PNG issues in IE - if ( show || hide ) { - props.push( "opacity" ); - } - - $.effects.save( el, props ); - el.show(); - $.effects.createWrapper( el ); // Create Wrapper - - // default distance for the BIGGEST bounce is the outer Distance / 3 - if ( !distance ) { - distance = el[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3; - } - - if ( show ) { - downAnim = { opacity: 1 }; - downAnim[ ref ] = 0; - - // if we are showing, force opacity 0 and set the initial position - // then do the "first" animation - el.css( "opacity", 0 ) - .css( ref, motion ? -distance * 2 : distance * 2 ) - .animate( downAnim, speed, easing ); - } - - // start at the smallest distance if we are hiding - if ( hide ) { - distance = distance / Math.pow( 2, times - 1 ); - } - - downAnim = {}; - downAnim[ ref ] = 0; - // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here - for ( i = 0; i < times; i++ ) { - upAnim = {}; - upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; - - el.animate( upAnim, speed, easing ) - .animate( downAnim, speed, easing ); - - distance = hide ? distance * 2 : distance / 2; - } - - // Last Bounce when Hiding - if ( hide ) { - upAnim = { opacity: 0 }; - upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; - - el.animate( upAnim, speed, easing ); - } - - el.queue(function() { - if ( hide ) { - el.hide(); - } - $.effects.restore( el, props ); - $.effects.removeWrapper( el ); - done(); - }); - - // inject all the animations we just queued to be first in line (after "inprogress") - if ( queuelen > 1) { - queue.splice.apply( queue, - [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); - } - el.dequeue(); - -}; - - -/*! - * jQuery UI Effects Clip 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/clip-effect/ - */ - - -var effectClip = $.effects.effect.clip = function( o, done ) { - // Create element - var el = $( this ), - props = [ "position", "top", "bottom", "left", "right", "height", "width" ], - mode = $.effects.setMode( el, o.mode || "hide" ), - show = mode === "show", - direction = o.direction || "vertical", - vert = direction === "vertical", - size = vert ? "height" : "width", - position = vert ? "top" : "left", - animation = {}, - wrapper, animate, distance; - - // Save & Show - $.effects.save( el, props ); - el.show(); - - // Create Wrapper - wrapper = $.effects.createWrapper( el ).css({ - overflow: "hidden" - }); - animate = ( el[0].tagName === "IMG" ) ? wrapper : el; - distance = animate[ size ](); - - // Shift - if ( show ) { - animate.css( size, 0 ); - animate.css( position, distance / 2 ); - } - - // Create Animation Object: - animation[ size ] = show ? distance : 0; - animation[ position ] = show ? 0 : distance / 2; - - // Animate - animate.animate( animation, { - queue: false, - duration: o.duration, - easing: o.easing, - complete: function() { - if ( !show ) { - el.hide(); - } - $.effects.restore( el, props ); - $.effects.removeWrapper( el ); - done(); - } - }); - -}; - - -/*! - * jQuery UI Effects Drop 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/drop-effect/ - */ - - -var effectDrop = $.effects.effect.drop = function( o, done ) { - - var el = $( this ), - props = [ "position", "top", "bottom", "left", "right", "opacity", "height", "width" ], - mode = $.effects.setMode( el, o.mode || "hide" ), - show = mode === "show", - direction = o.direction || "left", - ref = ( direction === "up" || direction === "down" ) ? "top" : "left", - motion = ( direction === "up" || direction === "left" ) ? "pos" : "neg", - animation = { - opacity: show ? 1 : 0 - }, - distance; - - // Adjust - $.effects.save( el, props ); - el.show(); - $.effects.createWrapper( el ); - - distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ) / 2; - - if ( show ) { - el - .css( "opacity", 0 ) - .css( ref, motion === "pos" ? -distance : distance ); - } - - // Animation - animation[ ref ] = ( show ? - ( motion === "pos" ? "+=" : "-=" ) : - ( motion === "pos" ? "-=" : "+=" ) ) + - distance; - - // Animate - el.animate( animation, { - queue: false, - duration: o.duration, - easing: o.easing, - complete: function() { - if ( mode === "hide" ) { - el.hide(); - } - $.effects.restore( el, props ); - $.effects.removeWrapper( el ); - done(); - } - }); -}; - - -/*! - * jQuery UI Effects Explode 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/explode-effect/ - */ - - -var effectExplode = $.effects.effect.explode = function( o, done ) { - - var rows = o.pieces ? Math.round( Math.sqrt( o.pieces ) ) : 3, - cells = rows, - el = $( this ), - mode = $.effects.setMode( el, o.mode || "hide" ), - show = mode === "show", - - // show and then visibility:hidden the element before calculating offset - offset = el.show().css( "visibility", "hidden" ).offset(), - - // width and height of a piece - width = Math.ceil( el.outerWidth() / cells ), - height = Math.ceil( el.outerHeight() / rows ), - pieces = [], - - // loop - i, j, left, top, mx, my; - - // children animate complete: - function childComplete() { - pieces.push( this ); - if ( pieces.length === rows * cells ) { - animComplete(); - } - } - - // clone the element for each row and cell. - for ( i = 0; i < rows ; i++ ) { // ===> - top = offset.top + i * height; - my = i - ( rows - 1 ) / 2 ; - - for ( j = 0; j < cells ; j++ ) { // ||| - left = offset.left + j * width; - mx = j - ( cells - 1 ) / 2 ; - - // Create a clone of the now hidden main element that will be absolute positioned - // within a wrapper div off the -left and -top equal to size of our pieces - el - .clone() - .appendTo( "body" ) - .wrap( "<div></div>" ) - .css({ - position: "absolute", - visibility: "visible", - left: -j * width, - top: -i * height - }) - - // select the wrapper - make it overflow: hidden and absolute positioned based on - // where the original was located +left and +top equal to the size of pieces - .parent() - .addClass( "ui-effects-explode" ) - .css({ - position: "absolute", - overflow: "hidden", - width: width, - height: height, - left: left + ( show ? mx * width : 0 ), - top: top + ( show ? my * height : 0 ), - opacity: show ? 0 : 1 - }).animate({ - left: left + ( show ? 0 : mx * width ), - top: top + ( show ? 0 : my * height ), - opacity: show ? 1 : 0 - }, o.duration || 500, o.easing, childComplete ); - } - } - - function animComplete() { - el.css({ - visibility: "visible" - }); - $( pieces ).remove(); - if ( !show ) { - el.hide(); - } - done(); - } -}; - - -/*! - * jQuery UI Effects Fade 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/fade-effect/ - */ - - -var effectFade = $.effects.effect.fade = function( o, done ) { - var el = $( this ), - mode = $.effects.setMode( el, o.mode || "toggle" ); - - el.animate({ - opacity: mode - }, { - queue: false, - duration: o.duration, - easing: o.easing, - complete: done - }); -}; - - -/*! - * jQuery UI Effects Fold 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/fold-effect/ - */ - - -var effectFold = $.effects.effect.fold = function( o, done ) { - - // Create element - var el = $( this ), - props = [ "position", "top", "bottom", "left", "right", "height", "width" ], - mode = $.effects.setMode( el, o.mode || "hide" ), - show = mode === "show", - hide = mode === "hide", - size = o.size || 15, - percent = /([0-9]+)%/.exec( size ), - horizFirst = !!o.horizFirst, - widthFirst = show !== horizFirst, - ref = widthFirst ? [ "width", "height" ] : [ "height", "width" ], - duration = o.duration / 2, - wrapper, distance, - animation1 = {}, - animation2 = {}; - - $.effects.save( el, props ); - el.show(); - - // Create Wrapper - wrapper = $.effects.createWrapper( el ).css({ - overflow: "hidden" - }); - distance = widthFirst ? - [ wrapper.width(), wrapper.height() ] : - [ wrapper.height(), wrapper.width() ]; - - if ( percent ) { - size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ]; - } - if ( show ) { - wrapper.css( horizFirst ? { - height: 0, - width: size - } : { - height: size, - width: 0 - }); - } - - // Animation - animation1[ ref[ 0 ] ] = show ? distance[ 0 ] : size; - animation2[ ref[ 1 ] ] = show ? distance[ 1 ] : 0; - - // Animate - wrapper - .animate( animation1, duration, o.easing ) - .animate( animation2, duration, o.easing, function() { - if ( hide ) { - el.hide(); - } - $.effects.restore( el, props ); - $.effects.removeWrapper( el ); - done(); - }); - -}; - - -/*! - * jQuery UI Effects Highlight 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/highlight-effect/ - */ - - -var effectHighlight = $.effects.effect.highlight = function( o, done ) { - var elem = $( this ), - props = [ "backgroundImage", "backgroundColor", "opacity" ], - mode = $.effects.setMode( elem, o.mode || "show" ), - animation = { - backgroundColor: elem.css( "backgroundColor" ) - }; - - if (mode === "hide") { - animation.opacity = 0; - } - - $.effects.save( elem, props ); - - elem - .show() - .css({ - backgroundImage: "none", - backgroundColor: o.color || "#ffff99" - }) - .animate( animation, { - queue: false, - duration: o.duration, - easing: o.easing, - complete: function() { - if ( mode === "hide" ) { - elem.hide(); - } - $.effects.restore( elem, props ); - done(); - } - }); -}; - - -/*! - * jQuery UI Effects Size 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/size-effect/ - */ - - -var effectSize = $.effects.effect.size = function( o, done ) { - - // Create element - var original, baseline, factor, - el = $( this ), - props0 = [ "position", "top", "bottom", "left", "right", "width", "height", "overflow", "opacity" ], - - // Always restore - props1 = [ "position", "top", "bottom", "left", "right", "overflow", "opacity" ], - - // Copy for children - props2 = [ "width", "height", "overflow" ], - cProps = [ "fontSize" ], - vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ], - hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ], - - // Set options - mode = $.effects.setMode( el, o.mode || "effect" ), - restore = o.restore || mode !== "effect", - scale = o.scale || "both", - origin = o.origin || [ "middle", "center" ], - position = el.css( "position" ), - props = restore ? props0 : props1, - zero = { - height: 0, - width: 0, - outerHeight: 0, - outerWidth: 0 - }; - - if ( mode === "show" ) { - el.show(); - } - original = { - height: el.height(), - width: el.width(), - outerHeight: el.outerHeight(), - outerWidth: el.outerWidth() - }; - - if ( o.mode === "toggle" && mode === "show" ) { - el.from = o.to || zero; - el.to = o.from || original; - } else { - el.from = o.from || ( mode === "show" ? zero : original ); - el.to = o.to || ( mode === "hide" ? zero : original ); - } - - // Set scaling factor - factor = { - from: { - y: el.from.height / original.height, - x: el.from.width / original.width - }, - to: { - y: el.to.height / original.height, - x: el.to.width / original.width - } - }; - - // Scale the css box - if ( scale === "box" || scale === "both" ) { - - // Vertical props scaling - if ( factor.from.y !== factor.to.y ) { - props = props.concat( vProps ); - el.from = $.effects.setTransition( el, vProps, factor.from.y, el.from ); - el.to = $.effects.setTransition( el, vProps, factor.to.y, el.to ); - } - - // Horizontal props scaling - if ( factor.from.x !== factor.to.x ) { - props = props.concat( hProps ); - el.from = $.effects.setTransition( el, hProps, factor.from.x, el.from ); - el.to = $.effects.setTransition( el, hProps, factor.to.x, el.to ); - } - } - - // Scale the content - if ( scale === "content" || scale === "both" ) { - - // Vertical props scaling - if ( factor.from.y !== factor.to.y ) { - props = props.concat( cProps ).concat( props2 ); - el.from = $.effects.setTransition( el, cProps, factor.from.y, el.from ); - el.to = $.effects.setTransition( el, cProps, factor.to.y, el.to ); - } - } - - $.effects.save( el, props ); - el.show(); - $.effects.createWrapper( el ); - el.css( "overflow", "hidden" ).css( el.from ); - - // Adjust - if (origin) { // Calculate baseline shifts - baseline = $.effects.getBaseline( origin, original ); - el.from.top = ( original.outerHeight - el.outerHeight() ) * baseline.y; - el.from.left = ( original.outerWidth - el.outerWidth() ) * baseline.x; - el.to.top = ( original.outerHeight - el.to.outerHeight ) * baseline.y; - el.to.left = ( original.outerWidth - el.to.outerWidth ) * baseline.x; - } - el.css( el.from ); // set top & left - - // Animate - if ( scale === "content" || scale === "both" ) { // Scale the children - - // Add margins/font-size - vProps = vProps.concat([ "marginTop", "marginBottom" ]).concat(cProps); - hProps = hProps.concat([ "marginLeft", "marginRight" ]); - props2 = props0.concat(vProps).concat(hProps); - - el.find( "*[width]" ).each( function() { - var child = $( this ), - c_original = { - height: child.height(), - width: child.width(), - outerHeight: child.outerHeight(), - outerWidth: child.outerWidth() - }; - if (restore) { - $.effects.save(child, props2); - } - - child.from = { - height: c_original.height * factor.from.y, - width: c_original.width * factor.from.x, - outerHeight: c_original.outerHeight * factor.from.y, - outerWidth: c_original.outerWidth * factor.from.x - }; - child.to = { - height: c_original.height * factor.to.y, - width: c_original.width * factor.to.x, - outerHeight: c_original.height * factor.to.y, - outerWidth: c_original.width * factor.to.x - }; - - // Vertical props scaling - if ( factor.from.y !== factor.to.y ) { - child.from = $.effects.setTransition( child, vProps, factor.from.y, child.from ); - child.to = $.effects.setTransition( child, vProps, factor.to.y, child.to ); - } - - // Horizontal props scaling - if ( factor.from.x !== factor.to.x ) { - child.from = $.effects.setTransition( child, hProps, factor.from.x, child.from ); - child.to = $.effects.setTransition( child, hProps, factor.to.x, child.to ); - } - - // Animate children - child.css( child.from ); - child.animate( child.to, o.duration, o.easing, function() { - - // Restore children - if ( restore ) { - $.effects.restore( child, props2 ); - } - }); - }); - } - - // Animate - el.animate( el.to, { - queue: false, - duration: o.duration, - easing: o.easing, - complete: function() { - if ( el.to.opacity === 0 ) { - el.css( "opacity", el.from.opacity ); - } - if ( mode === "hide" ) { - el.hide(); - } - $.effects.restore( el, props ); - if ( !restore ) { - - // we need to calculate our new positioning based on the scaling - if ( position === "static" ) { - el.css({ - position: "relative", - top: el.to.top, - left: el.to.left - }); - } else { - $.each([ "top", "left" ], function( idx, pos ) { - el.css( pos, function( _, str ) { - var val = parseInt( str, 10 ), - toRef = idx ? el.to.left : el.to.top; - - // if original was "auto", recalculate the new value from wrapper - if ( str === "auto" ) { - return toRef + "px"; - } - - return val + toRef + "px"; - }); - }); - } - } - - $.effects.removeWrapper( el ); - done(); - } - }); - -}; - - -/*! - * jQuery UI Effects Scale 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/scale-effect/ - */ - - -var effectScale = $.effects.effect.scale = function( o, done ) { - - // Create element - var el = $( this ), - options = $.extend( true, {}, o ), - mode = $.effects.setMode( el, o.mode || "effect" ), - percent = parseInt( o.percent, 10 ) || - ( parseInt( o.percent, 10 ) === 0 ? 0 : ( mode === "hide" ? 0 : 100 ) ), - direction = o.direction || "both", - origin = o.origin, - original = { - height: el.height(), - width: el.width(), - outerHeight: el.outerHeight(), - outerWidth: el.outerWidth() - }, - factor = { - y: direction !== "horizontal" ? (percent / 100) : 1, - x: direction !== "vertical" ? (percent / 100) : 1 - }; - - // We are going to pass this effect to the size effect: - options.effect = "size"; - options.queue = false; - options.complete = done; - - // Set default origin and restore for show/hide - if ( mode !== "effect" ) { - options.origin = origin || [ "middle", "center" ]; - options.restore = true; - } - - options.from = o.from || ( mode === "show" ? { - height: 0, - width: 0, - outerHeight: 0, - outerWidth: 0 - } : original ); - options.to = { - height: original.height * factor.y, - width: original.width * factor.x, - outerHeight: original.outerHeight * factor.y, - outerWidth: original.outerWidth * factor.x - }; - - // Fade option to support puff - if ( options.fade ) { - if ( mode === "show" ) { - options.from.opacity = 0; - options.to.opacity = 1; - } - if ( mode === "hide" ) { - options.from.opacity = 1; - options.to.opacity = 0; - } - } - - // Animate - el.effect( options ); - -}; - - -/*! - * jQuery UI Effects Puff 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/puff-effect/ - */ - - -var effectPuff = $.effects.effect.puff = function( o, done ) { - var elem = $( this ), - mode = $.effects.setMode( elem, o.mode || "hide" ), - hide = mode === "hide", - percent = parseInt( o.percent, 10 ) || 150, - factor = percent / 100, - original = { - height: elem.height(), - width: elem.width(), - outerHeight: elem.outerHeight(), - outerWidth: elem.outerWidth() - }; - - $.extend( o, { - effect: "scale", - queue: false, - fade: true, - mode: mode, - complete: done, - percent: hide ? percent : 100, - from: hide ? - original : - { - height: original.height * factor, - width: original.width * factor, - outerHeight: original.outerHeight * factor, - outerWidth: original.outerWidth * factor - } - }); - - elem.effect( o ); -}; - - -/*! - * jQuery UI Effects Pulsate 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/pulsate-effect/ - */ - - -var effectPulsate = $.effects.effect.pulsate = function( o, done ) { - var elem = $( this ), - mode = $.effects.setMode( elem, o.mode || "show" ), - show = mode === "show", - hide = mode === "hide", - showhide = ( show || mode === "hide" ), - - // showing or hiding leaves of the "last" animation - anims = ( ( o.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ), - duration = o.duration / anims, - animateTo = 0, - queue = elem.queue(), - queuelen = queue.length, - i; - - if ( show || !elem.is(":visible")) { - elem.css( "opacity", 0 ).show(); - animateTo = 1; - } - - // anims - 1 opacity "toggles" - for ( i = 1; i < anims; i++ ) { - elem.animate({ - opacity: animateTo - }, duration, o.easing ); - animateTo = 1 - animateTo; - } - - elem.animate({ - opacity: animateTo - }, duration, o.easing); - - elem.queue(function() { - if ( hide ) { - elem.hide(); - } - done(); - }); - - // We just queued up "anims" animations, we need to put them next in the queue - if ( queuelen > 1 ) { - queue.splice.apply( queue, - [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); - } - elem.dequeue(); -}; - - -/*! - * jQuery UI Effects Shake 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/shake-effect/ - */ - - -var effectShake = $.effects.effect.shake = function( o, done ) { - - var el = $( this ), - props = [ "position", "top", "bottom", "left", "right", "height", "width" ], - mode = $.effects.setMode( el, o.mode || "effect" ), - direction = o.direction || "left", - distance = o.distance || 20, - times = o.times || 3, - anims = times * 2 + 1, - speed = Math.round( o.duration / anims ), - ref = (direction === "up" || direction === "down") ? "top" : "left", - positiveMotion = (direction === "up" || direction === "left"), - animation = {}, - animation1 = {}, - animation2 = {}, - i, - - // we will need to re-assemble the queue to stack our animations in place - queue = el.queue(), - queuelen = queue.length; - - $.effects.save( el, props ); - el.show(); - $.effects.createWrapper( el ); - - // Animation - animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance; - animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2; - animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2; - - // Animate - el.animate( animation, speed, o.easing ); - - // Shakes - for ( i = 1; i < times; i++ ) { - el.animate( animation1, speed, o.easing ).animate( animation2, speed, o.easing ); - } - el - .animate( animation1, speed, o.easing ) - .animate( animation, speed / 2, o.easing ) - .queue(function() { - if ( mode === "hide" ) { - el.hide(); - } - $.effects.restore( el, props ); - $.effects.removeWrapper( el ); - done(); - }); - - // inject all the animations we just queued to be first in line (after "inprogress") - if ( queuelen > 1) { - queue.splice.apply( queue, - [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); - } - el.dequeue(); - -}; - - -/*! - * jQuery UI Effects Slide 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/slide-effect/ - */ - - -var effectSlide = $.effects.effect.slide = function( o, done ) { - - // Create element - var el = $( this ), - props = [ "position", "top", "bottom", "left", "right", "width", "height" ], - mode = $.effects.setMode( el, o.mode || "show" ), - show = mode === "show", - direction = o.direction || "left", - ref = (direction === "up" || direction === "down") ? "top" : "left", - positiveMotion = (direction === "up" || direction === "left"), - distance, - animation = {}; - - // Adjust - $.effects.save( el, props ); - el.show(); - distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ); - - $.effects.createWrapper( el ).css({ - overflow: "hidden" - }); - - if ( show ) { - el.css( ref, positiveMotion ? (isNaN(distance) ? "-" + distance : -distance) : distance ); - } - - // Animation - animation[ ref ] = ( show ? - ( positiveMotion ? "+=" : "-=") : - ( positiveMotion ? "-=" : "+=")) + - distance; - - // Animate - el.animate( animation, { - queue: false, - duration: o.duration, - easing: o.easing, - complete: function() { - if ( mode === "hide" ) { - el.hide(); - } - $.effects.restore( el, props ); - $.effects.removeWrapper( el ); - done(); - } - }); -}; - - -/*! - * jQuery UI Effects Transfer 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/transfer-effect/ - */ - - -var effectTransfer = $.effects.effect.transfer = function( o, done ) { - var elem = $( this ), - target = $( o.to ), - targetFixed = target.css( "position" ) === "fixed", - body = $("body"), - fixTop = targetFixed ? body.scrollTop() : 0, - fixLeft = targetFixed ? body.scrollLeft() : 0, - endPosition = target.offset(), - animation = { - top: endPosition.top - fixTop, - left: endPosition.left - fixLeft, - height: target.innerHeight(), - width: target.innerWidth() - }, - startPosition = elem.offset(), - transfer = $( "<div class='ui-effects-transfer'></div>" ) - .appendTo( document.body ) - .addClass( o.className ) - .css({ - top: startPosition.top - fixTop, - left: startPosition.left - fixLeft, - height: elem.innerHeight(), - width: elem.innerWidth(), - position: targetFixed ? "fixed" : "absolute" - }) - .animate( animation, o.duration, o.easing, function() { - transfer.remove(); - done(); - }); -}; - - - -})); \ No newline at end of file diff --git a/website/agenda/planung/js/jquery-ui.min.js b/website/agenda/planung/js/jquery-ui.min.js deleted file mode 100644 index 25398a1..0000000 --- a/website/agenda/planung/js/jquery-ui.min.js +++ /dev/null @@ -1,13 +0,0 @@ -/*! jQuery UI - v1.12.1 - 2016-09-14 -* http://jqueryui.com -* Includes: widget.js, position.js, data.js, disable-selection.js, effect.js, effects/effect-blind.js, effects/effect-bounce.js, effects/effect-clip.js, effects/effect-drop.js, effects/effect-explode.js, effects/effect-fade.js, effects/effect-fold.js, effects/effect-highlight.js, effects/effect-puff.js, effects/effect-pulsate.js, effects/effect-scale.js, effects/effect-shake.js, effects/effect-size.js, effects/effect-slide.js, effects/effect-transfer.js, focusable.js, form-reset-mixin.js, jquery-1-7.js, keycode.js, labels.js, scroll-parent.js, tabbable.js, unique-id.js, widgets/accordion.js, widgets/autocomplete.js, widgets/button.js, widgets/checkboxradio.js, widgets/controlgroup.js, widgets/datepicker.js, widgets/dialog.js, widgets/draggable.js, widgets/droppable.js, widgets/menu.js, widgets/mouse.js, widgets/progressbar.js, widgets/resizable.js, widgets/selectable.js, widgets/selectmenu.js, widgets/slider.js, widgets/sortable.js, widgets/spinner.js, widgets/tabs.js, widgets/tooltip.js -* Copyright jQuery Foundation and other contributors; Licensed MIT */ - -(function(t){"function"==typeof define&&define.amd?define(["jquery"],t):t(jQuery)})(function(t){function e(t){for(var e=t.css("visibility");"inherit"===e;)t=t.parent(),e=t.css("visibility");return"hidden"!==e}function i(t){for(var e,i;t.length&&t[0]!==document;){if(e=t.css("position"),("absolute"===e||"relative"===e||"fixed"===e)&&(i=parseInt(t.css("zIndex"),10),!isNaN(i)&&0!==i))return i;t=t.parent()}return 0}function s(){this._curInst=null,this._keyEvent=!1,this._disabledInputs=[],this._datepickerShowing=!1,this._inDialog=!1,this._mainDivId="ui-datepicker-div",this._inlineClass="ui-datepicker-inline",this._appendClass="ui-datepicker-append",this._triggerClass="ui-datepicker-trigger",this._dialogClass="ui-datepicker-dialog",this._disableClass="ui-datepicker-disabled",this._unselectableClass="ui-datepicker-unselectable",this._currentClass="ui-datepicker-current-day",this._dayOverClass="ui-datepicker-days-cell-over",this.regional=[],this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""},this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:!1,hideIfNoPrevNext:!1,navigationAsDateFormat:!1,gotoCurrent:!1,changeMonth:!1,changeYear:!1,yearRange:"c-10:c+10",showOtherMonths:!1,selectOtherMonths:!1,showWeek:!1,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:!0,showButtonPanel:!1,autoSize:!1,disabled:!1},t.extend(this._defaults,this.regional[""]),this.regional.en=t.extend(!0,{},this.regional[""]),this.regional["en-US"]=t.extend(!0,{},this.regional.en),this.dpDiv=n(t("<div id='"+this._mainDivId+"' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"))}function n(e){var i="button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";return e.on("mouseout",i,function(){t(this).removeClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&t(this).removeClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&t(this).removeClass("ui-datepicker-next-hover")}).on("mouseover",i,o)}function o(){t.datepicker._isDisabledDatepicker(m.inline?m.dpDiv.parent()[0]:m.input[0])||(t(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"),t(this).addClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&t(this).addClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&t(this).addClass("ui-datepicker-next-hover"))}function a(e,i){t.extend(e,i);for(var s in i)null==i[s]&&(e[s]=i[s]);return e}function r(t){return function(){var e=this.element.val();t.apply(this,arguments),this._refresh(),e!==this.element.val()&&this._trigger("change")}}t.ui=t.ui||{},t.ui.version="1.12.1";var h=0,l=Array.prototype.slice;t.cleanData=function(e){return function(i){var s,n,o;for(o=0;null!=(n=i[o]);o++)try{s=t._data(n,"events"),s&&s.remove&&t(n).triggerHandler("remove")}catch(a){}e(i)}}(t.cleanData),t.widget=function(e,i,s){var n,o,a,r={},h=e.split(".")[0];e=e.split(".")[1];var l=h+"-"+e;return s||(s=i,i=t.Widget),t.isArray(s)&&(s=t.extend.apply(null,[{}].concat(s))),t.expr[":"][l.toLowerCase()]=function(e){return!!t.data(e,l)},t[h]=t[h]||{},n=t[h][e],o=t[h][e]=function(t,e){return this._createWidget?(arguments.length&&this._createWidget(t,e),void 0):new o(t,e)},t.extend(o,n,{version:s.version,_proto:t.extend({},s),_childConstructors:[]}),a=new i,a.options=t.widget.extend({},a.options),t.each(s,function(e,s){return t.isFunction(s)?(r[e]=function(){function t(){return i.prototype[e].apply(this,arguments)}function n(t){return i.prototype[e].apply(this,t)}return function(){var e,i=this._super,o=this._superApply;return this._super=t,this._superApply=n,e=s.apply(this,arguments),this._super=i,this._superApply=o,e}}(),void 0):(r[e]=s,void 0)}),o.prototype=t.widget.extend(a,{widgetEventPrefix:n?a.widgetEventPrefix||e:e},r,{constructor:o,namespace:h,widgetName:e,widgetFullName:l}),n?(t.each(n._childConstructors,function(e,i){var s=i.prototype;t.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete n._childConstructors):i._childConstructors.push(o),t.widget.bridge(e,o),o},t.widget.extend=function(e){for(var i,s,n=l.call(arguments,1),o=0,a=n.length;a>o;o++)for(i in n[o])s=n[o][i],n[o].hasOwnProperty(i)&&void 0!==s&&(e[i]=t.isPlainObject(s)?t.isPlainObject(e[i])?t.widget.extend({},e[i],s):t.widget.extend({},s):s);return e},t.widget.bridge=function(e,i){var s=i.prototype.widgetFullName||e;t.fn[e]=function(n){var o="string"==typeof n,a=l.call(arguments,1),r=this;return o?this.length||"instance"!==n?this.each(function(){var i,o=t.data(this,s);return"instance"===n?(r=o,!1):o?t.isFunction(o[n])&&"_"!==n.charAt(0)?(i=o[n].apply(o,a),i!==o&&void 0!==i?(r=i&&i.jquery?r.pushStack(i.get()):i,!1):void 0):t.error("no such method '"+n+"' for "+e+" widget instance"):t.error("cannot call methods on "+e+" prior to initialization; "+"attempted to call method '"+n+"'")}):r=void 0:(a.length&&(n=t.widget.extend.apply(null,[n].concat(a))),this.each(function(){var e=t.data(this,s);e?(e.option(n||{}),e._init&&e._init()):t.data(this,s,new i(n,this))})),r}},t.Widget=function(){},t.Widget._childConstructors=[],t.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{classes:{},disabled:!1,create:null},_createWidget:function(e,i){i=t(i||this.defaultElement||this)[0],this.element=t(i),this.uuid=h++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=t(),this.hoverable=t(),this.focusable=t(),this.classesElementLookup={},i!==this&&(t.data(i,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===i&&this.destroy()}}),this.document=t(i.style?i.ownerDocument:i.document||i),this.window=t(this.document[0].defaultView||this.document[0].parentWindow)),this.options=t.widget.extend({},this.options,this._getCreateOptions(),e),this._create(),this.options.disabled&&this._setOptionDisabled(this.options.disabled),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:function(){return{}},_getCreateEventData:t.noop,_create:t.noop,_init:t.noop,destroy:function(){var e=this;this._destroy(),t.each(this.classesElementLookup,function(t,i){e._removeClass(i,t)}),this.element.off(this.eventNamespace).removeData(this.widgetFullName),this.widget().off(this.eventNamespace).removeAttr("aria-disabled"),this.bindings.off(this.eventNamespace)},_destroy:t.noop,widget:function(){return this.element},option:function(e,i){var s,n,o,a=e;if(0===arguments.length)return t.widget.extend({},this.options);if("string"==typeof e)if(a={},s=e.split("."),e=s.shift(),s.length){for(n=a[e]=t.widget.extend({},this.options[e]),o=0;s.length-1>o;o++)n[s[o]]=n[s[o]]||{},n=n[s[o]];if(e=s.pop(),1===arguments.length)return void 0===n[e]?null:n[e];n[e]=i}else{if(1===arguments.length)return void 0===this.options[e]?null:this.options[e];a[e]=i}return this._setOptions(a),this},_setOptions:function(t){var e;for(e in t)this._setOption(e,t[e]);return this},_setOption:function(t,e){return"classes"===t&&this._setOptionClasses(e),this.options[t]=e,"disabled"===t&&this._setOptionDisabled(e),this},_setOptionClasses:function(e){var i,s,n;for(i in e)n=this.classesElementLookup[i],e[i]!==this.options.classes[i]&&n&&n.length&&(s=t(n.get()),this._removeClass(n,i),s.addClass(this._classes({element:s,keys:i,classes:e,add:!0})))},_setOptionDisabled:function(t){this._toggleClass(this.widget(),this.widgetFullName+"-disabled",null,!!t),t&&(this._removeClass(this.hoverable,null,"ui-state-hover"),this._removeClass(this.focusable,null,"ui-state-focus"))},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_classes:function(e){function i(i,o){var a,r;for(r=0;i.length>r;r++)a=n.classesElementLookup[i[r]]||t(),a=e.add?t(t.unique(a.get().concat(e.element.get()))):t(a.not(e.element).get()),n.classesElementLookup[i[r]]=a,s.push(i[r]),o&&e.classes[i[r]]&&s.push(e.classes[i[r]])}var s=[],n=this;return e=t.extend({element:this.element,classes:this.options.classes||{}},e),this._on(e.element,{remove:"_untrackClassesElement"}),e.keys&&i(e.keys.match(/\S+/g)||[],!0),e.extra&&i(e.extra.match(/\S+/g)||[]),s.join(" ")},_untrackClassesElement:function(e){var i=this;t.each(i.classesElementLookup,function(s,n){-1!==t.inArray(e.target,n)&&(i.classesElementLookup[s]=t(n.not(e.target).get()))})},_removeClass:function(t,e,i){return this._toggleClass(t,e,i,!1)},_addClass:function(t,e,i){return this._toggleClass(t,e,i,!0)},_toggleClass:function(t,e,i,s){s="boolean"==typeof s?s:i;var n="string"==typeof t||null===t,o={extra:n?e:i,keys:n?t:e,element:n?this.element:t,add:s};return o.element.toggleClass(this._classes(o),s),this},_on:function(e,i,s){var n,o=this;"boolean"!=typeof e&&(s=i,i=e,e=!1),s?(i=n=t(i),this.bindings=this.bindings.add(i)):(s=i,i=this.element,n=this.widget()),t.each(s,function(s,a){function r(){return e||o.options.disabled!==!0&&!t(this).hasClass("ui-state-disabled")?("string"==typeof a?o[a]:a).apply(o,arguments):void 0}"string"!=typeof a&&(r.guid=a.guid=a.guid||r.guid||t.guid++);var h=s.match(/^([\w:-]*)\s*(.*)$/),l=h[1]+o.eventNamespace,c=h[2];c?n.on(l,c,r):i.on(l,r)})},_off:function(e,i){i=(i||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.off(i).off(i),this.bindings=t(this.bindings.not(e).get()),this.focusable=t(this.focusable.not(e).get()),this.hoverable=t(this.hoverable.not(e).get())},_delay:function(t,e){function i(){return("string"==typeof t?s[t]:t).apply(s,arguments)}var s=this;return setTimeout(i,e||0)},_hoverable:function(e){this.hoverable=this.hoverable.add(e),this._on(e,{mouseenter:function(e){this._addClass(t(e.currentTarget),null,"ui-state-hover")},mouseleave:function(e){this._removeClass(t(e.currentTarget),null,"ui-state-hover")}})},_focusable:function(e){this.focusable=this.focusable.add(e),this._on(e,{focusin:function(e){this._addClass(t(e.currentTarget),null,"ui-state-focus")},focusout:function(e){this._removeClass(t(e.currentTarget),null,"ui-state-focus")}})},_trigger:function(e,i,s){var n,o,a=this.options[e];if(s=s||{},i=t.Event(i),i.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase(),i.target=this.element[0],o=i.originalEvent)for(n in o)n in i||(i[n]=o[n]);return this.element.trigger(i,s),!(t.isFunction(a)&&a.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},t.each({show:"fadeIn",hide:"fadeOut"},function(e,i){t.Widget.prototype["_"+e]=function(s,n,o){"string"==typeof n&&(n={effect:n});var a,r=n?n===!0||"number"==typeof n?i:n.effect||i:e;n=n||{},"number"==typeof n&&(n={duration:n}),a=!t.isEmptyObject(n),n.complete=o,n.delay&&s.delay(n.delay),a&&t.effects&&t.effects.effect[r]?s[e](n):r!==e&&s[r]?s[r](n.duration,n.easing,o):s.queue(function(i){t(this)[e](),o&&o.call(s[0]),i()})}}),t.widget,function(){function e(t,e,i){return[parseFloat(t[0])*(u.test(t[0])?e/100:1),parseFloat(t[1])*(u.test(t[1])?i/100:1)]}function i(e,i){return parseInt(t.css(e,i),10)||0}function s(e){var i=e[0];return 9===i.nodeType?{width:e.width(),height:e.height(),offset:{top:0,left:0}}:t.isWindow(i)?{width:e.width(),height:e.height(),offset:{top:e.scrollTop(),left:e.scrollLeft()}}:i.preventDefault?{width:0,height:0,offset:{top:i.pageY,left:i.pageX}}:{width:e.outerWidth(),height:e.outerHeight(),offset:e.offset()}}var n,o=Math.max,a=Math.abs,r=/left|center|right/,h=/top|center|bottom/,l=/[\+\-]\d+(\.[\d]+)?%?/,c=/^\w+/,u=/%$/,d=t.fn.position;t.position={scrollbarWidth:function(){if(void 0!==n)return n;var e,i,s=t("<div style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>"),o=s.children()[0];return t("body").append(s),e=o.offsetWidth,s.css("overflow","scroll"),i=o.offsetWidth,e===i&&(i=s[0].clientWidth),s.remove(),n=e-i},getScrollInfo:function(e){var i=e.isWindow||e.isDocument?"":e.element.css("overflow-x"),s=e.isWindow||e.isDocument?"":e.element.css("overflow-y"),n="scroll"===i||"auto"===i&&e.width<e.element[0].scrollWidth,o="scroll"===s||"auto"===s&&e.height<e.element[0].scrollHeight;return{width:o?t.position.scrollbarWidth():0,height:n?t.position.scrollbarWidth():0}},getWithinInfo:function(e){var i=t(e||window),s=t.isWindow(i[0]),n=!!i[0]&&9===i[0].nodeType,o=!s&&!n;return{element:i,isWindow:s,isDocument:n,offset:o?t(e).offset():{left:0,top:0},scrollLeft:i.scrollLeft(),scrollTop:i.scrollTop(),width:i.outerWidth(),height:i.outerHeight()}}},t.fn.position=function(n){if(!n||!n.of)return d.apply(this,arguments);n=t.extend({},n);var u,p,f,g,m,_,v=t(n.of),b=t.position.getWithinInfo(n.within),y=t.position.getScrollInfo(b),w=(n.collision||"flip").split(" "),k={};return _=s(v),v[0].preventDefault&&(n.at="left top"),p=_.width,f=_.height,g=_.offset,m=t.extend({},g),t.each(["my","at"],function(){var t,e,i=(n[this]||"").split(" ");1===i.length&&(i=r.test(i[0])?i.concat(["center"]):h.test(i[0])?["center"].concat(i):["center","center"]),i[0]=r.test(i[0])?i[0]:"center",i[1]=h.test(i[1])?i[1]:"center",t=l.exec(i[0]),e=l.exec(i[1]),k[this]=[t?t[0]:0,e?e[0]:0],n[this]=[c.exec(i[0])[0],c.exec(i[1])[0]]}),1===w.length&&(w[1]=w[0]),"right"===n.at[0]?m.left+=p:"center"===n.at[0]&&(m.left+=p/2),"bottom"===n.at[1]?m.top+=f:"center"===n.at[1]&&(m.top+=f/2),u=e(k.at,p,f),m.left+=u[0],m.top+=u[1],this.each(function(){var s,r,h=t(this),l=h.outerWidth(),c=h.outerHeight(),d=i(this,"marginLeft"),_=i(this,"marginTop"),x=l+d+i(this,"marginRight")+y.width,C=c+_+i(this,"marginBottom")+y.height,D=t.extend({},m),I=e(k.my,h.outerWidth(),h.outerHeight());"right"===n.my[0]?D.left-=l:"center"===n.my[0]&&(D.left-=l/2),"bottom"===n.my[1]?D.top-=c:"center"===n.my[1]&&(D.top-=c/2),D.left+=I[0],D.top+=I[1],s={marginLeft:d,marginTop:_},t.each(["left","top"],function(e,i){t.ui.position[w[e]]&&t.ui.position[w[e]][i](D,{targetWidth:p,targetHeight:f,elemWidth:l,elemHeight:c,collisionPosition:s,collisionWidth:x,collisionHeight:C,offset:[u[0]+I[0],u[1]+I[1]],my:n.my,at:n.at,within:b,elem:h})}),n.using&&(r=function(t){var e=g.left-D.left,i=e+p-l,s=g.top-D.top,r=s+f-c,u={target:{element:v,left:g.left,top:g.top,width:p,height:f},element:{element:h,left:D.left,top:D.top,width:l,height:c},horizontal:0>i?"left":e>0?"right":"center",vertical:0>r?"top":s>0?"bottom":"middle"};l>p&&p>a(e+i)&&(u.horizontal="center"),c>f&&f>a(s+r)&&(u.vertical="middle"),u.important=o(a(e),a(i))>o(a(s),a(r))?"horizontal":"vertical",n.using.call(this,t,u)}),h.offset(t.extend(D,{using:r}))})},t.ui.position={fit:{left:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollLeft:s.offset.left,a=s.width,r=t.left-e.collisionPosition.marginLeft,h=n-r,l=r+e.collisionWidth-a-n;e.collisionWidth>a?h>0&&0>=l?(i=t.left+h+e.collisionWidth-a-n,t.left+=h-i):t.left=l>0&&0>=h?n:h>l?n+a-e.collisionWidth:n:h>0?t.left+=h:l>0?t.left-=l:t.left=o(t.left-r,t.left)},top:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollTop:s.offset.top,a=e.within.height,r=t.top-e.collisionPosition.marginTop,h=n-r,l=r+e.collisionHeight-a-n;e.collisionHeight>a?h>0&&0>=l?(i=t.top+h+e.collisionHeight-a-n,t.top+=h-i):t.top=l>0&&0>=h?n:h>l?n+a-e.collisionHeight:n:h>0?t.top+=h:l>0?t.top-=l:t.top=o(t.top-r,t.top)}},flip:{left:function(t,e){var i,s,n=e.within,o=n.offset.left+n.scrollLeft,r=n.width,h=n.isWindow?n.scrollLeft:n.offset.left,l=t.left-e.collisionPosition.marginLeft,c=l-h,u=l+e.collisionWidth-r-h,d="left"===e.my[0]?-e.elemWidth:"right"===e.my[0]?e.elemWidth:0,p="left"===e.at[0]?e.targetWidth:"right"===e.at[0]?-e.targetWidth:0,f=-2*e.offset[0];0>c?(i=t.left+d+p+f+e.collisionWidth-r-o,(0>i||a(c)>i)&&(t.left+=d+p+f)):u>0&&(s=t.left-e.collisionPosition.marginLeft+d+p+f-h,(s>0||u>a(s))&&(t.left+=d+p+f))},top:function(t,e){var i,s,n=e.within,o=n.offset.top+n.scrollTop,r=n.height,h=n.isWindow?n.scrollTop:n.offset.top,l=t.top-e.collisionPosition.marginTop,c=l-h,u=l+e.collisionHeight-r-h,d="top"===e.my[1],p=d?-e.elemHeight:"bottom"===e.my[1]?e.elemHeight:0,f="top"===e.at[1]?e.targetHeight:"bottom"===e.at[1]?-e.targetHeight:0,g=-2*e.offset[1];0>c?(s=t.top+p+f+g+e.collisionHeight-r-o,(0>s||a(c)>s)&&(t.top+=p+f+g)):u>0&&(i=t.top-e.collisionPosition.marginTop+p+f+g-h,(i>0||u>a(i))&&(t.top+=p+f+g))}},flipfit:{left:function(){t.ui.position.flip.left.apply(this,arguments),t.ui.position.fit.left.apply(this,arguments)},top:function(){t.ui.position.flip.top.apply(this,arguments),t.ui.position.fit.top.apply(this,arguments)}}}}(),t.ui.position,t.extend(t.expr[":"],{data:t.expr.createPseudo?t.expr.createPseudo(function(e){return function(i){return!!t.data(i,e)}}):function(e,i,s){return!!t.data(e,s[3])}}),t.fn.extend({disableSelection:function(){var t="onselectstart"in document.createElement("div")?"selectstart":"mousedown";return function(){return this.on(t+".ui-disableSelection",function(t){t.preventDefault()})}}(),enableSelection:function(){return this.off(".ui-disableSelection")}});var c="ui-effects-",u="ui-effects-style",d="ui-effects-animated",p=t;t.effects={effect:{}},function(t,e){function i(t,e,i){var s=u[e.type]||{};return null==t?i||!e.def?null:e.def:(t=s.floor?~~t:parseFloat(t),isNaN(t)?e.def:s.mod?(t+s.mod)%s.mod:0>t?0:t>s.max?s.max:t)}function s(i){var s=l(),n=s._rgba=[];return i=i.toLowerCase(),f(h,function(t,o){var a,r=o.re.exec(i),h=r&&o.parse(r),l=o.space||"rgba";return h?(a=s[l](h),s[c[l].cache]=a[c[l].cache],n=s._rgba=a._rgba,!1):e}),n.length?("0,0,0,0"===n.join()&&t.extend(n,o.transparent),s):o[i]}function n(t,e,i){return i=(i+1)%1,1>6*i?t+6*(e-t)*i:1>2*i?e:2>3*i?t+6*(e-t)*(2/3-i):t}var o,a="backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",r=/^([\-+])=\s*(\d+\.?\d*)/,h=[{re:/rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,parse:function(t){return[t[1],t[2],t[3],t[4]]}},{re:/rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,parse:function(t){return[2.55*t[1],2.55*t[2],2.55*t[3],t[4]]}},{re:/#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,parse:function(t){return[parseInt(t[1],16),parseInt(t[2],16),parseInt(t[3],16)]}},{re:/#([a-f0-9])([a-f0-9])([a-f0-9])/,parse:function(t){return[parseInt(t[1]+t[1],16),parseInt(t[2]+t[2],16),parseInt(t[3]+t[3],16)]}},{re:/hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,space:"hsla",parse:function(t){return[t[1],t[2]/100,t[3]/100,t[4]]}}],l=t.Color=function(e,i,s,n){return new t.Color.fn.parse(e,i,s,n)},c={rgba:{props:{red:{idx:0,type:"byte"},green:{idx:1,type:"byte"},blue:{idx:2,type:"byte"}}},hsla:{props:{hue:{idx:0,type:"degrees"},saturation:{idx:1,type:"percent"},lightness:{idx:2,type:"percent"}}}},u={"byte":{floor:!0,max:255},percent:{max:1},degrees:{mod:360,floor:!0}},d=l.support={},p=t("<p>")[0],f=t.each;p.style.cssText="background-color:rgba(1,1,1,.5)",d.rgba=p.style.backgroundColor.indexOf("rgba")>-1,f(c,function(t,e){e.cache="_"+t,e.props.alpha={idx:3,type:"percent",def:1}}),l.fn=t.extend(l.prototype,{parse:function(n,a,r,h){if(n===e)return this._rgba=[null,null,null,null],this;(n.jquery||n.nodeType)&&(n=t(n).css(a),a=e);var u=this,d=t.type(n),p=this._rgba=[];return a!==e&&(n=[n,a,r,h],d="array"),"string"===d?this.parse(s(n)||o._default):"array"===d?(f(c.rgba.props,function(t,e){p[e.idx]=i(n[e.idx],e)}),this):"object"===d?(n instanceof l?f(c,function(t,e){n[e.cache]&&(u[e.cache]=n[e.cache].slice())}):f(c,function(e,s){var o=s.cache;f(s.props,function(t,e){if(!u[o]&&s.to){if("alpha"===t||null==n[t])return;u[o]=s.to(u._rgba)}u[o][e.idx]=i(n[t],e,!0)}),u[o]&&0>t.inArray(null,u[o].slice(0,3))&&(u[o][3]=1,s.from&&(u._rgba=s.from(u[o])))}),this):e},is:function(t){var i=l(t),s=!0,n=this;return f(c,function(t,o){var a,r=i[o.cache];return r&&(a=n[o.cache]||o.to&&o.to(n._rgba)||[],f(o.props,function(t,i){return null!=r[i.idx]?s=r[i.idx]===a[i.idx]:e})),s}),s},_space:function(){var t=[],e=this;return f(c,function(i,s){e[s.cache]&&t.push(i)}),t.pop()},transition:function(t,e){var s=l(t),n=s._space(),o=c[n],a=0===this.alpha()?l("transparent"):this,r=a[o.cache]||o.to(a._rgba),h=r.slice();return s=s[o.cache],f(o.props,function(t,n){var o=n.idx,a=r[o],l=s[o],c=u[n.type]||{};null!==l&&(null===a?h[o]=l:(c.mod&&(l-a>c.mod/2?a+=c.mod:a-l>c.mod/2&&(a-=c.mod)),h[o]=i((l-a)*e+a,n)))}),this[n](h)},blend:function(e){if(1===this._rgba[3])return this;var i=this._rgba.slice(),s=i.pop(),n=l(e)._rgba;return l(t.map(i,function(t,e){return(1-s)*n[e]+s*t}))},toRgbaString:function(){var e="rgba(",i=t.map(this._rgba,function(t,e){return null==t?e>2?1:0:t});return 1===i[3]&&(i.pop(),e="rgb("),e+i.join()+")"},toHslaString:function(){var e="hsla(",i=t.map(this.hsla(),function(t,e){return null==t&&(t=e>2?1:0),e&&3>e&&(t=Math.round(100*t)+"%"),t});return 1===i[3]&&(i.pop(),e="hsl("),e+i.join()+")"},toHexString:function(e){var i=this._rgba.slice(),s=i.pop();return e&&i.push(~~(255*s)),"#"+t.map(i,function(t){return t=(t||0).toString(16),1===t.length?"0"+t:t}).join("")},toString:function(){return 0===this._rgba[3]?"transparent":this.toRgbaString()}}),l.fn.parse.prototype=l.fn,c.hsla.to=function(t){if(null==t[0]||null==t[1]||null==t[2])return[null,null,null,t[3]];var e,i,s=t[0]/255,n=t[1]/255,o=t[2]/255,a=t[3],r=Math.max(s,n,o),h=Math.min(s,n,o),l=r-h,c=r+h,u=.5*c;return e=h===r?0:s===r?60*(n-o)/l+360:n===r?60*(o-s)/l+120:60*(s-n)/l+240,i=0===l?0:.5>=u?l/c:l/(2-c),[Math.round(e)%360,i,u,null==a?1:a]},c.hsla.from=function(t){if(null==t[0]||null==t[1]||null==t[2])return[null,null,null,t[3]];var e=t[0]/360,i=t[1],s=t[2],o=t[3],a=.5>=s?s*(1+i):s+i-s*i,r=2*s-a;return[Math.round(255*n(r,a,e+1/3)),Math.round(255*n(r,a,e)),Math.round(255*n(r,a,e-1/3)),o]},f(c,function(s,n){var o=n.props,a=n.cache,h=n.to,c=n.from;l.fn[s]=function(s){if(h&&!this[a]&&(this[a]=h(this._rgba)),s===e)return this[a].slice();var n,r=t.type(s),u="array"===r||"object"===r?s:arguments,d=this[a].slice();return f(o,function(t,e){var s=u["object"===r?t:e.idx];null==s&&(s=d[e.idx]),d[e.idx]=i(s,e)}),c?(n=l(c(d)),n[a]=d,n):l(d)},f(o,function(e,i){l.fn[e]||(l.fn[e]=function(n){var o,a=t.type(n),h="alpha"===e?this._hsla?"hsla":"rgba":s,l=this[h](),c=l[i.idx];return"undefined"===a?c:("function"===a&&(n=n.call(this,c),a=t.type(n)),null==n&&i.empty?this:("string"===a&&(o=r.exec(n),o&&(n=c+parseFloat(o[2])*("+"===o[1]?1:-1))),l[i.idx]=n,this[h](l)))})})}),l.hook=function(e){var i=e.split(" ");f(i,function(e,i){t.cssHooks[i]={set:function(e,n){var o,a,r="";if("transparent"!==n&&("string"!==t.type(n)||(o=s(n)))){if(n=l(o||n),!d.rgba&&1!==n._rgba[3]){for(a="backgroundColor"===i?e.parentNode:e;(""===r||"transparent"===r)&&a&&a.style;)try{r=t.css(a,"backgroundColor"),a=a.parentNode}catch(h){}n=n.blend(r&&"transparent"!==r?r:"_default")}n=n.toRgbaString()}try{e.style[i]=n}catch(h){}}},t.fx.step[i]=function(e){e.colorInit||(e.start=l(e.elem,i),e.end=l(e.end),e.colorInit=!0),t.cssHooks[i].set(e.elem,e.start.transition(e.end,e.pos))}})},l.hook(a),t.cssHooks.borderColor={expand:function(t){var e={};return f(["Top","Right","Bottom","Left"],function(i,s){e["border"+s+"Color"]=t}),e}},o=t.Color.names={aqua:"#00ffff",black:"#000000",blue:"#0000ff",fuchsia:"#ff00ff",gray:"#808080",green:"#008000",lime:"#00ff00",maroon:"#800000",navy:"#000080",olive:"#808000",purple:"#800080",red:"#ff0000",silver:"#c0c0c0",teal:"#008080",white:"#ffffff",yellow:"#ffff00",transparent:[null,null,null,0],_default:"#ffffff"}}(p),function(){function e(e){var i,s,n=e.ownerDocument.defaultView?e.ownerDocument.defaultView.getComputedStyle(e,null):e.currentStyle,o={};if(n&&n.length&&n[0]&&n[n[0]])for(s=n.length;s--;)i=n[s],"string"==typeof n[i]&&(o[t.camelCase(i)]=n[i]);else for(i in n)"string"==typeof n[i]&&(o[i]=n[i]);return o}function i(e,i){var s,o,a={};for(s in i)o=i[s],e[s]!==o&&(n[s]||(t.fx.step[s]||!isNaN(parseFloat(o)))&&(a[s]=o));return a}var s=["add","remove","toggle"],n={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};t.each(["borderLeftStyle","borderRightStyle","borderBottomStyle","borderTopStyle"],function(e,i){t.fx.step[i]=function(t){("none"!==t.end&&!t.setAttr||1===t.pos&&!t.setAttr)&&(p.style(t.elem,i,t.end),t.setAttr=!0)}}),t.fn.addBack||(t.fn.addBack=function(t){return this.add(null==t?this.prevObject:this.prevObject.filter(t))}),t.effects.animateClass=function(n,o,a,r){var h=t.speed(o,a,r);return this.queue(function(){var o,a=t(this),r=a.attr("class")||"",l=h.children?a.find("*").addBack():a;l=l.map(function(){var i=t(this);return{el:i,start:e(this)}}),o=function(){t.each(s,function(t,e){n[e]&&a[e+"Class"](n[e])})},o(),l=l.map(function(){return this.end=e(this.el[0]),this.diff=i(this.start,this.end),this}),a.attr("class",r),l=l.map(function(){var e=this,i=t.Deferred(),s=t.extend({},h,{queue:!1,complete:function(){i.resolve(e)}});return this.el.animate(this.diff,s),i.promise()}),t.when.apply(t,l.get()).done(function(){o(),t.each(arguments,function(){var e=this.el;t.each(this.diff,function(t){e.css(t,"")})}),h.complete.call(a[0])})})},t.fn.extend({addClass:function(e){return function(i,s,n,o){return s?t.effects.animateClass.call(this,{add:i},s,n,o):e.apply(this,arguments)}}(t.fn.addClass),removeClass:function(e){return function(i,s,n,o){return arguments.length>1?t.effects.animateClass.call(this,{remove:i},s,n,o):e.apply(this,arguments)}}(t.fn.removeClass),toggleClass:function(e){return function(i,s,n,o,a){return"boolean"==typeof s||void 0===s?n?t.effects.animateClass.call(this,s?{add:i}:{remove:i},n,o,a):e.apply(this,arguments):t.effects.animateClass.call(this,{toggle:i},s,n,o)}}(t.fn.toggleClass),switchClass:function(e,i,s,n,o){return t.effects.animateClass.call(this,{add:i,remove:e},s,n,o)}})}(),function(){function e(e,i,s,n){return t.isPlainObject(e)&&(i=e,e=e.effect),e={effect:e},null==i&&(i={}),t.isFunction(i)&&(n=i,s=null,i={}),("number"==typeof i||t.fx.speeds[i])&&(n=s,s=i,i={}),t.isFunction(s)&&(n=s,s=null),i&&t.extend(e,i),s=s||i.duration,e.duration=t.fx.off?0:"number"==typeof s?s:s in t.fx.speeds?t.fx.speeds[s]:t.fx.speeds._default,e.complete=n||i.complete,e}function i(e){return!e||"number"==typeof e||t.fx.speeds[e]?!0:"string"!=typeof e||t.effects.effect[e]?t.isFunction(e)?!0:"object"!=typeof e||e.effect?!1:!0:!0}function s(t,e){var i=e.outerWidth(),s=e.outerHeight(),n=/^rect\((-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto)\)$/,o=n.exec(t)||["",0,i,s,0];return{top:parseFloat(o[1])||0,right:"auto"===o[2]?i:parseFloat(o[2]),bottom:"auto"===o[3]?s:parseFloat(o[3]),left:parseFloat(o[4])||0}}t.expr&&t.expr.filters&&t.expr.filters.animated&&(t.expr.filters.animated=function(e){return function(i){return!!t(i).data(d)||e(i)}}(t.expr.filters.animated)),t.uiBackCompat!==!1&&t.extend(t.effects,{save:function(t,e){for(var i=0,s=e.length;s>i;i++)null!==e[i]&&t.data(c+e[i],t[0].style[e[i]])},restore:function(t,e){for(var i,s=0,n=e.length;n>s;s++)null!==e[s]&&(i=t.data(c+e[s]),t.css(e[s],i))},setMode:function(t,e){return"toggle"===e&&(e=t.is(":hidden")?"show":"hide"),e},createWrapper:function(e){if(e.parent().is(".ui-effects-wrapper"))return e.parent();var i={width:e.outerWidth(!0),height:e.outerHeight(!0),"float":e.css("float")},s=t("<div></div>").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),n={width:e.width(),height:e.height()},o=document.activeElement;try{o.id}catch(a){o=document.body}return e.wrap(s),(e[0]===o||t.contains(e[0],o))&&t(o).trigger("focus"),s=e.parent(),"static"===e.css("position")?(s.css({position:"relative"}),e.css({position:"relative"})):(t.extend(i,{position:e.css("position"),zIndex:e.css("z-index")}),t.each(["top","left","bottom","right"],function(t,s){i[s]=e.css(s),isNaN(parseInt(i[s],10))&&(i[s]="auto")}),e.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),e.css(n),s.css(i).show()},removeWrapper:function(e){var i=document.activeElement;return e.parent().is(".ui-effects-wrapper")&&(e.parent().replaceWith(e),(e[0]===i||t.contains(e[0],i))&&t(i).trigger("focus")),e}}),t.extend(t.effects,{version:"1.12.1",define:function(e,i,s){return s||(s=i,i="effect"),t.effects.effect[e]=s,t.effects.effect[e].mode=i,s},scaledDimensions:function(t,e,i){if(0===e)return{height:0,width:0,outerHeight:0,outerWidth:0};var s="horizontal"!==i?(e||100)/100:1,n="vertical"!==i?(e||100)/100:1;return{height:t.height()*n,width:t.width()*s,outerHeight:t.outerHeight()*n,outerWidth:t.outerWidth()*s}},clipToBox:function(t){return{width:t.clip.right-t.clip.left,height:t.clip.bottom-t.clip.top,left:t.clip.left,top:t.clip.top}},unshift:function(t,e,i){var s=t.queue();e>1&&s.splice.apply(s,[1,0].concat(s.splice(e,i))),t.dequeue()},saveStyle:function(t){t.data(u,t[0].style.cssText)},restoreStyle:function(t){t[0].style.cssText=t.data(u)||"",t.removeData(u)},mode:function(t,e){var i=t.is(":hidden");return"toggle"===e&&(e=i?"show":"hide"),(i?"hide"===e:"show"===e)&&(e="none"),e},getBaseline:function(t,e){var i,s;switch(t[0]){case"top":i=0;break;case"middle":i=.5;break;case"bottom":i=1;break;default:i=t[0]/e.height}switch(t[1]){case"left":s=0;break;case"center":s=.5;break;case"right":s=1;break;default:s=t[1]/e.width}return{x:s,y:i}},createPlaceholder:function(e){var i,s=e.css("position"),n=e.position();return e.css({marginTop:e.css("marginTop"),marginBottom:e.css("marginBottom"),marginLeft:e.css("marginLeft"),marginRight:e.css("marginRight")}).outerWidth(e.outerWidth()).outerHeight(e.outerHeight()),/^(static|relative)/.test(s)&&(s="absolute",i=t("<"+e[0].nodeName+">").insertAfter(e).css({display:/^(inline|ruby)/.test(e.css("display"))?"inline-block":"block",visibility:"hidden",marginTop:e.css("marginTop"),marginBottom:e.css("marginBottom"),marginLeft:e.css("marginLeft"),marginRight:e.css("marginRight"),"float":e.css("float")}).outerWidth(e.outerWidth()).outerHeight(e.outerHeight()).addClass("ui-effects-placeholder"),e.data(c+"placeholder",i)),e.css({position:s,left:n.left,top:n.top}),i},removePlaceholder:function(t){var e=c+"placeholder",i=t.data(e);i&&(i.remove(),t.removeData(e))},cleanUp:function(e){t.effects.restoreStyle(e),t.effects.removePlaceholder(e)},setTransition:function(e,i,s,n){return n=n||{},t.each(i,function(t,i){var o=e.cssUnit(i);o[0]>0&&(n[i]=o[0]*s+o[1])}),n}}),t.fn.extend({effect:function(){function i(e){function i(){r.removeData(d),t.effects.cleanUp(r),"hide"===s.mode&&r.hide(),a()}function a(){t.isFunction(h)&&h.call(r[0]),t.isFunction(e)&&e()}var r=t(this);s.mode=c.shift(),t.uiBackCompat===!1||o?"none"===s.mode?(r[l](),a()):n.call(r[0],s,i):(r.is(":hidden")?"hide"===l:"show"===l)?(r[l](),a()):n.call(r[0],s,a)}var s=e.apply(this,arguments),n=t.effects.effect[s.effect],o=n.mode,a=s.queue,r=a||"fx",h=s.complete,l=s.mode,c=[],u=function(e){var i=t(this),s=t.effects.mode(i,l)||o;i.data(d,!0),c.push(s),o&&("show"===s||s===o&&"hide"===s)&&i.show(),o&&"none"===s||t.effects.saveStyle(i),t.isFunction(e)&&e()};return t.fx.off||!n?l?this[l](s.duration,h):this.each(function(){h&&h.call(this)}):a===!1?this.each(u).each(i):this.queue(r,u).queue(r,i)},show:function(t){return function(s){if(i(s))return t.apply(this,arguments);var n=e.apply(this,arguments);return n.mode="show",this.effect.call(this,n) -}}(t.fn.show),hide:function(t){return function(s){if(i(s))return t.apply(this,arguments);var n=e.apply(this,arguments);return n.mode="hide",this.effect.call(this,n)}}(t.fn.hide),toggle:function(t){return function(s){if(i(s)||"boolean"==typeof s)return t.apply(this,arguments);var n=e.apply(this,arguments);return n.mode="toggle",this.effect.call(this,n)}}(t.fn.toggle),cssUnit:function(e){var i=this.css(e),s=[];return t.each(["em","px","%","pt"],function(t,e){i.indexOf(e)>0&&(s=[parseFloat(i),e])}),s},cssClip:function(t){return t?this.css("clip","rect("+t.top+"px "+t.right+"px "+t.bottom+"px "+t.left+"px)"):s(this.css("clip"),this)},transfer:function(e,i){var s=t(this),n=t(e.to),o="fixed"===n.css("position"),a=t("body"),r=o?a.scrollTop():0,h=o?a.scrollLeft():0,l=n.offset(),c={top:l.top-r,left:l.left-h,height:n.innerHeight(),width:n.innerWidth()},u=s.offset(),d=t("<div class='ui-effects-transfer'></div>").appendTo("body").addClass(e.className).css({top:u.top-r,left:u.left-h,height:s.innerHeight(),width:s.innerWidth(),position:o?"fixed":"absolute"}).animate(c,e.duration,e.easing,function(){d.remove(),t.isFunction(i)&&i()})}}),t.fx.step.clip=function(e){e.clipInit||(e.start=t(e.elem).cssClip(),"string"==typeof e.end&&(e.end=s(e.end,e.elem)),e.clipInit=!0),t(e.elem).cssClip({top:e.pos*(e.end.top-e.start.top)+e.start.top,right:e.pos*(e.end.right-e.start.right)+e.start.right,bottom:e.pos*(e.end.bottom-e.start.bottom)+e.start.bottom,left:e.pos*(e.end.left-e.start.left)+e.start.left})}}(),function(){var e={};t.each(["Quad","Cubic","Quart","Quint","Expo"],function(t,i){e[i]=function(e){return Math.pow(e,t+2)}}),t.extend(e,{Sine:function(t){return 1-Math.cos(t*Math.PI/2)},Circ:function(t){return 1-Math.sqrt(1-t*t)},Elastic:function(t){return 0===t||1===t?t:-Math.pow(2,8*(t-1))*Math.sin((80*(t-1)-7.5)*Math.PI/15)},Back:function(t){return t*t*(3*t-2)},Bounce:function(t){for(var e,i=4;((e=Math.pow(2,--i))-1)/11>t;);return 1/Math.pow(4,3-i)-7.5625*Math.pow((3*e-2)/22-t,2)}}),t.each(e,function(e,i){t.easing["easeIn"+e]=i,t.easing["easeOut"+e]=function(t){return 1-i(1-t)},t.easing["easeInOut"+e]=function(t){return.5>t?i(2*t)/2:1-i(-2*t+2)/2}})}();var f=t.effects;t.effects.define("blind","hide",function(e,i){var s={up:["bottom","top"],vertical:["bottom","top"],down:["top","bottom"],left:["right","left"],horizontal:["right","left"],right:["left","right"]},n=t(this),o=e.direction||"up",a=n.cssClip(),r={clip:t.extend({},a)},h=t.effects.createPlaceholder(n);r.clip[s[o][0]]=r.clip[s[o][1]],"show"===e.mode&&(n.cssClip(r.clip),h&&h.css(t.effects.clipToBox(r)),r.clip=a),h&&h.animate(t.effects.clipToBox(r),e.duration,e.easing),n.animate(r,{queue:!1,duration:e.duration,easing:e.easing,complete:i})}),t.effects.define("bounce",function(e,i){var s,n,o,a=t(this),r=e.mode,h="hide"===r,l="show"===r,c=e.direction||"up",u=e.distance,d=e.times||5,p=2*d+(l||h?1:0),f=e.duration/p,g=e.easing,m="up"===c||"down"===c?"top":"left",_="up"===c||"left"===c,v=0,b=a.queue().length;for(t.effects.createPlaceholder(a),o=a.css(m),u||(u=a["top"===m?"outerHeight":"outerWidth"]()/3),l&&(n={opacity:1},n[m]=o,a.css("opacity",0).css(m,_?2*-u:2*u).animate(n,f,g)),h&&(u/=Math.pow(2,d-1)),n={},n[m]=o;d>v;v++)s={},s[m]=(_?"-=":"+=")+u,a.animate(s,f,g).animate(n,f,g),u=h?2*u:u/2;h&&(s={opacity:0},s[m]=(_?"-=":"+=")+u,a.animate(s,f,g)),a.queue(i),t.effects.unshift(a,b,p+1)}),t.effects.define("clip","hide",function(e,i){var s,n={},o=t(this),a=e.direction||"vertical",r="both"===a,h=r||"horizontal"===a,l=r||"vertical"===a;s=o.cssClip(),n.clip={top:l?(s.bottom-s.top)/2:s.top,right:h?(s.right-s.left)/2:s.right,bottom:l?(s.bottom-s.top)/2:s.bottom,left:h?(s.right-s.left)/2:s.left},t.effects.createPlaceholder(o),"show"===e.mode&&(o.cssClip(n.clip),n.clip=s),o.animate(n,{queue:!1,duration:e.duration,easing:e.easing,complete:i})}),t.effects.define("drop","hide",function(e,i){var s,n=t(this),o=e.mode,a="show"===o,r=e.direction||"left",h="up"===r||"down"===r?"top":"left",l="up"===r||"left"===r?"-=":"+=",c="+="===l?"-=":"+=",u={opacity:0};t.effects.createPlaceholder(n),s=e.distance||n["top"===h?"outerHeight":"outerWidth"](!0)/2,u[h]=l+s,a&&(n.css(u),u[h]=c+s,u.opacity=1),n.animate(u,{queue:!1,duration:e.duration,easing:e.easing,complete:i})}),t.effects.define("explode","hide",function(e,i){function s(){b.push(this),b.length===u*d&&n()}function n(){p.css({visibility:"visible"}),t(b).remove(),i()}var o,a,r,h,l,c,u=e.pieces?Math.round(Math.sqrt(e.pieces)):3,d=u,p=t(this),f=e.mode,g="show"===f,m=p.show().css("visibility","hidden").offset(),_=Math.ceil(p.outerWidth()/d),v=Math.ceil(p.outerHeight()/u),b=[];for(o=0;u>o;o++)for(h=m.top+o*v,c=o-(u-1)/2,a=0;d>a;a++)r=m.left+a*_,l=a-(d-1)/2,p.clone().appendTo("body").wrap("<div></div>").css({position:"absolute",visibility:"visible",left:-a*_,top:-o*v}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:_,height:v,left:r+(g?l*_:0),top:h+(g?c*v:0),opacity:g?0:1}).animate({left:r+(g?0:l*_),top:h+(g?0:c*v),opacity:g?1:0},e.duration||500,e.easing,s)}),t.effects.define("fade","toggle",function(e,i){var s="show"===e.mode;t(this).css("opacity",s?0:1).animate({opacity:s?1:0},{queue:!1,duration:e.duration,easing:e.easing,complete:i})}),t.effects.define("fold","hide",function(e,i){var s=t(this),n=e.mode,o="show"===n,a="hide"===n,r=e.size||15,h=/([0-9]+)%/.exec(r),l=!!e.horizFirst,c=l?["right","bottom"]:["bottom","right"],u=e.duration/2,d=t.effects.createPlaceholder(s),p=s.cssClip(),f={clip:t.extend({},p)},g={clip:t.extend({},p)},m=[p[c[0]],p[c[1]]],_=s.queue().length;h&&(r=parseInt(h[1],10)/100*m[a?0:1]),f.clip[c[0]]=r,g.clip[c[0]]=r,g.clip[c[1]]=0,o&&(s.cssClip(g.clip),d&&d.css(t.effects.clipToBox(g)),g.clip=p),s.queue(function(i){d&&d.animate(t.effects.clipToBox(f),u,e.easing).animate(t.effects.clipToBox(g),u,e.easing),i()}).animate(f,u,e.easing).animate(g,u,e.easing).queue(i),t.effects.unshift(s,_,4)}),t.effects.define("highlight","show",function(e,i){var s=t(this),n={backgroundColor:s.css("backgroundColor")};"hide"===e.mode&&(n.opacity=0),t.effects.saveStyle(s),s.css({backgroundImage:"none",backgroundColor:e.color||"#ffff99"}).animate(n,{queue:!1,duration:e.duration,easing:e.easing,complete:i})}),t.effects.define("size",function(e,i){var s,n,o,a=t(this),r=["fontSize"],h=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],l=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],c=e.mode,u="effect"!==c,d=e.scale||"both",p=e.origin||["middle","center"],f=a.css("position"),g=a.position(),m=t.effects.scaledDimensions(a),_=e.from||m,v=e.to||t.effects.scaledDimensions(a,0);t.effects.createPlaceholder(a),"show"===c&&(o=_,_=v,v=o),n={from:{y:_.height/m.height,x:_.width/m.width},to:{y:v.height/m.height,x:v.width/m.width}},("box"===d||"both"===d)&&(n.from.y!==n.to.y&&(_=t.effects.setTransition(a,h,n.from.y,_),v=t.effects.setTransition(a,h,n.to.y,v)),n.from.x!==n.to.x&&(_=t.effects.setTransition(a,l,n.from.x,_),v=t.effects.setTransition(a,l,n.to.x,v))),("content"===d||"both"===d)&&n.from.y!==n.to.y&&(_=t.effects.setTransition(a,r,n.from.y,_),v=t.effects.setTransition(a,r,n.to.y,v)),p&&(s=t.effects.getBaseline(p,m),_.top=(m.outerHeight-_.outerHeight)*s.y+g.top,_.left=(m.outerWidth-_.outerWidth)*s.x+g.left,v.top=(m.outerHeight-v.outerHeight)*s.y+g.top,v.left=(m.outerWidth-v.outerWidth)*s.x+g.left),a.css(_),("content"===d||"both"===d)&&(h=h.concat(["marginTop","marginBottom"]).concat(r),l=l.concat(["marginLeft","marginRight"]),a.find("*[width]").each(function(){var i=t(this),s=t.effects.scaledDimensions(i),o={height:s.height*n.from.y,width:s.width*n.from.x,outerHeight:s.outerHeight*n.from.y,outerWidth:s.outerWidth*n.from.x},a={height:s.height*n.to.y,width:s.width*n.to.x,outerHeight:s.height*n.to.y,outerWidth:s.width*n.to.x};n.from.y!==n.to.y&&(o=t.effects.setTransition(i,h,n.from.y,o),a=t.effects.setTransition(i,h,n.to.y,a)),n.from.x!==n.to.x&&(o=t.effects.setTransition(i,l,n.from.x,o),a=t.effects.setTransition(i,l,n.to.x,a)),u&&t.effects.saveStyle(i),i.css(o),i.animate(a,e.duration,e.easing,function(){u&&t.effects.restoreStyle(i)})})),a.animate(v,{queue:!1,duration:e.duration,easing:e.easing,complete:function(){var e=a.offset();0===v.opacity&&a.css("opacity",_.opacity),u||(a.css("position","static"===f?"relative":f).offset(e),t.effects.saveStyle(a)),i()}})}),t.effects.define("scale",function(e,i){var s=t(this),n=e.mode,o=parseInt(e.percent,10)||(0===parseInt(e.percent,10)?0:"effect"!==n?0:100),a=t.extend(!0,{from:t.effects.scaledDimensions(s),to:t.effects.scaledDimensions(s,o,e.direction||"both"),origin:e.origin||["middle","center"]},e);e.fade&&(a.from.opacity=1,a.to.opacity=0),t.effects.effect.size.call(this,a,i)}),t.effects.define("puff","hide",function(e,i){var s=t.extend(!0,{},e,{fade:!0,percent:parseInt(e.percent,10)||150});t.effects.effect.scale.call(this,s,i)}),t.effects.define("pulsate","show",function(e,i){var s=t(this),n=e.mode,o="show"===n,a="hide"===n,r=o||a,h=2*(e.times||5)+(r?1:0),l=e.duration/h,c=0,u=1,d=s.queue().length;for((o||!s.is(":visible"))&&(s.css("opacity",0).show(),c=1);h>u;u++)s.animate({opacity:c},l,e.easing),c=1-c;s.animate({opacity:c},l,e.easing),s.queue(i),t.effects.unshift(s,d,h+1)}),t.effects.define("shake",function(e,i){var s=1,n=t(this),o=e.direction||"left",a=e.distance||20,r=e.times||3,h=2*r+1,l=Math.round(e.duration/h),c="up"===o||"down"===o?"top":"left",u="up"===o||"left"===o,d={},p={},f={},g=n.queue().length;for(t.effects.createPlaceholder(n),d[c]=(u?"-=":"+=")+a,p[c]=(u?"+=":"-=")+2*a,f[c]=(u?"-=":"+=")+2*a,n.animate(d,l,e.easing);r>s;s++)n.animate(p,l,e.easing).animate(f,l,e.easing);n.animate(p,l,e.easing).animate(d,l/2,e.easing).queue(i),t.effects.unshift(n,g,h+1)}),t.effects.define("slide","show",function(e,i){var s,n,o=t(this),a={up:["bottom","top"],down:["top","bottom"],left:["right","left"],right:["left","right"]},r=e.mode,h=e.direction||"left",l="up"===h||"down"===h?"top":"left",c="up"===h||"left"===h,u=e.distance||o["top"===l?"outerHeight":"outerWidth"](!0),d={};t.effects.createPlaceholder(o),s=o.cssClip(),n=o.position()[l],d[l]=(c?-1:1)*u+n,d.clip=o.cssClip(),d.clip[a[h][1]]=d.clip[a[h][0]],"show"===r&&(o.cssClip(d.clip),o.css(l,d[l]),d.clip=s,d[l]=n),o.animate(d,{queue:!1,duration:e.duration,easing:e.easing,complete:i})});var f;t.uiBackCompat!==!1&&(f=t.effects.define("transfer",function(e,i){t(this).transfer(e,i)})),t.ui.focusable=function(i,s){var n,o,a,r,h,l=i.nodeName.toLowerCase();return"area"===l?(n=i.parentNode,o=n.name,i.href&&o&&"map"===n.nodeName.toLowerCase()?(a=t("img[usemap='#"+o+"']"),a.length>0&&a.is(":visible")):!1):(/^(input|select|textarea|button|object)$/.test(l)?(r=!i.disabled,r&&(h=t(i).closest("fieldset")[0],h&&(r=!h.disabled))):r="a"===l?i.href||s:s,r&&t(i).is(":visible")&&e(t(i)))},t.extend(t.expr[":"],{focusable:function(e){return t.ui.focusable(e,null!=t.attr(e,"tabindex"))}}),t.ui.focusable,t.fn.form=function(){return"string"==typeof this[0].form?this.closest("form"):t(this[0].form)},t.ui.formResetMixin={_formResetHandler:function(){var e=t(this);setTimeout(function(){var i=e.data("ui-form-reset-instances");t.each(i,function(){this.refresh()})})},_bindFormResetHandler:function(){if(this.form=this.element.form(),this.form.length){var t=this.form.data("ui-form-reset-instances")||[];t.length||this.form.on("reset.ui-form-reset",this._formResetHandler),t.push(this),this.form.data("ui-form-reset-instances",t)}},_unbindFormResetHandler:function(){if(this.form.length){var e=this.form.data("ui-form-reset-instances");e.splice(t.inArray(this,e),1),e.length?this.form.data("ui-form-reset-instances",e):this.form.removeData("ui-form-reset-instances").off("reset.ui-form-reset")}}},"1.7"===t.fn.jquery.substring(0,3)&&(t.each(["Width","Height"],function(e,i){function s(e,i,s,o){return t.each(n,function(){i-=parseFloat(t.css(e,"padding"+this))||0,s&&(i-=parseFloat(t.css(e,"border"+this+"Width"))||0),o&&(i-=parseFloat(t.css(e,"margin"+this))||0)}),i}var n="Width"===i?["Left","Right"]:["Top","Bottom"],o=i.toLowerCase(),a={innerWidth:t.fn.innerWidth,innerHeight:t.fn.innerHeight,outerWidth:t.fn.outerWidth,outerHeight:t.fn.outerHeight};t.fn["inner"+i]=function(e){return void 0===e?a["inner"+i].call(this):this.each(function(){t(this).css(o,s(this,e)+"px")})},t.fn["outer"+i]=function(e,n){return"number"!=typeof e?a["outer"+i].call(this,e):this.each(function(){t(this).css(o,s(this,e,!0,n)+"px")})}}),t.fn.addBack=function(t){return this.add(null==t?this.prevObject:this.prevObject.filter(t))}),t.ui.keyCode={BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38},t.ui.escapeSelector=function(){var t=/([!"#$%&'()*+,.\/:;<=>?@[\]^`{|}~])/g;return function(e){return e.replace(t,"\\$1")}}(),t.fn.labels=function(){var e,i,s,n,o;return this[0].labels&&this[0].labels.length?this.pushStack(this[0].labels):(n=this.eq(0).parents("label"),s=this.attr("id"),s&&(e=this.eq(0).parents().last(),o=e.add(e.length?e.siblings():this.siblings()),i="label[for='"+t.ui.escapeSelector(s)+"']",n=n.add(o.find(i).addBack(i))),this.pushStack(n))},t.fn.scrollParent=function(e){var i=this.css("position"),s="absolute"===i,n=e?/(auto|scroll|hidden)/:/(auto|scroll)/,o=this.parents().filter(function(){var e=t(this);return s&&"static"===e.css("position")?!1:n.test(e.css("overflow")+e.css("overflow-y")+e.css("overflow-x"))}).eq(0);return"fixed"!==i&&o.length?o:t(this[0].ownerDocument||document)},t.extend(t.expr[":"],{tabbable:function(e){var i=t.attr(e,"tabindex"),s=null!=i;return(!s||i>=0)&&t.ui.focusable(e,s)}}),t.fn.extend({uniqueId:function(){var t=0;return function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++t)})}}(),removeUniqueId:function(){return this.each(function(){/^ui-id-\d+$/.test(this.id)&&t(this).removeAttr("id")})}}),t.widget("ui.accordion",{version:"1.12.1",options:{active:0,animate:{},classes:{"ui-accordion-header":"ui-corner-top","ui-accordion-header-collapsed":"ui-corner-all","ui-accordion-content":"ui-corner-bottom"},collapsible:!1,event:"click",header:"> li > :first-child, > :not(li):even",heightStyle:"auto",icons:{activeHeader:"ui-icon-triangle-1-s",header:"ui-icon-triangle-1-e"},activate:null,beforeActivate:null},hideProps:{borderTopWidth:"hide",borderBottomWidth:"hide",paddingTop:"hide",paddingBottom:"hide",height:"hide"},showProps:{borderTopWidth:"show",borderBottomWidth:"show",paddingTop:"show",paddingBottom:"show",height:"show"},_create:function(){var e=this.options;this.prevShow=this.prevHide=t(),this._addClass("ui-accordion","ui-widget ui-helper-reset"),this.element.attr("role","tablist"),e.collapsible||e.active!==!1&&null!=e.active||(e.active=0),this._processPanels(),0>e.active&&(e.active+=this.headers.length),this._refresh()},_getCreateEventData:function(){return{header:this.active,panel:this.active.length?this.active.next():t()}},_createIcons:function(){var e,i,s=this.options.icons;s&&(e=t("<span>"),this._addClass(e,"ui-accordion-header-icon","ui-icon "+s.header),e.prependTo(this.headers),i=this.active.children(".ui-accordion-header-icon"),this._removeClass(i,s.header)._addClass(i,null,s.activeHeader)._addClass(this.headers,"ui-accordion-icons"))},_destroyIcons:function(){this._removeClass(this.headers,"ui-accordion-icons"),this.headers.children(".ui-accordion-header-icon").remove()},_destroy:function(){var t;this.element.removeAttr("role"),this.headers.removeAttr("role aria-expanded aria-selected aria-controls tabIndex").removeUniqueId(),this._destroyIcons(),t=this.headers.next().css("display","").removeAttr("role aria-hidden aria-labelledby").removeUniqueId(),"content"!==this.options.heightStyle&&t.css("height","")},_setOption:function(t,e){return"active"===t?(this._activate(e),void 0):("event"===t&&(this.options.event&&this._off(this.headers,this.options.event),this._setupEvents(e)),this._super(t,e),"collapsible"!==t||e||this.options.active!==!1||this._activate(0),"icons"===t&&(this._destroyIcons(),e&&this._createIcons()),void 0)},_setOptionDisabled:function(t){this._super(t),this.element.attr("aria-disabled",t),this._toggleClass(null,"ui-state-disabled",!!t),this._toggleClass(this.headers.add(this.headers.next()),null,"ui-state-disabled",!!t)},_keydown:function(e){if(!e.altKey&&!e.ctrlKey){var i=t.ui.keyCode,s=this.headers.length,n=this.headers.index(e.target),o=!1;switch(e.keyCode){case i.RIGHT:case i.DOWN:o=this.headers[(n+1)%s];break;case i.LEFT:case i.UP:o=this.headers[(n-1+s)%s];break;case i.SPACE:case i.ENTER:this._eventHandler(e);break;case i.HOME:o=this.headers[0];break;case i.END:o=this.headers[s-1]}o&&(t(e.target).attr("tabIndex",-1),t(o).attr("tabIndex",0),t(o).trigger("focus"),e.preventDefault())}},_panelKeyDown:function(e){e.keyCode===t.ui.keyCode.UP&&e.ctrlKey&&t(e.currentTarget).prev().trigger("focus")},refresh:function(){var e=this.options;this._processPanels(),e.active===!1&&e.collapsible===!0||!this.headers.length?(e.active=!1,this.active=t()):e.active===!1?this._activate(0):this.active.length&&!t.contains(this.element[0],this.active[0])?this.headers.length===this.headers.find(".ui-state-disabled").length?(e.active=!1,this.active=t()):this._activate(Math.max(0,e.active-1)):e.active=this.headers.index(this.active),this._destroyIcons(),this._refresh()},_processPanels:function(){var t=this.headers,e=this.panels;this.headers=this.element.find(this.options.header),this._addClass(this.headers,"ui-accordion-header ui-accordion-header-collapsed","ui-state-default"),this.panels=this.headers.next().filter(":not(.ui-accordion-content-active)").hide(),this._addClass(this.panels,"ui-accordion-content","ui-helper-reset ui-widget-content"),e&&(this._off(t.not(this.headers)),this._off(e.not(this.panels)))},_refresh:function(){var e,i=this.options,s=i.heightStyle,n=this.element.parent();this.active=this._findActive(i.active),this._addClass(this.active,"ui-accordion-header-active","ui-state-active")._removeClass(this.active,"ui-accordion-header-collapsed"),this._addClass(this.active.next(),"ui-accordion-content-active"),this.active.next().show(),this.headers.attr("role","tab").each(function(){var e=t(this),i=e.uniqueId().attr("id"),s=e.next(),n=s.uniqueId().attr("id");e.attr("aria-controls",n),s.attr("aria-labelledby",i)}).next().attr("role","tabpanel"),this.headers.not(this.active).attr({"aria-selected":"false","aria-expanded":"false",tabIndex:-1}).next().attr({"aria-hidden":"true"}).hide(),this.active.length?this.active.attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0}).next().attr({"aria-hidden":"false"}):this.headers.eq(0).attr("tabIndex",0),this._createIcons(),this._setupEvents(i.event),"fill"===s?(e=n.height(),this.element.siblings(":visible").each(function(){var i=t(this),s=i.css("position");"absolute"!==s&&"fixed"!==s&&(e-=i.outerHeight(!0))}),this.headers.each(function(){e-=t(this).outerHeight(!0)}),this.headers.next().each(function(){t(this).height(Math.max(0,e-t(this).innerHeight()+t(this).height()))}).css("overflow","auto")):"auto"===s&&(e=0,this.headers.next().each(function(){var i=t(this).is(":visible");i||t(this).show(),e=Math.max(e,t(this).css("height","").height()),i||t(this).hide()}).height(e))},_activate:function(e){var i=this._findActive(e)[0];i!==this.active[0]&&(i=i||this.active[0],this._eventHandler({target:i,currentTarget:i,preventDefault:t.noop}))},_findActive:function(e){return"number"==typeof e?this.headers.eq(e):t()},_setupEvents:function(e){var i={keydown:"_keydown"};e&&t.each(e.split(" "),function(t,e){i[e]="_eventHandler"}),this._off(this.headers.add(this.headers.next())),this._on(this.headers,i),this._on(this.headers.next(),{keydown:"_panelKeyDown"}),this._hoverable(this.headers),this._focusable(this.headers)},_eventHandler:function(e){var i,s,n=this.options,o=this.active,a=t(e.currentTarget),r=a[0]===o[0],h=r&&n.collapsible,l=h?t():a.next(),c=o.next(),u={oldHeader:o,oldPanel:c,newHeader:h?t():a,newPanel:l};e.preventDefault(),r&&!n.collapsible||this._trigger("beforeActivate",e,u)===!1||(n.active=h?!1:this.headers.index(a),this.active=r?t():a,this._toggle(u),this._removeClass(o,"ui-accordion-header-active","ui-state-active"),n.icons&&(i=o.children(".ui-accordion-header-icon"),this._removeClass(i,null,n.icons.activeHeader)._addClass(i,null,n.icons.header)),r||(this._removeClass(a,"ui-accordion-header-collapsed")._addClass(a,"ui-accordion-header-active","ui-state-active"),n.icons&&(s=a.children(".ui-accordion-header-icon"),this._removeClass(s,null,n.icons.header)._addClass(s,null,n.icons.activeHeader)),this._addClass(a.next(),"ui-accordion-content-active")))},_toggle:function(e){var i=e.newPanel,s=this.prevShow.length?this.prevShow:e.oldPanel;this.prevShow.add(this.prevHide).stop(!0,!0),this.prevShow=i,this.prevHide=s,this.options.animate?this._animate(i,s,e):(s.hide(),i.show(),this._toggleComplete(e)),s.attr({"aria-hidden":"true"}),s.prev().attr({"aria-selected":"false","aria-expanded":"false"}),i.length&&s.length?s.prev().attr({tabIndex:-1,"aria-expanded":"false"}):i.length&&this.headers.filter(function(){return 0===parseInt(t(this).attr("tabIndex"),10)}).attr("tabIndex",-1),i.attr("aria-hidden","false").prev().attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0})},_animate:function(t,e,i){var s,n,o,a=this,r=0,h=t.css("box-sizing"),l=t.length&&(!e.length||t.index()<e.index()),c=this.options.animate||{},u=l&&c.down||c,d=function(){a._toggleComplete(i)};return"number"==typeof u&&(o=u),"string"==typeof u&&(n=u),n=n||u.easing||c.easing,o=o||u.duration||c.duration,e.length?t.length?(s=t.show().outerHeight(),e.animate(this.hideProps,{duration:o,easing:n,step:function(t,e){e.now=Math.round(t)}}),t.hide().animate(this.showProps,{duration:o,easing:n,complete:d,step:function(t,i){i.now=Math.round(t),"height"!==i.prop?"content-box"===h&&(r+=i.now):"content"!==a.options.heightStyle&&(i.now=Math.round(s-e.outerHeight()-r),r=0)}}),void 0):e.animate(this.hideProps,o,n,d):t.animate(this.showProps,o,n,d)},_toggleComplete:function(t){var e=t.oldPanel,i=e.prev();this._removeClass(e,"ui-accordion-content-active"),this._removeClass(i,"ui-accordion-header-active")._addClass(i,"ui-accordion-header-collapsed"),e.length&&(e.parent()[0].className=e.parent()[0].className),this._trigger("activate",null,t)}}),t.ui.safeActiveElement=function(t){var e;try{e=t.activeElement}catch(i){e=t.body}return e||(e=t.body),e.nodeName||(e=t.body),e},t.widget("ui.menu",{version:"1.12.1",defaultElement:"<ul>",delay:300,options:{icons:{submenu:"ui-icon-caret-1-e"},items:"> *",menus:"ul",position:{my:"left top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.mouseHandled=!1,this.element.uniqueId().attr({role:this.options.role,tabIndex:0}),this._addClass("ui-menu","ui-widget ui-widget-content"),this._on({"mousedown .ui-menu-item":function(t){t.preventDefault()},"click .ui-menu-item":function(e){var i=t(e.target),s=t(t.ui.safeActiveElement(this.document[0]));!this.mouseHandled&&i.not(".ui-state-disabled").length&&(this.select(e),e.isPropagationStopped()||(this.mouseHandled=!0),i.has(".ui-menu").length?this.expand(e):!this.element.is(":focus")&&s.closest(".ui-menu").length&&(this.element.trigger("focus",[!0]),this.active&&1===this.active.parents(".ui-menu").length&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":function(e){if(!this.previousFilter){var i=t(e.target).closest(".ui-menu-item"),s=t(e.currentTarget);i[0]===s[0]&&(this._removeClass(s.siblings().children(".ui-state-active"),null,"ui-state-active"),this.focus(e,s))}},mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(t,e){var i=this.active||this.element.find(this.options.items).eq(0);e||this.focus(t,i)},blur:function(e){this._delay(function(){var i=!t.contains(this.element[0],t.ui.safeActiveElement(this.document[0]));i&&this.collapseAll(e)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(t){this._closeOnDocumentClick(t)&&this.collapseAll(t),this.mouseHandled=!1}})},_destroy:function(){var e=this.element.find(".ui-menu-item").removeAttr("role aria-disabled"),i=e.children(".ui-menu-item-wrapper").removeUniqueId().removeAttr("tabIndex role aria-haspopup");this.element.removeAttr("aria-activedescendant").find(".ui-menu").addBack().removeAttr("role aria-labelledby aria-expanded aria-hidden aria-disabled tabIndex").removeUniqueId().show(),i.children().each(function(){var e=t(this);e.data("ui-menu-submenu-caret")&&e.remove()})},_keydown:function(e){var i,s,n,o,a=!0;switch(e.keyCode){case t.ui.keyCode.PAGE_UP:this.previousPage(e);break;case t.ui.keyCode.PAGE_DOWN:this.nextPage(e);break;case t.ui.keyCode.HOME:this._move("first","first",e);break;case t.ui.keyCode.END:this._move("last","last",e);break;case t.ui.keyCode.UP:this.previous(e);break;case t.ui.keyCode.DOWN:this.next(e);break;case t.ui.keyCode.LEFT:this.collapse(e);break;case t.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(e);break;case t.ui.keyCode.ENTER:case t.ui.keyCode.SPACE:this._activate(e);break;case t.ui.keyCode.ESCAPE:this.collapse(e);break;default:a=!1,s=this.previousFilter||"",o=!1,n=e.keyCode>=96&&105>=e.keyCode?""+(e.keyCode-96):String.fromCharCode(e.keyCode),clearTimeout(this.filterTimer),n===s?o=!0:n=s+n,i=this._filterMenuItems(n),i=o&&-1!==i.index(this.active.next())?this.active.nextAll(".ui-menu-item"):i,i.length||(n=String.fromCharCode(e.keyCode),i=this._filterMenuItems(n)),i.length?(this.focus(e,i),this.previousFilter=n,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter}a&&e.preventDefault()},_activate:function(t){this.active&&!this.active.is(".ui-state-disabled")&&(this.active.children("[aria-haspopup='true']").length?this.expand(t):this.select(t))},refresh:function(){var e,i,s,n,o,a=this,r=this.options.icons.submenu,h=this.element.find(this.options.menus);this._toggleClass("ui-menu-icons",null,!!this.element.find(".ui-icon").length),s=h.filter(":not(.ui-menu)").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"}).each(function(){var e=t(this),i=e.prev(),s=t("<span>").data("ui-menu-submenu-caret",!0);a._addClass(s,"ui-menu-icon","ui-icon "+r),i.attr("aria-haspopup","true").prepend(s),e.attr("aria-labelledby",i.attr("id"))}),this._addClass(s,"ui-menu","ui-widget ui-widget-content ui-front"),e=h.add(this.element),i=e.find(this.options.items),i.not(".ui-menu-item").each(function(){var e=t(this);a._isDivider(e)&&a._addClass(e,"ui-menu-divider","ui-widget-content")}),n=i.not(".ui-menu-item, .ui-menu-divider"),o=n.children().not(".ui-menu").uniqueId().attr({tabIndex:-1,role:this._itemRole()}),this._addClass(n,"ui-menu-item")._addClass(o,"ui-menu-item-wrapper"),i.filter(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!t.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},_setOption:function(t,e){if("icons"===t){var i=this.element.find(".ui-menu-icon");this._removeClass(i,null,this.options.icons.submenu)._addClass(i,null,e.submenu)}this._super(t,e)},_setOptionDisabled:function(t){this._super(t),this.element.attr("aria-disabled",t+""),this._toggleClass(null,"ui-state-disabled",!!t)},focus:function(t,e){var i,s,n;this.blur(t,t&&"focus"===t.type),this._scrollIntoView(e),this.active=e.first(),s=this.active.children(".ui-menu-item-wrapper"),this._addClass(s,null,"ui-state-active"),this.options.role&&this.element.attr("aria-activedescendant",s.attr("id")),n=this.active.parent().closest(".ui-menu-item").children(".ui-menu-item-wrapper"),this._addClass(n,null,"ui-state-active"),t&&"keydown"===t.type?this._close():this.timer=this._delay(function(){this._close()},this.delay),i=e.children(".ui-menu"),i.length&&t&&/^mouse/.test(t.type)&&this._startOpening(i),this.activeMenu=e.parent(),this._trigger("focus",t,{item:e})},_scrollIntoView:function(e){var i,s,n,o,a,r;this._hasScroll()&&(i=parseFloat(t.css(this.activeMenu[0],"borderTopWidth"))||0,s=parseFloat(t.css(this.activeMenu[0],"paddingTop"))||0,n=e.offset().top-this.activeMenu.offset().top-i-s,o=this.activeMenu.scrollTop(),a=this.activeMenu.height(),r=e.outerHeight(),0>n?this.activeMenu.scrollTop(o+n):n+r>a&&this.activeMenu.scrollTop(o+n-a+r))},blur:function(t,e){e||clearTimeout(this.timer),this.active&&(this._removeClass(this.active.children(".ui-menu-item-wrapper"),null,"ui-state-active"),this._trigger("blur",t,{item:this.active}),this.active=null)},_startOpening:function(t){clearTimeout(this.timer),"true"===t.attr("aria-hidden")&&(this.timer=this._delay(function(){this._close(),this._open(t)},this.delay))},_open:function(e){var i=t.extend({of:this.active},this.options.position);clearTimeout(this.timer),this.element.find(".ui-menu").not(e.parents(".ui-menu")).hide().attr("aria-hidden","true"),e.show().removeAttr("aria-hidden").attr("aria-expanded","true").position(i)},collapseAll:function(e,i){clearTimeout(this.timer),this.timer=this._delay(function(){var s=i?this.element:t(e&&e.target).closest(this.element.find(".ui-menu"));s.length||(s=this.element),this._close(s),this.blur(e),this._removeClass(s.find(".ui-state-active"),null,"ui-state-active"),this.activeMenu=s},this.delay)},_close:function(t){t||(t=this.active?this.active.parent():this.element),t.find(".ui-menu").hide().attr("aria-hidden","true").attr("aria-expanded","false")},_closeOnDocumentClick:function(e){return!t(e.target).closest(".ui-menu").length},_isDivider:function(t){return!/[^\-\u2014\u2013\s]/.test(t.text())},collapse:function(t){var e=this.active&&this.active.parent().closest(".ui-menu-item",this.element);e&&e.length&&(this._close(),this.focus(t,e))},expand:function(t){var e=this.active&&this.active.children(".ui-menu ").find(this.options.items).first();e&&e.length&&(this._open(e.parent()),this._delay(function(){this.focus(t,e)}))},next:function(t){this._move("next","first",t)},previous:function(t){this._move("prev","last",t)},isFirstItem:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},isLastItem:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},_move:function(t,e,i){var s;this.active&&(s="first"===t||"last"===t?this.active["first"===t?"prevAll":"nextAll"](".ui-menu-item").eq(-1):this.active[t+"All"](".ui-menu-item").eq(0)),s&&s.length&&this.active||(s=this.activeMenu.find(this.options.items)[e]()),this.focus(i,s)},nextPage:function(e){var i,s,n;return this.active?(this.isLastItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.nextAll(".ui-menu-item").each(function(){return i=t(this),0>i.offset().top-s-n}),this.focus(e,i)):this.focus(e,this.activeMenu.find(this.options.items)[this.active?"last":"first"]())),void 0):(this.next(e),void 0)},previousPage:function(e){var i,s,n;return this.active?(this.isFirstItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.prevAll(".ui-menu-item").each(function(){return i=t(this),i.offset().top-s+n>0}),this.focus(e,i)):this.focus(e,this.activeMenu.find(this.options.items).first())),void 0):(this.next(e),void 0)},_hasScroll:function(){return this.element.outerHeight()<this.element.prop("scrollHeight")},select:function(e){this.active=this.active||t(e.target).closest(".ui-menu-item");var i={item:this.active};this.active.has(".ui-menu").length||this.collapseAll(e,!0),this._trigger("select",e,i)},_filterMenuItems:function(e){var i=e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&"),s=RegExp("^"+i,"i");return this.activeMenu.find(this.options.items).filter(".ui-menu-item").filter(function(){return s.test(t.trim(t(this).children(".ui-menu-item-wrapper").text()))})}}),t.widget("ui.autocomplete",{version:"1.12.1",defaultElement:"<input>",options:{appendTo:null,autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},requestIndex:0,pending:0,_create:function(){var e,i,s,n=this.element[0].nodeName.toLowerCase(),o="textarea"===n,a="input"===n; -this.isMultiLine=o||!a&&this._isContentEditable(this.element),this.valueMethod=this.element[o||a?"val":"text"],this.isNewMenu=!0,this._addClass("ui-autocomplete-input"),this.element.attr("autocomplete","off"),this._on(this.element,{keydown:function(n){if(this.element.prop("readOnly"))return e=!0,s=!0,i=!0,void 0;e=!1,s=!1,i=!1;var o=t.ui.keyCode;switch(n.keyCode){case o.PAGE_UP:e=!0,this._move("previousPage",n);break;case o.PAGE_DOWN:e=!0,this._move("nextPage",n);break;case o.UP:e=!0,this._keyEvent("previous",n);break;case o.DOWN:e=!0,this._keyEvent("next",n);break;case o.ENTER:this.menu.active&&(e=!0,n.preventDefault(),this.menu.select(n));break;case o.TAB:this.menu.active&&this.menu.select(n);break;case o.ESCAPE:this.menu.element.is(":visible")&&(this.isMultiLine||this._value(this.term),this.close(n),n.preventDefault());break;default:i=!0,this._searchTimeout(n)}},keypress:function(s){if(e)return e=!1,(!this.isMultiLine||this.menu.element.is(":visible"))&&s.preventDefault(),void 0;if(!i){var n=t.ui.keyCode;switch(s.keyCode){case n.PAGE_UP:this._move("previousPage",s);break;case n.PAGE_DOWN:this._move("nextPage",s);break;case n.UP:this._keyEvent("previous",s);break;case n.DOWN:this._keyEvent("next",s)}}},input:function(t){return s?(s=!1,t.preventDefault(),void 0):(this._searchTimeout(t),void 0)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(t){return this.cancelBlur?(delete this.cancelBlur,void 0):(clearTimeout(this.searching),this.close(t),this._change(t),void 0)}}),this._initSource(),this.menu=t("<ul>").appendTo(this._appendTo()).menu({role:null}).hide().menu("instance"),this._addClass(this.menu.element,"ui-autocomplete","ui-front"),this._on(this.menu.element,{mousedown:function(e){e.preventDefault(),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur,this.element[0]!==t.ui.safeActiveElement(this.document[0])&&this.element.trigger("focus")})},menufocus:function(e,i){var s,n;return this.isNewMenu&&(this.isNewMenu=!1,e.originalEvent&&/^mouse/.test(e.originalEvent.type))?(this.menu.blur(),this.document.one("mousemove",function(){t(e.target).trigger(e.originalEvent)}),void 0):(n=i.item.data("ui-autocomplete-item"),!1!==this._trigger("focus",e,{item:n})&&e.originalEvent&&/^key/.test(e.originalEvent.type)&&this._value(n.value),s=i.item.attr("aria-label")||n.value,s&&t.trim(s).length&&(this.liveRegion.children().hide(),t("<div>").text(s).appendTo(this.liveRegion)),void 0)},menuselect:function(e,i){var s=i.item.data("ui-autocomplete-item"),n=this.previous;this.element[0]!==t.ui.safeActiveElement(this.document[0])&&(this.element.trigger("focus"),this.previous=n,this._delay(function(){this.previous=n,this.selectedItem=s})),!1!==this._trigger("select",e,{item:s})&&this._value(s.value),this.term=this._value(),this.close(e),this.selectedItem=s}}),this.liveRegion=t("<div>",{role:"status","aria-live":"assertive","aria-relevant":"additions"}).appendTo(this.document[0].body),this._addClass(this.liveRegion,null,"ui-helper-hidden-accessible"),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_destroy:function(){clearTimeout(this.searching),this.element.removeAttr("autocomplete"),this.menu.element.remove(),this.liveRegion.remove()},_setOption:function(t,e){this._super(t,e),"source"===t&&this._initSource(),"appendTo"===t&&this.menu.element.appendTo(this._appendTo()),"disabled"===t&&e&&this.xhr&&this.xhr.abort()},_isEventTargetInWidget:function(e){var i=this.menu.element[0];return e.target===this.element[0]||e.target===i||t.contains(i,e.target)},_closeOnClickOutside:function(t){this._isEventTargetInWidget(t)||this.close()},_appendTo:function(){var e=this.options.appendTo;return e&&(e=e.jquery||e.nodeType?t(e):this.document.find(e).eq(0)),e&&e[0]||(e=this.element.closest(".ui-front, dialog")),e.length||(e=this.document[0].body),e},_initSource:function(){var e,i,s=this;t.isArray(this.options.source)?(e=this.options.source,this.source=function(i,s){s(t.ui.autocomplete.filter(e,i.term))}):"string"==typeof this.options.source?(i=this.options.source,this.source=function(e,n){s.xhr&&s.xhr.abort(),s.xhr=t.ajax({url:i,data:e,dataType:"json",success:function(t){n(t)},error:function(){n([])}})}):this.source=this.options.source},_searchTimeout:function(t){clearTimeout(this.searching),this.searching=this._delay(function(){var e=this.term===this._value(),i=this.menu.element.is(":visible"),s=t.altKey||t.ctrlKey||t.metaKey||t.shiftKey;(!e||e&&!i&&!s)&&(this.selectedItem=null,this.search(null,t))},this.options.delay)},search:function(t,e){return t=null!=t?t:this._value(),this.term=this._value(),t.length<this.options.minLength?this.close(e):this._trigger("search",e)!==!1?this._search(t):void 0},_search:function(t){this.pending++,this._addClass("ui-autocomplete-loading"),this.cancelSearch=!1,this.source({term:t},this._response())},_response:function(){var e=++this.requestIndex;return t.proxy(function(t){e===this.requestIndex&&this.__response(t),this.pending--,this.pending||this._removeClass("ui-autocomplete-loading")},this)},__response:function(t){t&&(t=this._normalize(t)),this._trigger("response",null,{content:t}),!this.options.disabled&&t&&t.length&&!this.cancelSearch?(this._suggest(t),this._trigger("open")):this._close()},close:function(t){this.cancelSearch=!0,this._close(t)},_close:function(t){this._off(this.document,"mousedown"),this.menu.element.is(":visible")&&(this.menu.element.hide(),this.menu.blur(),this.isNewMenu=!0,this._trigger("close",t))},_change:function(t){this.previous!==this._value()&&this._trigger("change",t,{item:this.selectedItem})},_normalize:function(e){return e.length&&e[0].label&&e[0].value?e:t.map(e,function(e){return"string"==typeof e?{label:e,value:e}:t.extend({},e,{label:e.label||e.value,value:e.value||e.label})})},_suggest:function(e){var i=this.menu.element.empty();this._renderMenu(i,e),this.isNewMenu=!0,this.menu.refresh(),i.show(),this._resizeMenu(),i.position(t.extend({of:this.element},this.options.position)),this.options.autoFocus&&this.menu.next(),this._on(this.document,{mousedown:"_closeOnClickOutside"})},_resizeMenu:function(){var t=this.menu.element;t.outerWidth(Math.max(t.width("").outerWidth()+1,this.element.outerWidth()))},_renderMenu:function(e,i){var s=this;t.each(i,function(t,i){s._renderItemData(e,i)})},_renderItemData:function(t,e){return this._renderItem(t,e).data("ui-autocomplete-item",e)},_renderItem:function(e,i){return t("<li>").append(t("<div>").text(i.label)).appendTo(e)},_move:function(t,e){return this.menu.element.is(":visible")?this.menu.isFirstItem()&&/^previous/.test(t)||this.menu.isLastItem()&&/^next/.test(t)?(this.isMultiLine||this._value(this.term),this.menu.blur(),void 0):(this.menu[t](e),void 0):(this.search(null,e),void 0)},widget:function(){return this.menu.element},_value:function(){return this.valueMethod.apply(this.element,arguments)},_keyEvent:function(t,e){(!this.isMultiLine||this.menu.element.is(":visible"))&&(this._move(t,e),e.preventDefault())},_isContentEditable:function(t){if(!t.length)return!1;var e=t.prop("contentEditable");return"inherit"===e?this._isContentEditable(t.parent()):"true"===e}}),t.extend(t.ui.autocomplete,{escapeRegex:function(t){return t.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")},filter:function(e,i){var s=RegExp(t.ui.autocomplete.escapeRegex(i),"i");return t.grep(e,function(t){return s.test(t.label||t.value||t)})}}),t.widget("ui.autocomplete",t.ui.autocomplete,{options:{messages:{noResults:"No search results.",results:function(t){return t+(t>1?" results are":" result is")+" available, use up and down arrow keys to navigate."}}},__response:function(e){var i;this._superApply(arguments),this.options.disabled||this.cancelSearch||(i=e&&e.length?this.options.messages.results(e.length):this.options.messages.noResults,this.liveRegion.children().hide(),t("<div>").text(i).appendTo(this.liveRegion))}}),t.ui.autocomplete;var g=/ui-corner-([a-z]){2,6}/g;t.widget("ui.controlgroup",{version:"1.12.1",defaultElement:"<div>",options:{direction:"horizontal",disabled:null,onlyVisible:!0,items:{button:"input[type=button], input[type=submit], input[type=reset], button, a",controlgroupLabel:".ui-controlgroup-label",checkboxradio:"input[type='checkbox'], input[type='radio']",selectmenu:"select",spinner:".ui-spinner-input"}},_create:function(){this._enhance()},_enhance:function(){this.element.attr("role","toolbar"),this.refresh()},_destroy:function(){this._callChildMethod("destroy"),this.childWidgets.removeData("ui-controlgroup-data"),this.element.removeAttr("role"),this.options.items.controlgroupLabel&&this.element.find(this.options.items.controlgroupLabel).find(".ui-controlgroup-label-contents").contents().unwrap()},_initWidgets:function(){var e=this,i=[];t.each(this.options.items,function(s,n){var o,a={};return n?"controlgroupLabel"===s?(o=e.element.find(n),o.each(function(){var e=t(this);e.children(".ui-controlgroup-label-contents").length||e.contents().wrapAll("<span class='ui-controlgroup-label-contents'></span>")}),e._addClass(o,null,"ui-widget ui-widget-content ui-state-default"),i=i.concat(o.get()),void 0):(t.fn[s]&&(a=e["_"+s+"Options"]?e["_"+s+"Options"]("middle"):{classes:{}},e.element.find(n).each(function(){var n=t(this),o=n[s]("instance"),r=t.widget.extend({},a);if("button"!==s||!n.parent(".ui-spinner").length){o||(o=n[s]()[s]("instance")),o&&(r.classes=e._resolveClassesValues(r.classes,o)),n[s](r);var h=n[s]("widget");t.data(h[0],"ui-controlgroup-data",o?o:n[s]("instance")),i.push(h[0])}})),void 0):void 0}),this.childWidgets=t(t.unique(i)),this._addClass(this.childWidgets,"ui-controlgroup-item")},_callChildMethod:function(e){this.childWidgets.each(function(){var i=t(this),s=i.data("ui-controlgroup-data");s&&s[e]&&s[e]()})},_updateCornerClass:function(t,e){var i="ui-corner-top ui-corner-bottom ui-corner-left ui-corner-right ui-corner-all",s=this._buildSimpleOptions(e,"label").classes.label;this._removeClass(t,null,i),this._addClass(t,null,s)},_buildSimpleOptions:function(t,e){var i="vertical"===this.options.direction,s={classes:{}};return s.classes[e]={middle:"",first:"ui-corner-"+(i?"top":"left"),last:"ui-corner-"+(i?"bottom":"right"),only:"ui-corner-all"}[t],s},_spinnerOptions:function(t){var e=this._buildSimpleOptions(t,"ui-spinner");return e.classes["ui-spinner-up"]="",e.classes["ui-spinner-down"]="",e},_buttonOptions:function(t){return this._buildSimpleOptions(t,"ui-button")},_checkboxradioOptions:function(t){return this._buildSimpleOptions(t,"ui-checkboxradio-label")},_selectmenuOptions:function(t){var e="vertical"===this.options.direction;return{width:e?"auto":!1,classes:{middle:{"ui-selectmenu-button-open":"","ui-selectmenu-button-closed":""},first:{"ui-selectmenu-button-open":"ui-corner-"+(e?"top":"tl"),"ui-selectmenu-button-closed":"ui-corner-"+(e?"top":"left")},last:{"ui-selectmenu-button-open":e?"":"ui-corner-tr","ui-selectmenu-button-closed":"ui-corner-"+(e?"bottom":"right")},only:{"ui-selectmenu-button-open":"ui-corner-top","ui-selectmenu-button-closed":"ui-corner-all"}}[t]}},_resolveClassesValues:function(e,i){var s={};return t.each(e,function(n){var o=i.options.classes[n]||"";o=t.trim(o.replace(g,"")),s[n]=(o+" "+e[n]).replace(/\s+/g," ")}),s},_setOption:function(t,e){return"direction"===t&&this._removeClass("ui-controlgroup-"+this.options.direction),this._super(t,e),"disabled"===t?(this._callChildMethod(e?"disable":"enable"),void 0):(this.refresh(),void 0)},refresh:function(){var e,i=this;this._addClass("ui-controlgroup ui-controlgroup-"+this.options.direction),"horizontal"===this.options.direction&&this._addClass(null,"ui-helper-clearfix"),this._initWidgets(),e=this.childWidgets,this.options.onlyVisible&&(e=e.filter(":visible")),e.length&&(t.each(["first","last"],function(t,s){var n=e[s]().data("ui-controlgroup-data");if(n&&i["_"+n.widgetName+"Options"]){var o=i["_"+n.widgetName+"Options"](1===e.length?"only":s);o.classes=i._resolveClassesValues(o.classes,n),n.element[n.widgetName](o)}else i._updateCornerClass(e[s](),s)}),this._callChildMethod("refresh"))}}),t.widget("ui.checkboxradio",[t.ui.formResetMixin,{version:"1.12.1",options:{disabled:null,label:null,icon:!0,classes:{"ui-checkboxradio-label":"ui-corner-all","ui-checkboxradio-icon":"ui-corner-all"}},_getCreateOptions:function(){var e,i,s=this,n=this._super()||{};return this._readType(),i=this.element.labels(),this.label=t(i[i.length-1]),this.label.length||t.error("No label found for checkboxradio widget"),this.originalLabel="",this.label.contents().not(this.element[0]).each(function(){s.originalLabel+=3===this.nodeType?t(this).text():this.outerHTML}),this.originalLabel&&(n.label=this.originalLabel),e=this.element[0].disabled,null!=e&&(n.disabled=e),n},_create:function(){var t=this.element[0].checked;this._bindFormResetHandler(),null==this.options.disabled&&(this.options.disabled=this.element[0].disabled),this._setOption("disabled",this.options.disabled),this._addClass("ui-checkboxradio","ui-helper-hidden-accessible"),this._addClass(this.label,"ui-checkboxradio-label","ui-button ui-widget"),"radio"===this.type&&this._addClass(this.label,"ui-checkboxradio-radio-label"),this.options.label&&this.options.label!==this.originalLabel?this._updateLabel():this.originalLabel&&(this.options.label=this.originalLabel),this._enhance(),t&&(this._addClass(this.label,"ui-checkboxradio-checked","ui-state-active"),this.icon&&this._addClass(this.icon,null,"ui-state-hover")),this._on({change:"_toggleClasses",focus:function(){this._addClass(this.label,null,"ui-state-focus ui-visual-focus")},blur:function(){this._removeClass(this.label,null,"ui-state-focus ui-visual-focus")}})},_readType:function(){var e=this.element[0].nodeName.toLowerCase();this.type=this.element[0].type,"input"===e&&/radio|checkbox/.test(this.type)||t.error("Can't create checkboxradio on element.nodeName="+e+" and element.type="+this.type)},_enhance:function(){this._updateIcon(this.element[0].checked)},widget:function(){return this.label},_getRadioGroup:function(){var e,i=this.element[0].name,s="input[name='"+t.ui.escapeSelector(i)+"']";return i?(e=this.form.length?t(this.form[0].elements).filter(s):t(s).filter(function(){return 0===t(this).form().length}),e.not(this.element)):t([])},_toggleClasses:function(){var e=this.element[0].checked;this._toggleClass(this.label,"ui-checkboxradio-checked","ui-state-active",e),this.options.icon&&"checkbox"===this.type&&this._toggleClass(this.icon,null,"ui-icon-check ui-state-checked",e)._toggleClass(this.icon,null,"ui-icon-blank",!e),"radio"===this.type&&this._getRadioGroup().each(function(){var e=t(this).checkboxradio("instance");e&&e._removeClass(e.label,"ui-checkboxradio-checked","ui-state-active")})},_destroy:function(){this._unbindFormResetHandler(),this.icon&&(this.icon.remove(),this.iconSpace.remove())},_setOption:function(t,e){return"label"!==t||e?(this._super(t,e),"disabled"===t?(this._toggleClass(this.label,null,"ui-state-disabled",e),this.element[0].disabled=e,void 0):(this.refresh(),void 0)):void 0},_updateIcon:function(e){var i="ui-icon ui-icon-background ";this.options.icon?(this.icon||(this.icon=t("<span>"),this.iconSpace=t("<span> </span>"),this._addClass(this.iconSpace,"ui-checkboxradio-icon-space")),"checkbox"===this.type?(i+=e?"ui-icon-check ui-state-checked":"ui-icon-blank",this._removeClass(this.icon,null,e?"ui-icon-blank":"ui-icon-check")):i+="ui-icon-blank",this._addClass(this.icon,"ui-checkboxradio-icon",i),e||this._removeClass(this.icon,null,"ui-icon-check ui-state-checked"),this.icon.prependTo(this.label).after(this.iconSpace)):void 0!==this.icon&&(this.icon.remove(),this.iconSpace.remove(),delete this.icon)},_updateLabel:function(){var t=this.label.contents().not(this.element[0]);this.icon&&(t=t.not(this.icon[0])),this.iconSpace&&(t=t.not(this.iconSpace[0])),t.remove(),this.label.append(this.options.label)},refresh:function(){var t=this.element[0].checked,e=this.element[0].disabled;this._updateIcon(t),this._toggleClass(this.label,"ui-checkboxradio-checked","ui-state-active",t),null!==this.options.label&&this._updateLabel(),e!==this.options.disabled&&this._setOptions({disabled:e})}}]),t.ui.checkboxradio,t.widget("ui.button",{version:"1.12.1",defaultElement:"<button>",options:{classes:{"ui-button":"ui-corner-all"},disabled:null,icon:null,iconPosition:"beginning",label:null,showLabel:!0},_getCreateOptions:function(){var t,e=this._super()||{};return this.isInput=this.element.is("input"),t=this.element[0].disabled,null!=t&&(e.disabled=t),this.originalLabel=this.isInput?this.element.val():this.element.html(),this.originalLabel&&(e.label=this.originalLabel),e},_create:function(){!this.option.showLabel&!this.options.icon&&(this.options.showLabel=!0),null==this.options.disabled&&(this.options.disabled=this.element[0].disabled||!1),this.hasTitle=!!this.element.attr("title"),this.options.label&&this.options.label!==this.originalLabel&&(this.isInput?this.element.val(this.options.label):this.element.html(this.options.label)),this._addClass("ui-button","ui-widget"),this._setOption("disabled",this.options.disabled),this._enhance(),this.element.is("a")&&this._on({keyup:function(e){e.keyCode===t.ui.keyCode.SPACE&&(e.preventDefault(),this.element[0].click?this.element[0].click():this.element.trigger("click"))}})},_enhance:function(){this.element.is("button")||this.element.attr("role","button"),this.options.icon&&(this._updateIcon("icon",this.options.icon),this._updateTooltip())},_updateTooltip:function(){this.title=this.element.attr("title"),this.options.showLabel||this.title||this.element.attr("title",this.options.label)},_updateIcon:function(e,i){var s="iconPosition"!==e,n=s?this.options.iconPosition:i,o="top"===n||"bottom"===n;this.icon?s&&this._removeClass(this.icon,null,this.options.icon):(this.icon=t("<span>"),this._addClass(this.icon,"ui-button-icon","ui-icon"),this.options.showLabel||this._addClass("ui-button-icon-only")),s&&this._addClass(this.icon,null,i),this._attachIcon(n),o?(this._addClass(this.icon,null,"ui-widget-icon-block"),this.iconSpace&&this.iconSpace.remove()):(this.iconSpace||(this.iconSpace=t("<span> </span>"),this._addClass(this.iconSpace,"ui-button-icon-space")),this._removeClass(this.icon,null,"ui-wiget-icon-block"),this._attachIconSpace(n))},_destroy:function(){this.element.removeAttr("role"),this.icon&&this.icon.remove(),this.iconSpace&&this.iconSpace.remove(),this.hasTitle||this.element.removeAttr("title")},_attachIconSpace:function(t){this.icon[/^(?:end|bottom)/.test(t)?"before":"after"](this.iconSpace)},_attachIcon:function(t){this.element[/^(?:end|bottom)/.test(t)?"append":"prepend"](this.icon)},_setOptions:function(t){var e=void 0===t.showLabel?this.options.showLabel:t.showLabel,i=void 0===t.icon?this.options.icon:t.icon;e||i||(t.showLabel=!0),this._super(t)},_setOption:function(t,e){"icon"===t&&(e?this._updateIcon(t,e):this.icon&&(this.icon.remove(),this.iconSpace&&this.iconSpace.remove())),"iconPosition"===t&&this._updateIcon(t,e),"showLabel"===t&&(this._toggleClass("ui-button-icon-only",null,!e),this._updateTooltip()),"label"===t&&(this.isInput?this.element.val(e):(this.element.html(e),this.icon&&(this._attachIcon(this.options.iconPosition),this._attachIconSpace(this.options.iconPosition)))),this._super(t,e),"disabled"===t&&(this._toggleClass(null,"ui-state-disabled",e),this.element[0].disabled=e,e&&this.element.blur())},refresh:function(){var t=this.element.is("input, button")?this.element[0].disabled:this.element.hasClass("ui-button-disabled");t!==this.options.disabled&&this._setOptions({disabled:t}),this._updateTooltip()}}),t.uiBackCompat!==!1&&(t.widget("ui.button",t.ui.button,{options:{text:!0,icons:{primary:null,secondary:null}},_create:function(){this.options.showLabel&&!this.options.text&&(this.options.showLabel=this.options.text),!this.options.showLabel&&this.options.text&&(this.options.text=this.options.showLabel),this.options.icon||!this.options.icons.primary&&!this.options.icons.secondary?this.options.icon&&(this.options.icons.primary=this.options.icon):this.options.icons.primary?this.options.icon=this.options.icons.primary:(this.options.icon=this.options.icons.secondary,this.options.iconPosition="end"),this._super()},_setOption:function(t,e){return"text"===t?(this._super("showLabel",e),void 0):("showLabel"===t&&(this.options.text=e),"icon"===t&&(this.options.icons.primary=e),"icons"===t&&(e.primary?(this._super("icon",e.primary),this._super("iconPosition","beginning")):e.secondary&&(this._super("icon",e.secondary),this._super("iconPosition","end"))),this._superApply(arguments),void 0)}}),t.fn.button=function(e){return function(){return!this.length||this.length&&"INPUT"!==this[0].tagName||this.length&&"INPUT"===this[0].tagName&&"checkbox"!==this.attr("type")&&"radio"!==this.attr("type")?e.apply(this,arguments):(t.ui.checkboxradio||t.error("Checkboxradio widget missing"),0===arguments.length?this.checkboxradio({icon:!1}):this.checkboxradio.apply(this,arguments))}}(t.fn.button),t.fn.buttonset=function(){return t.ui.controlgroup||t.error("Controlgroup widget missing"),"option"===arguments[0]&&"items"===arguments[1]&&arguments[2]?this.controlgroup.apply(this,[arguments[0],"items.button",arguments[2]]):"option"===arguments[0]&&"items"===arguments[1]?this.controlgroup.apply(this,[arguments[0],"items.button"]):("object"==typeof arguments[0]&&arguments[0].items&&(arguments[0].items={button:arguments[0].items}),this.controlgroup.apply(this,arguments))}),t.ui.button,t.extend(t.ui,{datepicker:{version:"1.12.1"}});var m;t.extend(s.prototype,{markerClassName:"hasDatepicker",maxRows:4,_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(t){return a(this._defaults,t||{}),this},_attachDatepicker:function(e,i){var s,n,o;s=e.nodeName.toLowerCase(),n="div"===s||"span"===s,e.id||(this.uuid+=1,e.id="dp"+this.uuid),o=this._newInst(t(e),n),o.settings=t.extend({},i||{}),"input"===s?this._connectDatepicker(e,o):n&&this._inlineDatepicker(e,o)},_newInst:function(e,i){var s=e[0].id.replace(/([^A-Za-z0-9_\-])/g,"\\\\$1");return{id:s,input:e,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:i,dpDiv:i?n(t("<div class='"+this._inlineClass+" ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")):this.dpDiv}},_connectDatepicker:function(e,i){var s=t(e);i.append=t([]),i.trigger=t([]),s.hasClass(this.markerClassName)||(this._attachments(s,i),s.addClass(this.markerClassName).on("keydown",this._doKeyDown).on("keypress",this._doKeyPress).on("keyup",this._doKeyUp),this._autoSize(i),t.data(e,"datepicker",i),i.settings.disabled&&this._disableDatepicker(e))},_attachments:function(e,i){var s,n,o,a=this._get(i,"appendText"),r=this._get(i,"isRTL");i.append&&i.append.remove(),a&&(i.append=t("<span class='"+this._appendClass+"'>"+a+"</span>"),e[r?"before":"after"](i.append)),e.off("focus",this._showDatepicker),i.trigger&&i.trigger.remove(),s=this._get(i,"showOn"),("focus"===s||"both"===s)&&e.on("focus",this._showDatepicker),("button"===s||"both"===s)&&(n=this._get(i,"buttonText"),o=this._get(i,"buttonImage"),i.trigger=t(this._get(i,"buttonImageOnly")?t("<img/>").addClass(this._triggerClass).attr({src:o,alt:n,title:n}):t("<button type='button'></button>").addClass(this._triggerClass).html(o?t("<img/>").attr({src:o,alt:n,title:n}):n)),e[r?"before":"after"](i.trigger),i.trigger.on("click",function(){return t.datepicker._datepickerShowing&&t.datepicker._lastInput===e[0]?t.datepicker._hideDatepicker():t.datepicker._datepickerShowing&&t.datepicker._lastInput!==e[0]?(t.datepicker._hideDatepicker(),t.datepicker._showDatepicker(e[0])):t.datepicker._showDatepicker(e[0]),!1}))},_autoSize:function(t){if(this._get(t,"autoSize")&&!t.inline){var e,i,s,n,o=new Date(2009,11,20),a=this._get(t,"dateFormat");a.match(/[DM]/)&&(e=function(t){for(i=0,s=0,n=0;t.length>n;n++)t[n].length>i&&(i=t[n].length,s=n);return s},o.setMonth(e(this._get(t,a.match(/MM/)?"monthNames":"monthNamesShort"))),o.setDate(e(this._get(t,a.match(/DD/)?"dayNames":"dayNamesShort"))+20-o.getDay())),t.input.attr("size",this._formatDate(t,o).length)}},_inlineDatepicker:function(e,i){var s=t(e);s.hasClass(this.markerClassName)||(s.addClass(this.markerClassName).append(i.dpDiv),t.data(e,"datepicker",i),this._setDate(i,this._getDefaultDate(i),!0),this._updateDatepicker(i),this._updateAlternate(i),i.settings.disabled&&this._disableDatepicker(e),i.dpDiv.css("display","block"))},_dialogDatepicker:function(e,i,s,n,o){var r,h,l,c,u,d=this._dialogInst;return d||(this.uuid+=1,r="dp"+this.uuid,this._dialogInput=t("<input type='text' id='"+r+"' style='position: absolute; top: -100px; width: 0px;'/>"),this._dialogInput.on("keydown",this._doKeyDown),t("body").append(this._dialogInput),d=this._dialogInst=this._newInst(this._dialogInput,!1),d.settings={},t.data(this._dialogInput[0],"datepicker",d)),a(d.settings,n||{}),i=i&&i.constructor===Date?this._formatDate(d,i):i,this._dialogInput.val(i),this._pos=o?o.length?o:[o.pageX,o.pageY]:null,this._pos||(h=document.documentElement.clientWidth,l=document.documentElement.clientHeight,c=document.documentElement.scrollLeft||document.body.scrollLeft,u=document.documentElement.scrollTop||document.body.scrollTop,this._pos=[h/2-100+c,l/2-150+u]),this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px"),d.settings.onSelect=s,this._inDialog=!0,this.dpDiv.addClass(this._dialogClass),this._showDatepicker(this._dialogInput[0]),t.blockUI&&t.blockUI(this.dpDiv),t.data(this._dialogInput[0],"datepicker",d),this},_destroyDatepicker:function(e){var i,s=t(e),n=t.data(e,"datepicker");s.hasClass(this.markerClassName)&&(i=e.nodeName.toLowerCase(),t.removeData(e,"datepicker"),"input"===i?(n.append.remove(),n.trigger.remove(),s.removeClass(this.markerClassName).off("focus",this._showDatepicker).off("keydown",this._doKeyDown).off("keypress",this._doKeyPress).off("keyup",this._doKeyUp)):("div"===i||"span"===i)&&s.removeClass(this.markerClassName).empty(),m===n&&(m=null))},_enableDatepicker:function(e){var i,s,n=t(e),o=t.data(e,"datepicker");n.hasClass(this.markerClassName)&&(i=e.nodeName.toLowerCase(),"input"===i?(e.disabled=!1,o.trigger.filter("button").each(function(){this.disabled=!1}).end().filter("img").css({opacity:"1.0",cursor:""})):("div"===i||"span"===i)&&(s=n.children("."+this._inlineClass),s.children().removeClass("ui-state-disabled"),s.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!1)),this._disabledInputs=t.map(this._disabledInputs,function(t){return t===e?null:t}))},_disableDatepicker:function(e){var i,s,n=t(e),o=t.data(e,"datepicker");n.hasClass(this.markerClassName)&&(i=e.nodeName.toLowerCase(),"input"===i?(e.disabled=!0,o.trigger.filter("button").each(function(){this.disabled=!0}).end().filter("img").css({opacity:"0.5",cursor:"default"})):("div"===i||"span"===i)&&(s=n.children("."+this._inlineClass),s.children().addClass("ui-state-disabled"),s.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!0)),this._disabledInputs=t.map(this._disabledInputs,function(t){return t===e?null:t}),this._disabledInputs[this._disabledInputs.length]=e)},_isDisabledDatepicker:function(t){if(!t)return!1;for(var e=0;this._disabledInputs.length>e;e++)if(this._disabledInputs[e]===t)return!0;return!1},_getInst:function(e){try{return t.data(e,"datepicker")}catch(i){throw"Missing instance data for this datepicker"}},_optionDatepicker:function(e,i,s){var n,o,r,h,l=this._getInst(e);return 2===arguments.length&&"string"==typeof i?"defaults"===i?t.extend({},t.datepicker._defaults):l?"all"===i?t.extend({},l.settings):this._get(l,i):null:(n=i||{},"string"==typeof i&&(n={},n[i]=s),l&&(this._curInst===l&&this._hideDatepicker(),o=this._getDateDatepicker(e,!0),r=this._getMinMaxDate(l,"min"),h=this._getMinMaxDate(l,"max"),a(l.settings,n),null!==r&&void 0!==n.dateFormat&&void 0===n.minDate&&(l.settings.minDate=this._formatDate(l,r)),null!==h&&void 0!==n.dateFormat&&void 0===n.maxDate&&(l.settings.maxDate=this._formatDate(l,h)),"disabled"in n&&(n.disabled?this._disableDatepicker(e):this._enableDatepicker(e)),this._attachments(t(e),l),this._autoSize(l),this._setDate(l,o),this._updateAlternate(l),this._updateDatepicker(l)),void 0)},_changeDatepicker:function(t,e,i){this._optionDatepicker(t,e,i)},_refreshDatepicker:function(t){var e=this._getInst(t);e&&this._updateDatepicker(e)},_setDateDatepicker:function(t,e){var i=this._getInst(t);i&&(this._setDate(i,e),this._updateDatepicker(i),this._updateAlternate(i))},_getDateDatepicker:function(t,e){var i=this._getInst(t);return i&&!i.inline&&this._setDateFromField(i,e),i?this._getDate(i):null},_doKeyDown:function(e){var i,s,n,o=t.datepicker._getInst(e.target),a=!0,r=o.dpDiv.is(".ui-datepicker-rtl");if(o._keyEvent=!0,t.datepicker._datepickerShowing)switch(e.keyCode){case 9:t.datepicker._hideDatepicker(),a=!1;break;case 13:return n=t("td."+t.datepicker._dayOverClass+":not(."+t.datepicker._currentClass+")",o.dpDiv),n[0]&&t.datepicker._selectDay(e.target,o.selectedMonth,o.selectedYear,n[0]),i=t.datepicker._get(o,"onSelect"),i?(s=t.datepicker._formatDate(o),i.apply(o.input?o.input[0]:null,[s,o])):t.datepicker._hideDatepicker(),!1;case 27:t.datepicker._hideDatepicker();break;case 33:t.datepicker._adjustDate(e.target,e.ctrlKey?-t.datepicker._get(o,"stepBigMonths"):-t.datepicker._get(o,"stepMonths"),"M");break;case 34:t.datepicker._adjustDate(e.target,e.ctrlKey?+t.datepicker._get(o,"stepBigMonths"):+t.datepicker._get(o,"stepMonths"),"M");break;case 35:(e.ctrlKey||e.metaKey)&&t.datepicker._clearDate(e.target),a=e.ctrlKey||e.metaKey;break;case 36:(e.ctrlKey||e.metaKey)&&t.datepicker._gotoToday(e.target),a=e.ctrlKey||e.metaKey;break;case 37:(e.ctrlKey||e.metaKey)&&t.datepicker._adjustDate(e.target,r?1:-1,"D"),a=e.ctrlKey||e.metaKey,e.originalEvent.altKey&&t.datepicker._adjustDate(e.target,e.ctrlKey?-t.datepicker._get(o,"stepBigMonths"):-t.datepicker._get(o,"stepMonths"),"M");break;case 38:(e.ctrlKey||e.metaKey)&&t.datepicker._adjustDate(e.target,-7,"D"),a=e.ctrlKey||e.metaKey;break;case 39:(e.ctrlKey||e.metaKey)&&t.datepicker._adjustDate(e.target,r?-1:1,"D"),a=e.ctrlKey||e.metaKey,e.originalEvent.altKey&&t.datepicker._adjustDate(e.target,e.ctrlKey?+t.datepicker._get(o,"stepBigMonths"):+t.datepicker._get(o,"stepMonths"),"M");break;case 40:(e.ctrlKey||e.metaKey)&&t.datepicker._adjustDate(e.target,7,"D"),a=e.ctrlKey||e.metaKey;break;default:a=!1}else 36===e.keyCode&&e.ctrlKey?t.datepicker._showDatepicker(this):a=!1;a&&(e.preventDefault(),e.stopPropagation())},_doKeyPress:function(e){var i,s,n=t.datepicker._getInst(e.target);return t.datepicker._get(n,"constrainInput")?(i=t.datepicker._possibleChars(t.datepicker._get(n,"dateFormat")),s=String.fromCharCode(null==e.charCode?e.keyCode:e.charCode),e.ctrlKey||e.metaKey||" ">s||!i||i.indexOf(s)>-1):void 0},_doKeyUp:function(e){var i,s=t.datepicker._getInst(e.target);if(s.input.val()!==s.lastVal)try{i=t.datepicker.parseDate(t.datepicker._get(s,"dateFormat"),s.input?s.input.val():null,t.datepicker._getFormatConfig(s)),i&&(t.datepicker._setDateFromField(s),t.datepicker._updateAlternate(s),t.datepicker._updateDatepicker(s))}catch(n){}return!0},_showDatepicker:function(e){if(e=e.target||e,"input"!==e.nodeName.toLowerCase()&&(e=t("input",e.parentNode)[0]),!t.datepicker._isDisabledDatepicker(e)&&t.datepicker._lastInput!==e){var s,n,o,r,h,l,c;s=t.datepicker._getInst(e),t.datepicker._curInst&&t.datepicker._curInst!==s&&(t.datepicker._curInst.dpDiv.stop(!0,!0),s&&t.datepicker._datepickerShowing&&t.datepicker._hideDatepicker(t.datepicker._curInst.input[0])),n=t.datepicker._get(s,"beforeShow"),o=n?n.apply(e,[e,s]):{},o!==!1&&(a(s.settings,o),s.lastVal=null,t.datepicker._lastInput=e,t.datepicker._setDateFromField(s),t.datepicker._inDialog&&(e.value=""),t.datepicker._pos||(t.datepicker._pos=t.datepicker._findPos(e),t.datepicker._pos[1]+=e.offsetHeight),r=!1,t(e).parents().each(function(){return r|="fixed"===t(this).css("position"),!r}),h={left:t.datepicker._pos[0],top:t.datepicker._pos[1]},t.datepicker._pos=null,s.dpDiv.empty(),s.dpDiv.css({position:"absolute",display:"block",top:"-1000px"}),t.datepicker._updateDatepicker(s),h=t.datepicker._checkOffset(s,h,r),s.dpDiv.css({position:t.datepicker._inDialog&&t.blockUI?"static":r?"fixed":"absolute",display:"none",left:h.left+"px",top:h.top+"px"}),s.inline||(l=t.datepicker._get(s,"showAnim"),c=t.datepicker._get(s,"duration"),s.dpDiv.css("z-index",i(t(e))+1),t.datepicker._datepickerShowing=!0,t.effects&&t.effects.effect[l]?s.dpDiv.show(l,t.datepicker._get(s,"showOptions"),c):s.dpDiv[l||"show"](l?c:null),t.datepicker._shouldFocusInput(s)&&s.input.trigger("focus"),t.datepicker._curInst=s)) -}},_updateDatepicker:function(e){this.maxRows=4,m=e,e.dpDiv.empty().append(this._generateHTML(e)),this._attachHandlers(e);var i,s=this._getNumberOfMonths(e),n=s[1],a=17,r=e.dpDiv.find("."+this._dayOverClass+" a");r.length>0&&o.apply(r.get(0)),e.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""),n>1&&e.dpDiv.addClass("ui-datepicker-multi-"+n).css("width",a*n+"em"),e.dpDiv[(1!==s[0]||1!==s[1]?"add":"remove")+"Class"]("ui-datepicker-multi"),e.dpDiv[(this._get(e,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl"),e===t.datepicker._curInst&&t.datepicker._datepickerShowing&&t.datepicker._shouldFocusInput(e)&&e.input.trigger("focus"),e.yearshtml&&(i=e.yearshtml,setTimeout(function(){i===e.yearshtml&&e.yearshtml&&e.dpDiv.find("select.ui-datepicker-year:first").replaceWith(e.yearshtml),i=e.yearshtml=null},0))},_shouldFocusInput:function(t){return t.input&&t.input.is(":visible")&&!t.input.is(":disabled")&&!t.input.is(":focus")},_checkOffset:function(e,i,s){var n=e.dpDiv.outerWidth(),o=e.dpDiv.outerHeight(),a=e.input?e.input.outerWidth():0,r=e.input?e.input.outerHeight():0,h=document.documentElement.clientWidth+(s?0:t(document).scrollLeft()),l=document.documentElement.clientHeight+(s?0:t(document).scrollTop());return i.left-=this._get(e,"isRTL")?n-a:0,i.left-=s&&i.left===e.input.offset().left?t(document).scrollLeft():0,i.top-=s&&i.top===e.input.offset().top+r?t(document).scrollTop():0,i.left-=Math.min(i.left,i.left+n>h&&h>n?Math.abs(i.left+n-h):0),i.top-=Math.min(i.top,i.top+o>l&&l>o?Math.abs(o+r):0),i},_findPos:function(e){for(var i,s=this._getInst(e),n=this._get(s,"isRTL");e&&("hidden"===e.type||1!==e.nodeType||t.expr.filters.hidden(e));)e=e[n?"previousSibling":"nextSibling"];return i=t(e).offset(),[i.left,i.top]},_hideDatepicker:function(e){var i,s,n,o,a=this._curInst;!a||e&&a!==t.data(e,"datepicker")||this._datepickerShowing&&(i=this._get(a,"showAnim"),s=this._get(a,"duration"),n=function(){t.datepicker._tidyDialog(a)},t.effects&&(t.effects.effect[i]||t.effects[i])?a.dpDiv.hide(i,t.datepicker._get(a,"showOptions"),s,n):a.dpDiv["slideDown"===i?"slideUp":"fadeIn"===i?"fadeOut":"hide"](i?s:null,n),i||n(),this._datepickerShowing=!1,o=this._get(a,"onClose"),o&&o.apply(a.input?a.input[0]:null,[a.input?a.input.val():"",a]),this._lastInput=null,this._inDialog&&(this._dialogInput.css({position:"absolute",left:"0",top:"-100px"}),t.blockUI&&(t.unblockUI(),t("body").append(this.dpDiv))),this._inDialog=!1)},_tidyDialog:function(t){t.dpDiv.removeClass(this._dialogClass).off(".ui-datepicker-calendar")},_checkExternalClick:function(e){if(t.datepicker._curInst){var i=t(e.target),s=t.datepicker._getInst(i[0]);(i[0].id!==t.datepicker._mainDivId&&0===i.parents("#"+t.datepicker._mainDivId).length&&!i.hasClass(t.datepicker.markerClassName)&&!i.closest("."+t.datepicker._triggerClass).length&&t.datepicker._datepickerShowing&&(!t.datepicker._inDialog||!t.blockUI)||i.hasClass(t.datepicker.markerClassName)&&t.datepicker._curInst!==s)&&t.datepicker._hideDatepicker()}},_adjustDate:function(e,i,s){var n=t(e),o=this._getInst(n[0]);this._isDisabledDatepicker(n[0])||(this._adjustInstDate(o,i+("M"===s?this._get(o,"showCurrentAtPos"):0),s),this._updateDatepicker(o))},_gotoToday:function(e){var i,s=t(e),n=this._getInst(s[0]);this._get(n,"gotoCurrent")&&n.currentDay?(n.selectedDay=n.currentDay,n.drawMonth=n.selectedMonth=n.currentMonth,n.drawYear=n.selectedYear=n.currentYear):(i=new Date,n.selectedDay=i.getDate(),n.drawMonth=n.selectedMonth=i.getMonth(),n.drawYear=n.selectedYear=i.getFullYear()),this._notifyChange(n),this._adjustDate(s)},_selectMonthYear:function(e,i,s){var n=t(e),o=this._getInst(n[0]);o["selected"+("M"===s?"Month":"Year")]=o["draw"+("M"===s?"Month":"Year")]=parseInt(i.options[i.selectedIndex].value,10),this._notifyChange(o),this._adjustDate(n)},_selectDay:function(e,i,s,n){var o,a=t(e);t(n).hasClass(this._unselectableClass)||this._isDisabledDatepicker(a[0])||(o=this._getInst(a[0]),o.selectedDay=o.currentDay=t("a",n).html(),o.selectedMonth=o.currentMonth=i,o.selectedYear=o.currentYear=s,this._selectDate(e,this._formatDate(o,o.currentDay,o.currentMonth,o.currentYear)))},_clearDate:function(e){var i=t(e);this._selectDate(i,"")},_selectDate:function(e,i){var s,n=t(e),o=this._getInst(n[0]);i=null!=i?i:this._formatDate(o),o.input&&o.input.val(i),this._updateAlternate(o),s=this._get(o,"onSelect"),s?s.apply(o.input?o.input[0]:null,[i,o]):o.input&&o.input.trigger("change"),o.inline?this._updateDatepicker(o):(this._hideDatepicker(),this._lastInput=o.input[0],"object"!=typeof o.input[0]&&o.input.trigger("focus"),this._lastInput=null)},_updateAlternate:function(e){var i,s,n,o=this._get(e,"altField");o&&(i=this._get(e,"altFormat")||this._get(e,"dateFormat"),s=this._getDate(e),n=this.formatDate(i,s,this._getFormatConfig(e)),t(o).val(n))},noWeekends:function(t){var e=t.getDay();return[e>0&&6>e,""]},iso8601Week:function(t){var e,i=new Date(t.getTime());return i.setDate(i.getDate()+4-(i.getDay()||7)),e=i.getTime(),i.setMonth(0),i.setDate(1),Math.floor(Math.round((e-i)/864e5)/7)+1},parseDate:function(e,i,s){if(null==e||null==i)throw"Invalid arguments";if(i="object"==typeof i?""+i:i+"",""===i)return null;var n,o,a,r,h=0,l=(s?s.shortYearCutoff:null)||this._defaults.shortYearCutoff,c="string"!=typeof l?l:(new Date).getFullYear()%100+parseInt(l,10),u=(s?s.dayNamesShort:null)||this._defaults.dayNamesShort,d=(s?s.dayNames:null)||this._defaults.dayNames,p=(s?s.monthNamesShort:null)||this._defaults.monthNamesShort,f=(s?s.monthNames:null)||this._defaults.monthNames,g=-1,m=-1,_=-1,v=-1,b=!1,y=function(t){var i=e.length>n+1&&e.charAt(n+1)===t;return i&&n++,i},w=function(t){var e=y(t),s="@"===t?14:"!"===t?20:"y"===t&&e?4:"o"===t?3:2,n="y"===t?s:1,o=RegExp("^\\d{"+n+","+s+"}"),a=i.substring(h).match(o);if(!a)throw"Missing number at position "+h;return h+=a[0].length,parseInt(a[0],10)},k=function(e,s,n){var o=-1,a=t.map(y(e)?n:s,function(t,e){return[[e,t]]}).sort(function(t,e){return-(t[1].length-e[1].length)});if(t.each(a,function(t,e){var s=e[1];return i.substr(h,s.length).toLowerCase()===s.toLowerCase()?(o=e[0],h+=s.length,!1):void 0}),-1!==o)return o+1;throw"Unknown name at position "+h},x=function(){if(i.charAt(h)!==e.charAt(n))throw"Unexpected literal at position "+h;h++};for(n=0;e.length>n;n++)if(b)"'"!==e.charAt(n)||y("'")?x():b=!1;else switch(e.charAt(n)){case"d":_=w("d");break;case"D":k("D",u,d);break;case"o":v=w("o");break;case"m":m=w("m");break;case"M":m=k("M",p,f);break;case"y":g=w("y");break;case"@":r=new Date(w("@")),g=r.getFullYear(),m=r.getMonth()+1,_=r.getDate();break;case"!":r=new Date((w("!")-this._ticksTo1970)/1e4),g=r.getFullYear(),m=r.getMonth()+1,_=r.getDate();break;case"'":y("'")?x():b=!0;break;default:x()}if(i.length>h&&(a=i.substr(h),!/^\s+/.test(a)))throw"Extra/unparsed characters found in date: "+a;if(-1===g?g=(new Date).getFullYear():100>g&&(g+=(new Date).getFullYear()-(new Date).getFullYear()%100+(c>=g?0:-100)),v>-1)for(m=1,_=v;;){if(o=this._getDaysInMonth(g,m-1),o>=_)break;m++,_-=o}if(r=this._daylightSavingAdjust(new Date(g,m-1,_)),r.getFullYear()!==g||r.getMonth()+1!==m||r.getDate()!==_)throw"Invalid date";return r},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:1e7*60*60*24*(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925)),formatDate:function(t,e,i){if(!e)return"";var s,n=(i?i.dayNamesShort:null)||this._defaults.dayNamesShort,o=(i?i.dayNames:null)||this._defaults.dayNames,a=(i?i.monthNamesShort:null)||this._defaults.monthNamesShort,r=(i?i.monthNames:null)||this._defaults.monthNames,h=function(e){var i=t.length>s+1&&t.charAt(s+1)===e;return i&&s++,i},l=function(t,e,i){var s=""+e;if(h(t))for(;i>s.length;)s="0"+s;return s},c=function(t,e,i,s){return h(t)?s[e]:i[e]},u="",d=!1;if(e)for(s=0;t.length>s;s++)if(d)"'"!==t.charAt(s)||h("'")?u+=t.charAt(s):d=!1;else switch(t.charAt(s)){case"d":u+=l("d",e.getDate(),2);break;case"D":u+=c("D",e.getDay(),n,o);break;case"o":u+=l("o",Math.round((new Date(e.getFullYear(),e.getMonth(),e.getDate()).getTime()-new Date(e.getFullYear(),0,0).getTime())/864e5),3);break;case"m":u+=l("m",e.getMonth()+1,2);break;case"M":u+=c("M",e.getMonth(),a,r);break;case"y":u+=h("y")?e.getFullYear():(10>e.getFullYear()%100?"0":"")+e.getFullYear()%100;break;case"@":u+=e.getTime();break;case"!":u+=1e4*e.getTime()+this._ticksTo1970;break;case"'":h("'")?u+="'":d=!0;break;default:u+=t.charAt(s)}return u},_possibleChars:function(t){var e,i="",s=!1,n=function(i){var s=t.length>e+1&&t.charAt(e+1)===i;return s&&e++,s};for(e=0;t.length>e;e++)if(s)"'"!==t.charAt(e)||n("'")?i+=t.charAt(e):s=!1;else switch(t.charAt(e)){case"d":case"m":case"y":case"@":i+="0123456789";break;case"D":case"M":return null;case"'":n("'")?i+="'":s=!0;break;default:i+=t.charAt(e)}return i},_get:function(t,e){return void 0!==t.settings[e]?t.settings[e]:this._defaults[e]},_setDateFromField:function(t,e){if(t.input.val()!==t.lastVal){var i=this._get(t,"dateFormat"),s=t.lastVal=t.input?t.input.val():null,n=this._getDefaultDate(t),o=n,a=this._getFormatConfig(t);try{o=this.parseDate(i,s,a)||n}catch(r){s=e?"":s}t.selectedDay=o.getDate(),t.drawMonth=t.selectedMonth=o.getMonth(),t.drawYear=t.selectedYear=o.getFullYear(),t.currentDay=s?o.getDate():0,t.currentMonth=s?o.getMonth():0,t.currentYear=s?o.getFullYear():0,this._adjustInstDate(t)}},_getDefaultDate:function(t){return this._restrictMinMax(t,this._determineDate(t,this._get(t,"defaultDate"),new Date))},_determineDate:function(e,i,s){var n=function(t){var e=new Date;return e.setDate(e.getDate()+t),e},o=function(i){try{return t.datepicker.parseDate(t.datepicker._get(e,"dateFormat"),i,t.datepicker._getFormatConfig(e))}catch(s){}for(var n=(i.toLowerCase().match(/^c/)?t.datepicker._getDate(e):null)||new Date,o=n.getFullYear(),a=n.getMonth(),r=n.getDate(),h=/([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,l=h.exec(i);l;){switch(l[2]||"d"){case"d":case"D":r+=parseInt(l[1],10);break;case"w":case"W":r+=7*parseInt(l[1],10);break;case"m":case"M":a+=parseInt(l[1],10),r=Math.min(r,t.datepicker._getDaysInMonth(o,a));break;case"y":case"Y":o+=parseInt(l[1],10),r=Math.min(r,t.datepicker._getDaysInMonth(o,a))}l=h.exec(i)}return new Date(o,a,r)},a=null==i||""===i?s:"string"==typeof i?o(i):"number"==typeof i?isNaN(i)?s:n(i):new Date(i.getTime());return a=a&&"Invalid Date"==""+a?s:a,a&&(a.setHours(0),a.setMinutes(0),a.setSeconds(0),a.setMilliseconds(0)),this._daylightSavingAdjust(a)},_daylightSavingAdjust:function(t){return t?(t.setHours(t.getHours()>12?t.getHours()+2:0),t):null},_setDate:function(t,e,i){var s=!e,n=t.selectedMonth,o=t.selectedYear,a=this._restrictMinMax(t,this._determineDate(t,e,new Date));t.selectedDay=t.currentDay=a.getDate(),t.drawMonth=t.selectedMonth=t.currentMonth=a.getMonth(),t.drawYear=t.selectedYear=t.currentYear=a.getFullYear(),n===t.selectedMonth&&o===t.selectedYear||i||this._notifyChange(t),this._adjustInstDate(t),t.input&&t.input.val(s?"":this._formatDate(t))},_getDate:function(t){var e=!t.currentYear||t.input&&""===t.input.val()?null:this._daylightSavingAdjust(new Date(t.currentYear,t.currentMonth,t.currentDay));return e},_attachHandlers:function(e){var i=this._get(e,"stepMonths"),s="#"+e.id.replace(/\\\\/g,"\\");e.dpDiv.find("[data-handler]").map(function(){var e={prev:function(){t.datepicker._adjustDate(s,-i,"M")},next:function(){t.datepicker._adjustDate(s,+i,"M")},hide:function(){t.datepicker._hideDatepicker()},today:function(){t.datepicker._gotoToday(s)},selectDay:function(){return t.datepicker._selectDay(s,+this.getAttribute("data-month"),+this.getAttribute("data-year"),this),!1},selectMonth:function(){return t.datepicker._selectMonthYear(s,this,"M"),!1},selectYear:function(){return t.datepicker._selectMonthYear(s,this,"Y"),!1}};t(this).on(this.getAttribute("data-event"),e[this.getAttribute("data-handler")])})},_generateHTML:function(t){var e,i,s,n,o,a,r,h,l,c,u,d,p,f,g,m,_,v,b,y,w,k,x,C,D,I,T,P,M,S,H,z,O,A,N,W,E,F,L,R=new Date,B=this._daylightSavingAdjust(new Date(R.getFullYear(),R.getMonth(),R.getDate())),Y=this._get(t,"isRTL"),j=this._get(t,"showButtonPanel"),q=this._get(t,"hideIfNoPrevNext"),K=this._get(t,"navigationAsDateFormat"),U=this._getNumberOfMonths(t),V=this._get(t,"showCurrentAtPos"),$=this._get(t,"stepMonths"),X=1!==U[0]||1!==U[1],G=this._daylightSavingAdjust(t.currentDay?new Date(t.currentYear,t.currentMonth,t.currentDay):new Date(9999,9,9)),Q=this._getMinMaxDate(t,"min"),J=this._getMinMaxDate(t,"max"),Z=t.drawMonth-V,te=t.drawYear;if(0>Z&&(Z+=12,te--),J)for(e=this._daylightSavingAdjust(new Date(J.getFullYear(),J.getMonth()-U[0]*U[1]+1,J.getDate())),e=Q&&Q>e?Q:e;this._daylightSavingAdjust(new Date(te,Z,1))>e;)Z--,0>Z&&(Z=11,te--);for(t.drawMonth=Z,t.drawYear=te,i=this._get(t,"prevText"),i=K?this.formatDate(i,this._daylightSavingAdjust(new Date(te,Z-$,1)),this._getFormatConfig(t)):i,s=this._canAdjustMonth(t,-1,te,Z)?"<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click' title='"+i+"'><span class='ui-icon ui-icon-circle-triangle-"+(Y?"e":"w")+"'>"+i+"</span></a>":q?"":"<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='"+i+"'><span class='ui-icon ui-icon-circle-triangle-"+(Y?"e":"w")+"'>"+i+"</span></a>",n=this._get(t,"nextText"),n=K?this.formatDate(n,this._daylightSavingAdjust(new Date(te,Z+$,1)),this._getFormatConfig(t)):n,o=this._canAdjustMonth(t,1,te,Z)?"<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click' title='"+n+"'><span class='ui-icon ui-icon-circle-triangle-"+(Y?"w":"e")+"'>"+n+"</span></a>":q?"":"<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='"+n+"'><span class='ui-icon ui-icon-circle-triangle-"+(Y?"w":"e")+"'>"+n+"</span></a>",a=this._get(t,"currentText"),r=this._get(t,"gotoCurrent")&&t.currentDay?G:B,a=K?this.formatDate(a,r,this._getFormatConfig(t)):a,h=t.inline?"":"<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>"+this._get(t,"closeText")+"</button>",l=j?"<div class='ui-datepicker-buttonpane ui-widget-content'>"+(Y?h:"")+(this._isInRange(t,r)?"<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'>"+a+"</button>":"")+(Y?"":h)+"</div>":"",c=parseInt(this._get(t,"firstDay"),10),c=isNaN(c)?0:c,u=this._get(t,"showWeek"),d=this._get(t,"dayNames"),p=this._get(t,"dayNamesMin"),f=this._get(t,"monthNames"),g=this._get(t,"monthNamesShort"),m=this._get(t,"beforeShowDay"),_=this._get(t,"showOtherMonths"),v=this._get(t,"selectOtherMonths"),b=this._getDefaultDate(t),y="",k=0;U[0]>k;k++){for(x="",this.maxRows=4,C=0;U[1]>C;C++){if(D=this._daylightSavingAdjust(new Date(te,Z,t.selectedDay)),I=" ui-corner-all",T="",X){if(T+="<div class='ui-datepicker-group",U[1]>1)switch(C){case 0:T+=" ui-datepicker-group-first",I=" ui-corner-"+(Y?"right":"left");break;case U[1]-1:T+=" ui-datepicker-group-last",I=" ui-corner-"+(Y?"left":"right");break;default:T+=" ui-datepicker-group-middle",I=""}T+="'>"}for(T+="<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix"+I+"'>"+(/all|left/.test(I)&&0===k?Y?o:s:"")+(/all|right/.test(I)&&0===k?Y?s:o:"")+this._generateMonthYearHeader(t,Z,te,Q,J,k>0||C>0,f,g)+"</div><table class='ui-datepicker-calendar'><thead>"+"<tr>",P=u?"<th class='ui-datepicker-week-col'>"+this._get(t,"weekHeader")+"</th>":"",w=0;7>w;w++)M=(w+c)%7,P+="<th scope='col'"+((w+c+6)%7>=5?" class='ui-datepicker-week-end'":"")+">"+"<span title='"+d[M]+"'>"+p[M]+"</span></th>";for(T+=P+"</tr></thead><tbody>",S=this._getDaysInMonth(te,Z),te===t.selectedYear&&Z===t.selectedMonth&&(t.selectedDay=Math.min(t.selectedDay,S)),H=(this._getFirstDayOfMonth(te,Z)-c+7)%7,z=Math.ceil((H+S)/7),O=X?this.maxRows>z?this.maxRows:z:z,this.maxRows=O,A=this._daylightSavingAdjust(new Date(te,Z,1-H)),N=0;O>N;N++){for(T+="<tr>",W=u?"<td class='ui-datepicker-week-col'>"+this._get(t,"calculateWeek")(A)+"</td>":"",w=0;7>w;w++)E=m?m.apply(t.input?t.input[0]:null,[A]):[!0,""],F=A.getMonth()!==Z,L=F&&!v||!E[0]||Q&&Q>A||J&&A>J,W+="<td class='"+((w+c+6)%7>=5?" ui-datepicker-week-end":"")+(F?" ui-datepicker-other-month":"")+(A.getTime()===D.getTime()&&Z===t.selectedMonth&&t._keyEvent||b.getTime()===A.getTime()&&b.getTime()===D.getTime()?" "+this._dayOverClass:"")+(L?" "+this._unselectableClass+" ui-state-disabled":"")+(F&&!_?"":" "+E[1]+(A.getTime()===G.getTime()?" "+this._currentClass:"")+(A.getTime()===B.getTime()?" ui-datepicker-today":""))+"'"+(F&&!_||!E[2]?"":" title='"+E[2].replace(/'/g,"'")+"'")+(L?"":" data-handler='selectDay' data-event='click' data-month='"+A.getMonth()+"' data-year='"+A.getFullYear()+"'")+">"+(F&&!_?" ":L?"<span class='ui-state-default'>"+A.getDate()+"</span>":"<a class='ui-state-default"+(A.getTime()===B.getTime()?" ui-state-highlight":"")+(A.getTime()===G.getTime()?" ui-state-active":"")+(F?" ui-priority-secondary":"")+"' href='#'>"+A.getDate()+"</a>")+"</td>",A.setDate(A.getDate()+1),A=this._daylightSavingAdjust(A);T+=W+"</tr>"}Z++,Z>11&&(Z=0,te++),T+="</tbody></table>"+(X?"</div>"+(U[0]>0&&C===U[1]-1?"<div class='ui-datepicker-row-break'></div>":""):""),x+=T}y+=x}return y+=l,t._keyEvent=!1,y},_generateMonthYearHeader:function(t,e,i,s,n,o,a,r){var h,l,c,u,d,p,f,g,m=this._get(t,"changeMonth"),_=this._get(t,"changeYear"),v=this._get(t,"showMonthAfterYear"),b="<div class='ui-datepicker-title'>",y="";if(o||!m)y+="<span class='ui-datepicker-month'>"+a[e]+"</span>";else{for(h=s&&s.getFullYear()===i,l=n&&n.getFullYear()===i,y+="<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>",c=0;12>c;c++)(!h||c>=s.getMonth())&&(!l||n.getMonth()>=c)&&(y+="<option value='"+c+"'"+(c===e?" selected='selected'":"")+">"+r[c]+"</option>");y+="</select>"}if(v||(b+=y+(!o&&m&&_?"":" ")),!t.yearshtml)if(t.yearshtml="",o||!_)b+="<span class='ui-datepicker-year'>"+i+"</span>";else{for(u=this._get(t,"yearRange").split(":"),d=(new Date).getFullYear(),p=function(t){var e=t.match(/c[+\-].*/)?i+parseInt(t.substring(1),10):t.match(/[+\-].*/)?d+parseInt(t,10):parseInt(t,10);return isNaN(e)?d:e},f=p(u[0]),g=Math.max(f,p(u[1]||"")),f=s?Math.max(f,s.getFullYear()):f,g=n?Math.min(g,n.getFullYear()):g,t.yearshtml+="<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";g>=f;f++)t.yearshtml+="<option value='"+f+"'"+(f===i?" selected='selected'":"")+">"+f+"</option>";t.yearshtml+="</select>",b+=t.yearshtml,t.yearshtml=null}return b+=this._get(t,"yearSuffix"),v&&(b+=(!o&&m&&_?"":" ")+y),b+="</div>"},_adjustInstDate:function(t,e,i){var s=t.selectedYear+("Y"===i?e:0),n=t.selectedMonth+("M"===i?e:0),o=Math.min(t.selectedDay,this._getDaysInMonth(s,n))+("D"===i?e:0),a=this._restrictMinMax(t,this._daylightSavingAdjust(new Date(s,n,o)));t.selectedDay=a.getDate(),t.drawMonth=t.selectedMonth=a.getMonth(),t.drawYear=t.selectedYear=a.getFullYear(),("M"===i||"Y"===i)&&this._notifyChange(t)},_restrictMinMax:function(t,e){var i=this._getMinMaxDate(t,"min"),s=this._getMinMaxDate(t,"max"),n=i&&i>e?i:e;return s&&n>s?s:n},_notifyChange:function(t){var e=this._get(t,"onChangeMonthYear");e&&e.apply(t.input?t.input[0]:null,[t.selectedYear,t.selectedMonth+1,t])},_getNumberOfMonths:function(t){var e=this._get(t,"numberOfMonths");return null==e?[1,1]:"number"==typeof e?[1,e]:e},_getMinMaxDate:function(t,e){return this._determineDate(t,this._get(t,e+"Date"),null)},_getDaysInMonth:function(t,e){return 32-this._daylightSavingAdjust(new Date(t,e,32)).getDate()},_getFirstDayOfMonth:function(t,e){return new Date(t,e,1).getDay()},_canAdjustMonth:function(t,e,i,s){var n=this._getNumberOfMonths(t),o=this._daylightSavingAdjust(new Date(i,s+(0>e?e:n[0]*n[1]),1));return 0>e&&o.setDate(this._getDaysInMonth(o.getFullYear(),o.getMonth())),this._isInRange(t,o)},_isInRange:function(t,e){var i,s,n=this._getMinMaxDate(t,"min"),o=this._getMinMaxDate(t,"max"),a=null,r=null,h=this._get(t,"yearRange");return h&&(i=h.split(":"),s=(new Date).getFullYear(),a=parseInt(i[0],10),r=parseInt(i[1],10),i[0].match(/[+\-].*/)&&(a+=s),i[1].match(/[+\-].*/)&&(r+=s)),(!n||e.getTime()>=n.getTime())&&(!o||e.getTime()<=o.getTime())&&(!a||e.getFullYear()>=a)&&(!r||r>=e.getFullYear())},_getFormatConfig:function(t){var e=this._get(t,"shortYearCutoff");return e="string"!=typeof e?e:(new Date).getFullYear()%100+parseInt(e,10),{shortYearCutoff:e,dayNamesShort:this._get(t,"dayNamesShort"),dayNames:this._get(t,"dayNames"),monthNamesShort:this._get(t,"monthNamesShort"),monthNames:this._get(t,"monthNames")}},_formatDate:function(t,e,i,s){e||(t.currentDay=t.selectedDay,t.currentMonth=t.selectedMonth,t.currentYear=t.selectedYear);var n=e?"object"==typeof e?e:this._daylightSavingAdjust(new Date(s,i,e)):this._daylightSavingAdjust(new Date(t.currentYear,t.currentMonth,t.currentDay));return this.formatDate(this._get(t,"dateFormat"),n,this._getFormatConfig(t))}}),t.fn.datepicker=function(e){if(!this.length)return this;t.datepicker.initialized||(t(document).on("mousedown",t.datepicker._checkExternalClick),t.datepicker.initialized=!0),0===t("#"+t.datepicker._mainDivId).length&&t("body").append(t.datepicker.dpDiv);var i=Array.prototype.slice.call(arguments,1);return"string"!=typeof e||"isDisabled"!==e&&"getDate"!==e&&"widget"!==e?"option"===e&&2===arguments.length&&"string"==typeof arguments[1]?t.datepicker["_"+e+"Datepicker"].apply(t.datepicker,[this[0]].concat(i)):this.each(function(){"string"==typeof e?t.datepicker["_"+e+"Datepicker"].apply(t.datepicker,[this].concat(i)):t.datepicker._attachDatepicker(this,e)}):t.datepicker["_"+e+"Datepicker"].apply(t.datepicker,[this[0]].concat(i))},t.datepicker=new s,t.datepicker.initialized=!1,t.datepicker.uuid=(new Date).getTime(),t.datepicker.version="1.12.1",t.datepicker,t.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase());var _=!1;t(document).on("mouseup",function(){_=!1}),t.widget("ui.mouse",{version:"1.12.1",options:{cancel:"input, textarea, button, select, option",distance:1,delay:0},_mouseInit:function(){var e=this;this.element.on("mousedown."+this.widgetName,function(t){return e._mouseDown(t)}).on("click."+this.widgetName,function(i){return!0===t.data(i.target,e.widgetName+".preventClickEvent")?(t.removeData(i.target,e.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):void 0}),this.started=!1},_mouseDestroy:function(){this.element.off("."+this.widgetName),this._mouseMoveDelegate&&this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(e){if(!_){this._mouseMoved=!1,this._mouseStarted&&this._mouseUp(e),this._mouseDownEvent=e;var i=this,s=1===e.which,n="string"==typeof this.options.cancel&&e.target.nodeName?t(e.target).closest(this.options.cancel).length:!1;return s&&!n&&this._mouseCapture(e)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){i.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=this._mouseStart(e)!==!1,!this._mouseStarted)?(e.preventDefault(),!0):(!0===t.data(e.target,this.widgetName+".preventClickEvent")&&t.removeData(e.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(t){return i._mouseMove(t)},this._mouseUpDelegate=function(t){return i._mouseUp(t)},this.document.on("mousemove."+this.widgetName,this._mouseMoveDelegate).on("mouseup."+this.widgetName,this._mouseUpDelegate),e.preventDefault(),_=!0,!0)):!0}},_mouseMove:function(e){if(this._mouseMoved){if(t.ui.ie&&(!document.documentMode||9>document.documentMode)&&!e.button)return this._mouseUp(e);if(!e.which)if(e.originalEvent.altKey||e.originalEvent.ctrlKey||e.originalEvent.metaKey||e.originalEvent.shiftKey)this.ignoreMissingWhich=!0;else if(!this.ignoreMissingWhich)return this._mouseUp(e)}return(e.which||e.button)&&(this._mouseMoved=!0),this._mouseStarted?(this._mouseDrag(e),e.preventDefault()):(this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,e)!==!1,this._mouseStarted?this._mouseDrag(e):this._mouseUp(e)),!this._mouseStarted)},_mouseUp:function(e){this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,e.target===this._mouseDownEvent.target&&t.data(e.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(e)),this._mouseDelayTimer&&(clearTimeout(this._mouseDelayTimer),delete this._mouseDelayTimer),this.ignoreMissingWhich=!1,_=!1,e.preventDefault()},_mouseDistanceMet:function(t){return Math.max(Math.abs(this._mouseDownEvent.pageX-t.pageX),Math.abs(this._mouseDownEvent.pageY-t.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}}),t.ui.plugin={add:function(e,i,s){var n,o=t.ui[e].prototype;for(n in s)o.plugins[n]=o.plugins[n]||[],o.plugins[n].push([i,s[n]])},call:function(t,e,i,s){var n,o=t.plugins[e];if(o&&(s||t.element[0].parentNode&&11!==t.element[0].parentNode.nodeType))for(n=0;o.length>n;n++)t.options[o[n][0]]&&o[n][1].apply(t.element,i)}},t.ui.safeBlur=function(e){e&&"body"!==e.nodeName.toLowerCase()&&t(e).trigger("blur")},t.widget("ui.draggable",t.ui.mouse,{version:"1.12.1",widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1,drag:null,start:null,stop:null},_create:function(){"original"===this.options.helper&&this._setPositionRelative(),this.options.addClasses&&this._addClass("ui-draggable"),this._setHandleClassName(),this._mouseInit()},_setOption:function(t,e){this._super(t,e),"handle"===t&&(this._removeHandleClassName(),this._setHandleClassName())},_destroy:function(){return(this.helper||this.element).is(".ui-draggable-dragging")?(this.destroyOnClear=!0,void 0):(this._removeHandleClassName(),this._mouseDestroy(),void 0)},_mouseCapture:function(e){var i=this.options;return this.helper||i.disabled||t(e.target).closest(".ui-resizable-handle").length>0?!1:(this.handle=this._getHandle(e),this.handle?(this._blurActiveElement(e),this._blockFrames(i.iframeFix===!0?"iframe":i.iframeFix),!0):!1)},_blockFrames:function(e){this.iframeBlocks=this.document.find(e).map(function(){var e=t(this);return t("<div>").css("position","absolute").appendTo(e.parent()).outerWidth(e.outerWidth()).outerHeight(e.outerHeight()).offset(e.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_blurActiveElement:function(e){var i=t.ui.safeActiveElement(this.document[0]),s=t(e.target);s.closest(i).length||t.ui.safeBlur(i)},_mouseStart:function(e){var i=this.options;return this.helper=this._createHelper(e),this._addClass(this.helper,"ui-draggable-dragging"),this._cacheHelperProportions(),t.ui.ddmanager&&(t.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(!0),this.offsetParent=this.helper.offsetParent(),this.hasFixedAncestor=this.helper.parents().filter(function(){return"fixed"===t(this).css("position")}).length>0,this.positionAbs=this.element.offset(),this._refreshOffsets(e),this.originalPosition=this.position=this._generatePosition(e,!1),this.originalPageX=e.pageX,this.originalPageY=e.pageY,i.cursorAt&&this._adjustOffsetFromHelper(i.cursorAt),this._setContainment(),this._trigger("start",e)===!1?(this._clear(),!1):(this._cacheHelperProportions(),t.ui.ddmanager&&!i.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e),this._mouseDrag(e,!0),t.ui.ddmanager&&t.ui.ddmanager.dragStart(this,e),!0)},_refreshOffsets:function(t){this.offset={top:this.positionAbs.top-this.margins.top,left:this.positionAbs.left-this.margins.left,scroll:!1,parent:this._getParentOffset(),relative:this._getRelativeOffset()},this.offset.click={left:t.pageX-this.offset.left,top:t.pageY-this.offset.top}},_mouseDrag:function(e,i){if(this.hasFixedAncestor&&(this.offset.parent=this._getParentOffset()),this.position=this._generatePosition(e,!0),this.positionAbs=this._convertPositionTo("absolute"),!i){var s=this._uiHash();if(this._trigger("drag",e,s)===!1)return this._mouseUp(new t.Event("mouseup",e)),!1;this.position=s.position}return this.helper[0].style.left=this.position.left+"px",this.helper[0].style.top=this.position.top+"px",t.ui.ddmanager&&t.ui.ddmanager.drag(this,e),!1},_mouseStop:function(e){var i=this,s=!1;return t.ui.ddmanager&&!this.options.dropBehaviour&&(s=t.ui.ddmanager.drop(this,e)),this.dropped&&(s=this.dropped,this.dropped=!1),"invalid"===this.options.revert&&!s||"valid"===this.options.revert&&s||this.options.revert===!0||t.isFunction(this.options.revert)&&this.options.revert.call(this.element,s)?t(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){i._trigger("stop",e)!==!1&&i._clear()}):this._trigger("stop",e)!==!1&&this._clear(),!1},_mouseUp:function(e){return this._unblockFrames(),t.ui.ddmanager&&t.ui.ddmanager.dragStop(this,e),this.handleElement.is(e.target)&&this.element.trigger("focus"),t.ui.mouse.prototype._mouseUp.call(this,e)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp(new t.Event("mouseup",{target:this.element[0]})):this._clear(),this},_getHandle:function(e){return this.options.handle?!!t(e.target).closest(this.element.find(this.options.handle)).length:!0},_setHandleClassName:function(){this.handleElement=this.options.handle?this.element.find(this.options.handle):this.element,this._addClass(this.handleElement,"ui-draggable-handle")},_removeHandleClassName:function(){this._removeClass(this.handleElement,"ui-draggable-handle")},_createHelper:function(e){var i=this.options,s=t.isFunction(i.helper),n=s?t(i.helper.apply(this.element[0],[e])):"clone"===i.helper?this.element.clone().removeAttr("id"):this.element;return n.parents("body").length||n.appendTo("parent"===i.appendTo?this.element[0].parentNode:i.appendTo),s&&n[0]===this.element[0]&&this._setPositionRelative(),n[0]===this.element[0]||/(fixed|absolute)/.test(n.css("position"))||n.css("position","absolute"),n},_setPositionRelative:function(){/^(?:r|a|f)/.test(this.element.css("position"))||(this.element[0].style.position="relative")},_adjustOffsetFromHelper:function(e){"string"==typeof e&&(e=e.split(" ")),t.isArray(e)&&(e={left:+e[0],top:+e[1]||0}),"left"in e&&(this.offset.click.left=e.left+this.margins.left),"right"in e&&(this.offset.click.left=this.helperProportions.width-e.right+this.margins.left),"top"in e&&(this.offset.click.top=e.top+this.margins.top),"bottom"in e&&(this.offset.click.top=this.helperProportions.height-e.bottom+this.margins.top)},_isRootNode:function(t){return/(html|body)/i.test(t.tagName)||t===this.document[0]},_getParentOffset:function(){var e=this.offsetParent.offset(),i=this.document[0];return"absolute"===this.cssPosition&&this.scrollParent[0]!==i&&t.contains(this.scrollParent[0],this.offsetParent[0])&&(e.left+=this.scrollParent.scrollLeft(),e.top+=this.scrollParent.scrollTop()),this._isRootNode(this.offsetParent[0])&&(e={top:0,left:0}),{top:e.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:e.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"!==this.cssPosition)return{top:0,left:0};var t=this.element.position(),e=this._isRootNode(this.scrollParent[0]);return{top:t.top-(parseInt(this.helper.css("top"),10)||0)+(e?0:this.scrollParent.scrollTop()),left:t.left-(parseInt(this.helper.css("left"),10)||0)+(e?0:this.scrollParent.scrollLeft())} -},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e,i,s,n=this.options,o=this.document[0];return this.relativeContainer=null,n.containment?"window"===n.containment?(this.containment=[t(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,t(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,t(window).scrollLeft()+t(window).width()-this.helperProportions.width-this.margins.left,t(window).scrollTop()+(t(window).height()||o.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],void 0):"document"===n.containment?(this.containment=[0,0,t(o).width()-this.helperProportions.width-this.margins.left,(t(o).height()||o.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],void 0):n.containment.constructor===Array?(this.containment=n.containment,void 0):("parent"===n.containment&&(n.containment=this.helper[0].parentNode),i=t(n.containment),s=i[0],s&&(e=/(scroll|auto)/.test(i.css("overflow")),this.containment=[(parseInt(i.css("borderLeftWidth"),10)||0)+(parseInt(i.css("paddingLeft"),10)||0),(parseInt(i.css("borderTopWidth"),10)||0)+(parseInt(i.css("paddingTop"),10)||0),(e?Math.max(s.scrollWidth,s.offsetWidth):s.offsetWidth)-(parseInt(i.css("borderRightWidth"),10)||0)-(parseInt(i.css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(e?Math.max(s.scrollHeight,s.offsetHeight):s.offsetHeight)-(parseInt(i.css("borderBottomWidth"),10)||0)-(parseInt(i.css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relativeContainer=i),void 0):(this.containment=null,void 0)},_convertPositionTo:function(t,e){e||(e=this.position);var i="absolute"===t?1:-1,s=this._isRootNode(this.scrollParent[0]);return{top:e.top+this.offset.relative.top*i+this.offset.parent.top*i-("fixed"===this.cssPosition?-this.offset.scroll.top:s?0:this.offset.scroll.top)*i,left:e.left+this.offset.relative.left*i+this.offset.parent.left*i-("fixed"===this.cssPosition?-this.offset.scroll.left:s?0:this.offset.scroll.left)*i}},_generatePosition:function(t,e){var i,s,n,o,a=this.options,r=this._isRootNode(this.scrollParent[0]),h=t.pageX,l=t.pageY;return r&&this.offset.scroll||(this.offset.scroll={top:this.scrollParent.scrollTop(),left:this.scrollParent.scrollLeft()}),e&&(this.containment&&(this.relativeContainer?(s=this.relativeContainer.offset(),i=[this.containment[0]+s.left,this.containment[1]+s.top,this.containment[2]+s.left,this.containment[3]+s.top]):i=this.containment,t.pageX-this.offset.click.left<i[0]&&(h=i[0]+this.offset.click.left),t.pageY-this.offset.click.top<i[1]&&(l=i[1]+this.offset.click.top),t.pageX-this.offset.click.left>i[2]&&(h=i[2]+this.offset.click.left),t.pageY-this.offset.click.top>i[3]&&(l=i[3]+this.offset.click.top)),a.grid&&(n=a.grid[1]?this.originalPageY+Math.round((l-this.originalPageY)/a.grid[1])*a.grid[1]:this.originalPageY,l=i?n-this.offset.click.top>=i[1]||n-this.offset.click.top>i[3]?n:n-this.offset.click.top>=i[1]?n-a.grid[1]:n+a.grid[1]:n,o=a.grid[0]?this.originalPageX+Math.round((h-this.originalPageX)/a.grid[0])*a.grid[0]:this.originalPageX,h=i?o-this.offset.click.left>=i[0]||o-this.offset.click.left>i[2]?o:o-this.offset.click.left>=i[0]?o-a.grid[0]:o+a.grid[0]:o),"y"===a.axis&&(h=this.originalPageX),"x"===a.axis&&(l=this.originalPageY)),{top:l-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.offset.scroll.top:r?0:this.offset.scroll.top),left:h-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.offset.scroll.left:r?0:this.offset.scroll.left)}},_clear:function(){this._removeClass(this.helper,"ui-draggable-dragging"),this.helper[0]===this.element[0]||this.cancelHelperRemoval||this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1,this.destroyOnClear&&this.destroy()},_trigger:function(e,i,s){return s=s||this._uiHash(),t.ui.plugin.call(this,e,[i,s,this],!0),/^(drag|start|stop)/.test(e)&&(this.positionAbs=this._convertPositionTo("absolute"),s.offset=this.positionAbs),t.Widget.prototype._trigger.call(this,e,i,s)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),t.ui.plugin.add("draggable","connectToSortable",{start:function(e,i,s){var n=t.extend({},i,{item:s.element});s.sortables=[],t(s.options.connectToSortable).each(function(){var i=t(this).sortable("instance");i&&!i.options.disabled&&(s.sortables.push(i),i.refreshPositions(),i._trigger("activate",e,n))})},stop:function(e,i,s){var n=t.extend({},i,{item:s.element});s.cancelHelperRemoval=!1,t.each(s.sortables,function(){var t=this;t.isOver?(t.isOver=0,s.cancelHelperRemoval=!0,t.cancelHelperRemoval=!1,t._storedCSS={position:t.placeholder.css("position"),top:t.placeholder.css("top"),left:t.placeholder.css("left")},t._mouseStop(e),t.options.helper=t.options._helper):(t.cancelHelperRemoval=!0,t._trigger("deactivate",e,n))})},drag:function(e,i,s){t.each(s.sortables,function(){var n=!1,o=this;o.positionAbs=s.positionAbs,o.helperProportions=s.helperProportions,o.offset.click=s.offset.click,o._intersectsWith(o.containerCache)&&(n=!0,t.each(s.sortables,function(){return this.positionAbs=s.positionAbs,this.helperProportions=s.helperProportions,this.offset.click=s.offset.click,this!==o&&this._intersectsWith(this.containerCache)&&t.contains(o.element[0],this.element[0])&&(n=!1),n})),n?(o.isOver||(o.isOver=1,s._parent=i.helper.parent(),o.currentItem=i.helper.appendTo(o.element).data("ui-sortable-item",!0),o.options._helper=o.options.helper,o.options.helper=function(){return i.helper[0]},e.target=o.currentItem[0],o._mouseCapture(e,!0),o._mouseStart(e,!0,!0),o.offset.click.top=s.offset.click.top,o.offset.click.left=s.offset.click.left,o.offset.parent.left-=s.offset.parent.left-o.offset.parent.left,o.offset.parent.top-=s.offset.parent.top-o.offset.parent.top,s._trigger("toSortable",e),s.dropped=o.element,t.each(s.sortables,function(){this.refreshPositions()}),s.currentItem=s.element,o.fromOutside=s),o.currentItem&&(o._mouseDrag(e),i.position=o.position)):o.isOver&&(o.isOver=0,o.cancelHelperRemoval=!0,o.options._revert=o.options.revert,o.options.revert=!1,o._trigger("out",e,o._uiHash(o)),o._mouseStop(e,!0),o.options.revert=o.options._revert,o.options.helper=o.options._helper,o.placeholder&&o.placeholder.remove(),i.helper.appendTo(s._parent),s._refreshOffsets(e),i.position=s._generatePosition(e,!0),s._trigger("fromSortable",e),s.dropped=!1,t.each(s.sortables,function(){this.refreshPositions()}))})}}),t.ui.plugin.add("draggable","cursor",{start:function(e,i,s){var n=t("body"),o=s.options;n.css("cursor")&&(o._cursor=n.css("cursor")),n.css("cursor",o.cursor)},stop:function(e,i,s){var n=s.options;n._cursor&&t("body").css("cursor",n._cursor)}}),t.ui.plugin.add("draggable","opacity",{start:function(e,i,s){var n=t(i.helper),o=s.options;n.css("opacity")&&(o._opacity=n.css("opacity")),n.css("opacity",o.opacity)},stop:function(e,i,s){var n=s.options;n._opacity&&t(i.helper).css("opacity",n._opacity)}}),t.ui.plugin.add("draggable","scroll",{start:function(t,e,i){i.scrollParentNotHidden||(i.scrollParentNotHidden=i.helper.scrollParent(!1)),i.scrollParentNotHidden[0]!==i.document[0]&&"HTML"!==i.scrollParentNotHidden[0].tagName&&(i.overflowOffset=i.scrollParentNotHidden.offset())},drag:function(e,i,s){var n=s.options,o=!1,a=s.scrollParentNotHidden[0],r=s.document[0];a!==r&&"HTML"!==a.tagName?(n.axis&&"x"===n.axis||(s.overflowOffset.top+a.offsetHeight-e.pageY<n.scrollSensitivity?a.scrollTop=o=a.scrollTop+n.scrollSpeed:e.pageY-s.overflowOffset.top<n.scrollSensitivity&&(a.scrollTop=o=a.scrollTop-n.scrollSpeed)),n.axis&&"y"===n.axis||(s.overflowOffset.left+a.offsetWidth-e.pageX<n.scrollSensitivity?a.scrollLeft=o=a.scrollLeft+n.scrollSpeed:e.pageX-s.overflowOffset.left<n.scrollSensitivity&&(a.scrollLeft=o=a.scrollLeft-n.scrollSpeed))):(n.axis&&"x"===n.axis||(e.pageY-t(r).scrollTop()<n.scrollSensitivity?o=t(r).scrollTop(t(r).scrollTop()-n.scrollSpeed):t(window).height()-(e.pageY-t(r).scrollTop())<n.scrollSensitivity&&(o=t(r).scrollTop(t(r).scrollTop()+n.scrollSpeed))),n.axis&&"y"===n.axis||(e.pageX-t(r).scrollLeft()<n.scrollSensitivity?o=t(r).scrollLeft(t(r).scrollLeft()-n.scrollSpeed):t(window).width()-(e.pageX-t(r).scrollLeft())<n.scrollSensitivity&&(o=t(r).scrollLeft(t(r).scrollLeft()+n.scrollSpeed)))),o!==!1&&t.ui.ddmanager&&!n.dropBehaviour&&t.ui.ddmanager.prepareOffsets(s,e)}}),t.ui.plugin.add("draggable","snap",{start:function(e,i,s){var n=s.options;s.snapElements=[],t(n.snap.constructor!==String?n.snap.items||":data(ui-draggable)":n.snap).each(function(){var e=t(this),i=e.offset();this!==s.element[0]&&s.snapElements.push({item:this,width:e.outerWidth(),height:e.outerHeight(),top:i.top,left:i.left})})},drag:function(e,i,s){var n,o,a,r,h,l,c,u,d,p,f=s.options,g=f.snapTolerance,m=i.offset.left,_=m+s.helperProportions.width,v=i.offset.top,b=v+s.helperProportions.height;for(d=s.snapElements.length-1;d>=0;d--)h=s.snapElements[d].left-s.margins.left,l=h+s.snapElements[d].width,c=s.snapElements[d].top-s.margins.top,u=c+s.snapElements[d].height,h-g>_||m>l+g||c-g>b||v>u+g||!t.contains(s.snapElements[d].item.ownerDocument,s.snapElements[d].item)?(s.snapElements[d].snapping&&s.options.snap.release&&s.options.snap.release.call(s.element,e,t.extend(s._uiHash(),{snapItem:s.snapElements[d].item})),s.snapElements[d].snapping=!1):("inner"!==f.snapMode&&(n=g>=Math.abs(c-b),o=g>=Math.abs(u-v),a=g>=Math.abs(h-_),r=g>=Math.abs(l-m),n&&(i.position.top=s._convertPositionTo("relative",{top:c-s.helperProportions.height,left:0}).top),o&&(i.position.top=s._convertPositionTo("relative",{top:u,left:0}).top),a&&(i.position.left=s._convertPositionTo("relative",{top:0,left:h-s.helperProportions.width}).left),r&&(i.position.left=s._convertPositionTo("relative",{top:0,left:l}).left)),p=n||o||a||r,"outer"!==f.snapMode&&(n=g>=Math.abs(c-v),o=g>=Math.abs(u-b),a=g>=Math.abs(h-m),r=g>=Math.abs(l-_),n&&(i.position.top=s._convertPositionTo("relative",{top:c,left:0}).top),o&&(i.position.top=s._convertPositionTo("relative",{top:u-s.helperProportions.height,left:0}).top),a&&(i.position.left=s._convertPositionTo("relative",{top:0,left:h}).left),r&&(i.position.left=s._convertPositionTo("relative",{top:0,left:l-s.helperProportions.width}).left)),!s.snapElements[d].snapping&&(n||o||a||r||p)&&s.options.snap.snap&&s.options.snap.snap.call(s.element,e,t.extend(s._uiHash(),{snapItem:s.snapElements[d].item})),s.snapElements[d].snapping=n||o||a||r||p)}}),t.ui.plugin.add("draggable","stack",{start:function(e,i,s){var n,o=s.options,a=t.makeArray(t(o.stack)).sort(function(e,i){return(parseInt(t(e).css("zIndex"),10)||0)-(parseInt(t(i).css("zIndex"),10)||0)});a.length&&(n=parseInt(t(a[0]).css("zIndex"),10)||0,t(a).each(function(e){t(this).css("zIndex",n+e)}),this.css("zIndex",n+a.length))}}),t.ui.plugin.add("draggable","zIndex",{start:function(e,i,s){var n=t(i.helper),o=s.options;n.css("zIndex")&&(o._zIndex=n.css("zIndex")),n.css("zIndex",o.zIndex)},stop:function(e,i,s){var n=s.options;n._zIndex&&t(i.helper).css("zIndex",n._zIndex)}}),t.ui.draggable,t.widget("ui.resizable",t.ui.mouse,{version:"1.12.1",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,classes:{"ui-resizable-se":"ui-icon ui-icon-gripsmall-diagonal-se"},containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_num:function(t){return parseFloat(t)||0},_isNumber:function(t){return!isNaN(parseFloat(t))},_hasScroll:function(e,i){if("hidden"===t(e).css("overflow"))return!1;var s=i&&"left"===i?"scrollLeft":"scrollTop",n=!1;return e[s]>0?!0:(e[s]=1,n=e[s]>0,e[s]=0,n)},_create:function(){var e,i=this.options,s=this;this._addClass("ui-resizable"),t.extend(this,{_aspectRatio:!!i.aspectRatio,aspectRatio:i.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:i.helper||i.ghost||i.animate?i.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/^(canvas|textarea|input|select|button|img)$/i)&&(this.element.wrap(t("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.resizable("instance")),this.elementIsWrapper=!0,e={marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom"),marginLeft:this.originalElement.css("marginLeft")},this.element.css(e),this.originalElement.css("margin",0),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css(e),this._proportionallyResize()),this._setupHandles(),i.autoHide&&t(this.element).on("mouseenter",function(){i.disabled||(s._removeClass("ui-resizable-autohide"),s._handles.show())}).on("mouseleave",function(){i.disabled||s.resizing||(s._addClass("ui-resizable-autohide"),s._handles.hide())}),this._mouseInit()},_destroy:function(){this._mouseDestroy();var e,i=function(e){t(e).removeData("resizable").removeData("ui-resizable").off(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(i(this.element),e=this.element,this.originalElement.css({position:e.css("position"),width:e.outerWidth(),height:e.outerHeight(),top:e.css("top"),left:e.css("left")}).insertAfter(e),e.remove()),this.originalElement.css("resize",this.originalResizeStyle),i(this.originalElement),this},_setOption:function(t,e){switch(this._super(t,e),t){case"handles":this._removeHandles(),this._setupHandles();break;default:}},_setupHandles:function(){var e,i,s,n,o,a=this.options,r=this;if(this.handles=a.handles||(t(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this._handles=t(),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),s=this.handles.split(","),this.handles={},i=0;s.length>i;i++)e=t.trim(s[i]),n="ui-resizable-"+e,o=t("<div>"),this._addClass(o,"ui-resizable-handle "+n),o.css({zIndex:a.zIndex}),this.handles[e]=".ui-resizable-"+e,this.element.append(o);this._renderAxis=function(e){var i,s,n,o;e=e||this.element;for(i in this.handles)this.handles[i].constructor===String?this.handles[i]=this.element.children(this.handles[i]).first().show():(this.handles[i].jquery||this.handles[i].nodeType)&&(this.handles[i]=t(this.handles[i]),this._on(this.handles[i],{mousedown:r._mouseDown})),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/^(textarea|input|select|button)$/i)&&(s=t(this.handles[i],this.element),o=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join(""),e.css(n,o),this._proportionallyResize()),this._handles=this._handles.add(this.handles[i])},this._renderAxis(this.element),this._handles=this._handles.add(this.element.find(".ui-resizable-handle")),this._handles.disableSelection(),this._handles.on("mouseover",function(){r.resizing||(this.className&&(o=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),r.axis=o&&o[1]?o[1]:"se")}),a.autoHide&&(this._handles.hide(),this._addClass("ui-resizable-autohide"))},_removeHandles:function(){this._handles.remove()},_mouseCapture:function(e){var i,s,n=!1;for(i in this.handles)s=t(this.handles[i])[0],(s===e.target||t.contains(s,e.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(e){var i,s,n,o=this.options,a=this.element;return this.resizing=!0,this._renderProxy(),i=this._num(this.helper.css("left")),s=this._num(this.helper.css("top")),o.containment&&(i+=t(o.containment).scrollLeft()||0,s+=t(o.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:i,top:s},this.size=this._helper?{width:this.helper.width(),height:this.helper.height()}:{width:a.width(),height:a.height()},this.originalSize=this._helper?{width:a.outerWidth(),height:a.outerHeight()}:{width:a.width(),height:a.height()},this.sizeDiff={width:a.outerWidth()-a.width(),height:a.outerHeight()-a.height()},this.originalPosition={left:i,top:s},this.originalMousePosition={left:e.pageX,top:e.pageY},this.aspectRatio="number"==typeof o.aspectRatio?o.aspectRatio:this.originalSize.width/this.originalSize.height||1,n=t(".ui-resizable-"+this.axis).css("cursor"),t("body").css("cursor","auto"===n?this.axis+"-resize":n),this._addClass("ui-resizable-resizing"),this._propagate("start",e),!0},_mouseDrag:function(e){var i,s,n=this.originalMousePosition,o=this.axis,a=e.pageX-n.left||0,r=e.pageY-n.top||0,h=this._change[o];return this._updatePrevProperties(),h?(i=h.apply(this,[e,a,r]),this._updateVirtualBoundaries(e.shiftKey),(this._aspectRatio||e.shiftKey)&&(i=this._updateRatio(i,e)),i=this._respectSize(i,e),this._updateCache(i),this._propagate("resize",e),s=this._applyChanges(),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),t.isEmptyObject(s)||(this._updatePrevProperties(),this._trigger("resize",e,this.ui()),this._applyChanges()),!1):!1},_mouseStop:function(e){this.resizing=!1;var i,s,n,o,a,r,h,l=this.options,c=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&this._hasScroll(i[0],"left")?0:c.sizeDiff.height,o=s?0:c.sizeDiff.width,a={width:c.helper.width()-o,height:c.helper.height()-n},r=parseFloat(c.element.css("left"))+(c.position.left-c.originalPosition.left)||null,h=parseFloat(c.element.css("top"))+(c.position.top-c.originalPosition.top)||null,l.animate||this.element.css(t.extend(a,{top:h,left:r})),c.helper.height(c.size.height),c.helper.width(c.size.width),this._helper&&!l.animate&&this._proportionallyResize()),t("body").css("cursor","auto"),this._removeClass("ui-resizable-resizing"),this._propagate("stop",e),this._helper&&this.helper.remove(),!1},_updatePrevProperties:function(){this.prevPosition={top:this.position.top,left:this.position.left},this.prevSize={width:this.size.width,height:this.size.height}},_applyChanges:function(){var t={};return this.position.top!==this.prevPosition.top&&(t.top=this.position.top+"px"),this.position.left!==this.prevPosition.left&&(t.left=this.position.left+"px"),this.size.width!==this.prevSize.width&&(t.width=this.size.width+"px"),this.size.height!==this.prevSize.height&&(t.height=this.size.height+"px"),this.helper.css(t),t},_updateVirtualBoundaries:function(t){var e,i,s,n,o,a=this.options;o={minWidth:this._isNumber(a.minWidth)?a.minWidth:0,maxWidth:this._isNumber(a.maxWidth)?a.maxWidth:1/0,minHeight:this._isNumber(a.minHeight)?a.minHeight:0,maxHeight:this._isNumber(a.maxHeight)?a.maxHeight:1/0},(this._aspectRatio||t)&&(e=o.minHeight*this.aspectRatio,s=o.minWidth/this.aspectRatio,i=o.maxHeight*this.aspectRatio,n=o.maxWidth/this.aspectRatio,e>o.minWidth&&(o.minWidth=e),s>o.minHeight&&(o.minHeight=s),o.maxWidth>i&&(o.maxWidth=i),o.maxHeight>n&&(o.maxHeight=n)),this._vBoundaries=o},_updateCache:function(t){this.offset=this.helper.offset(),this._isNumber(t.left)&&(this.position.left=t.left),this._isNumber(t.top)&&(this.position.top=t.top),this._isNumber(t.height)&&(this.size.height=t.height),this._isNumber(t.width)&&(this.size.width=t.width)},_updateRatio:function(t){var e=this.position,i=this.size,s=this.axis;return this._isNumber(t.height)?t.width=t.height*this.aspectRatio:this._isNumber(t.width)&&(t.height=t.width/this.aspectRatio),"sw"===s&&(t.left=e.left+(i.width-t.width),t.top=null),"nw"===s&&(t.top=e.top+(i.height-t.height),t.left=e.left+(i.width-t.width)),t},_respectSize:function(t){var e=this._vBoundaries,i=this.axis,s=this._isNumber(t.width)&&e.maxWidth&&e.maxWidth<t.width,n=this._isNumber(t.height)&&e.maxHeight&&e.maxHeight<t.height,o=this._isNumber(t.width)&&e.minWidth&&e.minWidth>t.width,a=this._isNumber(t.height)&&e.minHeight&&e.minHeight>t.height,r=this.originalPosition.left+this.originalSize.width,h=this.originalPosition.top+this.originalSize.height,l=/sw|nw|w/.test(i),c=/nw|ne|n/.test(i);return o&&(t.width=e.minWidth),a&&(t.height=e.minHeight),s&&(t.width=e.maxWidth),n&&(t.height=e.maxHeight),o&&l&&(t.left=r-e.minWidth),s&&l&&(t.left=r-e.maxWidth),a&&c&&(t.top=h-e.minHeight),n&&c&&(t.top=h-e.maxHeight),t.width||t.height||t.left||!t.top?t.width||t.height||t.top||!t.left||(t.left=null):t.top=null,t},_getPaddingPlusBorderDimensions:function(t){for(var e=0,i=[],s=[t.css("borderTopWidth"),t.css("borderRightWidth"),t.css("borderBottomWidth"),t.css("borderLeftWidth")],n=[t.css("paddingTop"),t.css("paddingRight"),t.css("paddingBottom"),t.css("paddingLeft")];4>e;e++)i[e]=parseFloat(s[e])||0,i[e]+=parseFloat(n[e])||0;return{height:i[0]+i[2],width:i[1]+i[3]}},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var t,e=0,i=this.helper||this.element;this._proportionallyResizeElements.length>e;e++)t=this._proportionallyResizeElements[e],this.outerDimensions||(this.outerDimensions=this._getPaddingPlusBorderDimensions(t)),t.css({height:i.height()-this.outerDimensions.height||0,width:i.width()-this.outerDimensions.width||0})},_renderProxy:function(){var e=this.element,i=this.options;this.elementOffset=e.offset(),this._helper?(this.helper=this.helper||t("<div style='overflow:hidden;'></div>"),this._addClass(this.helper,this._helper),this.helper.css({width:this.element.outerWidth(),height:this.element.outerHeight(),position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++i.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(t,e){return{width:this.originalSize.width+e}},w:function(t,e){var i=this.originalSize,s=this.originalPosition;return{left:s.left+e,width:i.width-e}},n:function(t,e,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(t,e,i){return{height:this.originalSize.height+i}},se:function(e,i,s){return t.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[e,i,s]))},sw:function(e,i,s){return t.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[e,i,s]))},ne:function(e,i,s){return t.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[e,i,s]))},nw:function(e,i,s){return t.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[e,i,s]))}},_propagate:function(e,i){t.ui.plugin.call(this,e,[i,this.ui()]),"resize"!==e&&this._trigger(e,i,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),t.ui.plugin.add("resizable","animate",{stop:function(e){var i=t(this).resizable("instance"),s=i.options,n=i._proportionallyResizeElements,o=n.length&&/textarea/i.test(n[0].nodeName),a=o&&i._hasScroll(n[0],"left")?0:i.sizeDiff.height,r=o?0:i.sizeDiff.width,h={width:i.size.width-r,height:i.size.height-a},l=parseFloat(i.element.css("left"))+(i.position.left-i.originalPosition.left)||null,c=parseFloat(i.element.css("top"))+(i.position.top-i.originalPosition.top)||null;i.element.animate(t.extend(h,c&&l?{top:c,left:l}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseFloat(i.element.css("width")),height:parseFloat(i.element.css("height")),top:parseFloat(i.element.css("top")),left:parseFloat(i.element.css("left"))};n&&n.length&&t(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate("resize",e)}})}}),t.ui.plugin.add("resizable","containment",{start:function(){var e,i,s,n,o,a,r,h=t(this).resizable("instance"),l=h.options,c=h.element,u=l.containment,d=u instanceof t?u.get(0):/parent/.test(u)?c.parent().get(0):u;d&&(h.containerElement=t(d),/document/.test(u)||u===document?(h.containerOffset={left:0,top:0},h.containerPosition={left:0,top:0},h.parentData={element:t(document),left:0,top:0,width:t(document).width(),height:t(document).height()||document.body.parentNode.scrollHeight}):(e=t(d),i=[],t(["Top","Right","Left","Bottom"]).each(function(t,s){i[t]=h._num(e.css("padding"+s))}),h.containerOffset=e.offset(),h.containerPosition=e.position(),h.containerSize={height:e.innerHeight()-i[3],width:e.innerWidth()-i[1]},s=h.containerOffset,n=h.containerSize.height,o=h.containerSize.width,a=h._hasScroll(d,"left")?d.scrollWidth:o,r=h._hasScroll(d)?d.scrollHeight:n,h.parentData={element:d,left:s.left,top:s.top,width:a,height:r}))},resize:function(e){var i,s,n,o,a=t(this).resizable("instance"),r=a.options,h=a.containerOffset,l=a.position,c=a._aspectRatio||e.shiftKey,u={top:0,left:0},d=a.containerElement,p=!0;d[0]!==document&&/static/.test(d.css("position"))&&(u=h),l.left<(a._helper?h.left:0)&&(a.size.width=a.size.width+(a._helper?a.position.left-h.left:a.position.left-u.left),c&&(a.size.height=a.size.width/a.aspectRatio,p=!1),a.position.left=r.helper?h.left:0),l.top<(a._helper?h.top:0)&&(a.size.height=a.size.height+(a._helper?a.position.top-h.top:a.position.top),c&&(a.size.width=a.size.height*a.aspectRatio,p=!1),a.position.top=a._helper?h.top:0),n=a.containerElement.get(0)===a.element.parent().get(0),o=/relative|absolute/.test(a.containerElement.css("position")),n&&o?(a.offset.left=a.parentData.left+a.position.left,a.offset.top=a.parentData.top+a.position.top):(a.offset.left=a.element.offset().left,a.offset.top=a.element.offset().top),i=Math.abs(a.sizeDiff.width+(a._helper?a.offset.left-u.left:a.offset.left-h.left)),s=Math.abs(a.sizeDiff.height+(a._helper?a.offset.top-u.top:a.offset.top-h.top)),i+a.size.width>=a.parentData.width&&(a.size.width=a.parentData.width-i,c&&(a.size.height=a.size.width/a.aspectRatio,p=!1)),s+a.size.height>=a.parentData.height&&(a.size.height=a.parentData.height-s,c&&(a.size.width=a.size.height*a.aspectRatio,p=!1)),p||(a.position.left=a.prevPosition.left,a.position.top=a.prevPosition.top,a.size.width=a.prevSize.width,a.size.height=a.prevSize.height)},stop:function(){var e=t(this).resizable("instance"),i=e.options,s=e.containerOffset,n=e.containerPosition,o=e.containerElement,a=t(e.helper),r=a.offset(),h=a.outerWidth()-e.sizeDiff.width,l=a.outerHeight()-e.sizeDiff.height;e._helper&&!i.animate&&/relative/.test(o.css("position"))&&t(this).css({left:r.left-n.left-s.left,width:h,height:l}),e._helper&&!i.animate&&/static/.test(o.css("position"))&&t(this).css({left:r.left-n.left-s.left,width:h,height:l})}}),t.ui.plugin.add("resizable","alsoResize",{start:function(){var e=t(this).resizable("instance"),i=e.options;t(i.alsoResize).each(function(){var e=t(this);e.data("ui-resizable-alsoresize",{width:parseFloat(e.width()),height:parseFloat(e.height()),left:parseFloat(e.css("left")),top:parseFloat(e.css("top"))})})},resize:function(e,i){var s=t(this).resizable("instance"),n=s.options,o=s.originalSize,a=s.originalPosition,r={height:s.size.height-o.height||0,width:s.size.width-o.width||0,top:s.position.top-a.top||0,left:s.position.left-a.left||0};t(n.alsoResize).each(function(){var e=t(this),s=t(this).data("ui-resizable-alsoresize"),n={},o=e.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];t.each(o,function(t,e){var i=(s[e]||0)+(r[e]||0);i&&i>=0&&(n[e]=i||null)}),e.css(n)})},stop:function(){t(this).removeData("ui-resizable-alsoresize")}}),t.ui.plugin.add("resizable","ghost",{start:function(){var e=t(this).resizable("instance"),i=e.size;e.ghost=e.originalElement.clone(),e.ghost.css({opacity:.25,display:"block",position:"relative",height:i.height,width:i.width,margin:0,left:0,top:0}),e._addClass(e.ghost,"ui-resizable-ghost"),t.uiBackCompat!==!1&&"string"==typeof e.options.ghost&&e.ghost.addClass(this.options.ghost),e.ghost.appendTo(e.helper)},resize:function(){var e=t(this).resizable("instance");e.ghost&&e.ghost.css({position:"relative",height:e.size.height,width:e.size.width})},stop:function(){var e=t(this).resizable("instance");e.ghost&&e.helper&&e.helper.get(0).removeChild(e.ghost.get(0))}}),t.ui.plugin.add("resizable","grid",{resize:function(){var e,i=t(this).resizable("instance"),s=i.options,n=i.size,o=i.originalSize,a=i.originalPosition,r=i.axis,h="number"==typeof s.grid?[s.grid,s.grid]:s.grid,l=h[0]||1,c=h[1]||1,u=Math.round((n.width-o.width)/l)*l,d=Math.round((n.height-o.height)/c)*c,p=o.width+u,f=o.height+d,g=s.maxWidth&&p>s.maxWidth,m=s.maxHeight&&f>s.maxHeight,_=s.minWidth&&s.minWidth>p,v=s.minHeight&&s.minHeight>f;s.grid=h,_&&(p+=l),v&&(f+=c),g&&(p-=l),m&&(f-=c),/^(se|s|e)$/.test(r)?(i.size.width=p,i.size.height=f):/^(ne)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.top=a.top-d):/^(sw)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.left=a.left-u):((0>=f-c||0>=p-l)&&(e=i._getPaddingPlusBorderDimensions(this)),f-c>0?(i.size.height=f,i.position.top=a.top-d):(f=c-e.height,i.size.height=f,i.position.top=a.top+o.height-f),p-l>0?(i.size.width=p,i.position.left=a.left-u):(p=l-e.width,i.size.width=p,i.position.left=a.left+o.width-p))}}),t.ui.resizable,t.widget("ui.dialog",{version:"1.12.1",options:{appendTo:"body",autoOpen:!0,buttons:[],classes:{"ui-dialog":"ui-corner-all","ui-dialog-titlebar":"ui-corner-all"},closeOnEscape:!0,closeText:"Close",draggable:!0,hide:null,height:"auto",maxHeight:null,maxWidth:null,minHeight:150,minWidth:150,modal:!1,position:{my:"center",at:"center",of:window,collision:"fit",using:function(e){var i=t(this).css(e).offset().top;0>i&&t(this).css("top",e.top-i)}},resizable:!0,show:null,title:null,width:300,beforeClose:null,close:null,drag:null,dragStart:null,dragStop:null,focus:null,open:null,resize:null,resizeStart:null,resizeStop:null},sizeRelatedOptions:{buttons:!0,height:!0,maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0,width:!0},resizableRelatedOptions:{maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0},_create:function(){this.originalCss={display:this.element[0].style.display,width:this.element[0].style.width,minHeight:this.element[0].style.minHeight,maxHeight:this.element[0].style.maxHeight,height:this.element[0].style.height},this.originalPosition={parent:this.element.parent(),index:this.element.parent().children().index(this.element)},this.originalTitle=this.element.attr("title"),null==this.options.title&&null!=this.originalTitle&&(this.options.title=this.originalTitle),this.options.disabled&&(this.options.disabled=!1),this._createWrapper(),this.element.show().removeAttr("title").appendTo(this.uiDialog),this._addClass("ui-dialog-content","ui-widget-content"),this._createTitlebar(),this._createButtonPane(),this.options.draggable&&t.fn.draggable&&this._makeDraggable(),this.options.resizable&&t.fn.resizable&&this._makeResizable(),this._isOpen=!1,this._trackFocus()},_init:function(){this.options.autoOpen&&this.open()},_appendTo:function(){var e=this.options.appendTo;return e&&(e.jquery||e.nodeType)?t(e):this.document.find(e||"body").eq(0)},_destroy:function(){var t,e=this.originalPosition;this._untrackInstance(),this._destroyOverlay(),this.element.removeUniqueId().css(this.originalCss).detach(),this.uiDialog.remove(),this.originalTitle&&this.element.attr("title",this.originalTitle),t=e.parent.children().eq(e.index),t.length&&t[0]!==this.element[0]?t.before(this.element):e.parent.append(this.element)},widget:function(){return this.uiDialog -},disable:t.noop,enable:t.noop,close:function(e){var i=this;this._isOpen&&this._trigger("beforeClose",e)!==!1&&(this._isOpen=!1,this._focusedElement=null,this._destroyOverlay(),this._untrackInstance(),this.opener.filter(":focusable").trigger("focus").length||t.ui.safeBlur(t.ui.safeActiveElement(this.document[0])),this._hide(this.uiDialog,this.options.hide,function(){i._trigger("close",e)}))},isOpen:function(){return this._isOpen},moveToTop:function(){this._moveToTop()},_moveToTop:function(e,i){var s=!1,n=this.uiDialog.siblings(".ui-front:visible").map(function(){return+t(this).css("z-index")}).get(),o=Math.max.apply(null,n);return o>=+this.uiDialog.css("z-index")&&(this.uiDialog.css("z-index",o+1),s=!0),s&&!i&&this._trigger("focus",e),s},open:function(){var e=this;return this._isOpen?(this._moveToTop()&&this._focusTabbable(),void 0):(this._isOpen=!0,this.opener=t(t.ui.safeActiveElement(this.document[0])),this._size(),this._position(),this._createOverlay(),this._moveToTop(null,!0),this.overlay&&this.overlay.css("z-index",this.uiDialog.css("z-index")-1),this._show(this.uiDialog,this.options.show,function(){e._focusTabbable(),e._trigger("focus")}),this._makeFocusTarget(),this._trigger("open"),void 0)},_focusTabbable:function(){var t=this._focusedElement;t||(t=this.element.find("[autofocus]")),t.length||(t=this.element.find(":tabbable")),t.length||(t=this.uiDialogButtonPane.find(":tabbable")),t.length||(t=this.uiDialogTitlebarClose.filter(":tabbable")),t.length||(t=this.uiDialog),t.eq(0).trigger("focus")},_keepFocus:function(e){function i(){var e=t.ui.safeActiveElement(this.document[0]),i=this.uiDialog[0]===e||t.contains(this.uiDialog[0],e);i||this._focusTabbable()}e.preventDefault(),i.call(this),this._delay(i)},_createWrapper:function(){this.uiDialog=t("<div>").hide().attr({tabIndex:-1,role:"dialog"}).appendTo(this._appendTo()),this._addClass(this.uiDialog,"ui-dialog","ui-widget ui-widget-content ui-front"),this._on(this.uiDialog,{keydown:function(e){if(this.options.closeOnEscape&&!e.isDefaultPrevented()&&e.keyCode&&e.keyCode===t.ui.keyCode.ESCAPE)return e.preventDefault(),this.close(e),void 0;if(e.keyCode===t.ui.keyCode.TAB&&!e.isDefaultPrevented()){var i=this.uiDialog.find(":tabbable"),s=i.filter(":first"),n=i.filter(":last");e.target!==n[0]&&e.target!==this.uiDialog[0]||e.shiftKey?e.target!==s[0]&&e.target!==this.uiDialog[0]||!e.shiftKey||(this._delay(function(){n.trigger("focus")}),e.preventDefault()):(this._delay(function(){s.trigger("focus")}),e.preventDefault())}},mousedown:function(t){this._moveToTop(t)&&this._focusTabbable()}}),this.element.find("[aria-describedby]").length||this.uiDialog.attr({"aria-describedby":this.element.uniqueId().attr("id")})},_createTitlebar:function(){var e;this.uiDialogTitlebar=t("<div>"),this._addClass(this.uiDialogTitlebar,"ui-dialog-titlebar","ui-widget-header ui-helper-clearfix"),this._on(this.uiDialogTitlebar,{mousedown:function(e){t(e.target).closest(".ui-dialog-titlebar-close")||this.uiDialog.trigger("focus")}}),this.uiDialogTitlebarClose=t("<button type='button'></button>").button({label:t("<a>").text(this.options.closeText).html(),icon:"ui-icon-closethick",showLabel:!1}).appendTo(this.uiDialogTitlebar),this._addClass(this.uiDialogTitlebarClose,"ui-dialog-titlebar-close"),this._on(this.uiDialogTitlebarClose,{click:function(t){t.preventDefault(),this.close(t)}}),e=t("<span>").uniqueId().prependTo(this.uiDialogTitlebar),this._addClass(e,"ui-dialog-title"),this._title(e),this.uiDialogTitlebar.prependTo(this.uiDialog),this.uiDialog.attr({"aria-labelledby":e.attr("id")})},_title:function(t){this.options.title?t.text(this.options.title):t.html(" ")},_createButtonPane:function(){this.uiDialogButtonPane=t("<div>"),this._addClass(this.uiDialogButtonPane,"ui-dialog-buttonpane","ui-widget-content ui-helper-clearfix"),this.uiButtonSet=t("<div>").appendTo(this.uiDialogButtonPane),this._addClass(this.uiButtonSet,"ui-dialog-buttonset"),this._createButtons()},_createButtons:function(){var e=this,i=this.options.buttons;return this.uiDialogButtonPane.remove(),this.uiButtonSet.empty(),t.isEmptyObject(i)||t.isArray(i)&&!i.length?(this._removeClass(this.uiDialog,"ui-dialog-buttons"),void 0):(t.each(i,function(i,s){var n,o;s=t.isFunction(s)?{click:s,text:i}:s,s=t.extend({type:"button"},s),n=s.click,o={icon:s.icon,iconPosition:s.iconPosition,showLabel:s.showLabel,icons:s.icons,text:s.text},delete s.click,delete s.icon,delete s.iconPosition,delete s.showLabel,delete s.icons,"boolean"==typeof s.text&&delete s.text,t("<button></button>",s).button(o).appendTo(e.uiButtonSet).on("click",function(){n.apply(e.element[0],arguments)})}),this._addClass(this.uiDialog,"ui-dialog-buttons"),this.uiDialogButtonPane.appendTo(this.uiDialog),void 0)},_makeDraggable:function(){function e(t){return{position:t.position,offset:t.offset}}var i=this,s=this.options;this.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(s,n){i._addClass(t(this),"ui-dialog-dragging"),i._blockFrames(),i._trigger("dragStart",s,e(n))},drag:function(t,s){i._trigger("drag",t,e(s))},stop:function(n,o){var a=o.offset.left-i.document.scrollLeft(),r=o.offset.top-i.document.scrollTop();s.position={my:"left top",at:"left"+(a>=0?"+":"")+a+" "+"top"+(r>=0?"+":"")+r,of:i.window},i._removeClass(t(this),"ui-dialog-dragging"),i._unblockFrames(),i._trigger("dragStop",n,e(o))}})},_makeResizable:function(){function e(t){return{originalPosition:t.originalPosition,originalSize:t.originalSize,position:t.position,size:t.size}}var i=this,s=this.options,n=s.resizable,o=this.uiDialog.css("position"),a="string"==typeof n?n:"n,e,s,w,se,sw,ne,nw";this.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:this.element,maxWidth:s.maxWidth,maxHeight:s.maxHeight,minWidth:s.minWidth,minHeight:this._minHeight(),handles:a,start:function(s,n){i._addClass(t(this),"ui-dialog-resizing"),i._blockFrames(),i._trigger("resizeStart",s,e(n))},resize:function(t,s){i._trigger("resize",t,e(s))},stop:function(n,o){var a=i.uiDialog.offset(),r=a.left-i.document.scrollLeft(),h=a.top-i.document.scrollTop();s.height=i.uiDialog.height(),s.width=i.uiDialog.width(),s.position={my:"left top",at:"left"+(r>=0?"+":"")+r+" "+"top"+(h>=0?"+":"")+h,of:i.window},i._removeClass(t(this),"ui-dialog-resizing"),i._unblockFrames(),i._trigger("resizeStop",n,e(o))}}).css("position",o)},_trackFocus:function(){this._on(this.widget(),{focusin:function(e){this._makeFocusTarget(),this._focusedElement=t(e.target)}})},_makeFocusTarget:function(){this._untrackInstance(),this._trackingInstances().unshift(this)},_untrackInstance:function(){var e=this._trackingInstances(),i=t.inArray(this,e);-1!==i&&e.splice(i,1)},_trackingInstances:function(){var t=this.document.data("ui-dialog-instances");return t||(t=[],this.document.data("ui-dialog-instances",t)),t},_minHeight:function(){var t=this.options;return"auto"===t.height?t.minHeight:Math.min(t.minHeight,t.height)},_position:function(){var t=this.uiDialog.is(":visible");t||this.uiDialog.show(),this.uiDialog.position(this.options.position),t||this.uiDialog.hide()},_setOptions:function(e){var i=this,s=!1,n={};t.each(e,function(t,e){i._setOption(t,e),t in i.sizeRelatedOptions&&(s=!0),t in i.resizableRelatedOptions&&(n[t]=e)}),s&&(this._size(),this._position()),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option",n)},_setOption:function(e,i){var s,n,o=this.uiDialog;"disabled"!==e&&(this._super(e,i),"appendTo"===e&&this.uiDialog.appendTo(this._appendTo()),"buttons"===e&&this._createButtons(),"closeText"===e&&this.uiDialogTitlebarClose.button({label:t("<a>").text(""+this.options.closeText).html()}),"draggable"===e&&(s=o.is(":data(ui-draggable)"),s&&!i&&o.draggable("destroy"),!s&&i&&this._makeDraggable()),"position"===e&&this._position(),"resizable"===e&&(n=o.is(":data(ui-resizable)"),n&&!i&&o.resizable("destroy"),n&&"string"==typeof i&&o.resizable("option","handles",i),n||i===!1||this._makeResizable()),"title"===e&&this._title(this.uiDialogTitlebar.find(".ui-dialog-title")))},_size:function(){var t,e,i,s=this.options;this.element.show().css({width:"auto",minHeight:0,maxHeight:"none",height:0}),s.minWidth>s.width&&(s.width=s.minWidth),t=this.uiDialog.css({height:"auto",width:s.width}).outerHeight(),e=Math.max(0,s.minHeight-t),i="number"==typeof s.maxHeight?Math.max(0,s.maxHeight-t):"none","auto"===s.height?this.element.css({minHeight:e,maxHeight:i,height:"auto"}):this.element.height(Math.max(0,s.height-t)),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())},_blockFrames:function(){this.iframeBlocks=this.document.find("iframe").map(function(){var e=t(this);return t("<div>").css({position:"absolute",width:e.outerWidth(),height:e.outerHeight()}).appendTo(e.parent()).offset(e.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_allowInteraction:function(e){return t(e.target).closest(".ui-dialog").length?!0:!!t(e.target).closest(".ui-datepicker").length},_createOverlay:function(){if(this.options.modal){var e=!0;this._delay(function(){e=!1}),this.document.data("ui-dialog-overlays")||this._on(this.document,{focusin:function(t){e||this._allowInteraction(t)||(t.preventDefault(),this._trackingInstances()[0]._focusTabbable())}}),this.overlay=t("<div>").appendTo(this._appendTo()),this._addClass(this.overlay,null,"ui-widget-overlay ui-front"),this._on(this.overlay,{mousedown:"_keepFocus"}),this.document.data("ui-dialog-overlays",(this.document.data("ui-dialog-overlays")||0)+1)}},_destroyOverlay:function(){if(this.options.modal&&this.overlay){var t=this.document.data("ui-dialog-overlays")-1;t?this.document.data("ui-dialog-overlays",t):(this._off(this.document,"focusin"),this.document.removeData("ui-dialog-overlays")),this.overlay.remove(),this.overlay=null}}}),t.uiBackCompat!==!1&&t.widget("ui.dialog",t.ui.dialog,{options:{dialogClass:""},_createWrapper:function(){this._super(),this.uiDialog.addClass(this.options.dialogClass)},_setOption:function(t,e){"dialogClass"===t&&this.uiDialog.removeClass(this.options.dialogClass).addClass(e),this._superApply(arguments)}}),t.ui.dialog,t.widget("ui.droppable",{version:"1.12.1",widgetEventPrefix:"drop",options:{accept:"*",addClasses:!0,greedy:!1,scope:"default",tolerance:"intersect",activate:null,deactivate:null,drop:null,out:null,over:null},_create:function(){var e,i=this.options,s=i.accept;this.isover=!1,this.isout=!0,this.accept=t.isFunction(s)?s:function(t){return t.is(s)},this.proportions=function(){return arguments.length?(e=arguments[0],void 0):e?e:e={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight}},this._addToManager(i.scope),i.addClasses&&this._addClass("ui-droppable")},_addToManager:function(e){t.ui.ddmanager.droppables[e]=t.ui.ddmanager.droppables[e]||[],t.ui.ddmanager.droppables[e].push(this)},_splice:function(t){for(var e=0;t.length>e;e++)t[e]===this&&t.splice(e,1)},_destroy:function(){var e=t.ui.ddmanager.droppables[this.options.scope];this._splice(e)},_setOption:function(e,i){if("accept"===e)this.accept=t.isFunction(i)?i:function(t){return t.is(i)};else if("scope"===e){var s=t.ui.ddmanager.droppables[this.options.scope];this._splice(s),this._addToManager(i)}this._super(e,i)},_activate:function(e){var i=t.ui.ddmanager.current;this._addActiveClass(),i&&this._trigger("activate",e,this.ui(i))},_deactivate:function(e){var i=t.ui.ddmanager.current;this._removeActiveClass(),i&&this._trigger("deactivate",e,this.ui(i))},_over:function(e){var i=t.ui.ddmanager.current;i&&(i.currentItem||i.element)[0]!==this.element[0]&&this.accept.call(this.element[0],i.currentItem||i.element)&&(this._addHoverClass(),this._trigger("over",e,this.ui(i)))},_out:function(e){var i=t.ui.ddmanager.current;i&&(i.currentItem||i.element)[0]!==this.element[0]&&this.accept.call(this.element[0],i.currentItem||i.element)&&(this._removeHoverClass(),this._trigger("out",e,this.ui(i)))},_drop:function(e,i){var s=i||t.ui.ddmanager.current,n=!1;return s&&(s.currentItem||s.element)[0]!==this.element[0]?(this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function(){var i=t(this).droppable("instance");return i.options.greedy&&!i.options.disabled&&i.options.scope===s.options.scope&&i.accept.call(i.element[0],s.currentItem||s.element)&&v(s,t.extend(i,{offset:i.element.offset()}),i.options.tolerance,e)?(n=!0,!1):void 0}),n?!1:this.accept.call(this.element[0],s.currentItem||s.element)?(this._removeActiveClass(),this._removeHoverClass(),this._trigger("drop",e,this.ui(s)),this.element):!1):!1},ui:function(t){return{draggable:t.currentItem||t.element,helper:t.helper,position:t.position,offset:t.positionAbs}},_addHoverClass:function(){this._addClass("ui-droppable-hover")},_removeHoverClass:function(){this._removeClass("ui-droppable-hover")},_addActiveClass:function(){this._addClass("ui-droppable-active")},_removeActiveClass:function(){this._removeClass("ui-droppable-active")}});var v=t.ui.intersect=function(){function t(t,e,i){return t>=e&&e+i>t}return function(e,i,s,n){if(!i.offset)return!1;var o=(e.positionAbs||e.position.absolute).left+e.margins.left,a=(e.positionAbs||e.position.absolute).top+e.margins.top,r=o+e.helperProportions.width,h=a+e.helperProportions.height,l=i.offset.left,c=i.offset.top,u=l+i.proportions().width,d=c+i.proportions().height;switch(s){case"fit":return o>=l&&u>=r&&a>=c&&d>=h;case"intersect":return o+e.helperProportions.width/2>l&&u>r-e.helperProportions.width/2&&a+e.helperProportions.height/2>c&&d>h-e.helperProportions.height/2;case"pointer":return t(n.pageY,c,i.proportions().height)&&t(n.pageX,l,i.proportions().width);case"touch":return(a>=c&&d>=a||h>=c&&d>=h||c>a&&h>d)&&(o>=l&&u>=o||r>=l&&u>=r||l>o&&r>u);default:return!1}}}();t.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(e,i){var s,n,o=t.ui.ddmanager.droppables[e.options.scope]||[],a=i?i.type:null,r=(e.currentItem||e.element).find(":data(ui-droppable)").addBack();t:for(s=0;o.length>s;s++)if(!(o[s].options.disabled||e&&!o[s].accept.call(o[s].element[0],e.currentItem||e.element))){for(n=0;r.length>n;n++)if(r[n]===o[s].element[0]){o[s].proportions().height=0;continue t}o[s].visible="none"!==o[s].element.css("display"),o[s].visible&&("mousedown"===a&&o[s]._activate.call(o[s],i),o[s].offset=o[s].element.offset(),o[s].proportions({width:o[s].element[0].offsetWidth,height:o[s].element[0].offsetHeight}))}},drop:function(e,i){var s=!1;return t.each((t.ui.ddmanager.droppables[e.options.scope]||[]).slice(),function(){this.options&&(!this.options.disabled&&this.visible&&v(e,this,this.options.tolerance,i)&&(s=this._drop.call(this,i)||s),!this.options.disabled&&this.visible&&this.accept.call(this.element[0],e.currentItem||e.element)&&(this.isout=!0,this.isover=!1,this._deactivate.call(this,i)))}),s},dragStart:function(e,i){e.element.parentsUntil("body").on("scroll.droppable",function(){e.options.refreshPositions||t.ui.ddmanager.prepareOffsets(e,i)})},drag:function(e,i){e.options.refreshPositions&&t.ui.ddmanager.prepareOffsets(e,i),t.each(t.ui.ddmanager.droppables[e.options.scope]||[],function(){if(!this.options.disabled&&!this.greedyChild&&this.visible){var s,n,o,a=v(e,this,this.options.tolerance,i),r=!a&&this.isover?"isout":a&&!this.isover?"isover":null;r&&(this.options.greedy&&(n=this.options.scope,o=this.element.parents(":data(ui-droppable)").filter(function(){return t(this).droppable("instance").options.scope===n}),o.length&&(s=t(o[0]).droppable("instance"),s.greedyChild="isover"===r)),s&&"isover"===r&&(s.isover=!1,s.isout=!0,s._out.call(s,i)),this[r]=!0,this["isout"===r?"isover":"isout"]=!1,this["isover"===r?"_over":"_out"].call(this,i),s&&"isout"===r&&(s.isout=!1,s.isover=!0,s._over.call(s,i)))}})},dragStop:function(e,i){e.element.parentsUntil("body").off("scroll.droppable"),e.options.refreshPositions||t.ui.ddmanager.prepareOffsets(e,i)}},t.uiBackCompat!==!1&&t.widget("ui.droppable",t.ui.droppable,{options:{hoverClass:!1,activeClass:!1},_addActiveClass:function(){this._super(),this.options.activeClass&&this.element.addClass(this.options.activeClass)},_removeActiveClass:function(){this._super(),this.options.activeClass&&this.element.removeClass(this.options.activeClass)},_addHoverClass:function(){this._super(),this.options.hoverClass&&this.element.addClass(this.options.hoverClass)},_removeHoverClass:function(){this._super(),this.options.hoverClass&&this.element.removeClass(this.options.hoverClass)}}),t.ui.droppable,t.widget("ui.progressbar",{version:"1.12.1",options:{classes:{"ui-progressbar":"ui-corner-all","ui-progressbar-value":"ui-corner-left","ui-progressbar-complete":"ui-corner-right"},max:100,value:0,change:null,complete:null},min:0,_create:function(){this.oldValue=this.options.value=this._constrainedValue(),this.element.attr({role:"progressbar","aria-valuemin":this.min}),this._addClass("ui-progressbar","ui-widget ui-widget-content"),this.valueDiv=t("<div>").appendTo(this.element),this._addClass(this.valueDiv,"ui-progressbar-value","ui-widget-header"),this._refreshValue()},_destroy:function(){this.element.removeAttr("role aria-valuemin aria-valuemax aria-valuenow"),this.valueDiv.remove()},value:function(t){return void 0===t?this.options.value:(this.options.value=this._constrainedValue(t),this._refreshValue(),void 0)},_constrainedValue:function(t){return void 0===t&&(t=this.options.value),this.indeterminate=t===!1,"number"!=typeof t&&(t=0),this.indeterminate?!1:Math.min(this.options.max,Math.max(this.min,t))},_setOptions:function(t){var e=t.value;delete t.value,this._super(t),this.options.value=this._constrainedValue(e),this._refreshValue()},_setOption:function(t,e){"max"===t&&(e=Math.max(this.min,e)),this._super(t,e)},_setOptionDisabled:function(t){this._super(t),this.element.attr("aria-disabled",t),this._toggleClass(null,"ui-state-disabled",!!t)},_percentage:function(){return this.indeterminate?100:100*(this.options.value-this.min)/(this.options.max-this.min)},_refreshValue:function(){var e=this.options.value,i=this._percentage();this.valueDiv.toggle(this.indeterminate||e>this.min).width(i.toFixed(0)+"%"),this._toggleClass(this.valueDiv,"ui-progressbar-complete",null,e===this.options.max)._toggleClass("ui-progressbar-indeterminate",null,this.indeterminate),this.indeterminate?(this.element.removeAttr("aria-valuenow"),this.overlayDiv||(this.overlayDiv=t("<div>").appendTo(this.valueDiv),this._addClass(this.overlayDiv,"ui-progressbar-overlay"))):(this.element.attr({"aria-valuemax":this.options.max,"aria-valuenow":e}),this.overlayDiv&&(this.overlayDiv.remove(),this.overlayDiv=null)),this.oldValue!==e&&(this.oldValue=e,this._trigger("change")),e===this.options.max&&this._trigger("complete")}}),t.widget("ui.selectable",t.ui.mouse,{version:"1.12.1",options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch",selected:null,selecting:null,start:null,stop:null,unselected:null,unselecting:null},_create:function(){var e=this;this._addClass("ui-selectable"),this.dragged=!1,this.refresh=function(){e.elementPos=t(e.element[0]).offset(),e.selectees=t(e.options.filter,e.element[0]),e._addClass(e.selectees,"ui-selectee"),e.selectees.each(function(){var i=t(this),s=i.offset(),n={left:s.left-e.elementPos.left,top:s.top-e.elementPos.top};t.data(this,"selectable-item",{element:this,$element:i,left:n.left,top:n.top,right:n.left+i.outerWidth(),bottom:n.top+i.outerHeight(),startselected:!1,selected:i.hasClass("ui-selected"),selecting:i.hasClass("ui-selecting"),unselecting:i.hasClass("ui-unselecting")})})},this.refresh(),this._mouseInit(),this.helper=t("<div>"),this._addClass(this.helper,"ui-selectable-helper")},_destroy:function(){this.selectees.removeData("selectable-item"),this._mouseDestroy()},_mouseStart:function(e){var i=this,s=this.options;this.opos=[e.pageX,e.pageY],this.elementPos=t(this.element[0]).offset(),this.options.disabled||(this.selectees=t(s.filter,this.element[0]),this._trigger("start",e),t(s.appendTo).append(this.helper),this.helper.css({left:e.pageX,top:e.pageY,width:0,height:0}),s.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var s=t.data(this,"selectable-item");s.startselected=!0,e.metaKey||e.ctrlKey||(i._removeClass(s.$element,"ui-selected"),s.selected=!1,i._addClass(s.$element,"ui-unselecting"),s.unselecting=!0,i._trigger("unselecting",e,{unselecting:s.element}))}),t(e.target).parents().addBack().each(function(){var s,n=t.data(this,"selectable-item");return n?(s=!e.metaKey&&!e.ctrlKey||!n.$element.hasClass("ui-selected"),i._removeClass(n.$element,s?"ui-unselecting":"ui-selected")._addClass(n.$element,s?"ui-selecting":"ui-unselecting"),n.unselecting=!s,n.selecting=s,n.selected=s,s?i._trigger("selecting",e,{selecting:n.element}):i._trigger("unselecting",e,{unselecting:n.element}),!1):void 0}))},_mouseDrag:function(e){if(this.dragged=!0,!this.options.disabled){var i,s=this,n=this.options,o=this.opos[0],a=this.opos[1],r=e.pageX,h=e.pageY;return o>r&&(i=r,r=o,o=i),a>h&&(i=h,h=a,a=i),this.helper.css({left:o,top:a,width:r-o,height:h-a}),this.selectees.each(function(){var i=t.data(this,"selectable-item"),l=!1,c={};i&&i.element!==s.element[0]&&(c.left=i.left+s.elementPos.left,c.right=i.right+s.elementPos.left,c.top=i.top+s.elementPos.top,c.bottom=i.bottom+s.elementPos.top,"touch"===n.tolerance?l=!(c.left>r||o>c.right||c.top>h||a>c.bottom):"fit"===n.tolerance&&(l=c.left>o&&r>c.right&&c.top>a&&h>c.bottom),l?(i.selected&&(s._removeClass(i.$element,"ui-selected"),i.selected=!1),i.unselecting&&(s._removeClass(i.$element,"ui-unselecting"),i.unselecting=!1),i.selecting||(s._addClass(i.$element,"ui-selecting"),i.selecting=!0,s._trigger("selecting",e,{selecting:i.element}))):(i.selecting&&((e.metaKey||e.ctrlKey)&&i.startselected?(s._removeClass(i.$element,"ui-selecting"),i.selecting=!1,s._addClass(i.$element,"ui-selected"),i.selected=!0):(s._removeClass(i.$element,"ui-selecting"),i.selecting=!1,i.startselected&&(s._addClass(i.$element,"ui-unselecting"),i.unselecting=!0),s._trigger("unselecting",e,{unselecting:i.element}))),i.selected&&(e.metaKey||e.ctrlKey||i.startselected||(s._removeClass(i.$element,"ui-selected"),i.selected=!1,s._addClass(i.$element,"ui-unselecting"),i.unselecting=!0,s._trigger("unselecting",e,{unselecting:i.element})))))}),!1}},_mouseStop:function(e){var i=this;return this.dragged=!1,t(".ui-unselecting",this.element[0]).each(function(){var s=t.data(this,"selectable-item");i._removeClass(s.$element,"ui-unselecting"),s.unselecting=!1,s.startselected=!1,i._trigger("unselected",e,{unselected:s.element})}),t(".ui-selecting",this.element[0]).each(function(){var s=t.data(this,"selectable-item");i._removeClass(s.$element,"ui-selecting")._addClass(s.$element,"ui-selected"),s.selecting=!1,s.selected=!0,s.startselected=!0,i._trigger("selected",e,{selected:s.element})}),this._trigger("stop",e),this.helper.remove(),!1}}),t.widget("ui.selectmenu",[t.ui.formResetMixin,{version:"1.12.1",defaultElement:"<select>",options:{appendTo:null,classes:{"ui-selectmenu-button-open":"ui-corner-top","ui-selectmenu-button-closed":"ui-corner-all"},disabled:null,icons:{button:"ui-icon-triangle-1-s"},position:{my:"left top",at:"left bottom",collision:"none"},width:!1,change:null,close:null,focus:null,open:null,select:null},_create:function(){var e=this.element.uniqueId().attr("id");this.ids={element:e,button:e+"-button",menu:e+"-menu"},this._drawButton(),this._drawMenu(),this._bindFormResetHandler(),this._rendered=!1,this.menuItems=t()},_drawButton:function(){var e,i=this,s=this._parseOption(this.element.find("option:selected"),this.element[0].selectedIndex);this.labels=this.element.labels().attr("for",this.ids.button),this._on(this.labels,{click:function(t){this.button.focus(),t.preventDefault()}}),this.element.hide(),this.button=t("<span>",{tabindex:this.options.disabled?-1:0,id:this.ids.button,role:"combobox","aria-expanded":"false","aria-autocomplete":"list","aria-owns":this.ids.menu,"aria-haspopup":"true",title:this.element.attr("title")}).insertAfter(this.element),this._addClass(this.button,"ui-selectmenu-button ui-selectmenu-button-closed","ui-button ui-widget"),e=t("<span>").appendTo(this.button),this._addClass(e,"ui-selectmenu-icon","ui-icon "+this.options.icons.button),this.buttonItem=this._renderButtonItem(s).appendTo(this.button),this.options.width!==!1&&this._resizeButton(),this._on(this.button,this._buttonEvents),this.button.one("focusin",function(){i._rendered||i._refreshMenu()})},_drawMenu:function(){var e=this;this.menu=t("<ul>",{"aria-hidden":"true","aria-labelledby":this.ids.button,id:this.ids.menu}),this.menuWrap=t("<div>").append(this.menu),this._addClass(this.menuWrap,"ui-selectmenu-menu","ui-front"),this.menuWrap.appendTo(this._appendTo()),this.menuInstance=this.menu.menu({classes:{"ui-menu":"ui-corner-bottom"},role:"listbox",select:function(t,i){t.preventDefault(),e._setSelection(),e._select(i.item.data("ui-selectmenu-item"),t)},focus:function(t,i){var s=i.item.data("ui-selectmenu-item");null!=e.focusIndex&&s.index!==e.focusIndex&&(e._trigger("focus",t,{item:s}),e.isOpen||e._select(s,t)),e.focusIndex=s.index,e.button.attr("aria-activedescendant",e.menuItems.eq(s.index).attr("id"))}}).menu("instance"),this.menuInstance._off(this.menu,"mouseleave"),this.menuInstance._closeOnDocumentClick=function(){return!1},this.menuInstance._isDivider=function(){return!1}},refresh:function(){this._refreshMenu(),this.buttonItem.replaceWith(this.buttonItem=this._renderButtonItem(this._getSelectedItem().data("ui-selectmenu-item")||{})),null===this.options.width&&this._resizeButton()},_refreshMenu:function(){var t,e=this.element.find("option");this.menu.empty(),this._parseOptions(e),this._renderMenu(this.menu,this.items),this.menuInstance.refresh(),this.menuItems=this.menu.find("li").not(".ui-selectmenu-optgroup").find(".ui-menu-item-wrapper"),this._rendered=!0,e.length&&(t=this._getSelectedItem(),this.menuInstance.focus(null,t),this._setAria(t.data("ui-selectmenu-item")),this._setOption("disabled",this.element.prop("disabled")))},open:function(t){this.options.disabled||(this._rendered?(this._removeClass(this.menu.find(".ui-state-active"),null,"ui-state-active"),this.menuInstance.focus(null,this._getSelectedItem())):this._refreshMenu(),this.menuItems.length&&(this.isOpen=!0,this._toggleAttr(),this._resizeMenu(),this._position(),this._on(this.document,this._documentClick),this._trigger("open",t)))},_position:function(){this.menuWrap.position(t.extend({of:this.button},this.options.position))},close:function(t){this.isOpen&&(this.isOpen=!1,this._toggleAttr(),this.range=null,this._off(this.document),this._trigger("close",t))},widget:function(){return this.button},menuWidget:function(){return this.menu},_renderButtonItem:function(e){var i=t("<span>");return this._setText(i,e.label),this._addClass(i,"ui-selectmenu-text"),i},_renderMenu:function(e,i){var s=this,n="";t.each(i,function(i,o){var a;o.optgroup!==n&&(a=t("<li>",{text:o.optgroup}),s._addClass(a,"ui-selectmenu-optgroup","ui-menu-divider"+(o.element.parent("optgroup").prop("disabled")?" ui-state-disabled":"")),a.appendTo(e),n=o.optgroup),s._renderItemData(e,o)})},_renderItemData:function(t,e){return this._renderItem(t,e).data("ui-selectmenu-item",e)},_renderItem:function(e,i){var s=t("<li>"),n=t("<div>",{title:i.element.attr("title")});return i.disabled&&this._addClass(s,null,"ui-state-disabled"),this._setText(n,i.label),s.append(n).appendTo(e)},_setText:function(t,e){e?t.text(e):t.html(" ")},_move:function(t,e){var i,s,n=".ui-menu-item";this.isOpen?i=this.menuItems.eq(this.focusIndex).parent("li"):(i=this.menuItems.eq(this.element[0].selectedIndex).parent("li"),n+=":not(.ui-state-disabled)"),s="first"===t||"last"===t?i["first"===t?"prevAll":"nextAll"](n).eq(-1):i[t+"All"](n).eq(0),s.length&&this.menuInstance.focus(e,s)},_getSelectedItem:function(){return this.menuItems.eq(this.element[0].selectedIndex).parent("li")},_toggle:function(t){this[this.isOpen?"close":"open"](t)},_setSelection:function(){var t;this.range&&(window.getSelection?(t=window.getSelection(),t.removeAllRanges(),t.addRange(this.range)):this.range.select(),this.button.focus())},_documentClick:{mousedown:function(e){this.isOpen&&(t(e.target).closest(".ui-selectmenu-menu, #"+t.ui.escapeSelector(this.ids.button)).length||this.close(e))}},_buttonEvents:{mousedown:function(){var t;window.getSelection?(t=window.getSelection(),t.rangeCount&&(this.range=t.getRangeAt(0))):this.range=document.selection.createRange()},click:function(t){this._setSelection(),this._toggle(t)},keydown:function(e){var i=!0;switch(e.keyCode){case t.ui.keyCode.TAB:case t.ui.keyCode.ESCAPE:this.close(e),i=!1;break;case t.ui.keyCode.ENTER:this.isOpen&&this._selectFocusedItem(e);break;case t.ui.keyCode.UP:e.altKey?this._toggle(e):this._move("prev",e);break;case t.ui.keyCode.DOWN:e.altKey?this._toggle(e):this._move("next",e);break;case t.ui.keyCode.SPACE:this.isOpen?this._selectFocusedItem(e):this._toggle(e);break;case t.ui.keyCode.LEFT:this._move("prev",e);break;case t.ui.keyCode.RIGHT:this._move("next",e);break;case t.ui.keyCode.HOME:case t.ui.keyCode.PAGE_UP:this._move("first",e);break;case t.ui.keyCode.END:case t.ui.keyCode.PAGE_DOWN:this._move("last",e);break;default:this.menu.trigger(e),i=!1}i&&e.preventDefault()}},_selectFocusedItem:function(t){var e=this.menuItems.eq(this.focusIndex).parent("li");e.hasClass("ui-state-disabled")||this._select(e.data("ui-selectmenu-item"),t)},_select:function(t,e){var i=this.element[0].selectedIndex;this.element[0].selectedIndex=t.index,this.buttonItem.replaceWith(this.buttonItem=this._renderButtonItem(t)),this._setAria(t),this._trigger("select",e,{item:t}),t.index!==i&&this._trigger("change",e,{item:t}),this.close(e)},_setAria:function(t){var e=this.menuItems.eq(t.index).attr("id");this.button.attr({"aria-labelledby":e,"aria-activedescendant":e}),this.menu.attr("aria-activedescendant",e)},_setOption:function(t,e){if("icons"===t){var i=this.button.find("span.ui-icon");this._removeClass(i,null,this.options.icons.button)._addClass(i,null,e.button)}this._super(t,e),"appendTo"===t&&this.menuWrap.appendTo(this._appendTo()),"width"===t&&this._resizeButton()},_setOptionDisabled:function(t){this._super(t),this.menuInstance.option("disabled",t),this.button.attr("aria-disabled",t),this._toggleClass(this.button,null,"ui-state-disabled",t),this.element.prop("disabled",t),t?(this.button.attr("tabindex",-1),this.close()):this.button.attr("tabindex",0)},_appendTo:function(){var e=this.options.appendTo;return e&&(e=e.jquery||e.nodeType?t(e):this.document.find(e).eq(0)),e&&e[0]||(e=this.element.closest(".ui-front, dialog")),e.length||(e=this.document[0].body),e},_toggleAttr:function(){this.button.attr("aria-expanded",this.isOpen),this._removeClass(this.button,"ui-selectmenu-button-"+(this.isOpen?"closed":"open"))._addClass(this.button,"ui-selectmenu-button-"+(this.isOpen?"open":"closed"))._toggleClass(this.menuWrap,"ui-selectmenu-open",null,this.isOpen),this.menu.attr("aria-hidden",!this.isOpen)},_resizeButton:function(){var t=this.options.width;return t===!1?(this.button.css("width",""),void 0):(null===t&&(t=this.element.show().outerWidth(),this.element.hide()),this.button.outerWidth(t),void 0)},_resizeMenu:function(){this.menu.outerWidth(Math.max(this.button.outerWidth(),this.menu.width("").outerWidth()+1))},_getCreateOptions:function(){var t=this._super();return t.disabled=this.element.prop("disabled"),t},_parseOptions:function(e){var i=this,s=[];e.each(function(e,n){s.push(i._parseOption(t(n),e))}),this.items=s},_parseOption:function(t,e){var i=t.parent("optgroup");return{element:t,index:e,value:t.val(),label:t.text(),optgroup:i.attr("label")||"",disabled:i.prop("disabled")||t.prop("disabled")}},_destroy:function(){this._unbindFormResetHandler(),this.menuWrap.remove(),this.button.remove(),this.element.show(),this.element.removeUniqueId(),this.labels.attr("for",this.ids.element)}}]),t.widget("ui.slider",t.ui.mouse,{version:"1.12.1",widgetEventPrefix:"slide",options:{animate:!1,classes:{"ui-slider":"ui-corner-all","ui-slider-handle":"ui-corner-all","ui-slider-range":"ui-corner-all ui-widget-header"},distance:0,max:100,min:0,orientation:"horizontal",range:!1,step:1,value:0,values:null,change:null,slide:null,start:null,stop:null},numPages:5,_create:function(){this._keySliding=!1,this._mouseSliding=!1,this._animateOff=!0,this._handleIndex=null,this._detectOrientation(),this._mouseInit(),this._calculateNewMax(),this._addClass("ui-slider ui-slider-"+this.orientation,"ui-widget ui-widget-content"),this._refresh(),this._animateOff=!1 -},_refresh:function(){this._createRange(),this._createHandles(),this._setupEvents(),this._refreshValue()},_createHandles:function(){var e,i,s=this.options,n=this.element.find(".ui-slider-handle"),o="<span tabindex='0'></span>",a=[];for(i=s.values&&s.values.length||1,n.length>i&&(n.slice(i).remove(),n=n.slice(0,i)),e=n.length;i>e;e++)a.push(o);this.handles=n.add(t(a.join("")).appendTo(this.element)),this._addClass(this.handles,"ui-slider-handle","ui-state-default"),this.handle=this.handles.eq(0),this.handles.each(function(e){t(this).data("ui-slider-handle-index",e).attr("tabIndex",0)})},_createRange:function(){var e=this.options;e.range?(e.range===!0&&(e.values?e.values.length&&2!==e.values.length?e.values=[e.values[0],e.values[0]]:t.isArray(e.values)&&(e.values=e.values.slice(0)):e.values=[this._valueMin(),this._valueMin()]),this.range&&this.range.length?(this._removeClass(this.range,"ui-slider-range-min ui-slider-range-max"),this.range.css({left:"",bottom:""})):(this.range=t("<div>").appendTo(this.element),this._addClass(this.range,"ui-slider-range")),("min"===e.range||"max"===e.range)&&this._addClass(this.range,"ui-slider-range-"+e.range)):(this.range&&this.range.remove(),this.range=null)},_setupEvents:function(){this._off(this.handles),this._on(this.handles,this._handleEvents),this._hoverable(this.handles),this._focusable(this.handles)},_destroy:function(){this.handles.remove(),this.range&&this.range.remove(),this._mouseDestroy()},_mouseCapture:function(e){var i,s,n,o,a,r,h,l,c=this,u=this.options;return u.disabled?!1:(this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()},this.elementOffset=this.element.offset(),i={x:e.pageX,y:e.pageY},s=this._normValueFromMouse(i),n=this._valueMax()-this._valueMin()+1,this.handles.each(function(e){var i=Math.abs(s-c.values(e));(n>i||n===i&&(e===c._lastChangedValue||c.values(e)===u.min))&&(n=i,o=t(this),a=e)}),r=this._start(e,a),r===!1?!1:(this._mouseSliding=!0,this._handleIndex=a,this._addClass(o,null,"ui-state-active"),o.trigger("focus"),h=o.offset(),l=!t(e.target).parents().addBack().is(".ui-slider-handle"),this._clickOffset=l?{left:0,top:0}:{left:e.pageX-h.left-o.width()/2,top:e.pageY-h.top-o.height()/2-(parseInt(o.css("borderTopWidth"),10)||0)-(parseInt(o.css("borderBottomWidth"),10)||0)+(parseInt(o.css("marginTop"),10)||0)},this.handles.hasClass("ui-state-hover")||this._slide(e,a,s),this._animateOff=!0,!0))},_mouseStart:function(){return!0},_mouseDrag:function(t){var e={x:t.pageX,y:t.pageY},i=this._normValueFromMouse(e);return this._slide(t,this._handleIndex,i),!1},_mouseStop:function(t){return this._removeClass(this.handles,null,"ui-state-active"),this._mouseSliding=!1,this._stop(t,this._handleIndex),this._change(t,this._handleIndex),this._handleIndex=null,this._clickOffset=null,this._animateOff=!1,!1},_detectOrientation:function(){this.orientation="vertical"===this.options.orientation?"vertical":"horizontal"},_normValueFromMouse:function(t){var e,i,s,n,o;return"horizontal"===this.orientation?(e=this.elementSize.width,i=t.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)):(e=this.elementSize.height,i=t.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)),s=i/e,s>1&&(s=1),0>s&&(s=0),"vertical"===this.orientation&&(s=1-s),n=this._valueMax()-this._valueMin(),o=this._valueMin()+s*n,this._trimAlignValue(o)},_uiHash:function(t,e,i){var s={handle:this.handles[t],handleIndex:t,value:void 0!==e?e:this.value()};return this._hasMultipleValues()&&(s.value=void 0!==e?e:this.values(t),s.values=i||this.values()),s},_hasMultipleValues:function(){return this.options.values&&this.options.values.length},_start:function(t,e){return this._trigger("start",t,this._uiHash(e))},_slide:function(t,e,i){var s,n,o=this.value(),a=this.values();this._hasMultipleValues()&&(n=this.values(e?0:1),o=this.values(e),2===this.options.values.length&&this.options.range===!0&&(i=0===e?Math.min(n,i):Math.max(n,i)),a[e]=i),i!==o&&(s=this._trigger("slide",t,this._uiHash(e,i,a)),s!==!1&&(this._hasMultipleValues()?this.values(e,i):this.value(i)))},_stop:function(t,e){this._trigger("stop",t,this._uiHash(e))},_change:function(t,e){this._keySliding||this._mouseSliding||(this._lastChangedValue=e,this._trigger("change",t,this._uiHash(e)))},value:function(t){return arguments.length?(this.options.value=this._trimAlignValue(t),this._refreshValue(),this._change(null,0),void 0):this._value()},values:function(e,i){var s,n,o;if(arguments.length>1)return this.options.values[e]=this._trimAlignValue(i),this._refreshValue(),this._change(null,e),void 0;if(!arguments.length)return this._values();if(!t.isArray(arguments[0]))return this._hasMultipleValues()?this._values(e):this.value();for(s=this.options.values,n=arguments[0],o=0;s.length>o;o+=1)s[o]=this._trimAlignValue(n[o]),this._change(null,o);this._refreshValue()},_setOption:function(e,i){var s,n=0;switch("range"===e&&this.options.range===!0&&("min"===i?(this.options.value=this._values(0),this.options.values=null):"max"===i&&(this.options.value=this._values(this.options.values.length-1),this.options.values=null)),t.isArray(this.options.values)&&(n=this.options.values.length),this._super(e,i),e){case"orientation":this._detectOrientation(),this._removeClass("ui-slider-horizontal ui-slider-vertical")._addClass("ui-slider-"+this.orientation),this._refreshValue(),this.options.range&&this._refreshRange(i),this.handles.css("horizontal"===i?"bottom":"left","");break;case"value":this._animateOff=!0,this._refreshValue(),this._change(null,0),this._animateOff=!1;break;case"values":for(this._animateOff=!0,this._refreshValue(),s=n-1;s>=0;s--)this._change(null,s);this._animateOff=!1;break;case"step":case"min":case"max":this._animateOff=!0,this._calculateNewMax(),this._refreshValue(),this._animateOff=!1;break;case"range":this._animateOff=!0,this._refresh(),this._animateOff=!1}},_setOptionDisabled:function(t){this._super(t),this._toggleClass(null,"ui-state-disabled",!!t)},_value:function(){var t=this.options.value;return t=this._trimAlignValue(t)},_values:function(t){var e,i,s;if(arguments.length)return e=this.options.values[t],e=this._trimAlignValue(e);if(this._hasMultipleValues()){for(i=this.options.values.slice(),s=0;i.length>s;s+=1)i[s]=this._trimAlignValue(i[s]);return i}return[]},_trimAlignValue:function(t){if(this._valueMin()>=t)return this._valueMin();if(t>=this._valueMax())return this._valueMax();var e=this.options.step>0?this.options.step:1,i=(t-this._valueMin())%e,s=t-i;return 2*Math.abs(i)>=e&&(s+=i>0?e:-e),parseFloat(s.toFixed(5))},_calculateNewMax:function(){var t=this.options.max,e=this._valueMin(),i=this.options.step,s=Math.round((t-e)/i)*i;t=s+e,t>this.options.max&&(t-=i),this.max=parseFloat(t.toFixed(this._precision()))},_precision:function(){var t=this._precisionOf(this.options.step);return null!==this.options.min&&(t=Math.max(t,this._precisionOf(this.options.min))),t},_precisionOf:function(t){var e=""+t,i=e.indexOf(".");return-1===i?0:e.length-i-1},_valueMin:function(){return this.options.min},_valueMax:function(){return this.max},_refreshRange:function(t){"vertical"===t&&this.range.css({width:"",left:""}),"horizontal"===t&&this.range.css({height:"",bottom:""})},_refreshValue:function(){var e,i,s,n,o,a=this.options.range,r=this.options,h=this,l=this._animateOff?!1:r.animate,c={};this._hasMultipleValues()?this.handles.each(function(s){i=100*((h.values(s)-h._valueMin())/(h._valueMax()-h._valueMin())),c["horizontal"===h.orientation?"left":"bottom"]=i+"%",t(this).stop(1,1)[l?"animate":"css"](c,r.animate),h.options.range===!0&&("horizontal"===h.orientation?(0===s&&h.range.stop(1,1)[l?"animate":"css"]({left:i+"%"},r.animate),1===s&&h.range[l?"animate":"css"]({width:i-e+"%"},{queue:!1,duration:r.animate})):(0===s&&h.range.stop(1,1)[l?"animate":"css"]({bottom:i+"%"},r.animate),1===s&&h.range[l?"animate":"css"]({height:i-e+"%"},{queue:!1,duration:r.animate}))),e=i}):(s=this.value(),n=this._valueMin(),o=this._valueMax(),i=o!==n?100*((s-n)/(o-n)):0,c["horizontal"===this.orientation?"left":"bottom"]=i+"%",this.handle.stop(1,1)[l?"animate":"css"](c,r.animate),"min"===a&&"horizontal"===this.orientation&&this.range.stop(1,1)[l?"animate":"css"]({width:i+"%"},r.animate),"max"===a&&"horizontal"===this.orientation&&this.range.stop(1,1)[l?"animate":"css"]({width:100-i+"%"},r.animate),"min"===a&&"vertical"===this.orientation&&this.range.stop(1,1)[l?"animate":"css"]({height:i+"%"},r.animate),"max"===a&&"vertical"===this.orientation&&this.range.stop(1,1)[l?"animate":"css"]({height:100-i+"%"},r.animate))},_handleEvents:{keydown:function(e){var i,s,n,o,a=t(e.target).data("ui-slider-handle-index");switch(e.keyCode){case t.ui.keyCode.HOME:case t.ui.keyCode.END:case t.ui.keyCode.PAGE_UP:case t.ui.keyCode.PAGE_DOWN:case t.ui.keyCode.UP:case t.ui.keyCode.RIGHT:case t.ui.keyCode.DOWN:case t.ui.keyCode.LEFT:if(e.preventDefault(),!this._keySliding&&(this._keySliding=!0,this._addClass(t(e.target),null,"ui-state-active"),i=this._start(e,a),i===!1))return}switch(o=this.options.step,s=n=this._hasMultipleValues()?this.values(a):this.value(),e.keyCode){case t.ui.keyCode.HOME:n=this._valueMin();break;case t.ui.keyCode.END:n=this._valueMax();break;case t.ui.keyCode.PAGE_UP:n=this._trimAlignValue(s+(this._valueMax()-this._valueMin())/this.numPages);break;case t.ui.keyCode.PAGE_DOWN:n=this._trimAlignValue(s-(this._valueMax()-this._valueMin())/this.numPages);break;case t.ui.keyCode.UP:case t.ui.keyCode.RIGHT:if(s===this._valueMax())return;n=this._trimAlignValue(s+o);break;case t.ui.keyCode.DOWN:case t.ui.keyCode.LEFT:if(s===this._valueMin())return;n=this._trimAlignValue(s-o)}this._slide(e,a,n)},keyup:function(e){var i=t(e.target).data("ui-slider-handle-index");this._keySliding&&(this._keySliding=!1,this._stop(e,i),this._change(e,i),this._removeClass(t(e.target),null,"ui-state-active"))}}}),t.widget("ui.sortable",t.ui.mouse,{version:"1.12.1",widgetEventPrefix:"sort",ready:!1,options:{appendTo:"parent",axis:!1,connectWith:!1,containment:!1,cursor:"auto",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:"original",items:"> *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3,activate:null,beforeStop:null,change:null,deactivate:null,out:null,over:null,receive:null,remove:null,sort:null,start:null,stop:null,update:null},_isOverAxis:function(t,e,i){return t>=e&&e+i>t},_isFloating:function(t){return/left|right/.test(t.css("float"))||/inline|table-cell/.test(t.css("display"))},_create:function(){this.containerCache={},this._addClass("ui-sortable"),this.refresh(),this.offset=this.element.offset(),this._mouseInit(),this._setHandleClassName(),this.ready=!0},_setOption:function(t,e){this._super(t,e),"handle"===t&&this._setHandleClassName()},_setHandleClassName:function(){var e=this;this._removeClass(this.element.find(".ui-sortable-handle"),"ui-sortable-handle"),t.each(this.items,function(){e._addClass(this.instance.options.handle?this.item.find(this.instance.options.handle):this.item,"ui-sortable-handle")})},_destroy:function(){this._mouseDestroy();for(var t=this.items.length-1;t>=0;t--)this.items[t].item.removeData(this.widgetName+"-item");return this},_mouseCapture:function(e,i){var s=null,n=!1,o=this;return this.reverting?!1:this.options.disabled||"static"===this.options.type?!1:(this._refreshItems(e),t(e.target).parents().each(function(){return t.data(this,o.widgetName+"-item")===o?(s=t(this),!1):void 0}),t.data(e.target,o.widgetName+"-item")===o&&(s=t(e.target)),s?!this.options.handle||i||(t(this.options.handle,s).find("*").addBack().each(function(){this===e.target&&(n=!0)}),n)?(this.currentItem=s,this._removeCurrentsFromItems(),!0):!1:!1)},_mouseStart:function(e,i,s){var n,o,a=this.options;if(this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(e),this._cacheHelperProportions(),this._cacheMargins(),this.scrollParent=this.helper.scrollParent(),this.offset=this.currentItem.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},t.extend(this.offset,{click:{left:e.pageX-this.offset.left,top:e.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),this.originalPosition=this._generatePosition(e),this.originalPageX=e.pageX,this.originalPageY=e.pageY,a.cursorAt&&this._adjustOffsetFromHelper(a.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!==this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),a.containment&&this._setContainment(),a.cursor&&"auto"!==a.cursor&&(o=this.document.find("body"),this.storedCursor=o.css("cursor"),o.css("cursor",a.cursor),this.storedStylesheet=t("<style>*{ cursor: "+a.cursor+" !important; }</style>").appendTo(o)),a.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",a.opacity)),a.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",a.zIndex)),this.scrollParent[0]!==this.document[0]&&"HTML"!==this.scrollParent[0].tagName&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",e,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions(),!s)for(n=this.containers.length-1;n>=0;n--)this.containers[n]._trigger("activate",e,this._uiHash(this));return t.ui.ddmanager&&(t.ui.ddmanager.current=this),t.ui.ddmanager&&!a.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e),this.dragging=!0,this._addClass(this.helper,"ui-sortable-helper"),this._mouseDrag(e),!0},_mouseDrag:function(e){var i,s,n,o,a=this.options,r=!1;for(this.position=this._generatePosition(e),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs),this.options.scroll&&(this.scrollParent[0]!==this.document[0]&&"HTML"!==this.scrollParent[0].tagName?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-e.pageY<a.scrollSensitivity?this.scrollParent[0].scrollTop=r=this.scrollParent[0].scrollTop+a.scrollSpeed:e.pageY-this.overflowOffset.top<a.scrollSensitivity&&(this.scrollParent[0].scrollTop=r=this.scrollParent[0].scrollTop-a.scrollSpeed),this.overflowOffset.left+this.scrollParent[0].offsetWidth-e.pageX<a.scrollSensitivity?this.scrollParent[0].scrollLeft=r=this.scrollParent[0].scrollLeft+a.scrollSpeed:e.pageX-this.overflowOffset.left<a.scrollSensitivity&&(this.scrollParent[0].scrollLeft=r=this.scrollParent[0].scrollLeft-a.scrollSpeed)):(e.pageY-this.document.scrollTop()<a.scrollSensitivity?r=this.document.scrollTop(this.document.scrollTop()-a.scrollSpeed):this.window.height()-(e.pageY-this.document.scrollTop())<a.scrollSensitivity&&(r=this.document.scrollTop(this.document.scrollTop()+a.scrollSpeed)),e.pageX-this.document.scrollLeft()<a.scrollSensitivity?r=this.document.scrollLeft(this.document.scrollLeft()-a.scrollSpeed):this.window.width()-(e.pageX-this.document.scrollLeft())<a.scrollSensitivity&&(r=this.document.scrollLeft(this.document.scrollLeft()+a.scrollSpeed))),r!==!1&&t.ui.ddmanager&&!a.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e)),this.positionAbs=this._convertPositionTo("absolute"),this.options.axis&&"y"===this.options.axis||(this.helper[0].style.left=this.position.left+"px"),this.options.axis&&"x"===this.options.axis||(this.helper[0].style.top=this.position.top+"px"),i=this.items.length-1;i>=0;i--)if(s=this.items[i],n=s.item[0],o=this._intersectsWithPointer(s),o&&s.instance===this.currentContainer&&n!==this.currentItem[0]&&this.placeholder[1===o?"next":"prev"]()[0]!==n&&!t.contains(this.placeholder[0],n)&&("semi-dynamic"===this.options.type?!t.contains(this.element[0],n):!0)){if(this.direction=1===o?"down":"up","pointer"!==this.options.tolerance&&!this._intersectsWithSides(s))break;this._rearrange(e,s),this._trigger("change",e,this._uiHash());break}return this._contactContainers(e),t.ui.ddmanager&&t.ui.ddmanager.drag(this,e),this._trigger("sort",e,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseStop:function(e,i){if(e){if(t.ui.ddmanager&&!this.options.dropBehaviour&&t.ui.ddmanager.drop(this,e),this.options.revert){var s=this,n=this.placeholder.offset(),o=this.options.axis,a={};o&&"x"!==o||(a.left=n.left-this.offset.parent.left-this.margins.left+(this.offsetParent[0]===this.document[0].body?0:this.offsetParent[0].scrollLeft)),o&&"y"!==o||(a.top=n.top-this.offset.parent.top-this.margins.top+(this.offsetParent[0]===this.document[0].body?0:this.offsetParent[0].scrollTop)),this.reverting=!0,t(this.helper).animate(a,parseInt(this.options.revert,10)||500,function(){s._clear(e)})}else this._clear(e,i);return!1}},cancel:function(){if(this.dragging){this._mouseUp(new t.Event("mouseup",{target:null})),"original"===this.options.helper?(this.currentItem.css(this._storedCSS),this._removeClass(this.currentItem,"ui-sortable-helper")):this.currentItem.show();for(var e=this.containers.length-1;e>=0;e--)this.containers[e]._trigger("deactivate",null,this._uiHash(this)),this.containers[e].containerCache.over&&(this.containers[e]._trigger("out",null,this._uiHash(this)),this.containers[e].containerCache.over=0)}return this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),"original"!==this.options.helper&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),t.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?t(this.domPosition.prev).after(this.currentItem):t(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(e){var i=this._getItemsAsjQuery(e&&e.connected),s=[];return e=e||{},t(i).each(function(){var i=(t(e.item||this).attr(e.attribute||"id")||"").match(e.expression||/(.+)[\-=_](.+)/);i&&s.push((e.key||i[1]+"[]")+"="+(e.key&&e.expression?i[1]:i[2]))}),!s.length&&e.key&&s.push(e.key+"="),s.join("&")},toArray:function(e){var i=this._getItemsAsjQuery(e&&e.connected),s=[];return e=e||{},i.each(function(){s.push(t(e.item||this).attr(e.attribute||"id")||"")}),s},_intersectsWith:function(t){var e=this.positionAbs.left,i=e+this.helperProportions.width,s=this.positionAbs.top,n=s+this.helperProportions.height,o=t.left,a=o+t.width,r=t.top,h=r+t.height,l=this.offset.click.top,c=this.offset.click.left,u="x"===this.options.axis||s+l>r&&h>s+l,d="y"===this.options.axis||e+c>o&&a>e+c,p=u&&d;return"pointer"===this.options.tolerance||this.options.forcePointerForContainers||"pointer"!==this.options.tolerance&&this.helperProportions[this.floating?"width":"height"]>t[this.floating?"width":"height"]?p:e+this.helperProportions.width/2>o&&a>i-this.helperProportions.width/2&&s+this.helperProportions.height/2>r&&h>n-this.helperProportions.height/2},_intersectsWithPointer:function(t){var e,i,s="x"===this.options.axis||this._isOverAxis(this.positionAbs.top+this.offset.click.top,t.top,t.height),n="y"===this.options.axis||this._isOverAxis(this.positionAbs.left+this.offset.click.left,t.left,t.width),o=s&&n;return o?(e=this._getDragVerticalDirection(),i=this._getDragHorizontalDirection(),this.floating?"right"===i||"down"===e?2:1:e&&("down"===e?2:1)):!1},_intersectsWithSides:function(t){var e=this._isOverAxis(this.positionAbs.top+this.offset.click.top,t.top+t.height/2,t.height),i=this._isOverAxis(this.positionAbs.left+this.offset.click.left,t.left+t.width/2,t.width),s=this._getDragVerticalDirection(),n=this._getDragHorizontalDirection();return this.floating&&n?"right"===n&&i||"left"===n&&!i:s&&("down"===s&&e||"up"===s&&!e)},_getDragVerticalDirection:function(){var t=this.positionAbs.top-this.lastPositionAbs.top;return 0!==t&&(t>0?"down":"up")},_getDragHorizontalDirection:function(){var t=this.positionAbs.left-this.lastPositionAbs.left;return 0!==t&&(t>0?"right":"left")},refresh:function(t){return this._refreshItems(t),this._setHandleClassName(),this.refreshPositions(),this},_connectWith:function(){var t=this.options;return t.connectWith.constructor===String?[t.connectWith]:t.connectWith},_getItemsAsjQuery:function(e){function i(){r.push(this)}var s,n,o,a,r=[],h=[],l=this._connectWith();if(l&&e)for(s=l.length-1;s>=0;s--)for(o=t(l[s],this.document[0]),n=o.length-1;n>=0;n--)a=t.data(o[n],this.widgetFullName),a&&a!==this&&!a.options.disabled&&h.push([t.isFunction(a.options.items)?a.options.items.call(a.element):t(a.options.items,a.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),a]);for(h.push([t.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):t(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]),s=h.length-1;s>=0;s--)h[s][0].each(i);return t(r)},_removeCurrentsFromItems:function(){var e=this.currentItem.find(":data("+this.widgetName+"-item)");this.items=t.grep(this.items,function(t){for(var i=0;e.length>i;i++)if(e[i]===t.item[0])return!1;return!0})},_refreshItems:function(e){this.items=[],this.containers=[this];var i,s,n,o,a,r,h,l,c=this.items,u=[[t.isFunction(this.options.items)?this.options.items.call(this.element[0],e,{item:this.currentItem}):t(this.options.items,this.element),this]],d=this._connectWith();if(d&&this.ready)for(i=d.length-1;i>=0;i--)for(n=t(d[i],this.document[0]),s=n.length-1;s>=0;s--)o=t.data(n[s],this.widgetFullName),o&&o!==this&&!o.options.disabled&&(u.push([t.isFunction(o.options.items)?o.options.items.call(o.element[0],e,{item:this.currentItem}):t(o.options.items,o.element),o]),this.containers.push(o));for(i=u.length-1;i>=0;i--)for(a=u[i][1],r=u[i][0],s=0,l=r.length;l>s;s++)h=t(r[s]),h.data(this.widgetName+"-item",a),c.push({item:h,instance:a,width:0,height:0,left:0,top:0})},refreshPositions:function(e){this.floating=this.items.length?"x"===this.options.axis||this._isFloating(this.items[0].item):!1,this.offsetParent&&this.helper&&(this.offset.parent=this._getParentOffset());var i,s,n,o;for(i=this.items.length-1;i>=0;i--)s=this.items[i],s.instance!==this.currentContainer&&this.currentContainer&&s.item[0]!==this.currentItem[0]||(n=this.options.toleranceElement?t(this.options.toleranceElement,s.item):s.item,e||(s.width=n.outerWidth(),s.height=n.outerHeight()),o=n.offset(),s.left=o.left,s.top=o.top);if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(i=this.containers.length-1;i>=0;i--)o=this.containers[i].element.offset(),this.containers[i].containerCache.left=o.left,this.containers[i].containerCache.top=o.top,this.containers[i].containerCache.width=this.containers[i].element.outerWidth(),this.containers[i].containerCache.height=this.containers[i].element.outerHeight();return this},_createPlaceholder:function(e){e=e||this;var i,s=e.options;s.placeholder&&s.placeholder.constructor!==String||(i=s.placeholder,s.placeholder={element:function(){var s=e.currentItem[0].nodeName.toLowerCase(),n=t("<"+s+">",e.document[0]);return e._addClass(n,"ui-sortable-placeholder",i||e.currentItem[0].className)._removeClass(n,"ui-sortable-helper"),"tbody"===s?e._createTrPlaceholder(e.currentItem.find("tr").eq(0),t("<tr>",e.document[0]).appendTo(n)):"tr"===s?e._createTrPlaceholder(e.currentItem,n):"img"===s&&n.attr("src",e.currentItem.attr("src")),i||n.css("visibility","hidden"),n},update:function(t,n){(!i||s.forcePlaceholderSize)&&(n.height()||n.height(e.currentItem.innerHeight()-parseInt(e.currentItem.css("paddingTop")||0,10)-parseInt(e.currentItem.css("paddingBottom")||0,10)),n.width()||n.width(e.currentItem.innerWidth()-parseInt(e.currentItem.css("paddingLeft")||0,10)-parseInt(e.currentItem.css("paddingRight")||0,10)))}}),e.placeholder=t(s.placeholder.element.call(e.element,e.currentItem)),e.currentItem.after(e.placeholder),s.placeholder.update(e,e.placeholder)},_createTrPlaceholder:function(e,i){var s=this;e.children().each(function(){t("<td> </td>",s.document[0]).attr("colspan",t(this).attr("colspan")||1).appendTo(i)})},_contactContainers:function(e){var i,s,n,o,a,r,h,l,c,u,d=null,p=null;for(i=this.containers.length-1;i>=0;i--)if(!t.contains(this.currentItem[0],this.containers[i].element[0]))if(this._intersectsWith(this.containers[i].containerCache)){if(d&&t.contains(this.containers[i].element[0],d.element[0]))continue;d=this.containers[i],p=i}else this.containers[i].containerCache.over&&(this.containers[i]._trigger("out",e,this._uiHash(this)),this.containers[i].containerCache.over=0);if(d)if(1===this.containers.length)this.containers[p].containerCache.over||(this.containers[p]._trigger("over",e,this._uiHash(this)),this.containers[p].containerCache.over=1);else{for(n=1e4,o=null,c=d.floating||this._isFloating(this.currentItem),a=c?"left":"top",r=c?"width":"height",u=c?"pageX":"pageY",s=this.items.length-1;s>=0;s--)t.contains(this.containers[p].element[0],this.items[s].item[0])&&this.items[s].item[0]!==this.currentItem[0]&&(h=this.items[s].item.offset()[a],l=!1,e[u]-h>this.items[s][r]/2&&(l=!0),n>Math.abs(e[u]-h)&&(n=Math.abs(e[u]-h),o=this.items[s],this.direction=l?"up":"down"));if(!o&&!this.options.dropOnEmpty)return;if(this.currentContainer===this.containers[p])return this.currentContainer.containerCache.over||(this.containers[p]._trigger("over",e,this._uiHash()),this.currentContainer.containerCache.over=1),void 0;o?this._rearrange(e,o,null,!0):this._rearrange(e,null,this.containers[p].element,!0),this._trigger("change",e,this._uiHash()),this.containers[p]._trigger("change",e,this._uiHash(this)),this.currentContainer=this.containers[p],this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[p]._trigger("over",e,this._uiHash(this)),this.containers[p].containerCache.over=1}},_createHelper:function(e){var i=this.options,s=t.isFunction(i.helper)?t(i.helper.apply(this.element[0],[e,this.currentItem])):"clone"===i.helper?this.currentItem.clone():this.currentItem;return s.parents("body").length||t("parent"!==i.appendTo?i.appendTo:this.currentItem[0].parentNode)[0].appendChild(s[0]),s[0]===this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}),(!s[0].style.width||i.forceHelperSize)&&s.width(this.currentItem.width()),(!s[0].style.height||i.forceHelperSize)&&s.height(this.currentItem.height()),s},_adjustOffsetFromHelper:function(e){"string"==typeof e&&(e=e.split(" ")),t.isArray(e)&&(e={left:+e[0],top:+e[1]||0}),"left"in e&&(this.offset.click.left=e.left+this.margins.left),"right"in e&&(this.offset.click.left=this.helperProportions.width-e.right+this.margins.left),"top"in e&&(this.offset.click.top=e.top+this.margins.top),"bottom"in e&&(this.offset.click.top=this.helperProportions.height-e.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var e=this.offsetParent.offset();return"absolute"===this.cssPosition&&this.scrollParent[0]!==this.document[0]&&t.contains(this.scrollParent[0],this.offsetParent[0])&&(e.left+=this.scrollParent.scrollLeft(),e.top+=this.scrollParent.scrollTop()),(this.offsetParent[0]===this.document[0].body||this.offsetParent[0].tagName&&"html"===this.offsetParent[0].tagName.toLowerCase()&&t.ui.ie)&&(e={top:0,left:0}),{top:e.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:e.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"===this.cssPosition){var t=this.currentItem.position();return{top:t.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:t.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e,i,s,n=this.options;"parent"===n.containment&&(n.containment=this.helper[0].parentNode),("document"===n.containment||"window"===n.containment)&&(this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,"document"===n.containment?this.document.width():this.window.width()-this.helperProportions.width-this.margins.left,("document"===n.containment?this.document.height()||document.body.parentNode.scrollHeight:this.window.height()||this.document[0].body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top]),/^(document|window|parent)$/.test(n.containment)||(e=t(n.containment)[0],i=t(n.containment).offset(),s="hidden"!==t(e).css("overflow"),this.containment=[i.left+(parseInt(t(e).css("borderLeftWidth"),10)||0)+(parseInt(t(e).css("paddingLeft"),10)||0)-this.margins.left,i.top+(parseInt(t(e).css("borderTopWidth"),10)||0)+(parseInt(t(e).css("paddingTop"),10)||0)-this.margins.top,i.left+(s?Math.max(e.scrollWidth,e.offsetWidth):e.offsetWidth)-(parseInt(t(e).css("borderLeftWidth"),10)||0)-(parseInt(t(e).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,i.top+(s?Math.max(e.scrollHeight,e.offsetHeight):e.offsetHeight)-(parseInt(t(e).css("borderTopWidth"),10)||0)-(parseInt(t(e).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top])},_convertPositionTo:function(e,i){i||(i=this.position);var s="absolute"===e?1:-1,n="absolute"!==this.cssPosition||this.scrollParent[0]!==this.document[0]&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,o=/(html|body)/i.test(n[0].tagName);return{top:i.top+this.offset.relative.top*s+this.offset.parent.top*s-("fixed"===this.cssPosition?-this.scrollParent.scrollTop():o?0:n.scrollTop())*s,left:i.left+this.offset.relative.left*s+this.offset.parent.left*s-("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():o?0:n.scrollLeft())*s}},_generatePosition:function(e){var i,s,n=this.options,o=e.pageX,a=e.pageY,r="absolute"!==this.cssPosition||this.scrollParent[0]!==this.document[0]&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,h=/(html|body)/i.test(r[0].tagName);return"relative"!==this.cssPosition||this.scrollParent[0]!==this.document[0]&&this.scrollParent[0]!==this.offsetParent[0]||(this.offset.relative=this._getRelativeOffset()),this.originalPosition&&(this.containment&&(e.pageX-this.offset.click.left<this.containment[0]&&(o=this.containment[0]+this.offset.click.left),e.pageY-this.offset.click.top<this.containment[1]&&(a=this.containment[1]+this.offset.click.top),e.pageX-this.offset.click.left>this.containment[2]&&(o=this.containment[2]+this.offset.click.left),e.pageY-this.offset.click.top>this.containment[3]&&(a=this.containment[3]+this.offset.click.top)),n.grid&&(i=this.originalPageY+Math.round((a-this.originalPageY)/n.grid[1])*n.grid[1],a=this.containment?i-this.offset.click.top>=this.containment[1]&&i-this.offset.click.top<=this.containment[3]?i:i-this.offset.click.top>=this.containment[1]?i-n.grid[1]:i+n.grid[1]:i,s=this.originalPageX+Math.round((o-this.originalPageX)/n.grid[0])*n.grid[0],o=this.containment?s-this.offset.click.left>=this.containment[0]&&s-this.offset.click.left<=this.containment[2]?s:s-this.offset.click.left>=this.containment[0]?s-n.grid[0]:s+n.grid[0]:s)),{top:a-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.scrollParent.scrollTop():h?0:r.scrollTop()),left:o-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():h?0:r.scrollLeft())}},_rearrange:function(t,e,i,s){i?i[0].appendChild(this.placeholder[0]):e.item[0].parentNode.insertBefore(this.placeholder[0],"down"===this.direction?e.item[0]:e.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var n=this.counter; -this._delay(function(){n===this.counter&&this.refreshPositions(!s)})},_clear:function(t,e){function i(t,e,i){return function(s){i._trigger(t,s,e._uiHash(e))}}this.reverting=!1;var s,n=[];if(!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null,this.helper[0]===this.currentItem[0]){for(s in this._storedCSS)("auto"===this._storedCSS[s]||"static"===this._storedCSS[s])&&(this._storedCSS[s]="");this.currentItem.css(this._storedCSS),this._removeClass(this.currentItem,"ui-sortable-helper")}else this.currentItem.show();for(this.fromOutside&&!e&&n.push(function(t){this._trigger("receive",t,this._uiHash(this.fromOutside))}),!this.fromOutside&&this.domPosition.prev===this.currentItem.prev().not(".ui-sortable-helper")[0]&&this.domPosition.parent===this.currentItem.parent()[0]||e||n.push(function(t){this._trigger("update",t,this._uiHash())}),this!==this.currentContainer&&(e||(n.push(function(t){this._trigger("remove",t,this._uiHash())}),n.push(function(t){return function(e){t._trigger("receive",e,this._uiHash(this))}}.call(this,this.currentContainer)),n.push(function(t){return function(e){t._trigger("update",e,this._uiHash(this))}}.call(this,this.currentContainer)))),s=this.containers.length-1;s>=0;s--)e||n.push(i("deactivate",this,this.containers[s])),this.containers[s].containerCache.over&&(n.push(i("out",this,this.containers[s])),this.containers[s].containerCache.over=0);if(this.storedCursor&&(this.document.find("body").css("cursor",this.storedCursor),this.storedStylesheet.remove()),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex","auto"===this._storedZIndex?"":this._storedZIndex),this.dragging=!1,e||this._trigger("beforeStop",t,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.cancelHelperRemoval||(this.helper[0]!==this.currentItem[0]&&this.helper.remove(),this.helper=null),!e){for(s=0;n.length>s;s++)n[s].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!this.cancelHelperRemoval},_trigger:function(){t.Widget.prototype._trigger.apply(this,arguments)===!1&&this.cancel()},_uiHash:function(e){var i=e||this;return{helper:i.helper,placeholder:i.placeholder||t([]),position:i.position,originalPosition:i.originalPosition,offset:i.positionAbs,item:i.currentItem,sender:e?e.element:null}}}),t.widget("ui.spinner",{version:"1.12.1",defaultElement:"<input>",widgetEventPrefix:"spin",options:{classes:{"ui-spinner":"ui-corner-all","ui-spinner-down":"ui-corner-br","ui-spinner-up":"ui-corner-tr"},culture:null,icons:{down:"ui-icon-triangle-1-s",up:"ui-icon-triangle-1-n"},incremental:!0,max:null,min:null,numberFormat:null,page:10,step:1,change:null,spin:null,start:null,stop:null},_create:function(){this._setOption("max",this.options.max),this._setOption("min",this.options.min),this._setOption("step",this.options.step),""!==this.value()&&this._value(this.element.val(),!0),this._draw(),this._on(this._events),this._refresh(),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_getCreateOptions:function(){var e=this._super(),i=this.element;return t.each(["min","max","step"],function(t,s){var n=i.attr(s);null!=n&&n.length&&(e[s]=n)}),e},_events:{keydown:function(t){this._start(t)&&this._keydown(t)&&t.preventDefault()},keyup:"_stop",focus:function(){this.previous=this.element.val()},blur:function(t){return this.cancelBlur?(delete this.cancelBlur,void 0):(this._stop(),this._refresh(),this.previous!==this.element.val()&&this._trigger("change",t),void 0)},mousewheel:function(t,e){if(e){if(!this.spinning&&!this._start(t))return!1;this._spin((e>0?1:-1)*this.options.step,t),clearTimeout(this.mousewheelTimer),this.mousewheelTimer=this._delay(function(){this.spinning&&this._stop(t)},100),t.preventDefault()}},"mousedown .ui-spinner-button":function(e){function i(){var e=this.element[0]===t.ui.safeActiveElement(this.document[0]);e||(this.element.trigger("focus"),this.previous=s,this._delay(function(){this.previous=s}))}var s;s=this.element[0]===t.ui.safeActiveElement(this.document[0])?this.previous:this.element.val(),e.preventDefault(),i.call(this),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur,i.call(this)}),this._start(e)!==!1&&this._repeat(null,t(e.currentTarget).hasClass("ui-spinner-up")?1:-1,e)},"mouseup .ui-spinner-button":"_stop","mouseenter .ui-spinner-button":function(e){return t(e.currentTarget).hasClass("ui-state-active")?this._start(e)===!1?!1:(this._repeat(null,t(e.currentTarget).hasClass("ui-spinner-up")?1:-1,e),void 0):void 0},"mouseleave .ui-spinner-button":"_stop"},_enhance:function(){this.uiSpinner=this.element.attr("autocomplete","off").wrap("<span>").parent().append("<a></a><a></a>")},_draw:function(){this._enhance(),this._addClass(this.uiSpinner,"ui-spinner","ui-widget ui-widget-content"),this._addClass("ui-spinner-input"),this.element.attr("role","spinbutton"),this.buttons=this.uiSpinner.children("a").attr("tabIndex",-1).attr("aria-hidden",!0).button({classes:{"ui-button":""}}),this._removeClass(this.buttons,"ui-corner-all"),this._addClass(this.buttons.first(),"ui-spinner-button ui-spinner-up"),this._addClass(this.buttons.last(),"ui-spinner-button ui-spinner-down"),this.buttons.first().button({icon:this.options.icons.up,showLabel:!1}),this.buttons.last().button({icon:this.options.icons.down,showLabel:!1}),this.buttons.height()>Math.ceil(.5*this.uiSpinner.height())&&this.uiSpinner.height()>0&&this.uiSpinner.height(this.uiSpinner.height())},_keydown:function(e){var i=this.options,s=t.ui.keyCode;switch(e.keyCode){case s.UP:return this._repeat(null,1,e),!0;case s.DOWN:return this._repeat(null,-1,e),!0;case s.PAGE_UP:return this._repeat(null,i.page,e),!0;case s.PAGE_DOWN:return this._repeat(null,-i.page,e),!0}return!1},_start:function(t){return this.spinning||this._trigger("start",t)!==!1?(this.counter||(this.counter=1),this.spinning=!0,!0):!1},_repeat:function(t,e,i){t=t||500,clearTimeout(this.timer),this.timer=this._delay(function(){this._repeat(40,e,i)},t),this._spin(e*this.options.step,i)},_spin:function(t,e){var i=this.value()||0;this.counter||(this.counter=1),i=this._adjustValue(i+t*this._increment(this.counter)),this.spinning&&this._trigger("spin",e,{value:i})===!1||(this._value(i),this.counter++)},_increment:function(e){var i=this.options.incremental;return i?t.isFunction(i)?i(e):Math.floor(e*e*e/5e4-e*e/500+17*e/200+1):1},_precision:function(){var t=this._precisionOf(this.options.step);return null!==this.options.min&&(t=Math.max(t,this._precisionOf(this.options.min))),t},_precisionOf:function(t){var e=""+t,i=e.indexOf(".");return-1===i?0:e.length-i-1},_adjustValue:function(t){var e,i,s=this.options;return e=null!==s.min?s.min:0,i=t-e,i=Math.round(i/s.step)*s.step,t=e+i,t=parseFloat(t.toFixed(this._precision())),null!==s.max&&t>s.max?s.max:null!==s.min&&s.min>t?s.min:t},_stop:function(t){this.spinning&&(clearTimeout(this.timer),clearTimeout(this.mousewheelTimer),this.counter=0,this.spinning=!1,this._trigger("stop",t))},_setOption:function(t,e){var i,s,n;return"culture"===t||"numberFormat"===t?(i=this._parse(this.element.val()),this.options[t]=e,this.element.val(this._format(i)),void 0):(("max"===t||"min"===t||"step"===t)&&"string"==typeof e&&(e=this._parse(e)),"icons"===t&&(s=this.buttons.first().find(".ui-icon"),this._removeClass(s,null,this.options.icons.up),this._addClass(s,null,e.up),n=this.buttons.last().find(".ui-icon"),this._removeClass(n,null,this.options.icons.down),this._addClass(n,null,e.down)),this._super(t,e),void 0)},_setOptionDisabled:function(t){this._super(t),this._toggleClass(this.uiSpinner,null,"ui-state-disabled",!!t),this.element.prop("disabled",!!t),this.buttons.button(t?"disable":"enable")},_setOptions:r(function(t){this._super(t)}),_parse:function(t){return"string"==typeof t&&""!==t&&(t=window.Globalize&&this.options.numberFormat?Globalize.parseFloat(t,10,this.options.culture):+t),""===t||isNaN(t)?null:t},_format:function(t){return""===t?"":window.Globalize&&this.options.numberFormat?Globalize.format(t,this.options.numberFormat,this.options.culture):t},_refresh:function(){this.element.attr({"aria-valuemin":this.options.min,"aria-valuemax":this.options.max,"aria-valuenow":this._parse(this.element.val())})},isValid:function(){var t=this.value();return null===t?!1:t===this._adjustValue(t)},_value:function(t,e){var i;""!==t&&(i=this._parse(t),null!==i&&(e||(i=this._adjustValue(i)),t=this._format(i))),this.element.val(t),this._refresh()},_destroy:function(){this.element.prop("disabled",!1).removeAttr("autocomplete role aria-valuemin aria-valuemax aria-valuenow"),this.uiSpinner.replaceWith(this.element)},stepUp:r(function(t){this._stepUp(t)}),_stepUp:function(t){this._start()&&(this._spin((t||1)*this.options.step),this._stop())},stepDown:r(function(t){this._stepDown(t)}),_stepDown:function(t){this._start()&&(this._spin((t||1)*-this.options.step),this._stop())},pageUp:r(function(t){this._stepUp((t||1)*this.options.page)}),pageDown:r(function(t){this._stepDown((t||1)*this.options.page)}),value:function(t){return arguments.length?(r(this._value).call(this,t),void 0):this._parse(this.element.val())},widget:function(){return this.uiSpinner}}),t.uiBackCompat!==!1&&t.widget("ui.spinner",t.ui.spinner,{_enhance:function(){this.uiSpinner=this.element.attr("autocomplete","off").wrap(this._uiSpinnerHtml()).parent().append(this._buttonHtml())},_uiSpinnerHtml:function(){return"<span>"},_buttonHtml:function(){return"<a></a><a></a>"}}),t.ui.spinner,t.widget("ui.tabs",{version:"1.12.1",delay:300,options:{active:null,classes:{"ui-tabs":"ui-corner-all","ui-tabs-nav":"ui-corner-all","ui-tabs-panel":"ui-corner-bottom","ui-tabs-tab":"ui-corner-top"},collapsible:!1,event:"click",heightStyle:"content",hide:null,show:null,activate:null,beforeActivate:null,beforeLoad:null,load:null},_isLocal:function(){var t=/#.*$/;return function(e){var i,s;i=e.href.replace(t,""),s=location.href.replace(t,"");try{i=decodeURIComponent(i)}catch(n){}try{s=decodeURIComponent(s)}catch(n){}return e.hash.length>1&&i===s}}(),_create:function(){var e=this,i=this.options;this.running=!1,this._addClass("ui-tabs","ui-widget ui-widget-content"),this._toggleClass("ui-tabs-collapsible",null,i.collapsible),this._processTabs(),i.active=this._initialActive(),t.isArray(i.disabled)&&(i.disabled=t.unique(i.disabled.concat(t.map(this.tabs.filter(".ui-state-disabled"),function(t){return e.tabs.index(t)}))).sort()),this.active=this.options.active!==!1&&this.anchors.length?this._findActive(i.active):t(),this._refresh(),this.active.length&&this.load(i.active)},_initialActive:function(){var e=this.options.active,i=this.options.collapsible,s=location.hash.substring(1);return null===e&&(s&&this.tabs.each(function(i,n){return t(n).attr("aria-controls")===s?(e=i,!1):void 0}),null===e&&(e=this.tabs.index(this.tabs.filter(".ui-tabs-active"))),(null===e||-1===e)&&(e=this.tabs.length?0:!1)),e!==!1&&(e=this.tabs.index(this.tabs.eq(e)),-1===e&&(e=i?!1:0)),!i&&e===!1&&this.anchors.length&&(e=0),e},_getCreateEventData:function(){return{tab:this.active,panel:this.active.length?this._getPanelForTab(this.active):t()}},_tabKeydown:function(e){var i=t(t.ui.safeActiveElement(this.document[0])).closest("li"),s=this.tabs.index(i),n=!0;if(!this._handlePageNav(e)){switch(e.keyCode){case t.ui.keyCode.RIGHT:case t.ui.keyCode.DOWN:s++;break;case t.ui.keyCode.UP:case t.ui.keyCode.LEFT:n=!1,s--;break;case t.ui.keyCode.END:s=this.anchors.length-1;break;case t.ui.keyCode.HOME:s=0;break;case t.ui.keyCode.SPACE:return e.preventDefault(),clearTimeout(this.activating),this._activate(s),void 0;case t.ui.keyCode.ENTER:return e.preventDefault(),clearTimeout(this.activating),this._activate(s===this.options.active?!1:s),void 0;default:return}e.preventDefault(),clearTimeout(this.activating),s=this._focusNextTab(s,n),e.ctrlKey||e.metaKey||(i.attr("aria-selected","false"),this.tabs.eq(s).attr("aria-selected","true"),this.activating=this._delay(function(){this.option("active",s)},this.delay))}},_panelKeydown:function(e){this._handlePageNav(e)||e.ctrlKey&&e.keyCode===t.ui.keyCode.UP&&(e.preventDefault(),this.active.trigger("focus"))},_handlePageNav:function(e){return e.altKey&&e.keyCode===t.ui.keyCode.PAGE_UP?(this._activate(this._focusNextTab(this.options.active-1,!1)),!0):e.altKey&&e.keyCode===t.ui.keyCode.PAGE_DOWN?(this._activate(this._focusNextTab(this.options.active+1,!0)),!0):void 0},_findNextTab:function(e,i){function s(){return e>n&&(e=0),0>e&&(e=n),e}for(var n=this.tabs.length-1;-1!==t.inArray(s(),this.options.disabled);)e=i?e+1:e-1;return e},_focusNextTab:function(t,e){return t=this._findNextTab(t,e),this.tabs.eq(t).trigger("focus"),t},_setOption:function(t,e){return"active"===t?(this._activate(e),void 0):(this._super(t,e),"collapsible"===t&&(this._toggleClass("ui-tabs-collapsible",null,e),e||this.options.active!==!1||this._activate(0)),"event"===t&&this._setupEvents(e),"heightStyle"===t&&this._setupHeightStyle(e),void 0)},_sanitizeSelector:function(t){return t?t.replace(/[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g,"\\$&"):""},refresh:function(){var e=this.options,i=this.tablist.children(":has(a[href])");e.disabled=t.map(i.filter(".ui-state-disabled"),function(t){return i.index(t)}),this._processTabs(),e.active!==!1&&this.anchors.length?this.active.length&&!t.contains(this.tablist[0],this.active[0])?this.tabs.length===e.disabled.length?(e.active=!1,this.active=t()):this._activate(this._findNextTab(Math.max(0,e.active-1),!1)):e.active=this.tabs.index(this.active):(e.active=!1,this.active=t()),this._refresh()},_refresh:function(){this._setOptionDisabled(this.options.disabled),this._setupEvents(this.options.event),this._setupHeightStyle(this.options.heightStyle),this.tabs.not(this.active).attr({"aria-selected":"false","aria-expanded":"false",tabIndex:-1}),this.panels.not(this._getPanelForTab(this.active)).hide().attr({"aria-hidden":"true"}),this.active.length?(this.active.attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0}),this._addClass(this.active,"ui-tabs-active","ui-state-active"),this._getPanelForTab(this.active).show().attr({"aria-hidden":"false"})):this.tabs.eq(0).attr("tabIndex",0)},_processTabs:function(){var e=this,i=this.tabs,s=this.anchors,n=this.panels;this.tablist=this._getList().attr("role","tablist"),this._addClass(this.tablist,"ui-tabs-nav","ui-helper-reset ui-helper-clearfix ui-widget-header"),this.tablist.on("mousedown"+this.eventNamespace,"> li",function(e){t(this).is(".ui-state-disabled")&&e.preventDefault()}).on("focus"+this.eventNamespace,".ui-tabs-anchor",function(){t(this).closest("li").is(".ui-state-disabled")&&this.blur()}),this.tabs=this.tablist.find("> li:has(a[href])").attr({role:"tab",tabIndex:-1}),this._addClass(this.tabs,"ui-tabs-tab","ui-state-default"),this.anchors=this.tabs.map(function(){return t("a",this)[0]}).attr({role:"presentation",tabIndex:-1}),this._addClass(this.anchors,"ui-tabs-anchor"),this.panels=t(),this.anchors.each(function(i,s){var n,o,a,r=t(s).uniqueId().attr("id"),h=t(s).closest("li"),l=h.attr("aria-controls");e._isLocal(s)?(n=s.hash,a=n.substring(1),o=e.element.find(e._sanitizeSelector(n))):(a=h.attr("aria-controls")||t({}).uniqueId()[0].id,n="#"+a,o=e.element.find(n),o.length||(o=e._createPanel(a),o.insertAfter(e.panels[i-1]||e.tablist)),o.attr("aria-live","polite")),o.length&&(e.panels=e.panels.add(o)),l&&h.data("ui-tabs-aria-controls",l),h.attr({"aria-controls":a,"aria-labelledby":r}),o.attr("aria-labelledby",r)}),this.panels.attr("role","tabpanel"),this._addClass(this.panels,"ui-tabs-panel","ui-widget-content"),i&&(this._off(i.not(this.tabs)),this._off(s.not(this.anchors)),this._off(n.not(this.panels)))},_getList:function(){return this.tablist||this.element.find("ol, ul").eq(0)},_createPanel:function(e){return t("<div>").attr("id",e).data("ui-tabs-destroy",!0)},_setOptionDisabled:function(e){var i,s,n;for(t.isArray(e)&&(e.length?e.length===this.anchors.length&&(e=!0):e=!1),n=0;s=this.tabs[n];n++)i=t(s),e===!0||-1!==t.inArray(n,e)?(i.attr("aria-disabled","true"),this._addClass(i,null,"ui-state-disabled")):(i.removeAttr("aria-disabled"),this._removeClass(i,null,"ui-state-disabled"));this.options.disabled=e,this._toggleClass(this.widget(),this.widgetFullName+"-disabled",null,e===!0)},_setupEvents:function(e){var i={};e&&t.each(e.split(" "),function(t,e){i[e]="_eventHandler"}),this._off(this.anchors.add(this.tabs).add(this.panels)),this._on(!0,this.anchors,{click:function(t){t.preventDefault()}}),this._on(this.anchors,i),this._on(this.tabs,{keydown:"_tabKeydown"}),this._on(this.panels,{keydown:"_panelKeydown"}),this._focusable(this.tabs),this._hoverable(this.tabs)},_setupHeightStyle:function(e){var i,s=this.element.parent();"fill"===e?(i=s.height(),i-=this.element.outerHeight()-this.element.height(),this.element.siblings(":visible").each(function(){var e=t(this),s=e.css("position");"absolute"!==s&&"fixed"!==s&&(i-=e.outerHeight(!0))}),this.element.children().not(this.panels).each(function(){i-=t(this).outerHeight(!0)}),this.panels.each(function(){t(this).height(Math.max(0,i-t(this).innerHeight()+t(this).height()))}).css("overflow","auto")):"auto"===e&&(i=0,this.panels.each(function(){i=Math.max(i,t(this).height("").height())}).height(i))},_eventHandler:function(e){var i=this.options,s=this.active,n=t(e.currentTarget),o=n.closest("li"),a=o[0]===s[0],r=a&&i.collapsible,h=r?t():this._getPanelForTab(o),l=s.length?this._getPanelForTab(s):t(),c={oldTab:s,oldPanel:l,newTab:r?t():o,newPanel:h};e.preventDefault(),o.hasClass("ui-state-disabled")||o.hasClass("ui-tabs-loading")||this.running||a&&!i.collapsible||this._trigger("beforeActivate",e,c)===!1||(i.active=r?!1:this.tabs.index(o),this.active=a?t():o,this.xhr&&this.xhr.abort(),l.length||h.length||t.error("jQuery UI Tabs: Mismatching fragment identifier."),h.length&&this.load(this.tabs.index(o),e),this._toggle(e,c))},_toggle:function(e,i){function s(){o.running=!1,o._trigger("activate",e,i)}function n(){o._addClass(i.newTab.closest("li"),"ui-tabs-active","ui-state-active"),a.length&&o.options.show?o._show(a,o.options.show,s):(a.show(),s())}var o=this,a=i.newPanel,r=i.oldPanel;this.running=!0,r.length&&this.options.hide?this._hide(r,this.options.hide,function(){o._removeClass(i.oldTab.closest("li"),"ui-tabs-active","ui-state-active"),n()}):(this._removeClass(i.oldTab.closest("li"),"ui-tabs-active","ui-state-active"),r.hide(),n()),r.attr("aria-hidden","true"),i.oldTab.attr({"aria-selected":"false","aria-expanded":"false"}),a.length&&r.length?i.oldTab.attr("tabIndex",-1):a.length&&this.tabs.filter(function(){return 0===t(this).attr("tabIndex")}).attr("tabIndex",-1),a.attr("aria-hidden","false"),i.newTab.attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0})},_activate:function(e){var i,s=this._findActive(e);s[0]!==this.active[0]&&(s.length||(s=this.active),i=s.find(".ui-tabs-anchor")[0],this._eventHandler({target:i,currentTarget:i,preventDefault:t.noop}))},_findActive:function(e){return e===!1?t():this.tabs.eq(e)},_getIndex:function(e){return"string"==typeof e&&(e=this.anchors.index(this.anchors.filter("[href$='"+t.ui.escapeSelector(e)+"']"))),e},_destroy:function(){this.xhr&&this.xhr.abort(),this.tablist.removeAttr("role").off(this.eventNamespace),this.anchors.removeAttr("role tabIndex").removeUniqueId(),this.tabs.add(this.panels).each(function(){t.data(this,"ui-tabs-destroy")?t(this).remove():t(this).removeAttr("role tabIndex aria-live aria-busy aria-selected aria-labelledby aria-hidden aria-expanded")}),this.tabs.each(function(){var e=t(this),i=e.data("ui-tabs-aria-controls");i?e.attr("aria-controls",i).removeData("ui-tabs-aria-controls"):e.removeAttr("aria-controls")}),this.panels.show(),"content"!==this.options.heightStyle&&this.panels.css("height","")},enable:function(e){var i=this.options.disabled;i!==!1&&(void 0===e?i=!1:(e=this._getIndex(e),i=t.isArray(i)?t.map(i,function(t){return t!==e?t:null}):t.map(this.tabs,function(t,i){return i!==e?i:null})),this._setOptionDisabled(i))},disable:function(e){var i=this.options.disabled;if(i!==!0){if(void 0===e)i=!0;else{if(e=this._getIndex(e),-1!==t.inArray(e,i))return;i=t.isArray(i)?t.merge([e],i).sort():[e]}this._setOptionDisabled(i)}},load:function(e,i){e=this._getIndex(e);var s=this,n=this.tabs.eq(e),o=n.find(".ui-tabs-anchor"),a=this._getPanelForTab(n),r={tab:n,panel:a},h=function(t,e){"abort"===e&&s.panels.stop(!1,!0),s._removeClass(n,"ui-tabs-loading"),a.removeAttr("aria-busy"),t===s.xhr&&delete s.xhr};this._isLocal(o[0])||(this.xhr=t.ajax(this._ajaxSettings(o,i,r)),this.xhr&&"canceled"!==this.xhr.statusText&&(this._addClass(n,"ui-tabs-loading"),a.attr("aria-busy","true"),this.xhr.done(function(t,e,n){setTimeout(function(){a.html(t),s._trigger("load",i,r),h(n,e)},1)}).fail(function(t,e){setTimeout(function(){h(t,e)},1)})))},_ajaxSettings:function(e,i,s){var n=this;return{url:e.attr("href").replace(/#.*$/,""),beforeSend:function(e,o){return n._trigger("beforeLoad",i,t.extend({jqXHR:e,ajaxSettings:o},s))}}},_getPanelForTab:function(e){var i=t(e).attr("aria-controls");return this.element.find(this._sanitizeSelector("#"+i))}}),t.uiBackCompat!==!1&&t.widget("ui.tabs",t.ui.tabs,{_processTabs:function(){this._superApply(arguments),this._addClass(this.tabs,"ui-tab")}}),t.ui.tabs,t.widget("ui.tooltip",{version:"1.12.1",options:{classes:{"ui-tooltip":"ui-corner-all ui-widget-shadow"},content:function(){var e=t(this).attr("title")||"";return t("<a>").text(e).html()},hide:!0,items:"[title]:not([disabled])",position:{my:"left top+15",at:"left bottom",collision:"flipfit flip"},show:!0,track:!1,close:null,open:null},_addDescribedBy:function(e,i){var s=(e.attr("aria-describedby")||"").split(/\s+/);s.push(i),e.data("ui-tooltip-id",i).attr("aria-describedby",t.trim(s.join(" ")))},_removeDescribedBy:function(e){var i=e.data("ui-tooltip-id"),s=(e.attr("aria-describedby")||"").split(/\s+/),n=t.inArray(i,s);-1!==n&&s.splice(n,1),e.removeData("ui-tooltip-id"),s=t.trim(s.join(" ")),s?e.attr("aria-describedby",s):e.removeAttr("aria-describedby")},_create:function(){this._on({mouseover:"open",focusin:"open"}),this.tooltips={},this.parents={},this.liveRegion=t("<div>").attr({role:"log","aria-live":"assertive","aria-relevant":"additions"}).appendTo(this.document[0].body),this._addClass(this.liveRegion,null,"ui-helper-hidden-accessible"),this.disabledTitles=t([])},_setOption:function(e,i){var s=this;this._super(e,i),"content"===e&&t.each(this.tooltips,function(t,e){s._updateContent(e.element)})},_setOptionDisabled:function(t){this[t?"_disable":"_enable"]()},_disable:function(){var e=this;t.each(this.tooltips,function(i,s){var n=t.Event("blur");n.target=n.currentTarget=s.element[0],e.close(n,!0)}),this.disabledTitles=this.disabledTitles.add(this.element.find(this.options.items).addBack().filter(function(){var e=t(this);return e.is("[title]")?e.data("ui-tooltip-title",e.attr("title")).removeAttr("title"):void 0}))},_enable:function(){this.disabledTitles.each(function(){var e=t(this);e.data("ui-tooltip-title")&&e.attr("title",e.data("ui-tooltip-title"))}),this.disabledTitles=t([])},open:function(e){var i=this,s=t(e?e.target:this.element).closest(this.options.items);s.length&&!s.data("ui-tooltip-id")&&(s.attr("title")&&s.data("ui-tooltip-title",s.attr("title")),s.data("ui-tooltip-open",!0),e&&"mouseover"===e.type&&s.parents().each(function(){var e,s=t(this);s.data("ui-tooltip-open")&&(e=t.Event("blur"),e.target=e.currentTarget=this,i.close(e,!0)),s.attr("title")&&(s.uniqueId(),i.parents[this.id]={element:this,title:s.attr("title")},s.attr("title",""))}),this._registerCloseHandlers(e,s),this._updateContent(s,e))},_updateContent:function(t,e){var i,s=this.options.content,n=this,o=e?e.type:null;return"string"==typeof s||s.nodeType||s.jquery?this._open(e,t,s):(i=s.call(t[0],function(i){n._delay(function(){t.data("ui-tooltip-open")&&(e&&(e.type=o),this._open(e,t,i))})}),i&&this._open(e,t,i),void 0)},_open:function(e,i,s){function n(t){l.of=t,a.is(":hidden")||a.position(l)}var o,a,r,h,l=t.extend({},this.options.position);if(s){if(o=this._find(i))return o.tooltip.find(".ui-tooltip-content").html(s),void 0;i.is("[title]")&&(e&&"mouseover"===e.type?i.attr("title",""):i.removeAttr("title")),o=this._tooltip(i),a=o.tooltip,this._addDescribedBy(i,a.attr("id")),a.find(".ui-tooltip-content").html(s),this.liveRegion.children().hide(),h=t("<div>").html(a.find(".ui-tooltip-content").html()),h.removeAttr("name").find("[name]").removeAttr("name"),h.removeAttr("id").find("[id]").removeAttr("id"),h.appendTo(this.liveRegion),this.options.track&&e&&/^mouse/.test(e.type)?(this._on(this.document,{mousemove:n}),n(e)):a.position(t.extend({of:i},this.options.position)),a.hide(),this._show(a,this.options.show),this.options.track&&this.options.show&&this.options.show.delay&&(r=this.delayedShow=setInterval(function(){a.is(":visible")&&(n(l.of),clearInterval(r))},t.fx.interval)),this._trigger("open",e,{tooltip:a})}},_registerCloseHandlers:function(e,i){var s={keyup:function(e){if(e.keyCode===t.ui.keyCode.ESCAPE){var s=t.Event(e);s.currentTarget=i[0],this.close(s,!0)}}};i[0]!==this.element[0]&&(s.remove=function(){this._removeTooltip(this._find(i).tooltip)}),e&&"mouseover"!==e.type||(s.mouseleave="close"),e&&"focusin"!==e.type||(s.focusout="close"),this._on(!0,i,s)},close:function(e){var i,s=this,n=t(e?e.currentTarget:this.element),o=this._find(n);return o?(i=o.tooltip,o.closing||(clearInterval(this.delayedShow),n.data("ui-tooltip-title")&&!n.attr("title")&&n.attr("title",n.data("ui-tooltip-title")),this._removeDescribedBy(n),o.hiding=!0,i.stop(!0),this._hide(i,this.options.hide,function(){s._removeTooltip(t(this))}),n.removeData("ui-tooltip-open"),this._off(n,"mouseleave focusout keyup"),n[0]!==this.element[0]&&this._off(n,"remove"),this._off(this.document,"mousemove"),e&&"mouseleave"===e.type&&t.each(this.parents,function(e,i){t(i.element).attr("title",i.title),delete s.parents[e]}),o.closing=!0,this._trigger("close",e,{tooltip:i}),o.hiding||(o.closing=!1)),void 0):(n.removeData("ui-tooltip-open"),void 0)},_tooltip:function(e){var i=t("<div>").attr("role","tooltip"),s=t("<div>").appendTo(i),n=i.uniqueId().attr("id");return this._addClass(s,"ui-tooltip-content"),this._addClass(i,"ui-tooltip","ui-widget ui-widget-content"),i.appendTo(this._appendTo(e)),this.tooltips[n]={element:e,tooltip:i}},_find:function(t){var e=t.data("ui-tooltip-id");return e?this.tooltips[e]:null},_removeTooltip:function(t){t.remove(),delete this.tooltips[t.attr("id")]},_appendTo:function(t){var e=t.closest(".ui-front, dialog");return e.length||(e=this.document[0].body),e},_destroy:function(){var e=this;t.each(this.tooltips,function(i,s){var n=t.Event("blur"),o=s.element;n.target=n.currentTarget=o[0],e.close(n,!0),t("#"+i).remove(),o.data("ui-tooltip-title")&&(o.attr("title")||o.attr("title",o.data("ui-tooltip-title")),o.removeData("ui-tooltip-title"))}),this.liveRegion.remove()}}),t.uiBackCompat!==!1&&t.widget("ui.tooltip",t.ui.tooltip,{options:{tooltipClass:null},_tooltip:function(){var t=this._superApply(arguments);return this.options.tooltipClass&&t.tooltip.addClass(this.options.tooltipClass),t}}),t.ui.tooltip}); \ No newline at end of file diff --git a/website/agenda/planung/js/jquery.autocomplete.css b/website/agenda/planung/js/jquery.autocomplete.css deleted file mode 100644 index b5a56bd..0000000 --- a/website/agenda/planung/js/jquery.autocomplete.css +++ /dev/null @@ -1,48 +0,0 @@ -.ac_results { - padding: 0px; - border: 1px solid WindowFrame; - background-color: Window; - overflow: hidden; - z-index:-10; -} - -.ac_results ul { - width: 100%; - list-style-position: outside; - list-style: none; - padding: 0; - margin: 0; - z-index:-10; -} - -.ac_results iframe { - display:none;/*sorry for IE5*/ - display/**/:block;/*sorry for IE5*/ - position:absolute; - top:0; - left:0; - z-index:-10; - filter:mask(); - width:3000px; - height:3000px; -} - -.ac_results li { - margin: 0px; - padding: 2px 5px; - cursor: pointer; - display: block; - width: 100%; - font: menu; - font-size: 12px; - overflow: hidden; -} - -.ac_loading { - background : Window url('./indicator.gif') right center no-repeat; -} - -.ac_over { - background-color: Highlight; - color: HighlightText; -} diff --git a/website/agenda/planung/js/jquery.autocomplete.js b/website/agenda/planung/js/jquery.autocomplete.js deleted file mode 100644 index 49a2d34..0000000 --- a/website/agenda/planung/js/jquery.autocomplete.js +++ /dev/null @@ -1,789 +0,0 @@ -jQuery.autocomplete = function(input, options) { - // Create a link to self - var me = this; - - // Version - var version = 1.6; - - // Create jQuery object for input element - var $input = $(input).attr('autocomplete', 'off'); - - // Create jQuery object as a unique request ID - var $requestId = 1; - - // Maximum request ID (it's kind of silly to have this, but whatever. - var $MAX_REQUEST_ID = 65000; - - // Apply inputClass if necessary - if (options.inputClass) { - $input.addClass(options.inputClass); - } - - /* - * Create results (DOM element) - */ - var results = document.createElement('div'); - - /* - * Create jQuery object for results - * - * var $results = $(results); - */ - var $results = $(results).hide().addClass(options.resultsClass).css('position', 'absolute'); - - if (options.width > 0) { - $results.css('width', options.width); - } - - // Add to body element - $('body').append(results); - - input.autocompleter = me; - - var timeout = null; - var prev = ''; - var active = -1; - var cache = {}; - var keyb = false; - var hasFocus = false; - var lastKeyPressCode = null; - var mouseDownOnSelect = false; - var hidingResults = false; - - // flush cache - function flushCache(){ - cache = {}; - cache.data = {}; - cache.length = 0; - }; - - // flush cache - flushCache(); - - // if there is a data array supplied - if (options.data != null) { - var sFirstChar = '', stMatchSets = {}, row = []; - - // no url was specified, we need to adjust the cache length to make sure it fits the local data store - if( typeof options.url != 'string' ) { - options.cacheLength = 1; - } - - // loop through the array and create a lookup structure - for (var i=0; i < options.data.length; i++) { - // if row is a string, make an array otherwise just reference the array - row = ((typeof options.data[i] == 'string') ? [options.data[i]] : options.data[i]); - - // if the length is zero, don't add to list - if( row[0].length > 0 ){ - // get the first character - sFirstChar = row[0].substring(0, 1).toLowerCase(); - // if no lookup array for this character exists, look it up now - if( !stMatchSets[sFirstChar] ) stMatchSets[sFirstChar] = []; - // if the match is a string - stMatchSets[sFirstChar].push(row); - } - } - - // add the data items to the cache - for( var k in stMatchSets ) { - // increase the cache size - options.cacheLength++; - // add to the cache - addToCache(k, stMatchSets[k]); - } - } - - $input - .keydown(function(e) { - // track last key pressed - lastKeyPressCode = e.keyCode; - switch(e.keyCode) { - case 38: // up - e.preventDefault(); - moveSelect(-1); - break; - case 40: // down - e.preventDefault(); - moveSelect(1); - break; - case 9: // tab - case 13: // return - if( selectCurrent() ){ - // make sure to blur off the current field - $input.get(0).blur(); - e.preventDefault(); - } - break; - case 16: - case 17: - case 18: - // shift, control, and alt keys... ignore! - break; - default: - active = -1; - if (timeout) clearTimeout(timeout); - timeout = setTimeout(function(){onChange();}, options.delay); - break; - } - }) - .focus(function(){ - // track whether the field has focus, we shouldn't process any results if the field no longer has focus - hasFocus = true; - }) - .blur(function() { - // track whether the field has focus - hasFocus = false; - if (!mouseDownOnSelect) { - hideResults(); - } - }); - - hideResultsNow(); - - if (options.focus) { - $input.focus(); - } - - function onChange() { - // ignore if the following keys are pressed: [del] [shift] [capslock] - if ((lastKeyPressCode == 46) || ((lastKeyPressCode > 8) && (lastKeyPressCode < 32))) { - doResultsHide(); - } - - var v = $input.val(); - - if (v == prev) return; - - prev = v; - - if (v.length >= options.minChars) { - $input.addClass(options.loadingClass); - requestData(v); - } - else { - $input.removeClass(options.loadingClass); - - doResultsHide(); - } - }; - - function moveSelect(step) { - - var lis = $('li', results); - if (!lis) return; - - active += step; - - if (active < 0) { - active = 0; - } - else if (active >= lis.size()) { - active = lis.size() - 1; - } - - lis.removeClass('ac_over'); - - $(lis[active]).addClass('ac_over'); - - // Weird behaviour in IE - // if (lis[active] && lis[active].scrollIntoView) { - // lis[active].scrollIntoView(false); - // } - - }; - - function selectCurrent() { - var li = $('li.ac_over', results)[0]; - - if (!li) { - var $li = $('li', results); - - if (options.selectOnly) { - if ($li.length == 1) li = $li[0]; - } - else if (options.selectFirst) { - li = $li[0]; - } - } - - if (li) { - selectItem(li); - return true; - } - else { - return false; - } - }; - - function selectItem(li) { - if (!li) { - li = document.createElement('li'); - li.extra = []; - li.selectValue = ''; - } - - var v = $.trim(li.selectValue ? li.selectValue : li.innerHTML); - - input.lastSelected = v; - prev = v; - $results.html(''); - $input.val(v); - - hideResultsNow(); - - if (options.onItemSelect) { - setTimeout(function() { - options.onItemSelect(li) - }, 1); - } - }; - - // selects a portion of the input string - function createSelection(start, end){ - /* - * get a reference to the input element - */ - var field = $input.get(0); - - if (field.createTextRange) { - var selRange = field.createTextRange(); - selRange.collapse(true); - selRange.moveStart('character', start); - selRange.moveEnd('character', end); - selRange.select(); - } - else if (field.setSelectionRange) { - field.setSelectionRange(start, end); - } - else { - if (field.selectionStart) { - field.selectionStart = start; - field.selectionEnd = end; - } - } - - field.focus(); - }; - - // fills in the input box w/the first match (assumed to be the best match) - function autoFill(sValue) { - /* - * if the last user key pressed was backspace, don't autofill - */ - if (lastKeyPressCode != 8) { - /* - * fill in the value (keep the case the user has typed) - */ - $input.val($input.val() + sValue.substring(prev.length)); - /* - * select the portion of the value not typed by the user (so the next character will erase) - */ - createSelection(prev.length, sValue.length); - } - }; - - function showResults() { - /* - * get the position of the input field right now (in case the DOM is shifted) - */ - var pos = findPos(options.popupParent || $input); - - /* - * either use the specified width, or autocalculate based on form element - */ - var iWidth; - - if (options.width > 0) { - iWidth = options.width; - } - else { - if (options.popupParent) { - iWidth = options.popupParent.innerWidth(); - } - else { - iWidth = $input.innerWidth(); - } - } - - var height; - - if (options.popupParent) { - /* - * for an arbitrary parent, we use inner height... it seems to work better (tighter to parent) - */ - height = options.popupParent.innerHeight(); - } - else { - /* - * Otherwise for input fields, use outer height. - */ - height = $input.outerHeight(); - } - - /* - * re-position - */ - $results.css({ - width: parseInt(iWidth) + 'px', - top: (pos.y + height) + 'px', - left: pos.x + 'px', - 'z-index': pos.zIndex - }); - - doResultsShow(); - }; - - function hideResults() { - if (timeout) clearTimeout(timeout); - timeout = setTimeout(hideResultsNow, 200); - }; - - function hideResultsNow() { - if (hidingResults) { - return; - } - hidingResults = true; - - if (timeout) { - clearTimeout(timeout); - } - - var v = $input.removeClass(options.loadingClass).val(); - - if ($results.is(':visible')) { - doResultsHide(); - } - - if (options.mustMatch) { - if (!input.lastSelected || input.lastSelected != v) { - selectItem(null); - } - } - - hidingResults = false; - }; - - function doResultsShow() { - if (options.resultsId) { - $results.attr('id', options.resultsId); - } - - $results.show(); - - if (typeof options.onResultsShow === 'function') { - options.onResultsShow($results[0]); - } - }; - - function doResultsHide() { - $results.hide(); - - if (typeof options.onResultsHide === 'function') { - options.onResultsHide($results[0]); - } - - if (options.resultsId) { - $results.removeAttr('id'); - } - }; - - function receiveData(q, data) { - if (data) { - $input.removeClass(options.loadingClass); - results.innerHTML = ''; - - /* - * if the field no longer has focus or if there are no matches, do not display the drop down - */ - if (!hasFocus || (data.length == 0)) { - return hideResultsNow(); - } - - if ($.browser.msie) { - /* - * we put a styled iframe behind the calendar so HTML SELECT elements don't show through - */ - $results.append(document.createElement('iframe')); - } - results.appendChild(dataToDom(data)); - - if (options.autoFill && ($input.val().toLowerCase() == q.toLowerCase()) ) { - /* - * autofill in the complete box w/the first match - * as long as the user hasn't entered in more data - */ - autoFill(data[0][0]); - } - else if (options.selectFirst) { - /* - * If the 'selectFirst' option was specified, then hilite the first element in the list. - */ - $('li:first', results).addClass('ac_over'); - } - - showResults(); - } - else { - hideResultsNow(); - } - }; - - function parseData(data) { - if (!data) return null; - var parsed = []; - var rows = data.split(options.lineSeparator); - for (var i=0; i < rows.length; i++) { - var row = $.trim(rows[i]); - if (row) { - parsed[parsed.length] = row.split(options.cellSeparator); - } - } - return parsed; - }; - - /** - * Create a new pop-up list element. - * - * @param data the data to use when constructing the element. - * - * @return a 'ul' dom element. - */ - function dataToDom(data) { - var ul = document.createElement('ul'); - var num = data.length; - - // limited results to a max number - if( (options.maxItemsToShow > 0) && (options.maxItemsToShow < num) ) num = options.maxItemsToShow; - - for (var i=0; i < num; i++) { - var row = data[i]; - if (!row) continue; - - var li = document.createElement('li'); - - if (options.formatItem) { - li.innerHTML = options.formatItem(row, i, num); - li.selectValue = row[0]; - } - else { - li.innerHTML = row[0]; - li.selectValue = row[0]; - } - - var extra = null; - - if (row.length > 1) { - extra = []; - for (var j=1; j < row.length; j++) { - extra[extra.length] = row[j]; - } - } - li.extra = extra; - ul.appendChild(li); - - $(li).hover( - function() { $('li', ul).removeClass('ac_over'); $(this).addClass('ac_over'); active = $('li', ul).indexOf($(this).get(0)); }, - function() { $(this).removeClass('ac_over'); } - ).click(function(e) { - e.preventDefault(); - e.stopPropagation(); - selectItem(this) - }); - - } - $(ul).mousedown(function() { - mouseDownOnSelect = true; - }).mouseup(function() { - mouseDownOnSelect = false; - }); - return ul; - }; - - /* - * Perform an ajax request for the specified query string - */ - function requestData(q) { - if (!options.matchCase) { - q = q.toLowerCase(); - } - - var data = options.cacheLength ? loadFromCache(q) : null; - - if (data) { - /* - * receive the cached data - */ - receiveData(q, data); - } - else if ((typeof options.url == 'string') && (options.url.length > 0)) { - /* - * if an AJAX url has been supplied, try loading the data now - * - * Increment the unique request ID, to ensure that we're only using the most recent request - */ - $requestId += 1; - if ($requestId >= $MAX_REQUEST_ID) { - $requestId = 0; // roll over - } - // Perform the request. - var thisRequestId = $requestId; - $.get(makeUrl(q), function(data) { - handleReceivedData(q, data, thisRequestId); - }); - } - else { - /* - * if there's been no data found, remove the loading class - */ - $input.removeClass(options.loadingClass); - } - }; - - function handleReceivedData(q, data, thisRequestId) { - data = parseData(data); - addToCache(q, data); - - if (thisRequestId == $requestId) { - /* - * If this is the most recent request, then put it into the list. - */ - receiveData(q, data); - } - }; - - function makeUrl(q) { - var sep = options.url.indexOf('?') == -1 ? '?' : '&'; - var url = options.url + sep + options.queryParam + '=' + encodeURI(q); - - for (var i in options.extraParams) { - url += '&' + i + '=' + encodeURI(options.extraParams[i]); - } - - return url; - }; - - function loadFromCache(q) { - if (!q) { - return null; - } - - if (cache.data[q]) { - return cache.data[q]; - } - - if (options.matchSubset) { - for (var i = q.length - 1; i >= options.minChars; i--) { - var qs = q.substr(0, i); - var c = cache.data[qs]; - if (c) { - var csub = []; - for (var j = 0; j < c.length; j++) { - var x = c[j]; - var x0 = x[0]; - if (matchSubset(x0, q)) { - csub[csub.length] = x; - } - } - return csub; - } - } - } - return null; - }; - - function matchSubset(s, sub) { - if (!options.matchCase) { - s = s.toLowerCase(); - } - - var i = s.indexOf(sub); - - if (i == -1) { - return false; - } - - return i == 0 || options.matchContains; - }; - - this.flushCache = function() { - flushCache(); - }; - - this.setExtraParams = function(p) { - options.extraParams = p; - }; - - this.findValue = function(){ - var q = $input.val(); - - if (!options.matchCase) { - q = q.toLowerCase(); - } - - var data = options.cacheLength ? loadFromCache(q) : null; - - if (data) { - findValueCallback(q, data); - } - else if ((typeof options.url == 'string') && (options.url.length > 0)) { - $.get(makeUrl(q), function(data) { - data = parseData(data) - addToCache(q, data); - findValueCallback(q, data); - }); - } - else { - // no matches - findValueCallback(q, null); - } - } - - function findValueCallback(q, data){ - if (data) { - $input.removeClass(options.loadingClass); - } - - var num = (data) ? data.length : 0; - var li = null; - - for (var i=0; i < num; i++) { - var row = data[i]; - - if (row[0].toLowerCase() == q.toLowerCase()) { - li = document.createElement('li'); - - if (options.formatItem) { - li.innerHTML = options.formatItem(row, i, num); - li.selectValue = row[0]; - } - else { - li.innerHTML = row[0]; - li.selectValue = row[0]; - } - - var extra = null; - - if (row.length > 1) { - extra = []; - - for (var j=1; j < row.length; j++) { - extra[extra.length] = row[j]; - } - } - li.extra = extra; - } - } - - if (options.onFindValue) { - setTimeout(function() { options.onFindValue(li) }, 1); - } - } - - function addToCache(q, data) { - if (!data || !q || !options.cacheLength) { - return; - } - - if (!cache.length || cache.length > options.cacheLength) { - flushCache(); - cache.length++; - } - else if (!cache[q]) { - cache.length++; - } - cache.data[q] = data; - }; - - function findPos(popupParent) { - var offset = popupParent.offset(); - var maxZIndex = 0; - var zIndexParent = popupParent; - - while (zIndexParent.length && !zIndexParent.is('body')) { - var thisZIndex = zIndexParent.css('z-index'); - - thisZIndex = parseInt(thisZIndex); - - if (thisZIndex || !isNaN(thisZIndex)) { - maxZIndex = Math.max(thisZIndex, maxZIndex); - } - - zIndexParent = zIndexParent.offsetParent(); - } - - return { - x: Math.ceil(offset.left), - y: Math.ceil(offset.top), - zIndex: maxZIndex + 10 - }; - } -} - -jQuery.fn.autocomplete = function(url, options, data) { - // Make sure options exists - options = options || {}; - // Set url as option - options.url = url; - // set some bulk local data - options.data = ((typeof data == 'object') && (data.constructor == Array)) ? data : null; - - // Set default values for required options - options = $.extend({ - autoFill: false, - cacheLength: 1, - cellSeparator: '|', - delay: 400, - extraParams: {}, - focus: false, - inputClass: 'ac_input', - lineSeparator: '\n', - loadingClass: 'ac_loading', - matchCase: 0, - matchSubset: 1, - matchContains: 0, - maxItemsToShow: -1, - minChars: 1, - mustMatch: 0, - onResultsShow: null, - onResultsHide: null, - popupParent: null, - queryParam: 'q', - resultsClass: 'ac_results', - resultsId: null, - selectFirst: false, - selectOnly: false, - width: 0 - }, options); - options.width = parseInt(options.width, 10); - - if (options.popupParent) { - options.popupParent = $(options.popupParent); - - if (options.popupParent.length == 0) { - options.popupParent = null; - } - } - - this.each(function() { - var input = this; - new jQuery.autocomplete(input, options); - }); - - // Don't break the chain - return this; -} - -jQuery.fn.autocompleteArray = function(data, options) { - return this.autocomplete(null, options, data); -} - -jQuery.fn.indexOf = function(e){ - for (var i = 0; i < this.length; i++) { - if (this[i] == e) { - return i; - } - } - - return -1; -}; diff --git a/website/agenda/planung/js/jquery.autocomplete.min.js b/website/agenda/planung/js/jquery.autocomplete.min.js deleted file mode 100644 index 4431349..0000000 --- a/website/agenda/planung/js/jquery.autocomplete.min.js +++ /dev/null @@ -1,14 +0,0 @@ -jQuery.autocomplete=function(j,b){function p(){i={};i.data={};i.length=0}function N(){if(s==46||s>8&&s<32)z();var a=f.val();if(a!=t){t=a;if(a.length>=b.minChars){f.addClass(b.loadingClass);O(a)}else{f.removeClass(b.loadingClass);z()}}}function G(a){var c=$("li",m);if(c){n+=a;if(n<0)n=0;else if(n>=c.size())n=c.size()-1;c.removeClass("ac_over");$(c[n]).addClass("ac_over")}}function P(){var a=$("li.ac_over",m)[0];if(!a){var c=$("li",m);if(b.selectOnly){if(c.length==1)a=c[0]}else if(b.selectFirst)a=c[0]}if(a){A(a); -return true}else return false}function A(a){if(!a){a=document.createElement("li");a.extra=[];a.selectValue=""}var c=$.trim(a.selectValue?a.selectValue:a.innerHTML);t=j.lastSelected=c;k.html("");f.val(c);u();b.onItemSelect&&setTimeout(function(){b.onItemSelect(a)},1)}function Q(a,c){var d=f.get(0);if(d.createTextRange){var e=d.createTextRange();e.collapse(true);e.moveStart("character",a);e.moveEnd("character",c);e.select()}else if(d.setSelectionRange)d.setSelectionRange(a,c);else if(d.selectionStart){d.selectionStart= -a;d.selectionEnd=c}d.focus()}function R(a){if(s!=8){f.val(f.val()+a.substring(t.length));Q(t.length,a.length)}}function S(){var a=T(b.popupParent||f),c;c=b.width>0?b.width:b.popupParent?b.popupParent.innerWidth():f.innerWidth();var d;d=b.popupParent?b.popupParent.innerHeight():f.outerHeight();k.css({width:parseInt(c)+"px",top:a.y+d+"px",left:a.x+"px","z-index":a.zIndex});U()}function V(){o&&clearTimeout(o);o=setTimeout(u,200)}function u(){if(!B){B=true;o&&clearTimeout(o);var a=f.removeClass(b.loadingClass).val(); -k.is(":visible")&&z();if(b.mustMatch)if(!j.lastSelected||j.lastSelected!=a)A(null);B=false}}function U(){b.resultsId&&k.attr("id",b.resultsId);k.show();typeof b.onResultsShow==="function"&&b.onResultsShow(k[0])}function z(){k.hide();typeof b.onResultsHide==="function"&&b.onResultsHide(k[0]);b.resultsId&&k.removeAttr("id")}function H(a,c){if(c){f.removeClass(b.loadingClass);m.innerHTML="";if(!C||c.length==0)return u();$.browser.msie&&k.append(document.createElement("iframe"));m.appendChild(W(c));if(b.autoFill&& -f.val().toLowerCase()==a.toLowerCase())R(c[0][0]);else b.selectFirst&&$("li:first",m).addClass("ac_over");S()}else u()}function I(a){if(!a)return null;var c=[];a=a.split(b.lineSeparator);for(var d=0;d<a.length;d++){var e=$.trim(a[d]);if(e)c[c.length]=e.split(b.cellSeparator)}return c}function W(a){var c=document.createElement("ul"),d=a.length;if(b.maxItemsToShow>0&&b.maxItemsToShow<d)d=b.maxItemsToShow;for(var e=0;e<d;e++){var g=a[e];if(g){var h=document.createElement("li");h.innerHTML=b.formatItem? -b.formatItem(g,e,d):g[0];h.selectValue=g[0];var l=null;if(g.length>1){l=[];for(var q=1;q<g.length;q++)l[l.length]=g[q]}h.extra=l;c.appendChild(h);$(h).hover(function(){$("li",c).removeClass("ac_over");$(this).addClass("ac_over");n=$("li",c).indexOf($(this).get(0))},function(){$(this).removeClass("ac_over")}).click(function(J){J.preventDefault();J.stopPropagation();A(this)})}}$(c).mousedown(function(){D=true}).mouseup(function(){D=false});return c}function O(a){b.matchCase||(a=a.toLowerCase());var c= -b.cacheLength?K(a):null;if(c)H(a,c);else if(typeof b.url=="string"&&b.url.length>0){v+=1;if(v>=X)v=0;var d=v;$.get(L(a),function(e){Y(a,e,d)})}else f.removeClass(b.loadingClass)}function Y(a,c,d){c=I(c);E(a,c);d==v&&H(a,c)}function L(a){var c=b.url.indexOf("?")==-1?"?":"&";a=b.url+c+b.queryParam+"="+encodeURI(a);for(var d in b.extraParams)a+="&"+d+"="+encodeURI(b.extraParams[d]);return a}function K(a){if(!a)return null;if(i.data[a])return i.data[a];if(b.matchSubset)for(var c=a.length-1;c>=b.minChars;c--){var d= -a.substr(0,c);if(d=i.data[d]){c=[];for(var e=0;e<d.length;e++){var g=d[e];if(Z(g[0],a))c[c.length]=g}return c}}return null}function Z(a,c){b.matchCase||(a=a.toLowerCase());a=a.indexOf(c);if(a==-1)return false;return a==0||b.matchContains}function F(a,c){c&&f.removeClass(b.loadingClass);for(var d=c?c.length:0,e=null,g=0;g<d;g++){var h=c[g];if(h[0].toLowerCase()==a.toLowerCase()){e=document.createElement("li");e.innerHTML=b.formatItem?b.formatItem(h,g,d):h[0];e.selectValue=h[0];var l=null;if(h.length> -1){l=[];for(var q=1;q<h.length;q++)l[l.length]=h[q]}e.extra=l}}b.onFindValue&&setTimeout(function(){b.onFindValue(e)},1)}function E(a,c){if(!(!c||!a||!b.cacheLength)){if(!i.length||i.length>b.cacheLength){p();i.length++}else i[a]||i.length++;i.data[a]=c}}function T(a){var c=a.offset(),d=0;for(a=a;a.length&&!a.is("body");){var e=a.css("z-index");if((e=parseInt(e))||!isNaN(e))d=Math.max(e,d);a=a.offsetParent()}return{x:Math.ceil(c.left),y:Math.ceil(c.top),zIndex:d+10}}var r=this,f=$(j).attr("autocomplete", -"off"),v=1,X=65E3;b.inputClass&&f.addClass(b.inputClass);var m=document.createElement("div"),k=$(m).hide().addClass(b.resultsClass).css("position","absolute");b.width>0&&k.css("width",b.width);$("body").append(m);j.autocompleter=r;var o=null,t="",n=-1,i={},C=false,s=null,D=false,B=false;p();if(b.data!=null){r="";var w={},y=[];if(typeof b.url!="string")b.cacheLength=1;for(var x=0;x<b.data.length;x++){y=typeof b.data[x]=="string"?[b.data[x]]:b.data[x];if(y[0].length>0){r=y[0].substring(0,1).toLowerCase(); -w[r]||(w[r]=[]);w[r].push(y)}}for(var M in w){b.cacheLength++;E(M,w[M])}}f.keydown(function(a){s=a.keyCode;switch(a.keyCode){case 38:a.preventDefault();G(-1);break;case 40:a.preventDefault();G(1);break;case 9:case 13:if(P()){f.get(0).blur();a.preventDefault()}break;case 16:case 17:case 18:break;default:n=-1;o&&clearTimeout(o);o=setTimeout(function(){N()},b.delay);break}}).focus(function(){C=true}).blur(function(){C=false;D||V()});u();b.focus&&f.focus();this.flushCache=function(){p()};this.setExtraParams= -function(a){b.extraParams=a};this.findValue=function(){var a=f.val();b.matchCase||(a=a.toLowerCase());var c=b.cacheLength?K(a):null;if(c)F(a,c);else typeof b.url=="string"&&b.url.length>0?$.get(L(a),function(d){d=I(d);E(a,d);F(a,d)}):F(a,null)}}; -jQuery.fn.autocomplete=function(j,b,p){b=b||{};b.url=j;b.data=typeof p=="object"&&p.constructor==Array?p:null;b=$.extend({autoFill:false,cacheLength:1,cellSeparator:"|",delay:400,extraParams:{},focus:false,inputClass:"ac_input",lineSeparator:"\n",loadingClass:"ac_loading",matchCase:0,matchSubset:1,matchContains:0,maxItemsToShow:-1,minChars:1,mustMatch:0,onResultsShow:null,onResultsHide:null,popupParent:null,queryParam:"q",resultsClass:"ac_results",resultsId:null,selectFirst:false,selectOnly:false, -width:0},b);b.width=parseInt(b.width,10);if(b.popupParent){b.popupParent=$(b.popupParent);if(b.popupParent.length==0)b.popupParent=null}this.each(function(){new jQuery.autocomplete(this,b)});return this};jQuery.fn.autocompleteArray=function(j,b){return this.autocomplete(null,b,j)};jQuery.fn.indexOf=function(j){for(var b=0;b<this.length;b++)if(this[b]==j)return b;return-1}; \ No newline at end of file diff --git a/website/agenda/planung/js/jquery.js b/website/agenda/planung/js/jquery.js deleted file mode 100644 index 0f60b7b..0000000 --- a/website/agenda/planung/js/jquery.js +++ /dev/null @@ -1,5 +0,0 @@ -/*! jQuery v1.11.3 | (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="1.11.3",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b){return b.toUpperCase()};m.fn=m.prototype={jquery:l,constructor:m,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=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.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},m.extend=m.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||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},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=r(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(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[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=r(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&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b="length"in a&&a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=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);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(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&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.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?m.extend(a,d):d}},e={};return d.pipe=d.then,m.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&&m.isFunction(a.promise)?e:0,g=1===f?a:m.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]&&m.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;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1; - -return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.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.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.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 m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?m.queue(this[0],a):void 0===b?this:this.each(function(){var c=m.queue(this,a,b);m._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&m.dequeue(this,a)})},dequeue:function(a){return this.each(function(){m.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=m.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=m._data(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=["Top","Right","Bottom","Left"],U=function(a,b){return a=b||a,"none"===m.css(a,"display")||!m.contains(a.ownerDocument,a)},V=m.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===m.type(c)){e=!0;for(h in c)m.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,m.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(m(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},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav></:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="<textarea>x</textarea>",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="<input type='radio' checked='checked' name='t'/>",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function aa(){return!0}function ba(){return!1}function ca(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!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(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},fix:function(a){if(a[m.expando])return a;var b,c,d,e=a.type,f=a,g=this.fixHooks[e];g||(this.fixHooks[e]=g=Z.test(e)?this.mouseHooks:Y.test(e)?this.keyHooks:{}),d=g.props?this.props.concat(g.props):this.props,a=new m.Event(f),b=d.length;while(b--)c=d[b],a[c]=f[c];return a.target||(a.target=f.srcElement||y),3===a.target.nodeType&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,g.filter?g.filter(a,f):a},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 fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,d,e,f=b.button,g=b.fromElement;return null==a.pageX&&null!=b.clientX&&(d=a.target.ownerDocument||y,e=d.documentElement,c=d.body,a.pageX=b.clientX+(e&&e.scrollLeft||c&&c.scrollLeft||0)-(e&&e.clientLeft||c&&c.clientLeft||0),a.pageY=b.clientY+(e&&e.scrollTop||c&&c.scrollTop||0)-(e&&e.clientTop||c&&c.clientTop||0)),!a.relatedTarget&&g&&(a.relatedTarget=g===a.target?b.toElement:g),a.which||void 0===f||(a.which=1&f?1:2&f?3:4&f?2:0),a}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==ca()&&this.focus)try{return this.focus(),!1}catch(a){}},delegateType:"focusin"},blur:{trigger:function(){return this===ca()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return m.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):void 0},_default:function(a){return m.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=m.extend(new m.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?m.event.trigger(e,null,b):m.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},m.removeEvent=y.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){var d="on"+b;a.detachEvent&&(typeof a[d]===K&&(a[d]=null),a.detachEvent(d,c))},m.Event=function(a,b){return this instanceof m.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?aa:ba):this.type=a,b&&m.extend(this,b),this.timeStamp=a&&a.timeStamp||m.now(),void(this[m.expando]=!0)):new m.Event(a,b)},m.Event.prototype={isDefaultPrevented:ba,isPropagationStopped:ba,isImmediatePropagationStopped:ba,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=aa,a&&(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=aa,a&&(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=aa,a&&a.stopImmediatePropagation&&a.stopImmediatePropagation(),this.stopPropagation()}},m.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){m.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return(!e||e!==d&&!m.contains(d,e))&&(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),k.submitBubbles||(m.event.special.submit={setup:function(){return m.nodeName(this,"form")?!1:void m.event.add(this,"click._submit keypress._submit",function(a){var b=a.target,c=m.nodeName(b,"input")||m.nodeName(b,"button")?b.form:void 0;c&&!m._data(c,"submitBubbles")&&(m.event.add(c,"submit._submit",function(a){a._submit_bubble=!0}),m._data(c,"submitBubbles",!0))})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&m.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){return m.nodeName(this,"form")?!1:void m.event.remove(this,"._submit")}}),k.changeBubbles||(m.event.special.change={setup:function(){return X.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(m.event.add(this,"propertychange._change",function(a){"checked"===a.originalEvent.propertyName&&(this._just_changed=!0)}),m.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1),m.event.simulate("change",this,a,!0)})),!1):void m.event.add(this,"beforeactivate._change",function(a){var b=a.target;X.test(b.nodeName)&&!m._data(b,"changeBubbles")&&(m.event.add(b,"change._change",function(a){!this.parentNode||a.isSimulated||a.isTrigger||m.event.simulate("change",this.parentNode,a,!0)}),m._data(b,"changeBubbles",!0))})},handle:function(a){var b=a.target;return this!==b||a.isSimulated||a.isTrigger||"radio"!==b.type&&"checkbox"!==b.type?a.handleObj.handler.apply(this,arguments):void 0},teardown:function(){return m.event.remove(this,"._change"),!X.test(this.nodeName)}}),k.focusinBubbles||m.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){m.event.simulate(b,a.target,m.event.fix(a),!0)};m.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=m._data(d,b);e||d.addEventListener(a,c,!0),m._data(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=m._data(d,b)-1;e?m._data(d,b,e):(d.removeEventListener(a,c,!0),m._removeData(d,b))}}}),m.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(f in a)this.on(f,b,c,a[f],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=ba;else if(!d)return this;return 1===e&&(g=d,d=function(a){return m().off(a),g.apply(this,arguments)},d.guid=g.guid||(g.guid=m.guid++)),this.each(function(){m.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,m(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=ba),this.each(function(){m.event.remove(this,a,c,b)})},trigger:function(a,b){return this.each(function(){m.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?m.event.trigger(a,b,c,!0):void 0}});function da(a){var b=ea.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}var ea="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",fa=/ jQuery\d+="(?:null|\d+)"/g,ga=new RegExp("<(?:"+ea+")[\\s/>]","i"),ha=/^\s+/,ia=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,ja=/<([\w:]+)/,ka=/<tbody/i,la=/<|&#?\w+;/,ma=/<(?:script|style|link)/i,na=/checked\s*(?:[^=]|=\s*.checked.)/i,oa=/^$|\/(?:java|ecma)script/i,pa=/^true\/(.*)/,qa=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,ra={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:k.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},sa=da(y),ta=sa.appendChild(y.createElement("div"));ra.optgroup=ra.option,ra.tbody=ra.tfoot=ra.colgroup=ra.caption=ra.thead,ra.th=ra.td;function ua(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ua(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function va(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wa(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xa(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function ya(a){var b=pa.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function za(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Aa(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Ba(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xa(b).text=a.text,ya(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!ga.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(ta.innerHTML=a.outerHTML,ta.removeChild(f=ta.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ua(f),h=ua(a),g=0;null!=(e=h[g]);++g)d[g]&&Ba(e,d[g]);if(b)if(c)for(h=h||ua(a),d=d||ua(f),g=0;null!=(e=h[g]);g++)Aa(e,d[g]);else Aa(a,f);return d=ua(f,"script"),d.length>0&&za(d,!i&&ua(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=da(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(la.test(f)){h=h||o.appendChild(b.createElement("div")),i=(ja.exec(f)||["",""])[1].toLowerCase(),l=ra[i]||ra._default,h.innerHTML=l[1]+f.replace(ia,"<$1></$2>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&ha.test(f)&&p.push(b.createTextNode(ha.exec(f)[0])),!k.tbody){f="table"!==i||ka.test(f)?"<table>"!==l[1]||ka.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ua(p,"input"),va),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ua(o.appendChild(f),"script"),g&&za(h),c)){e=0;while(f=h[e++])oa.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(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=wa(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=wa(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?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ua(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&za(ua(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ua(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fa,""):void 0;if(!("string"!=typeof a||ma.test(a)||!k.htmlSerialize&&ga.test(a)||!k.leadingWhitespace&&ha.test(a)||ra[(ja.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ia,"<$1></$2>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ua(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,m.cleanData(ua(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,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&na.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ua(i,"script"),xa),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ua(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,ya),j=0;f>j;j++)d=g[j],oa.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qa,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Ca,Da={};function Ea(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fa(a){var b=y,c=Da[a];return c||(c=Ea(a,b),"none"!==c&&c||(Ca=(Ca||m("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=(Ca[0].contentWindow||Ca[0].contentDocument).document,b.write(),b.close(),c=Ea(a,b),Ca.detach()),Da[a]=c),c}!function(){var a;k.shrinkWrapBlocks=function(){if(null!=a)return a;a=!1;var b,c,d;return c=y.getElementsByTagName("body")[0],c&&c.style?(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:1px;width:1px;zoom:1",b.appendChild(y.createElement("div")).style.width="5px",a=3!==b.offsetWidth),c.removeChild(d),a):void 0}}();var Ga=/^margin/,Ha=new RegExp("^("+S+")(?!px)[a-z%]+$","i"),Ia,Ja,Ka=/^(top|right|bottom|left)$/;a.getComputedStyle?(Ia=function(b){return b.ownerDocument.defaultView.opener?b.ownerDocument.defaultView.getComputedStyle(b,null):a.getComputedStyle(b,null)},Ja=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ia(a),g=c?c.getPropertyValue(b)||c[b]:void 0,c&&(""!==g||m.contains(a.ownerDocument,a)||(g=m.style(a,b)),Ha.test(g)&&Ga.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+""}):y.documentElement.currentStyle&&(Ia=function(a){return a.currentStyle},Ja=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ia(a),g=c?c[b]:void 0,null==g&&h&&h[b]&&(g=h[b]),Ha.test(g)&&!Ka.test(b)&&(d=h.left,e=a.runtimeStyle,f=e&&e.left,f&&(e.left=a.currentStyle.left),h.left="fontSize"===b?"1em":g,g=h.pixelLeft+"px",h.left=d,f&&(e.left=f)),void 0===g?g:g+""||"auto"});function La(a,b){return{get:function(){var c=a();if(null!=c)return c?void delete this.get:(this.get=b).apply(this,arguments)}}}!function(){var b,c,d,e,f,g,h;if(b=y.createElement("div"),b.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",d=b.getElementsByTagName("a")[0],c=d&&d.style){c.cssText="float:left;opacity:.5",k.opacity="0.5"===c.opacity,k.cssFloat=!!c.cssFloat,b.style.backgroundClip="content-box",b.cloneNode(!0).style.backgroundClip="",k.clearCloneStyle="content-box"===b.style.backgroundClip,k.boxSizing=""===c.boxSizing||""===c.MozBoxSizing||""===c.WebkitBoxSizing,m.extend(k,{reliableHiddenOffsets:function(){return null==g&&i(),g},boxSizingReliable:function(){return null==f&&i(),f},pixelPosition:function(){return null==e&&i(),e},reliableMarginRight:function(){return null==h&&i(),h}});function i(){var b,c,d,i;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),b.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",e=f=!1,h=!0,a.getComputedStyle&&(e="1%"!==(a.getComputedStyle(b,null)||{}).top,f="4px"===(a.getComputedStyle(b,null)||{width:"4px"}).width,i=b.appendChild(y.createElement("div")),i.style.cssText=b.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",i.style.marginRight=i.style.width="0",b.style.width="1px",h=!parseFloat((a.getComputedStyle(i,null)||{}).marginRight),b.removeChild(i)),b.innerHTML="<table><tr><td></td><td>t</td></tr></table>",i=b.getElementsByTagName("td"),i[0].style.cssText="margin:0;border:0;padding:0;display:none",g=0===i[0].offsetHeight,g&&(i[0].style.display="",i[1].style.display="none",g=0===i[0].offsetHeight),c.removeChild(d))}}}(),m.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 Ma=/alpha\([^)]*\)/i,Na=/opacity\s*=\s*([^)]*)/,Oa=/^(none|table(?!-c[ea]).+)/,Pa=new RegExp("^("+S+")(.*)$","i"),Qa=new RegExp("^([+-])=("+S+")","i"),Ra={position:"absolute",visibility:"hidden",display:"block"},Sa={letterSpacing:"0",fontWeight:"400"},Ta=["Webkit","O","Moz","ms"];function Ua(a,b){if(b in a)return b;var c=b.charAt(0).toUpperCase()+b.slice(1),d=b,e=Ta.length;while(e--)if(b=Ta[e]+c,b in a)return b;return d}function Va(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=m._data(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&U(d)&&(f[g]=m._data(d,"olddisplay",Fa(d.nodeName)))):(e=U(d),(c&&"none"!==c||!e)&&m._data(d,"olddisplay",e?c:m.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}function Wa(a,b,c){var d=Pa.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function Xa(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+=m.css(a,c+T[f],!0,e)),d?("content"===c&&(g-=m.css(a,"padding"+T[f],!0,e)),"margin"!==c&&(g-=m.css(a,"border"+T[f]+"Width",!0,e))):(g+=m.css(a,"padding"+T[f],!0,e),"padding"!==c&&(g+=m.css(a,"border"+T[f]+"Width",!0,e)));return g}function Ya(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=Ia(a),g=k.boxSizing&&"border-box"===m.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=Ja(a,b,f),(0>e||null==e)&&(e=a.style[b]),Ha.test(e))return e;d=g&&(k.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+Xa(a,b,c||(g?"border":"content"),d,f)+"px"}m.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Ja(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":k.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=m.camelCase(b),i=a.style;if(b=m.cssProps[h]||(m.cssProps[h]=Ua(i,h)),g=m.cssHooks[b]||m.cssHooks[h],void 0===c)return g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b];if(f=typeof c,"string"===f&&(e=Qa.exec(c))&&(c=(e[1]+1)*e[2]+parseFloat(m.css(a,b)),f="number"),null!=c&&c===c&&("number"!==f||m.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)))))try{i[b]=c}catch(j){}}},css:function(a,b,c,d){var e,f,g,h=m.camelCase(b);return b=m.cssProps[h]||(m.cssProps[h]=Ua(a.style,h)),g=m.cssHooks[b]||m.cssHooks[h],g&&"get"in g&&(f=g.get(a,!0,c)),void 0===f&&(f=Ja(a,b,d)),"normal"===f&&b in Sa&&(f=Sa[b]),""===c||c?(e=parseFloat(f),c===!0||m.isNumeric(e)?e||0:f):f}}),m.each(["height","width"],function(a,b){m.cssHooks[b]={get:function(a,c,d){return c?Oa.test(m.css(a,"display"))&&0===a.offsetWidth?m.swap(a,Ra,function(){return Ya(a,b,d)}):Ya(a,b,d):void 0},set:function(a,c,d){var e=d&&Ia(a);return Wa(a,c,d?Xa(a,b,d,k.boxSizing&&"border-box"===m.css(a,"boxSizing",!1,e),e):0)}}}),k.opacity||(m.cssHooks.opacity={get:function(a,b){return Na.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=m.isNumeric(b)?"alpha(opacity="+100*b+")":"",f=d&&d.filter||c.filter||"";c.zoom=1,(b>=1||""===b)&&""===m.trim(f.replace(Ma,""))&&c.removeAttribute&&(c.removeAttribute("filter"),""===b||d&&!d.filter)||(c.filter=Ma.test(f)?f.replace(Ma,e):f+" "+e)}}),m.cssHooks.marginRight=La(k.reliableMarginRight,function(a,b){return b?m.swap(a,{display:"inline-block"},Ja,[a,"marginRight"]):void 0}),m.each({margin:"",padding:"",border:"Width"},function(a,b){m.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+T[d]+b]=f[d]||f[d-2]||f[0];return e}},Ga.test(a)||(m.cssHooks[a+b].set=Wa)}),m.fn.extend({css:function(a,b){return V(this,function(a,b,c){var d,e,f={},g=0;if(m.isArray(b)){for(d=Ia(a),e=b.length;e>g;g++)f[b[g]]=m.css(a,b[g],!1,d);return f}return void 0!==c?m.style(a,b,c):m.css(a,b)},a,b,arguments.length>1)},show:function(){return Va(this,!0)},hide:function(){return Va(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){U(this)?m(this).show():m(this).hide()})}});function Za(a,b,c,d,e){ -return new Za.prototype.init(a,b,c,d,e)}m.Tween=Za,Za.prototype={constructor:Za,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||(m.cssNumber[c]?"":"px")},cur:function(){var a=Za.propHooks[this.prop];return a&&a.get?a.get(this):Za.propHooks._default.get(this)},run:function(a){var b,c=Za.propHooks[this.prop];return this.options.duration?this.pos=b=m.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):Za.propHooks._default.set(this),this}},Za.prototype.init.prototype=Za.prototype,Za.propHooks={_default:{get:function(a){var b;return null==a.elem[a.prop]||a.elem.style&&null!=a.elem.style[a.prop]?(b=m.css(a.elem,a.prop,""),b&&"auto"!==b?b:0):a.elem[a.prop]},set:function(a){m.fx.step[a.prop]?m.fx.step[a.prop](a):a.elem.style&&(null!=a.elem.style[m.cssProps[a.prop]]||m.cssHooks[a.prop])?m.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},Za.propHooks.scrollTop=Za.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},m.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},m.fx=Za.prototype.init,m.fx.step={};var $a,_a,ab=/^(?:toggle|show|hide)$/,bb=new RegExp("^(?:([+-])=|)("+S+")([a-z%]*)$","i"),cb=/queueHooks$/,db=[ib],eb={"*":[function(a,b){var c=this.createTween(a,b),d=c.cur(),e=bb.exec(b),f=e&&e[3]||(m.cssNumber[a]?"":"px"),g=(m.cssNumber[a]||"px"!==f&&+d)&&bb.exec(m.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,m.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 fb(){return setTimeout(function(){$a=void 0}),$a=m.now()}function gb(a,b){var c,d={height:a},e=0;for(b=b?1:0;4>e;e+=2-b)c=T[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function hb(a,b,c){for(var d,e=(eb[b]||[]).concat(eb["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function ib(a,b,c){var d,e,f,g,h,i,j,l,n=this,o={},p=a.style,q=a.nodeType&&U(a),r=m._data(a,"fxshow");c.queue||(h=m._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,n.always(function(){n.always(function(){h.unqueued--,m.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[p.overflow,p.overflowX,p.overflowY],j=m.css(a,"display"),l="none"===j?m._data(a,"olddisplay")||Fa(a.nodeName):j,"inline"===l&&"none"===m.css(a,"float")&&(k.inlineBlockNeedsLayout&&"inline"!==Fa(a.nodeName)?p.zoom=1:p.display="inline-block")),c.overflow&&(p.overflow="hidden",k.shrinkWrapBlocks()||n.always(function(){p.overflow=c.overflow[0],p.overflowX=c.overflow[1],p.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],ab.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(q?"hide":"show")){if("show"!==e||!r||void 0===r[d])continue;q=!0}o[d]=r&&r[d]||m.style(a,d)}else j=void 0;if(m.isEmptyObject(o))"inline"===("none"===j?Fa(a.nodeName):j)&&(p.display=j);else{r?"hidden"in r&&(q=r.hidden):r=m._data(a,"fxshow",{}),f&&(r.hidden=!q),q?m(a).show():n.done(function(){m(a).hide()}),n.done(function(){var b;m._removeData(a,"fxshow");for(b in o)m.style(a,b,o[b])});for(d in o)g=hb(q?r[d]:0,d,n),d in r||(r[d]=g.start,q&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function jb(a,b){var c,d,e,f,g;for(c in a)if(d=m.camelCase(c),e=b[d],f=a[c],m.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=m.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 kb(a,b,c){var d,e,f=0,g=db.length,h=m.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=$a||fb(),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:m.extend({},b),opts:m.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:$a||fb(),duration:c.duration,tweens:[],createTween:function(b,c){var d=m.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(jb(k,j.opts.specialEasing);g>f;f++)if(d=db[f].call(j,a,k,j.opts))return d;return m.map(k,hb,j),m.isFunction(j.opts.start)&&j.opts.start.call(a,j),m.fx.timer(m.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)}m.Animation=m.extend(kb,{tweener:function(a,b){m.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");for(var c,d=0,e=a.length;e>d;d++)c=a[d],eb[c]=eb[c]||[],eb[c].unshift(b)},prefilter:function(a,b){b?db.unshift(a):db.push(a)}}),m.speed=function(a,b,c){var d=a&&"object"==typeof a?m.extend({},a):{complete:c||!c&&b||m.isFunction(a)&&a,duration:a,easing:c&&b||b&&!m.isFunction(b)&&b};return d.duration=m.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in m.fx.speeds?m.fx.speeds[d.duration]:m.fx.speeds._default,(null==d.queue||d.queue===!0)&&(d.queue="fx"),d.old=d.complete,d.complete=function(){m.isFunction(d.old)&&d.old.call(this),d.queue&&m.dequeue(this,d.queue)},d},m.fn.extend({fadeTo:function(a,b,c,d){return this.filter(U).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=m.isEmptyObject(a),f=m.speed(b,c,d),g=function(){var b=kb(this,m.extend({},a),f);(e||m._data(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=m.timers,g=m._data(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&cb.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)&&m.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=m._data(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=m.timers,g=d?d.length:0;for(c.finish=!0,m.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})}}),m.each(["toggle","show","hide"],function(a,b){var c=m.fn[b];m.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(gb(b,!0),a,d,e)}}),m.each({slideDown:gb("show"),slideUp:gb("hide"),slideToggle:gb("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){m.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),m.timers=[],m.fx.tick=function(){var a,b=m.timers,c=0;for($a=m.now();c<b.length;c++)a=b[c],a()||b[c]!==a||b.splice(c--,1);b.length||m.fx.stop(),$a=void 0},m.fx.timer=function(a){m.timers.push(a),a()?m.fx.start():m.timers.pop()},m.fx.interval=13,m.fx.start=function(){_a||(_a=setInterval(m.fx.tick,m.fx.interval))},m.fx.stop=function(){clearInterval(_a),_a=null},m.fx.speeds={slow:600,fast:200,_default:400},m.fn.delay=function(a,b){return a=m.fx?m.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,b,c,d,e;b=y.createElement("div"),b.setAttribute("className","t"),b.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",d=b.getElementsByTagName("a")[0],c=y.createElement("select"),e=c.appendChild(y.createElement("option")),a=b.getElementsByTagName("input")[0],d.style.cssText="top:1px",k.getSetAttribute="t"!==b.className,k.style=/top/.test(d.getAttribute("style")),k.hrefNormalized="/a"===d.getAttribute("href"),k.checkOn=!!a.value,k.optSelected=e.selected,k.enctype=!!y.createElement("form").enctype,c.disabled=!0,k.optDisabled=!e.disabled,a=y.createElement("input"),a.setAttribute("value",""),k.input=""===a.getAttribute("value"),a.value="t",a.setAttribute("type","radio"),k.radioValue="t"===a.value}();var lb=/\r/g;m.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=m.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,m(this).val()):a,null==e?e="":"number"==typeof e?e+="":m.isArray(e)&&(e=m.map(e,function(a){return null==a?"":a+""})),b=m.valHooks[this.type]||m.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=m.valHooks[e.type]||m.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(lb,""):null==c?"":c)}}}),m.extend({valHooks:{option:{get:function(a){var b=m.find.attr(a,"value");return null!=b?b:m.trim(m.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&&m.nodeName(c.parentNode,"optgroup"))){if(b=m(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=m.makeArray(b),g=e.length;while(g--)if(d=e[g],m.inArray(m.valHooks.option.get(d),f)>=0)try{d.selected=c=!0}catch(h){d.scrollHeight}else d.selected=!1;return c||(a.selectedIndex=-1),e}}}}),m.each(["radio","checkbox"],function(){m.valHooks[this]={set:function(a,b){return m.isArray(b)?a.checked=m.inArray(m(a).val(),b)>=0:void 0}},k.checkOn||(m.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var mb,nb,ob=m.expr.attrHandle,pb=/^(?:checked|selected)$/i,qb=k.getSetAttribute,rb=k.input;m.fn.extend({attr:function(a,b){return V(this,m.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){m.removeAttr(this,a)})}}),m.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(a&&3!==f&&8!==f&&2!==f)return typeof a.getAttribute===K?m.prop(a,b,c):(1===f&&m.isXMLDoc(a)||(b=b.toLowerCase(),d=m.attrHooks[b]||(m.expr.match.bool.test(b)?nb:mb)),void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=m.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 m.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=m.propFix[c]||c,m.expr.match.bool.test(c)?rb&&qb||!pb.test(c)?a[d]=!1:a[m.camelCase("default-"+c)]=a[d]=!1:m.attr(a,c,""),a.removeAttribute(qb?c:d)},attrHooks:{type:{set:function(a,b){if(!k.radioValue&&"radio"===b&&m.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}}}),nb={set:function(a,b,c){return b===!1?m.removeAttr(a,c):rb&&qb||!pb.test(c)?a.setAttribute(!qb&&m.propFix[c]||c,c):a[m.camelCase("default-"+c)]=a[c]=!0,c}},m.each(m.expr.match.bool.source.match(/\w+/g),function(a,b){var c=ob[b]||m.find.attr;ob[b]=rb&&qb||!pb.test(b)?function(a,b,d){var e,f;return d||(f=ob[b],ob[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,ob[b]=f),e}:function(a,b,c){return c?void 0:a[m.camelCase("default-"+b)]?b.toLowerCase():null}}),rb&&qb||(m.attrHooks.value={set:function(a,b,c){return m.nodeName(a,"input")?void(a.defaultValue=b):mb&&mb.set(a,b,c)}}),qb||(mb={set:function(a,b,c){var d=a.getAttributeNode(c);return d||a.setAttributeNode(d=a.ownerDocument.createAttribute(c)),d.value=b+="","value"===c||b===a.getAttribute(c)?b:void 0}},ob.id=ob.name=ob.coords=function(a,b,c){var d;return c?void 0:(d=a.getAttributeNode(b))&&""!==d.value?d.value:null},m.valHooks.button={get:function(a,b){var c=a.getAttributeNode(b);return c&&c.specified?c.value:void 0},set:mb.set},m.attrHooks.contenteditable={set:function(a,b,c){mb.set(a,""===b?!1:b,c)}},m.each(["width","height"],function(a,b){m.attrHooks[b]={set:function(a,c){return""===c?(a.setAttribute(b,"auto"),c):void 0}}})),k.style||(m.attrHooks.style={get:function(a){return a.style.cssText||void 0},set:function(a,b){return a.style.cssText=b+""}});var sb=/^(?:input|select|textarea|button|object)$/i,tb=/^(?:a|area)$/i;m.fn.extend({prop:function(a,b){return V(this,m.prop,a,b,arguments.length>1)},removeProp:function(a){return a=m.propFix[a]||a,this.each(function(){try{this[a]=void 0,delete this[a]}catch(b){}})}}),m.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||!m.isXMLDoc(a),f&&(b=m.propFix[b]||b,e=m.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=m.find.attr(a,"tabindex");return b?parseInt(b,10):sb.test(a.nodeName)||tb.test(a.nodeName)&&a.href?0:-1}}}}),k.hrefNormalized||m.each(["href","src"],function(a,b){m.propHooks[b]={get:function(a){return a.getAttribute(b,4)}}}),k.optSelected||(m.propHooks.selected={get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null}}),m.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){m.propFix[this.toLowerCase()]=this}),k.enctype||(m.propFix.enctype="encoding");var ub=/[\t\r\n\f]/g;m.fn.extend({addClass:function(a){var b,c,d,e,f,g,h=0,i=this.length,j="string"==typeof a&&a;if(m.isFunction(a))return this.each(function(b){m(this).addClass(a.call(this,b,this.className))});if(j)for(b=(a||"").match(E)||[];i>h;h++)if(c=this[h],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(ub," "):" ")){f=0;while(e=b[f++])d.indexOf(" "+e+" ")<0&&(d+=e+" ");g=m.trim(d),c.className!==g&&(c.className=g)}return this},removeClass:function(a){var b,c,d,e,f,g,h=0,i=this.length,j=0===arguments.length||"string"==typeof a&&a;if(m.isFunction(a))return this.each(function(b){m(this).removeClass(a.call(this,b,this.className))});if(j)for(b=(a||"").match(E)||[];i>h;h++)if(c=this[h],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(ub," "):"")){f=0;while(e=b[f++])while(d.indexOf(" "+e+" ")>=0)d=d.replace(" "+e+" "," ");g=a?m.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(m.isFunction(a)?function(c){m(this).toggleClass(a.call(this,c,this.className,b),b)}:function(){if("string"===c){var b,d=0,e=m(this),f=a.match(E)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else(c===K||"boolean"===c)&&(this.className&&m._data(this,"__className__",this.className),this.className=this.className||a===!1?"":m._data(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(ub," ").indexOf(b)>=0)return!0;return!1}}),m.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){m.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),m.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 vb=m.now(),wb=/\?/,xb=/(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;m.parseJSON=function(b){if(a.JSON&&a.JSON.parse)return a.JSON.parse(b+"");var c,d=null,e=m.trim(b+"");return e&&!m.trim(e.replace(xb,function(a,b,e,f){return c&&b&&(d=0),0===d?a:(c=e||b,d+=!f-!e,"")}))?Function("return "+e)():m.error("Invalid JSON: "+b)},m.parseXML=function(b){var c,d;if(!b||"string"!=typeof b)return null;try{a.DOMParser?(d=new DOMParser,c=d.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b))}catch(e){c=void 0}return c&&c.documentElement&&!c.getElementsByTagName("parsererror").length||m.error("Invalid XML: "+b),c};var yb,zb,Ab=/#.*$/,Bb=/([?&])_=[^&]*/,Cb=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Db=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Eb=/^(?:GET|HEAD)$/,Fb=/^\/\//,Gb=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,Hb={},Ib={},Jb="*/".concat("*");try{zb=location.href}catch(Kb){zb=y.createElement("a"),zb.href="",zb=zb.href}yb=Gb.exec(zb.toLowerCase())||[];function Lb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(E)||[];if(m.isFunction(c))while(d=f[e++])"+"===d.charAt(0)?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Mb(a,b,c,d){var e={},f=a===Ib;function g(h){var i;return e[h]=!0,m.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 Nb(a,b){var c,d,e=m.ajaxSettings.flatOptions||{};for(d in b)void 0!==b[d]&&((e[d]?a:c||(c={}))[d]=b[d]);return c&&m.extend(!0,a,c),a}function Ob(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===e&&(e=a.mimeType||b.getResponseHeader("Content-Type"));if(e)for(g in h)if(h[g]&&h[g].test(e)){i.unshift(g);break}if(i[0]in c)f=i[0];else{for(g in c){if(!i[0]||a.converters[g+" "+i[0]]){f=g;break}d||(d=g)}f=f||d}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function Pb(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}}m.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:zb,type:"GET",isLocal:Db.test(yb[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Jb,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":m.parseJSON,"text xml":m.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Nb(Nb(a,m.ajaxSettings),b):Nb(m.ajaxSettings,a)},ajaxPrefilter:Lb(Hb),ajaxTransport:Lb(Ib),ajax:function(a,b){"object"==typeof a&&(b=a,a=void 0),b=b||{};var c,d,e,f,g,h,i,j,k=m.ajaxSetup({},b),l=k.context||k,n=k.context&&(l.nodeType||l.jquery)?m(l):m.event,o=m.Deferred(),p=m.Callbacks("once memory"),q=k.statusCode||{},r={},s={},t=0,u="canceled",v={readyState:0,getResponseHeader:function(a){var b;if(2===t){if(!j){j={};while(b=Cb.exec(f))j[b[1].toLowerCase()]=b[2]}b=j[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===t?f: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 i&&i.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||zb)+"").replace(Ab,"").replace(Fb,yb[1]+"//"),k.type=b.method||b.type||k.method||k.type,k.dataTypes=m.trim(k.dataType||"*").toLowerCase().match(E)||[""],null==k.crossDomain&&(c=Gb.exec(k.url.toLowerCase()),k.crossDomain=!(!c||c[1]===yb[1]&&c[2]===yb[2]&&(c[3]||("http:"===c[1]?"80":"443"))===(yb[3]||("http:"===yb[1]?"80":"443")))),k.data&&k.processData&&"string"!=typeof k.data&&(k.data=m.param(k.data,k.traditional)),Mb(Hb,k,b,v),2===t)return v;h=m.event&&k.global,h&&0===m.active++&&m.event.trigger("ajaxStart"),k.type=k.type.toUpperCase(),k.hasContent=!Eb.test(k.type),e=k.url,k.hasContent||(k.data&&(e=k.url+=(wb.test(e)?"&":"?")+k.data,delete k.data),k.cache===!1&&(k.url=Bb.test(e)?e.replace(Bb,"$1_="+vb++):e+(wb.test(e)?"&":"?")+"_="+vb++)),k.ifModified&&(m.lastModified[e]&&v.setRequestHeader("If-Modified-Since",m.lastModified[e]),m.etag[e]&&v.setRequestHeader("If-None-Match",m.etag[e])),(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]?", "+Jb+"; q=0.01":""):k.accepts["*"]);for(d in k.headers)v.setRequestHeader(d,k.headers[d]);if(k.beforeSend&&(k.beforeSend.call(l,v,k)===!1||2===t))return v.abort();u="abort";for(d in{success:1,error:1,complete:1})v[d](k[d]);if(i=Mb(Ib,k,b,v)){v.readyState=1,h&&n.trigger("ajaxSend",[v,k]),k.async&&k.timeout>0&&(g=setTimeout(function(){v.abort("timeout")},k.timeout));try{t=1,i.send(r,x)}catch(w){if(!(2>t))throw w;x(-1,w)}}else x(-1,"No Transport");function x(a,b,c,d){var j,r,s,u,w,x=b;2!==t&&(t=2,g&&clearTimeout(g),i=void 0,f=d||"",v.readyState=a>0?4:0,j=a>=200&&300>a||304===a,c&&(u=Ob(k,v,c)),u=Pb(k,u,v,j),j?(k.ifModified&&(w=v.getResponseHeader("Last-Modified"),w&&(m.lastModified[e]=w),w=v.getResponseHeader("etag"),w&&(m.etag[e]=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,h&&n.trigger(j?"ajaxSuccess":"ajaxError",[v,k,j?r:s]),p.fireWith(l,[v,x]),h&&(n.trigger("ajaxComplete",[v,k]),--m.active||m.event.trigger("ajaxStop")))}return v},getJSON:function(a,b,c){return m.get(a,b,c,"json")},getScript:function(a,b){return m.get(a,void 0,b,"script")}}),m.each(["get","post"],function(a,b){m[b]=function(a,c,d,e){return m.isFunction(c)&&(e=e||d,d=c,c=void 0),m.ajax({url:a,type:b,dataType:e,data:c,success:d})}}),m._evalUrl=function(a){return m.ajax({url:a,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},m.fn.extend({wrapAll:function(a){if(m.isFunction(a))return this.each(function(b){m(this).wrapAll(a.call(this,b))});if(this[0]){var b=m(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&1===a.firstChild.nodeType)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return this.each(m.isFunction(a)?function(b){m(this).wrapInner(a.call(this,b))}:function(){var b=m(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=m.isFunction(a);return this.each(function(c){m(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){m.nodeName(this,"body")||m(this).replaceWith(this.childNodes)}).end()}}),m.expr.filters.hidden=function(a){return a.offsetWidth<=0&&a.offsetHeight<=0||!k.reliableHiddenOffsets()&&"none"===(a.style&&a.style.display||m.css(a,"display"))},m.expr.filters.visible=function(a){return!m.expr.filters.hidden(a)};var Qb=/%20/g,Rb=/\[\]$/,Sb=/\r?\n/g,Tb=/^(?:submit|button|image|reset|file)$/i,Ub=/^(?:input|select|textarea|keygen)/i;function Vb(a,b,c,d){var e;if(m.isArray(b))m.each(b,function(b,e){c||Rb.test(a)?d(a,e):Vb(a+"["+("object"==typeof e?b:"")+"]",e,c,d)});else if(c||"object"!==m.type(b))d(a,b);else for(e in b)Vb(a+"["+e+"]",b[e],c,d)}m.param=function(a,b){var c,d=[],e=function(a,b){b=m.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=m.ajaxSettings&&m.ajaxSettings.traditional),m.isArray(a)||a.jquery&&!m.isPlainObject(a))m.each(a,function(){e(this.name,this.value)});else for(c in a)Vb(c,a[c],b,e);return d.join("&").replace(Qb,"+")},m.fn.extend({serialize:function(){return m.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=m.prop(this,"elements");return a?m.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!m(this).is(":disabled")&&Ub.test(this.nodeName)&&!Tb.test(a)&&(this.checked||!W.test(a))}).map(function(a,b){var c=m(this).val();return null==c?null:m.isArray(c)?m.map(c,function(a){return{name:b.name,value:a.replace(Sb,"\r\n")}}):{name:b.name,value:c.replace(Sb,"\r\n")}}).get()}}),m.ajaxSettings.xhr=void 0!==a.ActiveXObject?function(){return!this.isLocal&&/^(get|post|head|put|delete|options)$/i.test(this.type)&&Zb()||$b()}:Zb;var Wb=0,Xb={},Yb=m.ajaxSettings.xhr();a.attachEvent&&a.attachEvent("onunload",function(){for(var a in Xb)Xb[a](void 0,!0)}),k.cors=!!Yb&&"withCredentials"in Yb,Yb=k.ajax=!!Yb,Yb&&m.ajaxTransport(function(a){if(!a.crossDomain||k.cors){var b;return{send:function(c,d){var e,f=a.xhr(),g=++Wb;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)void 0!==c[e]&&f.setRequestHeader(e,c[e]+"");f.send(a.hasContent&&a.data||null),b=function(c,e){var h,i,j;if(b&&(e||4===f.readyState))if(delete Xb[g],b=void 0,f.onreadystatechange=m.noop,e)4!==f.readyState&&f.abort();else{j={},h=f.status,"string"==typeof f.responseText&&(j.text=f.responseText);try{i=f.statusText}catch(k){i=""}h||!a.isLocal||a.crossDomain?1223===h&&(h=204):h=j.text?200:404}j&&d(h,i,j,f.getAllResponseHeaders())},a.async?4===f.readyState?setTimeout(b):f.onreadystatechange=Xb[g]=b:b()},abort:function(){b&&b(void 0,!0)}}}});function Zb(){try{return new a.XMLHttpRequest}catch(b){}}function $b(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}m.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(a){return m.globalEval(a),a}}}),m.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),m.ajaxTransport("script",function(a){if(a.crossDomain){var b,c=y.head||m("head")[0]||y.documentElement;return{send:function(d,e){b=y.createElement("script"),b.async=!0,a.scriptCharset&&(b.charset=a.scriptCharset),b.src=a.url,b.onload=b.onreadystatechange=function(a,c){(c||!b.readyState||/loaded|complete/.test(b.readyState))&&(b.onload=b.onreadystatechange=null,b.parentNode&&b.parentNode.removeChild(b),b=null,c||e(200,"success"))},c.insertBefore(b,c.firstChild)},abort:function(){b&&b.onload(void 0,!0)}}}});var _b=[],ac=/(=)\?(?=&|$)|\?\?/;m.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=_b.pop()||m.expando+"_"+vb++;return this[a]=!0,a}}),m.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(ac.test(b.url)?"url":"string"==typeof b.data&&!(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&ac.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=m.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(ac,"$1"+e):b.jsonp!==!1&&(b.url+=(wb.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||m.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,_b.push(e)),g&&m.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),m.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||y;var d=u.exec(a),e=!c&&[];return d?[b.createElement(d[1])]:(d=m.buildFragment([a],b,e),e&&e.length&&m(e).remove(),m.merge([],d.childNodes))};var bc=m.fn.load;m.fn.load=function(a,b,c){if("string"!=typeof a&&bc)return bc.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>=0&&(d=m.trim(a.slice(h,a.length)),a=a.slice(0,h)),m.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(f="POST"),g.length>0&&m.ajax({url:a,type:f,dataType:"html",data:b}).done(function(a){e=arguments,g.html(d?m("<div>").append(m.parseHTML(a)).find(d):a)}).complete(c&&function(a,b){g.each(c,e||[a.responseText,b,a])}),this},m.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){m.fn[b]=function(a){return this.on(b,a)}}),m.expr.filters.animated=function(a){return m.grep(m.timers,function(b){return a===b.elem}).length};var cc=a.document.documentElement;function dc(a){return m.isWindow(a)?a:9===a.nodeType?a.defaultView||a.parentWindow:!1}m.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=m.css(a,"position"),l=m(a),n={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=m.css(a,"top"),i=m.css(a,"left"),j=("absolute"===k||"fixed"===k)&&m.inArray("auto",[f,i])>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),m.isFunction(b)&&(b=b.call(a,c,h)),null!=b.top&&(n.top=b.top-h.top+g),null!=b.left&&(n.left=b.left-h.left+e),"using"in b?b.using.call(a,n):l.css(n)}},m.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){m.offset.setOffset(this,a,b)});var b,c,d={top:0,left:0},e=this[0],f=e&&e.ownerDocument;if(f)return b=f.documentElement,m.contains(b,e)?(typeof e.getBoundingClientRect!==K&&(d=e.getBoundingClientRect()),c=dc(f),{top:d.top+(c.pageYOffset||b.scrollTop)-(b.clientTop||0),left:d.left+(c.pageXOffset||b.scrollLeft)-(b.clientLeft||0)}):d},position:function(){if(this[0]){var a,b,c={top:0,left:0},d=this[0];return"fixed"===m.css(d,"position")?b=d.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),m.nodeName(a[0],"html")||(c=a.offset()),c.top+=m.css(a[0],"borderTopWidth",!0),c.left+=m.css(a[0],"borderLeftWidth",!0)),{top:b.top-c.top-m.css(d,"marginTop",!0),left:b.left-c.left-m.css(d,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||cc;while(a&&!m.nodeName(a,"html")&&"static"===m.css(a,"position"))a=a.offsetParent;return a||cc})}}),m.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c=/Y/.test(b);m.fn[a]=function(d){return V(this,function(a,d,e){var f=dc(a);return void 0===e?f?b in f?f[b]:f.document.documentElement[d]:a[d]:void(f?f.scrollTo(c?m(f).scrollLeft():e,c?e:m(f).scrollTop()):a[d]=e)},a,d,arguments.length,null)}}),m.each(["top","left"],function(a,b){m.cssHooks[b]=La(k.pixelPosition,function(a,c){return c?(c=Ja(a,b),Ha.test(c)?m(a).position()[b]+"px":c):void 0})}),m.each({Height:"height",Width:"width"},function(a,b){m.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){m.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return V(this,function(b,c,d){var e;return m.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?m.css(b,c,g):m.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),m.fn.size=function(){return this.length},m.fn.andSelf=m.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return m});var ec=a.jQuery,fc=a.$;return m.noConflict=function(b){return a.$===m&&(a.$=fc),b&&a.jQuery===m&&(a.jQuery=ec),m},typeof b===K&&(a.jQuery=a.$=m),m}); diff --git a/website/agenda/planung/js/jquery.min.js b/website/agenda/planung/js/jquery.min.js index 5fd1339..2c69bc9 100644 --- a/website/agenda/planung/js/jquery.min.js +++ b/website/agenda/planung/js/jquery.min.js @@ -1,6 +1,2 @@ -/*! jQuery v1.12.4 | (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="1.12.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 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!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(n.isPlainObject(c)||(b=n.isArray(c)))?(b?(b=!1,f=a&&n.isArray(a)?a:[]):f=a&&n.isPlainObject(a)?a:{},g[d]=n.extend(j,f,c)):void 0!==c&&(g[d]=c));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||function(a){return"array"===n.type(a)},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},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;try{if(a.constructor&&!k.call(a,"constructor")&&!k.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(!l.ownFirst)for(b in a)return k.call(a,b);for(b in a);return void 0===b||k.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?i[j.call(a)]||"object":typeof a},globalEval:function(b){b&&n.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},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){var d;if(b){if(h)return h.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[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&&(f=a[b],b=a,a=f),n.isFunction(a)?(c=e.call(arguments,2),d=function(){return a.apply(b||this,c.concat(e.call(arguments)))},d.guid=a.guid=a.guid||n.guid++,d):void 0},now:function(){return+new Date},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 n.inArray(a,b)>-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=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;e>b;b++)if(n.contains(d[b],this))return!0}));for(b=0;e>b;b++)n.find(a,d[b],c);return c=this.pushStack(e>1?n.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},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.charAt(0)&&">"===a.charAt(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}if(f=d.getElementById(e[2]),f&&f.parentNode){if(f.id!==e[2])return A.find(a);this.length=1,this[0]=f}return this.context=d,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof 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,c=n(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(n.contains(this,c[b]))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?n.inArray(this[0],n(a)):n.inArray(a.jquery?a[0]:a,this):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){do a=a[b];while(a&&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 n.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document: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]||(e=n.uniqueSort(e)),D.test(a)&&(e=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=!0,c||j.disable(),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.addEventListener?(d.removeEventListener("DOMContentLoaded",K),a.removeEventListener("load",K)):(d.detachEvent("onreadystatechange",K),a.detachEvent("onload",K))}function K(){(d.addEventListener||"load"===a.event.type||"complete"===d.readyState)&&(J(),n.ready())}n.ready.promise=function(b){if(!I)if(I=n.Deferred(),"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll)a.setTimeout(n.ready);else if(d.addEventListener)d.addEventListener("DOMContentLoaded",K),a.addEventListener("load",K);else{d.attachEvent("onreadystatechange",K),a.attachEvent("onload",K);var c=!1;try{c=null==a.frameElement&&d.documentElement}catch(e){}c&&c.doScroll&&!function f(){if(!n.isReady){try{c.doScroll("left")}catch(b){return a.setTimeout(f,50)}J(),n.ready()}}()}return I.promise(b)},n.ready.promise();var L;for(L in n(l))break;l.ownFirst="0"===L,l.inlineBlockNeedsLayout=!1,n(function(){var a,b,c,e;c=d.getElementsByTagName("body")[0],c&&c.style&&(b=d.createElement("div"),e=d.createElement("div"),e.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(e).appendChild(b),"undefined"!=typeof b.style.zoom&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",l.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(e))}),function(){var a=d.createElement("div");l.deleteExpando=!0;try{delete a.test}catch(b){l.deleteExpando=!1}a=null}();var M=function(a){var b=n.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b},N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(O,"-$1").toLowerCase();if(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){}n.data(a,b,c)}else c=void 0; -}return c}function Q(a){var b;for(b in a)if(("data"!==b||!n.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function R(a,b,d,e){if(M(a)){var f,g,h=n.expando,i=a.nodeType,j=i?n.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||n.guid++:h),j[k]||(j[k]=i?{}:{toJSON:n.noop}),"object"!=typeof b&&"function"!=typeof b||(e?j[k]=n.extend(j[k],b):j[k].data=n.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[n.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[n.camelCase(b)])):f=g,f}}function S(a,b,c){if(M(a)){var d,e,f=a.nodeType,g=f?n.cache:a,h=f?a[n.expando]:n.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){n.isArray(b)?b=b.concat(n.map(b,n.camelCase)):b in d?b=[b]:(b=n.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!Q(d):!n.isEmptyObject(d))return}(c||(delete g[h].data,Q(g[h])))&&(f?n.cleanData([a],!0):l.deleteExpando||g!=g.window?delete g[h]:g[h]=void 0)}}}n.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?n.cache[a[n.expando]]:a[n.expando],!!a&&!Q(a)},data:function(a,b,c){return R(a,b,c)},removeData:function(a,b){return S(a,b)},_data:function(a,b,c){return R(a,b,c,!0)},_removeData:function(a,b){return S(a,b,!0)}}),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=n.data(f),1===f.nodeType&&!n._data(f,"parsedAttrs"))){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])));n._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){n.data(this,a)}):arguments.length>1?this.each(function(){n.data(this,a,b)}):f?P(f,a,n.data(f,a)):void 0},removeData:function(a){return this.each(function(){n.removeData(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=n._data(a,b),c&&(!d||n.isArray(c)?d=n._data(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._data(a,c)||n._data(a,c,{empty:n.Callbacks("once memory").add(function(){n._removeData(a,b+"queue"),n._removeData(a,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._data(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}}),function(){var a;l.shrinkWrapBlocks=function(){if(null!=a)return a;a=!1;var b,c,e;return c=d.getElementsByTagName("body")[0],c&&c.style?(b=d.createElement("div"),e=d.createElement("div"),e.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(e).appendChild(b),"undefined"!=typeof b.style.zoom&&(b.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:1px;width:1px;zoom:1",b.appendChild(d.createElement("div")).style.width="5px",a=3!==b.offsetWidth),c.removeChild(e),a):void 0}}();var T=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,U=new RegExp("^(?:([+-])=|)("+T+")([a-z%]*)$","i"),V=["Top","Right","Bottom","Left"],W=function(a,b){return a=b||a,"none"===n.css(a,"display")||!n.contains(a.ownerDocument,a)};function X(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)&&U.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 Y=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)Y(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},Z=/^(?:checkbox|radio)$/i,$=/<([\w:-]+)/,_=/^$|\/(?:java|ecma)script/i,aa=/^\s+/,ba="abbr|article|aside|audio|bdi|canvas|data|datalist|details|dialog|figcaption|figure|footer|header|hgroup|main|mark|meter|nav|output|picture|progress|section|summary|template|time|video";function ca(a){var b=ba.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}!function(){var a=d.createElement("div"),b=d.createDocumentFragment(),c=d.createElement("input");a.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",l.leadingWhitespace=3===a.firstChild.nodeType,l.tbody=!a.getElementsByTagName("tbody").length,l.htmlSerialize=!!a.getElementsByTagName("link").length,l.html5Clone="<:nav></:nav>"!==d.createElement("nav").cloneNode(!0).outerHTML,c.type="checkbox",c.checked=!0,b.appendChild(c),l.appendChecked=c.checked,a.innerHTML="<textarea>x</textarea>",l.noCloneChecked=!!a.cloneNode(!0).lastChild.defaultValue,b.appendChild(a),c=d.createElement("input"),c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),a.appendChild(c),l.checkClone=a.cloneNode(!0).cloneNode(!0).lastChild.checked,l.noCloneEvent=!!a.addEventListener,a[n.expando]=1,l.attributes=!a.getAttribute(n.expando)}();var da={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:l.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]};da.optgroup=da.option,da.tbody=da.tfoot=da.colgroup=da.caption=da.thead,da.th=da.td;function ea(a,b){var c,d,e=0,f="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||n.nodeName(d,b)?f.push(d):n.merge(f,ea(d,b));return void 0===b||b&&n.nodeName(a,b)?n.merge([a],f):f}function fa(a,b){for(var c,d=0;null!=(c=a[d]);d++)n._data(c,"globalEval",!b||n._data(b[d],"globalEval"))}var ga=/<|&#?\w+;/,ha=/<tbody/i;function ia(a){Z.test(a.type)&&(a.defaultChecked=a.checked)}function ja(a,b,c,d,e){for(var f,g,h,i,j,k,m,o=a.length,p=ca(b),q=[],r=0;o>r;r++)if(g=a[r],g||0===g)if("object"===n.type(g))n.merge(q,g.nodeType?[g]:g);else if(ga.test(g)){i=i||p.appendChild(b.createElement("div")),j=($.exec(g)||["",""])[1].toLowerCase(),m=da[j]||da._default,i.innerHTML=m[1]+n.htmlPrefilter(g)+m[2],f=m[0];while(f--)i=i.lastChild;if(!l.leadingWhitespace&&aa.test(g)&&q.push(b.createTextNode(aa.exec(g)[0])),!l.tbody){g="table"!==j||ha.test(g)?"<table>"!==m[1]||ha.test(g)?0:i:i.firstChild,f=g&&g.childNodes.length;while(f--)n.nodeName(k=g.childNodes[f],"tbody")&&!k.childNodes.length&&g.removeChild(k)}n.merge(q,i.childNodes),i.textContent="";while(i.firstChild)i.removeChild(i.firstChild);i=p.lastChild}else q.push(b.createTextNode(g));i&&p.removeChild(i),l.appendChecked||n.grep(ea(q,"input"),ia),r=0;while(g=q[r++])if(d&&n.inArray(g,d)>-1)e&&e.push(g);else if(h=n.contains(g.ownerDocument,g),i=ea(p.appendChild(g),"script"),h&&fa(i),c){f=0;while(g=i[f++])_.test(g.type||"")&&c.push(g)}return i=null,p}!function(){var b,c,e=d.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(l[b]=c in a)||(e.setAttribute(c,"t"),l[b]=e.attributes[c].expando===!1);e=null}();var ka=/^(?:input|select|textarea)$/i,la=/^key/,ma=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,na=/^(?:focusinfocus|focusoutblur)$/,oa=/^([^.]*)(?:\.(.+)|)/;function pa(){return!0}function qa(){return!1}function ra(){try{return d.activeElement}catch(a){}}function sa(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)sa(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=qa;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._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=n.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return"undefined"==typeof n||a&&n.event.triggered===a.type?void 0:n.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(G)||[""],h=b.length;while(h--)f=oa.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=n.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=n.event.special[o]||{},l=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(".")},i),(m=g[o])||(m=g[o]=[],m.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,l):m.push(l),n.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n.hasData(a)&&n._data(a);if(r&&(k=r.events)){b=(b||"").match(G)||[""],j=b.length;while(j--)if(h=oa.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=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=m.length;while(f--)g=m[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(m.splice(f,1),g.selector&&m.delegateCount--,l.remove&&l.remove.call(a,g));i&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(k)&&(delete r.handle,n._removeData(a,"events"))}},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(i=m=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!na.test(q+n.event.triggered)&&(q.indexOf(".")>-1&&(r=q.split("."),q=r.shift(),r.sort()),h=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]),l=n.event.special[q]||{},f||!l.trigger||l.trigger.apply(e,c)!==!1)){if(!f&&!l.noBubble&&!n.isWindow(e)){for(j=l.delegateType||q,na.test(j+q)||(i=i.parentNode);i;i=i.parentNode)p.push(i),m=i;m===(e.ownerDocument||d)&&p.push(m.defaultView||m.parentWindow||a)}o=0;while((i=p[o++])&&!b.isPropagationStopped())b.type=o>1?j:l.bindType||q,g=(n._data(i,"events")||{})[b.type]&&n._data(i,"handle"),g&&g.apply(i,c),g=h&&i[h],g&&g.apply&&M(i)&&(b.result=g.apply(i,c),b.result===!1&&b.preventDefault());if(b.type=q,!f&&!b.isDefaultPrevented()&&(!l._default||l._default.apply(p.pop(),c)===!1)&&M(e)&&h&&e[q]&&!n.isWindow(e)){m=e[h],m&&(e[h]=null),n.event.triggered=q;try{e[q]()}catch(s){}n.event.triggered=void 0,m&&(e[h]=m)}return b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,d,f,g,h=[],i=e.call(arguments),j=(n._data(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},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=ma.test(f)?this.mouseHooks:la.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=g.srcElement||d),3===a.target.nodeType&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,h.filter?h.filter(a,g):a},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 fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,e,f,g=b.button,h=b.fromElement;return null==a.pageX&&null!=b.clientX&&(e=a.target.ownerDocument||d,f=e.documentElement,c=e.body,a.pageX=b.clientX+(f&&f.scrollLeft||c&&c.scrollLeft||0)-(f&&f.clientLeft||c&&c.clientLeft||0),a.pageY=b.clientY+(f&&f.scrollTop||c&&c.scrollTop||0)-(f&&f.clientTop||c&&c.clientTop||0)),!a.relatedTarget&&h&&(a.relatedTarget=h===a.target?b.toElement:h),a.which||void 0===g||(a.which=1&g?1:2&g?3:4&g?2:0),a}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==ra()&&this.focus)try{return this.focus(),!1}catch(a){}},delegateType:"focusin"},blur:{trigger:function(){return this===ra()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return n.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(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){var d=n.extend(new n.Event,c,{type:a,isSimulated:!0});n.event.trigger(d,null,b),d.isDefaultPrevented()&&c.preventDefault()}},n.removeEvent=d.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c)}:function(a,b,c){var d="on"+b;a.detachEvent&&("undefined"==typeof a[d]&&(a[d]=null),a.detachEvent(d,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?pa:qa):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:qa,isPropagationStopped:qa,isImmediatePropagationStopped:qa,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=pa,a&&(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=pa,a&&!this.isSimulated&&(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=pa,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}}}),l.submit||(n.event.special.submit={setup:function(){return n.nodeName(this,"form")?!1:void n.event.add(this,"click._submit keypress._submit",function(a){var b=a.target,c=n.nodeName(b,"input")||n.nodeName(b,"button")?n.prop(b,"form"):void 0;c&&!n._data(c,"submit")&&(n.event.add(c,"submit._submit",function(a){a._submitBubble=!0}),n._data(c,"submit",!0))})},postDispatch:function(a){a._submitBubble&&(delete a._submitBubble,this.parentNode&&!a.isTrigger&&n.event.simulate("submit",this.parentNode,a))},teardown:function(){return n.nodeName(this,"form")?!1:void n.event.remove(this,"._submit")}}),l.change||(n.event.special.change={setup:function(){return ka.test(this.nodeName)?("checkbox"!==this.type&&"radio"!==this.type||(n.event.add(this,"propertychange._change",function(a){"checked"===a.originalEvent.propertyName&&(this._justChanged=!0)}),n.event.add(this,"click._change",function(a){this._justChanged&&!a.isTrigger&&(this._justChanged=!1),n.event.simulate("change",this,a)})),!1):void n.event.add(this,"beforeactivate._change",function(a){var b=a.target;ka.test(b.nodeName)&&!n._data(b,"change")&&(n.event.add(b,"change._change",function(a){!this.parentNode||a.isSimulated||a.isTrigger||n.event.simulate("change",this.parentNode,a)}),n._data(b,"change",!0))})},handle:function(a){var b=a.target;return this!==b||a.isSimulated||a.isTrigger||"radio"!==b.type&&"checkbox"!==b.type?a.handleObj.handler.apply(this,arguments):void 0},teardown:function(){return n.event.remove(this,"._change"),!ka.test(this.nodeName)}}),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._data(d,b);e||d.addEventListener(a,c,!0),n._data(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=n._data(d,b)-1;e?n._data(d,b,e):(d.removeEventListener(a,c,!0),n._removeData(d,b))}}}),n.fn.extend({on:function(a,b,c,d){return sa(this,a,b,c,d)},one:function(a,b,c,d){return sa(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=qa),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 ta=/ jQuery\d+="(?:null|\d+)"/g,ua=new RegExp("<(?:"+ba+")[\\s/>]","i"),va=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,wa=/<script|<style|<link/i,xa=/checked\s*(?:[^=]|=\s*.checked.)/i,ya=/^true\/(.*)/,za=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,Aa=ca(d),Ba=Aa.appendChild(d.createElement("div"));function Ca(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 Da(a){return a.type=(null!==n.find.attr(a,"type"))+"/"+a.type,a}function Ea(a){var b=ya.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Fa(a,b){if(1===b.nodeType&&n.hasData(a)){var c,d,e,f=n._data(a),g=n._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)n.event.add(b,c,h[c][d])}g.data&&(g.data=n.extend({},g.data))}}function Ga(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!l.noCloneEvent&&b[n.expando]){e=n._data(b);for(d in e.events)n.removeEvent(b,d,e.handle);b.removeAttribute(n.expando)}"script"===c&&b.text!==a.text?(Da(b).text=a.text,Ea(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),l.html5Clone&&a.innerHTML&&!n.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&Z.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:"input"!==c&&"textarea"!==c||(b.defaultValue=a.defaultValue)}}function Ha(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&&xa.test(q))return a.each(function(e){var f=a.eq(e);r&&(b[0]=q.call(this,e,f.html())),Ha(f,b,c,d)});if(o&&(k=ja(b,a[0].ownerDocument,!1,a,d),e=k.firstChild,1===k.childNodes.length&&(k=e),e||d)){for(i=n.map(ea(k,"script"),Da),h=i.length;o>m;m++)g=k,m!==p&&(g=n.clone(g,!0,!0),h&&n.merge(i,ea(g,"script"))),c.call(a[m],g,m);if(h)for(j=i[i.length-1].ownerDocument,n.map(i,Ea),m=0;h>m;m++)g=i[m],_.test(g.type||"")&&!n._data(g,"globalEval")&&n.contains(j,g)&&(g.src?n._evalUrl&&n._evalUrl(g.src):n.globalEval((g.text||g.textContent||g.innerHTML||"").replace(za,"")));k=e=null}return a}function Ia(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(ea(d)),d.parentNode&&(c&&n.contains(d.ownerDocument,d)&&fa(ea(d,"script")),d.parentNode.removeChild(d));return a}n.extend({htmlPrefilter:function(a){return a.replace(va,"<$1></$2>")},clone:function(a,b,c){var d,e,f,g,h,i=n.contains(a.ownerDocument,a);if(l.html5Clone||n.isXMLDoc(a)||!ua.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(Ba.innerHTML=a.outerHTML,Ba.removeChild(f=Ba.firstChild)),!(l.noCloneEvent&&l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(d=ea(f),h=ea(a),g=0;null!=(e=h[g]);++g)d[g]&&Ga(e,d[g]);if(b)if(c)for(h=h||ea(a),d=d||ea(f),g=0;null!=(e=h[g]);g++)Fa(e,d[g]);else Fa(a,f);return d=ea(f,"script"),d.length>0&&fa(d,!i&&ea(a,"script")),d=h=e=null,f},cleanData:function(a,b){for(var d,e,f,g,h=0,i=n.expando,j=n.cache,k=l.attributes,m=n.event.special;null!=(d=a[h]);h++)if((b||M(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)m[e]?n.event.remove(d,e):n.removeEvent(d,e,g.handle);j[f]&&(delete j[f],k||"undefined"==typeof d.removeAttribute?d[i]=void 0:d.removeAttribute(i),c.push(f))}}}),n.fn.extend({domManip:Ha,detach:function(a){return Ia(this,a,!0)},remove:function(a){return Ia(this,a)},text:function(a){return Y(this,function(a){return void 0===a?n.text(this):this.empty().append((this[0]&&this[0].ownerDocument||d).createTextNode(a))},null,a,arguments.length)},append:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.appendChild(a)}})},prepend:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ha(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(ea(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&n.nodeName(a,"select")&&(a.options.length=0)}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 Y(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(ta,""):void 0;if("string"==typeof a&&!wa.test(a)&&(l.htmlSerialize||!ua.test(a))&&(l.leadingWhitespace||!aa.test(a))&&!da[($.exec(a)||["",""])[1].toLowerCase()]){a=n.htmlPrefilter(a);try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ea(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return Ha(this,arguments,function(b){var c=this.parentNode;n.inArray(this,a)<0&&(n.cleanData(ea(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=0,e=[],f=n(a),h=f.length-1;h>=d;d++)c=d===h?this:this.clone(!0),n(f[d])[b](c),g.apply(e,c.get());return this.pushStack(e)}});var Ja,Ka={HTML:"block",BODY:"block"};function La(a,b){var c=n(b.createElement(a)).appendTo(b.body),d=n.css(c[0],"display");return c.detach(),d}function Ma(a){var b=d,c=Ka[a];return c||(c=La(a,b),"none"!==c&&c||(Ja=(Ja||n("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=(Ja[0].contentWindow||Ja[0].contentDocument).document,b.write(),b.close(),c=La(a,b),Ja.detach()),Ka[a]=c),c}var Na=/^margin/,Oa=new RegExp("^("+T+")(?!px)[a-z%]+$","i"),Pa=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},Qa=d.documentElement;!function(){var b,c,e,f,g,h,i=d.createElement("div"),j=d.createElement("div");if(j.style){j.style.cssText="float:left;opacity:.5",l.opacity="0.5"===j.style.opacity,l.cssFloat=!!j.style.cssFloat,j.style.backgroundClip="content-box",j.cloneNode(!0).style.backgroundClip="",l.clearCloneStyle="content-box"===j.style.backgroundClip,i=d.createElement("div"),i.style.cssText="border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute",j.innerHTML="",i.appendChild(j),l.boxSizing=""===j.style.boxSizing||""===j.style.MozBoxSizing||""===j.style.WebkitBoxSizing,n.extend(l,{reliableHiddenOffsets:function(){return null==b&&k(),f},boxSizingReliable:function(){return null==b&&k(),e},pixelMarginRight:function(){return null==b&&k(),c},pixelPosition:function(){return null==b&&k(),b},reliableMarginRight:function(){return null==b&&k(),g},reliableMarginLeft:function(){return null==b&&k(),h}});function k(){var k,l,m=d.documentElement;m.appendChild(i),j.style.cssText="-webkit-box-sizing:border-box;box-sizing:border-box;position:relative;display:block;margin:auto;border:1px;padding:1px;top:1%;width:50%",b=e=h=!1,c=g=!0,a.getComputedStyle&&(l=a.getComputedStyle(j),b="1%"!==(l||{}).top,h="2px"===(l||{}).marginLeft,e="4px"===(l||{width:"4px"}).width,j.style.marginRight="50%",c="4px"===(l||{marginRight:"4px"}).marginRight,k=j.appendChild(d.createElement("div")),k.style.cssText=j.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",k.style.marginRight=k.style.width="0",j.style.width="1px",g=!parseFloat((a.getComputedStyle(k)||{}).marginRight),j.removeChild(k)),j.style.display="none",f=0===j.getClientRects().length,f&&(j.style.display="",j.innerHTML="<table><tr><td></td><td>t</td></tr></table>",j.childNodes[0].style.borderCollapse="separate",k=j.getElementsByTagName("td"),k[0].style.cssText="margin:0;border:0;padding:0;display:none",f=0===k[0].offsetHeight,f&&(k[0].style.display="",k[1].style.display="none",f=0===k[0].offsetHeight)),m.removeChild(i)}}}();var Ra,Sa,Ta=/^(top|right|bottom|left)$/;a.getComputedStyle?(Ra=function(b){var c=b.ownerDocument.defaultView;return c&&c.opener||(c=a),c.getComputedStyle(b)},Sa=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ra(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()&&Oa.test(g)&&Na.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+""}):Qa.currentStyle&&(Ra=function(a){return a.currentStyle},Sa=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ra(a),g=c?c[b]:void 0,null==g&&h&&h[b]&&(g=h[b]),Oa.test(g)&&!Ta.test(b)&&(d=h.left,e=a.runtimeStyle,f=e&&e.left,f&&(e.left=a.currentStyle.left),h.left="fontSize"===b?"1em":g,g=h.pixelLeft+"px",h.left=d,f&&(e.left=f)),void 0===g?g:g+""||"auto"});function Ua(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}var Va=/alpha\([^)]*\)/i,Wa=/opacity\s*=\s*([^)]*)/i,Xa=/^(none|table(?!-c[ea]).+)/,Ya=new RegExp("^("+T+")(.*)$","i"),Za={position:"absolute",visibility:"hidden",display:"block"},$a={letterSpacing:"0",fontWeight:"400"},_a=["Webkit","O","Moz","ms"],ab=d.createElement("div").style;function bb(a){if(a in ab)return a;var b=a.charAt(0).toUpperCase()+a.slice(1),c=_a.length;while(c--)if(a=_a[c]+b,a in ab)return a}function cb(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=n._data(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&W(d)&&(f[g]=n._data(d,"olddisplay",Ma(d.nodeName)))):(e=W(d),(c&&"none"!==c||!e)&&n._data(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}function db(a,b,c){var d=Ya.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function eb(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+V[f],!0,e)),d?("content"===c&&(g-=n.css(a,"padding"+V[f],!0,e)),"margin"!==c&&(g-=n.css(a,"border"+V[f]+"Width",!0,e))):(g+=n.css(a,"padding"+V[f],!0,e),"padding"!==c&&(g+=n.css(a,"border"+V[f]+"Width",!0,e)));return g}function fb(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=Ra(a),g=l.boxSizing&&"border-box"===n.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=Sa(a,b,f),(0>e||null==e)&&(e=a.style[b]),Oa.test(e))return e;d=g&&(l.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+eb(a,b,c||(g?"border":"content"),d,f)+"px"}n.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Sa(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":l.cssFloat?"cssFloat":"styleFloat"},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;if(b=n.cssProps[h]||(n.cssProps[h]=bb(h)||h),g=n.cssHooks[b]||n.cssHooks[h],void 0===c)return g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b];if(f=typeof c,"string"===f&&(e=U.exec(c))&&e[1]&&(c=X(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)))))try{i[b]=c}catch(j){}}},css:function(a,b,c,d){var e,f,g,h=n.camelCase(b);return b=n.cssProps[h]||(n.cssProps[h]=bb(h)||h),g=n.cssHooks[b]||n.cssHooks[h],g&&"get"in g&&(f=g.get(a,!0,c)),void 0===f&&(f=Sa(a,b,d)),"normal"===f&&b in $a&&(f=$a[b]),""===c||c?(e=parseFloat(f),c===!0||isFinite(e)?e||0:f):f}}),n.each(["height","width"],function(a,b){n.cssHooks[b]={get:function(a,c,d){return c?Xa.test(n.css(a,"display"))&&0===a.offsetWidth?Pa(a,Za,function(){return fb(a,b,d)}):fb(a,b,d):void 0},set:function(a,c,d){var e=d&&Ra(a);return db(a,c,d?eb(a,b,d,l.boxSizing&&"border-box"===n.css(a,"boxSizing",!1,e),e):0)}}}),l.opacity||(n.cssHooks.opacity={get:function(a,b){return Wa.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=n.isNumeric(b)?"alpha(opacity="+100*b+")":"",f=d&&d.filter||c.filter||"";c.zoom=1,(b>=1||""===b)&&""===n.trim(f.replace(Va,""))&&c.removeAttribute&&(c.removeAttribute("filter"),""===b||d&&!d.filter)||(c.filter=Va.test(f)?f.replace(Va,e):f+" "+e)}}),n.cssHooks.marginRight=Ua(l.reliableMarginRight,function(a,b){return b?Pa(a,{display:"inline-block"},Sa,[a,"marginRight"]):void 0}),n.cssHooks.marginLeft=Ua(l.reliableMarginLeft,function(a,b){return b?(parseFloat(Sa(a,"marginLeft"))||(n.contains(a.ownerDocument,a)?a.getBoundingClientRect().left-Pa(a,{ -marginLeft:0},function(){return a.getBoundingClientRect().left}):0))+"px":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+V[d]+b]=f[d]||f[d-2]||f[0];return e}},Na.test(a)||(n.cssHooks[a+b].set=db)}),n.fn.extend({css:function(a,b){return Y(this,function(a,b,c){var d,e,f={},g=0;if(n.isArray(b)){for(d=Ra(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 cb(this,!0)},hide:function(){return cb(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){W(this)?n(this).show():n(this).hide()})}});function gb(a,b,c,d,e){return new gb.prototype.init(a,b,c,d,e)}n.Tween=gb,gb.prototype={constructor:gb,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=gb.propHooks[this.prop];return a&&a.get?a.get(this):gb.propHooks._default.get(this)},run:function(a){var b,c=gb.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):gb.propHooks._default.set(this),this}},gb.prototype.init.prototype=gb.prototype,gb.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)}}},gb.propHooks.scrollTop=gb.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=gb.prototype.init,n.fx.step={};var hb,ib,jb=/^(?:toggle|show|hide)$/,kb=/queueHooks$/;function lb(){return a.setTimeout(function(){hb=void 0}),hb=n.now()}function mb(a,b){var c,d={height:a},e=0;for(b=b?1:0;4>e;e+=2-b)c=V[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function nb(a,b,c){for(var d,e=(qb.tweeners[b]||[]).concat(qb.tweeners["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function ob(a,b,c){var d,e,f,g,h,i,j,k,m=this,o={},p=a.style,q=a.nodeType&&W(a),r=n._data(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++,m.always(function(){m.always(function(){h.unqueued--,n.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[p.overflow,p.overflowX,p.overflowY],j=n.css(a,"display"),k="none"===j?n._data(a,"olddisplay")||Ma(a.nodeName):j,"inline"===k&&"none"===n.css(a,"float")&&(l.inlineBlockNeedsLayout&&"inline"!==Ma(a.nodeName)?p.zoom=1:p.display="inline-block")),c.overflow&&(p.overflow="hidden",l.shrinkWrapBlocks()||m.always(function(){p.overflow=c.overflow[0],p.overflowX=c.overflow[1],p.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],jb.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(q?"hide":"show")){if("show"!==e||!r||void 0===r[d])continue;q=!0}o[d]=r&&r[d]||n.style(a,d)}else j=void 0;if(n.isEmptyObject(o))"inline"===("none"===j?Ma(a.nodeName):j)&&(p.display=j);else{r?"hidden"in r&&(q=r.hidden):r=n._data(a,"fxshow",{}),f&&(r.hidden=!q),q?n(a).show():m.done(function(){n(a).hide()}),m.done(function(){var b;n._removeData(a,"fxshow");for(b in o)n.style(a,b,o[b])});for(d in o)g=nb(q?r[d]:0,d,m),d in r||(r[d]=g.start,q&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function pb(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 qb(a,b,c){var d,e,f=0,g=qb.prefilters.length,h=n.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=hb||lb(),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:hb||lb(),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(pb(k,j.opts.specialEasing);g>f;f++)if(d=qb.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,nb,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(qb,{tweeners:{"*":[function(a,b){var c=this.createTween(a,b);return X(c.elem,a,U.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],qb.tweeners[c]=qb.tweeners[c]||[],qb.tweeners[c].unshift(b)},prefilters:[ob],prefilter:function(a,b){b?qb.prefilters.unshift(a):qb.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(W).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=qb(this,n.extend({},a),f);(e||n._data(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._data(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&kb.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._data(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(mb(b,!0),a,d,e)}}),n.each({slideDown:mb("show"),slideUp:mb("hide"),slideToggle:mb("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=n.timers,c=0;for(hb=n.now();c<b.length;c++)a=b[c],a()||b[c]!==a||b.splice(c--,1);b.length||n.fx.stop(),hb=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(){ib||(ib=a.setInterval(n.fx.tick,n.fx.interval))},n.fx.stop=function(){a.clearInterval(ib),ib=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,b=d.createElement("input"),c=d.createElement("div"),e=d.createElement("select"),f=e.appendChild(d.createElement("option"));c=d.createElement("div"),c.setAttribute("className","t"),c.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",a=c.getElementsByTagName("a")[0],b.setAttribute("type","checkbox"),c.appendChild(b),a=c.getElementsByTagName("a")[0],a.style.cssText="top:1px",l.getSetAttribute="t"!==c.className,l.style=/top/.test(a.getAttribute("style")),l.hrefNormalized="/a"===a.getAttribute("href"),l.checkOn=!!b.value,l.optSelected=f.selected,l.enctype=!!d.createElement("form").enctype,e.disabled=!0,l.optDisabled=!f.disabled,b=d.createElement("input"),b.setAttribute("value",""),l.input=""===b.getAttribute("value"),b.value="t",b.setAttribute("type","radio"),l.radioValue="t"===b.value}();var rb=/\r/g,sb=/[\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(rb,""):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(sb," ")}},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--)if(d=e[g],n.inArray(n.valHooks.option.get(d),f)>-1)try{d.selected=c=!0}catch(h){d.scrollHeight}else d.selected=!1;return c||(a.selectedIndex=-1),e}}}}),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 tb,ub,vb=n.expr.attrHandle,wb=/^(?:checked|selected)$/i,xb=l.getSetAttribute,yb=l.input;n.fn.extend({attr:function(a,b){return Y(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)?ub:tb)),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)?yb&&xb||!wb.test(c)?a[d]=!1:a[n.camelCase("default-"+c)]=a[d]=!1:n.attr(a,c,""),a.removeAttribute(xb?c:d)}}),ub={set:function(a,b,c){return b===!1?n.removeAttr(a,c):yb&&xb||!wb.test(c)?a.setAttribute(!xb&&n.propFix[c]||c,c):a[n.camelCase("default-"+c)]=a[c]=!0,c}},n.each(n.expr.match.bool.source.match(/\w+/g),function(a,b){var c=vb[b]||n.find.attr;yb&&xb||!wb.test(b)?vb[b]=function(a,b,d){var e,f;return d||(f=vb[b],vb[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,vb[b]=f),e}:vb[b]=function(a,b,c){return c?void 0:a[n.camelCase("default-"+b)]?b.toLowerCase():null}}),yb&&xb||(n.attrHooks.value={set:function(a,b,c){return n.nodeName(a,"input")?void(a.defaultValue=b):tb&&tb.set(a,b,c)}}),xb||(tb={set:function(a,b,c){var d=a.getAttributeNode(c);return d||a.setAttributeNode(d=a.ownerDocument.createAttribute(c)),d.value=b+="","value"===c||b===a.getAttribute(c)?b:void 0}},vb.id=vb.name=vb.coords=function(a,b,c){var d;return c?void 0:(d=a.getAttributeNode(b))&&""!==d.value?d.value:null},n.valHooks.button={get:function(a,b){var c=a.getAttributeNode(b);return c&&c.specified?c.value:void 0},set:tb.set},n.attrHooks.contenteditable={set:function(a,b,c){tb.set(a,""===b?!1:b,c)}},n.each(["width","height"],function(a,b){n.attrHooks[b]={set:function(a,c){return""===c?(a.setAttribute(b,"auto"),c):void 0}}})),l.style||(n.attrHooks.style={get:function(a){return a.style.cssText||void 0},set:function(a,b){return a.style.cssText=b+""}});var zb=/^(?:input|select|textarea|button|object)$/i,Ab=/^(?:a|area)$/i;n.fn.extend({prop:function(a,b){return Y(this,n.prop,a,b,arguments.length>1)},removeProp:function(a){return a=n.propFix[a]||a,this.each(function(){try{this[a]=void 0,delete this[a]}catch(b){}})}}),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):zb.test(a.nodeName)||Ab.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),l.hrefNormalized||n.each(["href","src"],function(a,b){n.propHooks[b]={get:function(a){return a.getAttribute(b,4)}}}),l.optSelected||(n.propHooks.selected={get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,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}),l.enctype||(n.propFix.enctype="encoding");var Bb=/[\t\r\n\f]/g;function Cb(a){return n.attr(a,"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,Cb(this)))});if("string"==typeof a&&a){b=a.match(G)||[];while(c=this[i++])if(e=Cb(c),d=1===c.nodeType&&(" "+e+" ").replace(Bb," ")){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=n.trim(d),e!==h&&n.attr(c,"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,Cb(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(G)||[];while(c=this[i++])if(e=Cb(c),d=1===c.nodeType&&(" "+e+" ").replace(Bb," ")){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=n.trim(d),e!==h&&n.attr(c,"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,Cb(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=Cb(this),b&&n._data(this,"__className__",b),n.attr(this,"class",b||a===!1?"":n._data(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+Cb(c)+" ").replace(Bb," ").indexOf(b)>-1)return!0;return!1}}),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)}});var Db=a.location,Eb=n.now(),Fb=/\?/,Gb=/(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;n.parseJSON=function(b){if(a.JSON&&a.JSON.parse)return a.JSON.parse(b+"");var c,d=null,e=n.trim(b+"");return e&&!n.trim(e.replace(Gb,function(a,b,e,f){return c&&b&&(d=0),0===d?a:(c=e||b,d+=!f-!e,"")}))?Function("return "+e)():n.error("Invalid JSON: "+b)},n.parseXML=function(b){var c,d;if(!b||"string"!=typeof b)return null;try{a.DOMParser?(d=new a.DOMParser,c=d.parseFromString(b,"text/xml")):(c=new a.ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b))}catch(e){c=void 0}return c&&c.documentElement&&!c.getElementsByTagName("parsererror").length||n.error("Invalid XML: "+b),c};var Hb=/#.*$/,Ib=/([?&])_=[^&]*/,Jb=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Kb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Lb=/^(?:GET|HEAD)$/,Mb=/^\/\//,Nb=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,Ob={},Pb={},Qb="*/".concat("*"),Rb=Db.href,Sb=Nb.exec(Rb.toLowerCase())||[];function Tb(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.charAt(0)?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Ub(a,b,c,d){var e={},f=a===Pb;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 Vb(a,b){var c,d,e=n.ajaxSettings.flatOptions||{};for(d in b)void 0!==b[d]&&((e[d]?a:c||(c={}))[d]=b[d]);return c&&n.extend(!0,a,c),a}function Wb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===e&&(e=a.mimeType||b.getResponseHeader("Content-Type"));if(e)for(g in h)if(h[g]&&h[g].test(e)){i.unshift(g);break}if(i[0]in c)f=i[0];else{for(g in c){if(!i[0]||a.converters[g+" "+i[0]]){f=g;break}d||(d=g)}f=f||d}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function Xb(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:Rb,type:"GET",isLocal:Kb.test(Sb[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Qb,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?Vb(Vb(a,n.ajaxSettings),b):Vb(n.ajaxSettings,a)},ajaxPrefilter:Tb(Ob),ajaxTransport:Tb(Pb),ajax:function(b,c){"object"==typeof b&&(c=b,b=void 0),c=c||{};var d,e,f,g,h,i,j,k,l=n.ajaxSetup({},c),m=l.context||l,o=l.context&&(m.nodeType||m.jquery)?n(m):n.event,p=n.Deferred(),q=n.Callbacks("once memory"),r=l.statusCode||{},s={},t={},u=0,v="canceled",w={readyState:0,getResponseHeader:function(a){var b;if(2===u){if(!k){k={};while(b=Jb.exec(g))k[b[1].toLowerCase()]=b[2]}b=k[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===u?g:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return u||(a=t[c]=t[c]||a,s[a]=b),this},overrideMimeType:function(a){return u||(l.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>u)for(b in a)r[b]=[r[b],a[b]];else w.always(a[w.status]);return this},abort:function(a){var b=a||v;return j&&j.abort(b),y(0,b),this}};if(p.promise(w).complete=q.add,w.success=w.done,w.error=w.fail,l.url=((b||l.url||Rb)+"").replace(Hb,"").replace(Mb,Sb[1]+"//"),l.type=c.method||c.type||l.method||l.type,l.dataTypes=n.trim(l.dataType||"*").toLowerCase().match(G)||[""],null==l.crossDomain&&(d=Nb.exec(l.url.toLowerCase()),l.crossDomain=!(!d||d[1]===Sb[1]&&d[2]===Sb[2]&&(d[3]||("http:"===d[1]?"80":"443"))===(Sb[3]||("http:"===Sb[1]?"80":"443")))),l.data&&l.processData&&"string"!=typeof l.data&&(l.data=n.param(l.data,l.traditional)),Ub(Ob,l,c,w),2===u)return w;i=n.event&&l.global,i&&0===n.active++&&n.event.trigger("ajaxStart"),l.type=l.type.toUpperCase(),l.hasContent=!Lb.test(l.type),f=l.url,l.hasContent||(l.data&&(f=l.url+=(Fb.test(f)?"&":"?")+l.data,delete l.data),l.cache===!1&&(l.url=Ib.test(f)?f.replace(Ib,"$1_="+Eb++):f+(Fb.test(f)?"&":"?")+"_="+Eb++)),l.ifModified&&(n.lastModified[f]&&w.setRequestHeader("If-Modified-Since",n.lastModified[f]),n.etag[f]&&w.setRequestHeader("If-None-Match",n.etag[f])),(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&w.setRequestHeader("Content-Type",l.contentType),w.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+("*"!==l.dataTypes[0]?", "+Qb+"; q=0.01":""):l.accepts["*"]);for(e in l.headers)w.setRequestHeader(e,l.headers[e]);if(l.beforeSend&&(l.beforeSend.call(m,w,l)===!1||2===u))return w.abort();v="abort";for(e in{success:1,error:1,complete:1})w[e](l[e]);if(j=Ub(Pb,l,c,w)){if(w.readyState=1,i&&o.trigger("ajaxSend",[w,l]),2===u)return w;l.async&&l.timeout>0&&(h=a.setTimeout(function(){w.abort("timeout")},l.timeout));try{u=1,j.send(s,y)}catch(x){if(!(2>u))throw x;y(-1,x)}}else y(-1,"No Transport");function y(b,c,d,e){var k,s,t,v,x,y=c;2!==u&&(u=2,h&&a.clearTimeout(h),j=void 0,g=e||"",w.readyState=b>0?4:0,k=b>=200&&300>b||304===b,d&&(v=Wb(l,w,d)),v=Xb(l,v,w,k),k?(l.ifModified&&(x=w.getResponseHeader("Last-Modified"),x&&(n.lastModified[f]=x),x=w.getResponseHeader("etag"),x&&(n.etag[f]=x)),204===b||"HEAD"===l.type?y="nocontent":304===b?y="notmodified":(y=v.state,s=v.data,t=v.error,k=!t)):(t=y,!b&&y||(y="error",0>b&&(b=0))),w.status=b,w.statusText=(c||y)+"",k?p.resolveWith(m,[s,y,w]):p.rejectWith(m,[w,y,t]),w.statusCode(r),r=void 0,i&&o.trigger(k?"ajaxSuccess":"ajaxError",[w,l,k?s:t]),q.fireWith(m,[w,y]),i&&(o.trigger("ajaxComplete",[w,l]),--n.active||n.event.trigger("ajaxStop")))}return w},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",cache:!0,async:!1,global:!1,"throws":!0})},n.fn.extend({wrapAll:function(a){if(n.isFunction(a))return this.each(function(b){n(this).wrapAll(a.call(this,b))});if(this[0]){var 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.firstChild&&1===a.firstChild.nodeType)a=a.firstChild;return a}).append(this)}return 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()}});function Yb(a){return a.style&&a.style.display||n.css(a,"display")}function Zb(a){if(!n.contains(a.ownerDocument||d,a))return!0;while(a&&1===a.nodeType){if("none"===Yb(a)||"hidden"===a.type)return!0;a=a.parentNode}return!1}n.expr.filters.hidden=function(a){return l.reliableHiddenOffsets()?a.offsetWidth<=0&&a.offsetHeight<=0&&!a.getClientRects().length:Zb(a)},n.expr.filters.visible=function(a){return!n.expr.filters.hidden(a)};var $b=/%20/g,_b=/\[\]$/,ac=/\r?\n/g,bc=/^(?:submit|button|image|reset|file)$/i,cc=/^(?:input|select|textarea|keygen)/i;function dc(a,b,c,d){var e;if(n.isArray(b))n.each(b,function(b,e){c||_b.test(a)?d(a,e):dc(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)dc(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)dc(c,a[c],b,e);return d.join("&").replace($b,"+")},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")&&cc.test(this.nodeName)&&!bc.test(a)&&(this.checked||!Z.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(ac,"\r\n")}}):{name:b.name,value:c.replace(ac,"\r\n")}}).get()}}),n.ajaxSettings.xhr=void 0!==a.ActiveXObject?function(){return this.isLocal?ic():d.documentMode>8?hc():/^(get|post|head|put|delete|options)$/i.test(this.type)&&hc()||ic()}:hc;var ec=0,fc={},gc=n.ajaxSettings.xhr();a.attachEvent&&a.attachEvent("onunload",function(){for(var a in fc)fc[a](void 0,!0)}),l.cors=!!gc&&"withCredentials"in gc,gc=l.ajax=!!gc,gc&&n.ajaxTransport(function(b){if(!b.crossDomain||l.cors){var c;return{send:function(d,e){var f,g=b.xhr(),h=++ec;if(g.open(b.type,b.url,b.async,b.username,b.password),b.xhrFields)for(f in b.xhrFields)g[f]=b.xhrFields[f];b.mimeType&&g.overrideMimeType&&g.overrideMimeType(b.mimeType),b.crossDomain||d["X-Requested-With"]||(d["X-Requested-With"]="XMLHttpRequest");for(f in d)void 0!==d[f]&&g.setRequestHeader(f,d[f]+"");g.send(b.hasContent&&b.data||null),c=function(a,d){var f,i,j;if(c&&(d||4===g.readyState))if(delete fc[h],c=void 0,g.onreadystatechange=n.noop,d)4!==g.readyState&&g.abort();else{j={},f=g.status,"string"==typeof g.responseText&&(j.text=g.responseText);try{i=g.statusText}catch(k){i=""}f||!b.isLocal||b.crossDomain?1223===f&&(f=204):f=j.text?200:404}j&&e(f,i,j,g.getAllResponseHeaders())},b.async?4===g.readyState?a.setTimeout(c):g.onreadystatechange=fc[h]=c:c()},abort:function(){c&&c(void 0,!0)}}}});function hc(){try{return new a.XMLHttpRequest}catch(b){}}function ic(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}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",a.global=!1)}),n.ajaxTransport("script",function(a){if(a.crossDomain){var b,c=d.head||n("head")[0]||d.documentElement;return{send:function(e,f){b=d.createElement("script"),b.async=!0,a.scriptCharset&&(b.charset=a.scriptCharset),b.src=a.url,b.onload=b.onreadystatechange=function(a,c){(c||!b.readyState||/loaded|complete/.test(b.readyState))&&(b.onload=b.onreadystatechange=null,b.parentNode&&b.parentNode.removeChild(b),b=null,c||f(200,"success"))},c.insertBefore(b,c.firstChild)},abort:function(){b&&b.onload(void 0,!0)}}}});var jc=[],kc=/(=)\?(?=&|$)|\?\?/;n.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=jc.pop()||n.expando+"_"+Eb++;return this[a]=!0,a}}),n.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(kc.test(b.url)?"url":"string"==typeof b.data&&0===(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&kc.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(kc,"$1"+e):b.jsonp!==!1&&(b.url+=(Fb.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,jc.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=ja([a],b,f),f&&f.length&&n(f).remove(),n.merge([],e.childNodes))};var lc=n.fn.load;n.fn.load=function(a,b,c){if("string"!=typeof a&&lc)return lc.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>-1&&(d=n.trim(a.slice(h,a.length)),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 mc(a){return n.isWindow(a)?a:9===a.nodeType?a.defaultView||a.parentWindow:!1}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)&&n.inArray("auto",[f,i])>-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={top:0,left:0},e=this[0],f=e&&e.ownerDocument;if(f)return b=f.documentElement,n.contains(b,e)?("undefined"!=typeof e.getBoundingClientRect&&(d=e.getBoundingClientRect()),c=mc(f),{top:d.top+(c.pageYOffset||b.scrollTop)-(b.clientTop||0),left:d.left+(c.pageXOffset||b.scrollLeft)-(b.clientLeft||0)}):d},position:function(){if(this[0]){var a,b,c={top:0,left:0},d=this[0];return"fixed"===n.css(d,"position")?b=d.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),n.nodeName(a[0],"html")||(c=a.offset()),c.top+=n.css(a[0],"borderTopWidth",!0),c.left+=n.css(a[0],"borderLeftWidth",!0)),{top:b.top-c.top-n.css(d,"marginTop",!0),left:b.left-c.left-n.css(d,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent;while(a&&!n.nodeName(a,"html")&&"static"===n.css(a,"position"))a=a.offsetParent;return a||Qa})}}),n.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c=/Y/.test(b);n.fn[a]=function(d){return Y(this,function(a,d,e){var f=mc(a);return void 0===e?f?b in f?f[b]:f.document.documentElement[d]:a[d]:void(f?f.scrollTo(c?n(f).scrollLeft():e,c?e:n(f).scrollTop()):a[d]=e)},a,d,arguments.length,null)}}),n.each(["top","left"],function(a,b){n.cssHooks[b]=Ua(l.pixelPosition,function(a,c){return c?(c=Sa(a,b),Oa.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 Y(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)}}),n.fn.size=function(){return this.length},n.fn.andSelf=n.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return n});var nc=a.jQuery,oc=a.$;return n.noConflict=function(b){return a.$===n&&(a.$=oc),b&&a.jQuery===n&&(a.jQuery=nc),n},b||(a.jQuery=a.$=n),n}); - +/*! jQuery v3.6.1 | (c) OpenJS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,y=n.hasOwnProperty,a=y.toString,l=a.call(Object),v={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.1",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0<t&&t-1 in e)}S.fn=S.prototype={jquery:f,constructor:S,length:0,toArray:function(){return s.call(this)},get:function(e){return null==e?s.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=S.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return S.each(this,e)},map:function(n){return this.pushStack(S.map(this,function(e,t){return n.call(e,t,e)}))},slice:function(){return this.pushStack(s.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},even:function(){return this.pushStack(S.grep(this,function(e,t){return(t+1)%2}))},odd:function(){return this.pushStack(S.grep(this,function(e,t){return t%2}))},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(0<=n&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:u,sort:t.sort,splice:t.splice},S.extend=S.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for("boolean"==typeof a&&(l=a,a=arguments[s]||{},s++),"object"==typeof a||m(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(e=arguments[s]))for(t in e)r=e[t],"__proto__"!==t&&a!==r&&(l&&r&&(S.isPlainObject(r)||(i=Array.isArray(r)))?(n=a[t],o=i&&!Array.isArray(n)?[]:i||S.isPlainObject(n)?n:{},i=!1,a[t]=S.extend(l,o,r)):void 0!==r&&(a[t]=r));return a},S.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isPlainObject:function(e){var t,n;return!(!e||"[object Object]"!==o.call(e))&&(!(t=r(e))||"function"==typeof(n=y.call(t,"constructor")&&t.constructor)&&a.call(n)===l)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},globalEval:function(e,t,n){b(e,{nonce:t&&t.nonce},n)},each:function(e,t){var n,r=0;if(p(e)){for(n=e.length;r<n;r++)if(!1===t.call(e[r],r,e[r]))break}else for(r in e)if(!1===t.call(e[r],r,e[r]))break;return e},makeArray:function(e,t){var n=t||[];return null!=e&&(p(Object(e))?S.merge(n,"string"==typeof e?[e]:e):u.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:i.call(t,e,n)},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;r++)e[i++]=t[r];return e.length=i,e},grep:function(e,t,n){for(var r=[],i=0,o=e.length,a=!n;i<o;i++)!t(e[i],i)!==a&&r.push(e[i]);return r},map:function(e,t,n){var r,i,o=0,a=[];if(p(e))for(r=e.length;o<r;o++)null!=(i=t(e[o],o,n))&&a.push(i);else for(o in e)null!=(i=t(e[o],o,n))&&a.push(i);return g(a)},guid:1,support:v}),"function"==typeof Symbol&&(S.fn[Symbol.iterator]=t[Symbol.iterator]),S.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(e,t){n["[object "+t+"]"]=t.toLowerCase()});var d=function(n){var e,d,b,o,i,h,f,g,w,u,l,T,C,a,E,y,s,c,v,S="sizzle"+1*new Date,p=n.document,k=0,r=0,m=ue(),x=ue(),A=ue(),N=ue(),j=function(e,t){return e===t&&(l=!0),0},D={}.hasOwnProperty,t=[],q=t.pop,L=t.push,H=t.push,O=t.slice,P=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},R="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",I="(?:\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+",W="\\["+M+"*("+I+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+I+"))|)"+M+"*\\]",F=":("+I+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+W+")*)|.*)\\)|)",$=new RegExp(M+"+","g"),B=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),_=new RegExp("^"+M+"*,"+M+"*"),z=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&v(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!y||!y.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ve(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ye(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ve(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],y=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="<a id='"+S+"'></a><select id='"+S+"-\r\\' msallowcapture=''><option selected=''></option></select>",e.querySelectorAll("[msallowcapture^='']").length&&y.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||y.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||y.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||y.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||y.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||y.push(".#.+[+~]"),e.querySelectorAll("\\\f"),y.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="<a href='' disabled='disabled'></a><select disabled='disabled'><option/></select>";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&y.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&y.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&y.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),y.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),y=y.length&&new RegExp(y.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),v=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&v(p,e)?-1:t==C||t.ownerDocument==p&&v(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!y||!y.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0<se(t,C,null,[e]).length},se.contains=function(e,t){return(e.ownerDocument||e)!=C&&T(e),v(e,t)},se.attr=function(e,t){(e.ownerDocument||e)!=C&&T(e);var n=b.attrHandle[t.toLowerCase()],r=n&&D.call(b.attrHandle,t.toLowerCase())?n(e,t,!E):void 0;return void 0!==r?r:d.attributes||!E?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},se.escape=function(e){return(e+"").replace(re,ie)},se.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},se.uniqueSort=function(e){var t,n=[],r=0,i=0;if(l=!d.detectDuplicates,u=!d.sortStable&&e.slice(0),e.sort(j),l){while(t=e[i++])t===e[i]&&(r=n.push(i));while(r--)e.splice(n[r],1)}return u=null,e},o=se.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else while(t=e[r++])n+=o(t);return n},(b=se.selectors={cacheLength:50,createPseudo:le,match:G,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1<t.indexOf(i):"$="===r?i&&t.slice(-i.length)===i:"~="===r?-1<(" "+t.replace($," ")+" ").indexOf(i):"|="===r&&(t===i||t.slice(0,i.length+1)===i+"-"))}},CHILD:function(h,e,t,g,y){var v="nth"!==h.slice(0,3),m="last"!==h.slice(-4),x="of-type"===e;return 1===g&&0===y?function(e){return!!e.parentNode}:function(e,t,n){var r,i,o,a,s,u,l=v!==m?"nextSibling":"previousSibling",c=e.parentNode,f=x&&e.nodeName.toLowerCase(),p=!n&&!x,d=!1;if(c){if(v){while(l){a=e;while(a=a[l])if(x?a.nodeName.toLowerCase()===f:1===a.nodeType)return!1;u=l="only"===h&&!u&&"nextSibling"}return!0}if(u=[m?c.firstChild:c.lastChild],m&&p){d=(s=(r=(i=(o=(a=c)[S]||(a[S]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]||[])[0]===k&&r[1])&&r[2],a=s&&c.childNodes[s];while(a=++s&&a&&a[l]||(d=s=0)||u.pop())if(1===a.nodeType&&++d&&a===e){i[h]=[k,s,d];break}}else if(p&&(d=s=(r=(i=(o=(a=e)[S]||(a[S]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]||[])[0]===k&&r[1]),!1===d)while(a=++s&&a&&a[l]||(d=s=0)||u.pop())if((x?a.nodeName.toLowerCase()===f:1===a.nodeType)&&++d&&(p&&((i=(o=a[S]||(a[S]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]=[k,d]),a===e))break;return(d-=y)===g||d%g==0&&0<=d/g}}},PSEUDO:function(e,o){var t,a=b.pseudos[e]||b.setFilters[e.toLowerCase()]||se.error("unsupported pseudo: "+e);return a[S]?a(o):1<a.length?(t=[e,e,"",o],b.setFilters.hasOwnProperty(e.toLowerCase())?le(function(e,t){var n,r=a(e,o),i=r.length;while(i--)e[n=P(e,r[i])]=!(t[n]=r[i])}):function(e){return a(e,0,t)}):a}},pseudos:{not:le(function(e){var r=[],i=[],s=f(e.replace(B,"$1"));return s[S]?le(function(e,t,n,r){var i,o=s(e,null,r,[]),a=e.length;while(a--)(i=o[a])&&(e[a]=!(t[a]=i))}):function(e,t,n){return r[0]=e,s(r,null,n,i),r[0]=null,!i.pop()}}),has:le(function(t){return function(e){return 0<se(t,e).length}}),contains:le(function(t){return t=t.replace(te,ne),function(e){return-1<(e.textContent||o(e)).indexOf(t)}}),lang:le(function(n){return V.test(n||"")||se.error("unsupported lang: "+n),n=n.replace(te,ne).toLowerCase(),function(e){var t;do{if(t=E?e.lang:e.getAttribute("xml:lang")||e.getAttribute("lang"))return(t=t.toLowerCase())===n||0===t.indexOf(n+"-")}while((e=e.parentNode)&&1===e.nodeType);return!1}}),target:function(e){var t=n.location&&n.location.hash;return t&&t.slice(1)===e.id},root:function(e){return e===a},focus:function(e){return e===C.activeElement&&(!C.hasFocus||C.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:ge(!1),disabled:ge(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!b.pseudos.empty(e)},header:function(e){return J.test(e.nodeName)},input:function(e){return Q.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:ye(function(){return[0]}),last:ye(function(e,t){return[t-1]}),eq:ye(function(e,t,n){return[n<0?n+t:n]}),even:ye(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:ye(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:ye(function(e,t,n){for(var r=n<0?n+t:t<n?t:n;0<=--r;)e.push(r);return e}),gt:ye(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}}).pseudos.nth=b.pseudos.eq,{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})b.pseudos[e]=de(e);for(e in{submit:!0,reset:!0})b.pseudos[e]=he(e);function me(){}function xe(e){for(var t=0,n=e.length,r="";t<n;t++)r+=e[t].value;return r}function be(s,e,t){var u=e.dir,l=e.next,c=l||u,f=t&&"parentNode"===c,p=r++;return e.first?function(e,t,n){while(e=e[u])if(1===e.nodeType||f)return s(e,t,n);return!1}:function(e,t,n){var r,i,o,a=[k,p];if(n){while(e=e[u])if((1===e.nodeType||f)&&s(e,t,n))return!0}else while(e=e[u])if(1===e.nodeType||f)if(i=(o=e[S]||(e[S]={}))[e.uniqueID]||(o[e.uniqueID]={}),l&&l===e.nodeName.toLowerCase())e=e[u]||e;else{if((r=i[c])&&r[0]===k&&r[1]===p)return a[2]=r[2];if((i[c]=a)[2]=s(e,t,n))return!0}return!1}}function we(i){return 1<i.length?function(e,t,n){var r=i.length;while(r--)if(!i[r](e,t,n))return!1;return!0}:i[0]}function Te(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;s<u;s++)(o=e[s])&&(n&&!n(o,r,i)||(a.push(o),l&&t.push(s)));return a}function Ce(d,h,g,y,v,e){return y&&!y[S]&&(y=Ce(y)),v&&!v[S]&&(v=Ce(v,e)),le(function(e,t,n,r){var i,o,a,s=[],u=[],l=t.length,c=e||function(e,t,n){for(var r=0,i=t.length;r<i;r++)se(e,t[r],n);return n}(h||"*",n.nodeType?[n]:n,[]),f=!d||!e&&h?c:Te(c,s,d,n,r),p=g?v||(e?d:l||y)?[]:t:f;if(g&&g(f,p,n,r),y){i=Te(p,u),y(i,[],n,r),o=i.length;while(o--)(a=i[o])&&(p[u[o]]=!(f[u[o]]=a))}if(e){if(v||d){if(v){i=[],o=p.length;while(o--)(a=p[o])&&i.push(f[o]=a);v(null,p=[],i,r)}o=p.length;while(o--)(a=p[o])&&-1<(i=v?P(e,a):s[o])&&(e[i]=!(t[i]=a))}}else p=Te(p===t?p.splice(l,p.length):p),v?v(null,t,p,r):H.apply(t,p)})}function Ee(e){for(var i,t,n,r=e.length,o=b.relative[e[0].type],a=o||b.relative[" "],s=o?1:0,u=be(function(e){return e===i},a,!0),l=be(function(e){return-1<P(i,e)},a,!0),c=[function(e,t,n){var r=!o&&(n||t!==w)||((i=t).nodeType?u(e,t,n):l(e,t,n));return i=null,r}];s<r;s++)if(t=b.relative[e[s].type])c=[be(we(c),t)];else{if((t=b.filter[e[s].type].apply(null,e[s].matches))[S]){for(n=++s;n<r;n++)if(b.relative[e[n].type])break;return Ce(1<s&&we(c),1<s&&xe(e.slice(0,s-1).concat({value:" "===e[s-2].type?"*":""})).replace(B,"$1"),t,s<n&&Ee(e.slice(s,n)),n<r&&Ee(e=e.slice(n)),n<r&&xe(e))}c.push(t)}return we(c)}return me.prototype=b.filters=b.pseudos,b.setFilters=new me,h=se.tokenize=function(e,t){var n,r,i,o,a,s,u,l=x[e+" "];if(l)return t?0:l.slice(0);a=e,s=[],u=b.preFilter;while(a){for(o in n&&!(r=_.exec(a))||(r&&(a=a.slice(r[0].length)||a),s.push(i=[])),n=!1,(r=z.exec(a))&&(n=r.shift(),i.push({value:n,type:r[0].replace(B," ")}),a=a.slice(n.length)),b.filter)!(r=G[o].exec(a))||u[o]&&!(r=u[o](r))||(n=r.shift(),i.push({value:n,type:o,matches:r}),a=a.slice(n.length));if(!n)break}return t?a.length:a?se.error(e):x(e,s).slice(0)},f=se.compile=function(e,t){var n,y,v,m,x,r,i=[],o=[],a=A[e+" "];if(!a){t||(t=h(e)),n=t.length;while(n--)(a=Ee(t[n]))[S]?i.push(a):o.push(a);(a=A(e,(y=o,m=0<(v=i).length,x=0<y.length,r=function(e,t,n,r,i){var o,a,s,u=0,l="0",c=e&&[],f=[],p=w,d=e||x&&b.find.TAG("*",i),h=k+=null==p?1:Math.random()||.1,g=d.length;for(i&&(w=t==C||t||i);l!==g&&null!=(o=d[l]);l++){if(x&&o){a=0,t||o.ownerDocument==C||(T(o),n=!E);while(s=y[a++])if(s(o,t||C,n)){r.push(o);break}i&&(k=h)}m&&((o=!s&&o)&&u--,e&&c.push(o))}if(u+=l,m&&l!==u){a=0;while(s=v[a++])s(c,f,t,n);if(e){if(0<u)while(l--)c[l]||f[l]||(f[l]=q.call(r));f=Te(f)}H.apply(r,f),i&&!e&&0<f.length&&1<u+v.length&&se.uniqueSort(r)}return i&&(k=h,w=p),c},m?le(r):r))).selector=e}return a},g=se.select=function(e,t,n,r){var i,o,a,s,u,l="function"==typeof e&&e,c=!r&&h(e=l.selector||e);if(n=n||[],1===c.length){if(2<(o=c[0]=c[0].slice(0)).length&&"ID"===(a=o[0]).type&&9===t.nodeType&&E&&b.relative[o[1].type]){if(!(t=(b.find.ID(a.matches[0].replace(te,ne),t)||[])[0]))return n;l&&(t=t.parentNode),e=e.slice(o.shift().value.length)}i=G.needsContext.test(e)?0:o.length;while(i--){if(a=o[i],b.relative[s=a.type])break;if((u=b.find[s])&&(r=u(a.matches[0].replace(te,ne),ee.test(o[0].type)&&ve(t.parentNode)||t))){if(o.splice(i,1),!(e=r.length&&xe(o)))return H.apply(n,r),n;break}}}return(l||f(e,c))(r,t,!E,n,!t||ee.test(e)&&ve(t.parentNode)||t),n},d.sortStable=S.split("").sort(j).join("")===S,d.detectDuplicates=!!l,T(),d.sortDetached=ce(function(e){return 1&e.compareDocumentPosition(C.createElement("fieldset"))}),ce(function(e){return e.innerHTML="<a href='#'></a>","#"===e.firstChild.getAttribute("href")})||fe("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),d.attributes&&ce(function(e){return e.innerHTML="<input/>",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||fe("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),ce(function(e){return null==e.getAttribute("disabled")})||fe(R,function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),se}(C);S.find=d,S.expr=d.selectors,S.expr[":"]=S.expr.pseudos,S.uniqueSort=S.unique=d.uniqueSort,S.text=d.getText,S.isXMLDoc=d.isXML,S.contains=d.contains,S.escapeSelector=d.escape;var h=function(e,t,n){var r=[],i=void 0!==n;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&S(e).is(n))break;r.push(e)}return r},T=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},k=S.expr.match.needsContext;function A(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var N=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1<i.call(n,e)!==r}):S.filter(n,e,r)}S.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?S.find.matchesSelector(r,e)?[r]:[]:S.find.matches(e,S.grep(t,function(e){return 1===e.nodeType}))},S.fn.extend({find:function(e){var t,n,r=this.length,i=this;if("string"!=typeof e)return this.pushStack(S(e).filter(function(){for(t=0;t<r;t++)if(S.contains(i[t],this))return!0}));for(n=this.pushStack([]),t=0;t<r;t++)S.find(e,i[t],n);return 1<r?S.uniqueSort(n):n},filter:function(e){return this.pushStack(j(this,e||[],!1))},not:function(e){return this.pushStack(j(this,e||[],!0))},is:function(e){return!!j(this,"string"==typeof e&&k.test(e)?S(e):e||[],!1).length}});var D,q=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e<n;e++)if(S.contains(this,t[e]))return!0})},closest:function(e,t){var n,r=0,i=this.length,o=[],a="string"!=typeof e&&S(e);if(!k.test(e))for(;r<i;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(n.nodeType<11&&(a?-1<a.index(n):1===n.nodeType&&S.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(1<o.length?S.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?i.call(S(e),this[0]):i.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(S.uniqueSort(S.merge(this.get(),S(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),S.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return h(e,"parentNode")},parentsUntil:function(e,t,n){return h(e,"parentNode",n)},next:function(e){return O(e,"nextSibling")},prev:function(e){return O(e,"previousSibling")},nextAll:function(e){return h(e,"nextSibling")},prevAll:function(e){return h(e,"previousSibling")},nextUntil:function(e,t,n){return h(e,"nextSibling",n)},prevUntil:function(e,t,n){return h(e,"previousSibling",n)},siblings:function(e){return T((e.parentNode||{}).firstChild,e)},children:function(e){return T(e.firstChild)},contents:function(e){return null!=e.contentDocument&&r(e.contentDocument)?e.contentDocument:(A(e,"template")&&(e=e.content||e),S.merge([],e.childNodes))}},function(r,i){S.fn[r]=function(e,t){var n=S.map(this,i,e);return"Until"!==r.slice(-5)&&(t=e),t&&"string"==typeof t&&(n=S.filter(t,n)),1<this.length&&(H[r]||S.uniqueSort(n),L.test(r)&&n.reverse()),this.pushStack(n)}});var P=/[^\x20\t\r\n\f]+/g;function R(e){return e}function M(e){throw e}function I(e,t,n,r){var i;try{e&&m(i=e.promise)?i.call(e).done(t).fail(n):e&&m(i=e.then)?i.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n.apply(void 0,[e])}}S.Callbacks=function(r){var e,n;r="string"==typeof r?(e=r,n={},S.each(e.match(P)||[],function(e,t){n[t]=!0}),n):S.extend({},r);var i,t,o,a,s=[],u=[],l=-1,c=function(){for(a=a||r.once,o=i=!0;u.length;l=-1){t=u.shift();while(++l<s.length)!1===s[l].apply(t[0],t[1])&&r.stopOnFalse&&(l=s.length,t=!1)}r.memory||(t=!1),i=!1,a&&(s=t?[]:"")},f={add:function(){return s&&(t&&!i&&(l=s.length-1,u.push(t)),function n(e){S.each(e,function(e,t){m(t)?r.unique&&f.has(t)||s.push(t):t&&t.length&&"string"!==w(t)&&n(t)})}(arguments),t&&!i&&c()),this},remove:function(){return S.each(arguments,function(e,t){var n;while(-1<(n=S.inArray(t,s,n)))s.splice(n,1),n<=l&&l--}),this},has:function(e){return e?-1<S.inArray(e,s):0<s.length},empty:function(){return s&&(s=[]),this},disable:function(){return a=u=[],s=t="",this},disabled:function(){return!s},lock:function(){return a=u=[],t||i||(s=t=""),this},locked:function(){return!!a},fireWith:function(e,t){return a||(t=[e,(t=t||[]).slice?t.slice():t],u.push(t),i||c()),this},fire:function(){return f.fireWith(this,arguments),this},fired:function(){return!!o}};return f},S.extend({Deferred:function(e){var o=[["notify","progress",S.Callbacks("memory"),S.Callbacks("memory"),2],["resolve","done",S.Callbacks("once memory"),S.Callbacks("once memory"),0,"resolved"],["reject","fail",S.Callbacks("once memory"),S.Callbacks("once memory"),1,"rejected"]],i="pending",a={state:function(){return i},always:function(){return s.done(arguments).fail(arguments),this},"catch":function(e){return a.then(null,e)},pipe:function(){var i=arguments;return S.Deferred(function(r){S.each(o,function(e,t){var n=m(i[t[4]])&&i[t[4]];s[t[1]](function(){var e=n&&n.apply(this,arguments);e&&m(e.promise)?e.promise().progress(r.notify).done(r.resolve).fail(r.reject):r[t[0]+"With"](this,n?[e]:arguments)})}),i=null}).promise()},then:function(t,n,r){var u=0;function l(i,o,a,s){return function(){var n=this,r=arguments,e=function(){var e,t;if(!(i<u)){if((e=a.apply(n,r))===o.promise())throw new TypeError("Thenable self-resolution");t=e&&("object"==typeof e||"function"==typeof e)&&e.then,m(t)?s?t.call(e,l(u,o,R,s),l(u,o,M,s)):(u++,t.call(e,l(u,o,R,s),l(u,o,M,s),l(u,o,R,o.notifyWith))):(a!==R&&(n=void 0,r=[e]),(s||o.resolveWith)(n,r))}},t=s?e:function(){try{e()}catch(e){S.Deferred.exceptionHook&&S.Deferred.exceptionHook(e,t.stackTrace),u<=i+1&&(a!==M&&(n=void 0,r=[e]),o.rejectWith(n,r))}};i?t():(S.Deferred.getStackHook&&(t.stackTrace=S.Deferred.getStackHook()),C.setTimeout(t))}}return S.Deferred(function(e){o[0][3].add(l(0,e,m(r)?r:R,e.notifyWith)),o[1][3].add(l(0,e,m(t)?t:R)),o[2][3].add(l(0,e,m(n)?n:M))}).promise()},promise:function(e){return null!=e?S.extend(e,a):a}},s={};return S.each(o,function(e,t){var n=t[2],r=t[5];a[t[1]]=n.add,r&&n.add(function(){i=r},o[3-e][2].disable,o[3-e][3].disable,o[0][2].lock,o[0][3].lock),n.add(t[3].fire),s[t[0]]=function(){return s[t[0]+"With"](this===s?void 0:this,arguments),this},s[t[0]+"With"]=n.fireWith}),a.promise(s),e&&e.call(s,s),s},when:function(e){var n=arguments.length,t=n,r=Array(t),i=s.call(arguments),o=S.Deferred(),a=function(t){return function(e){r[t]=this,i[t]=1<arguments.length?s.call(arguments):e,--n||o.resolveWith(r,i)}};if(n<=1&&(I(e,o.done(a(t)).resolve,o.reject,!n),"pending"===o.state()||m(i[t]&&i[t].then)))return o.then();while(t--)I(i[t],a(t),o.reject);return o.promise()}});var W=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;S.Deferred.exceptionHook=function(e,t){C.console&&C.console.warn&&e&&W.test(e.name)&&C.console.warn("jQuery.Deferred exception: "+e.message,e.stack,t)},S.readyException=function(e){C.setTimeout(function(){throw e})};var F=S.Deferred();function $(){E.removeEventListener("DOMContentLoaded",$),C.removeEventListener("load",$),S.ready()}S.fn.ready=function(e){return F.then(e)["catch"](function(e){S.readyException(e)}),this},S.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--S.readyWait:S.isReady)||(S.isReady=!0)!==e&&0<--S.readyWait||F.resolveWith(E,[S])}}),S.ready.then=F.then,"complete"===E.readyState||"loading"!==E.readyState&&!E.documentElement.doScroll?C.setTimeout(S.ready):(E.addEventListener("DOMContentLoaded",$),C.addEventListener("load",$));var B=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if("object"===w(n))for(s in i=!0,n)B(e,t,s,n[s],!0,o,a);else if(void 0!==r&&(i=!0,m(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(S(e),n)})),t))for(;s<u;s++)t(e[s],n,a?r:r.call(e[s],s,t(e[s],n)));return i?e:l?t.call(e):u?t(e[0],n):o},_=/^-ms-/,z=/-([a-z])/g;function U(e,t){return t.toUpperCase()}function X(e){return e.replace(_,"ms-").replace(z,U)}var V=function(e){return 1===e.nodeType||9===e.nodeType||!+e.nodeType};function G(){this.expando=S.expando+G.uid++}G.uid=1,G.prototype={cache:function(e){var t=e[this.expando];return t||(t={},V(e)&&(e.nodeType?e[this.expando]=t:Object.defineProperty(e,this.expando,{value:t,configurable:!0}))),t},set:function(e,t,n){var r,i=this.cache(e);if("string"==typeof t)i[X(t)]=n;else for(r in t)i[X(r)]=t[r];return i},get:function(e,t){return void 0===t?this.cache(e):e[this.expando]&&e[this.expando][X(t)]},access:function(e,t,n){return void 0===t||t&&"string"==typeof t&&void 0===n?this.get(e,t):(this.set(e,t,n),void 0!==n?n:t)},remove:function(e,t){var n,r=e[this.expando];if(void 0!==r){if(void 0!==t){n=(t=Array.isArray(t)?t.map(X):(t=X(t))in r?[t]:t.match(P)||[]).length;while(n--)delete r[t[n]]}(void 0===t||S.isEmptyObject(r))&&(e.nodeType?e[this.expando]=void 0:delete e[this.expando])}},hasData:function(e){var t=e[this.expando];return void 0!==t&&!S.isEmptyObject(t)}};var Y=new G,Q=new G,J=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,K=/[A-Z]/g;function Z(e,t,n){var r,i;if(void 0===n&&1===e.nodeType)if(r="data-"+t.replace(K,"-$&").toLowerCase(),"string"==typeof(n=e.getAttribute(r))){try{n="true"===(i=n)||"false"!==i&&("null"===i?null:i===+i+""?+i:J.test(i)?JSON.parse(i):i)}catch(e){}Q.set(e,t,n)}else n=void 0;return n}S.extend({hasData:function(e){return Q.hasData(e)||Y.hasData(e)},data:function(e,t,n){return Q.access(e,t,n)},removeData:function(e,t){Q.remove(e,t)},_data:function(e,t,n){return Y.access(e,t,n)},_removeData:function(e,t){Y.remove(e,t)}}),S.fn.extend({data:function(n,e){var t,r,i,o=this[0],a=o&&o.attributes;if(void 0===n){if(this.length&&(i=Q.get(o),1===o.nodeType&&!Y.get(o,"hasDataAttrs"))){t=a.length;while(t--)a[t]&&0===(r=a[t].name).indexOf("data-")&&(r=X(r.slice(5)),Z(o,r,i[r]));Y.set(o,"hasDataAttrs",!0)}return i}return"object"==typeof n?this.each(function(){Q.set(this,n)}):B(this,function(e){var t;if(o&&void 0===e)return void 0!==(t=Q.get(o,n))?t:void 0!==(t=Z(o,n))?t:void 0;this.each(function(){Q.set(this,n,e)})},null,e,1<arguments.length,null,!0)},removeData:function(e){return this.each(function(){Q.remove(this,e)})}}),S.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=Y.get(e,t),n&&(!r||Array.isArray(n)?r=Y.access(e,t,S.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=S.queue(e,t),r=n.length,i=n.shift(),o=S._queueHooks(e,t);"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,function(){S.dequeue(e,t)},o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return Y.get(e,n)||Y.access(e,n,{empty:S.Callbacks("once memory").add(function(){Y.remove(e,[t+"queue",n])})})}}),S.fn.extend({queue:function(t,n){var e=2;return"string"!=typeof t&&(n=t,t="fx",e--),arguments.length<e?S.queue(this[0],t):void 0===n?this:this.each(function(){var e=S.queue(this,t,n);S._queueHooks(this,t),"fx"===t&&"inprogress"!==e[0]&&S.dequeue(this,t)})},dequeue:function(e){return this.each(function(){S.dequeue(this,e)})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=S.Deferred(),o=this,a=this.length,s=function(){--r||i.resolveWith(o,[o])};"string"!=typeof e&&(t=e,e=void 0),e=e||"fx";while(a--)(n=Y.get(o[a],e+"queueHooks"))&&n.empty&&(r++,n.empty.add(s));return s(),i.promise(t)}});var ee=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,te=new RegExp("^(?:([+-])=|)("+ee+")([a-z%]*)$","i"),ne=["Top","Right","Bottom","Left"],re=E.documentElement,ie=function(e){return S.contains(e.ownerDocument,e)},oe={composed:!0};re.getRootNode&&(ie=function(e){return S.contains(e.ownerDocument,e)||e.getRootNode(oe)===e.ownerDocument});var ae=function(e,t){return"none"===(e=t||e).style.display||""===e.style.display&&ie(e)&&"none"===S.css(e,"display")};function se(e,t,n,r){var i,o,a=20,s=r?function(){return r.cur()}:function(){return S.css(e,t,"")},u=s(),l=n&&n[3]||(S.cssNumber[t]?"":"px"),c=e.nodeType&&(S.cssNumber[t]||"px"!==l&&+u)&&te.exec(S.css(e,t));if(c&&c[3]!==l){u/=2,l=l||c[3],c=+u||1;while(a--)S.style(e,t,c+l),(1-o)*(1-(o=s()/u||.5))<=0&&(a=0),c/=o;c*=2,S.style(e,t,c+l),n=n||[]}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}var ue={};function le(e,t){for(var n,r,i,o,a,s,u,l=[],c=0,f=e.length;c<f;c++)(r=e[c]).style&&(n=r.style.display,t?("none"===n&&(l[c]=Y.get(r,"display")||null,l[c]||(r.style.display="")),""===r.style.display&&ae(r)&&(l[c]=(u=a=o=void 0,a=(i=r).ownerDocument,s=i.nodeName,(u=ue[s])||(o=a.body.appendChild(a.createElement(s)),u=S.css(o,"display"),o.parentNode.removeChild(o),"none"===u&&(u="block"),ue[s]=u)))):"none"!==n&&(l[c]="none",Y.set(r,"display",n)));for(c=0;c<f;c++)null!=l[c]&&(e[c].style.display=l[c]);return e}S.fn.extend({show:function(){return le(this,!0)},hide:function(){return le(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){ae(this)?S(this).show():S(this).hide()})}});var ce,fe,pe=/^(?:checkbox|radio)$/i,de=/<([a-z][^\/\0>\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),v.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="<textarea>x</textarea>",v.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="<option></option>",v.option=!!ce.lastChild;var ge={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,"",""]};function ye(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ve(e,t){for(var n=0,r=e.length;n<r;n++)Y.set(e[n],"globalEval",!t||Y.get(t[n],"globalEval"))}ge.tbody=ge.tfoot=ge.colgroup=ge.caption=ge.thead,ge.th=ge.td,v.option||(ge.optgroup=ge.option=[1,"<select multiple='multiple'>","</select>"]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d<h;d++)if((o=e[d])||0===o)if("object"===w(o))S.merge(p,o.nodeType?[o]:o);else if(me.test(o)){a=a||f.appendChild(t.createElement("div")),s=(de.exec(o)||["",""])[1].toLowerCase(),u=ge[s]||ge._default,a.innerHTML=u[1]+S.htmlPrefilter(o)+u[2],c=u[0];while(c--)a=a.lastChild;S.merge(p,a.childNodes),(a=f.firstChild).textContent=""}else p.push(t.createTextNode(o));f.textContent="",d=0;while(o=p[d++])if(r&&-1<S.inArray(o,r))i&&i.push(o);else if(l=ie(o),a=ye(f.appendChild(o),"script"),l&&ve(a),n){c=0;while(o=a[c++])he.test(o.type||"")&&n.push(o)}return f}var be=/^([^.]*)(?:\.(.+)|)/;function we(){return!0}function Te(){return!1}function Ce(e,t){return e===function(){try{return E.activeElement}catch(e){}}()==("focus"===t)}function Ee(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"!=typeof n&&(r=r||n,n=void 0),t)Ee(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Te;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return S().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=S.guid++)),e.each(function(){S.event.add(this,t,i,r,n)})}function Se(e,i,o){o?(Y.set(e,i,!1),S.event.add(e,i,{namespace:!1,handler:function(e){var t,n,r=Y.get(this,i);if(1&e.isTrigger&&this[i]){if(r.length)(S.event.special[i]||{}).delegateType&&e.stopPropagation();else if(r=s.call(arguments),Y.set(this,i,r),t=o(this,i),this[i](),r!==(n=Y.get(this,i))||t?Y.set(this,i,!1):n={},r!==n)return e.stopImmediatePropagation(),e.preventDefault(),n&&n.value}else r.length&&(Y.set(this,i,{value:S.event.trigger(S.extend(r[0],S.Event.prototype),r.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===Y.get(e,i)&&S.event.add(e,i,we)}S.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,y=Y.get(t);if(V(t)){n.handler&&(n=(o=n).handler,i=o.selector),i&&S.find.matchesSelector(re,i),n.guid||(n.guid=S.guid++),(u=y.events)||(u=y.events=Object.create(null)),(a=y.handle)||(a=y.handle=function(e){return"undefined"!=typeof S&&S.event.triggered!==e.type?S.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||"").match(P)||[""]).length;while(l--)d=g=(s=be.exec(e[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=S.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=S.event.special[d]||{},c=S.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&S.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(d,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),S.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,y=Y.hasData(e)&&Y.get(e);if(y&&(u=y.events)){l=(t=(t||"").match(P)||[""]).length;while(l--)if(d=g=(s=be.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d){f=S.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,y.handle)||S.removeEvent(e,d,y.handle),delete u[d])}else for(d in u)S.event.remove(e,d+t[l],n,r,!0);S.isEmptyObject(u)&&Y.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=new Array(arguments.length),u=S.event.fix(e),l=(Y.get(this,"events")||Object.create(null))[u.type]||[],c=S.event.special[u.type]||{};for(s[0]=u,t=1;t<arguments.length;t++)s[t]=arguments[t];if(u.delegateTarget=this,!c.preDispatch||!1!==c.preDispatch.call(this,u)){a=S.event.handlers.call(this,u,l),t=0;while((i=a[t++])&&!u.isPropagationStopped()){u.currentTarget=i.elem,n=0;while((o=i.handlers[n++])&&!u.isImmediatePropagationStopped())u.rnamespace&&!1!==o.namespace&&!u.rnamespace.test(o.namespace)||(u.handleObj=o,u.data=o.data,void 0!==(r=((S.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,s))&&!1===(u.result=r)&&(u.preventDefault(),u.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,u),u.result}},handlers:function(e,t){var n,r,i,o,a,s=[],u=t.delegateCount,l=e.target;if(u&&l.nodeType&&!("click"===e.type&&1<=e.button))for(;l!==this;l=l.parentNode||this)if(1===l.nodeType&&("click"!==e.type||!0!==l.disabled)){for(o=[],a={},n=0;n<u;n++)void 0===a[i=(r=t[n]).selector+" "]&&(a[i]=r.needsContext?-1<S(i,this).index(l):S.find(i,this,null,[l]).length),a[i]&&o.push(r);o.length&&s.push({elem:l,handlers:o})}return l=this,u<t.length&&s.push({elem:l,handlers:t.slice(u)}),s},addProp:function(t,e){Object.defineProperty(S.Event.prototype,t,{enumerable:!0,configurable:!0,get:m(e)?function(){if(this.originalEvent)return e(this.originalEvent)}:function(){if(this.originalEvent)return this.originalEvent[t]},set:function(e){Object.defineProperty(this,t,{enumerable:!0,configurable:!0,writable:!0,value:e})}})},fix:function(e){return e[S.expando]?e:new S.Event(e)},special:{load:{noBubble:!0},click:{setup:function(e){var t=this||e;return pe.test(t.type)&&t.click&&A(t,"input")&&Se(t,"click",we),!1},trigger:function(e){var t=this||e;return pe.test(t.type)&&t.click&&A(t,"input")&&Se(t,"click"),!0},_default:function(e){var t=e.target;return pe.test(t.type)&&t.click&&A(t,"input")&&Y.get(t,"click")||A(t,"a")}},beforeunload:{postDispatch:function(e){void 0!==e.result&&e.originalEvent&&(e.originalEvent.returnValue=e.result)}}}},S.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n)},S.Event=function(e,t){if(!(this instanceof S.Event))return new S.Event(e,t);e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||void 0===e.defaultPrevented&&!1===e.returnValue?we:Te,this.target=e.target&&3===e.target.nodeType?e.target.parentNode:e.target,this.currentTarget=e.currentTarget,this.relatedTarget=e.relatedTarget):this.type=e,t&&S.extend(this,t),this.timeStamp=e&&e.timeStamp||Date.now(),this[S.expando]=!0},S.Event.prototype={constructor:S.Event,isDefaultPrevented:Te,isPropagationStopped:Te,isImmediatePropagationStopped:Te,isSimulated:!1,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=we,e&&!this.isSimulated&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=we,e&&!this.isSimulated&&e.stopPropagation()},stopImmediatePropagation:function(){var e=this.originalEvent;this.isImmediatePropagationStopped=we,e&&!this.isSimulated&&e.stopImmediatePropagation(),this.stopPropagation()}},S.each({altKey:!0,bubbles:!0,cancelable:!0,changedTouches:!0,ctrlKey:!0,detail:!0,eventPhase:!0,metaKey:!0,pageX:!0,pageY:!0,shiftKey:!0,view:!0,"char":!0,code:!0,charCode:!0,key:!0,keyCode:!0,button:!0,buttons:!0,clientX:!0,clientY:!0,offsetX:!0,offsetY:!0,pointerId:!0,pointerType:!0,screenX:!0,screenY:!0,targetTouches:!0,toElement:!0,touches:!0,which:!0},S.event.addProp),S.each({focus:"focusin",blur:"focusout"},function(t,e){S.event.special[t]={setup:function(){return Se(this,t,Ce),!1},trigger:function(){return Se(this,t),!0},_default:function(e){return Y.get(e.target,t)},delegateType:e}}),S.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(e,i){S.event.special[e]={delegateType:i,bindType:i,handle:function(e){var t,n=e.relatedTarget,r=e.handleObj;return n&&(n===this||S.contains(this,n))||(e.type=r.origType,t=r.handler.apply(this,arguments),e.type=i),t}}}),S.fn.extend({on:function(e,t,n,r){return Ee(this,e,t,n,r)},one:function(e,t,n,r){return Ee(this,e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,S(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return!1!==t&&"function"!=typeof t||(n=t,t=void 0),!1===n&&(n=Te),this.each(function(){S.event.remove(this,e,n,t)})}});var ke=/<script|<style|<link/i,Ae=/checked\s*(?:[^=]|=\s*.checked.)/i,Ne=/^\s*<!\[CDATA\[|\]\]>\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n<r;n++)S.event.add(t,i,s[i][n]);Q.hasData(e)&&(o=Q.access(e),a=S.extend({},o),Q.set(t,a))}}function He(n,r,i,o){r=g(r);var e,t,a,s,u,l,c=0,f=n.length,p=f-1,d=r[0],h=m(d);if(h||1<f&&"string"==typeof d&&!v.checkClone&&Ae.test(d))return n.each(function(e){var t=n.eq(e);h&&(r[0]=d.call(this,e,t.html())),He(t,r,i,o)});if(f&&(t=(e=xe(r,n[0].ownerDocument,!1,n,o)).firstChild,1===e.childNodes.length&&(e=t),t||o)){for(s=(a=S.map(ye(e,"script"),De)).length;c<f;c++)u=e,c!==p&&(u=S.clone(u,!0,!0),s&&S.merge(a,ye(u,"script"))),i.call(n[c],u,c);if(s)for(l=a[a.length-1].ownerDocument,S.map(a,qe),c=0;c<s;c++)u=a[c],he.test(u.type||"")&&!Y.access(u,"globalEval")&&S.contains(l,u)&&(u.src&&"module"!==(u.type||"").toLowerCase()?S._evalUrl&&!u.noModule&&S._evalUrl(u.src,{nonce:u.nonce||u.getAttribute("nonce")},l):b(u.textContent.replace(Ne,""),u,l))}return n}function Oe(e,t,n){for(var r,i=t?S.filter(t,e):e,o=0;null!=(r=i[o]);o++)n||1!==r.nodeType||S.cleanData(ye(r)),r.parentNode&&(n&&ie(r)&&ve(ye(r,"script")),r.parentNode.removeChild(r));return e}S.extend({htmlPrefilter:function(e){return e},clone:function(e,t,n){var r,i,o,a,s,u,l,c=e.cloneNode(!0),f=ie(e);if(!(v.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||S.isXMLDoc(e)))for(a=ye(c),r=0,i=(o=ye(e)).length;r<i;r++)s=o[r],u=a[r],void 0,"input"===(l=u.nodeName.toLowerCase())&&pe.test(s.type)?u.checked=s.checked:"input"!==l&&"textarea"!==l||(u.defaultValue=s.defaultValue);if(t)if(n)for(o=o||ye(e),a=a||ye(c),r=0,i=o.length;r<i;r++)Le(o[r],a[r]);else Le(e,c);return 0<(a=ye(c,"script")).length&&ve(a,!f&&ye(e,"script")),c},cleanData:function(e){for(var t,n,r,i=S.event.special,o=0;void 0!==(n=e[o]);o++)if(V(n)){if(t=n[Y.expando]){if(t.events)for(r in t.events)i[r]?S.event.remove(n,r):S.removeEvent(n,r,t.handle);n[Y.expando]=void 0}n[Q.expando]&&(n[Q.expando]=void 0)}}}),S.fn.extend({detach:function(e){return Oe(this,e,!0)},remove:function(e){return Oe(this,e)},text:function(e){return B(this,function(e){return void 0===e?S.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return He(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||je(this,e).appendChild(e)})},prepend:function(){return He(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=je(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return He(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return He(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(S.cleanData(ye(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return S.clone(this,e,t)})},html:function(e){return B(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!ke.test(e)&&!ge[(de.exec(e)||["",""])[1].toLowerCase()]){e=S.htmlPrefilter(e);try{for(;n<r;n++)1===(t=this[n]||{}).nodeType&&(S.cleanData(ye(t,!1)),t.innerHTML=e);t=0}catch(e){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var n=[];return He(this,arguments,function(e){var t=this.parentNode;S.inArray(this,n)<0&&(S.cleanData(ye(this)),t&&t.replaceChild(e,this))},n)}}),S.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,a){S.fn[e]=function(e){for(var t,n=[],r=S(e),i=r.length-1,o=0;o<=i;o++)t=o===i?this:this.clone(!0),S(r[o])[a](t),u.apply(n,t.get());return this.pushStack(n)}});var Pe=new RegExp("^("+ee+")(?!px)[a-z%]+$","i"),Re=/^--/,Me=function(e){var t=e.ownerDocument.defaultView;return t&&t.opener||(t=C),t.getComputedStyle(e)},Ie=function(e,t,n){var r,i,o={};for(i in t)o[i]=e.style[i],e.style[i]=t[i];for(i in r=n.call(e),t)e.style[i]=o[i];return r},We=new RegExp(ne.join("|"),"i"),Fe="[\\x20\\t\\r\\n\\f]",$e=new RegExp("^"+Fe+"+|((?:^|[^\\\\])(?:\\\\.)*)"+Fe+"+$","g");function Be(e,t,n){var r,i,o,a,s=Re.test(t),u=e.style;return(n=n||Me(e))&&(a=n.getPropertyValue(t)||n[t],s&&(a=a.replace($e,"$1")),""!==a||ie(e)||(a=S.style(e,t)),!v.pixelBoxStyles()&&Pe.test(a)&&We.test(t)&&(r=u.width,i=u.minWidth,o=u.maxWidth,u.minWidth=u.maxWidth=u.width=a,a=n.width,u.width=r,u.minWidth=i,u.maxWidth=o)),void 0!==a?a+"":a}function _e(e,t){return{get:function(){if(!e())return(this.get=t).apply(this,arguments);delete this.get}}}!function(){function e(){if(l){u.style.cssText="position:absolute;left:-11111px;width:60px;margin-top:1px;padding:0;border:0",l.style.cssText="position:relative;display:block;box-sizing:border-box;overflow:scroll;margin:auto;border:1px;padding:1px;width:60%;top:1%",re.appendChild(u).appendChild(l);var e=C.getComputedStyle(l);n="1%"!==e.top,s=12===t(e.marginLeft),l.style.right="60%",o=36===t(e.right),r=36===t(e.width),l.style.position="absolute",i=12===t(l.offsetWidth/3),re.removeChild(u),l=null}}function t(e){return Math.round(parseFloat(e))}var n,r,i,o,a,s,u=E.createElement("div"),l=E.createElement("div");l.style&&(l.style.backgroundClip="content-box",l.cloneNode(!0).style.backgroundClip="",v.clearCloneStyle="content-box"===l.style.backgroundClip,S.extend(v,{boxSizingReliable:function(){return e(),r},pixelBoxStyles:function(){return e(),o},pixelPosition:function(){return e(),n},reliableMarginLeft:function(){return e(),s},scrollboxSize:function(){return e(),i},reliableTrDimensions:function(){var e,t,n,r;return null==a&&(e=E.createElement("table"),t=E.createElement("tr"),n=E.createElement("div"),e.style.cssText="position:absolute;left:-11111px;border-collapse:separate",t.style.cssText="border:1px solid",t.style.height="1px",n.style.height="9px",n.style.display="block",re.appendChild(e).appendChild(t).appendChild(n),r=C.getComputedStyle(t),a=parseInt(r.height,10)+parseInt(r.borderTopWidth,10)+parseInt(r.borderBottomWidth,10)===t.offsetHeight,re.removeChild(e)),a}}))}();var ze=["Webkit","Moz","ms"],Ue=E.createElement("div").style,Xe={};function Ve(e){var t=S.cssProps[e]||Xe[e];return t||(e in Ue?e:Xe[e]=function(e){var t=e[0].toUpperCase()+e.slice(1),n=ze.length;while(n--)if((e=ze[n]+t)in Ue)return e}(e)||e)}var Ge=/^(none|table(?!-c[ea]).+)/,Ye={position:"absolute",visibility:"hidden",display:"block"},Qe={letterSpacing:"0",fontWeight:"400"};function Je(e,t,n){var r=te.exec(t);return r?Math.max(0,r[2]-(n||0))+(r[3]||"px"):t}function Ke(e,t,n,r,i,o){var a="width"===t?1:0,s=0,u=0;if(n===(r?"border":"content"))return 0;for(;a<4;a+=2)"margin"===n&&(u+=S.css(e,n+ne[a],!0,i)),r?("content"===n&&(u-=S.css(e,"padding"+ne[a],!0,i)),"margin"!==n&&(u-=S.css(e,"border"+ne[a]+"Width",!0,i))):(u+=S.css(e,"padding"+ne[a],!0,i),"padding"!==n?u+=S.css(e,"border"+ne[a]+"Width",!0,i):s+=S.css(e,"border"+ne[a]+"Width",!0,i));return!r&&0<=o&&(u+=Math.max(0,Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-o-u-s-.5))||0),u}function Ze(e,t,n){var r=Me(e),i=(!v.boxSizingReliable()||n)&&"border-box"===S.css(e,"boxSizing",!1,r),o=i,a=Be(e,t,r),s="offset"+t[0].toUpperCase()+t.slice(1);if(Pe.test(a)){if(!n)return a;a="auto"}return(!v.boxSizingReliable()&&i||!v.reliableTrDimensions()&&A(e,"tr")||"auto"===a||!parseFloat(a)&&"inline"===S.css(e,"display",!1,r))&&e.getClientRects().length&&(i="border-box"===S.css(e,"boxSizing",!1,r),(o=s in e)&&(a=e[s])),(a=parseFloat(a)||0)+Ke(e,t,n||(i?"border":"content"),o,r,a)+"px"}function et(e,t,n,r,i){return new et.prototype.init(e,t,n,r,i)}S.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Be(e,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,gridArea:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnStart:!0,gridRow:!0,gridRowEnd:!0,gridRowStart:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=X(t),u=Re.test(t),l=e.style;if(u||(t=Ve(s)),a=S.cssHooks[t]||S.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];"string"===(o=typeof n)&&(i=te.exec(n))&&i[1]&&(n=se(e,t,i),o="number"),null!=n&&n==n&&("number"!==o||u||(n+=i&&i[3]||(S.cssNumber[s]?"":"px")),v.clearCloneStyle||""!==n||0!==t.indexOf("background")||(l[t]="inherit"),a&&"set"in a&&void 0===(n=a.set(e,n,r))||(u?l.setProperty(t,n):l[t]=n))}},css:function(e,t,n,r){var i,o,a,s=X(t);return Re.test(t)||(t=Ve(s)),(a=S.cssHooks[t]||S.cssHooks[s])&&"get"in a&&(i=a.get(e,!0,n)),void 0===i&&(i=Be(e,t,r)),"normal"===i&&t in Qe&&(i=Qe[t]),""===n||n?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),S.each(["height","width"],function(e,u){S.cssHooks[u]={get:function(e,t,n){if(t)return!Ge.test(S.css(e,"display"))||e.getClientRects().length&&e.getBoundingClientRect().width?Ze(e,u,n):Ie(e,Ye,function(){return Ze(e,u,n)})},set:function(e,t,n){var r,i=Me(e),o=!v.scrollboxSize()&&"absolute"===i.position,a=(o||n)&&"border-box"===S.css(e,"boxSizing",!1,i),s=n?Ke(e,u,n,a,i):0;return a&&o&&(s-=Math.ceil(e["offset"+u[0].toUpperCase()+u.slice(1)]-parseFloat(i[u])-Ke(e,u,"border",!1,i)-.5)),s&&(r=te.exec(t))&&"px"!==(r[3]||"px")&&(e.style[u]=t,t=S.css(e,u)),Je(0,t,s)}}}),S.cssHooks.marginLeft=_e(v.reliableMarginLeft,function(e,t){if(t)return(parseFloat(Be(e,"marginLeft"))||e.getBoundingClientRect().left-Ie(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}))+"px"}),S.each({margin:"",padding:"",border:"Width"},function(i,o){S.cssHooks[i+o]={expand:function(e){for(var t=0,n={},r="string"==typeof e?e.split(" "):[e];t<4;t++)n[i+ne[t]+o]=r[t]||r[t-2]||r[0];return n}},"margin"!==i&&(S.cssHooks[i+o].set=Je)}),S.fn.extend({css:function(e,t){return B(this,function(e,t,n){var r,i,o={},a=0;if(Array.isArray(t)){for(r=Me(e),i=t.length;a<i;a++)o[t[a]]=S.css(e,t[a],!1,r);return o}return void 0!==n?S.style(e,t,n):S.css(e,t)},e,t,1<arguments.length)}}),((S.Tween=et).prototype={constructor:et,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||S.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(S.cssNumber[n]?"":"px")},cur:function(){var e=et.propHooks[this.prop];return e&&e.get?e.get(this):et.propHooks._default.get(this)},run:function(e){var t,n=et.propHooks[this.prop];return this.options.duration?this.pos=t=S.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):et.propHooks._default.set(this),this}}).init.prototype=et.prototype,(et.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=S.css(e.elem,e.prop,""))&&"auto"!==t?t:0},set:function(e){S.fx.step[e.prop]?S.fx.step[e.prop](e):1!==e.elem.nodeType||!S.cssHooks[e.prop]&&null==e.elem.style[Ve(e.prop)]?e.elem[e.prop]=e.now:S.style(e.elem,e.prop,e.now+e.unit)}}}).scrollTop=et.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},S.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},S.fx=et.prototype.init,S.fx.step={};var tt,nt,rt,it,ot=/^(?:toggle|show|hide)$/,at=/queueHooks$/;function st(){nt&&(!1===E.hidden&&C.requestAnimationFrame?C.requestAnimationFrame(st):C.setTimeout(st,S.fx.interval),S.fx.tick())}function ut(){return C.setTimeout(function(){tt=void 0}),tt=Date.now()}function lt(e,t){var n,r=0,i={height:e};for(t=t?1:0;r<4;r+=2-t)i["margin"+(n=ne[r])]=i["padding"+n]=e;return t&&(i.opacity=i.width=e),i}function ct(e,t,n){for(var r,i=(ft.tweeners[t]||[]).concat(ft.tweeners["*"]),o=0,a=i.length;o<a;o++)if(r=i[o].call(n,t,e))return r}function ft(o,e,t){var n,a,r=0,i=ft.prefilters.length,s=S.Deferred().always(function(){delete u.elem}),u=function(){if(a)return!1;for(var e=tt||ut(),t=Math.max(0,l.startTime+l.duration-e),n=1-(t/l.duration||0),r=0,i=l.tweens.length;r<i;r++)l.tweens[r].run(n);return s.notifyWith(o,[l,n,t]),n<1&&i?t:(i||s.notifyWith(o,[l,1,0]),s.resolveWith(o,[l]),!1)},l=s.promise({elem:o,props:S.extend({},e),opts:S.extend(!0,{specialEasing:{},easing:S.easing._default},t),originalProperties:e,originalOptions:t,startTime:tt||ut(),duration:t.duration,tweens:[],createTween:function(e,t){var n=S.Tween(o,l.opts,e,t,l.opts.specialEasing[e]||l.opts.easing);return l.tweens.push(n),n},stop:function(e){var t=0,n=e?l.tweens.length:0;if(a)return this;for(a=!0;t<n;t++)l.tweens[t].run(1);return e?(s.notifyWith(o,[l,1,0]),s.resolveWith(o,[l,e])):s.rejectWith(o,[l,e]),this}}),c=l.props;for(!function(e,t){var n,r,i,o,a;for(n in e)if(i=t[r=X(n)],o=e[n],Array.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),(a=S.cssHooks[r])&&"expand"in a)for(n in o=a.expand(o),delete e[r],o)n in e||(e[n]=o[n],t[n]=i);else t[r]=i}(c,l.opts.specialEasing);r<i;r++)if(n=ft.prefilters[r].call(l,o,c,l.opts))return m(n.stop)&&(S._queueHooks(l.elem,l.opts.queue).stop=n.stop.bind(n)),n;return S.map(c,ct,l),m(l.opts.start)&&l.opts.start.call(o,l),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always),S.fx.timer(S.extend(u,{elem:o,anim:l,queue:l.opts.queue})),l}S.Animation=S.extend(ft,{tweeners:{"*":[function(e,t){var n=this.createTween(e,t);return se(n.elem,e,te.exec(t),n),n}]},tweener:function(e,t){m(e)?(t=e,e=["*"]):e=e.match(P);for(var n,r=0,i=e.length;r<i;r++)n=e[r],ft.tweeners[n]=ft.tweeners[n]||[],ft.tweeners[n].unshift(t)},prefilters:[function(e,t,n){var r,i,o,a,s,u,l,c,f="width"in t||"height"in t,p=this,d={},h=e.style,g=e.nodeType&&ae(e),y=Y.get(e,"fxshow");for(r in n.queue||(null==(a=S._queueHooks(e,"fx")).unqueued&&(a.unqueued=0,s=a.empty.fire,a.empty.fire=function(){a.unqueued||s()}),a.unqueued++,p.always(function(){p.always(function(){a.unqueued--,S.queue(e,"fx").length||a.empty.fire()})})),t)if(i=t[r],ot.test(i)){if(delete t[r],o=o||"toggle"===i,i===(g?"hide":"show")){if("show"!==i||!y||void 0===y[r])continue;g=!0}d[r]=y&&y[r]||S.style(e,r)}if((u=!S.isEmptyObject(t))||!S.isEmptyObject(d))for(r in f&&1===e.nodeType&&(n.overflow=[h.overflow,h.overflowX,h.overflowY],null==(l=y&&y.display)&&(l=Y.get(e,"display")),"none"===(c=S.css(e,"display"))&&(l?c=l:(le([e],!0),l=e.style.display||l,c=S.css(e,"display"),le([e]))),("inline"===c||"inline-block"===c&&null!=l)&&"none"===S.css(e,"float")&&(u||(p.done(function(){h.display=l}),null==l&&(c=h.display,l="none"===c?"":c)),h.display="inline-block")),n.overflow&&(h.overflow="hidden",p.always(function(){h.overflow=n.overflow[0],h.overflowX=n.overflow[1],h.overflowY=n.overflow[2]})),u=!1,d)u||(y?"hidden"in y&&(g=y.hidden):y=Y.access(e,"fxshow",{display:l}),o&&(y.hidden=!g),g&&le([e],!0),p.done(function(){for(r in g||le([e]),Y.remove(e,"fxshow"),d)S.style(e,r,d[r])})),u=ct(g?y[r]:0,r,p),r in y||(y[r]=u.start,g&&(u.end=u.start,u.start=0))}],prefilter:function(e,t){t?ft.prefilters.unshift(e):ft.prefilters.push(e)}}),S.speed=function(e,t,n){var r=e&&"object"==typeof e?S.extend({},e):{complete:n||!n&&t||m(e)&&e,duration:e,easing:n&&t||t&&!m(t)&&t};return S.fx.off?r.duration=0:"number"!=typeof r.duration&&(r.duration in S.fx.speeds?r.duration=S.fx.speeds[r.duration]:r.duration=S.fx.speeds._default),null!=r.queue&&!0!==r.queue||(r.queue="fx"),r.old=r.complete,r.complete=function(){m(r.old)&&r.old.call(this),r.queue&&S.dequeue(this,r.queue)},r},S.fn.extend({fadeTo:function(e,t,n,r){return this.filter(ae).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(t,e,n,r){var i=S.isEmptyObject(t),o=S.speed(e,n,r),a=function(){var e=ft(this,S.extend({},t),o);(i||Y.get(this,"finish"))&&e.stop(!0)};return a.finish=a,i||!1===o.queue?this.each(a):this.queue(o.queue,a)},stop:function(i,e,o){var a=function(e){var t=e.stop;delete e.stop,t(o)};return"string"!=typeof i&&(o=e,e=i,i=void 0),e&&this.queue(i||"fx",[]),this.each(function(){var e=!0,t=null!=i&&i+"queueHooks",n=S.timers,r=Y.get(this);if(t)r[t]&&r[t].stop&&a(r[t]);else for(t in r)r[t]&&r[t].stop&&at.test(t)&&a(r[t]);for(t=n.length;t--;)n[t].elem!==this||null!=i&&n[t].queue!==i||(n[t].anim.stop(o),e=!1,n.splice(t,1));!e&&o||S.dequeue(this,i)})},finish:function(a){return!1!==a&&(a=a||"fx"),this.each(function(){var e,t=Y.get(this),n=t[a+"queue"],r=t[a+"queueHooks"],i=S.timers,o=n?n.length:0;for(t.finish=!0,S.queue(this,a,[]),r&&r.stop&&r.stop.call(this,!0),e=i.length;e--;)i[e].elem===this&&i[e].queue===a&&(i[e].anim.stop(!0),i.splice(e,1));for(e=0;e<o;e++)n[e]&&n[e].finish&&n[e].finish.call(this);delete t.finish})}}),S.each(["toggle","show","hide"],function(e,r){var i=S.fn[r];S.fn[r]=function(e,t,n){return null==e||"boolean"==typeof e?i.apply(this,arguments):this.animate(lt(r,!0),e,t,n)}}),S.each({slideDown:lt("show"),slideUp:lt("hide"),slideToggle:lt("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,r){S.fn[e]=function(e,t,n){return this.animate(r,e,t,n)}}),S.timers=[],S.fx.tick=function(){var e,t=0,n=S.timers;for(tt=Date.now();t<n.length;t++)(e=n[t])()||n[t]!==e||n.splice(t--,1);n.length||S.fx.stop(),tt=void 0},S.fx.timer=function(e){S.timers.push(e),S.fx.start()},S.fx.interval=13,S.fx.start=function(){nt||(nt=!0,st())},S.fx.stop=function(){nt=null},S.fx.speeds={slow:600,fast:200,_default:400},S.fn.delay=function(r,e){return r=S.fx&&S.fx.speeds[r]||r,e=e||"fx",this.queue(e,function(e,t){var n=C.setTimeout(e,r);t.stop=function(){C.clearTimeout(n)}})},rt=E.createElement("input"),it=E.createElement("select").appendChild(E.createElement("option")),rt.type="checkbox",v.checkOn=""!==rt.value,v.optSelected=it.selected,(rt=E.createElement("input")).value="t",rt.type="radio",v.radioValue="t"===rt.value;var pt,dt=S.expr.attrHandle;S.fn.extend({attr:function(e,t){return B(this,S.attr,e,t,1<arguments.length)},removeAttr:function(e){return this.each(function(){S.removeAttr(this,e)})}}),S.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return"undefined"==typeof e.getAttribute?S.prop(e,t,n):(1===o&&S.isXMLDoc(e)||(i=S.attrHooks[t.toLowerCase()]||(S.expr.match.bool.test(t)?pt:void 0)),void 0!==n?null===n?void S.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:null==(r=S.find.attr(e,t))?void 0:r)},attrHooks:{type:{set:function(e,t){if(!v.radioValue&&"radio"===t&&A(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(P);if(i&&1===e.nodeType)while(n=i[r++])e.removeAttribute(n)}}),pt={set:function(e,t,n){return!1===t?S.removeAttr(e,n):e.setAttribute(n,n),n}},S.each(S.expr.match.bool.source.match(/\w+/g),function(e,t){var a=dt[t]||S.find.attr;dt[t]=function(e,t,n){var r,i,o=t.toLowerCase();return n||(i=dt[o],dt[o]=r,r=null!=a(e,t,n)?o:null,dt[o]=i),r}});var ht=/^(?:input|select|textarea|button)$/i,gt=/^(?:a|area)$/i;function yt(e){return(e.match(P)||[]).join(" ")}function vt(e){return e.getAttribute&&e.getAttribute("class")||""}function mt(e){return Array.isArray(e)?e:"string"==typeof e&&e.match(P)||[]}S.fn.extend({prop:function(e,t){return B(this,S.prop,e,t,1<arguments.length)},removeProp:function(e){return this.each(function(){delete this[S.propFix[e]||e]})}}),S.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&S.isXMLDoc(e)||(t=S.propFix[t]||t,i=S.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=S.find.attr(e,"tabindex");return t?parseInt(t,10):ht.test(e.nodeName)||gt.test(e.nodeName)&&e.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),v.optSelected||(S.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),S.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){S.propFix[this.toLowerCase()]=this}),S.fn.extend({addClass:function(t){var e,n,r,i,o,a;return m(t)?this.each(function(e){S(this).addClass(t.call(this,e,vt(this)))}):(e=mt(t)).length?this.each(function(){if(r=vt(this),n=1===this.nodeType&&" "+yt(r)+" "){for(o=0;o<e.length;o++)i=e[o],n.indexOf(" "+i+" ")<0&&(n+=i+" ");a=yt(n),r!==a&&this.setAttribute("class",a)}}):this},removeClass:function(t){var e,n,r,i,o,a;return m(t)?this.each(function(e){S(this).removeClass(t.call(this,e,vt(this)))}):arguments.length?(e=mt(t)).length?this.each(function(){if(r=vt(this),n=1===this.nodeType&&" "+yt(r)+" "){for(o=0;o<e.length;o++){i=e[o];while(-1<n.indexOf(" "+i+" "))n=n.replace(" "+i+" "," ")}a=yt(n),r!==a&&this.setAttribute("class",a)}}):this:this.attr("class","")},toggleClass:function(t,n){var e,r,i,o,a=typeof t,s="string"===a||Array.isArray(t);return m(t)?this.each(function(e){S(this).toggleClass(t.call(this,e,vt(this),n),n)}):"boolean"==typeof n&&s?n?this.addClass(t):this.removeClass(t):(e=mt(t),this.each(function(){if(s)for(o=S(this),i=0;i<e.length;i++)r=e[i],o.hasClass(r)?o.removeClass(r):o.addClass(r);else void 0!==t&&"boolean"!==a||((r=vt(this))&&Y.set(this,"__className__",r),this.setAttribute&&this.setAttribute("class",r||!1===t?"":Y.get(this,"__className__")||""))}))},hasClass:function(e){var t,n,r=0;t=" "+e+" ";while(n=this[r++])if(1===n.nodeType&&-1<(" "+yt(vt(n))+" ").indexOf(t))return!0;return!1}});var xt=/\r/g;S.fn.extend({val:function(n){var r,e,i,t=this[0];return arguments.length?(i=m(n),this.each(function(e){var t;1===this.nodeType&&(null==(t=i?n.call(this,e,S(this).val()):n)?t="":"number"==typeof t?t+="":Array.isArray(t)&&(t=S.map(t,function(e){return null==e?"":e+""})),(r=S.valHooks[this.type]||S.valHooks[this.nodeName.toLowerCase()])&&"set"in r&&void 0!==r.set(this,t,"value")||(this.value=t))})):t?(r=S.valHooks[t.type]||S.valHooks[t.nodeName.toLowerCase()])&&"get"in r&&void 0!==(e=r.get(t,"value"))?e:"string"==typeof(e=t.value)?e.replace(xt,""):null==e?"":e:void 0}}),S.extend({valHooks:{option:{get:function(e){var t=S.find.attr(e,"value");return null!=t?t:yt(S.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a="select-one"===e.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r<u;r++)if(((n=i[r]).selected||r===o)&&!n.disabled&&(!n.parentNode.disabled||!A(n.parentNode,"optgroup"))){if(t=S(n).val(),a)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=S.makeArray(t),a=i.length;while(a--)((r=i[a]).selected=-1<S.inArray(S.valHooks.option.get(r),o))&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),S.each(["radio","checkbox"],function(){S.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=-1<S.inArray(S(e).val(),t)}},v.checkOn||(S.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})}),v.focusin="onfocusin"in C;var bt=/^(?:focusinfocus|focusoutblur)$/,wt=function(e){e.stopPropagation()};S.extend(S.event,{trigger:function(e,t,n,r){var i,o,a,s,u,l,c,f,p=[n||E],d=y.call(e,"type")?e.type:e,h=y.call(e,"namespace")?e.namespace.split("."):[];if(o=f=a=n=n||E,3!==n.nodeType&&8!==n.nodeType&&!bt.test(d+S.event.triggered)&&(-1<d.indexOf(".")&&(d=(h=d.split(".")).shift(),h.sort()),u=d.indexOf(":")<0&&"on"+d,(e=e[S.expando]?e:new S.Event(d,"object"==typeof e&&e)).isTrigger=r?2:3,e.namespace=h.join("."),e.rnamespace=e.namespace?new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,e.result=void 0,e.target||(e.target=n),t=null==t?[e]:S.makeArray(t,[e]),c=S.event.special[d]||{},r||!c.trigger||!1!==c.trigger.apply(n,t))){if(!r&&!c.noBubble&&!x(n)){for(s=c.delegateType||d,bt.test(s+d)||(o=o.parentNode);o;o=o.parentNode)p.push(o),a=o;a===(n.ownerDocument||E)&&p.push(a.defaultView||a.parentWindow||C)}i=0;while((o=p[i++])&&!e.isPropagationStopped())f=o,e.type=1<i?s:c.bindType||d,(l=(Y.get(o,"events")||Object.create(null))[e.type]&&Y.get(o,"handle"))&&l.apply(o,t),(l=u&&o[u])&&l.apply&&V(o)&&(e.result=l.apply(o,t),!1===e.result&&e.preventDefault());return e.type=d,r||e.isDefaultPrevented()||c._default&&!1!==c._default.apply(p.pop(),t)||!V(n)||u&&m(n[d])&&!x(n)&&((a=n[u])&&(n[u]=null),S.event.triggered=d,e.isPropagationStopped()&&f.addEventListener(d,wt),n[d](),e.isPropagationStopped()&&f.removeEventListener(d,wt),S.event.triggered=void 0,a&&(n[u]=a)),e.result}},simulate:function(e,t,n){var r=S.extend(new S.Event,n,{type:e,isSimulated:!0});S.event.trigger(r,null,t)}}),S.fn.extend({trigger:function(e,t){return this.each(function(){S.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return S.event.trigger(e,t,n,!0)}}),v.focusin||S.each({focus:"focusin",blur:"focusout"},function(n,r){var i=function(e){S.event.simulate(r,e.target,S.event.fix(e))};S.event.special[r]={setup:function(){var e=this.ownerDocument||this.document||this,t=Y.access(e,r);t||e.addEventListener(n,i,!0),Y.access(e,r,(t||0)+1)},teardown:function(){var e=this.ownerDocument||this.document||this,t=Y.access(e,r)-1;t?Y.access(e,r,t):(e.removeEventListener(n,i,!0),Y.remove(e,r))}}});var Tt=C.location,Ct={guid:Date.now()},Et=/\?/;S.parseXML=function(e){var t,n;if(!e||"string"!=typeof e)return null;try{t=(new C.DOMParser).parseFromString(e,"text/xml")}catch(e){}return n=t&&t.getElementsByTagName("parsererror")[0],t&&!n||S.error("Invalid XML: "+(n?S.map(n.childNodes,function(e){return e.textContent}).join("\n"):e)),t};var St=/\[\]$/,kt=/\r?\n/g,At=/^(?:submit|button|image|reset|file)$/i,Nt=/^(?:input|select|textarea|keygen)/i;function jt(n,e,r,i){var t;if(Array.isArray(e))S.each(e,function(e,t){r||St.test(n)?i(n,t):jt(n+"["+("object"==typeof t&&null!=t?e:"")+"]",t,r,i)});else if(r||"object"!==w(e))i(n,e);else for(t in e)jt(n+"["+t+"]",e[t],r,i)}S.param=function(e,t){var n,r=[],i=function(e,t){var n=m(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(null==e)return"";if(Array.isArray(e)||e.jquery&&!S.isPlainObject(e))S.each(e,function(){i(this.name,this.value)});else for(n in e)jt(n,e[n],t,i);return r.join("&")},S.fn.extend({serialize:function(){return S.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=S.prop(this,"elements");return e?S.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!S(this).is(":disabled")&&Nt.test(this.nodeName)&&!At.test(e)&&(this.checked||!pe.test(e))}).map(function(e,t){var n=S(this).val();return null==n?null:Array.isArray(n)?S.map(n,function(e){return{name:t.name,value:e.replace(kt,"\r\n")}}):{name:t.name,value:n.replace(kt,"\r\n")}}).get()}});var Dt=/%20/g,qt=/#.*$/,Lt=/([?&])_=[^&]*/,Ht=/^(.*?):[ \t]*([^\r\n]*)$/gm,Ot=/^(?:GET|HEAD)$/,Pt=/^\/\//,Rt={},Mt={},It="*/".concat("*"),Wt=E.createElement("a");function Ft(o){return function(e,t){"string"!=typeof e&&(t=e,e="*");var n,r=0,i=e.toLowerCase().match(P)||[];if(m(t))while(n=i[r++])"+"===n[0]?(n=n.slice(1)||"*",(o[n]=o[n]||[]).unshift(t)):(o[n]=o[n]||[]).push(t)}}function $t(t,i,o,a){var s={},u=t===Mt;function l(e){var r;return s[e]=!0,S.each(t[e]||[],function(e,t){var n=t(i,o,a);return"string"!=typeof n||u||s[n]?u?!(r=n):void 0:(i.dataTypes.unshift(n),l(n),!1)}),r}return l(i.dataTypes[0])||!s["*"]&&l("*")}function Bt(e,t){var n,r,i=S.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&S.extend(!0,e,r),e}Wt.href=Tt.href,S.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Tt.href,type:"GET",isLocal:/^(?:about|app|app-storage|.+-extension|file|res|widget):$/.test(Tt.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":It,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":S.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?Bt(Bt(e,S.ajaxSettings),t):Bt(S.ajaxSettings,e)},ajaxPrefilter:Ft(Rt),ajaxTransport:Ft(Mt),ajax:function(e,t){"object"==typeof e&&(t=e,e=void 0),t=t||{};var c,f,p,n,d,r,h,g,i,o,y=S.ajaxSetup({},t),v=y.context||y,m=y.context&&(v.nodeType||v.jquery)?S(v):S.event,x=S.Deferred(),b=S.Callbacks("once memory"),w=y.statusCode||{},a={},s={},u="canceled",T={readyState:0,getResponseHeader:function(e){var t;if(h){if(!n){n={};while(t=Ht.exec(p))n[t[1].toLowerCase()+" "]=(n[t[1].toLowerCase()+" "]||[]).concat(t[2])}t=n[e.toLowerCase()+" "]}return null==t?null:t.join(", ")},getAllResponseHeaders:function(){return h?p:null},setRequestHeader:function(e,t){return null==h&&(e=s[e.toLowerCase()]=s[e.toLowerCase()]||e,a[e]=t),this},overrideMimeType:function(e){return null==h&&(y.mimeType=e),this},statusCode:function(e){var t;if(e)if(h)T.always(e[T.status]);else for(t in e)w[t]=[w[t],e[t]];return this},abort:function(e){var t=e||u;return c&&c.abort(t),l(0,t),this}};if(x.promise(T),y.url=((e||y.url||Tt.href)+"").replace(Pt,Tt.protocol+"//"),y.type=t.method||t.type||y.method||y.type,y.dataTypes=(y.dataType||"*").toLowerCase().match(P)||[""],null==y.crossDomain){r=E.createElement("a");try{r.href=y.url,r.href=r.href,y.crossDomain=Wt.protocol+"//"+Wt.host!=r.protocol+"//"+r.host}catch(e){y.crossDomain=!0}}if(y.data&&y.processData&&"string"!=typeof y.data&&(y.data=S.param(y.data,y.traditional)),$t(Rt,y,t,T),h)return T;for(i in(g=S.event&&y.global)&&0==S.active++&&S.event.trigger("ajaxStart"),y.type=y.type.toUpperCase(),y.hasContent=!Ot.test(y.type),f=y.url.replace(qt,""),y.hasContent?y.data&&y.processData&&0===(y.contentType||"").indexOf("application/x-www-form-urlencoded")&&(y.data=y.data.replace(Dt,"+")):(o=y.url.slice(f.length),y.data&&(y.processData||"string"==typeof y.data)&&(f+=(Et.test(f)?"&":"?")+y.data,delete y.data),!1===y.cache&&(f=f.replace(Lt,"$1"),o=(Et.test(f)?"&":"?")+"_="+Ct.guid+++o),y.url=f+o),y.ifModified&&(S.lastModified[f]&&T.setRequestHeader("If-Modified-Since",S.lastModified[f]),S.etag[f]&&T.setRequestHeader("If-None-Match",S.etag[f])),(y.data&&y.hasContent&&!1!==y.contentType||t.contentType)&&T.setRequestHeader("Content-Type",y.contentType),T.setRequestHeader("Accept",y.dataTypes[0]&&y.accepts[y.dataTypes[0]]?y.accepts[y.dataTypes[0]]+("*"!==y.dataTypes[0]?", "+It+"; q=0.01":""):y.accepts["*"]),y.headers)T.setRequestHeader(i,y.headers[i]);if(y.beforeSend&&(!1===y.beforeSend.call(v,T,y)||h))return T.abort();if(u="abort",b.add(y.complete),T.done(y.success),T.fail(y.error),c=$t(Mt,y,t,T)){if(T.readyState=1,g&&m.trigger("ajaxSend",[T,y]),h)return T;y.async&&0<y.timeout&&(d=C.setTimeout(function(){T.abort("timeout")},y.timeout));try{h=!1,c.send(a,l)}catch(e){if(h)throw e;l(-1,e)}}else l(-1,"No Transport");function l(e,t,n,r){var i,o,a,s,u,l=t;h||(h=!0,d&&C.clearTimeout(d),c=void 0,p=r||"",T.readyState=0<e?4:0,i=200<=e&&e<300||304===e,n&&(s=function(e,t,n){var r,i,o,a,s=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader("Content-Type"));if(r)for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+" "+u[0]]){o=i;break}a||(a=i)}o=o||a}if(o)return o!==u[0]&&u.unshift(o),n[o]}(y,T,n)),!i&&-1<S.inArray("script",y.dataTypes)&&S.inArray("json",y.dataTypes)<0&&(y.converters["text script"]=function(){}),s=function(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if("*"===o)o=u;else if("*"!==u&&u!==o){if(!(a=l[u+" "+o]||l["* "+o]))for(i in l)if((s=i.split(" "))[1]===o&&(a=l[u+" "+s[0]]||l["* "+s[0]])){!0===a?a=l[i]:!0!==l[i]&&(o=s[0],c.unshift(s[1]));break}if(!0!==a)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(e){return{state:"parsererror",error:a?e:"No conversion from "+u+" to "+o}}}return{state:"success",data:t}}(y,s,T,i),i?(y.ifModified&&((u=T.getResponseHeader("Last-Modified"))&&(S.lastModified[f]=u),(u=T.getResponseHeader("etag"))&&(S.etag[f]=u)),204===e||"HEAD"===y.type?l="nocontent":304===e?l="notmodified":(l=s.state,o=s.data,i=!(a=s.error))):(a=l,!e&&l||(l="error",e<0&&(e=0))),T.status=e,T.statusText=(t||l)+"",i?x.resolveWith(v,[o,l,T]):x.rejectWith(v,[T,l,a]),T.statusCode(w),w=void 0,g&&m.trigger(i?"ajaxSuccess":"ajaxError",[T,y,i?o:a]),b.fireWith(v,[T,l]),g&&(m.trigger("ajaxComplete",[T,y]),--S.active||S.event.trigger("ajaxStop")))}return T},getJSON:function(e,t,n){return S.get(e,t,n,"json")},getScript:function(e,t){return S.get(e,void 0,t,"script")}}),S.each(["get","post"],function(e,i){S[i]=function(e,t,n,r){return m(t)&&(r=r||n,n=t,t=void 0),S.ajax(S.extend({url:e,type:i,dataType:r,data:t,success:n},S.isPlainObject(e)&&e))}}),S.ajaxPrefilter(function(e){var t;for(t in e.headers)"content-type"===t.toLowerCase()&&(e.contentType=e.headers[t]||"")}),S._evalUrl=function(e,t,n){return S.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,converters:{"text script":function(){}},dataFilter:function(e){S.globalEval(e,t,n)}})},S.fn.extend({wrapAll:function(e){var t;return this[0]&&(m(e)&&(e=e.call(this[0])),t=S(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(n){return m(n)?this.each(function(e){S(this).wrapInner(n.call(this,e))}):this.each(function(){var e=S(this),t=e.contents();t.length?t.wrapAll(n):e.append(n)})},wrap:function(t){var n=m(t);return this.each(function(e){S(this).wrapAll(n?t.call(this,e):t)})},unwrap:function(e){return this.parent(e).not("body").each(function(){S(this).replaceWith(this.childNodes)}),this}}),S.expr.pseudos.hidden=function(e){return!S.expr.pseudos.visible(e)},S.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},S.ajaxSettings.xhr=function(){try{return new C.XMLHttpRequest}catch(e){}};var _t={0:200,1223:204},zt=S.ajaxSettings.xhr();v.cors=!!zt&&"withCredentials"in zt,v.ajax=zt=!!zt,S.ajaxTransport(function(i){var o,a;if(v.cors||zt&&!i.crossDomain)return{send:function(e,t){var n,r=i.xhr();if(r.open(i.type,i.url,i.async,i.username,i.password),i.xhrFields)for(n in i.xhrFields)r[n]=i.xhrFields[n];for(n in i.mimeType&&r.overrideMimeType&&r.overrideMimeType(i.mimeType),i.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest"),e)r.setRequestHeader(n,e[n]);o=function(e){return function(){o&&(o=a=r.onload=r.onerror=r.onabort=r.ontimeout=r.onreadystatechange=null,"abort"===e?r.abort():"error"===e?"number"!=typeof r.status?t(0,"error"):t(r.status,r.statusText):t(_t[r.status]||r.status,r.statusText,"text"!==(r.responseType||"text")||"string"!=typeof r.responseText?{binary:r.response}:{text:r.responseText},r.getAllResponseHeaders()))}},r.onload=o(),a=r.onerror=r.ontimeout=o("error"),void 0!==r.onabort?r.onabort=a:r.onreadystatechange=function(){4===r.readyState&&C.setTimeout(function(){o&&a()})},o=o("abort");try{r.send(i.hasContent&&i.data||null)}catch(e){if(o)throw e}},abort:function(){o&&o()}}}),S.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),S.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return S.globalEval(e),e}}}),S.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),S.ajaxTransport("script",function(n){var r,i;if(n.crossDomain||n.scriptAttrs)return{send:function(e,t){r=S("<script>").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Ut,Xt=[],Vt=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Xt.pop()||S.expando+"_"+Ct.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Vt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Vt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Vt,"$1"+r):!1!==e.jsonp&&(e.url+=(Et.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Xt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),v.createHTMLDocument=((Ut=E.implementation.createHTMLDocument("").body).innerHTML="<form></form><form></form>",2===Ut.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(v.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1<s&&(r=yt(e.slice(s)),e=e.slice(0,s)),m(t)?(n=t,t=void 0):t&&"object"==typeof t&&(i="POST"),0<a.length&&S.ajax({url:e,type:i||"GET",dataType:"html",data:t}).done(function(e){o=arguments,a.html(r?S("<div>").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return B(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=_e(v.pixelPosition,function(e,t){if(t)return t=Be(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return B(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0<arguments.length?this.on(n,null,e,t):this.trigger(n)}});var Gt=/^[\s\uFEFF\xA0]+|([^\s\uFEFF\xA0])[\s\uFEFF\xA0]+$/g;S.proxy=function(e,t){var n,r,i;if("string"==typeof t&&(n=e[t],t=e,e=n),m(e))return r=s.call(arguments,2),(i=function(){return e.apply(t||this,r.concat(s.call(arguments)))}).guid=e.guid=e.guid||S.guid++,i},S.holdReady=function(e){e?S.readyWait++:S.ready(!0)},S.isArray=Array.isArray,S.parseJSON=JSON.parse,S.nodeName=A,S.isFunction=m,S.isWindow=x,S.camelCase=X,S.type=w,S.now=Date.now,S.isNumeric=function(e){var t=S.type(e);return("number"===t||"string"===t)&&!isNaN(e-parseFloat(e))},S.trim=function(e){return null==e?"":(e+"").replace(Gt,"$1")},"function"==typeof define&&define.amd&&define("jquery",[],function(){return S});var Yt=C.jQuery,Qt=C.$;return S.noConflict=function(e){return C.$===S&&(C.$=Qt),e&&C.jQuery===S&&(C.jQuery=Yt),S},"undefined"==typeof e&&(C.jQuery=C.$=S),S}); diff --git a/website/agenda/planung/js/jquery.rte.js b/website/agenda/planung/js/jquery.rte.js deleted file mode 100644 index 4960551..0000000 --- a/website/agenda/planung/js/jquery.rte.js +++ /dev/null @@ -1,211 +0,0 @@ -/* - * jQuery RTE plugin 0.3 - create a rich text form for Mozilla, Opera, and Internet Explorer - * - * Copyright (c) 2007 Batiste Bieler - * Distributed under the GPL (GPL-LICENSE.txt) licenses. - */ - -// define the rte light plugin -jQuery.fn.rte = function(css_url, media_url) { - - if(document.designMode || document.contentEditable) - { - $(this).each( function(){ - var textarea = $(this); - enableDesignMode(textarea); - }); - } - - function formatText(iframe, command, option) { - iframe.contentWindow.focus(); - $('#editor_menu:visible').hide(); - try{ - iframe.contentWindow.document.execCommand(command, false, option); - }catch(e){console.log(e)} - iframe.contentWindow.focus(); - } - - function tryEnableDesignMode(iframe, doc, callback) { - try { - iframe.contentWindow.document.open(); - iframe.contentWindow.document.write(doc); - iframe.contentWindow.document.close(); - } catch(error) { - console.log(error) - } - if (document.contentEditable) { - iframe.contentWindow.document.designMode = "On"; - callback(); - return true; - } - else if (document.designMode != null) { - try { - iframe.contentWindow.document.designMode = "on"; - callback(); - return true; - } catch (error) { - console.log(error) - } - } - setTimeout(function(){tryEnableDesignMode(iframe, doc, callback)}, 250); - return false; - } - - function enableDesignMode(textarea) { - // need to be created this way - var iframe = document.createElement("iframe"); - iframe.frameBorder=0; - iframe.frameMargin=0; - iframe.framePadding=0; - iframe.height=200; - if(textarea.attr('class')) - iframe.className = textarea.attr('class'); - if(textarea.attr('id')) - iframe.id = textarea.attr('id'); - if(textarea.attr('name')) - iframe.title = textarea.attr('name'); - textarea.after(iframe); - var css = ""; - if(css_url) - var css = "<link type='text/css' rel='stylesheet' href='"+css_url+"' />" - var content = textarea.val(); - // Mozilla need this to display caret - if($.trim(content)=='') - content = '<br>'; - var doc = "<html><head>"+css+"</head><body class='frameBody'>"+content+"</body></html>"; - tryEnableDesignMode(iframe, doc, function() { - $("#toolbar-"+iframe.title).remove(); - $(iframe).before(toolbar(iframe)); - textarea.remove(); - }); - } - - function disableDesignMode(iframe, submit) { - var content = iframe.contentWindow.document.getElementsByTagName("body")[0].innerHTML; - if(submit==true) - var textarea = $('<input type="hidden" />'); - else - var textarea = $('<textarea cols="40" rows="10"></textarea>'); - textarea.val(content); - t = textarea.get(0); - if(iframe.className) - t.className = iframe.className; - if(iframe.id) - t.id = iframe.id; - if(iframe.title) - t.name = iframe.title; - $(iframe).before(textarea); - if(submit!=true) - $(iframe).remove(); - return textarea; - } - -/** - <a href='#' class='link'><img src='"+media_url+"link.png' alt='link' /></a>\ - <a href='#' class='image'><img src='"+media_url+"image.png' alt='image' /></a>\ - <a href='#' class='disable'><img src='"+media_url+"close.gif' alt='close rte' /></a>\ - -*/ - function toolbar(iframe) { - - var tb = $("<div class='rte-toolbar' id='toolbar-"+iframe.title+"'><div>\ - <select>\ - <option value=''>Bloc style</option>\ - <option value='p'>Paragraph</option>\ - <option value='h3'>Title</option>\ - </select>\ - <a href='#' class='bold'><img src='"+media_url+"bold.gif' alt='bold' /></a>\ - <a href='#' class='italic'><img src='"+media_url+"italic.gif' alt='italic' /></a>\ - <a href='#' class='unorderedlist'><img src='"+media_url+"unordered.gif' alt='unordered list' /></a>\ - </div></div>"); - $('select', tb).change(function(){ - var index = this.selectedIndex; - if( index!=0 ) { - var selected = this.options[index].value; - formatText(iframe, "formatblock", '<'+selected+'>'); - } - }); - $('.bold', tb).click(function(){ formatText(iframe, 'bold');return false; }); - $('.italic', tb).click(function(){ formatText(iframe, 'italic');return false; }); - $('.unorderedlist', tb).click(function(){ formatText(iframe, 'insertunorderedlist');return false; }); - $('.link', tb).click(function(){ - var p=prompt("URL:"); - if(p) - formatText(iframe, 'CreateLink', p); - return false; }); - $('.image', tb).click(function(){ - var p=prompt("image URL:"); - if(p) - formatText(iframe, 'InsertImage', p); - return false; }); - $('.disable', tb).click(function() { - var txt = disableDesignMode(iframe); - var edm = $('<a href="#">Enable design mode</a>'); - tb.empty().append(edm); - edm.click(function(){ - enableDesignMode(txt); - return false; - }); - return false; - }); - $(iframe).parents('form').submit(function(){ - disableDesignMode(iframe, true); }); - var iframeDoc = $(iframe.contentWindow.document); - - var select = $('select', tb)[0]; - iframeDoc.mouseup(function(){ - setSelectedType(getSelectionElement(iframe), select); - return true; - }); - iframeDoc.keyup(function(){ - setSelectedType(getSelectionElement(iframe), select); - var body = $('body', iframeDoc); - if(body.scrollTop()>0) - iframe.height = Math.min(350, parseInt(iframe.height)+body.scrollTop()); - return true; - }); - - return tb; - } - - function setSelectedType(node, select) { - while(node.parentNode) { - var nName = node.nodeName.toLowerCase(); - for(var i=0;i<select.options.length;i++) { - if(nName==select.options[i].value){ - select.selectedIndex=i; - return true; - } - } - node = node.parentNode; - } - select.selectedIndex=0; - return true; - } - - function getSelectionElement(iframe) { - if (iframe.contentWindow.document.selection) { - // IE selections - selection = iframe.contentWindow.document.selection; - range = selection.createRange(); - try { - node = range.parentElement(); - } - catch (e) { - return false; - } - } else { - // Mozilla selections - try { - selection = iframe.contentWindow.getSelection(); - range = selection.getRangeAt(0); - } - catch(e){ - return false; - } - node = range.commonAncestorContainer; - } - return node; - } -} - diff --git a/website/agenda/planung/js/jquery.tablesorter.min.js b/website/agenda/planung/js/jquery.tablesorter.min.js index e20f011..dac499e 100644 --- a/website/agenda/planung/js/jquery.tablesorter.min.js +++ b/website/agenda/planung/js/jquery.tablesorter.min.js @@ -1,5 +1 @@ -/*! -* TableSorter 2.17.8 min - Client-side table sorting with ease! -* Copyright (c) 2007 Christian Bach -*/ -!function(h){h.extend({tablesorter:new function(){function d(){var b=arguments[0],a=1<arguments.length?Array.prototype.slice.call(arguments):b;if("undefined"!==typeof console&&"undefined"!==typeof console.log)console[/error/i.test(b)?"error":/warn/i.test(b)?"warn":"log"](a);else alert(a)}function q(b,a){d(b+" ("+((new Date).getTime()-a.getTime())+"ms)")}function p(b){for(var a in b)return!1;return!0}function r(b,a,c){if(!a)return"";var f,e=b.config,l=e.textExtraction||"",d="",d="basic"===l?h(a).attr(e.textAttribute)|| a.textContent||a.innerText||h(a).text()||"":"function"===typeof l?l(a,b,c):"function"===typeof(f=g.getColumnData(b,l,c))?f(a,b,c):a.textContent||a.innerText||h(a).text()||"";return h.trim(d)}function v(b){var a,c,f=b.config,e=f.$tbodies=f.$table.children("tbody:not(."+f.cssInfoBlock+")"),l,x,k,h,m,B,u,s,t,p=0,v="",w=e.length;if(0===w)return f.debug?d("Warning: *Empty table!* Not building a parser cache"):"";f.debug&&(t=new Date,d("Detecting parsers for each column"));a=[];for(c=[];p<w;){l=e[p].rows; if(l[p])for(x=f.columns,k=0;k<x;k++){h=f.$headers.filter('[data-column="'+k+'"]:last');m=g.getColumnData(b,f.headers,k);s=g.getParserById(g.getData(h,m,"extractor"));u=g.getParserById(g.getData(h,m,"sorter"));B="false"===g.getData(h,m,"parser");f.empties[k]=(g.getData(h,m,"empty")||f.emptyTo||(f.emptyToBottom?"bottom":"top")).toLowerCase();f.strings[k]=(g.getData(h,m,"string")||f.stringTo||"max").toLowerCase();B&&(u=g.getParserById("no-parser"));s||(s=!1);if(!u)a:{h=b;m=l;B=-1;u=k;for(var A=void 0, K=g.parsers.length,G=!1,z="",A=!0;""===z&&A;)B++,m[B]?(G=m[B].cells[u],z=r(h,G,u),h.config.debug&&d("Checking if value was empty on row "+B+", column: "+u+': "'+z+'"')):A=!1;for(;0<=--K;)if((A=g.parsers[K])&&"text"!==A.id&&A.is&&A.is(z,h,G)){u=A;break a}u=g.getParserById("text")}f.debug&&(v+="column:"+k+"; extractor:"+s.id+"; parser:"+u.id+"; string:"+f.strings[k]+"; empty: "+f.empties[k]+"\n");c[k]=u;a[k]=s}p+=c.length?w:1}f.debug&&(d(v?v:"No parsers detected"),q("Completed detecting parsers",t)); f.parsers=c;f.extractors=a}function w(b){var a,c,f,e,l,x,k,n,m,p,u,s=b.config,t=s.$table.children("tbody"),v=s.extractors,w=s.parsers;s.cache={};s.totalRows=0;if(!w)return s.debug?d("Warning: *Empty table!* Not building a cache"):"";s.debug&&(n=new Date);s.showProcessing&&g.isProcessing(b,!0);for(l=0;l<t.length;l++)if(u=[],a=s.cache[l]={normalized:[]},!t.eq(l).hasClass(s.cssInfoBlock)){m=t[l]&&t[l].rows.length||0;for(f=0;f<m;++f)if(p={child:[]},x=h(t[l].rows[f]),k=[],x.hasClass(s.cssChildRow)&&0!== f)c=a.normalized.length-1,a.normalized[c][s.columns].$row=a.normalized[c][s.columns].$row.add(x),x.prev().hasClass(s.cssChildRow)||x.prev().addClass(g.css.cssHasChild),p.child[c]=h.trim(x[0].textContent||x[0].innerText||x.text()||"");else{p.$row=x;p.order=f;for(e=0;e<s.columns;++e)"undefined"===typeof w[e]?s.debug&&d("No parser found for cell:",x[0].cells[e],"does it have a header?"):(c=r(b,x[0].cells[e],e),c="undefined"===typeof v[e].id?c:v[e].format(c,b,x[0].cells[e],e),c="no-parser"===w[e].id? "":w[e].format(c,b,x[0].cells[e],e),k.push(s.ignoreCase&&"string"===typeof c?c.toLowerCase():c),"numeric"===(w[e].type||"").toLowerCase()&&(u[e]=Math.max(Math.abs(c)||0,u[e]||0)));k[s.columns]=p;a.normalized.push(k)}a.colMax=u;s.totalRows+=a.normalized.length}s.showProcessing&&g.isProcessing(b);s.debug&&q("Building cache for "+m+" rows",n)}function z(b,a){var c=b.config,f=c.widgetOptions,e=b.tBodies,l=[],d=c.cache,k,n,m,r,u,s;if(p(d))return c.appender?c.appender(b,l):b.isUpdating?c.$table.trigger("updateComplete", b):"";c.debug&&(s=new Date);for(u=0;u<e.length;u++)if(k=h(e[u]),k.length&&!k.hasClass(c.cssInfoBlock)){m=g.processTbody(b,k,!0);k=d[u].normalized;n=k.length;for(r=0;r<n;r++)l.push(k[r][c.columns].$row),c.appender&&(!c.pager||c.pager.removeRows&&f.pager_removeRows||c.pager.ajax)||m.append(k[r][c.columns].$row);g.processTbody(b,m,!1)}c.appender&&c.appender(b,l);c.debug&&q("Rebuilt table",s);a||c.appender||g.applyWidget(b);b.isUpdating&&c.$table.trigger("updateComplete",b)}function D(b){return/^d/i.test(b)|| 1===b}function E(b){var a,c,f,e,l,x,k,n=b.config;n.headerList=[];n.headerContent=[];n.debug&&(k=new Date);n.columns=g.computeColumnIndex(n.$table.children("thead, tfoot").children("tr"));e=n.cssIcon?'<i class="'+(n.cssIcon===g.css.icon?g.css.icon:n.cssIcon+" "+g.css.icon)+'"></i>':"";n.$headers=h(b).find(n.selectorHeaders).each(function(k){c=h(this);a=g.getColumnData(b,n.headers,k,!0);n.headerContent[k]=h(this).html();""!==n.headerTemplate&&(l=n.headerTemplate.replace(/\{content\}/g,h(this).html()).replace(/\{icon\}/g, e),n.onRenderTemplate&&(f=n.onRenderTemplate.apply(c,[k,l]))&&"string"===typeof f&&(l=f),h(this).html('<div class="'+g.css.headerIn+'">'+l+"</div>"));n.onRenderHeader&&n.onRenderHeader.apply(c,[k]);this.column=parseInt(h(this).attr("data-column"),10);this.order=D(g.getData(c,a,"sortInitialOrder")||n.sortInitialOrder)?[1,0,2]:[0,1,2];this.count=-1;this.lockedOrder=!1;x=g.getData(c,a,"lockedOrder")||!1;"undefined"!==typeof x&&!1!==x&&(this.order=this.lockedOrder=D(x)?[1,1,1]:[0,0,0]);c.addClass(g.css.header+ " "+n.cssHeader);n.headerList[k]=this;c.parent().addClass(g.css.headerRow+" "+n.cssHeaderRow).attr("role","row");n.tabIndex&&c.attr("tabindex",0)}).attr({scope:"col",role:"columnheader"});H(b);n.debug&&(q("Built headers:",k),d(n.$headers))}function C(b,a,c){var f=b.config;f.$table.find(f.selectorRemove).remove();v(b);w(b);I(f.$table,a,c)}function H(b){var a,c,f,e=b.config;e.$headers.each(function(l,d){c=h(d);f=g.getColumnData(b,e.headers,l,!0);a="false"===g.getData(d,f,"sorter")||"false"===g.getData(d, f,"parser");d.sortDisabled=a;c[a?"addClass":"removeClass"]("sorter-false").attr("aria-disabled",""+a);b.id&&(a?c.removeAttr("aria-controls"):c.attr("aria-controls",b.id))})}function F(b){var a,c,f=b.config,e=f.sortList,l=e.length,d=g.css.sortNone+" "+f.cssNone,k=[g.css.sortAsc+" "+f.cssAsc,g.css.sortDesc+" "+f.cssDesc],n=["ascending","descending"],m=h(b).find("tfoot tr").children().add(f.$extraHeaders).removeClass(k.join(" "));f.$headers.removeClass(k.join(" ")).addClass(d).attr("aria-sort","none"); for(a=0;a<l;a++)if(2!==e[a][1]&&(b=f.$headers.not(".sorter-false").filter('[data-column="'+e[a][0]+'"]'+(1===l?":last":"")),b.length)){for(c=0;c<b.length;c++)b[c].sortDisabled||b.eq(c).removeClass(d).addClass(k[e[a][1]]).attr("aria-sort",n[e[a][1]]);m.length&&m.filter('[data-column="'+e[a][0]+'"]').removeClass(d).addClass(k[e[a][1]])}f.$headers.not(".sorter-false").each(function(){var b=h(this),a=this.order[(this.count+1)%(f.sortReset?3:2)],a=b.text()+": "+g.language[b.hasClass(g.css.sortAsc)?"sortAsc": b.hasClass(g.css.sortDesc)?"sortDesc":"sortNone"]+g.language[0===a?"nextAsc":1===a?"nextDesc":"nextNone"];b.attr("aria-label",a)})}function O(b){var a,c,f=b.config;f.widthFixed&&0===f.$table.find("colgroup").length&&(a=h("<colgroup>"),c=h(b).width(),h(b.tBodies).not("."+f.cssInfoBlock).find("tr:first").children(":visible").each(function(){a.append(h("<col>").css("width",parseInt(h(this).width()/c*1E3,10)/10+"%"))}),f.$table.prepend(a))}function P(b,a){var c,f,e,l,g,k=b.config,d=a||k.sortList;k.sortList= [];h.each(d,function(b,a){l=parseInt(a[0],10);if(e=k.$headers.filter('[data-column="'+l+'"]:last')[0]){f=(f=(""+a[1]).match(/^(1|d|s|o|n)/))?f[0]:"";switch(f){case "1":case "d":f=1;break;case "s":f=g||0;break;case "o":c=e.order[(g||0)%(k.sortReset?3:2)];f=0===c?1:1===c?0:2;break;case "n":e.count+=1;f=e.order[e.count%(k.sortReset?3:2)];break;default:f=0}g=0===b?f:g;c=[l,parseInt(f,10)||0];k.sortList.push(c);f=h.inArray(c[1],e.order);e.count=0<=f?f:c[1]%(k.sortReset?3:2)}})}function Q(b,a){return b&& b[a]?b[a].type||"":""}function L(b,a,c){if(b.isUpdating)return setTimeout(function(){L(b,a,c)},50);var f,e,l,d,k=b.config,n=!c[k.sortMultiSortKey],m=k.$table;m.trigger("sortStart",b);a.count=c[k.sortResetKey]?2:(a.count+1)%(k.sortReset?3:2);k.sortRestart&&(e=a,k.$headers.each(function(){this===e||!n&&h(this).is("."+g.css.sortDesc+",."+g.css.sortAsc)||(this.count=-1)}));e=a.column;if(n){k.sortList=[];if(null!==k.sortForce)for(f=k.sortForce,l=0;l<f.length;l++)f[l][0]!==e&&k.sortList.push(f[l]);f=a.order[a.count]; if(2>f&&(k.sortList.push([e,f]),1<a.colSpan))for(l=1;l<a.colSpan;l++)k.sortList.push([e+l,f])}else{if(k.sortAppend&&1<k.sortList.length)for(l=0;l<k.sortAppend.length;l++)d=g.isValueInArray(k.sortAppend[l][0],k.sortList),0<=d&&k.sortList.splice(d,1);if(0<=g.isValueInArray(e,k.sortList))for(l=0;l<k.sortList.length;l++)d=k.sortList[l],f=k.$headers.filter('[data-column="'+d[0]+'"]:last')[0],d[0]===e&&(d[1]=f.order[a.count],2===d[1]&&(k.sortList.splice(l,1),f.count=-1));else if(f=a.order[a.count],2>f&& (k.sortList.push([e,f]),1<a.colSpan))for(l=1;l<a.colSpan;l++)k.sortList.push([e+l,f])}if(null!==k.sortAppend)for(f=k.sortAppend,l=0;l<f.length;l++)f[l][0]!==e&&k.sortList.push(f[l]);m.trigger("sortBegin",b);setTimeout(function(){F(b);J(b);z(b);m.trigger("sortEnd",b)},1)}function J(b){var a,c,f,e,l,d,k,h,m,r,u,s=0,t=b.config,v=t.textSorter||"",w=t.sortList,y=w.length,z=b.tBodies.length;if(!t.serverSideSorting&&!p(t.cache)){t.debug&&(l=new Date);for(c=0;c<z;c++)d=t.cache[c].colMax,k=t.cache[c].normalized, k.sort(function(c,l){for(a=0;a<y;a++){e=w[a][0];h=w[a][1];s=0===h;if(t.sortStable&&c[e]===l[e]&&1===y)break;(f=/n/i.test(Q(t.parsers,e)))&&t.strings[e]?(f="boolean"===typeof t.string[t.strings[e]]?(s?1:-1)*(t.string[t.strings[e]]?-1:1):t.strings[e]?t.string[t.strings[e]]||0:0,m=t.numberSorter?t.numberSorter(c[e],l[e],s,d[e],b):g["sortNumeric"+(s?"Asc":"Desc")](c[e],l[e],f,d[e],e,b)):(r=s?c:l,u=s?l:c,m="function"===typeof v?v(r[e],u[e],s,e,b):"object"===typeof v&&v.hasOwnProperty(e)?v[e](r[e],u[e], s,e,b):g["sortNatural"+(s?"Asc":"Desc")](c[e],l[e],e,b,t));if(m)return m}return c[t.columns].order-l[t.columns].order});t.debug&&q("Sorting on "+w.toString()+" and dir "+h+" time",l)}}function M(b,a){var c=b[0];c.isUpdating&&b.trigger("updateComplete",c);h.isFunction(a)&&a(b[0])}function I(b,a,c){var f=b[0].config.sortList;!1!==a&&!b[0].isProcessing&&f.length?b.trigger("sorton",[f,function(){M(b,c)},!0]):(M(b,c),g.applyWidget(b[0],!1))}function N(b){var a=b.config,c=a.$table;c.unbind("sortReset update updateRows updateCell updateAll addRows updateComplete sorton appendCache updateCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave ".split(" ").join(a.namespace+ " ")).bind("sortReset"+a.namespace,function(f,e){f.stopPropagation();a.sortList=[];F(b);J(b);z(b);h.isFunction(e)&&e(b)}).bind("updateAll"+a.namespace,function(f,e,c){f.stopPropagation();b.isUpdating=!0;g.refreshWidgets(b,!0,!0);g.restoreHeaders(b);E(b);g.bindEvents(b,a.$headers,!0);N(b);C(b,e,c)}).bind("update"+a.namespace+" updateRows"+a.namespace,function(a,e,c){a.stopPropagation();b.isUpdating=!0;H(b);C(b,e,c)}).bind("updateCell"+a.namespace,function(f,e,l,g){f.stopPropagation();b.isUpdating= !0;c.find(a.selectorRemove).remove();var d,n,m;n=c.find("tbody");m=h(e);f=n.index(h.fn.closest?m.closest("tbody"):m.parents("tbody").filter(":first"));d=h.fn.closest?m.closest("tr"):m.parents("tr").filter(":first");e=m[0];n.length&&0<=f&&(n=n.eq(f).find("tr").index(d),m=m.index(),a.cache[f].normalized[n][a.columns].$row=d,d="undefined"===typeof a.extractors[m].id?r(b,e,m):a.extractors[m].format(r(b,e,m),b,e,m),e="no-parser"===a.parsers[m].id?"":a.parsers[m].format(d,b,e,m),a.cache[f].normalized[n][m]= a.ignoreCase&&"string"===typeof e?e.toLowerCase():e,"numeric"===(a.parsers[m].type||"").toLowerCase()&&(a.cache[f].colMax[m]=Math.max(Math.abs(e)||0,a.cache[f].colMax[m]||0)),I(c,l,g))}).bind("addRows"+a.namespace,function(f,e,l,g){f.stopPropagation();b.isUpdating=!0;if(p(a.cache))H(b),C(b,l,g);else{e=h(e).attr("role","row");var d,n,m,q,u,s=e.filter("tr").length,t=c.find("tbody").index(e.parents("tbody").filter(":first"));a.parsers&&a.parsers.length||v(b);for(f=0;f<s;f++){n=e[f].cells.length;u=[]; q={child:[],$row:e.eq(f),order:a.cache[t].normalized.length};for(d=0;d<n;d++)m="undefined"===typeof a.extractors[d].id?r(b,e[f].cells[d],d):a.extractors[d].format(r(b,e[f].cells[d],d),b,e[f].cells[d],d),m="no-parser"===a.parsers[d].id?"":a.parsers[d].format(m,b,e[f].cells[d],d),u[d]=a.ignoreCase&&"string"===typeof m?m.toLowerCase():m,"numeric"===(a.parsers[d].type||"").toLowerCase()&&(a.cache[t].colMax[d]=Math.max(Math.abs(u[d])||0,a.cache[t].colMax[d]||0));u.push(q);a.cache[t].normalized.push(u)}I(c, l,g)}}).bind("updateComplete"+a.namespace,function(){b.isUpdating=!1}).bind("sorton"+a.namespace,function(a,e,d,x){var k=b.config;a.stopPropagation();c.trigger("sortStart",this);P(b,e);F(b);k.delayInit&&p(k.cache)&&w(b);c.trigger("sortBegin",this);J(b);z(b,x);c.trigger("sortEnd",this);g.applyWidget(b);h.isFunction(d)&&d(b)}).bind("appendCache"+a.namespace,function(a,e,c){a.stopPropagation();z(b,c);h.isFunction(e)&&e(b)}).bind("updateCache"+a.namespace,function(c,e){a.parsers&&a.parsers.length||v(b); w(b);h.isFunction(e)&&e(b)}).bind("applyWidgetId"+a.namespace,function(c,e){c.stopPropagation();g.getWidgetById(e).format(b,a,a.widgetOptions)}).bind("applyWidgets"+a.namespace,function(a,c){a.stopPropagation();g.applyWidget(b,c)}).bind("refreshWidgets"+a.namespace,function(a,c,d){a.stopPropagation();g.refreshWidgets(b,c,d)}).bind("destroy"+a.namespace,function(a,c,d){a.stopPropagation();g.destroy(b,c,d)}).bind("resetToLoadState"+a.namespace,function(){g.refreshWidgets(b,!0,!0);a=h.extend(!0,g.defaults, a.originalSettings);b.hasInitialized=!1;g.setup(b,a)})}var g=this;g.version="2.17.8";g.parsers=[];g.widgets=[];g.defaults={theme:"default",widthFixed:!1,showProcessing:!1,headerTemplate:"{content}",onRenderTemplate:null,onRenderHeader:null,cancelSelection:!0,tabIndex:!0,dateFormat:"mmddyyyy",sortMultiSortKey:"shiftKey",sortResetKey:"ctrlKey",usNumberFormat:!0,delayInit:!1,serverSideSorting:!1,headers:{},ignoreCase:!0,sortForce:null,sortList:[],sortAppend:null,sortStable:!1,sortInitialOrder:"asc", sortLocaleCompare:!1,sortReset:!1,sortRestart:!1,emptyTo:"bottom",stringTo:"max",textExtraction:"basic",textAttribute:"data-text",textSorter:null,numberSorter:null,widgets:[],widgetOptions:{zebra:["even","odd"]},initWidgets:!0,initialized:null,tableClass:"",cssAsc:"",cssDesc:"",cssNone:"",cssHeader:"",cssHeaderRow:"",cssProcessing:"",cssChildRow:"tablesorter-childRow",cssIcon:"tablesorter-icon",cssInfoBlock:"tablesorter-infoOnly",selectorHeaders:"> thead th, > thead td",selectorSort:"th, td",selectorRemove:".remove-me", debug:!1,headerList:[],empties:{},strings:{},parsers:[]};g.css={table:"tablesorter",cssHasChild:"tablesorter-hasChildRow",childRow:"tablesorter-childRow",header:"tablesorter-header",headerRow:"tablesorter-headerRow",headerIn:"tablesorter-header-inner",icon:"tablesorter-icon",info:"tablesorter-infoOnly",processing:"tablesorter-processing",sortAsc:"tablesorter-headerAsc",sortDesc:"tablesorter-headerDesc",sortNone:"tablesorter-headerUnSorted"};g.language={sortAsc:"Ascending sort applied, ",sortDesc:"Descending sort applied, ", sortNone:"No sort applied, ",nextAsc:"activate to apply an ascending sort",nextDesc:"activate to apply a descending sort",nextNone:"activate to remove the sort"};g.log=d;g.benchmark=q;g.construct=function(b){return this.each(function(){var a=h.extend(!0,{},g.defaults,b);a.originalSettings=b;!this.hasInitialized&&g.buildTable&&"TABLE"!==this.tagName?g.buildTable(this,a):g.setup(this,a)})};g.setup=function(b,a){if(!b||!b.tHead||0===b.tBodies.length||!0===b.hasInitialized)return a.debug?d("ERROR: stopping initialization! No table, thead, tbody or tablesorter has already been initialized"): "";var c="",f=h(b),e=h.metadata;b.hasInitialized=!1;b.isProcessing=!0;b.config=a;h.data(b,"tablesorter",a);a.debug&&h.data(b,"startoveralltimer",new Date);a.supportsDataObject=function(a){a[0]=parseInt(a[0],10);return 1<a[0]||1===a[0]&&4<=parseInt(a[1],10)}(h.fn.jquery.split("."));a.string={max:1,min:-1,emptymin:1,emptymax:-1,zero:0,none:0,"null":0,top:!0,bottom:!1};a.emptyTo=a.emptyTo.toLowerCase();a.stringTo=a.stringTo.toLowerCase();/tablesorter\-/.test(f.attr("class"))||(c=""!==a.theme?" tablesorter-"+ a.theme:"");a.table=b;a.$table=f.addClass(g.css.table+" "+a.tableClass+c).attr("role","grid");a.$headers=f.find(a.selectorHeaders);a.namespace=a.namespace?"."+a.namespace.replace(/\W/g,""):".tablesorter"+Math.random().toString(16).slice(2);a.$table.children().children("tr").attr("role","row");a.$tbodies=f.children("tbody:not(."+a.cssInfoBlock+")").attr({"aria-live":"polite","aria-relevant":"all"});a.$table.find("caption").length&&a.$table.attr("aria-labelledby","theCaption");a.widgetInit={};a.textExtraction= a.$table.attr("data-text-extraction")||a.textExtraction||"basic";E(b);O(b);v(b);a.totalRows=0;a.delayInit||w(b);g.bindEvents(b,a.$headers,!0);N(b);a.supportsDataObject&&"undefined"!==typeof f.data().sortlist?a.sortList=f.data().sortlist:e&&f.metadata()&&f.metadata().sortlist&&(a.sortList=f.metadata().sortlist);g.applyWidget(b,!0);0<a.sortList.length?f.trigger("sorton",[a.sortList,{},!a.initWidgets,!0]):(F(b),a.initWidgets&&g.applyWidget(b,!1));a.showProcessing&&f.unbind("sortBegin"+a.namespace+" sortEnd"+ a.namespace).bind("sortBegin"+a.namespace+" sortEnd"+a.namespace,function(c){clearTimeout(a.processTimer);g.isProcessing(b);"sortBegin"===c.type&&(a.processTimer=setTimeout(function(){g.isProcessing(b,!0)},500))});b.hasInitialized=!0;b.isProcessing=!1;a.debug&&g.benchmark("Overall initialization time",h.data(b,"startoveralltimer"));f.trigger("tablesorter-initialized",b);"function"===typeof a.initialized&&a.initialized(b)};g.getColumnData=function(b,a,c,f){if("undefined"!==typeof a&&null!==a){b=h(b)[0]; var e,d=b.config;if(a[c])return f?a[c]:a[d.$headers.index(d.$headers.filter('[data-column="'+c+'"]:last'))];for(e in a)if("string"===typeof e&&(b=f?d.$headers.eq(c).filter(e):d.$headers.filter('[data-column="'+c+'"]:last').filter(e),b.length))return a[e]}};g.computeColumnIndex=function(b){var a=[],c=0,f,e,d,g,k,n,m,p,q,s;for(f=0;f<b.length;f++)for(k=b[f].cells,e=0;e<k.length;e++){d=k[e];g=h(d);n=d.parentNode.rowIndex;g.index();m=d.rowSpan||1;p=d.colSpan||1;"undefined"===typeof a[n]&&(a[n]=[]);for(d= 0;d<a[n].length+1;d++)if("undefined"===typeof a[n][d]){q=d;break}c=Math.max(q,c);g.attr({"data-column":q});for(d=n;d<n+m;d++)for("undefined"===typeof a[d]&&(a[d]=[]),s=a[d],g=q;g<q+p;g++)s[g]="x"}return c+1};g.isProcessing=function(b,a,c){b=h(b);var f=b[0].config,e=c||b.find("."+g.css.header);a?("undefined"!==typeof c&&0<f.sortList.length&&(e=e.filter(function(){return this.sortDisabled?!1:0<=g.isValueInArray(parseFloat(h(this).attr("data-column")),f.sortList)})),b.add(e).addClass(g.css.processing+ " "+f.cssProcessing)):b.add(e).removeClass(g.css.processing+" "+f.cssProcessing)};g.processTbody=function(b,a,c){b=h(b)[0];if(c)return b.isProcessing=!0,a.before('<span class="tablesorter-savemyplace"/>'),c=h.fn.detach?a.detach():a.remove();c=h(b).find("span.tablesorter-savemyplace");a.insertAfter(c);c.remove();b.isProcessing=!1};g.clearTableBody=function(b){h(b)[0].config.$tbodies.children().detach()};g.bindEvents=function(b,a,c){b=h(b)[0];var f,e=b.config;!0!==c&&(e.$extraHeaders=e.$extraHeaders? e.$extraHeaders.add(a):a);a.find(e.selectorSort).add(a.filter(e.selectorSort)).unbind(["mousedown","mouseup","sort","keyup",""].join(e.namespace+" ")).bind(["mousedown","mouseup","sort","keyup",""].join(e.namespace+" "),function(c,d){var g;g=c.type;if(!(1!==(c.which||c.button)&&!/sort|keyup/.test(g)||"keyup"===g&&13!==c.which||"mouseup"===g&&!0!==d&&250<(new Date).getTime()-f)){if("mousedown"===g)return f=(new Date).getTime(),/(input|select|button|textarea)/i.test(c.target.tagName)?"":!e.cancelSelection; e.delayInit&&p(e.cache)&&w(b);g=h.fn.closest?h(this).closest("th, td")[0]:/TH|TD/.test(this.tagName)?this:h(this).parents("th, td")[0];g=e.$headers[a.index(g)];g.sortDisabled||L(b,g,c)}});e.cancelSelection&&a.attr("unselectable","on").bind("selectstart",!1).css({"user-select":"none",MozUserSelect:"none"})};g.restoreHeaders=function(b){var a=h(b)[0].config;a.$table.find(a.selectorHeaders).each(function(b){h(this).find("."+g.css.headerIn).length&&h(this).html(a.headerContent[b])})};g.destroy=function(b, a,c){b=h(b)[0];if(b.hasInitialized){g.refreshWidgets(b,!0,!0);var f=h(b),e=b.config,d=f.find("thead:first"),q=d.find("tr."+g.css.headerRow).removeClass(g.css.headerRow+" "+e.cssHeaderRow),k=f.find("tfoot:first > tr").children("th, td");!1===a&&0<=h.inArray("uitheme",e.widgets)&&(f.trigger("applyWidgetId",["uitheme"]),f.trigger("applyWidgetId",["zebra"]));d.find("tr").not(q).remove();f.removeData("tablesorter").unbind("sortReset update updateAll updateRows updateCell addRows updateComplete sorton appendCache updateCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave keypress sortBegin sortEnd resetToLoadState ".split(" ").join(e.namespace+ " "));e.$headers.add(k).removeClass([g.css.header,e.cssHeader,e.cssAsc,e.cssDesc,g.css.sortAsc,g.css.sortDesc,g.css.sortNone].join(" ")).removeAttr("data-column").removeAttr("aria-label").attr("aria-disabled","true");q.find(e.selectorSort).unbind(["mousedown","mouseup","keypress",""].join(e.namespace+" "));g.restoreHeaders(b);f.toggleClass(g.css.table+" "+e.tableClass+" tablesorter-"+e.theme,!1===a);b.hasInitialized=!1;delete b.config.cache;"function"===typeof c&&c(b)}};g.regex={chunk:/(^([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)?$|^0x[0-9a-f]+$|\d+)/gi, chunks:/(^\\0|\\0$)/,hex:/^0x[0-9a-f]+$/i};g.sortNatural=function(b,a){if(b===a)return 0;var c,f,e,d,h,k;f=g.regex;if(f.hex.test(a)){c=parseInt(b.match(f.hex),16);e=parseInt(a.match(f.hex),16);if(c<e)return-1;if(c>e)return 1}c=b.replace(f.chunk,"\\0$1\\0").replace(f.chunks,"").split("\\0");f=a.replace(f.chunk,"\\0$1\\0").replace(f.chunks,"").split("\\0");k=Math.max(c.length,f.length);for(h=0;h<k;h++){e=isNaN(c[h])?c[h]||0:parseFloat(c[h])||0;d=isNaN(f[h])?f[h]||0:parseFloat(f[h])||0;if(isNaN(e)!== isNaN(d))return isNaN(e)?1:-1;typeof e!==typeof d&&(e+="",d+="");if(e<d)return-1;if(e>d)return 1}return 0};g.sortNaturalAsc=function(b,a,c,f,e){if(b===a)return 0;c=e.string[e.empties[c]||e.emptyTo];return""===b&&0!==c?"boolean"===typeof c?c?-1:1:-c||-1:""===a&&0!==c?"boolean"===typeof c?c?1:-1:c||1:g.sortNatural(b,a)};g.sortNaturalDesc=function(b,a,c,f,e){if(b===a)return 0;c=e.string[e.empties[c]||e.emptyTo];return""===b&&0!==c?"boolean"===typeof c?c?-1:1:c||1:""===a&&0!==c?"boolean"===typeof c?c? 1:-1:-c||-1:g.sortNatural(a,b)};g.sortText=function(b,a){return b>a?1:b<a?-1:0};g.getTextValue=function(b,a,c){if(c){var f=b?b.length:0,e=c+a;for(c=0;c<f;c++)e+=b.charCodeAt(c);return a*e}return 0};g.sortNumericAsc=function(b,a,c,f,e,d){if(b===a)return 0;d=d.config;e=d.string[d.empties[e]||d.emptyTo];if(""===b&&0!==e)return"boolean"===typeof e?e?-1:1:-e||-1;if(""===a&&0!==e)return"boolean"===typeof e?e?1:-1:e||1;isNaN(b)&&(b=g.getTextValue(b,c,f));isNaN(a)&&(a=g.getTextValue(a,c,f));return b-a};g.sortNumericDesc= function(b,a,c,f,e,d){if(b===a)return 0;d=d.config;e=d.string[d.empties[e]||d.emptyTo];if(""===b&&0!==e)return"boolean"===typeof e?e?-1:1:e||1;if(""===a&&0!==e)return"boolean"===typeof e?e?1:-1:-e||-1;isNaN(b)&&(b=g.getTextValue(b,c,f));isNaN(a)&&(a=g.getTextValue(a,c,f));return a-b};g.sortNumeric=function(b,a){return b-a};g.characterEquivalents={a:"\u00e1\u00e0\u00e2\u00e3\u00e4\u0105\u00e5",A:"\u00c1\u00c0\u00c2\u00c3\u00c4\u0104\u00c5",c:"\u00e7\u0107\u010d",C:"\u00c7\u0106\u010c",e:"\u00e9\u00e8\u00ea\u00eb\u011b\u0119", E:"\u00c9\u00c8\u00ca\u00cb\u011a\u0118",i:"\u00ed\u00ec\u0130\u00ee\u00ef\u0131",I:"\u00cd\u00cc\u0130\u00ce\u00cf",o:"\u00f3\u00f2\u00f4\u00f5\u00f6",O:"\u00d3\u00d2\u00d4\u00d5\u00d6",ss:"\u00df",SS:"\u1e9e",u:"\u00fa\u00f9\u00fb\u00fc\u016f",U:"\u00da\u00d9\u00db\u00dc\u016e"};g.replaceAccents=function(b){var a,c="[",d=g.characterEquivalents;if(!g.characterRegex){g.characterRegexArray={};for(a in d)"string"===typeof a&&(c+=d[a],g.characterRegexArray[a]=new RegExp("["+d[a]+"]","g"));g.characterRegex= new RegExp(c+"]")}if(g.characterRegex.test(b))for(a in d)"string"===typeof a&&(b=b.replace(g.characterRegexArray[a],a));return b};g.isValueInArray=function(b,a){var c,d=a.length;for(c=0;c<d;c++)if(a[c][0]===b)return c;return-1};g.addParser=function(b){var a,c=g.parsers.length,d=!0;for(a=0;a<c;a++)g.parsers[a].id.toLowerCase()===b.id.toLowerCase()&&(d=!1);d&&g.parsers.push(b)};g.getParserById=function(b){if("false"==b)return!1;var a,c=g.parsers.length;for(a=0;a<c;a++)if(g.parsers[a].id.toLowerCase()=== b.toString().toLowerCase())return g.parsers[a];return!1};g.addWidget=function(b){g.widgets.push(b)};g.hasWidget=function(b,a){b=h(b);return b.length&&b[0].config&&b[0].config.widgetInit[a]||!1};g.getWidgetById=function(b){var a,c,d=g.widgets.length;for(a=0;a<d;a++)if((c=g.widgets[a])&&c.hasOwnProperty("id")&&c.id.toLowerCase()===b.toLowerCase())return c};g.applyWidget=function(b,a){b=h(b)[0];var c=b.config,d=c.widgetOptions,e=[],l,p,k;!1!==a&&b.hasInitialized&&(b.isApplyingWidgets||b.isUpdating)|| (c.debug&&(l=new Date),c.widgets.length&&(b.isApplyingWidgets=!0,c.widgets=h.grep(c.widgets,function(a,b){return h.inArray(a,c.widgets)===b}),h.each(c.widgets||[],function(a,b){(k=g.getWidgetById(b))&&k.id&&(k.priority||(k.priority=10),e[a]=k)}),e.sort(function(a,b){return a.priority<b.priority?-1:a.priority===b.priority?0:1}),h.each(e,function(e,g){if(g){if(a||!c.widgetInit[g.id])c.widgetInit[g.id]=!0,g.hasOwnProperty("options")&&(d=b.config.widgetOptions=h.extend(!0,{},g.options,d)),g.hasOwnProperty("init")&& g.init(b,g,c,d);!a&&g.hasOwnProperty("format")&&g.format(b,c,d,!1)}})),setTimeout(function(){b.isApplyingWidgets=!1},0),c.debug&&(p=c.widgets.length,q("Completed "+(!0===a?"initializing ":"applying ")+p+" widget"+(1!==p?"s":""),l)))};g.refreshWidgets=function(b,a,c){b=h(b)[0];var f,e=b.config,l=e.widgets,q=g.widgets,k=q.length;for(f=0;f<k;f++)q[f]&&q[f].id&&(a||0>h.inArray(q[f].id,l))&&(e.debug&&d('Refeshing widgets: Removing "'+q[f].id+'"'),q[f].hasOwnProperty("remove")&&e.widgetInit[q[f].id]&&(q[f].remove(b, e,e.widgetOptions),e.widgetInit[q[f].id]=!1));!0!==c&&g.applyWidget(b,a)};g.getData=function(b,a,c){var d="";b=h(b);var e,g;if(!b.length)return"";e=h.metadata?b.metadata():!1;g=" "+(b.attr("class")||"");"undefined"!==typeof b.data(c)||"undefined"!==typeof b.data(c.toLowerCase())?d+=b.data(c)||b.data(c.toLowerCase()):e&&"undefined"!==typeof e[c]?d+=e[c]:a&&"undefined"!==typeof a[c]?d+=a[c]:" "!==g&&g.match(" "+c+"-")&&(d=g.match(new RegExp("\\s"+c+"-([\\w-]+)"))[1]||"");return h.trim(d)};g.formatFloat= function(b,a){if("string"!==typeof b||""===b)return b;var c;b=(a&&a.config?!1!==a.config.usNumberFormat:"undefined"!==typeof a?a:1)?b.replace(/,/g,""):b.replace(/[\s|\.]/g,"").replace(/,/g,".");/^\s*\([.\d]+\)/.test(b)&&(b=b.replace(/^\s*\(([.\d]+)\)/,"-$1"));c=parseFloat(b);return isNaN(c)?h.trim(b):c};g.isDigit=function(b){return isNaN(b)?/^[\-+(]?\d+[)]?$/.test(b.toString().replace(/[,.'"\s]/g,"")):!0}}});var r=h.tablesorter;h.fn.extend({tablesorter:r.construct});r.addParser({id:"no-parser",is:function(){return!1}, format:function(){return""},type:"text"});r.addParser({id:"text",is:function(){return!0},format:function(d,q){var p=q.config;d&&(d=h.trim(p.ignoreCase?d.toLocaleLowerCase():d),d=p.sortLocaleCompare?r.replaceAccents(d):d);return d},type:"text"});r.addParser({id:"digit",is:function(d){return r.isDigit(d)},format:function(d,q){var p=r.formatFloat((d||"").replace(/[^\w,. \-()]/g,""),q);return d&&"number"===typeof p?p:d?h.trim(d&&q.config.ignoreCase?d.toLocaleLowerCase():d):d},type:"numeric"});r.addParser({id:"currency", is:function(d){return/^\(?\d+[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]|[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]\d+\)?$/.test((d||"").replace(/[+\-,. ]/g,""))},format:function(d,q){var p=r.formatFloat((d||"").replace(/[^\w,. \-()]/g,""),q);return d&&"number"===typeof p?p:d?h.trim(d&&q.config.ignoreCase?d.toLocaleLowerCase():d):d},type:"numeric"});r.addParser({id:"ipAddress",is:function(d){return/^\d{1,3}[\.]\d{1,3}[\.]\d{1,3}[\.]\d{1,3}$/.test(d)},format:function(d,h){var p,y=d?d.split("."):"",v="",w=y.length; for(p=0;p<w;p++)v+=("00"+y[p]).slice(-3);return d?r.formatFloat(v,h):d},type:"numeric"});r.addParser({id:"url",is:function(d){return/^(https?|ftp|file):\/\//.test(d)},format:function(d){return d?h.trim(d.replace(/(https?|ftp|file):\/\//,"")):d},parsed:!0,type:"text"});r.addParser({id:"isoDate",is:function(d){return/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}/.test(d)},format:function(d,h){return d?r.formatFloat(""!==d?(new Date(d.replace(/-/g,"/"))).getTime()||d:"",h):d},type:"numeric"});r.addParser({id:"percent", is:function(d){return/(\d\s*?%|%\s*?\d)/.test(d)&&15>d.length},format:function(d,h){return d?r.formatFloat(d.replace(/%/g,""),h):d},type:"numeric"});r.addParser({id:"usLongDate",is:function(d){return/^[A-Z]{3,10}\.?\s+\d{1,2},?\s+(\d{4})(\s+\d{1,2}:\d{2}(:\d{2})?(\s+[AP]M)?)?$/i.test(d)||/^\d{1,2}\s+[A-Z]{3,10}\s+\d{4}/i.test(d)},format:function(d,h){return d?r.formatFloat((new Date(d.replace(/(\S)([AP]M)$/i,"$1 $2"))).getTime()||d,h):d},type:"numeric"});r.addParser({id:"shortDate",is:function(d){return/(^\d{1,2}[\/\s]\d{1,2}[\/\s]\d{4})|(^\d{4}[\/\s]\d{1,2}[\/\s]\d{1,2})/.test((d|| "").replace(/\s+/g," ").replace(/[\-.,]/g,"/"))},format:function(d,h,p,y){if(d){p=h.config;var v=p.$headers.filter("[data-column="+y+"]:last");y=v.length&&v[0].dateFormat||r.getData(v,r.getColumnData(h,p.headers,y),"dateFormat")||p.dateFormat;d=d.replace(/\s+/g," ").replace(/[\-.,]/g,"/");"mmddyyyy"===y?d=d.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/,"$3/$1/$2"):"ddmmyyyy"===y?d=d.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/,"$3/$2/$1"):"yyyymmdd"===y&&(d=d.replace(/(\d{4})[\/\s](\d{1,2})[\/\s](\d{1,2})/, "$1/$2/$3"))}return d?r.formatFloat((new Date(d)).getTime()||d,h):d},type:"numeric"});r.addParser({id:"time",is:function(d){return/^(([0-2]?\d:[0-5]\d)|([0-1]?\d:[0-5]\d\s?([AP]M)))$/i.test(d)},format:function(d,h){return d?r.formatFloat((new Date("2000/01/01 "+d.replace(/(\S)([AP]M)$/i,"$1 $2"))).getTime()||d,h):d},type:"numeric"});r.addParser({id:"metadata",is:function(){return!1},format:function(d,q,p){d=q.config;d=d.parserMetadataName?d.parserMetadataName:"sortValue";return h(p).metadata()[d]}, type:"numeric"});r.addWidget({id:"zebra",priority:90,format:function(d,q,p){var y,v,w,z,D,E=new RegExp(q.cssChildRow,"i"),C=q.$tbodies;q.debug&&(D=new Date);for(d=0;d<C.length;d++)w=0,y=C.eq(d),y=y.children("tr:visible").not(q.selectorRemove),y.each(function(){v=h(this);E.test(this.className)||w++;z=0===w%2;v.removeClass(p.zebra[z?1:0]).addClass(p.zebra[z?0:1])});q.debug&&r.benchmark("Applying Zebra widget",D)},remove:function(d,q,p){var r;q=q.$tbodies;var v=(p.zebra||["even","odd"]).join(" ");for(p= 0;p<q.length;p++)r=h.tablesorter.processTbody(d,q.eq(p),!0),r.children().removeClass(v),h.tablesorter.processTbody(d,r,!1)}})}(jQuery); +!function(e){"function"==typeof define&&define.amd?define(["jquery"],e):"object"==typeof module&&"object"==typeof module.exports?module.exports=e(require("jquery")):e(jQuery)}(function(e){return function(A){"use strict";var L=A.tablesorter={version:"2.31.3",parsers:[],widgets:[],defaults:{theme:"default",widthFixed:!1,showProcessing:!1,headerTemplate:"{content}",onRenderTemplate:null,onRenderHeader:null,cancelSelection:!0,tabIndex:!0,dateFormat:"mmddyyyy",sortMultiSortKey:"shiftKey",sortResetKey:"ctrlKey",usNumberFormat:!0,delayInit:!1,serverSideSorting:!1,resort:!0,headers:{},ignoreCase:!0,sortForce:null,sortList:[],sortAppend:null,sortStable:!1,sortInitialOrder:"asc",sortLocaleCompare:!1,sortReset:!1,sortRestart:!1,emptyTo:"bottom",stringTo:"max",duplicateSpan:!0,textExtraction:"basic",textAttribute:"data-text",textSorter:null,numberSorter:null,initWidgets:!0,widgetClass:"widget-{name}",widgets:[],widgetOptions:{zebra:["even","odd"]},initialized:null,tableClass:"",cssAsc:"",cssDesc:"",cssNone:"",cssHeader:"",cssHeaderRow:"",cssProcessing:"",cssChildRow:"tablesorter-childRow",cssInfoBlock:"tablesorter-infoOnly",cssNoSort:"tablesorter-noSort",cssIgnoreRow:"tablesorter-ignoreRow",cssIcon:"tablesorter-icon",cssIconNone:"",cssIconAsc:"",cssIconDesc:"",cssIconDisabled:"",pointerClick:"click",pointerDown:"mousedown",pointerUp:"mouseup",selectorHeaders:"> thead th, > thead td",selectorSort:"th, td",selectorRemove:".remove-me",debug:!1,headerList:[],empties:{},strings:{},parsers:[],globalize:0,imgAttr:0},css:{table:"tablesorter",cssHasChild:"tablesorter-hasChildRow",childRow:"tablesorter-childRow",colgroup:"tablesorter-colgroup",header:"tablesorter-header",headerRow:"tablesorter-headerRow",headerIn:"tablesorter-header-inner",icon:"tablesorter-icon",processing:"tablesorter-processing",sortAsc:"tablesorter-headerAsc",sortDesc:"tablesorter-headerDesc",sortNone:"tablesorter-headerUnSorted"},language:{sortAsc:"Ascending sort applied, ",sortDesc:"Descending sort applied, ",sortNone:"No sort applied, ",sortDisabled:"sorting is disabled",nextAsc:"activate to apply an ascending sort",nextDesc:"activate to apply a descending sort",nextNone:"activate to remove the sort"},regex:{templateContent:/\{content\}/g,templateIcon:/\{icon\}/g,templateName:/\{name\}/i,spaces:/\s+/g,nonWord:/\W/g,formElements:/(input|select|button|textarea)/i,chunk:/(^([+\-]?(?:\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)?$|^0x[0-9a-f]+$|\d+)/gi,chunks:/(^\\0|\\0$)/,hex:/^0x[0-9a-f]+$/i,comma:/,/g,digitNonUS:/[\s|\.]/g,digitNegativeTest:/^\s*\([.\d]+\)/,digitNegativeReplace:/^\s*\(([.\d]+)\)/,digitTest:/^[\-+(]?\d+[)]?$/,digitReplace:/[,.'"\s]/g},string:{max:1,min:-1,emptymin:1,emptymax:-1,zero:0,none:0,"null":0,top:!0,bottom:!1},keyCodes:{enter:13},dates:{},instanceMethods:{},setup:function(t,r){if(t&&t.tHead&&0!==t.tBodies.length&&!0!==t.hasInitialized){var e,o="",s=A(t),a=A.metadata;t.hasInitialized=!1,t.isProcessing=!0,t.config=r,A.data(t,"tablesorter",r),L.debug(r,"core")&&(console[console.group?"group":"log"]("Initializing tablesorter v"+L.version),A.data(t,"startoveralltimer",new Date)),r.supportsDataObject=((e=A.fn.jquery.split("."))[0]=parseInt(e[0],10),1<e[0]||1===e[0]&&4<=parseInt(e[1],10)),r.emptyTo=r.emptyTo.toLowerCase(),r.stringTo=r.stringTo.toLowerCase(),r.last={sortList:[],clickedIndex:-1},/tablesorter\-/.test(s.attr("class"))||(o=""!==r.theme?" tablesorter-"+r.theme:""),r.namespace?r.namespace="."+r.namespace.replace(L.regex.nonWord,""):r.namespace=".tablesorter"+Math.random().toString(16).slice(2),r.table=t,r.$table=s.addClass(L.css.table+" "+r.tableClass+o+" "+r.namespace.slice(1)).attr("role","grid"),r.$headers=s.find(r.selectorHeaders),r.$table.children().children("tr").attr("role","row"),r.$tbodies=s.children("tbody:not(."+r.cssInfoBlock+")").attr({"aria-live":"polite","aria-relevant":"all"}),r.$table.children("caption").length&&((o=r.$table.children("caption")[0]).id||(o.id=r.namespace.slice(1)+"caption"),r.$table.attr("aria-labelledby",o.id)),r.widgetInit={},r.textExtraction=r.$table.attr("data-text-extraction")||r.textExtraction||"basic",L.buildHeaders(r),L.fixColumnWidth(t),L.addWidgetFromClass(t),L.applyWidgetOptions(t),L.setupParsers(r),r.totalRows=0,r.debug&&L.validateOptions(r),r.delayInit||L.buildCache(r),L.bindEvents(t,r.$headers,!0),L.bindMethods(r),r.supportsDataObject&&void 0!==s.data().sortlist?r.sortList=s.data().sortlist:a&&s.metadata()&&s.metadata().sortlist&&(r.sortList=s.metadata().sortlist),L.applyWidget(t,!0),0<r.sortList.length?(r.last.sortList=r.sortList,L.sortOn(r,r.sortList,{},!r.initWidgets)):(L.setHeadersCss(r),r.initWidgets&&L.applyWidget(t,!1)),r.showProcessing&&s.unbind("sortBegin"+r.namespace+" sortEnd"+r.namespace).bind("sortBegin"+r.namespace+" sortEnd"+r.namespace,function(e){clearTimeout(r.timerProcessing),L.isProcessing(t),"sortBegin"===e.type&&(r.timerProcessing=setTimeout(function(){L.isProcessing(t,!0)},500))}),t.hasInitialized=!0,t.isProcessing=!1,L.debug(r,"core")&&(console.log("Overall initialization time:"+L.benchmark(A.data(t,"startoveralltimer"))),L.debug(r,"core")&&console.groupEnd&&console.groupEnd()),s.triggerHandler("tablesorter-initialized",t),"function"==typeof r.initialized&&r.initialized(t)}else L.debug(r,"core")&&(t.hasInitialized?console.warn("Stopping initialization. Tablesorter has already been initialized"):console.error("Stopping initialization! No table, thead or tbody",t))},bindMethods:function(r){var e=r.$table,t=r.namespace,o="sortReset update updateRows updateAll updateHeaders addRows updateCell updateComplete sorton appendCache updateCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave ".split(" ").join(t+" ");e.unbind(o.replace(L.regex.spaces," ")).bind("sortReset"+t,function(e,t){e.stopPropagation(),L.sortReset(this.config,function(e){e.isApplyingWidgets?setTimeout(function(){L.applyWidget(e,"",t)},100):L.applyWidget(e,"",t)})}).bind("updateAll"+t,function(e,t,r){e.stopPropagation(),L.updateAll(this.config,t,r)}).bind("update"+t+" updateRows"+t,function(e,t,r){e.stopPropagation(),L.update(this.config,t,r)}).bind("updateHeaders"+t,function(e,t){e.stopPropagation(),L.updateHeaders(this.config,t)}).bind("updateCell"+t,function(e,t,r,o){e.stopPropagation(),L.updateCell(this.config,t,r,o)}).bind("addRows"+t,function(e,t,r,o){e.stopPropagation(),L.addRows(this.config,t,r,o)}).bind("updateComplete"+t,function(){this.isUpdating=!1}).bind("sorton"+t,function(e,t,r,o){e.stopPropagation(),L.sortOn(this.config,t,r,o)}).bind("appendCache"+t,function(e,t,r){e.stopPropagation(),L.appendCache(this.config,r),A.isFunction(t)&&t(this)}).bind("updateCache"+t,function(e,t,r){e.stopPropagation(),L.updateCache(this.config,t,r)}).bind("applyWidgetId"+t,function(e,t){e.stopPropagation(),L.applyWidgetId(this,t)}).bind("applyWidgets"+t,function(e,t){e.stopPropagation(),L.applyWidget(this,!1,t)}).bind("refreshWidgets"+t,function(e,t,r){e.stopPropagation(),L.refreshWidgets(this,t,r)}).bind("removeWidget"+t,function(e,t,r){e.stopPropagation(),L.removeWidget(this,t,r)}).bind("destroy"+t,function(e,t,r){e.stopPropagation(),L.destroy(this,t,r)}).bind("resetToLoadState"+t,function(e){e.stopPropagation(),L.removeWidget(this,!0,!1);var t=A.extend(!0,{},r.originalSettings);(r=A.extend(!0,{},L.defaults,t)).originalSettings=t,this.hasInitialized=!1,L.setup(this,r)})},bindEvents:function(e,t,r){var o,i=(e=A(e)[0]).config,s=i.namespace,d=null;!0!==r&&(t.addClass(s.slice(1)+"_extra_headers"),(o=L.getClosest(t,"table")).length&&"TABLE"===o[0].nodeName&&o[0]!==e&&A(o[0]).addClass(s.slice(1)+"_extra_table")),o=(i.pointerDown+" "+i.pointerUp+" "+i.pointerClick+" sort keyup ").replace(L.regex.spaces," ").split(" ").join(s+" "),t.find(i.selectorSort).add(t.filter(i.selectorSort)).unbind(o).bind(o,function(e,t){var r,o,s,a=A(e.target),n=" "+e.type+" ";if(!(1!==(e.which||e.button)&&!n.match(" "+i.pointerClick+" | sort | keyup ")||" keyup "===n&&e.which!==L.keyCodes.enter||n.match(" "+i.pointerClick+" ")&&void 0!==e.which||n.match(" "+i.pointerUp+" ")&&d!==e.target&&!0!==t)){if(n.match(" "+i.pointerDown+" "))return d=e.target,void("1"===(s=a.jquery.split("."))[0]&&s[1]<4&&e.preventDefault());if(d=null,r=L.getClosest(A(this),"."+L.css.header),L.regex.formElements.test(e.target.nodeName)||a.hasClass(i.cssNoSort)||0<a.parents("."+i.cssNoSort).length||r.hasClass("sorter-false")||0<a.parents("button").length)return!i.cancelSelection;i.delayInit&&L.isEmptyObject(i.cache)&&L.buildCache(i),i.last.clickedIndex=r.attr("data-column")||r.index(),(o=i.$headerIndexed[i.last.clickedIndex][0])&&!o.sortDisabled&&L.initSort(i,o,e)}}),i.cancelSelection&&t.attr("unselectable","on").bind("selectstart",!1).css({"user-select":"none",MozUserSelect:"none"})},buildHeaders:function(d){var e,l,t,r;for(d.headerList=[],d.headerContent=[],d.sortVars=[],L.debug(d,"core")&&(t=new Date),d.columns=L.computeColumnIndex(d.$table.children("thead, tfoot").children("tr")),l=d.cssIcon?'<i class="'+(d.cssIcon===L.css.icon?L.css.icon:d.cssIcon+" "+L.css.icon)+'"></i>':"",d.$headers=A(A.map(d.$table.find(d.selectorHeaders),function(e,t){var r,o,s,a,n,i=A(e);if(!L.getClosest(i,"tr").hasClass(d.cssIgnoreRow))return/(th|td)/i.test(e.nodeName)||(n=L.getClosest(i,"th, td"),i.attr("data-column",n.attr("data-column"))),r=L.getColumnData(d.table,d.headers,t,!0),d.headerContent[t]=i.html(),""===d.headerTemplate||i.find("."+L.css.headerIn).length||(a=d.headerTemplate.replace(L.regex.templateContent,i.html()).replace(L.regex.templateIcon,i.find("."+L.css.icon).length?"":l),d.onRenderTemplate&&(o=d.onRenderTemplate.apply(i,[t,a]))&&"string"==typeof o&&(a=o),i.html('<div class="'+L.css.headerIn+'">'+a+"</div>")),d.onRenderHeader&&d.onRenderHeader.apply(i,[t,d,d.$table]),s=parseInt(i.attr("data-column"),10),e.column=s,n=L.getOrder(L.getData(i,r,"sortInitialOrder")||d.sortInitialOrder),d.sortVars[s]={count:-1,order:n?d.sortReset?[1,0,2]:[1,0]:d.sortReset?[0,1,2]:[0,1],lockedOrder:!1,sortedBy:""},void 0!==(n=L.getData(i,r,"lockedOrder")||!1)&&!1!==n&&(d.sortVars[s].lockedOrder=!0,d.sortVars[s].order=L.getOrder(n)?[1,1]:[0,0]),d.headerList[t]=e,i.addClass(L.css.header+" "+d.cssHeader),L.getClosest(i,"tr").addClass(L.css.headerRow+" "+d.cssHeaderRow).attr("role","row"),d.tabIndex&&i.attr("tabindex",0),e})),d.$headerIndexed=[],r=0;r<d.columns;r++)L.isEmptyObject(d.sortVars[r])&&(d.sortVars[r]={}),e=d.$headers.filter('[data-column="'+r+'"]'),d.$headerIndexed[r]=e.length?e.not(".sorter-false").length?e.not(".sorter-false").filter(":last"):e.filter(":last"):A();d.$table.find(d.selectorHeaders).attr({scope:"col",role:"columnheader"}),L.updateHeader(d),L.debug(d,"core")&&(console.log("Built headers:"+L.benchmark(t)),console.log(d.$headers))},addInstanceMethods:function(e){A.extend(L.instanceMethods,e)},setupParsers:function(e,t){var r,o,s,a,n,i,d,l,c,g,p,u,f,h,m=e.table,b=0,y=L.debug(e,"core"),w={};if(e.$tbodies=e.$table.children("tbody:not(."+e.cssInfoBlock+")"),0===(h=(f=void 0===t?e.$tbodies:t).length))return y?console.warn("Warning: *Empty table!* Not building a parser cache"):"";for(y&&(u=new Date,console[console.group?"group":"log"]("Detecting parsers for each column")),o={extractors:[],parsers:[]};b<h;){if((r=f[b].rows).length)for(n=0,a=e.columns,i=0;i<a;i++){if((d=e.$headerIndexed[n])&&d.length&&(l=L.getColumnData(m,e.headers,n),p=L.getParserById(L.getData(d,l,"extractor")),g=L.getParserById(L.getData(d,l,"sorter")),c="false"===L.getData(d,l,"parser"),e.empties[n]=(L.getData(d,l,"empty")||e.emptyTo||(e.emptyToBottom?"bottom":"top")).toLowerCase(),e.strings[n]=(L.getData(d,l,"string")||e.stringTo||"max").toLowerCase(),c&&(g=L.getParserById("no-parser")),p=p||!1,g=g||L.detectParserForColumn(e,r,-1,n),y&&(w["("+n+") "+d.text()]={parser:g.id,extractor:p?p.id:"none",string:e.strings[n],empty:e.empties[n]}),o.parsers[n]=g,o.extractors[n]=p,0<(s=d[0].colSpan-1)))for(n+=s,a+=s;0<s+1;)o.parsers[n-s]=g,o.extractors[n-s]=p,s--;n++}b+=o.parsers.length?h:1}y&&(L.isEmptyObject(w)?console.warn(" No parsers detected!"):console[console.table?"table":"log"](w),console.log("Completed detecting parsers"+L.benchmark(u)),console.groupEnd&&console.groupEnd()),e.parsers=o.parsers,e.extractors=o.extractors},addParser:function(e){var t,r=L.parsers.length,o=!0;for(t=0;t<r;t++)L.parsers[t].id.toLowerCase()===e.id.toLowerCase()&&(o=!1);o&&(L.parsers[L.parsers.length]=e)},getParserById:function(e){if("false"==e)return!1;var t,r=L.parsers.length;for(t=0;t<r;t++)if(L.parsers[t].id.toLowerCase()===e.toString().toLowerCase())return L.parsers[t];return!1},detectParserForColumn:function(e,t,r,o){for(var s,a,n,i=L.parsers.length,d=!1,l="",c=L.debug(e,"core"),g=!0;""===l&&g;)(n=t[++r])&&r<50?n.className.indexOf(L.cssIgnoreRow)<0&&(d=t[r].cells[o],l=L.getElementText(e,d,o),a=A(d),c&&console.log("Checking if value was empty on row "+r+", column: "+o+': "'+l+'"')):g=!1;for(;0<=--i;)if((s=L.parsers[i])&&"text"!==s.id&&s.is&&s.is(l,e.table,d,a))return s;return L.getParserById("text")},getElementText:function(e,t,r){if(!t)return"";var o,s=e.textExtraction||"",a=t.jquery?t:A(t);return"string"==typeof s?"basic"===s&&void 0!==(o=a.attr(e.textAttribute))?A.trim(o):A.trim(t.textContent||a.text()):"function"==typeof s?A.trim(s(a[0],e.table,r)):"function"==typeof(o=L.getColumnData(e.table,s,r))?A.trim(o(a[0],e.table,r)):A.trim(a[0].textContent||a.text())},getParsedText:function(e,t,r,o){void 0===o&&(o=L.getElementText(e,t,r));var s=""+o,a=e.parsers[r],n=e.extractors[r];return a&&(n&&"function"==typeof n.format&&(o=n.format(o,e.table,t,r)),s="no-parser"===a.id?"":a.format(""+o,e.table,t,r),e.ignoreCase&&"string"==typeof s&&(s=s.toLowerCase())),s},buildCache:function(e,t,r){var o,s,a,n,i,d,l,c,g,p,u,f,h,m,b,y,w,x,v,C,$,I,D=e.table,R=e.parsers,T=L.debug(e,"core");if(e.$tbodies=e.$table.children("tbody:not(."+e.cssInfoBlock+")"),l=void 0===r?e.$tbodies:r,e.cache={},e.totalRows=0,!R)return T?console.warn("Warning: *Empty table!* Not building a cache"):"";for(T&&(f=new Date),e.showProcessing&&L.isProcessing(D,!0),d=0;d<l.length;d++){for(y=[],o=e.cache[d]={normalized:[]},h=l[d]&&l[d].rows.length||0,n=0;n<h;++n)if(m={child:[],raw:[]},g=[],!(c=A(l[d].rows[n])).hasClass(e.selectorRemove.slice(1)))if(c.hasClass(e.cssChildRow)&&0!==n)for($=o.normalized.length-1,(b=o.normalized[$][e.columns]).$row=b.$row.add(c),c.prev().hasClass(e.cssChildRow)||c.prev().addClass(L.css.cssHasChild),p=c.children("th, td"),$=b.child.length,b.child[$]=[],x=0,C=e.columns,i=0;i<C;i++)(u=p[i])&&(b.child[$][i]=L.getParsedText(e,u,i),0<(w=p[i].colSpan-1)&&(x+=w,C+=w)),x++;else{for(m.$row=c,m.order=n,x=0,C=e.columns,i=0;i<C;++i){if((u=c[0].cells[i])&&x<e.columns&&(!(v=void 0!==R[x])&&T&&console.warn("No parser found for row: "+n+", column: "+i+'; cell containing: "'+A(u).text()+'"; does it have a header?'),s=L.getElementText(e,u,x),m.raw[x]=s,a=L.getParsedText(e,u,x,s),g[x]=a,v&&"numeric"===(R[x].type||"").toLowerCase()&&(y[x]=Math.max(Math.abs(a)||0,y[x]||0)),0<(w=u.colSpan-1))){for(I=0;I<=w;)a=e.duplicateSpan||0===I?a:"string"!=typeof e.textExtraction&&L.getElementText(e,u,x+I)||"",m.raw[x+I]=a,g[x+I]=a,I++;x+=w,C+=w}x++}g[e.columns]=m,o.normalized[o.normalized.length]=g}o.colMax=y,e.totalRows+=o.normalized.length}if(e.showProcessing&&L.isProcessing(D),T){for($=Math.min(5,e.cache[0].normalized.length),console[console.group?"group":"log"]("Building cache for "+e.totalRows+" rows (showing "+$+" rows in log) and "+e.columns+" columns"+L.benchmark(f)),s={},i=0;i<e.columns;i++)for(x=0;x<$;x++)s["row: "+x]||(s["row: "+x]={}),s["row: "+x][e.$headerIndexed[i].text()]=e.cache[0].normalized[x][i];console[console.table?"table":"log"](s),console.groupEnd&&console.groupEnd()}A.isFunction(t)&&t(D)},getColumnText:function(e,t,r,o){var s,a,n,i,d,l,c,g,p,u,f="function"==typeof r,h="all"===t,m={raw:[],parsed:[],$cell:[]},b=(e=A(e)[0]).config;if(!L.isEmptyObject(b)){for(d=b.$tbodies.length,s=0;s<d;s++)for(l=(n=b.cache[s].normalized).length,a=0;a<l;a++)i=n[a],o&&!i[b.columns].$row.is(o)||(u=!0,g=h?i.slice(0,b.columns):i[t],i=i[b.columns],c=h?i.raw:i.raw[t],p=h?i.$row.children():i.$row.children().eq(t),f&&(u=r({tbodyIndex:s,rowIndex:a,parsed:g,raw:c,$row:i.$row,$cell:p})),!1!==u&&(m.parsed[m.parsed.length]=g,m.raw[m.raw.length]=c,m.$cell[m.$cell.length]=p));return m}L.debug(b,"core")&&console.warn("No cache found - aborting getColumnText function!")},setHeadersCss:function(a){function e(e,t){e.removeClass(n).addClass(i[t]).attr("aria-sort",l[t]).find("."+L.css.icon).removeClass(d[2]).addClass(d[t])}var t,r,o=a.sortList,s=o.length,n=L.css.sortNone+" "+a.cssNone,i=[L.css.sortAsc+" "+a.cssAsc,L.css.sortDesc+" "+a.cssDesc],d=[a.cssIconAsc,a.cssIconDesc,a.cssIconNone],l=["ascending","descending"],c=a.$table.find("tfoot tr").children("td, th").add(A(a.namespace+"_extra_headers")).removeClass(i.join(" ")),g=a.$headers.add(A("thead "+a.namespace+"_extra_headers")).removeClass(i.join(" ")).addClass(n).attr("aria-sort","none").find("."+L.css.icon).removeClass(d.join(" ")).end();for(g.not(".sorter-false").find("."+L.css.icon).addClass(d[2]),a.cssIconDisabled&&g.filter(".sorter-false").find("."+L.css.icon).addClass(a.cssIconDisabled),t=0;t<s;t++)if(2!==o[t][1]){if((g=(g=a.$headers.filter(function(e){for(var t=!0,r=a.$headers.eq(e),o=parseInt(r.attr("data-column"),10),s=o+L.getClosest(r,"th, td")[0].colSpan;o<s;o++)t=!!t&&(t||-1<L.isValueInArray(o,a.sortList));return t})).not(".sorter-false").filter('[data-column="'+o[t][0]+'"]'+(1===s?":last":""))).length)for(r=0;r<g.length;r++)g[r].sortDisabled||e(g.eq(r),o[t][1]);c.length&&e(c.filter('[data-column="'+o[t][0]+'"]'),o[t][1])}for(s=a.$headers.length,t=0;t<s;t++)L.setColumnAriaLabel(a,a.$headers.eq(t))},getClosest:function(e,t){return A.fn.closest?e.closest(t):e.is(t)?e:e.parents(t).filter(":first")},setColumnAriaLabel:function(e,t,r){if(t.length){var o=parseInt(t.attr("data-column"),10),s=e.sortVars[o],a=t.hasClass(L.css.sortAsc)?"sortAsc":t.hasClass(L.css.sortDesc)?"sortDesc":"sortNone",n=A.trim(t.text())+": "+L.language[a];t.hasClass("sorter-false")||!1===r?n+=L.language.sortDisabled:(a=(s.count+1)%s.order.length,r=s.order[a],n+=L.language[0===r?"nextAsc":1===r?"nextDesc":"nextNone"]),t.attr("aria-label",n),s.sortedBy?t.attr("data-sortedBy",s.sortedBy):t.removeAttr("data-sortedBy")}},updateHeader:function(e){var t,r,o,s,a=e.table,n=e.$headers.length;for(t=0;t<n;t++)o=e.$headers.eq(t),s=L.getColumnData(a,e.headers,t,!0),r="false"===L.getData(o,s,"sorter")||"false"===L.getData(o,s,"parser"),L.setColumnSort(e,o,r)},setColumnSort:function(e,t,r){var o=e.table.id;t[0].sortDisabled=r,t[r?"addClass":"removeClass"]("sorter-false").attr("aria-disabled",""+r),e.tabIndex&&(r?t.removeAttr("tabindex"):t.attr("tabindex","0")),o&&(r?t.removeAttr("aria-controls"):t.attr("aria-controls",o))},updateHeaderSortCount:function(e,t){var r,o,s,a,n,i,d,l,c=t||e.sortList,g=c.length;for(e.sortList=[],a=0;a<g;a++)if(d=c[a],(r=parseInt(d[0],10))<e.columns){switch(e.sortVars[r].order||(l=L.getOrder(e.sortInitialOrder)?e.sortReset?[1,0,2]:[1,0]:e.sortReset?[0,1,2]:[0,1],e.sortVars[r].order=l,e.sortVars[r].count=0),l=e.sortVars[r].order,o=(o=(""+d[1]).match(/^(1|d|s|o|n)/))?o[0]:""){case"1":case"d":o=1;break;case"s":o=n||0;break;case"o":o=0===(i=l[(n||0)%l.length])?1:1===i?0:2;break;case"n":o=l[++e.sortVars[r].count%l.length];break;default:o=0}n=0===a?o:n,s=[r,parseInt(o,10)||0],e.sortList[e.sortList.length]=s,o=A.inArray(s[1],l),e.sortVars[r].count=0<=o?o:s[1]%l.length}},updateAll:function(e,t,r){var o=e.table;o.isUpdating=!0,L.refreshWidgets(o,!0,!0),L.buildHeaders(e),L.bindEvents(o,e.$headers,!0),L.bindMethods(e),L.commonUpdate(e,t,r)},update:function(e,t,r){e.table.isUpdating=!0,L.updateHeader(e),L.commonUpdate(e,t,r)},updateHeaders:function(e,t){e.table.isUpdating=!0,L.buildHeaders(e),L.bindEvents(e.table,e.$headers,!0),L.resortComplete(e,t)},updateCell:function(e,t,r,o){if(A(t).closest("tr").hasClass(e.cssChildRow))console.warn('Tablesorter Warning! "updateCell" for child row content has been disabled, use "update" instead');else{if(L.isEmptyObject(e.cache))return L.updateHeader(e),void L.commonUpdate(e,r,o);e.table.isUpdating=!0,e.$table.find(e.selectorRemove).remove();var s,a,n,i,d,l,c=e.$tbodies,g=A(t),p=c.index(L.getClosest(g,"tbody")),u=e.cache[p],f=L.getClosest(g,"tr");if(t=g[0],c.length&&0<=p){if(n=c.eq(p).find("tr").not("."+e.cssChildRow).index(f),d=u.normalized[n],(l=f[0].cells.length)!==e.columns)for(s=!1,a=i=0;a<l;a++)s||f[0].cells[a]===t?s=!0:i+=f[0].cells[a].colSpan;else i=g.index();s=L.getElementText(e,t,i),d[e.columns].raw[i]=s,s=L.getParsedText(e,t,i,s),d[i]=s,"numeric"===(e.parsers[i].type||"").toLowerCase()&&(u.colMax[i]=Math.max(Math.abs(s)||0,u.colMax[i]||0)),!1!==(s="undefined"!==r?r:e.resort)?L.checkResort(e,s,o):L.resortComplete(e,o)}else L.debug(e,"core")&&console.error("updateCell aborted, tbody missing or not within the indicated table"),e.table.isUpdating=!1}},addRows:function(e,t,r,o){var s,a,n,i,d,l,c,g,p,u,f,h,m,b="string"==typeof t&&1===e.$tbodies.length&&/<tr/.test(t||""),y=e.table;if(b)t=A(t),e.$tbodies.append(t);else if(!(t&&t instanceof A&&L.getClosest(t,"table")[0]===e.table))return L.debug(e,"core")&&console.error("addRows method requires (1) a jQuery selector reference to rows that have already been added to the table, or (2) row HTML string to be added to a table with only one tbody"),!1;if(y.isUpdating=!0,L.isEmptyObject(e.cache))L.updateHeader(e),L.commonUpdate(e,r,o);else{for(d=t.filter("tr").attr("role","row").length,n=e.$tbodies.index(t.parents("tbody").filter(":first")),e.parsers&&e.parsers.length||L.setupParsers(e),i=0;i<d;i++){for(p=0,c=t[i].cells.length,g=e.cache[n].normalized.length,f=[],u={child:[],raw:[],$row:t.eq(i),order:g},l=0;l<c;l++)h=t[i].cells[l],s=L.getElementText(e,h,p),u.raw[p]=s,a=L.getParsedText(e,h,p,s),f[p]=a,"numeric"===(e.parsers[p].type||"").toLowerCase()&&(e.cache[n].colMax[p]=Math.max(Math.abs(a)||0,e.cache[n].colMax[p]||0)),0<(m=h.colSpan-1)&&(p+=m),p++;f[e.columns]=u,e.cache[n].normalized[g]=f}L.checkResort(e,r,o)}},updateCache:function(e,t,r){e.parsers&&e.parsers.length||L.setupParsers(e,r),L.buildCache(e,t,r)},appendCache:function(e,t){var r,o,s,a,n,i,d,l=e.table,c=e.$tbodies,g=[],p=e.cache;if(L.isEmptyObject(p))return e.appender?e.appender(l,g):l.isUpdating?e.$table.triggerHandler("updateComplete",l):"";for(L.debug(e,"core")&&(d=new Date),i=0;i<c.length;i++)if((s=c.eq(i)).length){for(a=L.processTbody(l,s,!0),o=(r=p[i].normalized).length,n=0;n<o;n++)g[g.length]=r[n][e.columns].$row,e.appender&&(!e.pager||e.pager.removeRows||e.pager.ajax)||a.append(r[n][e.columns].$row);L.processTbody(l,a,!1)}e.appender&&e.appender(l,g),L.debug(e,"core")&&console.log("Rebuilt table"+L.benchmark(d)),t||e.appender||L.applyWidget(l),l.isUpdating&&e.$table.triggerHandler("updateComplete",l)},commonUpdate:function(e,t,r){e.$table.find(e.selectorRemove).remove(),L.setupParsers(e),L.buildCache(e),L.checkResort(e,t,r)},initSort:function(t,e,r){if(t.table.isUpdating)return setTimeout(function(){L.initSort(t,e,r)},50);var o,s,a,n,i,d,l,c=!r[t.sortMultiSortKey],g=t.table,p=t.$headers.length,u=L.getClosest(A(e),"th, td"),f=parseInt(u.attr("data-column"),10),h="mouseup"===r.type?"user":r.type,m=t.sortVars[f].order;if(u=u[0],t.$table.triggerHandler("sortStart",g),d=(t.sortVars[f].count+1)%m.length,t.sortVars[f].count=r[t.sortResetKey]?2:d,t.sortRestart)for(a=0;a<p;a++)l=t.$headers.eq(a),f!==(d=parseInt(l.attr("data-column"),10))&&(c||l.hasClass(L.css.sortNone))&&(t.sortVars[d].count=-1);if(c){if(A.each(t.sortVars,function(e){t.sortVars[e].sortedBy=""}),t.sortList=[],t.last.sortList=[],null!==t.sortForce)for(o=t.sortForce,s=0;s<o.length;s++)o[s][0]!==f&&(t.sortList[t.sortList.length]=o[s],t.sortVars[o[s][0]].sortedBy="sortForce");if((n=m[t.sortVars[f].count])<2&&(t.sortList[t.sortList.length]=[f,n],t.sortVars[f].sortedBy=h,1<u.colSpan))for(s=1;s<u.colSpan;s++)t.sortList[t.sortList.length]=[f+s,n],t.sortVars[f+s].count=A.inArray(n,m),t.sortVars[f+s].sortedBy=h}else if(t.sortList=A.extend([],t.last.sortList),0<=L.isValueInArray(f,t.sortList))for(t.sortVars[f].sortedBy=h,s=0;s<t.sortList.length;s++)(d=t.sortList[s])[0]===f&&(d[1]=m[t.sortVars[f].count],2===d[1]&&(t.sortList.splice(s,1),t.sortVars[f].count=-1));else if(n=m[t.sortVars[f].count],t.sortVars[f].sortedBy=h,n<2&&(t.sortList[t.sortList.length]=[f,n],1<u.colSpan))for(s=1;s<u.colSpan;s++)t.sortList[t.sortList.length]=[f+s,n],t.sortVars[f+s].count=A.inArray(n,m),t.sortVars[f+s].sortedBy=h;if(t.last.sortList=A.extend([],t.sortList),t.sortList.length&&t.sortAppend&&(o=A.isArray(t.sortAppend)?t.sortAppend:t.sortAppend[t.sortList[0][0]],!L.isEmptyObject(o)))for(s=0;s<o.length;s++)if(o[s][0]!==f&&L.isValueInArray(o[s][0],t.sortList)<0){if(i=(""+(n=o[s][1])).match(/^(a|d|s|o|n)/))switch(d=t.sortList[0][1],i[0]){case"d":n=1;break;case"s":n=d;break;case"o":n=0===d?1:0;break;case"n":n=(d+1)%m.length;break;default:n=0}t.sortList[t.sortList.length]=[o[s][0],n],t.sortVars[o[s][0]].sortedBy="sortAppend"}t.$table.triggerHandler("sortBegin",g),setTimeout(function(){L.setHeadersCss(t),L.multisort(t),L.appendCache(t),t.$table.triggerHandler("sortBeforeEnd",g),t.$table.triggerHandler("sortEnd",g)},1)},multisort:function(l){var e,t,c,r,g=l.table,p=[],u=0,f=l.textSorter||"",h=l.sortList,m=h.length,o=l.$tbodies.length;if(!l.serverSideSorting&&!L.isEmptyObject(l.cache)){if(L.debug(l,"core")&&(t=new Date),"object"==typeof f)for(c=l.columns;c--;)"function"==typeof(r=L.getColumnData(g,f,c))&&(p[c]=r);for(e=0;e<o;e++)c=l.cache[e].colMax,l.cache[e].normalized.sort(function(e,t){var r,o,s,a,n,i,d;for(r=0;r<m;r++){if(s=h[r][0],a=h[r][1],u=0===a,l.sortStable&&e[s]===t[s]&&1===m)return e[l.columns].order-t[l.columns].order;if(n=(o=/n/i.test(L.getSortType(l.parsers,s)))&&l.strings[s]?(o="boolean"==typeof L.string[l.strings[s]]?(u?1:-1)*(L.string[l.strings[s]]?-1:1):l.strings[s]&&L.string[l.strings[s]]||0,l.numberSorter?l.numberSorter(e[s],t[s],u,c[s],g):L["sortNumeric"+(u?"Asc":"Desc")](e[s],t[s],o,c[s],s,l)):(i=u?e:t,d=u?t:e,"function"==typeof f?f(i[s],d[s],u,s,g):"function"==typeof p[s]?p[s](i[s],d[s],u,s,g):L["sortNatural"+(u?"Asc":"Desc")](e[s]||"",t[s]||"",s,l)))return n}return e[l.columns].order-t[l.columns].order});L.debug(l,"core")&&console.log("Applying sort "+h.toString()+L.benchmark(t))}},resortComplete:function(e,t){e.table.isUpdating&&e.$table.triggerHandler("updateComplete",e.table),A.isFunction(t)&&t(e.table)},checkResort:function(e,t,r){var o=A.isArray(t)?t:e.sortList;!1===(void 0===t?e.resort:t)||e.serverSideSorting||e.table.isProcessing?(L.resortComplete(e,r),L.applyWidget(e.table,!1)):o.length?L.sortOn(e,o,function(){L.resortComplete(e,r)},!0):L.sortReset(e,function(){L.resortComplete(e,r),L.applyWidget(e.table,!1)})},sortOn:function(e,t,r,o){var s,a=e.table;for(e.$table.triggerHandler("sortStart",a),s=0;s<e.columns;s++)e.sortVars[s].sortedBy=-1<L.isValueInArray(s,t)?"sorton":"";L.updateHeaderSortCount(e,t),L.setHeadersCss(e),e.delayInit&&L.isEmptyObject(e.cache)&&L.buildCache(e),e.$table.triggerHandler("sortBegin",a),L.multisort(e),L.appendCache(e,o),e.$table.triggerHandler("sortBeforeEnd",a),e.$table.triggerHandler("sortEnd",a),L.applyWidget(a),A.isFunction(r)&&r(a)},sortReset:function(e,t){var r;for(e.sortList=[],r=0;r<e.columns;r++)e.sortVars[r].count=-1,e.sortVars[r].sortedBy="";L.setHeadersCss(e),L.multisort(e),L.appendCache(e),A.isFunction(t)&&t(e.table)},getSortType:function(e,t){return e&&e[t]&&e[t].type||""},getOrder:function(e){return/^d/i.test(e)||1===e},sortNatural:function(e,t){if(e===t)return 0;e=(e||"").toString(),t=(t||"").toString();var r,o,s,a,n,i,d=L.regex;if(d.hex.test(t)){if((r=parseInt(e.match(d.hex),16))<(o=parseInt(t.match(d.hex),16)))return-1;if(o<r)return 1}for(r=e.replace(d.chunk,"\\0$1\\0").replace(d.chunks,"").split("\\0"),o=t.replace(d.chunk,"\\0$1\\0").replace(d.chunks,"").split("\\0"),i=Math.max(r.length,o.length),n=0;n<i;n++){if(s=isNaN(r[n])?r[n]||0:parseFloat(r[n])||0,a=isNaN(o[n])?o[n]||0:parseFloat(o[n])||0,isNaN(s)!==isNaN(a))return isNaN(s)?1:-1;if(typeof s!=typeof a&&(s+="",a+=""),s<a)return-1;if(a<s)return 1}return 0},sortNaturalAsc:function(e,t,r,o){if(e===t)return 0;var s=L.string[o.empties[r]||o.emptyTo];return""===e&&0!==s?"boolean"==typeof s?s?-1:1:-s||-1:""===t&&0!==s?"boolean"==typeof s?s?1:-1:s||1:L.sortNatural(e,t)},sortNaturalDesc:function(e,t,r,o){if(e===t)return 0;var s=L.string[o.empties[r]||o.emptyTo];return""===e&&0!==s?"boolean"==typeof s?s?-1:1:s||1:""===t&&0!==s?"boolean"==typeof s?s?1:-1:-s||-1:L.sortNatural(t,e)},sortText:function(e,t){return t<e?1:e<t?-1:0},getTextValue:function(e,t,r){if(r){var o,s=e?e.length:0,a=r+t;for(o=0;o<s;o++)a+=e.charCodeAt(o);return t*a}return 0},sortNumericAsc:function(e,t,r,o,s,a){if(e===t)return 0;var n=L.string[a.empties[s]||a.emptyTo];return""===e&&0!==n?"boolean"==typeof n?n?-1:1:-n||-1:""===t&&0!==n?"boolean"==typeof n?n?1:-1:n||1:(isNaN(e)&&(e=L.getTextValue(e,r,o)),isNaN(t)&&(t=L.getTextValue(t,r,o)),e-t)},sortNumericDesc:function(e,t,r,o,s,a){if(e===t)return 0;var n=L.string[a.empties[s]||a.emptyTo];return""===e&&0!==n?"boolean"==typeof n?n?-1:1:n||1:""===t&&0!==n?"boolean"==typeof n?n?1:-1:-n||-1:(isNaN(e)&&(e=L.getTextValue(e,r,o)),isNaN(t)&&(t=L.getTextValue(t,r,o)),t-e)},sortNumeric:function(e,t){return e-t},addWidget:function(e){e.id&&!L.isEmptyObject(L.getWidgetById(e.id))&&console.warn('"'+e.id+'" widget was loaded more than once!'),L.widgets[L.widgets.length]=e},hasWidget:function(e,t){return(e=A(e)).length&&e[0].config&&e[0].config.widgetInit[t]||!1},getWidgetById:function(e){var t,r,o=L.widgets.length;for(t=0;t<o;t++)if((r=L.widgets[t])&&r.id&&r.id.toLowerCase()===e.toLowerCase())return r},applyWidgetOptions:function(e){var t,r,o,s=e.config,a=s.widgets.length;if(a)for(t=0;t<a;t++)(r=L.getWidgetById(s.widgets[t]))&&r.options&&(o=A.extend(!0,{},r.options),s.widgetOptions=A.extend(!0,o,s.widgetOptions),A.extend(!0,L.defaults.widgetOptions,r.options))},addWidgetFromClass:function(e){var t,r,o=e.config,s="^"+o.widgetClass.replace(L.regex.templateName,"(\\S+)+")+"$",a=new RegExp(s,"g"),n=(e.className||"").split(L.regex.spaces);if(n.length)for(t=n.length,r=0;r<t;r++)n[r].match(a)&&(o.widgets[o.widgets.length]=n[r].replace(a,"$1"))},applyWidgetId:function(e,t,r){var o,s,a,n=(e=A(e)[0]).config,i=n.widgetOptions,d=L.debug(n,"core"),l=L.getWidgetById(t);l&&(a=l.id,o=!1,A.inArray(a,n.widgets)<0&&(n.widgets[n.widgets.length]=a),d&&(s=new Date),!r&&n.widgetInit[a]||(n.widgetInit[a]=!0,e.hasInitialized&&L.applyWidgetOptions(e),"function"==typeof l.init&&(o=!0,d&&console[console.group?"group":"log"]("Initializing "+a+" widget"),l.init(e,l,n,i))),r||"function"!=typeof l.format||(o=!0,d&&console[console.group?"group":"log"]("Updating "+a+" widget"),l.format(e,n,i,!1)),d&&o&&(console.log("Completed "+(r?"initializing ":"applying ")+a+" widget"+L.benchmark(s)),console.groupEnd&&console.groupEnd()))},applyWidget:function(e,t,r){var o,s,a,n,i,d=(e=A(e)[0]).config,l=L.debug(d,"core"),c=[];if(!1===t||!e.hasInitialized||!e.isApplyingWidgets&&!e.isUpdating){if(l&&(i=new Date),L.addWidgetFromClass(e),clearTimeout(d.timerReady),d.widgets.length){for(e.isApplyingWidgets=!0,d.widgets=A.grep(d.widgets,function(e,t){return A.inArray(e,d.widgets)===t}),s=(a=d.widgets||[]).length,o=0;o<s;o++)(n=L.getWidgetById(a[o]))&&n.id?(n.priority||(n.priority=10),c[o]=n):l&&console.warn('"'+a[o]+'" was enabled, but the widget code has not been loaded!');for(c.sort(function(e,t){return e.priority<t.priority?-1:e.priority===t.priority?0:1}),s=c.length,l&&console[console.group?"group":"log"]("Start "+(t?"initializing":"applying")+" widgets"),o=0;o<s;o++)(n=c[o])&&n.id&&L.applyWidgetId(e,n.id,t);l&&console.groupEnd&&console.groupEnd()}d.timerReady=setTimeout(function(){e.isApplyingWidgets=!1,A.data(e,"lastWidgetApplication",new Date),d.$table.triggerHandler("tablesorter-ready"),t||"function"!=typeof r||r(e),l&&(n=d.widgets.length,console.log("Completed "+(!0===t?"initializing ":"applying ")+n+" widget"+(1!==n?"s":"")+L.benchmark(i)))},10)}},removeWidget:function(e,t,r){var o,s,a,n,i=(e=A(e)[0]).config;if(!0===t)for(t=[],n=L.widgets.length,a=0;a<n;a++)(s=L.widgets[a])&&s.id&&(t[t.length]=s.id);else t=(A.isArray(t)?t.join(","):t||"").toLowerCase().split(/[\s,]+/);for(n=t.length,o=0;o<n;o++)s=L.getWidgetById(t[o]),0<=(a=A.inArray(t[o],i.widgets))&&!0!==r&&i.widgets.splice(a,1),s&&s.remove&&(L.debug(i,"core")&&console.log((r?"Refreshing":"Removing")+' "'+t[o]+'" widget'),s.remove(e,i,i.widgetOptions,r),i.widgetInit[t[o]]=!1);i.$table.triggerHandler("widgetRemoveEnd",e)},refreshWidgets:function(e,t,r){function o(e){A(e).triggerHandler("refreshComplete")}var s,a,n=(e=A(e)[0]).config.widgets,i=L.widgets,d=i.length,l=[];for(s=0;s<d;s++)(a=i[s])&&a.id&&(t||A.inArray(a.id,n)<0)&&(l[l.length]=a.id);L.removeWidget(e,l.join(","),!0),!0!==r?(L.applyWidget(e,t||!1,o),t&&L.applyWidget(e,!1,o)):o(e)},benchmark:function(e){return" ("+((new Date).getTime()-e.getTime())+" ms)"},log:function(){console.log(arguments)},debug:function(e,t){return e&&(!0===e.debug||"string"==typeof e.debug&&-1<e.debug.indexOf(t))},isEmptyObject:function(e){for(var t in e)return!1;return!0},isValueInArray:function(e,t){var r,o=t&&t.length||0;for(r=0;r<o;r++)if(t[r][0]===e)return r;return-1},formatFloat:function(e,t){return"string"!=typeof e||""===e?e:(e=(t&&t.config?!1!==t.config.usNumberFormat:void 0===t||t)?e.replace(L.regex.comma,""):e.replace(L.regex.digitNonUS,"").replace(L.regex.comma,"."),L.regex.digitNegativeTest.test(e)&&(e=e.replace(L.regex.digitNegativeReplace,"-$1")),r=parseFloat(e),isNaN(r)?A.trim(e):r);var r},isDigit:function(e){return isNaN(e)?L.regex.digitTest.test(e.toString().replace(L.regex.digitReplace,"")):""!==e},computeColumnIndex:function(e,t){var r,o,s,a,n,i,d,l,c,g,p=t&&t.columns||0,u=[],f=new Array(p);for(r=0;r<e.length;r++)for(i=e[r].cells,o=0;o<i.length;o++){for(d=r,l=(n=i[o]).rowSpan||1,c=n.colSpan||1,void 0===u[d]&&(u[d]=[]),s=0;s<u[d].length+1;s++)if(void 0===u[d][s]){g=s;break}for(p&&n.cellIndex===g||(n.setAttribute?n.setAttribute("data-column",g):A(n).attr("data-column",g)),s=d;s<d+l;s++)for(void 0===u[s]&&(u[s]=[]),f=u[s],a=g;a<g+c;a++)f[a]="x"}return L.checkColumnCount(e,u,f.length),f.length},checkColumnCount:function(e,t,r){var o,s,a=!0,n=[];for(o=0;o<t.length;o++)if(t[o]&&(s=t[o].length,t[o].length!==r)){a=!1;break}a||(e.each(function(e,t){var r=t.parentElement.nodeName;n.indexOf(r)<0&&n.push(r)}),console.error("Invalid or incorrect number of columns in the "+n.join(" or ")+"; expected "+r+", but found "+s+" columns"))},fixColumnWidth:function(e){var t,r,o,s,a,n=(e=A(e)[0]).config,i=n.$table.children("colgroup");if(i.length&&i.hasClass(L.css.colgroup)&&i.remove(),n.widthFixed&&0===n.$table.children("colgroup").length){for(i=A('<colgroup class="'+L.css.colgroup+'">'),t=n.$table.width(),s=(o=n.$tbodies.find("tr:first").children(":visible")).length,a=0;a<s;a++)r=parseInt(o.eq(a).width()/t*1e3,10)/10+"%",i.append(A("<col>").css("width",r));n.$table.prepend(i)}},getData:function(e,t,r){var o,s,a="",n=A(e);return n.length?(o=!!A.metadata&&n.metadata(),s=" "+(n.attr("class")||""),void 0!==n.data(r)||void 0!==n.data(r.toLowerCase())?a+=n.data(r)||n.data(r.toLowerCase()):o&&void 0!==o[r]?a+=o[r]:t&&void 0!==t[r]?a+=t[r]:" "!==s&&s.match(" "+r+"-")&&(a=s.match(new RegExp("\\s"+r+"-([\\w-]+)"))[1]||""),A.trim(a)):""},getColumnData:function(e,t,r,o,s){if("object"!=typeof t||null===t)return t;var a,n=(e=A(e)[0]).config,i=s||n.$headers,d=n.$headerIndexed&&n.$headerIndexed[r]||i.find('[data-column="'+r+'"]:last');if(void 0!==t[r])return o?t[r]:t[i.index(d)];for(a in t)if("string"==typeof a&&d.filter(a).add(d.find(a)).length)return t[a]},isProcessing:function(e,t,r){var o=(e=A(e))[0].config,s=r||e.find("."+L.css.header);t?(void 0!==r&&0<o.sortList.length&&(s=s.filter(function(){return!this.sortDisabled&&0<=L.isValueInArray(parseFloat(A(this).attr("data-column")),o.sortList)})),e.add(s).addClass(L.css.processing+" "+o.cssProcessing)):e.add(s).removeClass(L.css.processing+" "+o.cssProcessing)},processTbody:function(e,t,r){if(e=A(e)[0],r)return e.isProcessing=!0,t.before('<colgroup class="tablesorter-savemyplace"/>'),A.fn.detach?t.detach():t.remove();var o=A(e).find("colgroup.tablesorter-savemyplace");t.insertAfter(o),o.remove(),e.isProcessing=!1},clearTableBody:function(e){A(e)[0].config.$tbodies.children().detach()},characterEquivalents:{a:"áàâãäąå",A:"ÁÀÂÃÄĄÅ",c:"çćč",C:"ÇĆČ",e:"éèêëěę",E:"ÉÈÊËĚĘ",i:"íìİîïı",I:"ÍÌİÎÏ",o:"óòôõöō",O:"ÓÒÔÕÖŌ",ss:"ß",SS:"ẞ",u:"úùûüů",U:"ÚÙÛÜŮ"},replaceAccents:function(e){var t,r="[",o=L.characterEquivalents;if(!L.characterRegex){for(t in L.characterRegexArray={},o)"string"==typeof t&&(r+=o[t],L.characterRegexArray[t]=new RegExp("["+o[t]+"]","g"));L.characterRegex=new RegExp(r+"]")}if(L.characterRegex.test(e))for(t in o)"string"==typeof t&&(e=e.replace(L.characterRegexArray[t],t));return e},validateOptions:function(e){var t,r,o,s,a="headers sortForce sortList sortAppend widgets".split(" "),n=e.originalSettings;if(n){for(t in L.debug(e,"core")&&(s=new Date),n)if("undefined"===(o=typeof L.defaults[t]))console.warn('Tablesorter Warning! "table.config.'+t+'" option not recognized');else if("object"===o)for(r in n[t])o=L.defaults[t]&&typeof L.defaults[t][r],A.inArray(t,a)<0&&"undefined"===o&&console.warn('Tablesorter Warning! "table.config.'+t+"."+r+'" option not recognized');L.debug(e,"core")&&console.log("validate options time:"+L.benchmark(s))}},restoreHeaders:function(e){var t,r,o=A(e)[0].config,s=o.$table.find(o.selectorHeaders),a=s.length;for(t=0;t<a;t++)(r=s.eq(t)).find("."+L.css.headerIn).length&&r.html(o.headerContent[t])},destroy:function(e,t,r){if((e=A(e)[0]).hasInitialized){L.removeWidget(e,!0,!1);var o,s=A(e),a=e.config,n=s.find("thead:first"),i=n.find("tr."+L.css.headerRow).removeClass(L.css.headerRow+" "+a.cssHeaderRow),d=s.find("tfoot:first > tr").children("th, td");!1===t&&0<=A.inArray("uitheme",a.widgets)&&(s.triggerHandler("applyWidgetId",["uitheme"]),s.triggerHandler("applyWidgetId",["zebra"])),n.find("tr").not(i).remove(),o="sortReset update updateRows updateAll updateHeaders updateCell addRows updateComplete sorton appendCache updateCache applyWidgetId applyWidgets refreshWidgets removeWidget destroy mouseup mouseleave "+"keypress sortBegin sortEnd resetToLoadState ".split(" ").join(a.namespace+" "),s.removeData("tablesorter").unbind(o.replace(L.regex.spaces," ")),a.$headers.add(d).removeClass([L.css.header,a.cssHeader,a.cssAsc,a.cssDesc,L.css.sortAsc,L.css.sortDesc,L.css.sortNone].join(" ")).removeAttr("data-column").removeAttr("aria-label").attr("aria-disabled","true"),i.find(a.selectorSort).unbind("mousedown mouseup keypress ".split(" ").join(a.namespace+" ").replace(L.regex.spaces," ")),L.restoreHeaders(e),s.toggleClass(L.css.table+" "+a.tableClass+" tablesorter-"+a.theme,!1===t),s.removeClass(a.namespace.slice(1)),e.hasInitialized=!1,delete e.config.cache,"function"==typeof r&&r(e),L.debug(a,"core")&&console.log("tablesorter has been removed")}}};A.fn.tablesorter=function(t){return this.each(function(){var e=A.extend(!0,{},L.defaults,t,L.instanceMethods);e.originalSettings=t,!this.hasInitialized&&L.buildTable&&"TABLE"!==this.nodeName?L.buildTable(this,e):L.setup(this,e)})},window.console&&window.console.log||(L.logs=[],console={},console.log=console.warn=console.error=console.table=function(){var e=1<arguments.length?arguments:arguments[0];L.logs[L.logs.length]={date:Date.now(),log:e}}),L.addParser({id:"no-parser",is:function(){return!1},format:function(){return""},type:"text"}),L.addParser({id:"text",is:function(){return!0},format:function(e,t){var r=t.config;return e&&(e=A.trim(r.ignoreCase?e.toLocaleLowerCase():e),e=r.sortLocaleCompare?L.replaceAccents(e):e),e},type:"text"}),L.regex.nondigit=/[^\w,. \-()]/g,L.addParser({id:"digit",is:function(e){return L.isDigit(e)},format:function(e,t){var r=L.formatFloat((e||"").replace(L.regex.nondigit,""),t);return e&&"number"==typeof r?r:e?A.trim(e&&t.config.ignoreCase?e.toLocaleLowerCase():e):e},type:"numeric"}),L.regex.currencyReplace=/[+\-,. ]/g,L.regex.currencyTest=/^\(?\d+[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]|[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]\d+\)?$/,L.addParser({id:"currency",is:function(e){return e=(e||"").replace(L.regex.currencyReplace,""),L.regex.currencyTest.test(e)},format:function(e,t){var r=L.formatFloat((e||"").replace(L.regex.nondigit,""),t);return e&&"number"==typeof r?r:e?A.trim(e&&t.config.ignoreCase?e.toLocaleLowerCase():e):e},type:"numeric"}),L.regex.urlProtocolTest=/^(https?|ftp|file):\/\//,L.regex.urlProtocolReplace=/(https?|ftp|file):\/\/(www\.)?/,L.addParser({id:"url",is:function(e){return L.regex.urlProtocolTest.test(e)},format:function(e){return e?A.trim(e.replace(L.regex.urlProtocolReplace,"")):e},type:"text"}),L.regex.dash=/-/g,L.regex.isoDate=/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}/,L.addParser({id:"isoDate",is:function(e){return L.regex.isoDate.test(e)},format:function(e){var t=e?new Date(e.replace(L.regex.dash,"/")):e;return t instanceof Date&&isFinite(t)?t.getTime():e},type:"numeric"}),L.regex.percent=/%/g,L.regex.percentTest=/(\d\s*?%|%\s*?\d)/,L.addParser({id:"percent",is:function(e){return L.regex.percentTest.test(e)&&e.length<15},format:function(e,t){return e?L.formatFloat(e.replace(L.regex.percent,""),t):e},type:"numeric"}),L.addParser({id:"image",is:function(e,t,r,o){return 0<o.find("img").length},format:function(e,t,r){return A(r).find("img").attr(t.config.imgAttr||"alt")||e},parsed:!0,type:"text"}),L.regex.dateReplace=/(\S)([AP]M)$/i,L.regex.usLongDateTest1=/^[A-Z]{3,10}\.?\s+\d{1,2},?\s+(\d{4})(\s+\d{1,2}:\d{2}(:\d{2})?(\s+[AP]M)?)?$/i,L.regex.usLongDateTest2=/^\d{1,2}\s+[A-Z]{3,10}\s+\d{4}/i,L.addParser({id:"usLongDate",is:function(e){return L.regex.usLongDateTest1.test(e)||L.regex.usLongDateTest2.test(e)},format:function(e){var t=e?new Date(e.replace(L.regex.dateReplace,"$1 $2")):e;return t instanceof Date&&isFinite(t)?t.getTime():e},type:"numeric"}),L.regex.shortDateTest=/(^\d{1,2}[\/\s]\d{1,2}[\/\s]\d{4})|(^\d{4}[\/\s]\d{1,2}[\/\s]\d{1,2})/,L.regex.shortDateReplace=/[\-.,]/g,L.regex.shortDateXXY=/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/,L.regex.shortDateYMD=/(\d{4})[\/\s](\d{1,2})[\/\s](\d{1,2})/,L.convertFormat=function(e,t){e=(e||"").replace(L.regex.spaces," ").replace(L.regex.shortDateReplace,"/"),"mmddyyyy"===t?e=e.replace(L.regex.shortDateXXY,"$3/$1/$2"):"ddmmyyyy"===t?e=e.replace(L.regex.shortDateXXY,"$3/$2/$1"):"yyyymmdd"===t&&(e=e.replace(L.regex.shortDateYMD,"$1/$2/$3"));var r=new Date(e);return r instanceof Date&&isFinite(r)?r.getTime():""},L.addParser({id:"shortDate",is:function(e){return e=(e||"").replace(L.regex.spaces," ").replace(L.regex.shortDateReplace,"/"),L.regex.shortDateTest.test(e)},format:function(e,t,r,o){if(e){var s=t.config,a=s.$headerIndexed[o],n=a.length&&a.data("dateFormat")||L.getData(a,L.getColumnData(t,s.headers,o),"dateFormat")||s.dateFormat;return a.length&&a.data("dateFormat",n),L.convertFormat(e,n)||e}return e},type:"numeric"}),L.regex.timeTest=/^(0?[1-9]|1[0-2]):([0-5]\d)(\s[AP]M)$|^((?:[01]\d|[2][0-4]):[0-5]\d)$/i,L.regex.timeMatch=/(0?[1-9]|1[0-2]):([0-5]\d)(\s[AP]M)|((?:[01]\d|[2][0-4]):[0-5]\d)/i,L.addParser({id:"time",is:function(e){return L.regex.timeTest.test(e)},format:function(e){var t=(e||"").match(L.regex.timeMatch),r=new Date(e),o=e&&(null!==t?t[0]:"00:00 AM"),s=o?new Date("2000/01/01 "+o.replace(L.regex.dateReplace,"$1 $2")):o;return s instanceof Date&&isFinite(s)?(r instanceof Date&&isFinite(r)?r.getTime():0)?parseFloat(s.getTime()+"."+r.getTime()):s.getTime():e},type:"numeric"}),L.addParser({id:"metadata",is:function(){return!1},format:function(e,t,r){var o=t.config,s=o.parserMetadataName?o.parserMetadataName:"sortValue";return A(r).metadata()[s]},type:"numeric"}),L.addWidget({id:"zebra",priority:90,format:function(e,t,r){var o,s,a,n,i,d,l,c=new RegExp(t.cssChildRow,"i"),g=t.$tbodies.add(A(t.namespace+"_extra_table").children("tbody:not(."+t.cssInfoBlock+")"));for(i=0;i<g.length;i++)for(a=0,l=(o=g.eq(i).children("tr:visible").not(t.selectorRemove)).length,d=0;d<l;d++)s=o.eq(d),c.test(s[0].className)||a++,n=a%2==0,s.removeClass(r.zebra[n?1:0]).addClass(r.zebra[n?0:1])},remove:function(e,t,r,o){if(!o){var s,a,n=t.$tbodies,i=(r.zebra||["even","odd"]).join(" ");for(s=0;s<n.length;s++)(a=L.processTbody(e,n.eq(s),!0)).children().removeClass(i),L.processTbody(e,a,!1)}}})}(e),e.tablesorter}); diff --git a/website/agenda/planung/js/jquery.tablesorter.scroller.js b/website/agenda/planung/js/jquery.tablesorter.scroller.js deleted file mode 100644 index 6cb97fe..0000000 --- a/website/agenda/planung/js/jquery.tablesorter.scroller.js +++ /dev/null @@ -1,221 +0,0 @@ -/*! - Copyright (C) 2011 T. Connell & Associates, Inc. - - Dual-licensed under the MIT and GPL licenses - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE - FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Resizable scroller widget for the jQuery tablesorter plugin - - Version 2.0 - modified by Rob Garrison 4/12/2013; updated 10/26/2014 (v2.18.0) - Requires jQuery v1.7+ - Requires the tablesorter plugin, v2.8+, available at http://mottie.github.com/tablesorter/docs/ - - Usage: - - $(function() { - - $('table.tablesorter').tablesorter({ - widgets: ['zebra', 'scroller'], - widgetOptions : { - scroller_height : 300, // height of scroll window - scroller_barWidth : 18, // scroll bar width - scroller_jumpToHeader : true, // header snap to browser top when scrolling the tbody - } - }); - - }); - - Website: www.tconnell.com -*/ -/*jshint browser:true, jquery:true, unused:false */ -;(function($){ -"use strict"; - -$.fn.hasScrollBar = function(){ - return this.get(0).scrollHeight > this.height(); -}; -var ts = $.tablesorter; - -ts.window_resize = function(){ - if (this.resize_timer) { - clearTimeout(this.resize_timer); - } - this.resize_timer = setTimeout(function(){ - $(this).trigger('resizeEnd'); - }, 250); -}; - -// Add extra scroller css -$(function(){ - var s = '<style>' + - '.tablesorter-scroller-reset { width: auto !important; } ' + - '.tablesorter-scroller { text-align: left; overflow: hidden; }' + - '.tablesorter-scroller-header { overflow: hidden; }' + - '.tablesorter-scroller-header table.tablesorter { margin-bottom: 0; }' + - '.tablesorter-scroller-table { overflow-y: scroll; }' + - '.tablesorter-scroller-table table.tablesorter { margin-top: 0; overflow: scroll; } ' + - '.tablesorter-scroller-table .tablesorter-filter-row, .tablesorter-scroller-table tfoot { display: none; }' + - '.tablesorter-scroller-table table.tablesorter thead tr.tablesorter-headerRow * {' + - 'line-height:0;height:0;border:none;background-image:none;padding-top:0;padding-bottom:0;margin-top:0;margin-bottom:0;overflow:hidden;' + - '}</style>'; - $(s).appendTo('body'); -}); - -ts.addWidget({ - id: 'scroller', - priority: 60, // run after the filter widget - options: { - scroller_height : 300, - scroller_barWidth : 18, - scroller_jumpToHeader: true, - scroller_upAfterSort: true - }, - init: function(table, thisWidget, c, wo){ - var $win = $(window), - namespace = c.namespace + 'tsscroller'; - // Setup window.resizeEnd event - $win - .bind('resize' + namespace, ts.window_resize) - .bind('resizeEnd' + namespace, function() { - // init is run before format, so scroller_resizeWidth - // won't be defined within the "c" or "wo" parameters - if (typeof table.config.widgetOptions.scroller_resizeWidth === 'function') { - // IE calls resize when you modify content, so we have to unbind the resize event - // so we don't end up with an infinite loop. we can rebind after we're done. - $win.unbind('resize' + namespace, ts.window_resize); - table.config.widgetOptions.scroller_resizeWidth(); - $win.bind('resize' + namespace, ts.window_resize); - } - }); - }, - format: function(table, c, wo) { - var h, $hdr, t, resize, $cells, - // c.namespace contains a unique tablesorter ID, per table - id = c.namespace.slice(1) + 'tsscroller', - $win = $(window), - $tbl = c.$table; - - if (!c.isScrolling) { - h = wo.scroller_height || 300; - t = $tbl.find('tbody').height(); - if (t !== 0 && h > t) { h = t + 10; } // Table is less than h px - - $hdr = $('<table class="' + $tbl.attr('class') + '" cellpadding=0 cellspacing=0><thead>' + $tbl.find('thead:first').html() + '</thead></table>'); - $tbl - .wrap('<div id="' + id + '" class="tablesorter-scroller" />') - .before($hdr) - .find('.tablesorter-filter-row').addClass('hideme'); - - $cells = $hdr - .wrap('<div class="tablesorter-scroller-header" style="width:' + $tbl.width() + ';" />') - .find('.' + ts.css.header); - - $tbl.wrap('<div class="tablesorter-scroller-table" style="height:' + h + 'px;width:' + $tbl.width() + ';" />'); - - // make scroller header sortable - ts.bindEvents(table, $cells); - - // look for filter widget - if ($tbl.hasClass('hasFilters')) { - ts.filter.bindSearch( $tbl, $hdr.find('.' + ts.css.filter) ); - } - - resize = function(){ - var d, b, $h, $th, w, - // Hide other scrollers so we can resize - $div = $('div.scroller[id != "' + id + '"]').hide(); - - $tbl.find('thead').show(); - - // Reset sizes so parent can resize. - $tbl - .addClass('tablesorter-scroller-reset') - .find('thead').find('.tablesorter-header-inner').addClass('tablesorter-scroller-reset'); - d = $tbl.parent(); - d.addClass('tablesorter-scroller-reset'); - - d.parent().trigger('resize'); - - // Shrink a bit to accommodate scrollbar - d.width( d.parent().innerWidth() - ( d.parent().hasScrollBar() ? wo.scroller_barWidth : 0 ) ); - w = d.innerWidth() - ( d.hasScrollBar() ? wo.scroller_barWidth : 0 ); - $tbl.width( w ); - $hdr.width( w ); - $hdr.parent().width( w ); - - $tbl.closest('.tablesorter-scroller').find('.tablesorter-scroller-reset').removeClass('tablesorter-scroller-reset'); - - // include left & right border widths - b = parseInt( $tbl.css('border-left-width'), 10 ) + parseInt( $tbl.css('border-right-width'), 10 ); - $h = $hdr.find('thead').children().children(); - - // adjust cloned header to match original table width - includes wrappers, headers, and header inner div - $tbl.find('thead').children().children().each(function(i, c){ - $th = $(c).find('.tablesorter-header-inner'); - if ($th.length) { - // I have no idea why this is in here anymore LOL - w = parseInt( $th.css('min-width').replace('auto', '0').replace(/(px|em)/, ''), 10 ); - if ( $th.width() < w ) { - $th.width(w); - } else { - w = $th.width(); - } - $h.eq(i) - .find('.tablesorter-header-inner').width(w - b) - // set inner width first - .parent() - .width( $th.parent().width() - b ); - } - }); - - $div.show(); - }; - - // Expose to external calls - wo.scroller_resizeWidth = resize; - - resize(); - - $tbl.find('thead').css('visibility', 'hidden'); - c.isScrolling = true; - - t = $tbl.parent().parent().height(); - - // The header will always jump into view if scrolling the table body - $tbl.parent().bind('scroll', function(){ - if (wo.scroller_jumpToHeader) { - var pos = $win.scrollTop() - $hdr.offset().top; - if ($(this).scrollTop() !== 0 && pos < t && pos > 0) { - $win.scrollTop( $hdr.offset().top ); - } - } - $hdr.parent().scrollLeft( $(this).scrollLeft() ); - }); - - } - - // Sorting, so scroll to top - if (wo.scroller_upAfterSort) { - $tbl.parent().animate({ scrollTop: 0 }, 'fast'); - } - - }, - remove : function(table, c){ - var $table = c.$table, - namespace = c.namespace + 'tsscroller'; - $table.closest('.tablesorter-scroller').find('.tablesorter-scroller-header').remove(); - $table - .unwrap() - .find('.tablesorter-filter-row').removeClass('hideme').end() - .find('thead').show().css('visibility', 'visible'); - $(window).unbind('resize' + namespace + ' resizeEnd' + namespace); - c.isScrolling = false; - } -}); - -})(jQuery); - diff --git a/website/agenda/planung/js/jquery.tablesorter.widgets.min.js b/website/agenda/planung/js/jquery.tablesorter.widgets.min.js deleted file mode 100644 index 1ec9d9f..0000000 --- a/website/agenda/planung/js/jquery.tablesorter.widgets.min.js +++ /dev/null @@ -1,17 +0,0 @@ -/*! tableSorter 2.16+ widgets - updated 9/15/2014 (v2.17.8) */ -;(function(k){ -var c=k.tablesorter=k.tablesorter||{}; -c.themes={bootstrap:{table:"table table-bordered table-striped",caption:"caption",header:"bootstrap-header",footerRow:"",footerCells:"",icons:"",sortNone:"bootstrap-icon-unsorted",sortAsc:"icon-chevron-up glyphicon glyphicon-chevron-up",sortDesc:"icon-chevron-down glyphicon glyphicon-chevron-down",active:"",hover:"",filterRow:"",even:"",odd:""},jui:{table:"ui-widget ui-widget-content ui-corner-all",caption:"ui-widget-content ui-corner-all",header:"ui-widget-header ui-corner-all ui-state-default", footerRow:"",footerCells:"",icons:"ui-icon",sortNone:"ui-icon-carat-2-n-s",sortAsc:"ui-icon-carat-1-n",sortDesc:"ui-icon-carat-1-s",active:"ui-state-active",hover:"ui-state-hover",filterRow:"",even:"ui-widget-content",odd:"ui-state-default"}};k.extend(c.css,{filterRow:"tablesorter-filter-row",filter:"tablesorter-filter",wrapper:"tablesorter-wrapper",resizer:"tablesorter-resizer",sticky:"tablesorter-stickyHeader",stickyVis:"tablesorter-sticky-visible"}); -c.storage=function(d,a,b,e){d=k(d)[0];var c, h,g=!1;c={};h=d.config;var n=k(d);d=e&&e.id||n.attr(e&&e.group||"data-table-group")||d.id||k(".tablesorter").index(n);e=e&&e.url||n.attr(e&&e.page||"data-table-page")||h&&h.fixedUrl||window.location.pathname;if("localStorage"in window)try{window.localStorage.setItem("_tmptest","temp"),g=!0,window.localStorage.removeItem("_tmptest")}catch(l){}k.parseJSON&&(g?c=k.parseJSON(localStorage[a]||"{}"):(h=document.cookie.split(/[;\s|=]/),c=k.inArray(a,h)+1,c=0!==c?k.parseJSON(h[c]||"{}"):{}));if((b||""=== b)&&window.JSON&&JSON.hasOwnProperty("stringify"))c[e]||(c[e]={}),c[e][d]=b,g?localStorage[a]=JSON.stringify(c):(b=new Date,b.setTime(b.getTime()+31536E6),document.cookie=a+"="+JSON.stringify(c).replace(/\"/g,'"')+"; expires="+b.toGMTString()+"; path=/");else return c&&c[e]?c[e][d]:""}; -c.addHeaderResizeEvent=function(d,a,b){d=k(d)[0];var c;b=k.extend({},{timer:250},b);var f=d.config,h=f.widgetOptions,g=function(a){h.resize_flag=!0;c=[];f.$headers.each(function(){var a=k(this),b=a.data("savedSizes")|| [0,0],d=this.offsetWidth,f=this.offsetHeight;if(d!==b[0]||f!==b[1])a.data("savedSizes",[d,f]),c.push(this)});c.length&&!1!==a&&f.$table.trigger("resize",[c]);h.resize_flag=!1};g(!1);clearInterval(h.resize_timer);if(a)return h.resize_flag=!1;h.resize_timer=setInterval(function(){h.resize_flag||g()},b.timer)}; -c.addWidget({id:"uitheme",priority:10,format:function(d,a,b){var e,f,h,g=c.themes;e=a.$table;h=a.$headers;var n=a.theme||"jui",l=g[n]||g.jui,g=l.sortNone+" "+l.sortDesc+" "+l.sortAsc;a.debug&& (f=new Date);e.hasClass("tablesorter-"+n)&&a.theme!==n&&d.hasInitialized||(""!==l.even&&(b.zebra[0]+=" "+l.even),""!==l.odd&&(b.zebra[1]+=" "+l.odd),e.find("caption").addClass(l.caption),d=e.removeClass(""===a.theme?"":"tablesorter-"+a.theme).addClass("tablesorter-"+n+" "+l.table).find("tfoot"),d.length&&d.find("tr").addClass(l.footerRow).children("th, td").addClass(l.footerCells),h.addClass(l.header).not(".sorter-false").bind("mouseenter.tsuitheme mouseleave.tsuitheme",function(a){k(this)["mouseenter"=== a.type?"addClass":"removeClass"](l.hover)}),h.find("."+c.css.wrapper).length||h.wrapInner('<div class="'+c.css.wrapper+'" style="position:relative;height:100%;width:100%"></div>'),a.cssIcon&&h.find("."+c.css.icon).addClass(l.icons),e.hasClass("hasFilters")&&h.find("."+c.css.filterRow).addClass(l.filterRow));for(e=0;e<a.columns;e++)h=a.$headers.add(a.$extraHeaders).filter('[data-column="'+e+'"]'),d=c.css.icon?h.find("."+c.css.icon):h,b=a.$headers.filter('[data-column="'+e+'"]:last'),b.length&&(b[0].sortDisabled? (h.removeClass(g),d.removeClass(g+" "+l.icons)):(b=h.hasClass(c.css.sortAsc)?l.sortAsc:h.hasClass(c.css.sortDesc)?l.sortDesc:h.hasClass(c.css.header)?l.sortNone:"",h[b===l.sortNone?"removeClass":"addClass"](l.active),d.removeClass(g).addClass(b)));a.debug&&c.benchmark("Applying "+n+" theme",f)},remove:function(d,a){var b=a.$table,e=a.theme||"jui",f=c.themes[e]||c.themes.jui,h=b.children("thead").children(),g=f.sortNone+" "+f.sortDesc+" "+f.sortAsc;b.removeClass("tablesorter-"+e+" "+f.table).find(c.css.header).removeClass(f.header); h.unbind("mouseenter.tsuitheme mouseleave.tsuitheme").removeClass(f.hover+" "+g+" "+f.active).find("."+c.css.filterRow).removeClass(f.filterRow);h.find("."+c.css.icon).removeClass(f.icons)}}); -c.addWidget({id:"columns",priority:30,options:{columns:["primary","secondary","tertiary"]},format:function(d,a,b){var e,f,h,g,n,l,r,p,s=a.$table,t=a.$tbodies,x=a.sortList,w=x.length,v=b&&b.columns||["primary","secondary","tertiary"],A=v.length-1;r=v.join(" ");a.debug&&(e=new Date);for(h=0;h<t.length;h++)f=c.processTbody(d, t.eq(h),!0),g=f.children("tr"),g.each(function(){n=k(this);if("none"!==this.style.display&&(l=n.children().removeClass(r),x&&x[0]&&(l.eq(x[0][0]).addClass(v[0]),1<w)))for(p=1;p<w;p++)l.eq(x[p][0]).addClass(v[p]||v[A])}),c.processTbody(d,f,!1);d=!1!==b.columns_thead?["thead tr"]:[];!1!==b.columns_tfoot&&d.push("tfoot tr");if(d.length&&(g=s.find(d.join(",")).children().removeClass(r),w))for(p=0;p<w;p++)g.filter('[data-column="'+x[p][0]+'"]').addClass(v[p]||v[A]);a.debug&&c.benchmark("Applying Columns widget", e)},remove:function(d,a,b){var e=a.$tbodies,f=(b.columns||["primary","secondary","tertiary"]).join(" ");a.$headers.removeClass(f);a.$table.children("tfoot").children("tr").children("th, td").removeClass(f);for(a=0;a<e.length;a++)b=c.processTbody(d,e.eq(a),!0),b.children("tr").each(function(){k(this).children().removeClass(f)}),c.processTbody(d,b,!1)}}); -c.addWidget({id:"filter",priority:50,options:{filter_childRows:!1,filter_columnFilters:!0,filter_cssFilter:"",filter_defaultFilter:{},filter_excludeFilter:{}, filter_external:"",filter_filteredRow:"filtered",filter_formatter:null,filter_functions:null,filter_hideEmpty:!0,filter_hideFilters:!1,filter_ignoreCase:!0,filter_liveSearch:!0,filter_onlyAvail:"filter-onlyAvail",filter_placeholder:{search:"",select:""},filter_reset:null,filter_saveFilters:!1,filter_searchDelay:300,filter_searchFiltered:!0,filter_selectSource:null,filter_startsWith:!1,filter_useParsedData:!1,filter_serversideFiltering:!1,filter_defaultAttrib:"data-value",filter_selectSourceSeparator:"|"}, format:function(d,a,b){a.$table.hasClass("hasFilters")||c.filter.init(d,a,b)},remove:function(d,a,b){var e,f=a.$tbodies;a.$table.removeClass("hasFilters").unbind("addRows updateCell update updateRows updateComplete appendCache filterReset filterEnd search ".split(" ").join(a.namespace+"filter ")).find("."+c.css.filterRow).remove();for(a=0;a<f.length;a++)e=c.processTbody(d,f.eq(a),!0),e.children().removeClass(b.filter_filteredRow).show(),c.processTbody(d,e,!1);b.filter_reset&&k(document).undelegate(b.filter_reset, "click.tsfilter")}}); -c.filter={regex:{regex:/^\/((?:\\\/|[^\/])+)\/([mig]{0,3})?$/,child:/tablesorter-childRow/,filtered:/filtered/,type:/undefined|number/,exact:/(^[\"|\'|=]+)|([\"|\'|=]+$)/g,nondigit:/[^\w,. \-()]/g,operators:/[<>=]/g,query:"(q|query)"},types:{regex:function(d,a){if(c.filter.regex.regex.test(a.iFilter)){var b,e=c.filter.regex.regex.exec(a.iFilter);try{b=(new RegExp(e[1],e[2])).test(a.iExact)}catch(f){b=!1}return b}return null},operators:function(d,a){if(/^[<>]=?/.test(a.iFilter)){var b, e;b=d.table;var f=a.index,h=a.parsed[f],g=c.formatFloat(a.iFilter.replace(c.filter.regex.operators,""),b),n=d.parsers[f],l=g;if(h||"numeric"===n.type)e=c.filter.parseFilter(d,k.trim(""+a.iFilter.replace(c.filter.regex.operators,"")),f,h,!0),g="number"!==typeof e||""===e||isNaN(e)?g:e;b=!h&&"numeric"!==n.type||isNaN(g)||"undefined"===typeof a.cache?isNaN(a.iExact)?c.formatFloat(a.iExact.replace(c.filter.regex.nondigit,""),b):c.formatFloat(a.iExact,b):a.cache;/>/.test(a.iFilter)&&(e=/>=/.test(a.iFilter)? b>=g:b>g);/</.test(a.iFilter)&&(e=/<=/.test(a.iFilter)?b<=g:b<g);e||""!==l||(e=!0);return e}return null},notMatch:function(d,a){if(/^\!/.test(a.iFilter)){var b,e=c.filter.parseFilter(d,a.iFilter.replace("!",""),a.index,a.parsed[a.index]);if(c.filter.regex.exact.test(e))return e=e.replace(c.filter.regex.exact,""),""===e?!0:k.trim(e)!==a.iExact;b=a.iExact.search(k.trim(e));return""===e?!0:!(d.widgetOptions.filter_startsWith?0===b:0<=b)}return null},exact:function(d,a){if(c.filter.regex.exact.test(a.iFilter)){var b= c.filter.parseFilter(d,a.iFilter.replace(c.filter.regex.exact,""),a.index,a.parsed[a.index]);return a.anyMatch?0<=k.inArray(b,a.rowArray):b==a.iExact}return null},and:function(d,a){if(c.filter.regex.andTest.test(a.filter)){for(var b=a.index,e=a.parsed[b],f=a.iFilter.split(c.filter.regex.andSplit),h=0<=a.iExact.search(k.trim(c.filter.parseFilter(d,f[0],b,e))),g=f.length-1;h&&g;)h=h&&0<=a.iExact.search(k.trim(c.filter.parseFilter(d,f[g],b,e))),g--;return h}return null},range:function(d,a){if(c.filter.regex.toTest.test(a.iFilter)){var b, e;e=d.table;var f=a.index,h=a.parsed[f],g=a.iFilter.split(c.filter.regex.toSplit),k=c.formatFloat(c.filter.parseFilter(d,g[0].replace(c.filter.regex.nondigit,""),f,h),e),l=c.formatFloat(c.filter.parseFilter(d,g[1].replace(c.filter.regex.nondigit,""),f,h),e);if(h||"numeric"===d.parsers[f].type)b=d.parsers[f].format(""+g[0],e,d.$headers.eq(f),f),k=""===b||isNaN(b)?k:b,b=d.parsers[f].format(""+g[1],e,d.$headers.eq(f),f),l=""===b||isNaN(b)?l:b;b=!h&&"numeric"!==d.parsers[f].type||isNaN(k)||isNaN(l)?isNaN(a.iExact)? c.formatFloat(a.iExact.replace(c.filter.regex.nondigit,""),e):c.formatFloat(a.iExact,e):a.cache;k>l&&(e=k,k=l,l=e);return b>=k&&b<=l||""===k||""===l}return null},wild:function(d,a){if(/[\?|\*]/.test(a.iFilter)||c.filter.regex.orReplace.test(a.filter)){var b=a.index,e=a.parsed[b],e=c.filter.parseFilter(d,a.iFilter.replace(c.filter.regex.orReplace,"|"),b,e);!d.$headers.filter('[data-column="'+b+'"]:last').hasClass("filter-match")&&/\|/.test(e)&&(e=a.anyMatch&&k.isArray(a.rowArray)?"("+e+")":"^("+e+ ")$");return(new RegExp(e.replace(/\?/g,"\\S{1}").replace(/\*/g,"\\S*"))).test(a.iExact)}return null},fuzzy:function(d,a){if(/^~/.test(a.iFilter)){var b,e=0,f=a.iExact.length,h=c.filter.parseFilter(d,a.iFilter.slice(1),a.index,a.parsed[a.index]);for(b=0;b<f;b++)a.iExact[b]===h[e]&&(e+=1);return e===h.length?!0:!1}return null}},init:function(d,a,b){c.language=k.extend(!0,{},{to:"to",or:"or",and:"and"},c.language);var e,f,h,g,n,l,r,p;e=c.filter.regex;a.debug&&(p=new Date);a.$table.addClass("hasFilters"); b.searchTimer=null;b.filter_initTimer=null;b.filter_formatterCount=0;b.filter_formatterInit=[];b.filter_initializing=!0;h="\\{"+c.filter.regex.query+"\\}";k.extend(e,{child:new RegExp(a.cssChildRow),filtered:new RegExp(b.filter_filteredRow),alreadyFiltered:new RegExp("(\\s+("+c.language.or+"|-|"+c.language.to+")\\s+)","i"),toTest:new RegExp("\\s+(-|"+c.language.to+")\\s+","i"),toSplit:new RegExp("(?:\\s+(?:-|"+c.language.to+")\\s+)","gi"),andTest:new RegExp("\\s+("+c.language.and+"|&&)\\s+","i"), andSplit:new RegExp("(?:\\s+(?:"+c.language.and+"|&&)\\s+)","gi"),orReplace:new RegExp("\\s+("+c.language.or+")\\s+","gi"),iQuery:new RegExp(h,"i"),igQuery:new RegExp(h,"ig")});!1!==b.filter_columnFilters&&a.$headers.filter(".filter-false, .parser-false").length!==a.$headers.length&&c.filter.buildRow(d,a,b);a.$table.bind("addRows updateCell update updateRows updateComplete appendCache filterReset filterEnd search ".split(" ").join(a.namespace+"filter "),function(e,f){a.$table.find("."+c.css.filterRow).toggle(!(b.filter_hideEmpty&& k.isEmptyObject(a.cache)&&(!a.delayInit||"appendCache"!==e.type)));/(search|filter)/.test(e.type)||(e.stopPropagation(),c.filter.buildDefault(d,!0));"filterReset"===e.type?(a.$table.find("."+c.css.filter).add(b.filter_$externalFilters).val(""),c.filter.searching(d,[])):"filterEnd"===e.type?c.filter.buildDefault(d,!0):(f="search"===e.type?f:"updateComplete"===e.type?a.$table.data("lastSearch"):"",/(update|add)/.test(e.type)&&"updateComplete"!==e.type&&(a.lastCombinedFilter=null,a.lastSearch=[]),c.filter.searching(d, f,!0));return!1});b.filter_reset&&(b.filter_reset instanceof k?b.filter_reset.click(function(){a.$table.trigger("filterReset")}):k(b.filter_reset).length&&k(document).undelegate(b.filter_reset,"click.tsfilter").delegate(b.filter_reset,"click.tsfilter",function(){a.$table.trigger("filterReset")}));if(b.filter_functions)for(n=0;n<a.columns;n++)if(h=c.getColumnData(d,b.filter_functions,n))if(g=a.$headers.filter('[data-column="'+n+'"]:last').removeClass("filter-select"),r=!(g.hasClass("filter-false")|| g.hasClass("parser-false")),e="",!0===h&&r)c.filter.buildSelect(d,n);else if("object"===typeof h&&r){for(f in h)"string"===typeof f&&(e+=""===e?'<option value="">'+(g.data("placeholder")||g.attr("data-placeholder")||b.filter_placeholder.select||"")+"</option>":"",h=r=f,0<=f.indexOf(b.filter_selectSourceSeparator)&&(r=f.split(b.filter_selectSourceSeparator),h=r[1],r=r[0]),e+="<option "+(h===r?"":'data-function-name="'+f+'" ')+'value="'+r+'">'+h+"</option>");a.$table.find("thead").find("select."+c.css.filter+ '[data-column="'+n+'"]').append(e)}c.filter.buildDefault(d,!0);c.filter.bindSearch(d,a.$table.find("."+c.css.filter),!0);b.filter_external&&c.filter.bindSearch(d,b.filter_external);b.filter_hideFilters&&c.filter.hideFilters(d,a);a.showProcessing&&a.$table.bind("filterStart"+a.namespace+"filter filterEnd"+a.namespace+"filter",function(b,e){g=e?a.$table.find("."+c.css.header).filter("[data-column]").filter(function(){return""!==e[k(this).data("column")]}):"";c.isProcessing(d,"filterStart"===b.type, e?g:"")});a.filteredRows=a.totalRows;a.debug&&c.benchmark("Applying Filter widget",p);a.$table.bind("tablesorter-initialized pagerInitialized",function(){var b=this.config.widgetOptions;l=c.filter.setDefaults(d,a,b)||[];l.length&&(a.delayInit&&""===l.join("")||c.setFilters(d,l,!0));a.$table.trigger("filterFomatterUpdate");setTimeout(function(){b.filter_initialized||c.filter.filterInitComplete(a)},100)});a.pager&&a.pager.initialized&&!b.filter_initialized&&(a.$table.trigger("filterFomatterUpdate"), setTimeout(function(){c.filter.filterInitComplete(a)},100))},formatterUpdated:function(c,a){var b=c.closest("table")[0].config.widgetOptions;b.filter_initialized||(b.filter_formatterInit[a]=1)},filterInitComplete:function(d){var a=d.widgetOptions,b=0,e=function(){a.filter_initialized=!0;a.filter_initializing=!1;c.filter.findRows(d.table,d.$table.data("lastSearch"),null);d.$table.trigger("filterInit",d)};k.each(a.filter_formatterInit,function(a,c){1===c&&b++});clearTimeout(a.filter_initTimer);a.filter_initialized|| b!==a.filter_formatterCount?a.filter_initialized||(a.filter_initTimer=setTimeout(function(){e()},500)):e()},setDefaults:function(d,a,b){var e,f=c.getFilters(d)||[];b.filter_saveFilters&&c.storage&&(e=c.storage(d,"tablesorter-filters")||[],(d=k.isArray(e))&&""===e.join("")||!d||(f=e));if(""===f.join(""))for(d=0;d<a.columns;d++)f[d]=a.$headers.filter('[data-column="'+d+'"]:last').attr(b.filter_defaultAttrib)||f[d];a.$table.data("lastSearch",f);return f},parseFilter:function(c,a,b,e,f){return f||e?c.parsers[b].format(a, c.table,[],b):a},buildRow:function(d,a,b){var e,f,h,g,n=a.columns;g='<tr role="row" class="'+c.css.filterRow+'">';for(f=0;f<n;f++)g+="<td></td>";a.$filters=k(g+"</tr>").appendTo(a.$table.children("thead").eq(0)).find("td");for(f=0;f<n;f++)h=a.$headers.filter('[data-column="'+f+'"]:last'),g=c.getColumnData(d,b.filter_functions,f),g=b.filter_functions&&g&&"function"!==typeof g||h.hasClass("filter-select"),e=c.getColumnData(d,a.headers,f),e="false"===c.getData(h[0],e,"filter")||"false"===c.getData(h[0], e,"parser"),g?g=k("<select>").appendTo(a.$filters.eq(f)):((g=c.getColumnData(d,b.filter_formatter,f))?(b.filter_formatterCount++,(g=g(a.$filters.eq(f),f))&&0===g.length&&(g=a.$filters.eq(f).children("input")),g&&(0===g.parent().length||g.parent().length&&g.parent()[0]!==a.$filters[f])&&a.$filters.eq(f).append(g)):g=k('<input type="search">').appendTo(a.$filters.eq(f)),g&&g.attr("placeholder",h.data("placeholder")||h.attr("data-placeholder")||b.filter_placeholder.search||"")),g&&(h=(k.isArray(b.filter_cssFilter)? "undefined"!==typeof b.filter_cssFilter[f]?b.filter_cssFilter[f]||"":"":b.filter_cssFilter)||"",g.addClass(c.css.filter+" "+h).attr("data-column",f),e&&(g.attr("placeholder","").addClass("disabled")[0].disabled=!0))},bindSearch:function(d,a,b){d=k(d)[0];a=k(a);if(a.length){var e=d.config,f=e.widgetOptions,h=f.filter_$externalFilters;!0!==b&&(f.filter_$anyMatch=a.filter('[data-column="all"]'),f.filter_$externalFilters=h&&h.length?f.filter_$externalFilters.add(a):a,c.setFilters(d,e.$table.data("lastSearch")|| [],!1===b));a.attr("data-lastSearchTime",(new Date).getTime()).unbind(["keypress","keyup","search","change",""].join(e.namespace+"filter ")).bind("keyup"+e.namespace+"filter",function(a){k(this).attr("data-lastSearchTime",(new Date).getTime());if(27===a.which)this.value="";else if(!1===f.filter_liveSearch||""!==this.value&&("number"===typeof f.filter_liveSearch&&this.value.length<f.filter_liveSearch||13!==a.which&&8!==a.which&&(32>a.which||37<=a.which&&40>=a.which)))return;c.filter.searching(d,!0, !0)}).bind(["search","change","keypress",""].join(e.namespace+"filter "),function(a){var b=k(this).data("column");if(13===a.which||"search"===a.type||"change"===a.type&&this.value!==e.lastSearch[b])a.preventDefault(),k(this).attr("data-lastSearchTime",(new Date).getTime()),c.filter.searching(d,!1,!0)})}},searching:function(d,a,b){var e=d.config.widgetOptions;clearTimeout(e.searchTimer);"undefined"===typeof a||!0===a?e.searchTimer=setTimeout(function(){c.filter.checkFilters(d,a,b)},e.filter_liveSearch? e.filter_searchDelay:10):c.filter.checkFilters(d,a,b)},checkFilters:function(d,a,b){var e=d.config,f=e.widgetOptions,h=k.isArray(a),g=h?a:c.getFilters(d,!0),n=(g||[]).join("");if(k.isEmptyObject(e.cache))e.delayInit&&e.pager&&e.pager.initialized&&e.$table.trigger("updateCache",[function(){c.filter.checkFilters(d,!1,b)}]);else if(h&&(c.setFilters(d,g,!1,!0!==b),f.filter_initialized||(e.lastCombinedFilter="")),f.filter_hideFilters&&e.$table.find("."+c.css.filterRow).trigger(""===n?"mouseleave":"mouseenter"), e.lastCombinedFilter!==n||!1===a)if(!1===a&&(e.lastCombinedFilter=null,e.lastSearch=[]),f.filter_initialized&&e.$table.trigger("filterStart",[g]),e.showProcessing)setTimeout(function(){c.filter.findRows(d,g,n);return!1},30);else return c.filter.findRows(d,g,n),!1},hideFilters:function(d,a){var b,e,f;k(d).find("."+c.css.filterRow).addClass("hideme").bind("mouseenter mouseleave",function(c){b=k(this);clearTimeout(f);f=setTimeout(function(){/enter|over/.test(c.type)?b.removeClass("hideme"):k(document.activeElement).closest("tr")[0]!== b[0]&&""===a.lastCombinedFilter&&b.addClass("hideme")},200)}).find("input, select").bind("focus blur",function(b){e=k(this).closest("tr");clearTimeout(f);f=setTimeout(function(){if(""===c.getFilters(a.$table).join(""))e["focus"===b.type?"removeClass":"addClass"]("hideme")},200)})},defaultFilter:function(d,a){if(""===d)return d;var b=c.filter.regex.iQuery,e=a.match(c.filter.regex.igQuery).length,f=1<e?k.trim(d).split(/\s/):[k.trim(d)],h=f.length-1,g=0,n=a;for(1>h&&1<e&&(f[1]=f[0]);b.test(n);)n=n.replace(b, f[g++]||""),b.test(n)&&g<h&&""!==(f[g]||"")&&(n=a.replace(b,n));return n},findRows:function(d,a,b){if(d.config.lastCombinedFilter!==b&&!d.config.widgetOptions.filter_initializing){var e,f,h,g,n,l,r,p,s,t,x,w,v,A,y,z,B,G,C,E,D=c.filter.regex,q=d.config,u=q.widgetOptions,F=q.$table.children("tbody"),m={anyMatch:!1},H=["range","notMatch","operators"];m.parsed=q.$headers.map(function(a){return q.parsers&&q.parsers[a]&&q.parsers[a].parsed||c.getData&&"parsed"===c.getData(q.$headers.filter('[data-column="'+ a+'"]:last'),c.getColumnData(d,q.headers,a),"filter")||k(this).hasClass("filter-parsed")}).get();q.debug&&(A=new Date);q.filteredRows=0;for(g=q.totalRows=0;g<F.length;g++)if(!F.eq(g).hasClass(q.cssInfoBlock||c.css.info)){n=c.processTbody(d,F.eq(g),!0);p=q.columns;f=k(k.map(q.cache[g].normalized,function(a){return a[p].$row.get()}));if(""===b||u.filter_serversideFiltering)f.removeClass(u.filter_filteredRow).not("."+q.cssChildRow).show();else{f=f.not("."+q.cssChildRow);e=f.length;z=u.filter_searchFiltered; h=q.lastSearch||q.$table.data("lastSearch")||[];if(z)for(l=0;l<p+1;l++)y=a[l]||"",z||(l=p),z=z&&h.length&&0===y.indexOf(h[l]||"")&&!D.alreadyFiltered.test(y)&&!/[=\"\|!]/.test(y)&&!(/(>=?\s*-\d)/.test(y)||/(<=?\s*\d)/.test(y))&&!(""!==y&&q.$filters&&q.$filters.eq(l).find("select").length&&!q.$headers.filter('[data-column="'+l+'"]:last').hasClass("filter-match"));y=f.not("."+u.filter_filteredRow).length;z&&0===y&&(z=!1);q.debug&&c.log("Searching through "+(z&&y<e?y:"all")+" rows");if(u.filter_$anyMatch&& u.filter_$anyMatch.length||a[q.columns])m.anyMatchFlag=!0,m.anyMatchFilter=u.filter_$anyMatch&&u.filter_$anyMatch.val()||a[q.columns]||"",q.sortLocaleCompare&&(m.anyMatchFilter=c.replaceAccents(m.anyMatchFilter)),u.filter_defaultFilter&&D.iQuery.test(c.getColumnData(d,u.filter_defaultFilter,q.columns,!0)||"")&&(m.anyMatchFilter=c.filter.defaultFilter(m.anyMatchFilter,c.getColumnData(d,u.filter_defaultFilter,q.columns,!0)),z=!1),m.iAnyMatchFilter=m.anyMatchFilter;for(h=0;h<e;h++)if(m.cacheArray=q.cache[g].normalized[h], s=f[h].className,!(D.child.test(s)||z&&D.filtered.test(s))){v=!0;s=f.eq(h).nextUntil("tr:not(."+q.cssChildRow+")");m.childRowText=s.length&&u.filter_childRows?s.text():"";m.childRowText=u.filter_ignoreCase?m.childRowText.toLocaleLowerCase():m.childRowText;l=f.eq(h).children();if(m.anyMatchFlag){m.anyMatch=!0;m.rowArray=l.map(function(a){m.parsed[a]?a=m.cacheArray[a]:(a=u.filter_ignoreCase?k(this).text().toLowerCase():k(this).text(),q.sortLocaleCompare&&(a=c.replaceAccents(a)));return a}).get();m.filter= m.anyMatchFilter;m.iFilter=m.iAnyMatchFilter;m.exact=m.rowArray.join(" ");m.iExact=m.exact.toLowerCase();m.cache=m.cacheArray.slice(0,-1).join(" ");B=null;k.each(c.filter.types,function(a,b){if(0>k.inArray(a,H)&&(x=b(q,m),null!==x))return B=x,!1});if(null!==B)v=B;else if(u.filter_startsWith)for(v=!1,p=q.columns;!v&&0<p;)p--,v=v||0===m.rowArray[p].indexOf(m.iFilter);else v=0<=(m.iExact+m.childRowText).indexOf(m.iFilter);m.anyMatch=!1}for(p=0;p<q.columns;p++)m.filter=a[p],m.index=p,G=(c.getColumnData(d, u.filter_excludeFilter,p,!0)||"").split(/\s+/),m.filter&&(m.cache=m.cacheArray[p],u.filter_useParsedData||m.parsed[p]?m.exact=m.cache:(m.exact=k.trim(l.eq(p).text()),m.exact=q.sortLocaleCompare?c.replaceAccents(m.exact):m.exact),m.iExact=!D.type.test(typeof m.exact)&&u.filter_ignoreCase?m.exact.toLocaleLowerCase():m.exact,w=v,E=u.filter_columnFilters?q.$filters.add(q.$externalFilters).filter('[data-column="'+p+'"]').find("select option:selected").attr("data-function-name")||"":"",m.filter=q.sortLocaleCompare? c.replaceAccents(m.filter):m.filter,y=!0,u.filter_defaultFilter&&D.iQuery.test(c.getColumnData(d,u.filter_defaultFilter,p)||"")&&(m.filter=c.filter.defaultFilter(m.filter,c.getColumnData(d,u.filter_defaultFilter,p)),y=!1),m.iFilter=u.filter_ignoreCase?(m.filter||"").toLocaleLowerCase():m.filter,C=c.getColumnData(d,u.filter_functions,p),r=q.$headers.filter('[data-column="'+p+'"]:last'),t=r.hasClass("filter-select"),C||t&&y?!0===C||t?w=r.hasClass("filter-match")?0<=m.iExact.search(m.iFilter):m.filter=== m.exact:"function"===typeof C?w=C(m.exact,m.cache,m.filter,p,f.eq(h)):"function"===typeof C[E||m.filter]&&(w=C[E||m.filter](m.exact,m.cache,m.filter,p,f.eq(h))):(B=null,k.each(c.filter.types,function(a,b){if(0>k.inArray(a,G)&&(x=b(q,m),null!==x))return B=x,!1}),null!==B?w=B:(m.exact=(m.iExact+m.childRowText).indexOf(c.filter.parseFilter(q,m.iFilter,p,m.parsed[p])),w=!u.filter_startsWith&&0<=m.exact||u.filter_startsWith&&0===m.exact)),v=w?v:!1);f.eq(h).toggle(v).toggleClass(u.filter_filteredRow,!v); s.length&&s.toggleClass(u.filter_filteredRow,!v)}}q.filteredRows+=f.not("."+u.filter_filteredRow).length;q.totalRows+=f.length;c.processTbody(d,n,!1)}q.lastCombinedFilter=b;q.lastSearch=a;q.$table.data("lastSearch",a);u.filter_saveFilters&&c.storage&&c.storage(d,"tablesorter-filters",a);q.debug&&c.benchmark("Completed filter widget search",A);u.filter_initialized&&q.$table.trigger("filterEnd",q);setTimeout(function(){q.$table.trigger("applyWidgets")},0)}},getOptionSource:function(d,a,b){var e,f=d.config, h=[],g=!1,n=f.widgetOptions.filter_selectSource,l=f.$table.data("lastSearch")||[],r=k.isFunction(n)?!0:c.getColumnData(d,n,a);b&&""!==l[a]&&(b=!1);if(!0===r)g=n(d,a,b);else{if(r instanceof k||"string"===k.type(r)&&0<=r.indexOf("</option>"))return r;k.isArray(r)?g=r:"object"===k.type(n)&&r&&(g=r(d,a,b))}!1===g&&(g=c.filter.getOptions(d,a,b));g=k.grep(g,function(a,b){return k.inArray(a,g)===b});f.$headers.filter('[data-column="'+a+'"]:last').hasClass("filter-select-nosort")||(k.each(g,function(b,c){h.push({t:c, p:f.parsers&&f.parsers[a].format(c,d,[],a)})}),e=f.textSorter||"",h.sort(function(b,f){var g=b.p.toString(),h=f.p.toString();return k.isFunction(e)?e(g,h,!0,a,d):"object"===typeof e&&e.hasOwnProperty(a)?e[a](g,h,!0,a,d):c.sortNatural?c.sortNatural(g,h):!0}),g=[],k.each(h,function(a,b){g.push(b.t)}));return g},getOptions:function(c,a,b){var e,f,h,g,n=c.config,l=n.widgetOptions,r=n.$table.children("tbody"),p=[];for(e=0;e<r.length;e++)if(!r.eq(e).hasClass(n.cssInfoBlock))for(g=n.cache[e],f=n.cache[e].normalized.length, c=0;c<f;c++)h=g.row?g.row[c]:g.normalized[c][n.columns].$row[0],b&&h.className.match(l.filter_filteredRow)||(l.filter_useParsedData||n.parsers[a].parsed||n.$headers.filter('[data-column="'+a+'"]:last').hasClass("filter-parsed")?p.push(""+g.normalized[c][a]):(h=h.cells[a])&&p.push(k.trim(h.textContent||h.innerText||k(h).text())));return p},buildSelect:function(d,a,b,e,f){d=k(d)[0];a=parseInt(a,10);if(d.config.cache&&!k.isEmptyObject(d.config.cache)){var h,g;g=d.config;var n=g.widgetOptions,l=g.$headers.filter('[data-column="'+ a+'"]:last'),l='<option value="">'+(l.data("placeholder")||l.attr("data-placeholder")||n.filter_placeholder.select||"")+"</option>",r=g.$table.find("thead").find("select."+c.css.filter+'[data-column="'+a+'"]').val();if("undefined"===typeof b||""===b)b=c.filter.getOptionSource(d,a,f);if(k.isArray(b)){for(d=0;d<b.length;d++)f=h=b[d]=(""+b[d]).replace(/\"/g,"""),0<=h.indexOf(n.filter_selectSourceSeparator)&&(h=h.split(n.filter_selectSourceSeparator),f=h[0],h=h[1]),l+=""!==b[d]?"<option "+(f===h? "":'data-function-name="'+b[d]+'" ')+'value="'+f+'">'+h+"</option>":"";b=[]}g=(g.$filters?g.$filters:g.$table.children("thead")).find("."+c.css.filter);n.filter_$externalFilters&&(g=g&&g.length?g.add(n.filter_$externalFilters):n.filter_$externalFilters);a=g.filter('select[data-column="'+a+'"]');a.length&&(a[e?"html":"append"](l),k.isArray(b)||a.append(b).val(r),a.val(r))}},buildDefault:function(d,a){var b,e,f,h=d.config,g=h.widgetOptions,k=h.columns;for(b=0;b<k;b++)e=h.$headers.filter('[data-column="'+ b+'"]:last'),f=!(e.hasClass("filter-false")||e.hasClass("parser-false")),(e.hasClass("filter-select")||!0===c.getColumnData(d,g.filter_functions,b))&&f&&c.filter.buildSelect(d,b,"",a,e.hasClass(g.filter_onlyAvail))}}; -c.getFilters=function(d,a,b,e){var f,h=!1,g=d?k(d)[0].config:"",n=g?g.widgetOptions:"";if(!0!==a&&n&&!n.filter_columnFilters)return k(d).data("lastSearch");if(g&&(g.$filters&&(f=g.$filters.find("."+c.css.filter)),n.filter_$externalFilters&&(f=f&&f.length?f.add(n.filter_$externalFilters): n.filter_$externalFilters),f&&f.length))for(h=b||[],d=0;d<g.columns+1;d++)a=f.filter('[data-column="'+(d===g.columns?"all":d)+'"]'),a.length&&(a=a.sort(function(a,b){return k(b).attr("data-lastSearchTime")-k(a).attr("data-lastSearchTime")}),k.isArray(b)?(e?a.slice(1):a).val(b[d]).trigger("change.tsfilter"):(h[d]=a.val()||"",a.slice(1).val(h[d])),d===g.columns&&a.length&&(n.filter_$anyMatch=a));0===h.length&&(h=!1);return h}; -c.setFilters=function(d,a,b,e){var f=d?k(d)[0].config:"";d=c.getFilters(d, !0,a,e);f&&b&&(f.lastCombinedFilter=null,f.lastSearch=[],c.filter.searching(f.$table[0],a,e),f.$table.trigger("filterFomatterUpdate"));return!!d}; -c.addWidget({id:"stickyHeaders",priority:60,options:{stickyHeaders:"",stickyHeaders_attachTo:null,stickyHeaders_offset:0,stickyHeaders_filteredToTop:!0,stickyHeaders_cloneId:"-sticky",stickyHeaders_addResizeEvent:!0,stickyHeaders_includeCaption:!0,stickyHeaders_zIndex:2},format:function(d,a,b){if(!(a.$table.hasClass("hasStickyHeaders")||0<=k.inArray("filter", a.widgets)&&!a.$table.hasClass("hasFilters"))){var e=a.$table,f=k(b.stickyHeaders_attachTo||"window"),h=e.children("thead:first"),g=f.length?f:k(window),n=h.children("tr").not(".sticky-false").children(),l="."+c.css.headerIn,r=e.find("tfoot"),p=isNaN(b.stickyHeaders_offset)?k(b.stickyHeaders_offset):"",s=f.length?0:p.length?p.height()||0:parseInt(b.stickyHeaders_offset,10)||0,t=b.$sticky=e.clone().addClass("containsStickyHeaders").css({position:f.length?"absolute":"fixed",margin:0,top:s,left:0,visibility:"hidden", zIndex:b.stickyHeaders_zIndex?b.stickyHeaders_zIndex:2}),x=t.children("thead:first").addClass(c.css.sticky+" "+b.stickyHeaders),w,v="",A=0,y="collapse"!==e.css("border-collapse")&&!/(webkit|msie)/i.test(navigator.userAgent),z=function(){s=p.length?p.height()||0:parseInt(b.stickyHeaders_offset,10)||0;A=0;y&&(A=2*parseInt(n.eq(0).css("border-left-width"),10));t.css({left:f.length?(parseInt(f.css("padding-left"),10)||0)+parseInt(a.$table.css("padding-left"),10)+parseInt(a.$table.css("margin-left"),10)+ parseInt(e.css("border-left-width"),10):h.offset().left-g.scrollLeft()-A,width:e.width()});w.filter(":visible").each(function(b){b=n.filter(":visible").eq(b);var c=y&&k(this).attr("data-column")===""+parseInt(a.columns/2,10)?1:0;k(this).css({width:b.width()-A}).find(l).width(b.find(l).width()-c)})};t.attr("id")&&(t[0].id+=b.stickyHeaders_cloneId);t.find("thead:gt(0), tr.sticky-false").hide();t.find("tbody, tfoot").remove();b.stickyHeaders_includeCaption?t.find("caption").css("margin-left","-1px"): t.find("caption").remove();w=x.children().children();t.css({height:0,width:0,padding:0,margin:0,border:0});w.find("."+c.css.resizer).remove();e.addClass("hasStickyHeaders").bind("pagerComplete.tsSticky",function(){z()});c.bindEvents(d,x.children().children(".tablesorter-header"));e.after(t);g.bind("scroll.tsSticky resize.tsSticky",function(a){if(e.is(":visible")){var c=e.offset(),d=b.stickyHeaders_includeCaption?0:e.find("caption").outerHeight(!0),d=(f.length?f.offset().top:g.scrollTop())+s-d,k=e.height()- (t.height()+(r.height()||0)),c=d>c.top&&d<c.top+k?"visible":"hidden",d={visibility:c};f.length?d.top=f.scrollTop():d.left=h.offset().left-g.scrollLeft()-A;t.removeClass("tablesorter-sticky-visible tablesorter-sticky-hidden").addClass("tablesorter-sticky-"+c).css(d);if(c!==v||"resize"===a.type)z(),v=c}});b.stickyHeaders_addResizeEvent&&c.addHeaderResizeEvent(d);e.hasClass("hasFilters")&&(e.bind("filterEnd",function(){var d=k(document.activeElement).closest("td"),d=d.parent().children().index(d);t.hasClass(c.css.stickyVis)&& b.stickyHeaders_filteredToTop&&(window.scrollTo(0,e.position().top),0<=d&&a.$filters&&a.$filters.eq(d).find("a, select, input").filter(":visible").focus())}),c.filter.bindSearch(e,w.find("."+c.css.filter)),b.filter_hideFilters&&c.filter.hideFilters(t,a));e.trigger("stickyHeadersInit")}},remove:function(d,a,b){a.$table.removeClass("hasStickyHeaders").unbind("pagerComplete.tsSticky").find("."+c.css.sticky).remove();b.$sticky&&b.$sticky.length&&b.$sticky.remove();k(".hasStickyHeaders").length||k(window).unbind("scroll.tsSticky resize.tsSticky"); c.addHeaderResizeEvent(d,!1)}}); -c.addWidget({id:"resizable",priority:40,options:{resizable:!0,resizable_addLastColumn:!1,resizable_widths:[],resizable_throttle:!1},format:function(d,a,b){if(!a.$table.hasClass("hasResizable")){a.$table.addClass("hasResizable");c.resizableReset(d,!0);var e,f,h,g,n,l={},r=a.$table,p=0,s=null,t=null,x=20>Math.abs(r.parent().width()-r.width()),w=function(a){if(0!==p&&s){var b=a.pageX-p,c=s.width();s.width(c+b);s.width()!==c&&x&&t.width(t.width()-b);p=a.pageX}},v=function(){c.storage&& s&&t&&(l={},l[s.index()]=s.width(),l[t.index()]=t.width(),s.width(l[s.index()]),t.width(l[t.index()]),!1!==b.resizable&&c.storage(d,"tablesorter-resizable",a.$headers.map(function(){return k(this).width()}).get()));p=0;s=t=null;k(window).trigger("resize")};if(l=c.storage&&!1!==b.resizable?c.storage(d,"tablesorter-resizable"):{})for(g in l)!isNaN(g)&&g<a.$headers.length&&a.$headers.eq(g).width(l[g]);e=r.children("thead:first").children("tr");e.children().each(function(){var b;b=k(this);g=b.attr("data-column"); b="false"===c.getData(b,c.getColumnData(d,a.headers,g),"resizable");e.children().filter('[data-column="'+g+'"]')[b?"addClass":"removeClass"]("resizable-false")});e.each(function(){h=k(this).children().not(".resizable-false");k(this).find("."+c.css.wrapper).length||h.wrapInner('<div class="'+c.css.wrapper+'" style="position:relative;height:100%;width:100%"></div>');b.resizable_addLastColumn||(h=h.slice(0,-1));f=f?f.add(h):h});f.each(function(){var a=k(this),b=parseInt(a.css("padding-right"),10)+10; a.find("."+c.css.wrapper).append('<div class="'+c.css.resizer+'" style="cursor:w-resize;position:absolute;z-index:1;right:-'+b+'px;top:0;height:100%;width:20px;"></div>')}).find("."+c.css.resizer).bind("mousedown",function(b){s=k(b.target).closest("th");var c=a.$headers.filter('[data-column="'+s.attr("data-column")+'"]');1<c.length&&(s=s.add(c));t=b.shiftKey?s.parent().find("th").not(".resizable-false").filter(":last"):s.nextAll(":not(.resizable-false)").eq(0);p=b.pageX});k(document).bind("mousemove.tsresize", function(a){0!==p&&s&&(b.resizable_throttle?(clearTimeout(n),n=setTimeout(function(){w(a)},isNaN(b.resizable_throttle)?5:b.resizable_throttle)):w(a))}).bind("mouseup.tsresize",function(){v()});r.find("thead:first").bind("contextmenu.tsresize",function(){c.resizableReset(d);var a=k.isEmptyObject?k.isEmptyObject(l):!0;l={};return a})}},remove:function(d,a){a.$table.removeClass("hasResizable").children("thead").unbind("mouseup.tsresize mouseleave.tsresize contextmenu.tsresize").children("tr").children().unbind("mousemove.tsresize mouseup.tsresize").find("."+ c.css.resizer).remove();c.resizableReset(d)}}); -c.resizableReset=function(d,a){k(d).each(function(){var b,e=this.config,f=e&&e.widgetOptions;d&&e&&(e.$headers.each(function(a){b=k(this);f.resizable_widths[a]?b.css("width",f.resizable_widths[a]):b.hasClass("resizable-false")||b.css("width","")}),c.storage&&!a&&c.storage(this,"tablesorter-resizable",{}))})}; -c.addWidget({id:"saveSort",priority:20,options:{saveSort:!0},init:function(c,a,b,e){a.format(c,b,e,!0)},format:function(d,a,b,e){var f,h=a.$table; b=!1!==b.saveSort;var g={sortList:a.sortList};a.debug&&(f=new Date);h.hasClass("hasSaveSort")?b&&d.hasInitialized&&c.storage&&(c.storage(d,"tablesorter-savesort",g),a.debug&&c.benchmark("saveSort widget: Saving last sort: "+a.sortList,f)):(h.addClass("hasSaveSort"),g="",c.storage&&(g=(b=c.storage(d,"tablesorter-savesort"))&&b.hasOwnProperty("sortList")&&k.isArray(b.sortList)?b.sortList:"",a.debug&&c.benchmark('saveSort: Last sort loaded: "'+g+'"',f),h.bind("saveSortReset",function(a){a.stopPropagation(); c.storage(d,"tablesorter-savesort","")})),e&&g&&0<g.length?a.sortList=g:d.hasInitialized&&g&&0<g.length&&h.trigger("sorton",[g]))},remove:function(d){c.storage&&c.storage(d,"tablesorter-savesort","")}}) -})(jQuery); diff --git a/website/agenda/planung/js/list_series.js b/website/agenda/planung/js/list-series.js similarity index 62% rename from website/agenda/planung/js/list_series.js rename to website/agenda/planung/js/list-series.js index 6ffae7a..1da96b6 100644 --- a/website/agenda/planung/js/list_series.js +++ b/website/agenda/planung/js/list-series.js @@ -1,22 +1,22 @@ function add_series(){ - $('#edit_new').toggle(); - return false; + $('#edit_new').toggle(); + return false; } function view_series_details(series_id, studio_id, project_id){ - var elem=$('.series_details_'+series_id).prev(); - if(elem.hasClass('active')){ - elem.removeClass('active'); - $('.series_details_'+series_id).slideToggle( - function(){ - $('#series_details_'+series_id).html(''); - } - ); - }else{ - elem.addClass('active'); - var url="series.cgi?project_id="+project_id+"&studio_id="+studio_id+"&series_id="+series_id+"&action=show"; - load(url); - } + var elem=$('.series_details_'+series_id).prev(); + if(elem.hasClass('active')){ + elem.removeClass('active'); + $('.series_details_'+series_id).slideToggle( + function(){ + $('#series_details_'+series_id).html(''); + } + ); + }else{ + elem.addClass('active'); + var url="series.cgi?project_id="+project_id+"&studio_id="+studio_id+"&series_id="+series_id+"&action=show"; + load(url); + } } @@ -44,8 +44,8 @@ function searchEvents(){ }else{ $('#clearSearch').show(); }; - searchEventsAt('#newSeries div', searchValue); - searchEventsAt('#oldSeries div', searchValue); + searchEventsAt('#newSeries a', searchValue); + searchEventsAt('#oldSeries a', searchValue); } function clearSearch(){ diff --git a/website/agenda/planung/js/localization-datetime.js b/website/agenda/planung/js/localization-datetime.js deleted file mode 100644 index 602e291..0000000 --- a/website/agenda/planung/js/localization-datetime.js +++ /dev/null @@ -1,49 +0,0 @@ -// region will be set at template -// set datepicker and timepicker localization for given region -function initRegions(region){ - - if (region == null) return; - if (region == 'en') return; - if ($.datepicker == null){ - console.log("datepicker not loaded") - return; - } - $.datepicker.regional['de'] = { - closeText: 'Schließen', - prevText: '<Zurück', - nextText: 'Vor>', - currentText: 'Heute', - monthNames: ['Januar','Februar','März','April','Mai','Juni', - 'Juli','August','September','Oktober','November','Dezember'], - monthNamesShort: ['Jan','Feb','Mär','Apr','Mai','Jun', - 'Jul','Aug','Sep','Okt','Nov','Dez'], - dayNames: ['Sonntag','Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag'], - dayNamesShort: ['So','Mo','Di','Mi','Do','Fr','Sa'], - dayNamesMin: ['So','Mo','Di','Mi','Do','Fr','Sa'], - weekHeader: 'KW', - dateFormat: 'dd.mm.yy', - firstDay: 1, - isRTL: false, - showMonthAfterYear: false, - yearSuffix: '' - }; - - $.timepicker.regional['de'] = { - timeOnlyTitle: 'Zeit wählen', - timeText: 'Zeit', - hourText: 'Stunde', - minuteText: 'Minute', - secondText: 'Sekunde', - millisecText: 'Millisekunde', - timezoneText: 'Zeitzone', - currentText: 'Jetzt', - closeText: 'Schließen', - timeFormat: 'HH:mm', - amNames: ['AM', 'A'], - pmNames: ['PM', 'P'], - isRTL: false - }; - - $.datepicker.setDefaults($.datepicker.regional[ region ]); - $.timepicker.setDefaults($.timepicker.regional[ region ]); -} diff --git a/website/agenda/planung/js/notify-events.js b/website/agenda/planung/js/notify-events.js new file mode 100644 index 0000000..7e4b88d --- /dev/null +++ b/website/agenda/planung/js/notify-events.js @@ -0,0 +1,18 @@ +function register_buttons() { + $("#forms form").on('click', 'button', function( event ) { + event.preventDefault(); + var form = $(this).closest('form'); + $.post("notify-events.cgi", form.serialize()) + .done( function(data) { + var content = $(data).find("#content"); + $('#result').html(content); + var formId = form.attr('id'); + $('#'+formId+" .mailHeader").addClass("done"); + }); + }); +} + +$(document).ready(function() { + register_buttons(); +}); + diff --git a/website/agenda/planung/js/page_leave_handler.js b/website/agenda/planung/js/page-leave-handler.js similarity index 58% rename from website/agenda/planung/js/page_leave_handler.js rename to website/agenda/planung/js/page-leave-handler.js index 75b3c07..b2ba42b 100644 --- a/website/agenda/planung/js/page_leave_handler.js +++ b/website/agenda/planung/js/page-leave-handler.js @@ -2,8 +2,16 @@ var pageHasChangedCounter=0; var pageIsLoaded=0; function pageHasChanged(){ + console.log("pageHasChanged="+pageHasChangedCounter) if (pageIsLoaded==0) return; pageHasChangedCounter++; + console.log("pageHasChanged="+pageHasChangedCounter); + return 1; +} + +function confirmPageLeave(){ + if(pageHasChangedCounter==0) return null; + return "Unsaved changed! Continue?"; } function pageLeaveHandler(){ @@ -12,14 +20,16 @@ function pageLeaveHandler(){ $('div.editor select' ).change(function(){pageHasChanged()}); window.onbeforeunload = function() { - if(pageHasChangedCounter==0)return null; - return "Unsaved changed! Continue?"; + return confirmPageLeave(); }; - //$(window).unload(function(){}); + pageIsLoaded=1; + console.log("pageLeaveHandler=initialized") + } function leavePage(){ pageHasChangedCounter=0; + console.log("leavePage") return 1; } diff --git a/website/agenda/planung/js/projects.js b/website/agenda/planung/js/projects.js index e21b329..0aaa1ea 100644 --- a/website/agenda/planung/js/projects.js +++ b/website/agenda/planung/js/projects.js @@ -1,49 +1,53 @@ function edit_project_assignments(name){ - if ($('#assign_'+name).css('display')=='none'){ - $('#view_'+name).hide(); - $('#edit_'+name).hide(); - $('#assign_'+name).show(); - }else{ - cancel_edit_project_assignments(name); - } - return false; + if ($('#assign_'+name).css('display')=='none'){ + $('#view_'+name).hide(); + $('#edit_'+name).hide(); + $('#assign_'+name).show(); + }else{ + cancel_edit_project_assignments(name); + } + return false; } function cancel_edit_project_assignments(name){ - $('#edit_'+name).hide(); - $('#assign_'+name).hide(); - $('#view_'+name).show(); - return false; + $('#edit_'+name).hide(); + $('#assign_'+name).hide(); + $('#view_'+name).show(); + return false; } -function edit_project(name){ - if ($('#edit_'+name).css('display')=='none'){ - $('#view_'+name).hide(); - $('#assign_'+name).hide(); - $('#edit_'+name).show(); - }else{ - cancel_edit_project(name); - } - return false; +function edit_project(elem, name){ + + if ($('#edit_'+name).css('display')=='none'){ + $('#view_'+name).hide(); + $('#assign_'+name).hide(); + $('#edit_'+name).show(); + elem.text(elem.data("cancel")); + elem.addClass("text"); + }else{ + cancel_edit_project(elem, name); + } + return false; } -function cancel_edit_project(name){ - $('#edit_'+name).hide(); - $('#assign_'+name).hide(); - $('#view_'+name).show(); - return false; +function cancel_edit_project(elem, name){ + $('#edit_'+name).hide(); + $('#assign_'+name).hide(); + $('#view_'+name).show(); + elem.text(elem.data("action")); + elem.removeClass("text"); + return false; } function add_project(){ - $('.editor').hide(); - $('#edit_new').show(); - return false; + $('.editor').hide(); + $('#edit_new').show(); + return false; } $(document).ready( function(){ - initRegions(region); showDatePicker('input.date'); } ); diff --git a/website/agenda/planung/js/selectEvent.js b/website/agenda/planung/js/select-event.js similarity index 70% rename from website/agenda/planung/js/selectEvent.js rename to website/agenda/planung/js/select-event.js index 9eca1d4..388d7a7 100644 --- a/website/agenda/planung/js/selectEvent.js +++ b/website/agenda/planung/js/select-event.js @@ -51,7 +51,7 @@ function updateEventSelection(resultElemId){ if (seriesId == null) return; if (year == null) return; - var url="selectEvent.cgi"; + var url="select-event.cgi"; url+="?project_id=" + getProjectId(); url+="&studio_id=" + getStudioId(); url+="&p_id=" + projectId; @@ -88,12 +88,37 @@ function updateEventSelection(resultElemId){ // set selected eventId at external result selector function selectEventAction(resultElemId){ - var eventId=$('#selectEvent #eventId').val(); + var projectId = $('#selectEvent #projectId').val(); + var studioId = $('#selectEvent #studioId').val(); + var seriesId = $('#selectEvent #seriesId').val(); + var eventId = $('#selectEvent #eventId').val(); if (eventId<=0) return; + + var filterProjectStudio = $('#selectEvent #selectProjectStudio').length!=0 ? 1:0; + var filterSeries = $('#selectEvent #selectSeries').length!=0 ? 1:0; + + var url = "user-selected-event.cgi"; + url += "?project_id=" + getProjectId(); + url += "&studio_id=" + getStudioId(); + url += "&series_id=" + getUrlParameter("series_id"); + url += "&filter_project_studio=" + filterProjectStudio; + url += "&filter_series=" + filterSeries; + url += "&selected_project=" + projectId; + url += "&selected_studio=" + studioId; + url += "&selected_series=" + seriesId; + url += "&selected_event=" + eventId; + $.get(url).done(function() { + console.log("success: "+url) + }).fail(function(jqXHR, textStatus) { + console.log("failed: "+url, "status:" + textStatus) + }); + + console.log(`set: "${resultElemId}"="${eventId}"`) // set the result value $('#'+resultElemId).val( eventId ); // trigger the change event for invisble form elements $('#'+resultElemId).trigger('change'); + return 1; } $(document).ready( diff --git a/website/agenda/planung/js/selectSeries.js b/website/agenda/planung/js/select-series.js similarity index 97% rename from website/agenda/planung/js/selectSeries.js rename to website/agenda/planung/js/select-series.js index 8e8d7b8..9e130c1 100644 --- a/website/agenda/planung/js/selectSeries.js +++ b/website/agenda/planung/js/select-series.js @@ -22,7 +22,7 @@ function updateSeriesSelection(resultElemId){ if (studioId == null) return; if (seriesId == null) return; - var url="selectSeries.cgi"; + var url="select-series.cgi"; url+="?project_id=" + getProjectId(); url+="&studio_id=" + getStudioId(); url+="&p_id=" + projectId; diff --git a/website/agenda/planung/js/series.js b/website/agenda/planung/js/series.js index b05359a..bcb282f 100644 --- a/website/agenda/planung/js/series.js +++ b/website/agenda/planung/js/series.js @@ -1,81 +1,81 @@ function add_series(){ - $('#edit_new').toggle(); - return false; + $('#edit_new').toggle(); + return false; } function view_series_details(series_id, studio_id, project_id){ - var elem=$('.series_details_'+series_id).prev(); - if(elem.hasClass('active')){ - elem.removeClass('active'); - $('.series_details_'+series_id).slideToggle( - function(){ - $('#series_details_'+series_id).html(''); - } - ); - }else{ - elem.addClass('active'); - var url="series.cgi?project_id="+project_id+"&studio_id="+studio_id+"&series_id="+series_id+"&action=show"; - load(url); - } + var elem=$('.series_details_'+series_id).prev(); + if(elem.hasClass('active')){ + elem.removeClass('active'); + $('.series_details_'+series_id).slideToggle( + function(){ + $('#series_details_'+series_id).html(''); + } + ); + }else{ + elem.addClass('active'); + var url="series.cgi?project_id="+project_id+"&studio_id="+studio_id+"&series_id="+series_id+"&action=show"; + load(url); + } } /* function edit_series(name){ - if ($('#edit_'+name).css('display')=='none'){ - $('#edit_'+name).show(); - }else{ - cancel_edit_series(name); - } - return false; + if ($('#edit_'+name).css('display')=='none'){ + $('#edit_'+name).show(); + }else{ + cancel_edit_series(name); + } + return false; } function cancel_edit_series(name){ - $('#edit_'+name).hide(); - return false; + $('#edit_'+name).hide(); + return false; } /* function edit_scan(name){ - if ($('#scan_'+name).css('display')=='none'){ - $('#scan_'+name).show(); - }else{ - cancel_edit_scan(name); - } - return false; + if ($('#scan_'+name).css('display')=='none'){ + $('#scan_'+name).show(); + }else{ + cancel_edit_scan(name); + } + return false; } function cancel_edit_scan(name){ - $('#scan_'+name).hide(); - return false; + $('#scan_'+name).hide(); + return false; } function edit_schedule(name){ - if ($('#edit_schedule_'+name).css('display')=='none'){ - $('#edit_schedule_'+name).show(); - }else{ - cancel_edit_schedule(name); - } - return false; + if ($('#edit_schedule_'+name).css('display')=='none'){ + $('#edit_schedule_'+name).show(); + }else{ + cancel_edit_schedule(name); + } + return false; } function cancel_edit_schedule(name){ - $('#edit_schedule_'+name).hide(); - return false; + $('#edit_schedule_'+name).hide(); + return false; } function show_schedule(name){ - if ($('#show_schedule_'+name).css('display')=='none'){ - $('#show_schedule_'+name).show(); - }else{ - hide_schedule(name); - } - return false; + if ($('#show_schedule_'+name).css('display')=='none'){ + $('#show_schedule_'+name).show(); + }else{ + hide_schedule(name); + } + return false; } function hide_schedule(name){ - $('#show_schedule_'+name).hide(); - return false; + $('#show_schedule_'+name).hide(); + return false; } */ diff --git a/website/agenda/planung/js/show-playout.js b/website/agenda/planung/js/show-playout.js new file mode 100644 index 0000000..76e70b2 --- /dev/null +++ b/website/agenda/planung/js/show-playout.js @@ -0,0 +1,14 @@ + +function showTable(){ + $('#playout-table').tablesorter({ + widgets: ["filter"], + usNumberFormat : false + }); +} + +$(document).ready( + function(){ + showTable(); + } +); + diff --git a/website/agenda/planung/js/studio_timeslots.js b/website/agenda/planung/js/studio-timeslots.js similarity index 52% rename from website/agenda/planung/js/studio_timeslots.js rename to website/agenda/planung/js/studio-timeslots.js index 0a321ef..2ce10cf 100644 --- a/website/agenda/planung/js/studio_timeslots.js +++ b/website/agenda/planung/js/studio-timeslots.js @@ -27,7 +27,7 @@ function updateWeekdays(){ function showDates(){ var date=$('#show_date select').val(); - var url='studio_timeslots.cgi?'; + var url='studio-timeslots.cgi?'; url+='project_id='+getProjectId(); url+='&studio_id='+getStudioId(); url+='&action=show_dates'; @@ -53,7 +53,7 @@ function initTable(){ scroller_jumpToHeader: true, scroller_idPrefix : 's_' }, - usNumberFormat : false + usNumberFormat : false }); $('.tablesorter-scroller-header').css('width','95%'); $('.tablesorter-scroller-table').css('width','95%'); @@ -62,51 +62,40 @@ function initTable(){ } $(document).ready( - function(){ - setupLocalization(function(){ - addBackButton(); - updateWeekdays(); - }); + function(){ + setupLocalization(function(){ + addBackButton(); + updateWeekdays(); + }); - $("#tabs").tabs({ - activate: function(){ - console.log("set style"); - $('.tablesorter-scroller-header').css('width','95%'); - $('.tablesorter-scroller-table').css('width','95%'); - $('.tablesorter-scroller-header table').css('width','95%'); - $('.tablesorter-scroller-table table').css('width','95%'); - } - }); - $('#tabs').removeClass('ui-widget ui-widget-content ui-corner-all'); + setTabs('#tabs'); - initTextWidth(); + initTextWidth(); - setTextWidth('.datetimepicker.start', 120); - setTextWidth('.datetimepicker.end', 120); - setTextWidth('.datetimepicker.end_date', 80); - setTextWidth('.datetimepicker.weekday', 20); - setTextWidth('.datetimepicker.frequency', 20); + setTextWidth('.datetimepicker.start', 130); + setTextWidth('.datetimepicker.end', 130); + setTextWidth('.datetimepicker.end_date', 90); + setTextWidth('.datetimepicker.weekday', 20); + setTextWidth('.datetimepicker.frequency', 20); - initRegions(region); + showDateTimePicker('.datetimepicker.start', { + onSelect: function(){updateWeekdays();} + }); + showDateTimePicker('.datetimepicker.end', { + onSelect: function(){updateWeekdays();} + }); + showDatePicker('.datetimepicker.end_date', { + onSelect: function(){updateWeekdays();} + }); - showDateTimePicker('.datetimepicker.start', { - onSelect: function(){updateWeekdays();} - }); - showDateTimePicker('.datetimepicker.end', { - onSelect: function(){updateWeekdays();} - }); - showDatePicker('.datetimepicker.end_date', { - onSelect: function(){updateWeekdays();} - }); + setSelectedOptions(); - setSelectedOptions(); - - showYearPicker('#show_date', { - onSelect: function(){ - showDates(); - } - }); - showDates(); + showYearPicker('#show_date', { + onSelect: function(){ + showDates(); + } + }); + showDates(); }); diff --git a/website/agenda/planung/js/studios.js b/website/agenda/planung/js/studios.js index e695c9d..14958f1 100644 --- a/website/agenda/planung/js/studios.js +++ b/website/agenda/planung/js/studios.js @@ -1,22 +1,28 @@ -var region='<TMPL_VAR loc.region>'; +var region='<TMPL_VAR loc.region escape=js>'; -function edit_studio(name){ - if ($('#edit_'+name).css('display')=='none'){ - $('#view_'+name).hide(); - $('#edit_'+name).show(); - }else{ - cancel_edit_studio(name); - } - return false; -} function add_studio(){ - $('.editor').hide(); - $('#edit_new').show(); - return false; -} -function cancel_edit_studio(name){ - $('#edit_'+name).hide(); - $('#view_'+name).show(); - return false; + $('.editor').hide(); + $('#edit_new').show(); + return false; +} + +function edit_studio(elem, name){ + if ($('#edit_'+name).css('display')=='none'){ + $('#view_'+name).hide(); + $('#edit_'+name).show(); + elem.text(elem.data("cancel")); + elem.addClass("text"); + }else{ + cancel_edit_studio(elem, name); + } + return false; +} + +function cancel_edit_studio(elem, name){ + $('#edit_'+name).hide(); + $('#view_'+name).show(); + elem.text(elem.data("action")); + elem.removeClass("text"); + return false; } diff --git a/website/agenda/planung/localization.cgi b/website/agenda/planung/localization.cgi index 012b361..e79115d 100755 --- a/website/agenda/planung/localization.cgi +++ b/website/agenda/planung/localization.cgi @@ -1,15 +1,18 @@ -#! /usr/bin/perl -w +#! /usr/bin/perl -use warnings "all"; use strict; -use Data::Dumper; +use warnings; +no warnings 'redefine'; -use config; -use params; -use log; -use JSON; -use auth; -use localization; +use Data::Dumper; +use JSON(); + +use config(); +use params(); +use log(); +use entry(); +use auth(); +use localization(); binmode STDOUT, ":utf8"; @@ -18,43 +21,41 @@ my $r = shift; my $config = config::get('../config/config.cgi'); my $debug = $config->{system}->{debug}; -my ( $user, $expires ) = auth::get_user( $cgi, $config ); +my ( $user, $expires ) = auth::get_user( $config, $params, $cgi ); return if ( $user eq '' ); my $request = { - url => $ENV{QUERY_STRING} || '', - params => { - original => $params, - checked => check_params($params), - } + url => $ENV{QUERY_STRING} || '', + params => { + original => $params, + checked => check_params( $config, $params ), + } }; $params = $request->{params}->{checked}; my $loc = localization::get( $config, { user => $user, file => $params->{usecase} } ); my $header = "Content-type:application/json; charset=UTF-8;\n\n"; $loc->{usecase} = $params->{usecase}; -my $json = to_json( $loc, { pretty => 1 } ); +my $json = JSON::to_json( $loc, { pretty => 1 } ); my @json_lines = (); for my $line ( split /\n/, $json ) { - push @json_lines, "'" . $line . "'\n"; + push @json_lines, "'" . $line . "'\n"; } $json = $header . $json; - -# .'var loc_text='.join('+',@json_lines).";\n" -# .'var loc = JQuery.parseJSON(loc_text)'; print $json; sub check_params { - my $params = shift; + my $config = shift; + my $params = shift; - my $checked = { usecase => '' }; + my $checked = { usecase => '' }; - if ( defined $params->{usecase} ) { - if ( $params->{usecase} =~ /^([a-z\-\_\,]+)$/ ) { - $checked->{usecase} = $1; - } - } - return $checked; + if ( defined $params->{usecase} ) { + if ( $params->{usecase} =~ /^([a-z\-\_\,]+)$/ ) { + $checked->{usecase} = $1; + } + } + return $checked; } diff --git a/website/agenda/planung/logout.cgi b/website/agenda/planung/logout.cgi index 3673b4a..9e36805 100755 --- a/website/agenda/planung/logout.cgi +++ b/website/agenda/planung/logout.cgi @@ -1,4 +1,4 @@ -#! /usr/bin/perl +#!/usr/bin/perl print qq{HTTP/1.0 401 Unauthorized Request Version: HTTP/1.0 diff --git a/website/agenda/planung/notify-events.cgi b/website/agenda/planung/notify-events.cgi new file mode 100755 index 0000000..b7a283d --- /dev/null +++ b/website/agenda/planung/notify-events.cgi @@ -0,0 +1,268 @@ +#!/usr/bin/perl + +use strict; +use warnings; +no warnings 'redefine'; + +use URI::Escape(); +use Data::Dumper; +use MIME::Lite(); + +use params(); +use config(); +use entry(); +use log(); +use template(); +use db(); +use auth(); +use uac(); +use time(); +use markup(); +use studios(); +use series(); +use localization(); + +binmode STDOUT, ":utf8"; + +my $r = shift; +( my $cgi, my $params, my $error ) = params::get($r); + +my $config = config::get('../config/config.cgi'); +my $debug = $config->{system}->{debug}; +my ( $user, $expires ) = auth::get_user( $config, $params, $cgi ); +return if ( ( !defined $user ) || ( $user eq '' ) ); + +my $user_presets = uac::get_user_presets( + $config, + { + user => $user, + project_id => $params->{project_id}, + studio_id => $params->{studio_id} + } +); +$params->{default_studio_id} = $user_presets->{studio_id}; +$params = uac::setDefaultStudio( $params, $user_presets ); +$params = uac::setDefaultProject( $params, $user_presets ); + +my $request = { + url => $ENV{QUERY_STRING} || '', + params => { + original => $params, + checked => check_params( $config, $params ), + }, +}; + +#set user at params->presets->user +$request = uac::prepare_request( $request, $user_presets ); + +$params = $request->{params}->{checked}; + +#show header +unless ( params::isJson() || ( $params->{template} =~ /\.txt/ ) ) { + my $headerParams = uac::set_template_permissions( $request->{permissions}, $params ); + $headerParams->{loc} = localization::get( $config, { user => $user, file => 'menu' } ); + template::process( $config, 'print', template::check( $config, 'default.html' ), $headerParams ); +} +return unless uac::check( $config, $params, $user_presets ) == 1; + +$config->{access}->{write} = 0; +if ( $params->{action} eq 'send' ) { + sendMail( $config, $request ); + return; +} +show_events( $config, $request ); + +#show existing event history +sub show_events { + my $config = shift; + my $request = shift; + + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + + for my $attr ( 'project_id', 'studio_id', 'duration' ) { # 'series_id','event_id' + unless ( defined $params->{$attr} ) { + uac::print_error( "missing " . $attr . " to show changes" ); + return; + } + } + + unless ( $permissions->{read_event} == 1 ) { + uac::print_error("missing permissions to show changes"); + return; + } + + # get events + my $duration = $params->{duration}; + my $options = { + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + from_date => time::time_to_date(), + till_date => time::time_to_date( time() + $duration * 24 * 60 * 60 ), + draft => 0, + published => 1 + }; + + my $events = series::get_events( $config, $options ); + + # get series_users + for my $event (@$events) { + my $mail = getMail( $config, $request, $event ); + $event->{mail} = $mail; + } + + return unless defined $events; + my @events = sort { $a->{start} cmp $b->{start} } @$events; + $params->{events} = \@events; + + for my $permission ( keys %{$permissions} ) { + $params->{'allow'}->{$permission} = $request->{permissions}->{$permission}; + } + + $params->{loc} = localization::get( $config, { user => $params->{presets}->{user}, file => 'notify-events' } ); + template::process( $config, 'print', $params->{template}, $params ); + +} + +sub sendMail { + my $config = shift; + my $request = shift; + + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + + for my $attr ( 'project_id', 'studio_id', 'series_id', 'event_id' ) { + unless ( defined $params->{$attr} ) { + uac::print_error( "missing " . $attr . " to send notification" ); + return; + } + } + + unless ( $permissions->{read_event} == 1 ) { + uac::print_error("missing permissions to send notification"); + return; + } + + my $options = { + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + series_id => $params->{series_id}, + event_id => $params->{event_id}, + draft => 0, + published => 0, + }; + my $events = series::get_events( $config, $options ); + + unless ( scalar(@$events) == 1 ) { + uac::print_error("did not found exactly one event"); + return; + } + + my $mail = getMail( $config, $request, $events->[0] ); + $mail->{To} = $params->{to} if defined $params->{to}; + $mail->{Cc} = $params->{cc} if defined $params->{cc}; + $mail->{Subject} = $params->{subject} if defined $params->{subject}; + $mail->{Data} = $params->{content} if defined $params->{content}; + + my $msg = MIME::Lite->new( + 'From' => $mail->{'From'}, + 'To' => $mail->{'To'}, + 'Cc' => $mail->{'Cc'}, + 'Reply-To' => $mail->{'Reply-To'}, + 'Subject' => $mail->{'Subject'}, + 'Data' => $mail->{'Data'}, + ); + + print '<pre>'; + $msg->print( \*STDOUT ); + print '</pre>'; + $msg->send; +} + +sub getMail { + my $config = shift; + my $request = shift; + my $event = shift; + + my $users = series::get_users( + $config, + { + project_id => $event->{project_id}, + studio_id => $event->{studio_id}, + series_id => $event->{series_id} + } + ); + + my $userNames = []; + my $userMails = []; + for my $user (@$users) { + push @$userNames, ( split( /\s+/, $user->{full_name} ) )[0]; + push @$userMails, $user->{email}; + } + if ( scalar(@$userMails) == 0 ) { + $event->{noRecipient} = 1; + return; + } + + my $mail = { + 'From' => 'programm@radiopiloten.de', + 'To' => join( ', ', @$userMails ), + 'Cc' => 'programm@radiopiloten.de', + 'Reply-To' => 'programm@radiopiloten.de', + 'Subject' => "$event->{start} - $event->{full_title}", + 'Data' => "Hallo " . join( ' und ', @$userNames ) . ",\n\n" + }; + + $mail->{Data} .= "nur zur Erinnerung...\n\n"; + $mail->{Data} .= "am $event->{weekday_name} ist die naechste '$event->{series_name}'-Sendung.\n\n"; + $mail->{Data} .= + "$event->{source_base_url}$event->{cache_base_url}/$config->{controllers}->{event}/$event->{event_id}.html\n\n"; + $mail->{Data} .= "Gruss, $request->{user}\n"; + return $mail; +} + +sub eventToText { + my $event = shift; + + my $s = events::get_keys($event)->{full_title} . "\n"; + $s .= $event->{excerpt} . "\n"; + $s .= $event->{user_excerpt} . "\n"; + $s .= $event->{topic} . "\n"; + $s .= $event->{content} . "\n"; + + #print STDERR "DUMP\n$s"; + return $s; + +} + +sub check_params { + my $config = shift; + my $params = shift; + + my $checked = {}; + my $template = ''; + $checked->{template} = template::check( $config, $params->{template}, 'notify-events' ); + + my $debug = $params->{debug} || ''; + if ( $debug =~ /([a-z\_\,]+)/ ) { + $debug = $1; + } + $checked->{debug} = $debug; + + entry::set_numbers( $checked, $params, [ + 'event_id', 'project_id', 'studio_id', 'default_studio_id', 'user_id', 'series_id', 'duration' + ]); + + entry::set_strings( $checked, $params, [ + 'subject', 'to', 'cc', 'content']); + + if ( defined $checked->{studio_id} ) { + $checked->{default_studio_id} = $checked->{studio_id}; + } else { + $checked->{studio_id} = -1; + } + + $checked->{action} = entry::element_of($params->{action}, ['send']); + return $checked; +} + diff --git a/website/agenda/planung/notify_events.cgi b/website/agenda/planung/notify_events.cgi deleted file mode 100755 index a70fc31..0000000 --- a/website/agenda/planung/notify_events.cgi +++ /dev/null @@ -1,291 +0,0 @@ -#! /usr/bin/perl -w - -use warnings "all"; -use strict; -use URI::Escape; -use Encode; -use Data::Dumper; - -#use Text::Diff::FormattedHTML; -use MIME::Lite; - -use params; -use config; -use log; -use template; -use db; -use auth; -use uac; - -#use roles; -use time; -use markup; -use studios; - -#use event_history; -#use events; -use series; - -#use series_dates; -#use series_events; -use localization; -binmode STDOUT, ":utf8"; - -my $r = shift; -( my $cgi, my $params, my $error ) = params::get($r); - -my $config = config::get('../config/config.cgi'); -my $debug = $config->{system}->{debug}; -my ( $user, $expires ) = auth::get_user( $cgi, $config ); -return if ( ( !defined $user ) || ( $user eq '' ) ); - -my $user_presets = uac::get_user_presets( - $config, - { - user => $user, - project_id => $params->{project_id}, - studio_id => $params->{studio_id} - } -); -$params->{default_studio_id} = $user_presets->{studio_id}; -$params->{studio_id} = $params->{default_studio_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); -$params->{project_id} = $user_presets->{project_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); - -my $request = { - url => $ENV{QUERY_STRING} || '', - params => { - original => $params, - checked => check_params($params), - }, -}; - -#print STDERR Dumper($request)."\n"; - -#set user at params->presets->user -$request = uac::prepare_request( $request, $user_presets ); -log::init($request); - -$params = $request->{params}->{checked}; - -#show header -unless ( params::isJson() || ( $params->{template}=~/\.txt/ ) ) { - my $headerParams = uac::set_template_permissions( $request->{permissions}, $params ); - $headerParams->{loc} = localization::get( $config, { user => $user, file => 'menu' } ); - template::process( 'print', template::check('default.html'), $headerParams ); -} -return unless uac::check( $config, $params, $user_presets ) == 1; - -$config->{access}->{write} = 0; -if ( $params->{action} eq 'send' ) { - sendMail( $config, $request ); - return; -} -show_events( $config, $request ); - -#show existing event history -sub show_events { - my $config = shift; - my $request = shift; - - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - - for my $attr ( 'project_id', 'studio_id', 'duration' ) { # 'series_id','event_id' - unless ( defined $params->{$attr} ) { - uac::print_error( "missing " . $attr . " to show changes" ); - return; - } - } - - unless ( $permissions->{read_event} == 1 ) { - uac::print_error("missing permissions to show changes"); - return; - } - - # get events - my $duration = $params->{duration}; - my $options = { - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - from_date => time::time_to_date(), - till_date => time::time_to_date( time() + $duration * 24 * 60 * 60 ), - draft => 0, - published => 1 - }; - - my $events = series::get_events( $config, $options ); - - # get series_users - for my $event (@$events) { - my $mail = getMail( $config, $request, $event ); - $event->{mail} = $mail; - } - - return unless defined $events; - my @events = sort { $a->{start} cmp $b->{start} } @$events; - $params->{events} = \@events; - - for my $permission ( keys %{$permissions} ) { - $params->{'allow'}->{$permission} = $request->{permissions}->{$permission}; - } - - $params->{loc} = localization::get( $config, { user => $params->{presets}->{user}, file => 'notify_events' } ); - template::process( 'print', $params->{template}, $params ); - -} - -sub sendMail { - my $config = shift; - my $request = shift; - - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - - for my $attr ( 'project_id', 'studio_id', 'series_id', 'event_id' ) { - unless ( defined $params->{$attr} ) { - uac::print_error( "missing " . $attr . " to send notification" ); - return; - } - } - - unless ( $permissions->{read_event} == 1 ) { - uac::print_error("missing permissions to send notification"); - return; - } - - my $options = { - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - series_id => $params->{series_id}, - event_id => $params->{event_id}, - draft => 0, - published => 0, - }; - my $events = series::get_events( $config, $options ); - - unless ( scalar(@$events) == 1 ) { - uac::print_error("did not found exactly one event"); - return; - } - - my $mail = getMail( $config, $request, $events->[0] ); - $mail->{To} = $params->{to} if defined $params->{to}; - $mail->{Cc} = $params->{cc} if defined $params->{cc}; - $mail->{Subject} = $params->{subject} if defined $params->{subject}; - $mail->{Data} = $params->{content} if defined $params->{content}; - - my $msg = MIME::Lite->new( - 'From' => $mail->{'From'}, - 'To' => $mail->{'To'}, - 'Cc' => $mail->{'Cc'}, - 'Reply-To' => $mail->{'Reply-To'}, - 'Subject' => $mail->{'Subject'}, - 'Data' => $mail->{'Data'}, - ); - - print '<pre>'; - $msg->print( \*STDOUT ); - print '</pre>'; - $msg->send; -} - -sub getMail { - my $config = shift; - my $request = shift; - my $event = shift; - - my $users = series::get_users( - $config, - { - project_id => $event->{project_id}, - studio_id => $event->{studio_id}, - series_id => $event->{series_id} - } - ); - - my $userNames = []; - my $userMails = []; - for my $user (@$users) { - push @$userNames, ( split( /\s+/, $user->{full_name} ) )[0]; - push @$userMails, $user->{email}; - } - if ( scalar(@$userMails) == 0 ) { - $event->{noRecipient} = 1; - return; - } - - my $mail = { - 'From' => 'programm@radiopiloten.de', - 'To' => join( ', ', @$userMails ), - 'Cc' => 'programm@radiopiloten.de', - 'Reply-To' => 'programm@radiopiloten.de', - 'Subject' => "$event->{start} - $event->{full_title}", - 'Data' => "Hallo " . join( ' und ', @$userNames ) . ",\n\n" - }; - - $mail->{Data} .= "nur zur Erinnerung...\n\n"; - $mail->{Data} .= "am $event->{weekday_name} ist die naechste '$event->{series_name}'-Sendung.\n\n"; - $mail->{Data} .= "$event->{source_base_url}$event->{cache_base_url}/$config->{controllers}->{event}/$event->{event_id}.html\n\n"; - $mail->{Data} .= "Gruss, $request->{user}\n"; - return $mail; -} - -sub eventToText { - my $event = shift; - - my $s = events::get_keys($event)->{full_title} . "\n"; - $s .= $event->{excerpt} . "\n"; - $s .= $event->{user_excerpt} . "\n"; - $s .= $event->{topic} . "\n"; - $s .= $event->{content} . "\n"; - - #print STDERR "DUMP\n$s"; - return $s; - -} - -sub check_params { - my $params = shift; - - my $checked = {}; - my $template = ''; - $checked->{template} = template::check( $params->{template}, 'notify_events' ); - - my $debug = $params->{debug} || ''; - if ( $debug =~ /([a-z\_\,]+)/ ) { - $debug = $1; - } - $checked->{debug} = $debug; - - #numeric values - for my $param ( 'event_id', 'project_id', 'studio_id', 'default_studio_id', 'user_id', 'series_id', 'duration' ) { - if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /^\d+$/ ) ) { - $checked->{$param} = $params->{$param}; - } - } - - for my $param ( 'subject', 'to', 'cc', 'content' ) { - if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /\S/ ) ) { - $checked->{$param} = $params->{$param}; - } - } - - if ( defined $checked->{studio_id} ) { - $checked->{default_studio_id} = $checked->{studio_id}; - } else { - $checked->{studio_id} = -1; - } - - #actions and roles - $checked->{action} = ''; - if ( defined $params->{action} ) { - if ( $params->{action} =~ /^(send)$/ ) { - $checked->{action} = $params->{action}; - } - } - - return $checked; -} - diff --git a/website/agenda/planung/playout.cgi b/website/agenda/planung/playout.cgi old mode 100644 new mode 100755 index f441306..34aa720 --- a/website/agenda/planung/playout.cgi +++ b/website/agenda/planung/playout.cgi @@ -1,29 +1,30 @@ -#! /usr/bin/perl -w +#!/usr/bin/perl -use warnings "all"; use strict; +use warnings; +no warnings 'redefine'; + use Data::Dumper; +use URI::Escape(); -use URI::Escape; -use Encode; -use localization; - -use params; -use config; -use log; -use template; -use auth; -use uac; -use roles; -use project; -use studios; -use events; -use series; -use series_schedule; -use series_events; -use series_dates; -use markup; -use playout; +use localization(); +use params(); +use config(); +use entry(); +use log(); +use template(); +use auth(); +use uac(); +use roles(); +use project(); +use studios(); +use events(); +use series(); +use series_schedule(); +use series_events(); +use series_dates(); +use markup(); +use playout(); binmode STDOUT, ":utf8"; @@ -32,38 +33,32 @@ my $r = shift; my $config = config::get('../config/config.cgi'); my $debug = $config->{system}->{debug}; -my ( $user, $expires ) = auth::get_user( $cgi, $config ); +my ( $user, $expires ) = auth::get_user( $config, $params, $cgi ); return if ( ( !defined $user ) || ( $user eq '' ) ); print "Content-type:text/html; charset=UTF-8;\n\n"; -#print STDERR $params->{project_id}."\n"; my $user_presets = uac::get_user_presets( - $config, - { - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - user => $user - } + $config, + { + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + user => $user + } ); $params->{default_studio_id} = $user_presets->{studio_id}; -$params->{studio_id} = $params->{default_studio_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); -$params->{project_id} = $user_presets->{project_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); - -#print STDERR $params->{project_id}."\n"; +$params = uac::setDefaultStudio( $params, $user_presets ); +$params = uac::setDefaultProject( $params, $user_presets ); my $request = { - url => $ENV{QUERY_STRING} || '', - params => { - original => $params, - checked => check_params($params), - }, + url => $ENV{QUERY_STRING} || '', + params => { + original => $params, + checked => check_params( $config, $params ), + }, }; $request = uac::prepare_request( $request, $user_presets ); -log::init($request); $params = $request->{params}->{checked}; @@ -71,92 +66,83 @@ $params = $request->{params}->{checked}; my $headerParams = uac::set_template_permissions( $request->{permissions}, $params ); $headerParams->{loc} = localization::get( $config, { user => $user, file => 'menu' } ); -#template::process('print', template::check('default.html'), $headerParams); +#template::process($config, 'print', template::check($config, 'default.html'), $headerParams); return unless uac::check( $config, $params, $user_presets ) == 1; if ( defined $params->{action} ) { - deleteFromPlayout( $config, $request ) if ( $params->{action} eq 'delete' ); + deleteFromPlayout( $config, $request ) if ( $params->{action} eq 'delete' ); } else { - print "missing action\n"; + print "missing action\n"; } return; sub deleteFromPlayout { - my $config = shift; - my $request = shift; + my $config = shift; + my $request = shift; - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - unless ( $permissions->{update_event_status_playout} == 1 ) { - uac::permissions_denied('update_event_status_playout'); - return; - } + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + unless ( $permissions->{update_event_status_playout} == 1 ) { + uac::permissions_denied('update_event_status_playout'); + return; + } - for my $attr ( 'project_id', 'studio_id', 'start_date' ) { - unless ( defined $params->{$attr} ) { - uac::print_error( "missing " . $attr . " to show event" ); - return; - } - } + for my $attr ( 'project_id', 'studio_id', 'start_date' ) { + unless ( defined $params->{$attr} ) { + uac::print_error( "missing " . $attr . " to show event" ); + return; + } + } - $config->{access}->{write} = 1; - my $dbh = db::connect($config); + $config->{access}->{write} = 1; + my $dbh = db::connect($config); - my $result = playout::delete( - $config, $dbh, - { - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - start => $params->{start_date} - } - ); - $config->{access}->{write} = 0; + my $result = playout::delete( + $config, $dbh, + { + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + start => $params->{start_date} + } + ); + $config->{access}->{write} = 0; - print "result:$result\n"; + print "result:$result\n"; } sub check_params { - my $params = shift; + my $config = shift; + my $params = shift; - my $checked = {}; + my $checked = {}; - my $debug = $params->{debug} || ''; - if ( $debug =~ /([a-z\_\,]+)/ ) { - $debug = $1; - } - $checked->{debug} = $debug; + $checked->{action} = ''; + if ( defined $params->{action} ) { + if ( $params->{action} =~ /^(delete)$/ ) { + $checked->{action} = $params->{action}; + } + } - #actions and roles - $checked->{action} = ''; - if ( defined $params->{action} ) { - if ( $params->{action} =~ /^(delete)$/ ) { - $checked->{action} = $params->{action}; - } - } + #numeric values + $checked->{exclude} = 0; + entry::set_numbers( $checked, $params, [ + 'project_id', 'studio_id']); - #numeric values - $checked->{exclude} = 0; - for my $param ( 'project_id', 'studio_id' ) { - if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /^\d+$/ ) ) { - $checked->{$param} = $params->{$param}; - } - } + #dates + for my $param ('start_date') { + if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /(\d\d\d\d\-\d\d\-\d\d \d\d\:\d\d)/ ) ) { + $checked->{$param} = $1 . ':00'; + } + } - #dates - for my $param ('start_date') { - if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /(\d\d\d\d\-\d\d\-\d\d \d\d\:\d\d)/ ) ) { - $checked->{$param} = $1 . ':00'; - } - } + if ( defined $checked->{studio_id} ) { + $checked->{default_studio_id} = $checked->{studio_id}; + } else { + $checked->{studio_id} = -1; + } - if ( defined $checked->{studio_id} ) { - $checked->{default_studio_id} = $checked->{studio_id}; - } else { - $checked->{studio_id} = -1; - } + #$checked->{template}=template::check($config, $params->{template},'playout'); - #$checked->{template}=template::check($params->{template},'playout'); - - return $checked; + return $checked; } diff --git a/website/agenda/planung/pot/de/audio_recordings.po b/website/agenda/planung/pot/de/audio-recordings.po similarity index 100% rename from website/agenda/planung/pot/de/audio_recordings.po rename to website/agenda/planung/pot/de/audio-recordings.po diff --git a/website/agenda/planung/pot/de/calendar.po b/website/agenda/planung/pot/de/calendar.po index 542c370..7d1533a 100644 --- a/website/agenda/planung/pot/de/calendar.po +++ b/website/agenda/planung/pot/de/calendar.po @@ -10,6 +10,9 @@ msgstr "Heute" msgid "button_search" msgstr "Suche" +msgid "label_pin" +msgstr "Anpinnen" + msgid "label_month" msgstr "Monat" @@ -34,6 +37,9 @@ msgstr "Planung" msgid "label_worktime" msgstr "Studiodienst" +msgid "label_descriptions" +msgstr "Beschreibungen" + msgid "label_playout" msgstr "Playout" diff --git a/website/agenda/planung/pot/de/notify_events.po b/website/agenda/planung/pot/de/create-events.po similarity index 100% rename from website/agenda/planung/pot/de/notify_events.po rename to website/agenda/planung/pot/de/create-events.po diff --git a/website/agenda/planung/pot/de/event_history.po b/website/agenda/planung/pot/de/event-history.po similarity index 100% rename from website/agenda/planung/pot/de/event_history.po rename to website/agenda/planung/pot/de/event-history.po diff --git a/website/agenda/planung/pot/de/event.po b/website/agenda/planung/pot/de/event.po index 413c65a..4b160fe 100644 --- a/website/agenda/planung/pot/de/event.po +++ b/website/agenda/planung/pot/de/event.po @@ -1,3 +1,4 @@ + msgid "region" msgstr "de" @@ -22,11 +23,14 @@ msgstr "Speichern" msgid "button_delete" msgstr "Löschen" +msgid "button_apply" +msgstr "Übernehmen" + msgid "button_unassign_event" msgstr "aus Sendereihe entfernen" msgid "button_show_event" -msgstr "Progammansicht" +msgstr "Programmansicht" msgid "button_show_changes" msgstr "Änderungen" @@ -95,7 +99,7 @@ msgid "label_episode" msgstr "Folge" msgid "label_live" -msgstr "Live-Sendung" +msgstr "live" msgid "label_draft" msgstr "Entwurf" @@ -121,6 +125,15 @@ msgstr "bearbeitet am" msgid "label_modified_by" msgstr "von" +msgid "label_content_format" +msgstr "Wiki-Sprache" + +msgid "label_content_format_markdown" +msgstr "Markdown" + +msgid "label_content_format_creole" +msgstr "Creole" + msgid "button_event_list" msgstr "Sendungen zeigen" @@ -143,7 +156,7 @@ msgid "label_select_event" msgstr "aktuelle Sendung mit" msgid "label_overwrite_event" -msgstr "Sendung überschreiben mit folgender Sendung" +msgstr "Sendung überschreiben mit " msgid "button_copy_event" msgstr "überschreiben" @@ -172,3 +185,5 @@ msgstr "Auszug ist zu lang. Für längeren Text bitte das Feld «aktuelle Themen msgid "label_excerpt_extension_too_long" msgstr "Auszug ist zu lang. Für längeren Text bitte das Feld «aktuelle Themen» verwenden." +msgid "button_copy_to_clipboard" +msgstr "in Zwischenablage kopieren" diff --git a/website/agenda/planung/pot/de/image.po b/website/agenda/planung/pot/de/image.po index 92e3d94..806ec85 100644 --- a/website/agenda/planung/pot/de/image.po +++ b/website/agenda/planung/pot/de/image.po @@ -8,7 +8,7 @@ msgid "tab_edit" msgstr "Bearbeiten" msgid "tab_upload" -msgstr "Hochladen" +msgstr "Neues Bild" msgid "button_upload" msgstr "Hochladen" @@ -16,18 +16,24 @@ msgstr "Hochladen" msgid "button_search" msgstr "Suchen" -msgid "button_zoom_in" -msgstr "Vergrößern" - -msgid "button_zoom_out" -msgstr "Verkleinern" - msgid "button_save" msgstr "Speichern" msgid "button_delete" msgstr "Löschen" +msgid "button_properties" +msgstr "Eigenschaften" + +msgid "button_publish" +msgstr "Veröffentlichen" + +msgid "button_depublish" +msgstr "Depublizieren" + +msgid "label_warn_unknown_licence" +msgstr "Angabe der Lizenz ermöglicht Veröffentlichung des Bildes." + msgid "label_name" msgstr "Name" @@ -52,4 +58,55 @@ msgstr "Editor-Link" msgid "label_search_hits" msgstr "Treffer" +msgid "label_author" +msgstr "Author" + +msgid "label_licence" +msgstr "Lizenz" + +msgid "label_public" +msgstr "veröffentlicht" + +msgid "label_file" +msgstr "Datei" + +msgid "label_name_required" +msgstr "Bitte Feld eintragen" + +msgid "label_licence_required" +msgstr "Bild kann ohne Author/Lizenz nicht veröffentlicht werden" + +msgid "label_mandatory_field" +msgstr "bitte füllen Sie dieses Feld aus" + +msgid "label_mandatory_field_licence" +msgstr "Angabe der Lizenz ermöglicht Veröffentlichung des Bildes" + +msgid "label_assign_to_event" +msgstr "Dieses Bild für Sendung nutzen" + +msgid "label_assign_to_series" +msgstr "Dieses Bild für Sendereihe nutzen" + +msgid "label_assign_to_studio" +msgstr "Dieses Bild für Studio nutzen" + +msgid "label_assign_to_project" +msgstr "Dieses Bild für Projekt nutzen" + +msgid "label_assign_to_projects" +msgstr "Dieses Bild für Projekt nutzen" + +msgid "label_warn_not_public_event" +msgstr "Bild muss veröffentlicht werden, um es in Sendebeschreibung zu nutzen." + +msgid "label_warn_not_public_series" +msgstr "Bild muss veröffentlicht werden, um es in Sendebeschreibung zu nutzen." + +msgid "label_warn_not_public_studio" +msgstr "Bild muss veröffentlicht werden, um es für Studio zu nutzen." + +msgid "label_warn_not_public_project" +msgstr "Bild muss veröffentlicht werden, um es in Projekt zu nutzen." + diff --git a/website/agenda/planung/pot/de/menu.po b/website/agenda/planung/pot/de/menu.po index 8d8aa8a..c5008c9 100644 --- a/website/agenda/planung/pot/de/menu.po +++ b/website/agenda/planung/pot/de/menu.po @@ -32,7 +32,7 @@ msgid "errors" msgstr "Fehler" msgid "logout" -msgstr "Abmelden" +msgstr "abmelden" msgid "studio" msgstr "Studio" @@ -49,3 +49,15 @@ msgstr "Import" msgid "help" msgstr "Hilfe" +msgid "images" +msgstr "Bilder" + +msgid "schedule" +msgstr "Dienstplan" + +msgid "preview" +msgstr "Vorschau" + +msgid "user-stats" +msgstr "Nutzeraktivität" + diff --git a/website/agenda/planung/pot/de/notify-events.po b/website/agenda/planung/pot/de/notify-events.po new file mode 100644 index 0000000..bc66a9f --- /dev/null +++ b/website/agenda/planung/pot/de/notify-events.po @@ -0,0 +1,3 @@ +msgid "button_send" +msgstr "Senden" + diff --git a/website/agenda/planung/pot/de/projects.po b/website/agenda/planung/pot/de/projects.po index 1834cab..d64ba9a 100644 --- a/website/agenda/planung/pot/de/projects.po +++ b/website/agenda/planung/pot/de/projects.po @@ -25,6 +25,9 @@ msgstr "Studio entfernen" msgid "button_edit" msgstr "Bearbeiten" +msgid "button_change" +msgstr "Studios zuordnen" + msgid "button_create" msgstr "Anlegen" @@ -44,7 +47,7 @@ msgid "label_assign_studio" msgstr "Studio hinzufügen" msgid "label_name" -msgstr "Name" +msgstr "ID" msgid "label_title" msgstr "Titel" @@ -58,11 +61,14 @@ msgstr "Start" msgid "label_end_date" msgstr "Ende" +msgid "label_activity" +msgstr "aktiv" + msgid "label_image" msgstr "Logo" msgid "label_email" -msgstr "email" +msgstr "E-Mail" msgid "label_studios" msgstr "Studios" diff --git a/website/agenda/planung/pot/de/roles.po b/website/agenda/planung/pot/de/roles.po index 81d65ce..ac53ee6 100644 --- a/website/agenda/planung/pot/de/roles.po +++ b/website/agenda/planung/pot/de/roles.po @@ -73,6 +73,9 @@ msgstr "Podcast-URL bearbeiten" msgid "label_update_event_field_archive_url" msgstr "Archiv-URL bearbeiten" +msgid "label_update_event_field_content_format" +msgstr "Wiki-Format setzen" + msgid "label_create_event_from_schedule" msgstr "Sendungen vom Plan anlegen" diff --git a/website/agenda/planung/pot/de/selectEvent.po b/website/agenda/planung/pot/de/select-event.po similarity index 100% rename from website/agenda/planung/pot/de/selectEvent.po rename to website/agenda/planung/pot/de/select-event.po diff --git a/website/agenda/planung/pot/de/selectSeries.po b/website/agenda/planung/pot/de/select-series.po similarity index 100% rename from website/agenda/planung/pot/de/selectSeries.po rename to website/agenda/planung/pot/de/select-series.po diff --git a/website/agenda/planung/pot/de/series.po b/website/agenda/planung/pot/de/series.po index bd99552..0fd0693 100644 --- a/website/agenda/planung/pot/de/series.po +++ b/website/agenda/planung/pot/de/series.po @@ -22,6 +22,9 @@ msgstr "Alte Sendereihen" msgid "button_show_changes" msgstr "Änderungen" +msgid "button_rebuild_episodes" +msgstr "Episoden neuzählen" + msgid "label_name" msgstr "Name" @@ -77,6 +80,18 @@ msgstr "Podcast URL" msgid "template_archive_url" msgstr "Archiv URL" +msgid "template_predecessor_id" +msgstr "ID der Vorgänger-Serie" + +msgid "template_content_format" +msgstr "Wiki-Sprache" + +msgid "template_content_format_markdown" +msgstr "Markdown" + +msgid "template_content_format_creole" +msgstr "Creole" + msgid "tab_schedule" msgstr "Planung" @@ -327,3 +342,4 @@ msgstr "löschen" msgid "label_excerpt_too_long" msgstr "Auszug ist zu lang. Für längeren Text bitte das Feld «aktuelle Themen» verwenden." + diff --git a/website/agenda/planung/pot/de/studio_timeslots.po b/website/agenda/planung/pot/de/studio-timeslots.po similarity index 94% rename from website/agenda/planung/pot/de/studio_timeslots.po rename to website/agenda/planung/pot/de/studio-timeslots.po index ba19bb0..5a327e1 100644 --- a/website/agenda/planung/pot/de/studio_timeslots.po +++ b/website/agenda/planung/pot/de/studio-timeslots.po @@ -58,6 +58,9 @@ msgstr "wöchentlich" msgid "every_two_weeks" msgstr "alle 14 Tage" +msgid "every_four_weeks" +msgstr "alle 28 Tage" + msgid "every_month" msgstr "monatlich" diff --git a/website/agenda/planung/pot/de/studios.po b/website/agenda/planung/pot/de/studios.po index 0d01acc..52281d4 100644 --- a/website/agenda/planung/pot/de/studios.po +++ b/website/agenda/planung/pot/de/studios.po @@ -34,6 +34,9 @@ msgstr "Beschreibung" msgid "label_location" msgstr "ID" +msgid "label_image" +msgstr "Logo" + msgid "label_stream" msgstr "Stream-URL" diff --git a/website/agenda/planung/pot/de/user_settings.po b/website/agenda/planung/pot/de/user-settings.po similarity index 89% rename from website/agenda/planung/pot/de/user_settings.po rename to website/agenda/planung/pot/de/user-settings.po index bb154fe..7915c9f 100644 --- a/website/agenda/planung/pot/de/user_settings.po +++ b/website/agenda/planung/pot/de/user-settings.po @@ -7,6 +7,12 @@ msgstr "Einstellungen" msgid "label_language" msgstr "Sprache" +msgid "label_studio" +msgstr "Studio" + +msgid "label_project" +msgstr "Projekt" + msgid "label_color" msgstr "Farbe" @@ -76,3 +82,5 @@ msgstr "Passwort (Wiederholung)" msgid "password_hint" msgstr "mindestens 8 Zeichen und (kleine und große Buchstaben, Zahlen und Sonderzeichen)" +msgid "setDefaultProjectStudio" +msgstr "Projekt und Studio als Default setzen" diff --git a/website/agenda/planung/pot/de/user_stats.po b/website/agenda/planung/pot/de/user-stats.po similarity index 56% rename from website/agenda/planung/pot/de/user_stats.po rename to website/agenda/planung/pot/de/user-stats.po index 0e843bf..15bbbaa 100644 --- a/website/agenda/planung/pot/de/user_stats.po +++ b/website/agenda/planung/pot/de/user-stats.po @@ -31,3 +31,30 @@ msgstr "letzte Änderung" msgid "label_score" msgstr "Punkte" +msgid "label_login" +msgstr "Login" + +msgid "label_full_name" +msgstr "Name" + +msgid "label_last_login" +msgstr "letztes Login" + +msgid "label_login_count" +msgstr "Anzahl Logins" + +msgid "label_disabled" +msgstr "gesperrt" + +msgid "label_created_at" +msgstr "erstellt am" + +msgid "label_created_by" +msgstr "erstellt von" + +msgid "button_show_active_users" +msgstr "aktive Nutzer" + +msgid "button_show_user_stats" +msgstr "Nutzerstatistik" + diff --git a/website/agenda/planung/pot/de/work_time.po b/website/agenda/planung/pot/de/work-time.po similarity index 100% rename from website/agenda/planung/pot/de/work_time.po rename to website/agenda/planung/pot/de/work-time.po diff --git a/website/agenda/planung/pot/en/audio_recordings.po b/website/agenda/planung/pot/en/audio-recordings.po similarity index 100% rename from website/agenda/planung/pot/en/audio_recordings.po rename to website/agenda/planung/pot/en/audio-recordings.po diff --git a/website/agenda/planung/pot/en/calendar.po b/website/agenda/planung/pot/en/calendar.po index feb3632..8c5a1ad 100644 --- a/website/agenda/planung/pot/en/calendar.po +++ b/website/agenda/planung/pot/en/calendar.po @@ -7,6 +7,9 @@ msgstr "today" msgid "button_search" msgstr "search" +msgid "label_pin" +msgstr "pin" + msgid "label_month" msgstr "month" @@ -31,6 +34,9 @@ msgstr "schedule" msgid "label_worktime" msgstr "worktime" +msgid "label_descriptions" +msgstr "descriptions" + msgid "label_playout" msgstr "playout" diff --git a/website/agenda/planung/pot/en/notify_events.po b/website/agenda/planung/pot/en/create-events.po similarity index 100% rename from website/agenda/planung/pot/en/notify_events.po rename to website/agenda/planung/pot/en/create-events.po diff --git a/website/agenda/planung/pot/en/event_history.po b/website/agenda/planung/pot/en/event-history.po similarity index 100% rename from website/agenda/planung/pot/en/event_history.po rename to website/agenda/planung/pot/en/event-history.po diff --git a/website/agenda/planung/pot/en/event.po b/website/agenda/planung/pot/en/event.po index 997c12d..05051ee 100644 --- a/website/agenda/planung/pot/en/event.po +++ b/website/agenda/planung/pot/en/event.po @@ -22,6 +22,9 @@ msgstr "save" msgid "button_delete" msgstr "delete" +msgid "button_apply" +msgstr "apply" + msgid "button_unassign_event" msgstr "unassign from series" @@ -121,6 +124,15 @@ msgstr "modified at" msgid "label_modified_by" msgstr "by" +msgid "label_content_format" +msgstr "wiki Language" + +msgid "label_content_format_markdown" +msgstr "Markdown" + +msgid "label_content_format_creole" +msgstr "Creole" + msgid "button_event_list" msgstr "show events" @@ -165,3 +177,7 @@ msgstr "excerpt is too long. for longer text please use the field «Current Topi msgid "label_excerpt_extension_too_long" msgstr "excerpt is too long. for longer text please use the field «Current Topics»" + +msgid "button_copy_to_clipboard" +msgstr "copy to clipboard" + diff --git a/website/agenda/planung/pot/en/image.po b/website/agenda/planung/pot/en/image.po index 9399773..35de737 100644 --- a/website/agenda/planung/pot/en/image.po +++ b/website/agenda/planung/pot/en/image.po @@ -1,3 +1,4 @@ + msgid "region" msgstr "en" @@ -16,18 +17,24 @@ msgstr "upload" msgid "button_search" msgstr "search" -msgid "button_zoom_in" -msgstr "zoom in" - -msgid "button_zoom_out" -msgstr "zoom out" - msgid "button_save" msgstr "save" msgid "button_delete" msgstr "delete" +msgid "button_properties" +msgstr "properties" + +msgid "button_publish" +msgstr "publish" + +msgid "button_depublish" +msgstr "hold back" + +msgid "label_warn_unknown_licence" +msgstr "Cannot be pusblished without setting a licence" + msgid "label_name" msgstr "name" @@ -52,3 +59,54 @@ msgstr "Editor-Link" msgid "label_search_hits" msgstr "hits" +msgid "label_licence" +msgstr "licence" + +msgid "label_author" +msgstr "author" + +msgid "label_public" +msgstr "published" + +msgid "label_file" +msgstr "file" + +msgid "label_name_required" +msgstr "please fill in" + +msgid "label_licence_required" +msgstr "image cannot be published without license" + +msgid "label_mandatory_field" +msgstr "please fill in" + +msgid "label_mandatory_field_licence" +msgstr "fill in licence to allow publishing the image" + +msgid "label_assign_to_event" +msgstr "use image for event" + +msgid "label_assign_to_series" +msgstr "use image for series" + +msgid "label_assign_to_studio" +msgstr "use image for studio" + +msgid "label_assign_to_project" +msgstr "use image for project" + +msgid "label_assign_to_projects" +msgstr "use image for project" + +msgid "label_warn_not_public_event" +msgstr "image must has been published before assigning to event" + +msgid "label_warn_not_public_series" +msgstr "image must has been published before assigning to series" + +msgid "label_warn_not_public_studio" +msgstr "image must has been published before assigning to studio" + +msgid "label_warn_not_public_project" +msgstr "image must has been published before assigning to project" + diff --git a/website/agenda/planung/pot/en/menu.po b/website/agenda/planung/pot/en/menu.po index 644dc3b..fba146c 100644 --- a/website/agenda/planung/pot/en/menu.po +++ b/website/agenda/planung/pot/en/menu.po @@ -49,3 +49,15 @@ msgstr "Import" msgid "help" msgstr "Help" +msgid "images" +msgstr "Images" + +msgid "schedule" +msgstr "Schedule" + +msgid "preview" +msgstr "Preview" + +msgid "user-stats" +msgstr "User Stats" + diff --git a/website/agenda/planung/pot/en/notify-events.po b/website/agenda/planung/pot/en/notify-events.po new file mode 100644 index 0000000..9885f4b --- /dev/null +++ b/website/agenda/planung/pot/en/notify-events.po @@ -0,0 +1,3 @@ +msgid "button_send" +msgstr "Send" + diff --git a/website/agenda/planung/pot/en/projects.po b/website/agenda/planung/pot/en/projects.po index fc94679..e674b12 100644 --- a/website/agenda/planung/pot/en/projects.po +++ b/website/agenda/planung/pot/en/projects.po @@ -43,8 +43,11 @@ msgstr "assign studio" msgid "button_edit" msgstr "edit" +msgid "button_change" +msgstr "edit studios" + msgid "button_show_changes" -msgstr "changes" +msgstr "show changes" msgid "label_name" msgstr "name" @@ -61,6 +64,9 @@ msgstr "start date" msgid "label_end_date" msgstr "end date" +msgid "label_activity" +msgstr "active" + msgid "label_image" msgstr "logo" diff --git a/website/agenda/planung/pot/en/roles.po b/website/agenda/planung/pot/en/roles.po index d5fcded..8379cf5 100644 --- a/website/agenda/planung/pot/en/roles.po +++ b/website/agenda/planung/pot/en/roles.po @@ -76,6 +76,9 @@ msgstr "edit podcast URL" msgid "label_update_event_field_archive_url" msgstr "edit archive URL" +msgid "label_update_event_field_content_format" +msgstr "set Wiki-Format" + msgid "label_create_event_from_schedule" msgstr "create new events (with date from an existing schedule)" diff --git a/website/agenda/planung/pot/en/selectEvent.po b/website/agenda/planung/pot/en/select-event.po similarity index 100% rename from website/agenda/planung/pot/en/selectEvent.po rename to website/agenda/planung/pot/en/select-event.po diff --git a/website/agenda/planung/pot/en/selectSeries.po b/website/agenda/planung/pot/en/select-series.po similarity index 100% rename from website/agenda/planung/pot/en/selectSeries.po rename to website/agenda/planung/pot/en/select-series.po diff --git a/website/agenda/planung/pot/en/series.po b/website/agenda/planung/pot/en/series.po index 5117b5d..ec240e7 100644 --- a/website/agenda/planung/pot/en/series.po +++ b/website/agenda/planung/pot/en/series.po @@ -22,6 +22,9 @@ msgstr "old series" msgid "button_show_changes" msgstr "changes" +msgid "button_rebuild_episodes" +msgstr "recount episodes" + msgid "label_name" msgstr "name" @@ -77,6 +80,18 @@ msgstr "Podcast URL" msgid "template_archive_url" msgstr "Archive URL" +msgid "template_predecessor_id" +msgstr "Series Predecessor ID" + +msgid "template_content_format" +msgstr "wiki Language" + +msgid "template_content_format_markdown" +msgstr "Markdown" + +msgid "template_content_format_creole" +msgstr "Creole" + msgid "tab_schedule" msgstr "Schedule" diff --git a/website/agenda/planung/pot/en/studio_timeslots.po b/website/agenda/planung/pot/en/studio-timeslots.po similarity index 94% rename from website/agenda/planung/pot/en/studio_timeslots.po rename to website/agenda/planung/pot/en/studio-timeslots.po index 1fe2b8e..b7b414f 100644 --- a/website/agenda/planung/pot/en/studio_timeslots.po +++ b/website/agenda/planung/pot/en/studio-timeslots.po @@ -58,6 +58,9 @@ msgstr "weekly" msgid "every_two_weeks" msgstr "every two weeks" +msgid "every_four_weeks" +msgstr "every four weeks" + msgid "every_month" msgstr "every month" diff --git a/website/agenda/planung/pot/en/studios.po b/website/agenda/planung/pot/en/studios.po index 510248a..278f28d 100644 --- a/website/agenda/planung/pot/en/studios.po +++ b/website/agenda/planung/pot/en/studios.po @@ -34,6 +34,9 @@ msgstr "description" msgid "label_location" msgstr "id" +msgid "label_image" +msgstr "image" + msgid "label_stream" msgstr "stream" diff --git a/website/agenda/planung/pot/en/user_settings.po b/website/agenda/planung/pot/en/user-settings.po similarity index 88% rename from website/agenda/planung/pot/en/user_settings.po rename to website/agenda/planung/pot/en/user-settings.po index 07e9e42..4c500d9 100644 --- a/website/agenda/planung/pot/en/user_settings.po +++ b/website/agenda/planung/pot/en/user-settings.po @@ -7,6 +7,12 @@ msgstr "user settings" msgid "label_language" msgstr "language" +msgid "label_studio" +msgstr "Studio" + +msgid "label_project" +msgstr "Project" + msgid "label_color" msgstr "color" @@ -75,3 +81,6 @@ msgstr "Password (repeat)" msgid "password_hint" msgstr "at least 8 characters (small and big characters, numbers and special characters)" + +msgid "setDefaultProjectStudio" +msgstr "set project and studio for default" diff --git a/website/agenda/planung/pot/en/user_stats.po b/website/agenda/planung/pot/en/user-stats.po similarity index 54% rename from website/agenda/planung/pot/en/user_stats.po rename to website/agenda/planung/pot/en/user-stats.po index 3a7bd6a..8b63e90 100644 --- a/website/agenda/planung/pot/en/user_stats.po +++ b/website/agenda/planung/pot/en/user-stats.po @@ -31,3 +31,30 @@ msgstr "last modified at" msgid "label_score" msgstr "Score" +msgid "label_login" +msgstr "Login" + +msgid "label_full_name" +msgstr "Name" + +msgid "label_last_login" +msgstr "last login date" + +msgid "label_login_count" +msgstr "login counts" + +msgid "label_disabled" +msgstr "disabled" + +msgid "label_created_at" +msgstr "created at" + +msgid "label_created_by" +msgstr "created by" + +msgid "button_show_active_users" +msgstr "active users" + +msgid "button_show_user_stats" +msgstr "user stats" + diff --git a/website/agenda/planung/pot/en/work_time.po b/website/agenda/planung/pot/en/work-time.po similarity index 100% rename from website/agenda/planung/pot/en/work_time.po rename to website/agenda/planung/pot/en/work-time.po diff --git a/website/agenda/planung/projects.cgi b/website/agenda/planung/projects.cgi index e35234d..2d13e9a 100755 --- a/website/agenda/planung/projects.cgi +++ b/website/agenda/planung/projects.cgi @@ -1,19 +1,22 @@ -#! /usr/bin/perl -w +#!/usr/bin/perl -use warnings "all"; use strict; +use warnings; +no warnings 'redefine'; + use Data::Dumper; -use config; -use params; -use log; -use template; -use auth; -use roles; -use uac; -use studios; -use series; -use localization; +use config(); +use entry(); +use params(); +use log(); +use template(); +use auth(); +use roles(); +use uac(); +use studios(); +use series(); +use localization(); my $r = shift; ( my $cgi, my $params, my $error ) = params::get($r); @@ -21,287 +24,269 @@ my $r = shift; my $config = config::get('../config/config.cgi'); my $debug = $config->{system}->{debug}; -my ( $user, $expires ) = auth::get_user( $cgi, $config ); +my ( $user, $expires ) = auth::get_user( $config, $params, $cgi ); return if ( $user eq '' ); -my $permissions = roles::get_user_permissions(); +my $permissions = roles::get_user_permissions($config); my $user_presets = uac::get_user_presets( - $config, - { - user => $user, - project_id => $params->{project_id}, - studio_id => $params->{studio_id} - } + $config, + { + user => $user, + project_id => $params->{project_id}, + studio_id => $params->{studio_id} + } ); $params->{default_studio_id} = $user_presets->{studio_id}; -$params->{studio_id} = $params->{default_studio_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); -$params->{project_id} = $user_presets->{project_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); +$params = uac::setDefaultStudio( $params, $user_presets ); +$params = uac::setDefaultProject( $params, $user_presets ); my $request = { - url => $ENV{QUERY_STRING} || '', - params => { - original => $params, - checked => check_params($params), - }, + url => $ENV{QUERY_STRING} || '', + params => { + original => $params, + checked => check_params( $config, $params ), + }, }; $request = uac::prepare_request( $request, $user_presets ); -log::init($request); $params = $request->{params}->{checked}; #process header my $headerParams = uac::set_template_permissions( $request->{permissions}, $params ); $headerParams->{loc} = localization::get( $config, { user => $user, file => 'menu' } ); -template::process( 'print', template::check('default.html'), $headerParams ); +template::process( $config, 'print', template::check( $config, 'projects-header.html' ), $headerParams ); return unless uac::check( $config, $params, $user_presets ) == 1; -print q{ - <link rel="stylesheet" href="css/projects.css" type="text/css" /> - <script src="js/datetime.js" type="text/javascript"></script> - <script src="js/projects.js" type="text/javascript"></script> -}; - if ( defined $params->{action} ) { - save_project( $config, $request ) if ( $params->{action} eq 'save' ); - delete_project( $config, $request ) if ( $params->{action} eq 'delete' ); - assign_studio( $config, $request ) if ( $params->{action} eq 'assign_studio' ); - unassign_studio( $config, $request ) if ( $params->{action} eq 'unassign_studio' ); + save_project( $config, $request ) if ( $params->{action} eq 'save' ); + delete_project( $config, $request ) if ( $params->{action} eq 'delete' ); + assign_studio( $config, $request ) if ( $params->{action} eq 'assign_studio' ); + unassign_studio( $config, $request ) if ( $params->{action} eq 'unassign_studio' ); } $config->{access}->{write} = 0; show_projects( $config, $request ); sub delete_project { - my $config = shift; - my $request = shift; + my $config = shift; + my $request = shift; - my $permissions = $request->{permissions}; - unless ( $permissions->{delete_project} == 1 ) { - uac::permissions_denied('delete_project'); - return; - } + my $permissions = $request->{permissions}; + unless ( $permissions->{delete_project} == 1 ) { + uac::permissions_denied('delete_project'); + return; + } - my $params = $request->{params}->{checked}; - my $columns = project::get_columns($config); + my $params = $request->{params}->{checked}; + my $columns = project::get_columns($config); - my $entry = {}; - for my $param ( keys %$params ) { - if ( defined $columns->{$param} ) { - $entry->{$param} = $params->{$param} || ''; - } - } + my $entry = {}; + for my $param ( keys %$params ) { + if ( exists $columns->{$param} ) { + $entry->{$param} = $params->{$param} || ''; + } + } - my $project_id = $params->{pid} || ''; + my $project_id = $params->{pid} || ''; - if ( $project_id ne '' ) { - $config->{access}->{write} = 1; - $entry->{project_id} = $project_id; - delete $entry->{studio_id}; - project::delete( $config, $entry ); - uac::print_info("Project deleted"); - } + if ( $project_id ne '' ) { + $config->{access}->{write} = 1; + $entry->{project_id} = $project_id; + delete $entry->{studio_id}; + project::delete( $config, $entry ); + uac::print_info("Project deleted"); + } } sub save_project { - my $config = shift; - my $request = shift; + my $config = shift; + my $request = shift; - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; - #filter entry for studio columns - my $columns = project::get_columns($config); - my $entry = {}; - for my $param ( keys %$params ) { - if ( defined $columns->{$param} ) { - $entry->{$param} = $params->{$param} || ''; - } - } + #filter entry for studio columns + my $columns = project::get_columns($config); + my $entry = {}; + for my $param ( keys %$params ) { + if ( exists $columns->{$param} ) { + $entry->{$param} = $params->{$param} || ''; + } + } - my $project_id = $params->{pid} || ''; - if ( $project_id ne '' ) { - unless ( $permissions->{update_project} == 1 ) { - uac::permissions_denied('update_project'); - return; - } - $entry->{project_id} = $project_id; - delete $entry->{studio_id}; + my $project_id = $params->{pid} || ''; + if ( $project_id ne '' ) { + unless ( $permissions->{update_project} == 1 ) { + uac::permissions_denied('update_project'); + return; + } + $entry->{project_id} = $project_id; + delete $entry->{studio_id}; - $config->{access}->{write} = 1; - project::update( $config, $entry ); - $config->{access}->{write} = 0; - uac::print_info("project saved"); - } else { - unless ( $permissions->{create_project} == 1 ) { - uac::permissions_denied('create_project'); - return; - } - my $projects = project::get( $config, { name => $entry->{name} } ); - if ( @$projects > 0 ) { - uac::print_error("project with name '$entry->{name}' already exists"); - return; - } - delete $entry->{project_id}; - delete $entry->{studio_id}; + $config->{access}->{write} = 1; + project::update( $config, $entry ); + $config->{access}->{write} = 0; + uac::print_info("project saved"); + } else { + unless ( $permissions->{create_project} == 1 ) { + uac::permissions_denied('create_project'); + return; + } + my $projects = project::get( $config, { name => $entry->{name} } ); + if ( scalar @$projects > 0 ) { + uac::print_error("project with name '$entry->{name}' already exists"); + return; + } + delete $entry->{project_id}; + delete $entry->{studio_id}; - $config->{access}->{write} = 1; - project::insert( $config, $entry ); - $config->{access}->{write} = 0; - uac::print_info("project created"); - } + $config->{access}->{write} = 1; + project::insert( $config, $entry ); + $config->{access}->{write} = 0; + uac::print_info("project created"); + } } sub assign_studio { - my $config = shift; - my $request = shift; + my $config = shift; + my $request = shift; - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - unless ( $permissions->{assign_project_studio} == 1 ) { - uac::permissions_denied('assign_project_studio'); - return; - } + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + unless ( $permissions->{assign_project_studio} == 1 ) { + uac::permissions_denied('assign_project_studio'); + return; + } - for my $param ( 'pid', 'sid' ) { - unless ( defined $params->{$param} ) { - uac::print_error( 'missing ' . $param ); - return; - } - } - $config->{access}->{write} = 1; - project::assign_studio( - $config, - { - project_id => $params->{pid}, - studio_id => $params->{sid} - } - ); - $config->{access}->{write} = 0; - uac::print_info("project assigned"); + for my $param ( 'pid', 'sid' ) { + unless ( defined $params->{$param} ) { + uac::print_error( 'missing ' . $param ); + return; + } + } + $config->{access}->{write} = 1; + project::assign_studio( + $config, + { + project_id => $params->{pid}, + studio_id => $params->{sid} + } + ); + $config->{access}->{write} = 0; + uac::print_info("project assigned"); } # TODO: unassign series from studio sub unassign_studio { - my $config = shift; - my $request = shift; + my $config = shift; + my $request = shift; - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - unless ( $permissions->{assign_project_studio} == 1 ) { - uac::permissions_denied('assign_project_studio'); - return; - } + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + unless ( $permissions->{assign_project_studio} == 1 ) { + uac::permissions_denied('assign_project_studio'); + return; + } - for my $param ( 'pid', 'sid' ) { - unless ( defined $params->{$param} ) { - uac::print_error( 'missing ' . $param ); - return; - } - } - $config->{access}->{write} = 1; - project::unassign_studio( - $config, - { - project_id => $params->{pid}, - studio_id => $params->{sid} - } - ); - $config->{access}->{write} = 0; - uac::print_info("project unassigned"); + for my $param ( 'pid', 'sid' ) { + unless ( defined $params->{$param} ) { + uac::print_error( 'missing ' . $param ); + return; + } + } + $config->{access}->{write} = 1; + project::unassign_studio( + $config, + { + project_id => $params->{pid}, + studio_id => $params->{sid} + } + ); + $config->{access}->{write} = 0; + uac::print_info("project unassigned"); } sub show_projects { - my $config = shift; - my $request = shift; + my $config = shift; + my $request = shift; - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; - unless ( $permissions->{read_project} == 1 ) { - uac::permissions_denied('read_project'); - return; - } + unless ( $permissions->{read_project} == 1 ) { + uac::permissions_denied('read_project'); + return; + } - my $projects = project::get($config); - my $studios = studios::get($config); - my @projects = reverse sort { $a->{end_date} cmp $b->{end_date} } (@$projects); - $projects = \@projects; + my $projects = project::get($config); + my $studios = studios::get($config); + my @projects = reverse sort { $a->{end_date} cmp $b->{end_date} } (@$projects); + $projects = \@projects; - for my $project (@$projects) { + for my $project (@$projects) { - # get assigned studios - my $project_studio_assignements = project::get_studio_assignments( $config, { project_id => $project->{project_id} } ); - $project->{pid} = $project->{project_id}; + # get assigned studios + my $project_studio_assignements = + project::get_studio_assignments( $config, { project_id => $project->{project_id} } ); + $project->{pid} = $project->{project_id}; - # get assigned studios by id - my $assigned_studio_by_id = {}; - for my $studio (@$project_studio_assignements) { - $assigned_studio_by_id->{ $studio->{studio_id} } = 1; - } + # get assigned studios by id + my $assigned_studio_by_id = { map { $_->{studio_id} => 1 } @$project_studio_assignements }; + my $assigned_studios = []; + my $unassigned_studios = []; + for my $studio (@$studios) { + my %studio = %$studio; + $studio = \%studio; + $studio->{pid} = $project->{pid}; + $studio->{sid} = $studio->{id}; + if ( defined $assigned_studio_by_id->{ $studio->{id} } ) { + push @$assigned_studios, $studio; + } else { + push @$unassigned_studios, $studio; + } + } + $project->{assigned_studios} = $assigned_studios; + $project->{unassigned_studios} = $unassigned_studios; - my $assigned_studios = []; - my $unassigned_studios = []; - for my $studio (@$studios) { - my %studio = %$studio; - $studio = \%studio; - $studio->{pid} = $project->{pid}; - $studio->{sid} = $studio->{id}; - if ( defined $assigned_studio_by_id->{ $studio->{id} } ) { - push @$assigned_studios, $studio; - } else { - push @$unassigned_studios, $studio; - } - } - $project->{assigned_studios} = $assigned_studios; - $project->{unassigned_studios} = $unassigned_studios; - } + if ( ( defined $params->{setImage} ) && ( $project->{pid} eq $params->{pid} ) ) { + $project->{image} = $params->{setImage}; + } + } - $params->{projects} = $projects; - $params->{loc} = localization::get( $config, { user => $params->{presets}->{user}, file => 'projects' } ); - uac::set_template_permissions( $permissions, $params ); + $params->{projects} = $projects; + $params->{loc} = localization::get( $config, { user => $params->{presets}->{user}, file => 'projects' } ); + uac::set_template_permissions( $permissions, $params ); - template::process( 'print', $params->{template}, $params ); + template::process( $config, 'print', $params->{template}, $params ); } sub check_params { - my $params = shift; + my $config = shift; + my $params = shift; - my $checked = {}; + my $checked = {}; - #template - my $template = ''; - $template = template::check( $params->{template}, 'projects' ); - $checked->{template} = $template; + #template + my $template = ''; + $template = template::check( $config, $params->{template}, 'projects' ); + $checked->{template} = $template; - #actions - my $action = ''; - if ( defined $params->{action} ) { - if ( $params->{action} =~ /^(save|delete|assign_studio|unassign_studio)$/ ) { - $checked->{action} = $params->{action}; - } - } + $checked->{action} = entry::element_of($params->{action}, + ['save', 'delete', 'assign_studio', 'unassign_studio'] ); - for my $param ( 'name', 'title', 'subtitle', 'start_date', 'end_date', 'image', 'email' ) { - if ( defined $params->{$param} ) { - $checked->{$param} = $params->{$param}; - } - } + entry::set_strings( $checked, $params, [ + 'name', 'title', 'subtitle', 'start_date', 'end_date', 'image', 'email', 'setImage' ]); - #numeric values - for my $param ( 'project_id', 'studio_id', 'default_studio_id', 'pid', 'sid' ) { - if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /^\d+$/ ) ) { - $checked->{$param} = $params->{$param}; - } - } - if ( defined $checked->{studio_id} ) { - $checked->{default_studio_id} = $checked->{studio_id}; - } else { - $checked->{studio_id} = -1; - } + entry::set_numbers( $checked, $params, [ + 'project_id', 'studio_id', 'default_studio_id', 'pid', 'sid']); + + if ( defined $checked->{studio_id} ) { + $checked->{default_studio_id} = $checked->{studio_id}; + } else { + $checked->{studio_id} = -1; + } - return $checked; + return $checked; } diff --git a/website/agenda/planung/request-password.cgi b/website/agenda/planung/request-password.cgi new file mode 100755 index 0000000..cc17b1b --- /dev/null +++ b/website/agenda/planung/request-password.cgi @@ -0,0 +1,160 @@ +#!/usr/bin/perl + +use strict; +use warnings; +no warnings 'redefine'; + +use Data::Dumper; + +use params(); +use config(); +use entry(); +use db(); +use auth(); +use password_requests(); + +binmode STDOUT, ":utf8"; + +my $r = shift; +( my $cgi, my $params, my $error ) = params::get($r); + +my $config = config::get('../config/config.cgi'); +my $debug = $config->{system}->{debug}; + +$params = check_params( $config, $params ); + +print "Content-type:text/html\n\n"; +print qq{<!DOCTYPE html> +<html> +<head> + <meta charset="UTF-8"> +</head> +<style> + * {text-align:center; font-family: sans-serif;} + div,input {padding:6px;margin:6px;} + .error {background:red; color:white;} + .info {background:blue; color:white;} +</style> +<body> +<h1>Change your password</h1> +}; + +sub info{ + print qq{<div class="info">$_[0]</div>\n}; +} +sub error{ + print qq{<div class="error">$_[0]</div>\n}; +} + +if ( defined $params->{user} ) { + sendToken( $config, $params ); + return; +} else { + my $result = checkToken( $config, $params ); + return; +} + +sub sendToken { + my $config = shift; + my $params = shift; + my $entry = password_requests::sendToken( $config, { user => $params->{user} } ); + if ( defined $entry ) { + info "Please check you mails."; + } else { + error "Sorry."; + } +} + +sub checkToken { + my $config = shift; + my $params = shift; + + my $token = $params->{token}; + + my $entry = password_requests::get( $config, { token => $token } ); + unless ( defined $entry ) { + return error "The token is invalid."; + } + + my $created_at = $entry->{created_at}; + unless ( defined $created_at ) { + return error "The token age is invalid."; + } + + my $age = time() - time::datetime_to_time($created_at); + if ( $age > 600 ) { + error "The token is too old."; + password_requests::delete( $config, { token => $token } ); + return undef; + } + + $config->{access}->{write} = 1; + $entry->{max_attempts}++; + password_requests::update( $config, $entry ); + $config->{access}->{write} = 0; + + if ( $entry->{max_attempts} > 10 ) { + error "Too many failed attempts. Please request a new token by mail."; + password_requests::delete( $config, { token => $token } ); + return undef; + } + + unless ( ( defined $params->{user_password} ) && ( defined $params->{user_password2} ) ) { + printForm($token); + return undef; + } + + if ( $params->{action} eq 'change' ) { + my $user = $entry->{user}; + my $request = { + config => $config, + params => { checked => $params } + }; + my $result = password_requests::changePassword( $config, $request, $user ); + if ( defined $result->{error} ) { + error $result->{error}; + printForm($token); + } + + if ( defined $result->{success} ) { + info $result->{success}; + password_requests::delete( $config, { user => $user } ); + my $url = $config->{locations}->{editor_base_url}; + print qq{ + <script type="text/javascript"> + setTimeout( () => window.location = "$url", 3000); + </script> + You will be forwarded to $url … + }; + } + } + +} + +sub printForm { + my $token = shift; + print qq{ + <form method="post"> + <input type="hidden" name="token" value="$token"> + <input type="password" name="user_password" placeholder="Please enter a password"> + <input type="password" name="user_password2" placeholder="Please repeat the password"> + <input type="submit" name="action" value="change"> + </form> + }; + +} + +sub check_params { + my $config = shift; + my $params = shift; + + my $checked = {}; + + entry::set_strings( $checked, $params, [ + 'user', 'token', 'user_password', 'user_password2']); + + $checked->{action} = entry::element_of($params->{action}, ['change']); + + return $checked; +} + diff --git a/website/agenda/planung/roles.cgi b/website/agenda/planung/roles.cgi index 71ee003..e9a92f4 100755 --- a/website/agenda/planung/roles.cgi +++ b/website/agenda/planung/roles.cgi @@ -1,18 +1,22 @@ -#! /usr/bin/perl -w +#!/usr/bin/perl -use warnings "all"; use strict; +use warnings; +no warnings 'redefine'; + use Data::Dumper; -use config; -use params; -use log; -use template; -use auth; -use roles; -use uac; -use studios; -use localization; +use config(); +use params(); +use entry(); +use log(); +use template(); +use auth(); +use roles(); +use uac(); +use studios(); +use localization(); + binmode STDOUT, ":utf8"; my $r = shift; @@ -21,60 +25,56 @@ my $r = shift; my $config = config::get('../config/config.cgi'); my $debug = $config->{system}->{debug}; -my ( $user, $expires ) = auth::get_user( $cgi, $config ); +my ( $user, $expires ) = auth::get_user( $config, $params, $cgi ); return if ( ( !defined $user ) || ( $user eq '' ) ); our $actions = { - read => 1, - update => 2, - assign => 3, - remove => 4, - disable => 5, - scan => 6, - create => 7, - delete => 8, + read => 1, + update => 2, + assign => 3, + remove => 4, + disable => 5, + scan => 6, + create => 7, + delete => 8, }; my $user_presets = uac::get_user_presets( - $config, - { - user => $user, - project_id => $params->{project_id}, - studio_id => $params->{studio_id} - } + $config, + { + user => $user, + project_id => $params->{project_id}, + studio_id => $params->{studio_id} + } ); $params->{default_studio_id} = $user_presets->{studio_id}; -$params->{studio_id} = $params->{default_studio_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); +$params = uac::setDefaultStudio( $params, $user_presets ); $params->{project_id} = $user_presets->{project_id}; my $request = { - url => $ENV{QUERY_STRING} || '', - params => { - original => $params, - checked => check_params($params), - }, + url => $ENV{QUERY_STRING} || '', + params => { + original => $params, + checked => check_params( $config, $params ), + }, }; $request = uac::prepare_request( $request, $user_presets ); -log::init($request); - $params = $request->{params}->{checked}; #process header my $headerParams = uac::set_template_permissions( $request->{permissions}, $params ); $headerParams->{loc} = localization::get( $config, { user => $user, file => 'menu' } ); -template::process( 'print', template::check('roles.html'), $headerParams ); +template::process( $config, 'print', template::check( $config, 'roles.html' ), $headerParams ); return unless uac::check( $config, $params, $user_presets ) == 1; if ( defined $params->{action} ) { - save_roles( $config, $request ) if ( $params->{action} eq 'save' ); + save_roles( $config, $request ) if ( $params->{action} eq 'save' ); } #show current roles $config->{access}->{write} = 0; show_roles( $config, $request ); -#print '<pre>'.Dumper($request); return; # update roles in database: @@ -84,387 +84,374 @@ return; # new roles will have role level 0 by default # sub save_roles { - my $config = shift; - my $request = shift; + my $config = shift; + my $request = shift; - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; - unless ( $permissions->{update_role} == 1 ) { - uac::permissions_denied('update_role'); - return; - } + unless ( $permissions->{update_role} == 1 ) { + uac::permissions_denied('update_role'); + return; + } - my $studio_id = $params->{studio_id}; - my $project_id = $params->{project_id}; - my $roles = uac::get_roles( $config, { project_id => $project_id, studio_id => $studio_id } ); + my $studio_id = $params->{studio_id}; + my $project_id = $params->{project_id}; + my $roles = uac::get_roles( $config, { project_id => $project_id, studio_id => $studio_id } ); - my $role_by_id = {}; - my $role_by_name = {}; - for my $role (@$roles) { - $role_by_id->{ $role->{id} } = $role; - $role_by_name->{ $role->{role} } = $role; - } + my $role_by_id = {}; + my $role_by_name = {}; + for my $role (@$roles) { + $role_by_id->{ $role->{id} } = $role; + $role_by_name->{ $role->{role} } = $role; + } - my $columns = uac::get_role_columns($config); + my $columns = uac::get_role_columns($config); - #print '<pre>'.Dumper($columns).'</pre>'; + #initialize all value ids (given by params matching to database columns) + my $values = {}; + for my $param ( sort keys %$params ) { + if ( $param =~ /(.+?)\_(\d+)?$/ ) { + my $column = $1; + my $id = $2 || ''; + next unless defined $columns->{$column}; + $values->{$id} = {} if ( update_allowed( $permissions, $role_by_id, $id ) ); + } + } - #initialize all value ids (given by params matching to database columns) - my $values = {}; - for my $param ( keys %$params ) { - if ( $param =~ /(.+?)\_(\d+)?$/ ) { - my $column = $1; - my $id = $2 || ''; - next unless defined $columns->{$column}; - $values->{$id} = {} if ( update_allowed( $permissions, $role_by_id, $id ) ); - } - } + #init checkbox values with 0 + for my $id ( sort keys %$values ) { + if ( update_allowed( $permissions, $role_by_id, $id ) ) { + for my $column ( keys %$columns ) { + next + if ( $column eq 'level' + || $column eq 'role' + || $column eq 'id' + || $column eq 'project_id' + || $column eq 'studio_id' + || $column eq 'created_at' + ); + $values->{$id}->{$column} = 0; + } + } + } - #init checkbox values with 0 - for my $id ( keys %$values ) { - if ( update_allowed( $permissions, $role_by_id, $id ) ) { - for my $column ( keys %$columns ) { - next if ( $column eq 'level' || $column eq 'role' || $column eq 'id' || $column eq 'project_id' || $column eq 'studio_id' ); - $values->{$id}->{$column} = 0; - } - } - } + #set all checkbox values to 1 + for my $param ( sort keys %$params ) { + if ( $param =~ /(.+?)\_(\d+)?$/ ) { + my $column = $1; + my $id = $2 || ''; + next unless defined $columns->{$column}; + if ( update_allowed( $permissions, $role_by_id, $id ) ) { + my $value = $params->{$param} || ''; + if ( $column eq 'level' ) { + if ( check_level( $permissions, $value ) == 1 ) { + $values->{$id}->{$column} = $value; + } else { + uac::permissions_denied("change the level of role!"); + return; + } + } elsif ( $column eq 'role' ) { + $values->{$id}->{$column} = $value; + } elsif ( $column eq 'id' || $column eq 'project_id' || $column eq 'studio_id' ) { - #set all checkbox values to 1 - for my $param ( keys %$params ) { - if ( $param =~ /(.+?)\_(\d+)?$/ ) { - my $column = $1; - my $id = $2 || ''; - next unless ( defined $columns->{$column} ); - if ( update_allowed( $permissions, $role_by_id, $id ) ) { - my $value = $params->{$param} || ''; - if ( $column eq 'level' ) { - if ( check_level( $permissions, $value ) == 1 ) { - $values->{$id}->{$column} = $value; - } else { - uac::permissions_denied("change the level of role!"); - return; - } - } elsif ( $column eq 'role' ) { - $values->{$id}->{$column} = $value; - } elsif ( $column eq 'id' || $column eq 'project_id' || $column eq 'studio_id' ) { + #id and studio id will be set later + } else { + $values->{$id}->{$column} = 1 if ( $value =~ /^\d+$/ ); + } + } + } + } - #id and studio id will be set later - } else { - $values->{$id}->{$column} = 1 if ( $value =~ /^\d+$/ ); - } - } - } - } + #order roles to update by level + for my $id ( sort { $values->{$a}->{level} <=> $values->{$b}->{level} } keys %$values ) { + my $role = $values->{$id}; + $role->{id} = $id || ''; + $role->{studio_id} = $studio_id; + $role->{project_id} = $project_id; - #print STDERR Dumper($values); - #order roles to update by level - for my $id ( sort { $values->{$a}->{level} <=> $values->{$b}->{level} } keys %$values ) { - my $role = $values->{$id}; - $role->{id} = $id || ''; - $role->{studio_id} = $studio_id; - $role->{project_id} = $project_id; + #if you are not admin + next if check_level( $permissions, $role->{level} ) == 0; - #if you are not admin - next if check_level( $permissions, $role->{level} ) == 0; + if ( $role->{project_id} eq '' ) { + uac::print_error('missing parameter project_id!'); + next; + } + if ( $role->{studio_id} eq '' ) { + uac::print_error('missing parameter studio_id!'); + next; + } + if ( ( $role->{role} eq '' ) && ( $id ne '' ) ) { + uac::print_error('missing parameter role!'); + next; + } - if ( $role->{project_id} eq '' ) { - uac::print_error('missing parameter project_id!'); - next; - } - if ( $role->{studio_id} eq '' ) { - uac::print_error('missing parameter studio_id!'); - next; - } - if ( ( $role->{role} eq '' ) && ( $id ne '' ) ) { - uac::print_error('missing parameter role!'); - next; - } + my $role_from_db = undef; + $role_from_db = $role_by_name->{ $role->{role} } if defined $role_by_name->{ $role->{role} }; - my $role_from_db = undef; - $role_from_db = $role_by_name->{ $role->{role} } if defined $role_by_name->{ $role->{role} }; + if ( $id eq '' ) { - if ( $id eq '' ) { + #insert role + next if $role->{role} eq ''; + if ( defined $role_from_db ) { + uac::print_error("a role with name '$role->{role}' already exists!"); + next; + } + $role->{level} = 0; + print "insert $id $role->{role}<br>\n"; + $config->{access}->{write} = 1; + uac::insert_role( $config, $role ); + $config->{access}->{write} = 0; + } else { - #insert role - next if ( $role->{role} eq '' ); - if ( defined $role_from_db ) { - uac::print_error("a role with name '$role->{role}' already exists!"); - next; - } - $role->{level} = 0; - print "insert $id $role->{role}<br>\n"; - $config->{access}->{write} = 1; - uac::insert_role( $config, $role ); - $config->{access}->{write} = 0; - } else { + #update role + if ( ( defined $role_from_db ) && ( $id ne $role_from_db->{id} ) ) { + uac::print_error( 'you cannot rename role to existing role!' + . " '$role->{role}' ($id) != '$role_from_db->{role}' ($role_from_db->{id})" ); + next; + } + print "update $role->{role}<br>\n"; - #update role - if ( ( defined $role_from_db ) && ( $id ne $role_from_db->{id} ) ) { - uac::print_error( 'you cannot rename role to existing role!' - . " '$role->{role}' ($id) != '$role_from_db->{role}' ($role_from_db->{id})" ); - next; - } - print "update $role->{role}<br>\n"; - - #print '<div style="height:3em;overflow:auto;white-space:pre">'.Dumper($role).'</div>'; - $config->{access}->{write} = 1; - uac::update_role( $config, $role ); - $config->{access}->{write} = 0; - } - } - print qq{<div class="ok head">changes saved</div>}; + #print '<div style="height:3em;overflow:auto;white-space:pre">'.Dumper($role).'</div>'; + $config->{access}->{write} = 1; + uac::update_role( $config, $role ); + $config->{access}->{write} = 0; + } + } + print qq{<div class="ok head">changes saved</div>}; } #check if update is allowed sub update_allowed { - my $permissions = shift; - my $role_by_id = shift; - my $id = shift; + my $permissions = shift; + my $role_by_id = shift; + my $id = shift; - return 0 unless defined $permissions; - return 0 unless defined $role_by_id; - return 0 unless defined $id; - return 1 if $id eq ''; - return 0 unless defined $role_by_id->{$id}; - my $role = $role_by_id->{$id}; - return check_level( $permissions, $role->{level} ); + return 0 unless defined $permissions; + return 0 unless defined $role_by_id; + return 0 unless defined $id; + return 1 if $id eq ''; + return 0 unless defined $role_by_id->{$id}; + my $role = $role_by_id->{$id}; + return check_level( $permissions, $role->{level} ); } #check if update is allowed sub check_level { - my $permissions = shift; - my $level = shift; - return 0 unless defined $permissions; - return 0 unless defined $level; - return 1 if ( $permissions->{is_admin} ); - return 1 if ( $permissions->{level} > $level ); - return 0; + my $permissions = shift; + my $level = shift; + return 0 unless defined $permissions; + return 0 unless defined $level; + return 1 if ( $permissions->{is_admin} ); + return 1 if ( $permissions->{level} > $level ); + return 0; } # user has to be assigned to studio # user needs to have permissions read_role sub show_roles { - my $config = shift; - my $request = shift; + my $config = shift; + my $request = shift; - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - unless ( $permissions->{read_role} == 1 ) { - uac::permissions_denied('read_role'); - return; - } + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + unless ( $permissions->{read_role} == 1 ) { + uac::permissions_denied('read_role'); + return; + } - my $studio_id = $params->{studio_id}; - my $project_id = $params->{project_id}; - my $columns = uac::get_role_columns($config); + my $studio_id = $params->{studio_id}; + my $project_id = $params->{project_id}; + my $columns = uac::get_role_columns($config); - #get user roles - my $conditions = {}; - $conditions->{studio_id} = $params->{studio_id} if ( $params->{studio_id} ne '' ); - $conditions->{project_id} = $params->{project_id} if ( $params->{project_id} ne '' ); - my $roles = uac::get_roles( $config, $conditions ); - @$roles = reverse sort { $a->{level} cmp $b->{level} } (@$roles); + #get user roles + my $conditions = {}; + $conditions->{studio_id} = $params->{studio_id} if ( $params->{studio_id} ne '' ); + $conditions->{project_id} = $params->{project_id} if ( $params->{project_id} ne '' ); + my $roles = uac::get_roles( $config, $conditions ); + @$roles = reverse sort { $a->{level} cmp $b->{level} } (@$roles); - #add new role template - unshift @$roles, { role => '', level => '0' }; + #add new role template + unshift @$roles, { role => '', level => '0' }; - #print user role form - my $out = qq{ + #print user role form + my $out = qq{ <div id="edit_roles"> <form method="post"> <input type="hidden" name="project_id" value="$project_id"> <input type="hidden" name="studio_id" value="$studio_id"> }; - if ( defined $permissions->{update_role} ) { + if ( defined $permissions->{update_role} ) { - #add new user role button - $out .= q{ + #add new user role button + $out .= q{ <button id="add_user_role_button" onclick="add_user_role();return false;">add user role</button> } - } + } - $out .= '<hr>'; - $out .= '<table class="table">'; - my $localization = localization::get( $config, { user => $params->{presets}->{user}, file => 'roles' } ); - for my $key ( keys %$localization ) { - $localization->{$key} =~ s/\(/<span class\=\"comment\">/; - $localization->{$key} =~ s/\)/<\/span>/; - } + $out .= '<div class="panel">'; + $out .= '<table class="table">'; + my $localization = localization::get( $config, { user => $params->{presets}->{user}, file => 'roles' } ); + for my $key ( keys %$localization ) { + $localization->{$key} =~ s/\(/<span class\=\"comment\">/; + $localization->{$key} =~ s/\)/<\/span>/; + } - #add role row - $out .= qq{<tr>}; - my $description = $localization->{label_role} || 'role'; - $out .= qq{<td>$description</td>}; + #add role row + $out .= qq{<tr>}; + my $description = $localization->{label_role} || 'role'; + $out .= qq{<td>$description</td>}; - for my $role (@$roles) { - $role->{active} = ''; - $role->{active} = ' disabled' if check_level( $permissions, $role->{level} ) == 0; - $role->{active} = ' disabled' unless defined $permissions->{update_role}; - } + for my $role (@$roles) { + $role->{active} = ''; + $role->{active} = ' disabled' if check_level( $permissions, $role->{level} ) == 0; + $role->{active} = ' disabled' unless defined $permissions->{update_role}; + } - for my $role (@$roles) { + for my $role (@$roles) { - #print Dumper($role); - my $id = $role->{id} || ''; - my $value = $role->{role} || ''; - my $style = ''; - $style = ' id="new_user_role" class="editor" style="display:none"' if ( $id eq '' ); - my $active = $role->{active}; - $out .= qq{<td$style><input name="role_$id" value="$value" class="role$active" title="$value"></td>}; - } - $out .= qq{</tr>}; + my $id = $role->{id} || ''; + my $value = $role->{role} || ''; + my $style = ''; + $style = ' id="new_user_role" class="editor" style="display:none"' if ( $id eq '' ); + my $active = $role->{active}; + $out .= qq{<td$style><input name="role_$id" value="$value" class="role$active" title="$value"></td>}; + } + $out .= qq{</tr>}; - #add level row - $out .= qq{<tr>}; - $description = $localization->{label_level} || 'level'; - $out .= qq{<td>$description</td>}; - for my $role (@$roles) { - my $id = $role->{id} || ''; - my $value = $role->{level} || ''; - my $style = ''; - $style = ' id="new_user_level" class="editor" style="display:none"' if ( $id eq '' ); - my $active = $role->{active}; - $out .= qq{<td$style><input name="level_$id" value="$value" class="role$active" title="$value"></td>}; - } - $out .= qq{</tr>}; + #add level row + $out .= qq{<tr>}; + $description = $localization->{label_level} || 'level'; + $out .= qq{<td>$description</td>}; + for my $role (@$roles) { + my $id = $role->{id} || ''; + my $value = $role->{level} || ''; + my $style = ''; + $style = ' id="new_user_level" class="editor" style="display:none"' if ( $id eq '' ); + my $active = $role->{active}; + $out .= qq{<td$style><input name="level_$id" value="$value" class="role$active" title="$value"></td>}; + } + $out .= qq{</tr>}; - #add permission rows - $columns = sort_columns($columns); + #add permission rows + $columns = sort_columns($columns); - # print '<pre>'; - # for my $key (@$columns){ - # printf (" %-40s => '',\n", "'".$key."'"); - # } - # print '</pre>'; - - for my $key (@$columns) { - next - if ( $key eq 'level' - || $key eq 'role' - || $key eq 'id' - || $key eq 'project_id' - || $key eq 'studio_id' - || $key eq 'modified_at' - || $key eq 'created_at' ); - my $title = $key; - $title =~ s/\_/ /g; - my $description = $localization->{ 'label_' . $key } || $key; - $out .= qq{<tr>}; - $out .= qq{<td title="$title">$description</td>}; - for my $role (@$roles) { - my $value = $role->{$key} || '0'; - my $id = $role->{id} || ''; - my $active = $role->{active}; - my $style = ''; - $style = ' class="editor' . $active . '" style="display:none"' if ( $id eq '' ); - my $checked = ''; - $checked = 'checked="checked"' if ( $value eq '1' ); - $active =~ s/\s//g; - $out .= qq{<td$style> + for my $key (@$columns) { + next + if ( $key eq 'level' + || $key eq 'role' + || $key eq 'id' + || $key eq 'project_id' + || $key eq 'studio_id' + || $key eq 'modified_at' + || $key eq 'created_at' ); + my $title = $key; + $title =~ s/\_/ /g; + my $description = $localization->{ 'label_' . $key } || $key; + $out .= qq{<tr>}; + $out .= qq{<td title="$title">$description</td>}; + for my $role (@$roles) { + my $value = $role->{$key} || '0'; + my $id = $role->{id} || ''; + my $active = $role->{active}; + my $style = ''; + $style = ' class="editor' . $active . '" style="display:none"' if ( $id eq '' ); + my $checked = ''; + $checked = 'checked="checked"' if ( $value eq '1' ); + $active =~ s/\s//g; + $out .= qq{<td$style> <input type="checkbox" name="} . $key . '_' . $id . qq{" value="$value" $checked class="$active"> </td> }; - } - $out .= qq{</tr>}; - } - $out .= '</table>'; - $out .= '<input type="submit" name="action" value="save">' if ( defined $permissions->{update_role} ); - $out .= '</form>'; - $out .= '</div>'; - print $out. "\n"; + } + $out .= qq{</tr>}; + } + $out .= '</table>'; + $out .= '<input type="submit" name="action" value="save">' if defined $permissions->{update_role}; + $out .= '</form>'; + $out .= '</div>'; + print $out. "\n"; } # sort columns by group and action sub sort_columns { - my $columns = shift; + my $columns = shift; - my $column_level = {}; - my $groups = sort_groups($columns); - for my $column ( keys %$columns ) { - my @words = split /_/, $column; - my $action = shift @words; - my $group = join( ' ', @words ); + my $column_level = {}; + my $groups = sort_groups($columns); + for my $column ( keys %$columns ) { + my @words = split /_/, $column; + my $action = shift @words; + my $group = join( ' ', @words ); - #print "action:'$action' group:'$group' <br>\n"; + my $index = $groups->{$group} || 0; + $index += $actions->{$action} if defined $actions->{$action}; + $column_level->{$column} = $index; + } - my $index = $groups->{$group} || 0; - $index += $actions->{$action} if ( defined $actions->{$action} ); - $column_level->{$column} = $index; - - # print $index."<br>"; - } - - my @columns = sort { $column_level->{$a} <=> $column_level->{$b} } ( keys %$column_level ); - return \@columns; + my @columns = sort { $column_level->{$a} <=> $column_level->{$b} } ( keys %$column_level ); + return \@columns; } # sort columns by group sub sort_groups { - my $columns = shift; - my $groups = {}; + my $columns = shift; + my $groups = {}; - #extract groups - for my $column ( keys %$columns ) { - my @words = split /_/, $column; - my $action = shift @words; - my $group = join( ' ', @words ); - $groups->{$group} = 1; - } + #extract groups + for my $column ( keys %$columns ) { + my @words = split /_/, $column; + my $action = shift @words; + my $group = join( ' ', @words ); + $groups->{$group} = 1; + } - #weigth groups - my $i = 0; - for my $group ( sort keys %$groups ) { - $groups->{$group} = $i; - $i += 100; - } + #weigth groups + my $i = 0; + for my $group ( sort keys %$groups ) { + $groups->{$group} = $i; + $i += 100; + } - #print "<pre>"; - #for my $group (sort {$groups->{$a} <=> $groups->{$b}} (keys %$groups)){ - # print "$groups->{$group}\t$group\n"; - #} - #print "</pre>"; + #print "<pre>"; + #for my $group (sort {$groups->{$a} <=> $groups->{$b}} (keys %$groups)){ + # print "$groups->{$group}\t$group\n"; + #} + #print "</pre>"; - return $groups; + return $groups; } sub check_params { - my $params = shift; + my $config = shift; + my $params = shift; - my $checked = {}; + my $checked = {}; - #template - my $template = ''; - $template = template::check( $params->{template}, 'roles.html' ); - $checked->{template} = $template; + #template + my $template = ''; + $template = template::check( $config, $params->{template}, 'roles.html' ); + $checked->{template} = $template; - #actions - if ( defined $params->{action} ) { - if ( $params->{action} eq 'save' ) { - $checked->{action} = $params->{action}; - } - } + $checked->{action} = entry::element_of( $params->{action}, ['save']); - #numeric values - for my $param ( 'project_id', 'studio_id', 'default_studio_id' ) { - if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /^\d+$/ ) ) { - $checked->{$param} = $params->{$param}; - } - } - if ( defined $checked->{studio_id} ) { - $checked->{default_studio_id} = $checked->{studio_id}; - } else { - $checked->{studio_id} = -1; - } + entry::set_numbers( $checked, $params, [ + 'project_id', 'studio_id', 'default_studio_id' + ]); - #permission fields - for my $key ( keys %$params ) { - $checked->{$key} = $params->{$key} if ( $key =~ /^[a-z_]+_\d*$/ ); - } + if ( defined $checked->{studio_id} ) { + $checked->{default_studio_id} = $checked->{studio_id}; + } else { + $checked->{studio_id} = -1; + } - return $checked; + #permission fields + for my $key ( keys %$params ) { + $checked->{$key} = $params->{$key} if ( $key =~ /^[a-z_]+_\d*$/ ); + } + + return $checked; } diff --git a/website/agenda/planung/select-event.cgi b/website/agenda/planung/select-event.cgi new file mode 100755 index 0000000..2ef481d --- /dev/null +++ b/website/agenda/planung/select-event.cgi @@ -0,0 +1,207 @@ +#!/usr/bin/perl + +use strict; +use warnings; +no warnings 'redefine'; + +use Data::Dumper; + +use params(); +use config(); +use entry(); +use log(); +use template(); +use auth(); +use uac(); + +use series(); +use localization(); +use user_selected_events(); + +binmode STDOUT, ":utf8"; + +my $r = shift; +( my $cgi, my $params, my $error ) = params::get($r); + +my $config = config::get('../config/config.cgi'); +my ( $user, $expires ) = auth::get_user( $config, $params, $cgi ); +return if !defined $user or $user eq ''; + +my $user_presets = uac::get_user_presets( + $config, + { + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + user => $user + } +); +$params->{default_studio_id} = $user_presets->{studio_id}; +$params = uac::setDefaultStudio( $params, $user_presets ); +$params = uac::setDefaultProject( $params, $user_presets ); + +#process header +print "Content-type:text/html; charset=UTF-8;\n\n"; + +my $request = { + url => $ENV{QUERY_STRING} || '', + params => { + original => $params, + checked => check_params( $config, $params ), + }, +}; +$request = uac::prepare_request( $request, $user_presets ); + +$params = $request->{params}->{checked}; +$params = uac::set_template_permissions( $request->{permissions}, $params ); +$params->{loc} = localization::get( $config, { user => $user, file => 'select-event' } ); + +return unless uac::check( $config, $params, $user_presets ) == 1; +show_events( $config, $request ); + +#TODO: filter by published, draft +sub show_events { + my $config = shift; + my $request = shift; + + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + unless ( $permissions->{read_event} == 1 ) { + uac::permissions_denied('read_event'); + return; + } + + my $entry = { + user => $request->{user}, + project_id => $params->{p_id}, + studio_id => $params->{s_id}, + series_id => $params->{series_id}, + filter_project_studio => $params->{selectProjectStudio}, + filter_series => $params->{selectSeries}, + }; + my $preset = user_selected_events::get($config, $entry); + + # get user projects + my $user_projects = uac::get_projects_by_user( $config, { user => $request->{user} } ); + my $project_by_id = {}; + for my $project (@$user_projects) { + $project_by_id->{ $project->{project_id} } = $project; + } + + # get user studios + my $user_studios = uac::get_studios_by_user( $config, { user => $request->{user} } ); + for my $studio (@$user_studios) { + my $project_id = $studio->{project_id}; + my $studio_id = $studio->{id}; + $studio->{project_name} = $project_by_id->{$project_id}->{name}; + if ($preset) { + $studio->{selected} = 1 if $project_id eq $preset->{selected_project} and $studio_id eq $preset->{selected_studio}; + } else { + $studio->{selected} = 1 if $project_id eq $params->{p_id} and $studio_id eq $params->{s_id}; + } + } + + # get series + my $options = {}; + if ($preset){ + $options->{project_id} = $preset->{selected_project}; + $options->{studio_id} = $preset->{selected_studio}; + }else{ + $options->{project_id} = $params->{p_id} if defined $params->{p_id}; + $options->{studio_id} = $params->{s_id} if defined $params->{s_id}; + } + my $series = series::get( $config, $options ); + + for my $serie (@$series) { + if ( defined $params->{series_id} ){ + if ($preset){ + $serie->{selected} = 1 if $serie->{series_id} eq $preset->{selected_series}; + } else { + $serie->{selected} = 1 if $serie->{series_id} eq $params->{series_id}; + } + } + $serie->{series_name} = 'Einzelsendung' if $serie->{series_name} eq '_single_'; + } + + # get events + if ($preset){ + $options->{series_id} = $preset->{selected_series}; + }else{ + $options->{series_id} = $params->{series_id} if defined $params->{series_id}; + } + $options->{from_date} = $params->{from_date} if defined $params->{from_date}; + $options->{till_date} = $params->{till_date} if defined $params->{till_date}; + $options->{set_no_listen_keys} = 1; + my $events = series::get_events( $config, $options ); + + my $preset_year = ''; + for my $event ( @$events ) { + if ($preset and $preset->{selected_event} eq $event->{id}){ + $event->{selected} = 1; + $preset_year = (split /\-/, $event->{start_date})[0]; + } + } + + # filter by year + my $years = []; + for my $year ( 2005 .. 2025 ) { + my $date = { year => $year }; + if ( $preset ){ + $date->{selected} = 1 if $preset_year eq $year; + }else{ + $date->{selected} = 1 if ( defined $params->{from_date} ) && ( $params->{from_date} eq $year . '-01-01' ); + } + push @$years, $date; + } + + $params->{studios} = $user_studios; + $params->{series} = $series; + $params->{events} = $events; + $params->{years} = $years; + template::process( $config, 'print', $params->{template}, $params ); + return; +} + +sub check_params { + my $config = shift; + my $params = shift; + + my $checked = {}; + + entry::set_numbers( $checked, $params, [ + 'id', 'project_id', 'studio_id', 'series_id', 'event_id', 'p_id', 's_id' + ]); + + entry::set_bools( $checked, $params, + [ 'selectProjectStudio', 'selectSeries', 'selectRange' ] + ); + + for my $param ('resultElemId') { + if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /^[a-zA-ZöäüÖÄÜß_\d]+$/ ) ) { + $checked->{$param} = $params->{$param}; + } + } + + for my $param ( 'from_date', 'till_date' ) { + if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /(\d\d\d\d\-\d\d\-\d\d)/ ) ) { + $checked->{$param} = $1; + } + } + + if ( ( defined $params->{year} ) && ( $params->{year} =~ /^\d\d\d\d$/ ) ) { + $checked->{year} = $params->{year}; + } + + # set defaults for project and studio id if not given + $checked->{s_id} = $params->{studio_id} || '-1' unless defined $params->{s_id}; + $checked->{p_id} = $params->{project_id} || '-1' unless defined $params->{p_id}; + + if ( defined $checked->{studio_id} ) { + $checked->{default_studio_id} = $checked->{studio_id}; + } else { + $checked->{studio_id} = -1; + } + + $checked->{template} = template::check( $config, $params->{template}, 'select-event' ); + + return $checked; +} diff --git a/website/agenda/planung/select-series.cgi b/website/agenda/planung/select-series.cgi new file mode 100755 index 0000000..65f1ce1 --- /dev/null +++ b/website/agenda/planung/select-series.cgi @@ -0,0 +1,145 @@ +#!/usr/bin/perl + +use strict; +use warnings; +no warnings 'redefine'; + +use Data::Dumper; + +use params(); +use config(); +use entry(); +use log(); +use template(); +use auth(); +use uac(); +use series(); +use localization(); + +binmode STDOUT, ":utf8"; + +my $r = shift; +( my $cgi, my $params, my $error ) = params::get($r); + +my $config = config::get('../config/config.cgi'); +my $debug = $config->{system}->{debug}; +my ( $user, $expires ) = auth::get_user( $config, $params, $cgi ); +return if ( ( !defined $user ) || ( $user eq '' ) ); + +my $user_presets = uac::get_user_presets( + $config, + { + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + user => $user + } +); +$params->{default_studio_id} = $user_presets->{studio_id}; +$params = uac::setDefaultStudio( $params, $user_presets ); +$params = uac::setDefaultProject( $params, $user_presets ); + +my $request = { + url => $ENV{QUERY_STRING} || '', + params => { + original => $params, + checked => check_params( $config, $params ), + }, +}; +$request = uac::prepare_request( $request, $user_presets ); + +$params = $request->{params}->{checked}; +$params = uac::set_template_permissions( $request->{permissions}, $params ); +$params->{loc} = localization::get( $config, { user => $user, file => 'select-series' } ); + +#process header +print "Content-type:text/html; charset=UTF-8;\n\n"; + +return unless uac::check( $config, $params, $user_presets ) == 1; + +my $permissions = $request->{permissions}; +unless ( $permissions->{read_series} == 1 ) { + uac::permissions_denied('read_series'); + return; +} + +show_series( $config, $request ); + +sub show_series { + my $config = shift; + my $request = shift; + + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + unless ( $permissions->{read_series} == 1 ) { + uac::permissions_denied('read_series'); + return; + } + + # get user projects + my $user_projects = uac::get_projects_by_user( $config, { user => $request->{user} } ); + my $projects = {}; + for my $project (@$user_projects) { + $projects->{ $project->{project_id} } = $project; + } + + # get user studios + my $user_studios = uac::get_studios_by_user( $config, { user => $request->{user} } ); + for my $studio (@$user_studios) { + my $project_id = $studio->{project_id}; + my $studio_id = $studio->{id}; + $studio->{project_name} = $projects->{$project_id}->{name}; + $studio->{selected} = 1 if ( $project_id eq $params->{p_id} ) && ( $studio_id eq $params->{s_id} ); + } + + # get series + my $options = {}; + $options->{project_id} = $params->{p_id} if defined $params->{p_id}; + $options->{studio_id} = $params->{s_id} if defined $params->{s_id}; + my $series = series::get( $config, $options ); + + for my $serie (@$series) { + $serie->{selected} = 1 if ( defined $params->{series_id} ) && ( $serie->{series_id} eq $params->{series_id} ); + $serie->{series_name} = 'Einzelsendung' if $serie->{series_name} eq '_single_'; + } + + $params->{studios} = $user_studios; + $params->{series} = $series; + + template::process( $config, 'print', $params->{template}, $params ); + return; +} + +sub check_params { + my $config = shift; + my $params = shift; + + my $checked = {}; + + entry::set_numbers( $checked, $params, [ + 'id', 'project_id', 'studio_id', 'series_id', 'p_id', 's_id' + ]); + + entry::set_bools( $checked, $params, [ + 'selectProjectStudio', 'selectSeries', 'selectRange' ]); + + for my $param ('resultElemId') { + if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /^[a-zA-ZöäüÖÄÜß_\d]+$/ ) ) { + $checked->{$param} = $params->{$param}; + } + } + + # set defaults for project and studio id if not given + $checked->{s_id} = $params->{studio_id} || '-1' unless defined $params->{s_id}; + $checked->{p_id} = $params->{project_id} || '-1' unless defined $params->{p_id}; + + if ( defined $checked->{studio_id} ) { + $checked->{default_studio_id} = $checked->{studio_id}; + } else { + $checked->{studio_id} = -1; + } + + $checked->{template} = template::check( $config, $params->{template}, 'select-series' ); + + return $checked; +} + diff --git a/website/agenda/planung/selectEvent.cgi b/website/agenda/planung/selectEvent.cgi deleted file mode 100755 index e862750..0000000 --- a/website/agenda/planung/selectEvent.cgi +++ /dev/null @@ -1,190 +0,0 @@ -#! /usr/bin/perl -w - -use warnings "all"; -use strict; -use Data::Dumper; - -use params; -use config; -use log; -use template; -use auth; -use uac; - -#use roles; -#use project; -#use studios; -#use events; -use series; - -#use series_schedule; -#use series_events; -#use series_dates; -#use markup; -#use URI::Escape; -#use Encode; -use localization; - -binmode STDOUT, ":utf8"; - -my $r = shift; -( my $cgi, my $params, my $error ) = params::get($r); - -my $config = config::get('../config/config.cgi'); -my $debug = $config->{system}->{debug}; -my ( $user, $expires ) = auth::get_user( $cgi, $config ); -return if ( ( !defined $user ) || ( $user eq '' ) ); - -my $user_presets = uac::get_user_presets( - $config, - { - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - user => $user - } -); -$params->{default_studio_id} = $user_presets->{studio_id}; -$params->{studio_id} = $params->{default_studio_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); -$params->{project_id} = $user_presets->{project_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); - -my $request = { - url => $ENV{QUERY_STRING} || '', - params => { - original => $params, - checked => check_params($params), - }, -}; -$request = uac::prepare_request( $request, $user_presets ); -log::init($request); - -$params = $request->{params}->{checked}; -$params = uac::set_template_permissions( $request->{permissions}, $params ); -$params->{loc} = localization::get( $config, { user => $user, file => 'selectEvent' } ); - -#process header -print "Content-type:text/html; charset=UTF-8;\n\n"; - -return unless uac::check( $config, $params, $user_presets ) == 1; -show_events( $config, $request ); - -#TODO: filter by published, draft -sub show_events { - my $config = shift; - my $request = shift; - - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - unless ( $permissions->{read_event} == 1 ) { - uac::permissions_denied('read_event'); - return; - } - - # get user projects - my $user_projects = uac::get_projects_by_user( $config, { user => $request->{user} } ); - my $projects = {}; - for my $project (@$user_projects) { - $projects->{ $project->{project_id} } = $project; - } - - # get user studios - my $user_studios = uac::get_studios_by_user( $config, { user => $request->{user} } ); - for my $studio (@$user_studios) { - my $project_id = $studio->{project_id}; - my $studio_id = $studio->{id}; - $studio->{project_name} = $projects->{$project_id}->{name}; - $studio->{selected} = 1 if ( $project_id eq $params->{p_id} ) && ( $studio_id eq $params->{s_id} ); - } - - # get series - my $options = {}; - $options->{project_id} = $params->{p_id} if defined $params->{p_id}; - $options->{studio_id} = $params->{s_id} if defined $params->{s_id}; - my $series = series::get( $config, $options ); - - for my $serie (@$series) { - $serie->{selected} = 1 if ( defined $params->{series_id} ) && ( $serie->{series_id} eq $params->{series_id} ); - $serie->{series_name} = 'Einzelsendung' if $serie->{series_name} eq '_single_'; - } - - # get events - $options->{series_id} = $params->{series_id} if defined $params->{series_id}; - $options->{from_date} = $params->{from_date} if defined $params->{from_date}; - $options->{till_date} = $params->{till_date} if defined $params->{till_date}; - my $events = series::get_events( $config, $options ); - - # filter by year - my $years = []; - for my $year ( 2005 .. 2025 ) { - my $date = { year => $year }; - $date->{selected} = 1 if ( defined $params->{from_date} ) && ( $params->{from_date} eq $year . '-01-01' ); - push @$years, $date; - } - - #print Dumper($params->{loc}); - $params->{studios} = $user_studios; - $params->{series} = $series; - $params->{events} = $events; - $params->{years} = $years; - - #print STDERR Dumper($params); - template::process( 'print', $params->{template}, $params ); - return; -} - -sub check_params { - my $params = shift; - - my $checked = {}; - - my $debug = $params->{debug} || ''; - if ( $debug =~ /([a-z\_\,]+)/ ) { - $debug = $1; - } - $checked->{debug} = $debug; - - #numeric values - for my $param ( 'id', 'project_id', 'studio_id', 'series_id', 'event_id', 'p_id', 's_id' ) { - if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /^[\-\d]+$/ ) ) { - $checked->{$param} = $params->{$param}; - } - } - - for my $param ( 'selectProjectStudio', 'selectSeries', 'selectRange' ) { - if ( ( defined $params->{$param} ) && ( $params->{$param} eq '1' ) ) { - $checked->{$param} = $params->{$param}; - } - } - - for my $param ('resultElemId') { - if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /^[a-zA-ZöäüÖÄÜß_\d]+$/ ) ) { - $checked->{$param} = $params->{$param}; - } - } - - for my $param ( 'from_date', 'till_date' ) { - if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /(\d\d\d\d\-\d\d\-\d\d)/ ) ) { - $checked->{$param} = $1; - } - } - - if ( ( defined $params->{year} ) && ( $params->{year} =~ /^\d\d\d\d$/ ) ) { - $checked->{year} = $params->{year}; - } - - # set defaults for project and studio id if not given - $checked->{s_id} = $params->{studio_id} || '-1' unless defined $params->{s_id}; - $checked->{p_id} = $params->{project_id} || '-1' unless defined $params->{p_id}; - - if ( defined $checked->{studio_id} ) { - $checked->{default_studio_id} = $checked->{studio_id}; - } else { - $checked->{studio_id} = -1; - } - - $checked->{template} = template::check( $params->{template}, 'selectEvent' ); - - return $checked; -} - diff --git a/website/agenda/planung/selectSeries.cgi b/website/agenda/planung/selectSeries.cgi deleted file mode 100755 index a027fac..0000000 --- a/website/agenda/planung/selectSeries.cgi +++ /dev/null @@ -1,156 +0,0 @@ -#! /usr/bin/perl -w - -use warnings "all"; -use strict; -use Data::Dumper; - -use params; -use config; -use log; -use template; -use auth; -use uac; -use series; -use localization; - -binmode STDOUT, ":utf8"; - -my $r = shift; -( my $cgi, my $params, my $error ) = params::get($r); - -my $config = config::get('../config/config.cgi'); -my $debug = $config->{system}->{debug}; -my ( $user, $expires ) = auth::get_user( $cgi, $config ); -return if ( ( !defined $user ) || ( $user eq '' ) ); - -my $user_presets = uac::get_user_presets( - $config, - { - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - user => $user - } -); -$params->{default_studio_id} = $user_presets->{studio_id}; -$params->{studio_id} = $params->{default_studio_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); -$params->{project_id} = $user_presets->{project_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); - -my $request = { - url => $ENV{QUERY_STRING} || '', - params => { - original => $params, - checked => check_params($params), - }, -}; -$request = uac::prepare_request( $request, $user_presets ); -log::init($request); - -$params = $request->{params}->{checked}; -$params = uac::set_template_permissions( $request->{permissions}, $params ); -$params->{loc} = localization::get( $config, { user => $user, file => 'selectSeries' } ); - -#process header -print "Content-type:text/html; charset=UTF-8;\n\n"; - -return unless uac::check( $config, $params, $user_presets ) == 1; - -my $permissions = $request->{permissions}; -unless ( $permissions->{read_series} == 1 ) { - uac::permissions_denied('read_series'); - return; -} - -show_series( $config, $request ); - -sub show_series { - my $config = shift; - my $request = shift; - - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - unless ( $permissions->{read_series} == 1 ) { - uac::permissions_denied('read_series'); - return; - } - - # get user projects - my $user_projects = uac::get_projects_by_user( $config, { user => $request->{user} } ); - my $projects = {}; - for my $project (@$user_projects) { - $projects->{ $project->{project_id} } = $project; - } - - # get user studios - my $user_studios = uac::get_studios_by_user( $config, { user => $request->{user} } ); - for my $studio (@$user_studios) { - my $project_id = $studio->{project_id}; - my $studio_id = $studio->{id}; - $studio->{project_name} = $projects->{$project_id}->{name}; - $studio->{selected} = 1 if ( $project_id eq $params->{p_id} ) && ( $studio_id eq $params->{s_id} ); - } - - # get series - my $options = {}; - $options->{project_id} = $params->{p_id} if defined $params->{p_id}; - $options->{studio_id} = $params->{s_id} if defined $params->{s_id}; - my $series = series::get( $config, $options ); - - for my $serie (@$series) { - $serie->{selected} = 1 if ( defined $params->{series_id} ) && ( $serie->{series_id} eq $params->{series_id} ); - $serie->{series_name} = 'Einzelsendung' if $serie->{series_name} eq '_single_'; - } - - $params->{studios} = $user_studios; - $params->{series} = $series; - - template::process( 'print', $params->{template}, $params ); - return; -} - -sub check_params { - my $params = shift; - - my $checked = {}; - - my $debug = $params->{debug} || ''; - if ( $debug =~ /([a-z\_\,]+)/ ) { - $debug = $1; - } - $checked->{debug} = $debug; - - #numeric values - for my $param ( 'id', 'project_id', 'studio_id', 'series_id', 'p_id', 's_id' ) { - if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /^[\-\d]+$/ ) ) { - $checked->{$param} = $params->{$param}; - } - } - - for my $param ( 'selectProjectStudio', 'selectSeries', 'selectRange' ) { - if ( ( defined $params->{$param} ) && ( $params->{$param} eq '1' ) ) { - $checked->{$param} = $params->{$param}; - } - } - - for my $param ('resultElemId') { - if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /^[a-zA-ZöäüÖÄÜß_\d]+$/ ) ) { - $checked->{$param} = $params->{$param}; - } - } - - # set defaults for project and studio id if not given - $checked->{s_id} = $params->{studio_id} || '-1' unless defined $params->{s_id}; - $checked->{p_id} = $params->{project_id} || '-1' unless defined $params->{p_id}; - - if ( defined $checked->{studio_id} ) { - $checked->{default_studio_id} = $checked->{studio_id}; - } else { - $checked->{studio_id} = -1; - } - - $checked->{template} = template::check( $params->{template}, 'selectSeries' ); - - return $checked; -} - diff --git a/website/agenda/planung/series.cgi b/website/agenda/planung/series.cgi index a6a8734..8d07c75 100755 --- a/website/agenda/planung/series.cgi +++ b/website/agenda/planung/series.cgi @@ -1,28 +1,32 @@ -#! /usr/bin/perl -w +#!/usr/bin/perl -use warnings "all"; use strict; -use Data::Dumper; +use warnings; +no warnings 'redefine'; -use params; -use config; -use log; -use template; -use auth; -use uac; -use roles; -use project; -use studios; -use events; -use series; -use series_schedule; -use series_events; -use series_dates; -use user_stats; -use markup; -use URI::Escape; -use Encode; -use localization; +use Data::Dumper; +use URI::Escape(); +use Encode(); + +use utf8(); +use params(); +use config(); +use entry(); +use log(); +use template(); +use auth(); +use uac(); +use roles(); +use project(); +use studios(); +use events(); +use series(); +use series_dates(); +use markup(); +use localization(); +use series_schedule(); +use series_events(); +use user_stats(); binmode STDOUT, ":utf8"; @@ -31,491 +35,496 @@ my $r = shift; my $config = config::get('../config/config.cgi'); my $debug = $config->{system}->{debug}; -my ( $user, $expires ) = auth::get_user( $cgi, $config ); -return if ( ( !defined $user ) || ( $user eq '' ) ); +my ( $user, $expires ) = auth::get_user( $config, $params, $cgi ); +return if ( !defined $user ) || ( $user eq '' ); -#print STDERR $params->{project_id}."\n"; my $user_presets = uac::get_user_presets( - $config, - { - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - user => $user - } + $config, + { + user => $user, + project_id => $params->{project_id}, + studio_id => $params->{studio_id} + } ); $params->{default_studio_id} = $user_presets->{studio_id}; -$params->{studio_id} = $params->{default_studio_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); -$params->{project_id} = $user_presets->{project_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); +$params = uac::setDefaultStudio( $params, $user_presets ); +$params = uac::setDefaultProject( $params, $user_presets ); #print STDERR $params->{project_id}."\n"; my $request = { - url => $ENV{QUERY_STRING} || '', - params => { - original => $params, - checked => check_params($params), - }, + url => $ENV{QUERY_STRING} || '', + params => { + original => $params, + checked => check_params( $config, $params ), + }, }; $request = uac::prepare_request( $request, $user_presets ); -log::init($request); - $params = $request->{params}->{checked}; #process header unless ( params::isJson() ) { - my $headerParams = uac::set_template_permissions( $request->{permissions}, $params ); - $headerParams->{loc} = localization::get( $config, { user => $user, file => 'menu' } ); - template::process( 'print', template::check('default.html'), $headerParams ); + my $headerParams = uac::set_template_permissions( $request->{permissions}, $params ); + $headerParams->{loc} = localization::get( $config, { user => $user, file => 'menu' } ); + template::process( $config, 'print', template::check( $config, 'series-header.html' ), + $headerParams ); } return unless uac::check( $config, $params, $user_presets ) == 1; -print q{ - <script src="js/datetime.js" type="text/javascript"></script> - <script src="js/event.js" type="text/javascript"></script> - <link rel="stylesheet" href="css/series.css" type="text/css" /> -} unless params::isJson(); - -# <script src="js/localization.js" type="text/javascript"></script> - if ( defined $params->{action} ) { - save_schedule( $config, $request ) if ( $params->{action} eq 'save_schedule' ); - delete_schedule( $config, $request ) if ( $params->{action} eq 'delete_schedule' ); - add_user( $config, $request ) if ( $params->{action} eq 'add_user' ); - remove_user( $config, $request ) if ( $params->{action} eq 'remove_user' ); - save_series( $config, $request ) if ( $params->{action} eq 'save' ); - save_series( $config, $request ) if ( $params->{action} eq 'create' ); - delete_series( $config, $request ) if ( $params->{action} eq 'delete' ); + save_schedule( $config, $request ) if ( $params->{action} eq 'save_schedule' ); + delete_schedule( $config, $request ) if ( $params->{action} eq 'delete_schedule' ); + add_user( $config, $request ) if ( $params->{action} eq 'add_user' ); + remove_user( $config, $request ) if ( $params->{action} eq 'remove_user' ); + save_series( $config, $request ) if ( $params->{action} eq 'save' ); + save_series( $config, $request ) if ( $params->{action} eq 'create' ); + delete_series( $config, $request ) if ( $params->{action} eq 'delete' ); - # scan_events ($config, $request) if ($params->{action} eq 'scan_events'); - assign_event( $config, $request ) if ( $params->{action} eq 'assign_event' ); - unassign_event( $config, $request ) if ( $params->{action} eq 'unassign_event' ); - if ( $params->{action} eq 'reassign_event' ) { - my $result = reassign_event( $config, $request ); - return if $result == 1; - } - - # save_scan ($config, $request) if ($params->{action} eq 'save_scan'); + # scan_events ($config, $request) if ($params->{action} eq 'scan_events'); + assign_event( $config, $request ) if ( $params->{action} eq 'assign_event' ); + unassign_event( $config, $request ) if ( $params->{action} eq 'unassign_event' ); + if ( $params->{action} eq 'reassign_event' ) { + my $result = reassign_event( $config, $request ); + return if defined $result; + } + if ( $params->{action} eq 'rebuild_episodes' ) { + rebuild_episodes( $config, $request ); + return; + } + if ( $params->{action} eq 'set_rebuilt_episodes' ) { + set_rebuilt_episodes( $config, $request ); + return; + } } $config->{access}->{write} = 0; -#print STDERR "show_series\n"; - if ( defined $params->{series_id} ) { - print q{<script src="js/edit_series.js" type="text/javascript"></script>} unless params::isJson(); - show_series( $config, $request ); + template::process( $config, 'print', template::check( $config, 'show-series-header.html' ),{}) + unless params::isJson(); + show_series( $config, $request ); } else { - print q{ - <link rel="stylesheet" href="css/list_series.css" type="text/css" /> - <script src="js/list_series.js" type="text/javascript"></script> - } unless params::isJson(); - list_series( $config, $request ); + template::process( $config, 'print', template::check( $config, 'list-series-header.html' ),{}) + unless params::isJson(); + list_series( $config, $request ); } + return; #insert or update a schedule and update all schedule dates sub save_schedule { - my $config = shift; - my $request = shift; + my $config = shift; + my $request = shift; - my $params = $request->{params}->{checked}; + my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - unless ( $permissions->{update_schedule} == 1 ) { - uac::permissions_denied('update_schedule'); - return; - } + my $permissions = $request->{permissions}; + unless ( $permissions->{update_schedule} == 1 ) { + uac::permissions_denied('update_schedule'); + return; + } - #print Dumper($params); - for my $attr ( 'project_id', 'studio_id', 'series_id', 'start' ) { - unless ( defined $params->{$attr} ) { - uac::print_error( $attr . ' not given!' ); - return; - } - } + for my $attr ( 'project_id', 'studio_id', 'series_id', 'start' ) { + unless ( defined $params->{$attr} ) { + uac::print_error( $attr . ' not given!' ); + return; + } + } - my $entry = {}; - for my $attr ( - 'project_id', 'studio_id', 'series_id', 'start', 'duration', 'exclude', 'period_type', 'end', - 'frequency', 'weekday', 'week_of_month', 'month', 'nextDay' - ) - { - $entry->{$attr} = $params->{$attr} if ( defined $params->{$attr} ); - } + my $entry = {}; + for my $attr ( + 'project_id', 'studio_id', 'series_id', 'start', 'duration', 'exclude', + 'period_type', 'end', 'frequency', 'weekday', 'week_of_month', 'month', + 'nextDay' + ) + { + $entry->{$attr} = $params->{$attr} if defined $params->{$attr}; + } - #print STDERR Dumper($entry); - unless ( project::is_series_assigned( $config, $entry ) == 1 ) { - uac::print_error('series is not assigned to project!'); - return undef; - } + unless ( project::is_series_assigned( $config, $entry ) == 1 ) { + uac::print_error('series is not assigned to project!'); + return undef; + } - my $found = 0; - for my $type ( 'single', 'days', 'week_of_month' ) { - $found = 1 if ( $entry->{period_type} eq $type ); - } - if ( $found == 0 ) { - uac::print_error('no period type selected!'); - return; - } + my $found = 0; + for my $type ( 'single', 'days', 'week_of_month' ) { + $found = 1 if ( $entry->{period_type} eq $type ); + } + if ( $found == 0 ) { + uac::print_error('no period type selected!'); + return; + } - $entry->{nextDay} = 0 unless defined $entry->{nextDay}; - $entry->{exclude} = 0 if $entry->{exclude} ne '1'; - $entry->{nextDay} = 0 if $entry->{nextDay} ne '1'; + $entry->{nextDay} = 0 unless defined $entry->{nextDay}; + $entry->{exclude} = 0 if $entry->{exclude} ne '1'; + $entry->{nextDay} = 0 if $entry->{nextDay} ne '1'; - if ( ( $entry->{end} ne '' ) && ( $entry->{end} le $entry->{start} ) ) { - uac::print_error('start date should be before end date!'); - return; - } + if ( ( $entry->{end} ne '' ) && ( $entry->{end} le $entry->{start} ) ) { + uac::print_error('start date should be before end date!'); + return; + } - #TODO: check if schedule is in studio_timeslots + #TODO: check if schedule is in studio_timeslots - #on adding a single exclude schedule, remove any existing single schedules with same date - if ( ( $entry->{period_type} eq 'single' ) && ( $entry->{exclude} eq '1' ) ) { - unless ( $permissions->{delete_schedule} == 1 ) { - uac::permissions_denied('delete_schedule'); - return; - } + #on adding a single exclude schedule, remove any existing single schedules with same date + if ( ( $entry->{period_type} eq 'single' ) && ( $entry->{exclude} eq '1' ) ) { + unless ( $permissions->{delete_schedule} == 1 ) { + uac::permissions_denied('delete_schedule'); + return; + } - #get single schedules - my $schedules = series_schedule::get( - $config, - { - project_id => $entry->{project_id}, - studio_id => $entry->{studio_id}, - series_id => $entry->{series_id}, - start => $entry->{start}, - period_type => 'single', - exclude => 0 - } - ); - if ( scalar(@$schedules) > 0 ) { - $config->{access}->{write} = 1; - for my $schedule (@$schedules) { - series_schedule::delete( $config, $schedule ); - } - my $updates = series_dates::update( $config, $entry ); - uac::print_info("single schedule deleted. $updates dates scheduled"); - $config->{access}->{write} = 0; - return; - } - } + #get single schedules + my $schedules = series_schedule::get( + $config, + { + project_id => $entry->{project_id}, + studio_id => $entry->{studio_id}, + series_id => $entry->{series_id}, + start => $entry->{start}, + period_type => 'single', + exclude => 0 + } + ); + if ( scalar(@$schedules) > 0 ) { + $config->{access}->{write} = 1; + for my $schedule (@$schedules) { + series_schedule::delete( $config, $schedule ); + } + my $updates = series_dates::update( $config, $entry ); + uac::print_info("single schedule deleted. $updates dates scheduled"); + $config->{access}->{write} = 0; + return; + } + } - $config->{access}->{write} = 1; - if ( defined $params->{schedule_id} ) { - $entry->{schedule_id} = $params->{schedule_id}; - series_schedule::update( $config, $entry ); + $config->{access}->{write} = 1; + if ( defined $params->{schedule_id} ) { + $entry->{schedule_id} = $params->{schedule_id}; + series_schedule::update( $config, $entry ); - #timeslots are checked inside - my $updates = series_dates::update( $config, $entry ); - uac::print_info("schedule saved. $updates dates scheduled"); - } else { - series_schedule::insert( $config, $entry ); + #timeslots are checked inside + my $updates = series_dates::update( $config, $entry ); + uac::print_info("schedule saved. $updates dates scheduled"); + } else { + series_schedule::insert( $config, $entry ); - #timeslots are checked inside - my $updates = series_dates::update( $config, $entry ); - uac::print_info("schedule added. $updates dates added"); - } - $config->{access}->{write} = 0; + #timeslots are checked inside + my $updates = series_dates::update( $config, $entry ); + uac::print_info("schedule added. $updates dates added"); + } + $config->{access}->{write} = 0; } sub delete_schedule { - my $config = shift; - my $request = shift; + my $config = shift; + my $request = shift; - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - unless ( $permissions->{delete_schedule} == 1 ) { - uac::permissions_denied('delete_schedule'); - return; - } + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + unless ( $permissions->{delete_schedule} == 1 ) { + uac::permissions_denied('delete_schedule'); + return; + } - my $entry = {}; - for my $attr ( 'project_id', 'studio_id', 'series_id', 'schedule_id' ) { - if ( defined $params->{$attr} ) { - $entry->{$attr} = $params->{$attr}; - } else { - uac::print_error( $attr . ' not given!' ); - return; - } - } + my $entry = {}; + for my $attr ( 'project_id', 'studio_id', 'series_id', 'schedule_id' ) { + if ( defined $params->{$attr} ) { + $entry->{$attr} = $params->{$attr}; + } else { + uac::print_error( $attr . ' not given!' ); + return; + } + } - unless ( project::is_series_assigned( $config, $entry ) == 1 ) { - uac::print_error('series is not assigned to project!'); - return undef; - } + unless ( project::is_series_assigned( $config, $entry ) == 1 ) { + uac::print_error('series is not assigned to project!'); + return undef; + } - $config->{access}->{write} = 1; - $entry->{schedule_id} = $params->{schedule_id}; - series_schedule::delete( $config, $entry ); - series_dates::update( $config, $entry ); - uac::print_info("schedule deleted"); + $config->{access}->{write} = 1; + $entry->{schedule_id} = $params->{schedule_id}; + series_schedule::delete( $config, $entry ); + series_dates::update( $config, $entry ); + uac::print_info("schedule deleted"); } #todo: check if assigned to studio sub delete_series { - my $config = shift; - my $request = shift; + my $config = shift; + my $request = shift; - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - unless ( $permissions->{delete_series} == 1 ) { - uac::permissions_denied('delete_series'); - return; - } + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + unless ( $permissions->{delete_series} == 1 ) { + uac::permissions_denied('delete_series'); + return; + } - my $entry = {}; - for my $attr ( 'project_id', 'studio_id', 'series_id' ) { - if ( defined $params->{$attr} ) { - $entry->{$attr} = $params->{$attr}; - } else { - uac::print_error( $attr . ' not given!' ); - return; - } - } + my $entry = {}; + for my $attr ( 'project_id', 'studio_id', 'series_id' ) { + if ( defined $params->{$attr} ) { + $entry->{$attr} = $params->{$attr}; + } else { + uac::print_error( $attr . ' not given!' ); + return; + } + } - unless ( project::is_series_assigned( $config, $entry ) == 1 ) { - uac::print_error('series is not assigned to project!'); - return undef; - } + unless ( project::is_series_assigned( $config, $entry ) == 1 ) { + uac::print_error('series is not assigned to project!'); + return undef; + } - my $project_id = $params->{project_id}; - my $studio_id = $params->{studio_id}; - my $series_id = $entry->{series_id}; + my $project_id = $params->{project_id}; + my $studio_id = $params->{studio_id}; + my $series_id = $entry->{series_id}; - #print Dumper($entry); - $config->{access}->{write} = 1; - if ( $entry->{series_id} ne '' ) { - my $result = series::delete( $config, $entry ); + $config->{access}->{write} = 1; + if ( $entry->{series_id} ne '' ) { + my $result = series::delete( $config, $entry ); - user_stats::increase( - $config, - 'delete_series', - { - project_id => $entry->{project_id}, - studio_id => $entry->{studio_id}, - series_id => $entry->{series_id}, - user => $params->{presets}->{user} - } - ); - $config->{access}->{write} = 0; - unless ( $result == 1 ) { - uac::print_error('could not delete series'); - return; - } - } - $config->{access}->{write} = 0; - uac::print_info("series deleted"); + user_stats::increase( + $config, + 'delete_series', + { + project_id => $entry->{project_id}, + studio_id => $entry->{studio_id}, + series_id => $entry->{series_id}, + user => $params->{presets}->{user} + } + ); + $config->{access}->{write} = 0; + unless ( $result == 1 ) { + uac::print_error('could not delete series'); + return; + } + } + $config->{access}->{write} = 0; + uac::print_info("series deleted"); } sub save_series { - my $config = shift; - my $request = shift; + my $config = shift; + my $request = shift; - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - my $columns = series::get_columns($config); + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + my $columns = series::get_columns($config); - for my $attr ( 'project_id', 'studio_id' ) { - unless ( defined $params->{$attr} ) { - uac::print_error( $attr . ' not given!' ); - return; - } - } - my $project_id = $params->{project_id}; - my $studio_id = $params->{studio_id}; + for my $attr ( 'project_id', 'studio_id' ) { + unless ( defined $params->{$attr} ) { + uac::print_error( $attr . ' not given!' ); + return; + } + } + my $project_id = $params->{project_id}; + my $studio_id = $params->{studio_id}; - # fill series entry - my $entry = {}; - for my $param ( keys %$params ) { - if ( defined $columns->{$param} ) { - $entry->{$param} = $params->{$param} || ''; - } - } - $entry->{project_id} = $params->{project_id}; - $entry->{studio_id} = $params->{studio_id}; - $entry->{series_id} = $params->{series_id} || ''; - $entry->{live} = $params->{live} || 0; - $entry->{count_episodes} = $params->{count_episodes} || 0; + # fill series entry + my $entry = {}; + for my $param ( keys %$params ) { + if ( exists $columns->{$param} ) { + $entry->{$param} = $params->{$param} || ''; + } + } + $entry->{project_id} = $params->{project_id}; + $entry->{studio_id} = $params->{studio_id}; + $entry->{series_id} = $params->{series_id} || ''; + $entry->{live} = $params->{live} // 0; + $entry->{count_episodes} = $params->{count_episodes} // 0; + $entry->{predecessor_id} = $params->{predecessor_id} // 0; + + if ($entry->{predecessor_id} eq $entry->{series_id}){ + uac::print_error( qq{save:Predecessor $entry->{predecessor_id} must be different from series id $entry->{series_id}.} ); + return; + } - #$entry->{html_content} = decode( 'utf-8', $entry->{content} ); - $entry->{html_content} = markup::creole_to_html( $entry->{content} ); - $entry->{html_content} =~ s/([^\>])\n+([^\<])/$1<br\/><br\/>$2/g; + #$entry->{html_content} = Encode::decode( 'utf-8', $entry->{content} ); + if ($entry->{content_format} //'' eq "markdown"){ + $entry->{html_content} = markup::markdown_to_html( $entry->{content} ); + }else{ + $entry->{html_content} = markup::creole_to_html( $entry->{content} ); + $entry->{html_content} =~ s/([^\>])\n+([^\<])/$1<br\/><br\/>$2/g; + } - $entry->{modified_at} = time::time_to_datetime( time() ); - $entry->{modified_by} = $request->{user}; + $entry->{modified_at} = time::time_to_datetime( time() ); + $entry->{modified_by} = $request->{user}; - if ( ( $params->{title} eq '' ) && ( $params->{series_name} eq '' ) ) { - uac::print_error("please set at least series name!"); - return; - } + if ( ( $params->{title} eq '' ) && ( $params->{series_name} eq '' ) ) { + uac::print_error("please set at least series name!"); + return; + } - #print STDERR Dumper($entry); - my $series_ids = series::get( - $config, - { - project_id => $entry->{project_id}, - studio_id => $entry->{studio_id}, - series_name => $entry->{series_name}, - title => $entry->{title} - } - ); + # make sure name is not used anywhere else + my $series_ids = series::get( + $config, + { + project_id => $entry->{project_id}, + studio_id => $entry->{studio_id}, + series_name => $entry->{series_name}, + title => $entry->{title} + } + ); - #print STDERR "done\n"; - #my @series_ids=@$series_ids; + if ( $params->{action} eq 'create' ) { - if ( $params->{action} eq 'create' ) { + unless ( $permissions->{create_series} == 1 ) { + uac::permissions_denied('create_series'); + return; + } + if ( project::is_series_assigned( $config, $entry ) == 1 ) { + uac::print_error('series is already assigned to project!'); + return undef; + } + if ( scalar(@$series_ids) > 0 ) { + uac::permissions_denied('insert, entry already exists'); + return; + } - unless ( $permissions->{create_series} == 1 ) { - uac::permissions_denied('create_series'); - return; - } - if ( project::is_series_assigned( $config, $entry ) == 1 ) { - uac::print_error('series is already assigned to project!'); - return undef; - } - if ( scalar(@$series_ids) > 0 ) { - uac::permissions_denied('insert, entry already exists'); - return; - } + $config->{access}->{write} = 1; + my $series_id = series::insert( $config, $entry ); - $config->{access}->{write} = 1; - my $series_id = series::insert( $config, $entry ); + user_stats::increase( + $config, + 'create_series', + { + project_id => $entry->{project_id}, + studio_id => $entry->{studio_id}, + series_id => $entry->{series_id}, + user => $params->{presets}->{user} + } + ); - user_stats::increase( - $config, - 'create_series', - { - project_id => $entry->{project_id}, - studio_id => $entry->{studio_id}, - series_id => $entry->{series_id}, - user => $params->{presets}->{user} - } - ); + $config->{access}->{write} = 0; - $config->{access}->{write} = 0; + unless ( defined $series_id ) { + uac::print_error('could not insert series'); + return; + } + } + if ( $params->{action} eq 'save' ) { - #print STDERR Dumper($entry); - unless ( defined $series_id ) { - uac::print_error('could not insert series'); - return; - } - } - if ( $params->{action} eq 'save' ) { + unless ( $permissions->{update_series} == 1 ) { + uac::permissions_denied('update_series'); + return; + } + unless ( ( defined $params->{series_id} ) && ( $params->{series_id} ne '' ) ) { + uac::permissions_denied('update. missing parameter series_id'); + return; + } + unless ( project::is_series_assigned( $config, $entry ) == 1 ) { + uac::print_error('series is not assigned to project!'); + return undef; + } + + if ( scalar(@$series_ids) > 1 ) { + uac::permissions_denied(q{update due to series already exists multiple times with name "$entry->{series_name}" and title "$entry->{title}"}); + return; + } + if ( ( scalar(@$series_ids) == 1 ) + && ( $series_ids->[0]->{series_id} ne $params->{series_id} ) ) + { + uac::permissions_denied('update due to series id does not match to existing entry'); + return; + } - unless ( $permissions->{update_series} == 1 ) { - uac::permissions_denied('update_series'); - return; - } - unless ( ( defined $params->{series_id} ) && ( $params->{series_id} ne '' ) ) { - uac::permissions_denied('update. missing parameter series_id'); - return; - } - unless ( project::is_series_assigned( $config, $entry ) == 1 ) { - uac::print_error('series is not assigned to project!'); - return undef; - } - if ( scalar(@$series_ids) > 1 ) { - uac::permissions_denied('update due to entry already exists'); - return; - } - if ( ( scalar(@$series_ids) == 1 ) && ( $series_ids->[0]->{series_id} ne $params->{series_id} ) ) { - uac::permissions_denied('update due to series id does not match to existing entry'); - return; - } + $config->{access}->{write} = 1; + my $result = series::update( $config, $entry ); - #print STDERR Dumper($entry); - $config->{access}->{write} = 1; - my $result = series::update( $config, $entry ); + series_events::update_series_images( + $config, + { + project_id => $entry->{project_id}, + studio_id => $entry->{studio_id}, + series_id => $entry->{series_id}, + series_image => $params->{image} + } + ); - user_stats::increase( - $config, - 'update_series', - { - project_id => $entry->{project_id}, - studio_id => $entry->{studio_id}, - series_id => $entry->{series_id}, - user => $params->{presets}->{user} - } - ); + user_stats::increase( + $config, + 'update_series', + { + project_id => $entry->{project_id}, + studio_id => $entry->{studio_id}, + series_id => $entry->{series_id}, + user => $params->{presets}->{user} + } + ); - $config->{access}->{write} = 0; - unless ( defined $result ) { - uac::print_error('could not update series'); - return; - } + $config->{access}->{write} = 0; + unless ( defined $result ) { + uac::print_error('could not update series'); + return; + } - } - uac::print_info("series saved"); + } + uac::print_info("series saved"); } #save series name and title of events to be assigned to this series #deprecated sub save_scan { - my $config = shift; - my $request = shift; + my $config = shift; + my $request = shift; - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - unless ( $permissions->{scan_series_events} == 1 ) { - uac::permissions_denied('scan_series_events'); - return; - } + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + unless ( $permissions->{scan_series_events} == 1 ) { + uac::permissions_denied('scan_series_events'); + return; + } - unless ( $permissions->{update_series} == 1 ) { - uac::permissions_denied('update_series'); - return; - } - for my $param ( 'project_id', 'studio_id', 'series_id' ) { - unless ( ( defined $params->{$param} ) && ( $params->{$param} ne '' ) ) { - uac::permissions_denied("save. missing parameter $param"); - return; - } - } - unless ( ( $params->{assign_event_series_name} =~ /\S/ ) - || ( $params->{assign_event_title} =~ /\S/ ) ) - { - uac::permissions_denied("save. one of series name or title must be set"); - return; - } - my $entry = { - studio_id => $params->{studio_id}, - series_id => $params->{series_id}, - assign_event_series_name => $params->{assign_event_series_name}, - assign_event_title => $params->{assign_event_title}, - }; + unless ( $permissions->{update_series} == 1 ) { + uac::permissions_denied('update_series'); + return; + } + for my $param ( 'project_id', 'studio_id', 'series_id' ) { + unless ( ( defined $params->{$param} ) && ( $params->{$param} ne '' ) ) { + uac::permissions_denied("save. missing parameter $param"); + return; + } + } + unless ( ( $params->{assign_event_series_name} =~ /\S/ ) + || ( $params->{assign_event_title} =~ /\S/ ) ) + { + uac::permissions_denied("save. one of series name or title must be set"); + return; + } + my $entry = { + studio_id => $params->{studio_id}, + series_id => $params->{series_id}, + assign_event_series_name => $params->{assign_event_series_name}, + assign_event_title => $params->{assign_event_title}, + }; - #print STDERR '<br>'.Dumper($entry)."\n"; - $config->{access}->{write} = 1; - series::update( $config, $entry ); - $config->{access}->{write} = 0; - uac::print_info("changes saved"); + $config->{access}->{write} = 1; + series::update( $config, $entry ); + $config->{access}->{write} = 0; + uac::print_info("changes saved"); } #deprecated sub scan_events { - my $config = shift; - my $request = shift; + my $config = shift; + my $request = shift; - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - unless ( $permissions->{scan_series_events} == 1 ) { - uac::permissions_denied('scan_series_events'); - return; - } + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + unless ( $permissions->{scan_series_events} == 1 ) { + uac::permissions_denied('scan_series_events'); + return; + } - $config->{access}->{write} = 1; - my $series = series::get( - $config, - { - 'project_id' => $params->{project_id}, - 'studio_id' => $params->{studio_id} - } - ); + $config->{access}->{write} = 1; + my $series = series::get( + $config, + { + 'project_id' => $params->{project_id}, + 'studio_id' => $params->{studio_id} + } + ); - #print STDERR Dumper($series); - - $params->{scan_results} = q{ + $params->{scan_results} = q{ <table> <tr> <th>event</th> @@ -524,727 +533,941 @@ sub scan_events { </tr> }; - #list of all studios by id - my $studios = studios::get( - $config, - { - project_id => $params->{project_id}, - studio_id => $params->{studio_id} - } - ); - my $studio_by_id = {}; - for my $studio (@$studios) { - $studio_by_id->{ $studio->{id} } = $studio; - } - my $studio = $studio_by_id->{ $params->{studio_id} }; - my $location = $studio->{location}; + #list of all studios by id + my $studios = studios::get( + $config, + { + project_id => $params->{project_id}, + studio_id => $params->{studio_id} + } + ); + my $studio_by_id = {}; + for my $studio (@$studios) { + $studio_by_id->{ $studio->{id} } = $studio; + } + my $studio = $studio_by_id->{ $params->{studio_id} }; + my $location = $studio->{location}; - for my $serie (@$series) { + for my $serie (@$series) { - #get matching events by series_name and title - my $series_name = $serie->{assign_event_series_name}; - my $title = $serie->{assign_event_title}; - my $events = series::search_events( - $config, $request, - { - series_name => $series_name, - location => $location, - title => $title, - get => 'no_content', - archive => 'all', - limit => 1000, - } - ); - my $event_ids = []; - @$event_ids = map { $_->{event_id} } @$events; + #get matching events by series_name and title + my $series_name = $serie->{assign_event_series_name}; + my $title = $serie->{assign_event_title}; + my $events = series::search_events( + $config, $request, + { + series_name => $series_name, + location => $location, + title => $title, + get => 'no_content', + archive => 'all', + limit => 1000, + } + ); + my $event_ids = []; + @$event_ids = map { $_->{event_id} } @$events; - $params->{scan_results} .= - '<tr>' . '<td>' - . $serie->{series_name} . ' - ' - . $serie->{title} . '</td>' . '<td>' - . $series_name . ' - ' - . $title . '</td>' . '<td>' - . scalar(@$event_ids) . '</td>' . '</tr>' . "\n"; + $params->{scan_results} .= + '<tr>' . '<td>' + . $serie->{series_name} . ' - ' + . $serie->{title} . '</td>' . '<td>' + . $series_name . ' - ' + . $title . '</td>' . '<td>' + . scalar(@$event_ids) . '</td>' . '</tr>' . "\n"; - #if($serie->{series_id}==66){ - #print STDERR $serie->{series_name}.' - '.$serie->{title}.' '.Dumper($event_ids); - series::set_event_ids( $config, $params->{project_id}, $params->{studio_id}, $serie, $event_ids ); - - #} - } - $params->{scan_results} .= "</table><hr>\n"; - $config->{access}->{write} = 0; - uac::print_info("events successfully assigned to all series"); + series::set_event_ids( $config, $params->{project_id}, $params->{studio_id}, $serie, + $event_ids ); + } + $params->{scan_results} .= "</table><hr>\n"; + $config->{access}->{write} = 0; + uac::print_info("events successfully assigned to all series"); } sub assign_event { - my $config = shift; - my $request = shift; + my $config = shift; + my $request = shift; - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - unless ( $permissions->{assign_series_events} == 1 ) { - uac::permissions_denied('assign_series_events'); - return; - } + print STDERR "assign event\n"; - my $entry = {}; - for my $attr ( 'project_id', 'studio_id', 'series_id', 'event_id' ) { - if ( defined $params->{$attr} ) { - $entry->{$attr} = $params->{$attr}; - } else { - uac::print_error( $attr . ' not given!' ); - return; - } - } + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + unless ( $permissions->{assign_series_events} == 1 ) { + uac::permissions_denied('assign_series_events'); + return undef; + } - # check if event exists, - # this has to use events::get, since it cannot check for series_id - # TODO: check location of studio_id - my $request2 = { - params => { - checked => events::check_params( - $config, - { - event_id => $entry->{event_id}, - template => 'no', - limit => 1, - archive => 'all' - } - ) - }, - config => $request->{config}, - permissions => $request->{permissions} - }; - $request2->{params}->{checked}->{published} = 'all'; - my $events = events::get( $config, $request2 ); - my $event = $events->[0]; + my $entry = {}; + for my $attr ( 'project_id', 'studio_id', 'series_id', 'event_id' ) { + if ( defined $params->{$attr} ) { + $entry->{$attr} = $params->{$attr}; + } else { + uac::print_error( $attr . ' not given!' ); + return undef; + } + } - #print STDERR Dumper($event); + # check if event exists, + # this has to use events::get, since it cannot check for series_id + # TODO: check location of studio_id + my $request2 = { + params => { + checked => events::check_params( + $config, + { + event_id => $entry->{event_id}, + template => 'no', + limit => 1, + archive => 'all', - #is series assigned to studio - my $result = series_events::check_permission( - $request, - { - permission => 'assign_series_events', - check_for => [ 'studio', 'user', 'series', 'studio_timeslots' ], - project_id => $entry->{project_id}, - studio_id => $entry->{studio_id}, - series_id => $entry->{series_id}, - event_id => $entry->{event_id}, - start => $event->{start_datetime}, - end => $event->{end_datetime} - } - ); - unless ( $result eq '1' ) { - uac::print_error($result); - return undef; - } + # no_exclude => 1 + } + ) + }, + config => $request->{config}, + permissions => $request->{permissions} + }; + $request2->{params}->{checked}->{published} = 'all'; - $config->{access}->{write} = 1; - $result = series::assign_event( - $config, - { - project_id => $entry->{project_id}, - studio_id => $entry->{studio_id}, - series_id => $entry->{series_id}, - event_id => $entry->{event_id}, - manual => 1 - } - ); - unless ( defined $result ) { - uac::print_error("error on assigning event to series"); - return undef; - } + my $events = events::get( $config, $request2 ); - my $series = series::get( - $config, - { - project_id => $entry->{project_id}, - studio_id => $entry->{studio_id}, - series_id => $entry->{series_id}, - } - ); - if ( @$series == 1 ) { - my $serie = $series->[0]; + if ( scalar(@$events) != 1 ) { + uac::print_error("no event found for event_id=$entry->{event_id}, archive=all"); + return undef; + } - #set event's series name to value from series - my $series_name = $serie->{series_name} || ''; - if ( $series_name ne '' ) { + my $event = $events->[0]; - # prepend series_name from event to title on adding to single_events series - my $title = $event->{title}; - if ( $serie->{has_single_events} eq '1' ) { - $title = $event->{series_name} . ' - ' . $title if $event->{series_name} ne ''; - } + #is series assigned to studio + my $result = series_events::check_permission( + $request, + { + permission => 'assign_series_events', + check_for => [ 'studio', 'user', 'series', 'studio_timeslots' ], + project_id => $entry->{project_id}, + studio_id => $entry->{studio_id}, + series_id => $entry->{series_id}, + event_id => $entry->{event_id}, + start => $event->{start_datetime}, + end => $event->{end_datetime} + } + ); + unless ( $result eq '1' ) { + uac::print_error($result); + return undef; + } - # save event content - series_events::save_content( - $config, - { - studio_id => $entry->{studio_id}, - id => $entry->{event_id}, #TODO: id=> event_id - series_name => $series_name, - title => $title, - episode => $event->{episode}, - rerun => $event->{rerun}, - } - ); + $config->{access}->{write} = 1; + $result = series::assign_event( + $config, + { + project_id => $entry->{project_id}, + studio_id => $entry->{studio_id}, + series_id => $entry->{series_id}, + event_id => $entry->{event_id}, + manual => 1 + } + ); + unless ( defined $result ) { + uac::print_error("error on assigning event to series"); + return undef; + } - # add to history - $event->{project_id} = $entry->{project_id}; - $event->{studio_id} = $entry->{studio_id}; - $event->{series_id} = $entry->{series_id}; - $event->{event_id} = $entry->{event_id}; - $event->{series_name} = $series_name; - $event->{title} = $title; - $event->{user} = $params->{presets}->{user}; - event_history::insert( $config, $event ); + my $series = series::get( + $config, + { + project_id => $entry->{project_id}, + studio_id => $entry->{studio_id}, + series_id => $entry->{series_id}, + } + ); + if ( @$series == 1 ) { + my $serie = $series->[0]; - # print STDERR "ok\n"; - } - } else { - print STDERR "no series title found for studio $entry->{studio_id} series $entry->{series_id}, event $entry->{event_id}\n"; - } + #set event's series name to value from series + my $series_name = $serie->{series_name} || ''; + if ( $series_name ne '' ) { - $config->{access}->{write} = 0; - uac::print_info("event successfully assigned to series"); - $params->{getBack} = 1; - return 1; + # prepend series_name from event to title on adding to single_events series + my $title = $event->{title}; + if ( $serie->{has_single_events} eq '1' ) { + $title = $event->{series_name} . ' - ' . $title if $event->{series_name} ne ''; + } + + # save event content + series_events::save_content( + $config, + { + studio_id => $entry->{studio_id}, + id => $entry->{event_id}, #TODO: id=> event_id + series_name => $series_name, + title => $title, + episode => $event->{episode}, + rerun => $event->{rerun}, + } + ); + + # add to history + $event->{project_id} = $entry->{project_id}; + $event->{studio_id} = $entry->{studio_id}; + $event->{series_id} = $entry->{series_id}; + $event->{event_id} = $entry->{event_id}; + $event->{series_name} = $series_name; + $event->{title} = $title; + $event->{user} = $params->{presets}->{user}; + event_history::insert( $config, $event ); + } + } else { + print STDERR +"no series title found for studio $entry->{studio_id} series $entry->{series_id}, event $entry->{event_id}\n"; + } + + $config->{access}->{write} = 0; + uac::print_info("event successfully assigned to series"); + $params->{getBack} = 1; + return 1; } sub unassign_event { - my $config = shift; - my $request = shift; + my $config = shift; + my $request = shift; - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - unless ( $permissions->{assign_series_events} == 1 ) { - uac::permissions_denied('assign_series_events'); - return; - } + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + unless ( $permissions->{assign_series_events} == 1 ) { + uac::permissions_denied('assign_series_events'); + return undef; + } - my $entry = {}; - for my $attr ( 'project_id', 'studio_id', 'series_id', 'event_id' ) { - if ( defined $params->{$attr} ) { - $entry->{$attr} = $params->{$attr}; - } else { - uac::print_error( $attr . ' not given!' ); - return; - } - } + my $entry = {}; + for my $attr ( 'project_id', 'studio_id', 'series_id', 'event_id' ) { + if ( defined $params->{$attr} ) { + $entry->{$attr} = $params->{$attr}; + } else { + uac::print_error( $attr . ' not given!' ); + return undef; + } + } - #check if event exists - my $event = series::get_event( - $config, - { - project_id => $entry->{project_id}, - studio_id => $entry->{studio_id}, - series_id => $entry->{series_id}, - event_id => $entry->{event_id}, - } - ); - unless ( defined $event ) { - uac::print_error( + #check if event exists + my $event = series::get_event( + $config, + { + project_id => $entry->{project_id}, + studio_id => $entry->{studio_id}, + series_id => $entry->{series_id}, + event_id => $entry->{event_id}, + } + ); + unless ( defined $event ) { + uac::print_error( "event $entry->{event_id} not found for project_id=$entry->{project_id}, studio_id=$entry->{studio_id}, series_id=$entry->{series_id}" - ); - return; - } + ); + return undef; + } - #print Dumper($event); + #is series assigned to studio + my $result = series_events::check_permission( + $request, + { + permission => 'assign_series_events', + check_for => [ 'studio', 'user', 'series', 'studio_timeslots' ], + project_id => $entry->{project_id}, + studio_id => $entry->{studio_id}, + series_id => $entry->{series_id}, + event_id => $entry->{event_id}, + start => $event->{start_datetime}, + end => $event->{end_datetime} + } + ); + unless ( $result eq '1' ) { + uac::print_error($result); + return undef; + } - #is series assigned to studio - my $result = series_events::check_permission( - $request, - { - permission => 'assign_series_events', - check_for => [ 'studio', 'user', 'series', 'studio_timeslots' ], - project_id => $entry->{project_id}, - studio_id => $entry->{studio_id}, - series_id => $entry->{series_id}, - event_id => $entry->{event_id}, - start => $event->{start_datetime}, - end => $event->{end_datetime} - } - ); - unless ( $result eq '1' ) { - uac::print_error($result); - return undef; - } - - $config->{access}->{write} = 1; - $result = series::unassign_event( - $config, - { - project_id => $entry->{project_id}, - studio_id => $entry->{studio_id}, - series_id => $entry->{series_id}, - event_id => $entry->{event_id}, - } - ); - $config->{access}->{write} = 0; - unless ( defined $result ) { - uac::print_error("error on unassigning event from series"); - return undef; - } - uac::print_info("event successfully unassigned from series"); - $params->{getBack} = 1; - return 1; + $config->{access}->{write} = 1; + $result = series::unassign_event( + $config, + { + project_id => $entry->{project_id}, + studio_id => $entry->{studio_id}, + series_id => $entry->{series_id}, + event_id => $entry->{event_id}, + } + ); + $config->{access}->{write} = 0; + unless ( defined $result ) { + uac::print_error("error on unassigning event from series"); + return undef; + } + uac::print_info("event successfully unassigned from series"); + $params->{getBack} = 1; + return 1; } # assign event to new series id and remove from old series id sub reassign_event { - my $config = shift; - my $request = shift; + my $config = shift; + my $request = shift; - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - unless ( $permissions->{assign_series_events} == 1 ) { - uac::permissions_denied('assign_series_events'); - return; - } + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + unless ( $permissions->{assign_series_events} == 1 ) { + uac::permissions_denied('assign_series_events'); + return undef; + } - for my $attr ( 'project_id', 'studio_id', 'series_id', 'new_series_id', 'event_id' ) { - unless ( defined $params->{$attr} ) { - uac::print_error( $attr . ' not given!' ); - return; - } - } + for my $attr ( 'project_id', 'studio_id', 'series_id', 'new_series_id', 'event_id' ) { + unless ( defined $params->{$attr} ) { + uac::print_error( $attr . ' not given!' ); + return undef; + } + } - my $project_id = $params->{project_id}; - my $studio_id = $params->{studio_id}; - my $event_id = $params->{event_id}; - my $series_id = $params->{series_id}; - my $new_series_id = $params->{new_series_id}; + my $project_id = $params->{project_id}; + my $studio_id = $params->{studio_id}; + my $event_id = $params->{event_id}; + my $series_id = $params->{series_id}; + my $new_series_id = $params->{new_series_id}; - $request->{params}->{checked}->{series_id} = $new_series_id; - my $result = assign_event( $config, $request ); - if ( $result == 1 ) { - $request->{params}->{checked}->{series_id} = $series_id; - $result = unassign_event( $config, $request ); - } - if ( $result == 1 ) { - my $url = - 'event.cgi?project_id=' . $project_id . '&studio_id=' . $studio_id . '&series_id=' . $new_series_id . '&event_id=' . $event_id; - print qq{<meta http-equiv="refresh" content="0; url=$url" />} . "\n"; - delete $params->{getBack}; - return 1; - } + $request->{params}->{checked}->{series_id} = $new_series_id; + my $result = assign_event( $config, $request ); + unless ( defined $result ) { + uac::print_error("could not assign event"); + return undef; + } + + $request->{params}->{checked}->{series_id} = $series_id; + $result = unassign_event( $config, $request ); + unless ( defined $result ) { + uac::print_error("could not unassign event"); + return undef; + } + + my $url = + 'event.cgi?project_id=' + . $project_id + . '&studio_id=' + . $studio_id + . '&series_id=' + . $new_series_id + . '&event_id=' + . $event_id; + print qq{<meta http-equiv="refresh" content="0; url=$url" />} . "\n"; + delete $params->{getBack}; + return 1; } sub add_user { - my $config = shift; - my $request = shift; + my $config = shift; + my $request = shift; - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - unless ( $permissions->{assign_series_member} == 1 ) { - uac::permissions_denied('assign_series_member'); - return; - } + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + unless ( $permissions->{assign_series_member} == 1 ) { + uac::permissions_denied('assign_series_member'); + return; + } - for my $param ( 'project_id', 'studio_id', 'series_id', 'user_id' ) { - if ( $params->{$param} eq '' ) { - uac::print_error("missing $param"); - return; - } - } + for my $param ( 'project_id', 'studio_id', 'series_id', 'user_id' ) { + if ( $params->{$param} eq '' ) { + uac::print_error("missing $param"); + return; + } + } - unless ( project::is_series_assigned( $config, $params ) == 1 ) { - uac::print_error('series is not assigned to project!'); - return undef; - } + unless ( project::is_series_assigned( $config, $params ) == 1 ) { + uac::print_error('series is not assigned to project!'); + return undef; + } - $config->{access}->{write} = 1; - series::add_user( - $config, - { - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - series_id => $params->{series_id}, - user_id => $params->{user_id}, - user => $request->{user} - } - ); + $config->{access}->{write} = 1; + series::add_user( + $config, + { + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + series_id => $params->{series_id}, + user_id => $params->{user_id}, + user => $request->{user} + } + ); - uac::print_info("user assigned to series"); + uac::print_info("user assigned to series"); } sub remove_user { - my $config = shift; - my $request = shift; + my $config = shift; + my $request = shift; - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - unless ( $permissions->{remove_series_member} == 1 ) { - uac::permissions_denied('remove_series_member'); - return; - } + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + unless ( $permissions->{remove_series_member} == 1 ) { + uac::permissions_denied('remove_series_member'); + return; + } - for my $param ( 'project_id', 'studio_id', 'series_id', 'user_id' ) { - if ( $params->{$param} eq '' ) { - uac::print_error("missing $param"); - return; - } - } + for my $param ( 'project_id', 'studio_id', 'series_id', 'user_id' ) { + if ( $params->{$param} eq '' ) { + uac::print_error("missing $param"); + return; + } + } - unless ( project::is_series_assigned( $config, $params ) == 1 ) { - uac::print_error('series is not assigned to project!'); - return undef; - } + unless ( project::is_series_assigned( $config, $params ) == 1 ) { + uac::print_error('series is not assigned to project!'); + return undef; + } - $config->{access}->{write} = 1; - series::remove_user( - $config, - { - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - series_id => $params->{series_id}, - user_id => $params->{user_id} - } - ); - uac::print_info("user removed from series"); + $config->{access}->{write} = 1; + series::remove_user( + $config, + { + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + series_id => $params->{series_id}, + user_id => $params->{user_id} + } + ); + uac::print_info("user removed from series"); } sub list_series { - my $config = shift; - my $request = shift; + my $config = shift; + my $request = shift; - $config->{access}->{write} = 0; + $config->{access}->{write} = 0; - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - unless ( $permissions->{read_series} == 1 ) { - uac::permissions_denied('read_series'); - return; - } + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + unless ( $permissions->{read_series} == 1 ) { + uac::permissions_denied('read_series'); + return; + } - my $project_id = $params->{project_id}; - my $studio_id = $params->{studio_id}; - my $series_conditions = { - project_id => $project_id, - studio_id => $studio_id - }; - my $series = series::get_event_age( $config, $series_conditions ); - my $newSeries = []; - my $oldSeries = []; - for my $serie ( sort { lc $a->{series_name} cmp lc $b->{series_name} } (@$series) ) { + my $project_id = $params->{project_id}; + my $studio_id = $params->{studio_id}; - if ( $serie->{days_over} > 30 ) { - push @$oldSeries, $serie; - } else { - push @$newSeries, $serie; - } - } + my $studios = studios::get( + $config, + { + project_id => $project_id, + studio_id => $studio_id + } + ); - $params->{newSeries} = $newSeries; - $params->{oldSeries} = $oldSeries; + my $studio_by_id = {}; + for my $studio (@$studios) { + $studio_by_id->{ $studio->{id} } = $studio; + } + my $studio = $studio_by_id->{$studio_id}; - $params->{loc} = localization::get( $config, { user => $params->{presets}->{user}, file => 'all,series' } ); - template::process( 'print', $params->{template}, $params ); + my $series_conditions = { + project_id => $project_id, + studio_id => $studio_id + }; + my $series = series::get_event_age( $config, $series_conditions ); + + my $newSeries = []; + my $oldSeries = []; + for my $serie ( sort { lc $a->{series_name} cmp lc $b->{series_name} } (@$series) ) { + if ( $serie->{days_over} > 30 ) { + push @$oldSeries, $serie; + } else { + push @$newSeries, $serie; + } + } + + $params->{newSeries} = $newSeries; + $params->{oldSeries} = $oldSeries; + + $params->{image} = + studios::getImageById( $config, { project_id => $project_id, studio_id => $studio_id } ) + if ( ( !defined $params->{image} ) || ( $params->{image} eq '' ) ); + $params->{image} = project::getImageById( $config, { project_id => $project_id } ) + if ( ( !defined $params->{image} ) || ( $params->{image} eq '' ) ); + + $params->{loc} = + localization::get( $config, { user => $params->{presets}->{user}, file => 'all,series' } ); + template::process( $config, 'print', $params->{template}, $params ); } sub show_series { - my $config = shift; - my $request = shift; + my $config = shift; + my $request = shift; - $config->{access}->{write} = 0; + $config->{access}->{write} = 0; - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - unless ( $permissions->{read_series} == 1 ) { - uac::permissions_denied('read_series'); - return; - } + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + unless ( $permissions->{read_series} == 1 ) { + uac::permissions_denied('read_series'); + return; + } - for my $param ( 'project_id', 'studio_id', 'series_id' ) { - unless ( defined $params->{$param} ) { - uac::print_error("missing $param"); - return; - } - } + for my $param ( 'project_id', 'studio_id', 'series_id' ) { + unless ( defined $params->{$param} ) { + uac::print_error("missing $param"); + return; + } + } - unless ( project::is_series_assigned( $config, $params ) == 1 ) { - uac::print_error('series is not assigned to project!'); - return undef; - } + unless ( project::is_series_assigned( $config, $params ) == 1 ) { + uac::print_error('series is not assigned to project!'); + return undef; + } - #this will be updated later (especially allow_update_events) - for my $permission ( keys %{ $request->{permissions} } ) { - $params->{'allow'}->{$permission} = $request->{permissions}->{$permission}; - } + #this will be updated later (especially allow_update_events) + for my $permission ( keys %{ $request->{permissions} } ) { + $params->{'allow'}->{$permission} = $request->{permissions}->{$permission}; + } - my $project_id = $params->{project_id}; - my $studio_id = $params->{studio_id}; + my $project_id = $params->{project_id}; + my $studio_id = $params->{studio_id}; - #list of all studios by id - my $studios = studios::get( - $config, - { - project_id => $project_id, - studio_id => $studio_id - } - ); - my $studio_by_id = {}; - for my $studio (@$studios) { - $studio_by_id->{ $studio->{id} } = $studio; - } + #list of all studios by id + my $studios = studios::get( + $config, + { + project_id => $project_id, + studio_id => $studio_id + } + ); + my $studio_by_id = {}; + for my $studio (@$studios) { + $studio_by_id->{ $studio->{id} } = $studio; + } - #get series - my $series_conditions = { - project_id => $project_id, - studio_id => $studio_id, - series_id => $params->{series_id} - }; + #get series + my $series_conditions = { + project_id => $project_id, + studio_id => $studio_id, + series_id => $params->{series_id} + }; - my $series = series::get( $config, $series_conditions ); - if ( @$series > 1 ) { - uac::print_error( "too much series found for studio '" . $studio_by_id->{$studio_id}->{name} . "'" ); - return; - } + my $series = series::get( $config, $series_conditions ); + if ( @$series > 1 ) { + uac::print_error( + "too much series found for studio '" . $studio_by_id->{$studio_id}->{name} . "'" ); + return; + } - if ( @$series == 0 ) { - uac::print_error( "selected series not assigned to studio '" . $studio_by_id->{$studio_id}->{name} . "'" ); - return; - } - my $serie = $series->[0]; + if ( @$series == 0 ) { + uac::print_error( "selected series not assigned to studio '" + . $studio_by_id->{$studio_id}->{name} + . "'" ); + return; + } + my $serie = $series->[0]; - #if ($serie->{has_single_events}==0){ - #delete $serie->{has_single_events}; - #$serie->{series_name}=''; - #} + uac::print_error( qq{show: Predecessor $serie->{predecessor_id} must be different from series id $serie->{series_id}.} ) + if ($serie->{predecessor_id}//'') eq $serie->{series_id}; - #get all users currently assigned to the user - my $user_studios = uac::get_studios_by_user( $config, { project_id => $project_id, user => $request->{user} } ); + #get all users currently assigned to the user + my $user_studios = + uac::get_studios_by_user( $config, { project_id => $project_id, user => $request->{user} } ); - my $studio_users = uac::get_users_by_studio( $config, { project_id => $project_id, studio_id => $studio_id } ); - for my $studio_user (@$studio_users) { - $studio_user->{user_id} = $studio_user->{id}; - } - my @users = @$studio_users; - @users = sort { $a->{full_name} cmp $b->{full_name} } @users; - $studio_users = \@users; + my $studio_users = + uac::get_users_by_studio( $config, { project_id => $project_id, studio_id => $studio_id } ); + for my $studio_user (@$studio_users) { + $studio_user->{user_id} = $studio_user->{id}; + } + my @users = @$studio_users; + @users = sort { lc $a->{full_name} cmp lc $b->{full_name} } @users; + $studio_users = \@users; - #show events from last month until next 3 months - my $from = DateTime->now( time_zone => $config->{date}->{time_zone} )->subtract( months => 1 )->datetime(); - my $till = DateTime->now( time_zone => $config->{date}->{time_zone} )->add( months => 3 )->datetime(); + #show events from last month until next 3 months + my $from = DateTime->now( time_zone => $config->{date}->{time_zone} )->subtract( months => 1 ) + ->datetime(); + my $till = + DateTime->now( time_zone => $config->{date}->{time_zone} )->add( months => 3 )->datetime(); - #add name of current studio - my $studio = $studio_by_id->{ $serie->{studio_id} }; - $serie->{studio} = $studio->{name}; + #add name of current studio + my $studio = $studio_by_id->{ $serie->{studio_id} }; + $serie->{studio} = $studio->{name}; - my $location = $studio->{location}; + my $location = $studio->{location}; - #add users - $serie->{series_users} = series::get_users( - $config, - { - project_id => $project_id, - studio_id => $serie->{studio_id}, - series_id => $serie->{series_id} - } - ); + # set default image from studio + $serie->{image} = + studios::getImageById( $config, { project_id => $project_id, studio_id => $studio_id } ) + if ( ( !defined $serie->{image} ) || ( $serie->{image} eq '' ) ); + $serie->{image} = project::getImageById( $config, { project_id => $project_id } ) + if ( ( !defined $serie->{image} ) || ( $serie->{image} eq '' ) ); - #add events - $serie->{events} = series::get_events( - $config, - { - project_id => $project_id, - studio_id => $serie->{studio_id}, - series_id => $serie->{series_id}, - from_date => $from, - till_date => $till, - location => $location, - limit => 30, - archive => 'all', - published => 'all' - } - ); - @{ $serie->{events} } = reverse @{ $serie->{events} }; + #add users + $serie->{series_users} = series::get_users( + $config, + { + project_id => $project_id, + studio_id => $serie->{studio_id}, + series_id => $serie->{series_id} + } + ); + uac::print_warn("There is no user assigned, yet. Please assign a user!") + if scalar @{ $serie->{series_users} } == 0; - my $allow_update_event = series_events::check_permission( - $request, - { - permission => 'update_event_of_series,update_event_of_others', - check_for => [ 'studio', 'user', 'series' ], - project_id => $project_id, - studio_id => $serie->{studio_id}, - series_id => $params->{series_id} - }, + #add events + $serie->{events} = series::get_events( + $config, + { + project_id => $project_id, + studio_id => $serie->{studio_id}, + series_id => $serie->{series_id}, + from_date => $from, + till_date => $till, + location => $location, + limit => 30, + archive => 'all', + published => 'all' + } + ); + @{ $serie->{events} } = reverse @{ $serie->{events} }; - ); + my $allow_update_event = series_events::check_permission( + $request, + { + permission => 'update_event_of_series,update_event_of_others', + check_for => [ 'studio', 'user', 'series' ], + project_id => $project_id, + studio_id => $serie->{studio_id}, + series_id => $params->{series_id} + }, - $params->{allow}->{update_event} = 0; - $params->{allow}->{update_event} = 1 if ( $allow_update_event eq '1' ); + ); - $serie->{studio_users} = $studio_users; + $params->{allow}->{update_event} = 0; + $params->{allow}->{update_event} = 1 if ( $allow_update_event eq '1' ); - $serie->{html_content} = markup::creole_to_html( $serie->{content} ); - $serie->{html_content} =~ s/([^\>])\n+([^\<])/$1<br\/><br\/>$2/g; + $serie->{studio_users} = $studio_users; - for my $user ( @{ $serie->{series_users} } ) { - $user->{user_id} = $user->{id}; - } + if (($serie->{markup_format}//'') eq 'markdown'){ + $serie->{html_content} = markup::markdown_to_html( $serie->{content} ); + }else{ + $serie->{html_content} = markup::creole_to_html( $serie->{content} ); + $serie->{html_content} =~ s/([^\>])\n+([^\<])/$1<br\/><br\/>$2/g; + } - #add schedules - my $schedules = series_schedule::get( - $config, - { - project_id => $project_id, - studio_id => $studio_id, - series_id => $serie->{series_id} - } - ); + for my $user ( @{ $serie->{series_users} } ) { + $user->{user_id} = $user->{id}; + } - #remove seconds from dates - for my $schedule (@$schedules) { - $schedule->{start} =~ s/(\d\d\:\d\d)\:\d\d/$1/ if defined $schedule->{start}; - $schedule->{end} =~ s/(\d\d\:\d\d)\:\d\d/$1/ if defined $schedule->{end}; + #add schedules + my $schedules = series_schedule::get( + $config, + { + project_id => $project_id, + studio_id => $studio_id, + series_id => $serie->{series_id} + } + ); - #detect schedule type - if ( $schedule->{period_type} eq '' ) { - $schedule->{period_type} = 'week_of_month'; - $schedule->{period_type} = 'days' unless ( $schedule->{week_of_month} =~ /\d/ ); - $schedule->{period_type} = 'single' unless ( $schedule->{end} =~ /\d/ ); - } - $schedule->{ 'period_type_' . $schedule->{period_type} } = 1; + #remove seconds from dates + for my $schedule (@$schedules) { + $schedule->{start} =~ s/(\d\d\:\d\d)\:\d\d/$1/ if defined $schedule->{start}; + $schedule->{end} =~ s/(\d\d\:\d\d)\:\d\d/$1/ if defined $schedule->{end}; - #print STDERR $schedule->{period_type}."\n"; - } + #detect schedule type + if ( $schedule->{period_type} eq '' ) { + $schedule->{period_type} = 'week_of_month'; + $schedule->{period_type} = 'days' unless ( $schedule->{week_of_month} =~ /\d/ ); + $schedule->{period_type} = 'single' unless ( $schedule->{end} =~ /\d/ ); + } + $schedule->{ 'period_type_' . $schedule->{period_type} } = 1; + } - $serie->{schedule} = $schedules; - $serie->{start} = $params->{start}; - $serie->{end} = $params->{end}; - $serie->{frequency} = $params->{frequency}; - $serie->{duration} = $serie->{default_duration}; - my $duration = $params->{duration} || ''; - $serie->{duration} = $params->{duration} if $duration ne ''; + $serie->{schedule} = $schedules; + $serie->{start} = $params->{start}; + $serie->{end} = $params->{end}; + $serie->{frequency} = $params->{frequency}; + $serie->{duration} = $serie->{default_duration}; + my $duration = $params->{duration} || ''; + $serie->{duration} = $params->{duration} if $duration ne ''; - $serie->{start} =~ s/(\d\d\:\d\d)\:\d\d/$1/ if defined $serie->{start}; - $serie->{end} =~ s/(\d\d\:\d\d)\:\d\d/$1/ if defined $serie->{end}; + $serie->{start} =~ s/(\d\d\:\d\d)\:\d\d/$1/ if defined $serie->{start}; + $serie->{end} =~ s/(\d\d\:\d\d)\:\d\d/$1/ if defined $serie->{end}; - #add series dates - my $series_dates = series_dates::get( - $config, - { - project_id => $project_id, - studio_id => $studio_id, - series_id => $serie->{series_id} - } - ); + #add series dates + my $series_dates = series_dates::get( + $config, + { + project_id => $project_id, + studio_id => $studio_id, + series_id => $serie->{series_id} + } + ); - #remove seconds from dates - for my $date (@$series_dates) { - $date->{start} =~ s/(\d\d\:\d\d)\:\d\d/$1/; - $date->{end} =~ s/(\d\d\:\d\d)\:\d\d/$1/; - } - $serie->{series_dates} = $series_dates; + #remove seconds from dates + for my $date (@$series_dates) { + $date->{start} =~ s/(\d\d\:\d\d)\:\d\d/$1/; + $date->{end} =~ s/(\d\d\:\d\d)\:\d\d/$1/; + } + $serie->{series_dates} = $series_dates; - $serie->{show_hint_to_add_schedule} = $params->{show_hint_to_add_schedule}; + $serie->{show_hint_to_add_schedule} = $params->{show_hint_to_add_schedule}; - #copy series to params - #$params->{series}=[$serie]; - for my $key ( keys %$serie ) { - $params->{$key} = $serie->{$key}; - } + if ( ( defined $params->{setImage} ) and ( $params->{setImage} ne $serie->{image} ) ) { + $serie->{image} = $params->{setImage}; + $params->{forced_change} = 1; + } - #print STDERR '<pre>'.Dumper($params).'</pre>'; - $params->{loc} = localization::get( $config, { user => $params->{presets}->{user}, file => 'all,series' } ); - template::process( 'print', $params->{template}, $params ); + #copy series to params + for my $key ( keys %$serie ) { + $params->{$key} = $serie->{$key}; + } + + for my $value ('markdown', 'creole'){ + $params->{"content_format_$value"}=1 if ($params->{content_format}//'') eq $value; + } + + $params->{loc} = + localization::get( $config, { user => $params->{presets}->{user}, file => 'all,series' } ); + template::process( $config, 'print', $params->{template}, $params ); +} + +sub set_rebuilt_episodes { + my $config = shift; + my $request = shift; + + $config->{access}->{write} = 0; + + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + unless ( $permissions->{read_series} == 1 ) { + uac::permissions_denied('read_series'); + return; + } + + for my $param ( 'project_id', 'studio_id', 'series_id' ) { + unless ( defined $params->{$param} ) { + uac::print_error("missing $param"); + return; + } + } + + unless ( project::is_series_assigned( $config, $params ) == 1 ) { + uac::print_error('series is not assigned to project!'); + return undef; + } + + #this will be updated later (especially allow_update_events) + for my $permission ( keys %{ $request->{permissions} } ) { + $params->{'allow'}->{$permission} = $request->{permissions}->{$permission}; + } + + my $project_id = $params->{project_id}; + my $studio_id = $params->{studio_id}; + my $series_id = $params->{series_id}; + my $events = series::get_rebuilt_episodes( + $config, + { + project_id => $project_id, + studio_id => $studio_id, + series_id => $series_id + } + ); + + my $updates = 0; + for my $event (@$events) { + next if $event->{project_id} ne $project_id; + next if $event->{studio_id} ne $studio_id; + next if $event->{old_episode} eq $event->{episode}; + series_events::set_episode( + $config, + { + id => $event->{id}, + episode => $event->{episode} + } + ); + $updates++; + } +} + +sub rebuild_episodes { + my $config = shift; + my $request = shift; + + $config->{access}->{write} = 0; + + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + unless ( $permissions->{read_series} == 1 ) { + uac::permissions_denied('read_series'); + return; + } + + for my $param ( 'project_id', 'studio_id', 'series_id' ) { + unless ( defined $params->{$param} ) { + uac::print_error("missing $param"); + return; + } + } + + unless ( project::is_series_assigned( $config, $params ) == 1 ) { + uac::print_error('series is not assigned to project!'); + return undef; + } + + #this will be updated later (especially allow_update_events) + for my $permission ( keys %{ $request->{permissions} } ) { + $params->{'allow'}->{$permission} = $request->{permissions}->{$permission}; + } + + my $project_id = $params->{project_id}; + my $studio_id = $params->{studio_id}; + my $series_id = $params->{series_id}; + my $events = series::get_rebuilt_episodes( + $config, + { + project_id => $project_id, + studio_id => $studio_id, + series_id => $series_id + } + ); + + my $events_by_id = {}; + for my $event (@$events) { + $events_by_id->{ $event->{id} } = $event; + } + + print "<style> + tr {cursor:pointer} + td {border:1px solid gray} + tr.error {background:#f99} + tr.warn {background:#ff9} + tr.ok {background:#9f9} + </style> + "; + + my $prev = undef; + my $max_episode = 0; + my $changes = 0; + my $errors = 0; + for my $event (@$events) { + $max_episode = $event->{episode} if $event->{episode} > $max_episode; + my $e1 = $event->{old_episode} // ''; + my $e2 = $event->{episode} // ''; + my $o1 = $prev->{old_episode} // ''; + my $o2 = $prev->{episode} // ''; + if ( $e1 eq $e2 ) { + $event->{class} = 'ok'; + } else { + $changes++; + $event->{class} = 'warn'; + } + if ( $e1 and $e2 and $o1 and $o2 and ( ( $e2 - $o2 ) != ( $e1 - $o1 ) ) ) { + $event->{class} = "error" if $e1 ne $e2; + $prev->{class} = "error" if defined $prev and $o1 ne $o2; + $errors++; + } + if ( $event->{episode} < $max_episode and !$event->{recurrence} ) { + $event->{class} = "error"; + $errors++; + } + $event->{recurrence_start} = $events_by_id->{ $event->{recurrence} }->{start}; + $event->{recurrence} = '-' unless $event->{recurrence}; + $prev = $event; + } + print "$errors errors, $changes changes\n"; + if ( ( $changes > 0 ) and ( $errors == 0 ) ) { + my $url = +"series.cgi?action=set_rebuilt_episodes&project_id=$project_id&studio_id=$studio_id&series_id=$series_id"; + print qq{<a class="button" href="$url"><button>apply changes</button></a>}; + } + my @cols = + qw(id start series_name title episode old_episode recurrence recurrence_start project_name studio_name); + print "<table>\n"; + print "<tr>" . join( "", map { "<th>" . ( $_ // '-' ) . "</th>" } @cols ) . "</tr>\n"; + + for my $event (@$events) { + print qq{<tr class="$event->{class}" onclick="window.location.href=\$(this).attr('href');"} + . qq{ href="event.cgi?action=edit&project_id=$event->{project_id}&studio_id=$event->{studio_id}&series_id=$series_id&event_id=$event->{id}"\n} + . qq{>} + . join( "", map { "<td>" . ( $event->{$_} // '-' ) . "</td>" } @cols ) + . "</tr>\n"; + } + print "</table>\n"; } sub check_params { - my $params = shift; + my $config = shift; + my $params = shift; - my $checked = {}; + my $checked = {}; - my $debug = $params->{debug} || ''; - if ( $debug =~ /([a-z\_\,]+)/ ) { - $debug = $1; - } - $checked->{debug} = $debug; + $checked->{action} = entry::element_of( $params->{action}, + [ qw( add_user remove_user + create delete save details show + save_schedule delete_schedule + save_scan scan_events + assign_event unassign_event reassign_event + rebuild_episodes set_rebuilt_episodes + )]); + + $checked->{exclude} = 0; + entry::set_numbers( $checked, $params, [ + 'id', 'project_id', + 'studio_id', 'default_studio_id', + 'user_id', 'new_series_id', + 'series_id', 'schedule_id', + 'exclude', 'show_hint_to_add_schedule', + 'event_id', 'weekday', + 'week_of_month', 'month', + 'nextDay', 'predecessor_id' + ]); + + if ( defined $checked->{studio_id} ) { + $checked->{default_studio_id} = $checked->{studio_id}; + } else { + $checked->{studio_id} = -1; + } - #actions and roles - $checked->{action} = ''; - if ( defined $params->{action} ) { - if ( $params->{action} =~ -/^(add_user|remove_user|create|delete|save|details|show|save_schedule|delete_schedule|save_scan|scan_events|assign_event|unassign_event|reassign_event)$/ - ) - { - $checked->{action} = $params->{action}; - } - } + if ( defined $checked->{series_id} ) { + $checked->{template} = template::check( $config, $params->{template}, 'edit-series' ); + } else { + $checked->{template} = template::check( $config, $params->{template}, 'series' ); + } - #numeric values - $checked->{exclude} = 0; - for my $param ( - 'id', 'project_id', 'studio_id', 'default_studio_id', - 'user_id', 'new_series_id', 'series_id', 'schedule_id', - 'exclude', 'show_hint_to_add_schedule', 'event_id', 'weekday', - 'week_of_month', 'month', 'nextDay' - ) - { - if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /^\d+$/ ) ) { - $checked->{$param} = $params->{$param}; - } - } - if ( defined $checked->{studio_id} ) { - $checked->{default_studio_id} = $checked->{studio_id}; - } else { - $checked->{studio_id} = -1; - } + if ( ( defined $checked->{action} ) && ( $checked->{action} eq 'save_schedule' ) ) { - if ( defined $checked->{series_id} ) { - $checked->{template} = template::check( $params->{template}, 'edit_series' ); - } else { - $checked->{template} = template::check( $params->{template}, 'series' ); - } + #set defaults + $checked->{create_events} = 0; + $checked->{publish_events} = 0; + } + + entry::set_numbers( $checked, $params, [ + 'frequency', 'duration', 'default_duration', 'create_events', + 'publish_events', 'live', 'count_episodes' + ]); - if ( ( defined $checked->{action} ) && ( $checked->{action} eq 'save_schedule' ) ) { + #scalars + entry::set_strings( $checked, $params, + [ 'search', 'from', 'till', 'period_type' ] + ); - #set defaults - $checked->{create_events} = 0; - $checked->{publish_events} = 0; - } - for my $param ( 'frequency', 'duration', 'default_duration', 'create_events', 'publish_events', 'live', 'count_episodes' ) { - if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /(\d+)/ ) ) { - $checked->{$param} = $1; - } - } + entry::set_strings( $checked, $params, [ + 'series_name', 'title', + 'excerpt', 'content', + 'topic', 'image', + 'image_label', 'assign_event_series_name', + 'assign_event_title', 'comment', + 'podcast_url', 'archive_url', + 'setImage', 'content_format' + ]); - #scalars - for my $param ( 'search', 'from', 'till', 'period_type' ) { - if ( defined $params->{$param} ) { - $checked->{$param} = $params->{$param}; - $checked->{$param} =~ s/^\s+//g; - $checked->{$param} =~ s/\s+$//g; - } - } + for my $attr ('start') { + if ( ( defined $params->{$attr} ) + && ( $params->{$attr} =~ /(\d\d\d\d\-\d\d\-\d\d[ T]\d\d\:\d\d)/ ) ) + { + $checked->{$attr} = $1 . ':00'; + } + } - for my $param ( 'series_name', 'title', 'excerpt', 'content', 'topic', 'image', - 'assign_event_series_name', 'assign_event_title', 'comment', 'podcast_url', 'archive_url' ) - { - if ( defined $params->{$param} ) { + for my $attr ('end') { + if ( ( defined $params->{$attr} ) && ( $params->{$attr} =~ /(\d\d\d\d\-\d\d\-\d\d)/ ) ) { + $checked->{$attr} = $1; + } + } - #$checked->{$param}=uri_unescape(); - $checked->{$param} = $params->{$param}; - $checked->{$param} =~ s/^\s+//g; - $checked->{$param} =~ s/\s+$//g; - } - } - - for my $attr ('start') { - if ( ( defined $params->{$attr} ) && ( $params->{$attr} =~ /(\d\d\d\d\-\d\d\-\d\d[ T]\d\d\:\d\d)/ ) ) { - $checked->{$attr} = $1 . ':00'; - } - } - - for my $attr ('end') { - if ( ( defined $params->{$attr} ) && ( $params->{$attr} =~ /(\d\d\d\d\-\d\d\-\d\d)/ ) ) { - $checked->{$attr} = $1; - } - } - - return $checked; + return $checked; } diff --git a/website/agenda/planung/set-user-day-start.cgi b/website/agenda/planung/set-user-day-start.cgi new file mode 100644 index 0000000..762dfa2 --- /dev/null +++ b/website/agenda/planung/set-user-day-start.cgi @@ -0,0 +1,100 @@ +#!/usr/bin/perl + +use strict; +use warnings; +no warnings 'redefine'; + +use Data::Dumper; + +use params(); +use config(); +use entry(); +use log(); +use template(); +use auth(); +use uac(); + +use series(); +use localization(); +use user_day_start(); + +binmode STDOUT, ":utf8"; + +my $r = shift; +( my $cgi, my $params, my $error ) = params::get($r); + +my $config = config::get('../config/config.cgi'); +my $debug = $config->{system}->{debug}; +my ( $user, $expires ) = auth::get_user( $config, $params, $cgi ); +return if ( ( !defined $user ) || ( $user eq '' ) ); + +my $user_presets = uac::get_user_presets( + $config, + { + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + user => $user + } +); +$params->{default_studio_id} = $user_presets->{studio_id}; +$params = uac::setDefaultStudio( $params, $user_presets ); +$params = uac::setDefaultProject( $params, $user_presets ); + +my $request = { + url => $ENV{QUERY_STRING} || '', + params => { + original => $params, + checked => check_params( $config, $params ), + }, +}; +$request = uac::prepare_request( $request, $user_presets ); + +$params = $request->{params}->{checked}; +$params = uac::set_template_permissions( $request->{permissions}, $params ); +$params->{loc} = localization::get( $config, { user => $user, file => 'select-event' } ); + +#process header +print "Content-type:text/text; charset=UTF-8;\n\n"; + +return unless uac::check( $config, $params, $user_presets ) == 1; +set_start_date( $config, $request ); + +sub set_start_date { + my $config = shift; + my $request = shift; + + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + unless ( $permissions->{read_event} == 1 ) { + uac::permissions_denied('read_event'); + return; + } + + my $preset = user_day_start::insert_or_update($config, { + user => $request->{user}, + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + day_start => $params->{day_start}, + }); + print "done\n"; + return; +} + +sub check_params { + my $config = shift; + my $params = shift; + + my $checked = {}; + + entry::set_numbers( $checked, $params, [ + 'id', 'project_id', 'studio_id', 'day_start' + ]); + + if ( defined $checked->{studio_id} ) { + $checked->{default_studio_id} = $checked->{studio_id}; + } else { + $checked->{studio_id} = -1; + } + return $checked; +} + diff --git a/website/agenda/planung/show-image.cgi b/website/agenda/planung/show-image.cgi new file mode 100755 index 0000000..9fef331 --- /dev/null +++ b/website/agenda/planung/show-image.cgi @@ -0,0 +1,129 @@ +#!/usr/bin/perl + +use strict; +use warnings; +no warnings 'redefine'; +use utf8; +use Data::Dumper; + +use params(); +use config(); +use entry(); +use log(); +use template(); +use auth(); +use uac(); +use images(); +use localization(); + +binmode STDOUT, ":utf8"; + +my $r = shift; +( my $cgi, my $params, my $error ) = params::get($r); + +my $config = config::get('../config/config.cgi'); +my $debug = $config->{system}->{debug}; +my ( $user, $expires ) = auth::get_user( $config, $params, $cgi ); +return if ( ( !defined $user ) || ( $user eq '' ) ); + +my $user_presets = uac::get_user_presets( + $config, + { + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + user => $user + } +); +$params->{default_studio_id} = $user_presets->{studio_id}; +$params = uac::setDefaultStudio( $params, $user_presets ); +$params = uac::setDefaultProject( $params, $user_presets ); + +my $request = { + url => $ENV{QUERY_STRING} || '', + params => { + original => $params, + checked => check_params( $config, $params ), + }, +}; +$request = uac::prepare_request( $request, $user_presets ); +$params = $request->{params}->{checked}; + +#process header + +return unless uac::check( $config, $params, $user_presets ) == 1; +showImage( $config, $request ); + +#TODO: filter by published, draft +sub showImage { + my $config = shift; + my $request = shift; + + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + + unless ( $permissions->{read_event} == 1 ) { + uac::permissions_denied('read_image'); + return; + } + + unless ( defined $params->{filename} ) { + uac::permissions_denied('missing filename'); + return; + } + + my $filename = images::getInternalPath( $config, $params ); + unless ( defined $filename ) { + uac::permissions_denied("could not find path"); + return; + } + + unless ( -e $filename ) { + uac::permissions_denied("read $filename"); + return; + } + + my $image = images::readFile($filename); + if ( defined $image->{error} ) { + uac::permissions_denied("read $filename, $image->{error}"); + return; + } + + binmode STDOUT; + print "Content-type:image/jpeg; charset=UTF-8;\n\n"; + print $image->{content}; + return; +} + +sub check_params { + my $config = shift; + my $params = shift; + + my $checked = {}; + + for my $param ('filename') { + if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /^[A-Za-z\_\-\.\d\/]+$/ ) ) { + $checked->{$param} = $params->{$param}; + $checked->{$param} =~ s/^.*\///g; + } + } + + $checked->{type} = 'thumbs'; + for my $param ('type') { + if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /^(thumbs|images|icons)$/ ) ) { + $checked->{$param} = $params->{$param}; + } + } + + entry::set_numbers( $checked, $params, [ + 'project_id', 'studio_id', 'series_id', 'event_id' + ]); + + if ( defined $checked->{studio_id} ) { + $checked->{default_studio_id} = $checked->{studio_id}; + } else { + $checked->{studio_id} = -1; + } + + return $checked; +} + diff --git a/website/agenda/planung/show-playout.cgi b/website/agenda/planung/show-playout.cgi index 6d8b791..20c620e 100755 --- a/website/agenda/planung/show-playout.cgi +++ b/website/agenda/planung/show-playout.cgi @@ -1,12 +1,10 @@ #!/usr/bin/perl -local $| = 0; - -use warnings; use strict; +use warnings; +no warnings 'redefine'; use Data::Dumper; -use CGI::Simple (); use ModPerl::Util (); use config; @@ -18,6 +16,8 @@ use studios; use series; use template; use playout; +use audio; +use entry; binmode STDOUT, ":utf8"; @@ -26,50 +26,40 @@ my $r = shift; my $config = config::get('../config/config.cgi'); my $debug = $config->{system}->{debug}; -my ( $user, $expires ) = auth::get_user( $cgi, $config ); -return if ( ( !defined $user ) || ( $user eq '' ) ); +my ( $user, $expires ) = auth::get_user( $config, $params, $cgi ); +return if ( !defined $user ) || ( $user eq '' ); -#print STDERR $params->{project_id}."\n"; my $user_presets = uac::get_user_presets( - $config, - { - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - user => $user - } + $config, + { + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + user => $user + } ); $params->{default_studio_id} = $user_presets->{studio_id}; -$params->{studio_id} = $params->{default_studio_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); -$params->{project_id} = $user_presets->{project_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); +$params = uac::setDefaultStudio( $params, $user_presets ); +$params = uac::setDefaultProject( $params, $user_presets ); -#print STDERR $params->{project_id}."\n"; my $request = { - url => $ENV{QUERY_STRING} || '', - params => { - original => $params, - checked => check_params($params), - }, + url => $ENV{QUERY_STRING} || '', + params => { + original => $params, + checked => check_params( $config, $params ), + }, }; $request = uac::prepare_request( $request, $user_presets ); -log::init($request); - $params = $request->{params}->{checked}; #process header unless ( params::isJson() ) { - my $headerParams = uac::set_template_permissions( $request->{permissions}, $params ); - $headerParams->{loc} = localization::get( $config, { user => $user, file => 'menu' } ); - template::process( 'print', template::check('default.html'), $headerParams ); + my $headerParams = uac::set_template_permissions( $request->{permissions}, $params ); + $headerParams->{loc} = localization::get( $config, { user => $user, file => 'menu' } ); + template::process( $config, 'print', template::check( $config, 'show-playout-header.html' ), + $headerParams ); } return unless uac::check( $config, $params, $user_presets ) == 1; -print q{ - <script src="js/show-playout.js" type="text/javascript"></script> - <link rel="stylesheet" href="css/show-playout.css" type="text/css" /> -} unless (params::isJson); - my $permissions = $request->{permissions}; $params->{action} = '' unless defined $params->{action}; $params->{error} = $error || ''; @@ -77,128 +67,84 @@ $params->{error} = $error || ''; showPlayout( $config, $request ); print STDERR "$0 ERROR: " . $params->{error} . "\n" if $params->{error} ne ''; -$params->{loc} = localization::get( $config, { user => $params->{presets}->{user}, file => 'event,comment' } ); -template::process( 'print', $params->{template}, $params ); +$params->{loc} = + localization::get( $config, { user => $params->{presets}->{user}, file => 'event,comment' } ); +template::process( $config, 'print', $params->{template}, $params ); exit; sub showPlayout { - my $config = shift; - my $request = shift; + my $config = shift; + my $request = shift; - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; - for my $attr ( 'project_id', 'studio_id' ) { - unless ( defined $params->{$attr} ) { - uac::print_error( "missing " . $attr . " to show playout" ); - return; - } - } + for my $attr ( 'project_id', 'studio_id' ) { + unless ( defined $params->{$attr} ) { + uac::print_error( "missing " . $attr . " to show playout" ); + return; + } + } - my $events = playout::get( - $config, - { - project_id => $params->{project_id}, - studio_id => $params->{studio_id}, - order => 'modified_at desc, start desc', - limit => 500 - } - ); + my $today = time::time_to_date( time() ); + my $startDate = time::add_days_to_date( $today, -14 ); + my $events = playout::get_scheduled( + $config, + { + project_id => $params->{project_id}, + studio_id => $params->{studio_id}, + order => 'p.modified_at asc, p.start asc', + from => $startDate + } + ); - # print '<pre>'.Dumper($events).'</pre>'; - unless ( defined $events ) { - uac::print_error("not found"); - return; - } + unless ( defined $events ) { + uac::print_error("not found"); + return; + } - for my $event (@$events) { - $event->{stream_size} =~ s/(\d)(\d\d\d)$/$1\.$2/g; - $event->{stream_size} =~ s/(\d)(\d\d\d\.\d\d\d)$/$1\.$2/g; - $event->{duration} =~ s/(\d\.\d)(\d+)$/$1/g; - $event->{duration} =~ s/(\d)\.0/$1/g; - $event->{rms_left} = formatLoudness( $event->{rms_left} ); - $event->{rms_right} = formatLoudness( $event->{rms_right} ); - $event->{bitrate} = formatBitrate($event); - $event->{duration} = formatDuration($event); - } + for my $event (@$events) { + $event->{stream_size} ||= ''; + $event->{stream_size} =~ s/(\d)(\d\d\d)$/$1\.$2/g; + $event->{stream_size} =~ s/(\d)(\d\d\d\.\d\d\d)$/$1\.$2/g; + $event->{duration} =~ s/(\d\.\d)(\d+)$/$1/g; + $event->{duration} =~ s/(\d)\.0/$1/g; + $event->{rms_left} = audio::formatLoudness( $event->{rms_left}, 'L:' ); + $event->{rms_right} = audio::formatLoudness( $event->{rms_right}, 'R:' ); + $event->{bitrate} = audio::formatBitrate( $event->{bitrate} ); + $event->{bitrate_mode} = audio::formatBitrateMode( $event->{bitrate_mode} ); + $event->{sampling_rate} = audio::formatSamplingRate( $event->{sampling_rate} ); + $event->{duration} = audio::formatDuration( + $event->{duration}, + $event->{event_duration}, + sprintf( "%.1g h", $event->{duration} / 3600) + ); + $event->{channels} = audio::formatChannels( $event->{channels} ); + $event->{class} = "past" if $event->{start} lt $today; + } - $params->{events} = $events; - - #print Dumper($events); -} - -sub formatDuration { - my $event = $_[0]; - my $duration = $event->{duration}; - return '' unless defined $duration; - return '' if $duration eq ''; - my $result = int( ( $duration + 3600 ) * 10 ) % 600; - my $class = "ok"; - $class = "warn" if $result > 1; - $class = "error" if $result > 10; - return sprintf( qq{<div class="%s">%.01f</div>}, $class, $duration ); -} - -sub formatBitrate { - my $event = $_[0]; - my $bitrate = $event->{bitrate}; - my $mode = $event->{bitrate_mode}; - if ( $bitrate ne '' ) { - if ( $bitrate >= 200 ) { - $bitrate = '<div class="warn">' . $bitrate . ' ' . $mode . '</div>'; - } elsif ( $bitrate < 190 ) { - $bitrate = '<div class="error">' . $bitrate . ' ' . $mode . '</div>'; - } else { - $bitrate .= ' ' . $mode; - } - } - return $bitrate; -} - -sub formatLoudness { - my $value = shift; - return '' unless defined $value; - return '' if $value == 0; - return '' if $value eq ''; - - $value = sprintf( "%.1f", $value ); - my $class = 'ok'; - $class = 'warn' if $value > -18.5; - $class = 'error' if $value > -16.0; - $class = 'warn' if $value < -24.0; - $class = 'error' if $value < -27.0; - - return qq{<div class="$class">$value dB</div>}; + $params->{events} = $events; } sub check_params { - my $params = shift; + my $config = shift; + my $params = shift; - my $checked = {}; - $checked->{error} = ''; - $checked->{template} = template::check( $params->{template}, 'show_playout' ); + my $checked = {}; + $checked->{error} = ''; + $checked->{template} = template::check( $config, $params->{template}, 'show-playout' ); - #numeric values - for my $param ( 'project_id', 'studio_id', 'default_studio_id', 'series_id', 'event_id', 'id' ) { - if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /^\d+$/ ) ) { - $checked->{$param} = $params->{$param}; - } - } + entry::set_numbers( $checked, $params, [ + 'project_id', 'studio_id', 'default_studio_id', 'series_id', 'event_id', 'id' + ]); - if ( defined $checked->{studio_id} ) { - $checked->{default_studio_id} = $checked->{studio_id}; - } else { - $checked->{studio_id} = -1; - } + if ( defined $checked->{studio_id} ) { + $checked->{default_studio_id} = $checked->{studio_id}; + } else { + $checked->{studio_id} = -1; + } - #word - for my $param ('debug') { - if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /^\s*(.+?)\s*$/ ) ) { - $checked->{$param} = $1; - } - } - - return $checked; + return $checked; } diff --git a/website/agenda/planung/studio-timeslots.cgi b/website/agenda/planung/studio-timeslots.cgi new file mode 100755 index 0000000..4398e1f --- /dev/null +++ b/website/agenda/planung/studio-timeslots.cgi @@ -0,0 +1,391 @@ +#!/usr/bin/perl + +use strict; +use warnings; +no warnings 'redefine'; + +use Data::Dumper; +use URI::Escape(); + +use params(); +use config(); +use entry(); +use log(); +use template(); +use auth(); +use uac(); +use roles(); +use project(); +use studios(); +use studio_timeslot_schedule(); +use studio_timeslot_dates(); +use markup(); +use localization(); + +binmode STDOUT, ":utf8"; + +my $r = shift; +( my $cgi, my $params, my $error ) = params::get($r); + +my $config = config::get('../config/config.cgi'); +my $debug = $config->{system}->{debug}; +my ( $user, $expires ) = auth::get_user( $config, $params, $cgi ); +return if ( ( !defined $user ) || ( $user eq '' ) ); + +my $user_presets = uac::get_user_presets( + $config, + { + user => $user, + project_id => $params->{project_id}, + studio_id => $params->{studio_id} + } +); +$params->{default_studio_id} = $user_presets->{studio_id}; +$params = uac::setDefaultStudio( $params, $user_presets ); +$params = uac::setDefaultProject( $params, $user_presets ); + +my $request = { + url => $ENV{QUERY_STRING} || '', + params => { + original => $params, + checked => check_params( $config, $params ), + }, +}; +$request = uac::prepare_request( $request, $user_presets ); +$params = $request->{params}->{checked}; + +#process header +my $headerParams = uac::set_template_permissions( $request->{permissions}, $params ); +$headerParams->{loc} = localization::get( $config, { user => $user, file => 'all,menu' } ); + +my $action = $params->{action} || ''; +if ( $action eq 'show_dates' ) { + #print "Content-type:text/html\n\n"; +} else { + template::process( $config, 'print', template::check( $config, 'default.html' ), $headerParams ); +} +return unless uac::check( $config, $params, $user_presets ) == 1; + +if ( $action eq 'show_dates' ) { + print "Content-Type:text/html\n\n"; +} else { + template::process( $config, 'print', template::check( $config, 'studio-timeslots-header.html' ), $headerParams ); +} + +if ( defined $params->{action} ) { + save_schedule( $config, $request ) if ( $params->{action} eq 'save_schedule' ); + delete_schedule( $config, $request ) if ( $params->{action} eq 'delete_schedule' ); + if ( $params->{action} eq 'show_dates' ) { + showDates( $config, $request ); + return; + } +} + +$config->{access}->{write} = 0; +showTimeslotSchedule( $config, $request ); +return; + +#insert or update a schedule and update all schedule dates +sub save_schedule { + my $config = shift; + my $request = shift; + + my $permissions = $request->{permissions}; + unless ( $permissions->{update_studio_timeslot_schedule} == 1 ) { + uac::permissions_denied('update_studio_timeslot_schedule'); + return; + } + + my $params = $request->{params}->{checked}; + + for my $attr ( 'project_id', 'studio_id', 'start', 'end', 'end_date', 'schedule_studio_id' ) { + unless ( defined $params->{$attr} ) { + uac::print_error( $attr . ' not given!' ); + return; + } + } + + my $entry = {}; + for my $attr ( 'project_id', 'start', 'end', 'end_date', 'frequency' ) { + $entry->{$attr} = $params->{$attr} if defined $params->{$attr}; + } + + #set schedule's studio to value from schedule_studio_id + $entry->{studio_id} = $params->{schedule_studio_id} if defined $params->{schedule_studio_id}; + + if ( ( $entry->{end} ne '' ) && ( $entry->{end} le $entry->{start} ) ) { + uac::print_error('start date should be before end date!'); + return; + } + + $config->{access}->{write} = 1; + if ( defined $params->{schedule_id} ) { + $entry->{schedule_id} = $params->{schedule_id}; + studio_timeslot_schedule::update( $config, $entry ); + + my $updates = studio_timeslot_dates::update( $config, $entry ); + uac::print_info("timeslot schedule saved. $updates dates scheduled"); + } else { + $entry->{schedule_id} = studio_timeslot_schedule::insert( $config, $entry ); + + my $updates = studio_timeslot_dates::update( $config, $entry ); + uac::print_info("timeslot schedule added. $updates dates added"); + } + +} + +sub delete_schedule { + my $config = shift; + my $request = shift; + + my $permissions = $request->{permissions}; + unless ( $permissions->{update_studio_timeslot_schedule} == 1 ) { + uac::permissions_denied('update_studio_timeslot_schedule'); + return; + } + + my $params = $request->{params}->{checked}; + + my $entry = {}; + for my $attr ( 'project_id', 'studio_id', 'schedule_id' ) { + if ( defined $params->{$attr} ) { + $entry->{$attr} = $params->{$attr}; + } else { + uac::print_error( $attr . ' not given!' ); + return; + } + } + + $config->{access}->{write} = 1; + $entry->{schedule_id} = $params->{schedule_id}; + studio_timeslot_schedule::delete( $config, $entry ); + studio_timeslot_dates::update( $config, $entry ); + uac::print_info("timeslot schedule deleted"); +} + +sub showTimeslotSchedule { + my $config = shift; + my $request = shift; + + $config->{access}->{write} = 0; + + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + unless ( $permissions->{read_studio_timeslot_schedule} == 1 ) { + uac::permissions_denied('read_studio_timeslot_schedule'); + return; + } + + for my $param ( 'project_id', 'studio_id' ) { + unless ( defined $params->{$param} ) { + uac::print_error("missing $param"); + return; + } + } + + #this will be updated later (especially allow_update_events) + for my $permission ( keys %{ $request->{permissions} } ) { + $params->{'allow'}->{$permission} = $request->{permissions}->{$permission}; + } + + $params->{loc} = + localization::get( $config, { user => $params->{presets}->{user}, file => 'all,studio-timeslots' } ); + + my $studio_id = $params->{studio_id}; + my $project_id = $params->{project_id}; + + #get project schedule + my $schedules = studio_timeslot_schedule::get( + $config, + { + project_id => $project_id + + # studio_id=>$studio_id + } + ); + + #list of all studios by id + my $studios = studios::get( $config, { project_id => $project_id } ); + + #remove seconds from dates + for my $schedule (@$schedules) { + $schedule->{start} =~ s/(\d\d\:\d\d)\:\d\d/$1/; + $schedule->{end} =~ s/(\d\d\:\d\d)\:\d\d/$1/; + + #insert assigned studio + for my $studio (@$studios) { + my $entry = { + id => $studio->{id}, + name => $studio->{name}, + }; + $entry->{selected} = 1 if ( $studio->{id} eq $schedule->{studio_id} ); + push @{ $schedule->{studios} }, $entry; + } + } + + my $result = { + project_id => $project_id, + studio_id => $studio_id + }; + $result->{schedule} = $schedules; + $result->{studios} = $studios; + $result->{start} = $params->{start}; + $result->{end} = $params->{end}; + $result->{end_date} = $params->{end_date}; + $result->{frequency} = $params->{frequency}; + + #remove seconds from datetimes + $result->{start} =~ s/(\d\d\:\d\d)\:\d\d/$1/ if defined $result->{start}; + $result->{end} =~ s/(\d\d\:\d\d)\:\d\d/$1/ if defined $result->{end}; + + #copy entry values to params + for my $key ( keys %$result ) { + $params->{$key} = $result->{$key}; + } + + #print '<pre>'.Dumper($params).'</pre>'; + template::process( $config, 'print', $params->{template}, $params ); +} + +sub showDates { + my $config = shift; + my $request = shift; + + $config->{access}->{write} = 0; + + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + unless ( $permissions->{read_studio_timeslot_schedule} == 1 ) { + uac::permissions_denied('read_studio_timeslot_schedule'); + return; + } + + for my $param ( 'project_id', 'studio_id' ) { + unless ( defined $params->{$param} ) { + uac::print_error("missing $param"); + return; + } + } + + #this will be updated later (especially allow_update_events) + for my $permission ( keys %{ $request->{permissions} } ) { + $params->{'allow'}->{$permission} = $request->{permissions}->{$permission}; + } + + my $studio_id = $params->{studio_id}; + my $project_id = $params->{project_id}; + + my $fromDate = $params->{show_date} . '-01-01'; + my $tillDate = $params->{show_date} . '-12-31'; + + #add timeslot dates + my $timeslot_dates = studio_timeslot_dates::get( + $config, + { + project_id => $project_id, + + # studio_id=>$studio_id, + from => $fromDate, + till => $tillDate + } + ); + + $params->{loc} = + localization::get( $config, { user => $params->{presets}->{user}, file => 'all,studio-timeslots' } ); + my $language = $params->{loc}->{region}; + + # translate weekday names to selected language + my $weekday = { + 'Mo' => $params->{loc}->{weekday_Mo}, + 'Tu' => $params->{loc}->{weekday_Tu}, + 'We' => $params->{loc}->{weekday_We}, + 'Th' => $params->{loc}->{weekday_Th}, + 'Fr' => $params->{loc}->{weekday_Fr}, + 'Sa' => $params->{loc}->{weekday_Sa}, + 'Su' => $params->{loc}->{weekday_Su}, + }; + + my $studios = studios::get( $config, { project_id => $project_id } ); + my $studio_by_id = {}; + for my $studio (@$studios) { + $studio_by_id->{ $studio->{id} } = $studio; + } + + #remove seconds from dates + for my $date (@$timeslot_dates) { + + #remove seconds from datetimes + $date->{start} =~ s/(\d\d\:\d\d)\:\d\d/$1/; + $date->{end} =~ s/(\d\d\:\d\d)\:\d\d/$1/; + + # translate weekday + if ( $language ne 'en' ) { + $date->{start_weekday} = $weekday->{ $date->{start_weekday} }; + $date->{end_weekday} = $weekday->{ $date->{end_weekday} }; + } + $date->{studio_name} = $studio_by_id->{ $date->{studio_id} }->{name}; + } + my $result = { + project_id => $project_id, + studio_id => $studio_id, + dates => $timeslot_dates + }; + + #copy entry values to params + for my $key ( keys %$result ) { + $params->{$key} = $result->{$key}; + } + + my $template = template::check( $config, 'studio-timeslot-dates' ); + template::process( $config, 'print', $template, $params ); +} + +sub check_params { + my $config = shift; + my $params = shift; + + my $checked = {}; + + #actions and roles + if ( defined $params->{action} ) { + if ( $params->{action} =~ /^(show|save_schedule|delete_schedule|show_dates)$/ ) { + $checked->{action} = $params->{action}; + } + } + + $checked->{exclude} = 0; + entry::set_numbers( $checked, $params, [ + 'id', 'project_id', 'studio_id', 'default_studio_id', 'schedule_id', 'schedule_studio_id' + ]); + + if ( ( defined $params->{show_date} ) && ( $params->{show_date} =~ /^(\d\d\d\d)/ ) ) { + $checked->{show_date} = $1; + } else { + my $date = time::date_to_array( time::time_to_date() ); + $checked->{show_date} = $date->[0]; + } + + if ( defined $checked->{studio_id} ) { + $checked->{default_studio_id} = $checked->{studio_id}; + } else { + $checked->{studio_id} = -1; + } + + $checked->{template} = template::check( $config, $params->{template}, 'studio-timeslots' ); + + entry::set_numbers( $checked, $params, ['frequency'] ); + + for my $attr ( 'start', 'end' ) { + if ( ( defined $params->{$attr} ) && ( $params->{$attr} =~ /(\d\d\d\d\-\d\d\-\d\d[ T]\d\d\:\d\d)/ ) ) { + $checked->{$attr} = $1 . ':00'; + } + } + for my $attr ('end_date') { + if ( ( defined $params->{$attr} ) && ( $params->{$attr} =~ /(\d\d\d\d\-\d\d\-\d\d)/ ) ) { + $checked->{$attr} = $1; + } + } + + return $checked; +} + diff --git a/website/agenda/planung/studio_timeslots.cgi b/website/agenda/planung/studio_timeslots.cgi deleted file mode 100755 index bb5db68..0000000 --- a/website/agenda/planung/studio_timeslots.cgi +++ /dev/null @@ -1,418 +0,0 @@ -#! /usr/bin/perl -w - -use warnings "all"; -use strict; -use Data::Dumper; - -use params; -use config; -use log; -use template; -use auth; -use uac; -use roles; -use project; -use studios; -use studio_timeslot_schedule; -use studio_timeslot_dates; -use markup; -use URI::Escape; -use Encode; -use localization; - -binmode STDOUT, ":utf8"; - -my $r = shift; -( my $cgi, my $params, my $error ) = params::get($r); - -my $config = config::get('../config/config.cgi'); -my $debug = $config->{system}->{debug}; -my ( $user, $expires ) = auth::get_user( $cgi, $config ); -return if ( ( !defined $user ) || ( $user eq '' ) ); - -my $user_presets = uac::get_user_presets( - $config, - { - user => $user, - project_id => $params->{project_id}, - studio_id => $params->{studio_id} - } -); -$params->{default_studio_id} = $user_presets->{studio_id}; -$params->{studio_id} = $params->{default_studio_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); -$params->{project_id} = $user_presets->{project_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); - -my $request = { - url => $ENV{QUERY_STRING} || '', - params => { - original => $params, - checked => check_params($params), - }, -}; -$request = uac::prepare_request( $request, $user_presets ); -log::init($request); - -$params = $request->{params}->{checked}; - -#process header -my $headerParams = uac::set_template_permissions( $request->{permissions}, $params ); -$headerParams->{loc} = localization::get( $config, { user => $user, file => 'all,menu' } ); - -my $action = $params->{action} || ''; -if ( $action eq 'show_dates' ) { - - #print "Content-type:text/html\n\n"; -} else { - template::process( 'print', template::check('default.html'), $headerParams ); -} -return unless uac::check( $config, $params, $user_presets ) == 1; - -if ( $action eq 'show_dates' ) { - print "Content-Type:text/html\n\n"; -} else { - print q{ - <script src="js/jquery-ui-timepicker.js" type="text/javascript"></script> - <link href="css/jquery-ui-timepicker.css" type="text/css" rel="stylesheet" /> - <link href="css/theme.default.css" rel="stylesheet"> - <script src="js/studio_timeslots.js" type="text/javascript"></script> - <script src="js/datetime.js" type="text/javascript"></script> - <link rel="stylesheet" href="css/studio_timeslots.css" type="text/css" /> - }; -} - -if ( defined $params->{action} ) { - save_schedule( $config, $request ) if ( $params->{action} eq 'save_schedule' ); - delete_schedule( $config, $request ) if ( $params->{action} eq 'delete_schedule' ); - if ( $params->{action} eq 'show_dates' ) { - showDates( $config, $request ); - return; - } -} - -$config->{access}->{write} = 0; -showTimeslotSchedule( $config, $request ); -return; - -#insert or update a schedule and update all schedule dates -sub save_schedule { - my $config = shift; - my $request = shift; - - my $permissions = $request->{permissions}; - unless ( $permissions->{update_studio_timeslot_schedule} == 1 ) { - uac::permissions_denied('update_studio_timeslot_schedule'); - return; - } - - #print Dumper($params); - my $params = $request->{params}->{checked}; - - for my $attr ( 'project_id', 'studio_id', 'start', 'end', 'end_date', 'schedule_studio_id' ) { - unless ( defined $params->{$attr} ) { - uac::print_error( $attr . ' not given!' ); - return; - } - } - - my $entry = {}; - for my $attr ( 'project_id', 'start', 'end', 'end_date', 'frequency' ) { - $entry->{$attr} = $params->{$attr} if ( defined $params->{$attr} ); - } - - #set schedule's studio to value from schedule_studio_id - $entry->{studio_id} = $params->{schedule_studio_id} if ( defined $params->{schedule_studio_id} ); - - if ( ( $entry->{end} ne '' ) && ( $entry->{end} le $entry->{start} ) ) { - uac::print_error('start date should be before end date!'); - return; - } - - #print Dumper($entry); - $config->{access}->{write} = 1; - if ( defined $params->{schedule_id} ) { - $entry->{schedule_id} = $params->{schedule_id}; - - #print Dumper($entry); - studio_timeslot_schedule::update( $config, $entry ); - - #my $updates=0; - #print Dumper($entry); - my $updates = studio_timeslot_dates::update( $config, $entry ); - uac::print_info("timeslot schedule saved. $updates dates scheduled"); - } else { - $entry->{schedule_id} = studio_timeslot_schedule::insert( $config, $entry ); - - #my $updates=0; - my $updates = studio_timeslot_dates::update( $config, $entry ); - uac::print_info("timeslot schedule added. $updates dates added"); - } - -} - -sub delete_schedule { - my $config = shift; - my $request = shift; - - my $permissions = $request->{permissions}; - unless ( $permissions->{update_studio_timeslot_schedule} == 1 ) { - uac::permissions_denied('update_studio_timeslot_schedule'); - return; - } - - my $params = $request->{params}->{checked}; - - my $entry = {}; - for my $attr ( 'project_id', 'studio_id', 'schedule_id' ) { - if ( defined $params->{$attr} ) { - $entry->{$attr} = $params->{$attr}; - } else { - uac::print_error( $attr . ' not given!' ); - return; - } - } - - $config->{access}->{write} = 1; - $entry->{schedule_id} = $params->{schedule_id}; - studio_timeslot_schedule::delete( $config, $entry ); - studio_timeslot_dates::update( $config, $entry ); - uac::print_info("timeslot schedule deleted"); -} - -sub showTimeslotSchedule { - my $config = shift; - my $request = shift; - - $config->{access}->{write} = 0; - - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - unless ( $permissions->{read_studio_timeslot_schedule} == 1 ) { - uac::permissions_denied('read_studio_timeslot_schedule'); - return; - } - - for my $param ( 'project_id', 'studio_id' ) { - unless ( defined $params->{$param} ) { - uac::print_error("missing $param"); - return; - } - } - - #this will be updated later (especially allow_update_events) - for my $permission ( keys %{ $request->{permissions} } ) { - $params->{'allow'}->{$permission} = $request->{permissions}->{$permission}; - } - - $params->{loc} = localization::get( $config, { user => $params->{presets}->{user}, file => 'all,studio_timeslots' } ); - - my $studio_id = $params->{studio_id}; - my $project_id = $params->{project_id}; - - #get project schedule - my $schedules = studio_timeslot_schedule::get( - $config, - { - project_id => $project_id - - # studio_id=>$studio_id - } - ); - - #list of all studios by id - my $studios = studios::get( $config, { project_id => $project_id } ); - - #remove seconds from dates - for my $schedule (@$schedules) { - $schedule->{start} =~ s/(\d\d\:\d\d)\:\d\d/$1/; - $schedule->{end} =~ s/(\d\d\:\d\d)\:\d\d/$1/; - - #insert assigned studio - for my $studio (@$studios) { - my $entry = { - id => $studio->{id}, - name => $studio->{name}, - }; - $entry->{selected} = 1 if ( $studio->{id} eq $schedule->{studio_id} ); - push @{ $schedule->{studios} }, $entry; - } - } - - my $result = { - project_id => $project_id, - studio_id => $studio_id - }; - $result->{schedule} = $schedules; - $result->{studios} = $studios; - $result->{start} = $params->{start}; - $result->{end} = $params->{end}; - $result->{end_date} = $params->{end_date}; - $result->{frequency} = $params->{frequency}; - - #remove seconds from datetimes - $result->{start} =~ s/(\d\d\:\d\d)\:\d\d/$1/ if defined $result->{start}; - $result->{end} =~ s/(\d\d\:\d\d)\:\d\d/$1/ if defined $result->{end}; - - #copy entry values to params - for my $key ( keys %$result ) { - $params->{$key} = $result->{$key}; - } - - #print '<pre>'.Dumper($params).'</pre>'; - template::process( 'print', $params->{template}, $params ); -} - -sub showDates { - my $config = shift; - my $request = shift; - - $config->{access}->{write} = 0; - - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - unless ( $permissions->{read_studio_timeslot_schedule} == 1 ) { - uac::permissions_denied('read_studio_timeslot_schedule'); - return; - } - - for my $param ( 'project_id', 'studio_id' ) { - unless ( defined $params->{$param} ) { - uac::print_error("missing $param"); - return; - } - } - - #this will be updated later (especially allow_update_events) - for my $permission ( keys %{ $request->{permissions} } ) { - $params->{'allow'}->{$permission} = $request->{permissions}->{$permission}; - } - - my $studio_id = $params->{studio_id}; - my $project_id = $params->{project_id}; - - my $fromDate = $params->{show_date} . '-01-01'; - my $tillDate = $params->{show_date} . '-12-31'; - - #add timeslot dates - my $timeslot_dates = studio_timeslot_dates::get( - $config, - { - project_id => $project_id, - - # studio_id=>$studio_id, - from => $fromDate, - till => $tillDate - } - ); - - $params->{loc} = localization::get( $config, { user => $params->{presets}->{user}, file => 'all,studio_timeslots' } ); - my $language = $params->{loc}->{region}; - - # translate weekday names to selected language - my $weekday = { - 'Mo' => $params->{loc}->{weekday_Mo}, - 'Tu' => $params->{loc}->{weekday_Tu}, - 'We' => $params->{loc}->{weekday_We}, - 'Th' => $params->{loc}->{weekday_Th}, - 'Fr' => $params->{loc}->{weekday_Fr}, - 'Sa' => $params->{loc}->{weekday_Sa}, - 'Su' => $params->{loc}->{weekday_Su}, - }; - - my $studios = studios::get( $config, { project_id => $project_id } ); - my $studio_by_id = {}; - for my $studio (@$studios) { - $studio_by_id->{ $studio->{id} } = $studio; - } - - #remove seconds from dates - for my $date (@$timeslot_dates) { - - #remove seconds from datetimes - $date->{start} =~ s/(\d\d\:\d\d)\:\d\d/$1/; - $date->{end} =~ s/(\d\d\:\d\d)\:\d\d/$1/; - - # translate weekday - if ( $language ne 'en' ) { - $date->{start_weekday} = $weekday->{ $date->{start_weekday} }; - $date->{end_weekday} = $weekday->{ $date->{end_weekday} }; - } - $date->{studio_name} = $studio_by_id->{ $date->{studio_id} }->{name}; - } - my $result = { - project_id => $project_id, - studio_id => $studio_id, - dates => $timeslot_dates - }; - - #copy entry values to params - for my $key ( keys %$result ) { - $params->{$key} = $result->{$key}; - } - - my $template = template::check('studio_timeslot_dates'); - template::process( 'print', $template, $params ); -} - -sub check_params { - my $params = shift; - - my $checked = {}; - - my $debug = $params->{debug} || ''; - if ( $debug =~ /([a-z\_\,]+)/ ) { - $debug = $1; - } - $checked->{debug} = $debug; - - #actions and roles - if ( defined $params->{action} ) { - if ( $params->{action} =~ /^(show|save_schedule|delete_schedule|show_dates)$/ ) { - $checked->{action} = $params->{action}; - } - } - - #numeric values - $checked->{exclude} = 0; - for my $param ( 'id', 'project_id', 'studio_id', 'default_studio_id', 'schedule_id', 'schedule_studio_id' ) { - if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /^\d+$/ ) ) { - $checked->{$param} = $params->{$param}; - } - } - - if ( ( defined $params->{show_date} ) && ( $params->{show_date} =~ /^(\d\d\d\d)/ ) ) { - $checked->{show_date} = $1; - } else { - my $date = time::date_to_array( time::time_to_date() ); - $checked->{show_date} = $date->[0]; - } - - if ( defined $checked->{studio_id} ) { - $checked->{default_studio_id} = $checked->{studio_id}; - } else { - $checked->{studio_id} = -1; - } - - $checked->{template} = template::check( $params->{template}, 'studio_timeslots' ); - - for my $param ('frequency') { - if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /(\d+)/ ) ) { - $checked->{$param} = $1; - } - } - - for my $attr ( 'start', 'end' ) { - if ( ( defined $params->{$attr} ) && ( $params->{$attr} =~ /(\d\d\d\d\-\d\d\-\d\d[ T]\d\d\:\d\d)/ ) ) { - $checked->{$attr} = $1 . ':00'; - } - } - for my $attr ('end_date') { - if ( ( defined $params->{$attr} ) && ( $params->{$attr} =~ /(\d\d\d\d\-\d\d\-\d\d)/ ) ) { - $checked->{$attr} = $1; - } - } - - return $checked; -} - diff --git a/website/agenda/planung/studios.cgi b/website/agenda/planung/studios.cgi index 08a3f73..f1ea19e 100755 --- a/website/agenda/planung/studios.cgi +++ b/website/agenda/planung/studios.cgi @@ -1,19 +1,22 @@ -#! /usr/bin/perl -w +#!/usr/bin/perl -use warnings "all"; use strict; +use warnings; +no warnings 'redefine'; + use Data::Dumper; -use config; -use params; -use log; -use template; -use auth; -use roles; -use uac; -use studios; -use series; -use localization; +use config(); +use entry(); +use params(); +use log(); +use template(); +use auth(); +use roles(); +use uac(); +use studios(); +use series(); +use localization(); my $r = shift; ( my $cgi, my $params, my $error ) = params::get($r); @@ -21,225 +24,215 @@ my $r = shift; my $config = config::get('../config/config.cgi'); my $debug = $config->{system}->{debug}; -my ( $user, $expires ) = auth::get_user( $cgi, $config ); +my ( $user, $expires ) = auth::get_user( $config, $params, $cgi ); return if ( $user eq '' ); -my $permissions = roles::get_user_permissions(); +my $permissions = roles::get_user_permissions($config); my $user_presets = uac::get_user_presets( - $config, - { - user => $user, - project_id => $params->{project_id}, - studio_id => $params->{studio_id} - } + $config, + { + user => $user, + project_id => $params->{project_id}, + studio_id => $params->{studio_id} + } ); $params->{default_studio_id} = $user_presets->{studio_id}; -$params->{studio_id} = $params->{default_studio_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); -$params->{project_id} = $user_presets->{project_id} - if ( ( !( defined $params->{action} ) ) || ( $params->{action} eq '' ) || ( $params->{action} eq 'login' ) ); +$params = uac::setDefaultStudio( $params, $user_presets ); +$params = uac::setDefaultProject( $params, $user_presets ); my $request = { - url => $ENV{QUERY_STRING} || '', - params => { - original => $params, - checked => check_params($params), - }, + url => $ENV{QUERY_STRING} || '', + params => { + original => $params, + checked => check_params( $config, $params ), + }, }; $request = uac::prepare_request( $request, $user_presets ); -log::init($request); - $params = $request->{params}->{checked}; #process header my $headerParams = uac::set_template_permissions( $request->{permissions}, $params ); $headerParams->{loc} = localization::get( $config, { user => $user, file => 'menu' } ); -template::process( 'print', template::check('default.html'), $headerParams ); +template::process( $config, 'print', template::check( $config, 'studios-header.html' ), $headerParams ); return unless uac::check( $config, $params, $user_presets ) == 1; -print q{ - <link rel="stylesheet" href="css/studios.css" type="text/css" /> - <script src="js/studios.js" type="text/javascript"></script> -}; - if ( defined $params->{action} ) { - save_studio( $config, $request ) if ( $params->{action} eq 'save' ); - delete_studio( $config, $request ) if ( $params->{action} eq 'delete' ); + save_studio( $config, $request ) if ( $params->{action} eq 'save' ); + delete_studio( $config, $request ) if ( $params->{action} eq 'delete' ); } $config->{access}->{write} = 0; show_studios( $config, $request ); sub delete_studio { - my $config = shift; - my $request = shift; + my $config = shift; + my $request = shift; - my $permissions = $request->{permissions}; - unless ( $permissions->{update_studio} == 1 ) { - uac::permissions_denied('update_studio'); - return; - } + my $permissions = $request->{permissions}; + unless ( $permissions->{update_studio} == 1 ) { + uac::permissions_denied('update_studio'); + return; + } - my $params = $request->{params}->{checked}; - my $columns = studios::get_columns($config); + my $params = $request->{params}->{checked}; + my $columns = studios::get_columns($config); - my $entry = {}; - for my $param ( keys %$params ) { - if ( defined $columns->{$param} ) { - $entry->{$param} = $params->{$param} || ''; - } - } + my $entry = {}; + for my $param ( keys %$params ) { + if ( exists $columns->{$param} ) { + $entry->{$param} = $params->{$param} || ''; + } + } - my $studio_id = $entry->{id} || ''; - if ( $studio_id ne '' ) { - $config->{access}->{write} = 1; + my $studio_id = $entry->{id} || ''; + if ( $studio_id ne '' ) { + $config->{access}->{write} = 1; - project::unassign_studio( - $config, - { - project_id => $params->{project_id}, - studio_id => $studio_id - } - ); + project::unassign_studio( + $config, + { + project_id => $params->{project_id}, + studio_id => $studio_id + } + ); - my $studio_assignments = project::get_studio_assignments( - $config, - { - studio_id => $studio_id - } - ); + my $studio_assignments = project::get_studio_assignments( + $config, + { + studio_id => $studio_id + } + ); - unless ( @$studio_assignments == 0 ) { - uac::print_info("Studio unassigned from project"); - uac::print_warn("Studio is assigned to other projects, so it will not be deleted"); - return undef; - } - studios::delete( $config, $entry ); - uac::print_info("Studio deleted"); - } + unless ( scalar @$studio_assignments == 0 ) { + uac::print_info("Studio unassigned from project"); + uac::print_warn("Studio is assigned to other projects, so it will not be deleted"); + return undef; + } + studios::delete( $config, $entry ); + uac::print_info("Studio deleted"); + } } sub save_studio { - my $config = shift; - my $request = shift; + my $config = shift; + my $request = shift; - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; - unless ( $permissions->{update_studio} == 1 ) { - uac::permissions_denied('update_studio'); - return; - } + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; + unless ( $permissions->{update_studio} == 1 ) { + uac::permissions_denied('update_studio'); + return; + } - #filter entry for studio columns - my $columns = studios::get_columns($config); - my $entry = {}; - for my $param ( keys %$params ) { - if ( defined $columns->{$param} ) { - $entry->{$param} = $params->{$param} || ''; - } - } + #filter entry for studio columns + my $columns = studios::get_columns($config); + my $entry = {}; + for my $param ( keys %$params ) { + if ( exists $columns->{$param} ) { + $entry->{$param} = $params->{$param} || ''; + } + } - $config->{access}->{write} = 1; - if ( ( defined $entry->{id} ) && ( $entry ne '' ) ) { - studios::update( $config, $entry ); - } else { - my $studios = studios::get( $config, { name => $entry->{name} } ); - if ( @$studios > 0 ) { - uac::print_error("studio with name '$entry->{name}' already exists"); - return; - } - $entry->{id} = studios::insert( $config, $entry ); + $config->{access}->{write} = 1; + if ( ( defined $entry->{id} ) && ( $entry ne '' ) ) { + studios::update( $config, $entry ); + } else { + my $studios = studios::get( $config, { name => $entry->{name} } ); + if ( scalar @$studios > 0 ) { + uac::print_error("studio with name '$entry->{name}' already exists"); + return; + } + $entry->{id} = studios::insert( $config, $entry ); - project::assign_studio( - $config, - { - project_id => $params->{project_id}, - studio_id => $entry->{id} - } - ); - } + project::assign_studio( + $config, + { + project_id => $params->{project_id}, + studio_id => $entry->{id} + } + ); + } - #insert series for single events (if not already existing) - my $studio_id = $entry->{id}; - my $single_series = series::get( - $config, - { - project_id => $params->{project_id}, - studio_id => $studio_id, - has_single_events => 1 - } - ); - if ( @$single_series == 0 ) { - series::insert( - $config, - { - project_id => $params->{project_id}, - studio_id => $studio_id, - has_single_events => 1, - count_episodes => 0, - series_name => '_single_' - } - ); - } + #insert series for single events (if not already existing) + my $studio_id = $entry->{id}; + my $single_series = series::get( + $config, + { + project_id => $params->{project_id}, + studio_id => $studio_id, + has_single_events => 1 + } + ); + if ( scalar @$single_series == 0 ) { + series::insert( + $config, + { + project_id => $params->{project_id}, + studio_id => $studio_id, + has_single_events => 1, + count_episodes => 0, + series_name => '_single_', + modified_by => $params->{presets}->{user} + } + ); + } - print qq{<div class="ok head">changes saved</div>}; + print qq{<div class="ok head">changes saved</div>}; } sub show_studios { - my $config = shift; - my $request = shift; + my $config = shift; + my $request = shift; - my $params = $request->{params}->{checked}; - my $permissions = $request->{permissions}; + my $params = $request->{params}->{checked}; + my $permissions = $request->{permissions}; - my $studios = studios::get( - $config, - { - project_id => $params->{project_id} - } - ); - $params->{studios} = $studios; - $params->{loc} = localization::get( $config, { user => $params->{presets}->{user}, file => 'studios' } ); - uac::set_template_permissions( $permissions, $params ); + my $studios = studios::get( + $config, + { + project_id => $params->{project_id} + } + ); - template::process( 'print', $params->{template}, $params ); + if ( $params->{setImage} ) { + for my $studio (@$studios) { + next unless $studio->{id} eq $params->{studio_id}; + $studio->{image} = $params->{setImage}; + } + } + + $params->{studios} = $studios; + $params->{loc} = localization::get( $config, { user => $params->{presets}->{user}, file => 'studios' } ); + uac::set_template_permissions( $permissions, $params ); + + template::process( $config, 'print', $params->{template}, $params ); } sub check_params { - my $params = shift; + my $config = shift; + my $params = shift; - my $checked = {}; + my $checked = {}; - #template - my $template = ''; - $template = template::check( $params->{template}, 'studios' ); - $checked->{template} = $template; + #template + my $template = ''; + $template = template::check( $config, $params->{template}, 'studios' ); + $checked->{template} = $template; - #actions - my $action = ''; - if ( defined $params->{action} ) { - if ( $params->{action} =~ /^(save|delete)$/ ) { - $checked->{action} = $params->{action}; - } - } + $checked->{action} = entry::element_of( $params->{action}, ['save', 'delete']); - for my $param ( 'name', 'description', 'location', 'stream', 'google_calendar' ) { - if ( defined $params->{$param} ) { - $checked->{$param} = $params->{$param}; - } - } + entry::set_strings( $checked, $params, [ + 'name', 'description', 'location', 'stream', 'google_calendar', 'image', 'setImage' ]); - #numeric values - for my $param ( 'project_id', 'studio_id', 'default_studio_id', 'id' ) { - if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /^\d+$/ ) ) { - $checked->{$param} = $params->{$param}; - } - } - if ( defined $checked->{studio_id} ) { - $checked->{default_studio_id} = $checked->{studio_id}; - } else { - $checked->{studio_id} = -1; - } + entry::set_numbers( $checked, $params, [ + 'project_id', 'studio_id', 'default_studio_id', 'id' + ]); - return $checked; + if ( defined $checked->{studio_id} ) { + $checked->{default_studio_id} = $checked->{studio_id}; + } else { + $checked->{studio_id} = -1; + } + + return $checked; } diff --git a/website/agenda/planung/templates/.old/.htaccess b/website/agenda/planung/templates/.old/.htaccess deleted file mode 100644 index 3a42882..0000000 --- a/website/agenda/planung/templates/.old/.htaccess +++ /dev/null @@ -1 +0,0 @@ -Deny from all diff --git a/website/agenda/planung/templates/.old/event_edit_user_content.ok.html b/website/agenda/planung/templates/.old/event_edit_user_content.ok.html deleted file mode 100644 index c3ee2ef..0000000 --- a/website/agenda/planung/templates/.old/event_edit_user_content.ok.html +++ /dev/null @@ -1,378 +0,0 @@ -<html> - -<head> - <meta http-equiv="content-type" content="text/html; charset=utf-8" /> - <title>edit event - - - - - - - - - - - - - - - -
- - - - - - -
-
-
- - - -
- -
- -
- - - - - - - - - -
- -
- - - - - - - -
-
-
-
- -
-
Event
- - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
when - - , , -
-
- start - - - duration - end -
- -
status - - checked="checked" value="1"> live - - - - checked="checked" value="1"> published - - - - checked="checked" value="1"> preproduced - - - - checked="checked" value="1"> archived - - - - checked="checked" value="1"> rerun - - - - checked="checked" value="1"> no sync - -
episode
- -
content
- - - - - - style="display:none" > - - - - - - - - - -
excerpt
description - -
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
title - - - - - - - - - - - - - -
excerpt - - - - - -
user excerpt - - - - - -
current topics - - - - - -
content - - - - - -
- image - - - - - - - -
- - - - - -
-
- - - - - - - - - - - - - - - - - - -
-
- -
-
- - -
last modified at by .
-
- -
- -
-
- - - diff --git a/website/agenda/planung/templates/.old/event_manager.html b/website/agenda/planung/templates/.old/event_manager.html deleted file mode 100644 index 5cc9c36..0000000 --- a/website/agenda/planung/templates/.old/event_manager.html +++ /dev/null @@ -1,152 +0,0 @@ - - -

Sendungen verwalten

- - - -projects: - - - | - - - - - - -
-
- - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ProgammWochentagDatumStartEndeBildSendereiheTitelAuszug
- - - - - - - - - - - - - - - - - - -

Kommentare , - mehr... - - -

- diff --git a/website/agenda/planung/templates/.old/menu.html b/website/agenda/planung/templates/.old/menu.html deleted file mode 100644 index 8960289..0000000 --- a/website/agenda/planung/templates/.old/menu.html +++ /dev/null @@ -1,283 +0,0 @@ - - - -
-
- - -
- -
-
- diff --git a/website/agenda/planung/templates/.old/select_studio.html b/website/agenda/planung/templates/.old/select_studio.html deleted file mode 100644 index 85cb716..0000000 --- a/website/agenda/planung/templates/.old/select_studio.html +++ /dev/null @@ -1,24 +0,0 @@ - -
- - logout -
- diff --git a/website/agenda/planung/templates/ajax_header.html b/website/agenda/planung/templates/ajax-header.html similarity index 100% rename from website/agenda/planung/templates/ajax_header.html rename to website/agenda/planung/templates/ajax-header.html diff --git a/website/agenda/planung/templates/assign-series-header.html b/website/agenda/planung/templates/assign-series-header.html new file mode 100644 index 0000000..a54bada --- /dev/null +++ b/website/agenda/planung/templates/assign-series-header.html @@ -0,0 +1,5 @@ + + + + + diff --git a/website/agenda/planung/templates/assign_series.html b/website/agenda/planung/templates/assign-series.html similarity index 54% rename from website/agenda/planung/templates/assign_series.html rename to website/agenda/planung/templates/assign-series.html index 4784d38..d112a8a 100644 --- a/website/agenda/planung/templates/assign_series.html +++ b/website/agenda/planung/templates/assign-series.html @@ -15,10 +15,23 @@ if (series_id=='')return false; $('#assignments_form input[name="series_id"]').val(series_id); - //console.log(project_id+" "+studio_id+" "+series_id); + $('#assignments_form input[name="action"]').val("assign_series"); + //var url="assign-series.cgi?project_id="+project_id+'&studio_id='+studio_id+'&series_id='+series_id+'&action=assign_series'; + //console.log("url:"+url); + $('#assignments_form').submit(); + return false; + } - var url="assign_series.cgi?project_id="+project_id+'&studio_id='+studio_id+'&series_id='+series_id+'&action=assign_series'; - //console.log(url); + function unassign_series(project_id, studio_id, series_id){ + if (project_id=='')return false; + if (studio_id=='')return false; + if (series_id=='')return false; + + $('#assignments_form input[name="series_id"]').val(series_id); + $('#assignments_form input[name="action"]').val("unassign_series"); + alert("unassign"); + //var url="assign-series.cgi?project_id="+project_id+'&studio_id='+studio_id+'&series_id='+series_id+'&action=unassign_series'; + //console.log("url:"+url); $('#assignments_form').submit(); return false; } @@ -31,7 +44,7 @@ } - assign series to project and studio + assign and unassign series to project and studio
@@ -41,24 +54,27 @@ -
+ - +
- + diff --git a/website/agenda/planung/templates/assignments-header.html b/website/agenda/planung/templates/assignments-header.html new file mode 100644 index 0000000..a54bada --- /dev/null +++ b/website/agenda/planung/templates/assignments-header.html @@ -0,0 +1,5 @@ + + + + + diff --git a/website/agenda/planung/templates/assignments.html b/website/agenda/planung/templates/assignments.html index 6282cb7..b94aadb 100644 --- a/website/agenda/planung/templates/assignments.html +++ b/website/agenda/planung/templates/assignments.html @@ -1,17 +1,10 @@ - - - - - - - + + diff --git a/website/agenda/planung/templates/autotext.json b/website/agenda/planung/templates/autotext.json index 4801981..8f37026 100644 --- a/website/agenda/planung/templates/autotext.json +++ b/website/agenda/planung/templates/autotext.json @@ -1,5 +1,4 @@ -Cache-Control: max-age=3600, must-revalidate -Content-type:application/json; charset=UTF-8; +Content-type:application/json; charset=UTF-8; [ {"id":"", "label":"", "value":""} , diff --git a/website/agenda/planung/templates/calendar-header.html b/website/agenda/planung/templates/calendar-header.html new file mode 100644 index 0000000..1eb1675 --- /dev/null +++ b/website/agenda/planung/templates/calendar-header.html @@ -0,0 +1,6 @@ + + + + + + diff --git a/website/agenda/planung/templates/change_password.html b/website/agenda/planung/templates/change-password.html similarity index 100% rename from website/agenda/planung/templates/change_password.html rename to website/agenda/planung/templates/change-password.html diff --git a/website/agenda/planung/templates/comment-header.html b/website/agenda/planung/templates/comment-header.html new file mode 100644 index 0000000..d40ecd7 --- /dev/null +++ b/website/agenda/planung/templates/comment-header.html @@ -0,0 +1,2 @@ + + diff --git a/website/agenda/planung/templates/comments.html b/website/agenda/planung/templates/comments.html index 1aefaf7..fd483f4 100644 --- a/website/agenda/planung/templates/comments.html +++ b/website/agenda/planung/templates/comments.html @@ -4,20 +4,12 @@ <TMPL_VAR .doc.title> - - + - @@ -64,7 +53,7 @@
diff --git a/website/agenda/planung/templates/create-events-header.html b/website/agenda/planung/templates/create-events-header.html new file mode 100644 index 0000000..a54bada --- /dev/null +++ b/website/agenda/planung/templates/create-events-header.html @@ -0,0 +1,5 @@ + + + + + diff --git a/website/agenda/planung/templates/create-events.html b/website/agenda/planung/templates/create-events.html new file mode 100644 index 0000000..a1320dd --- /dev/null +++ b/website/agenda/planung/templates/create-events.html @@ -0,0 +1,51 @@ + + +

create events from schedule

+
+
+ schedule events by + + + + + + + + + +
+
+ + events from till : +

+ +
- +
+ + + + + + + + + + + + + missing permission to read events + diff --git a/website/agenda/planung/templates/create_events.html b/website/agenda/planung/templates/create_events.html deleted file mode 100644 index 4784d38..0000000 --- a/website/agenda/planung/templates/create_events.html +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - assign series to project and studio - - -
-
- -
Series
- - -
- - - - - - -
-
- - - - - -
diff --git a/website/agenda/planung/templates/default.html b/website/agenda/planung/templates/default.html index a1abe2e..455a3ab 100644 --- a/website/agenda/planung/templates/default.html +++ b/website/agenda/planung/templates/default.html @@ -1,68 +1,88 @@ -
-
+ + +
diff --git a/website/agenda/planung/templates/edit_comment.html b/website/agenda/planung/templates/edit-comment.html similarity index 85% rename from website/agenda/planung/templates/edit_comment.html rename to website/agenda/planung/templates/edit-comment.html index f55ee52..8caaf57 100644 --- a/website/agenda/planung/templates/edit_comment.html +++ b/website/agenda/planung/templates/edit-comment.html @@ -19,8 +19,8 @@
- - + + @@ -287,18 +311,18 @@ @@ -334,11 +358,16 @@ - - checked="checked" value="1"value="0" > - - - + title=""> + + checked="checked" value="1" value="0" + > + + + + + checked="checked" value="1"value="0" > @@ -384,9 +413,9 @@
@@ -29,13 +29,13 @@ diff --git a/website/agenda/planung/templates/edit_event.html b/website/agenda/planung/templates/edit-event.html similarity index 67% rename from website/agenda/planung/templates/edit_event.html rename to website/agenda/planung/templates/edit-event.html index d659007..d0b71ac 100644 --- a/website/agenda/planung/templates/edit_event.html +++ b/website/agenda/planung/templates/edit-event.html @@ -3,23 +3,22 @@ <TMPL_VAR .doc.title> - + - - - + - + - + - -
+
@@ -62,8 +65,10 @@
- @@ -78,11 +83,16 @@ + class="text" + onclick="load('series.cgi?project_id=&studio_id=&series_id=&start=&exclude=1&show_hint_to_add_schedule=1#tabs-schedule')" + > - + @@ -90,18 +100,22 @@ - + -
+ - - +
@@ -112,9 +126,13 @@ - + + +
- -
- -
- - + -
- + : - + : - + :
description - +
-
+
@@ -426,7 +455,7 @@ - + @@ -437,7 +466,7 @@ - + @@ -449,12 +478,13 @@ - - + + @@ -485,50 +515,57 @@ + + + + + + + + + + + + - - - - -
-
- - - - - - - - - - - - - - - - - - -
-
+ + + +
+ + + + + + + + + + + + + +
+ +
-
- +
+
@@ -538,10 +575,7 @@
.
-
- -
- + diff --git a/website/agenda/planung/templates/edit-image.html b/website/agenda/planung/templates/edit-image.html new file mode 100644 index 0000000..9a63fd5 --- /dev/null +++ b/website/agenda/planung/templates/edit-image.html @@ -0,0 +1,77 @@ + + + + + +found no image + + + + +
+ + + + + + + +
+ +
+ + +
+
+ +
+
+ +
+ + + + checked="checked" value="1"value="0" />
+ +
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + +
+
+
+
+ + + + + diff --git a/website/agenda/planung/templates/edit-series.html b/website/agenda/planung/templates/edit-series.html new file mode 100644 index 0000000..f57135b --- /dev/null +++ b/website/agenda/planung/templates/edit-series.html @@ -0,0 +1,631 @@ + + + + + + + + + +
+ + + + + - + +
+ + +
+
+ + + + + +
+ + + + +
+
+ + + + + + +
+ + + + +
+
+ +
+ +
+ +
+
    + +
  • +
    +
  • +
  • + +
  • + + +
  • +
    +
    +
+ + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + + + +
value="1" checked="checked" value="0" >
value="1" checked="checked" value="0" >
+ +
+ +
+ + + + +
+
+
+
+
+ + +
+ + + +
+ +
+
+ + + + + +
+
+ +
+ +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+
+ +
+ +

+ +
+ +

+ +
+
+
+
+
+ +
+
+ + + + +
+
+ +
+ +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+
+ +
+ + +
+
+ + +
+
+
+
+
+
+ + +
+ + + + + + + + + + + + class="exclude" > + + + + + + +
+
+
+ + +
+ + + + + onclick="edit_event('','','','','hide_series')" + + > + + + + + + + + + + + + + + + +
-
+ +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
+ + + +
+
+ + + + + + + + +
+
+
+
+
+ + + + + +
+
+
+
+
+ +
+
.
+ + + + + + diff --git a/website/agenda/planung/templates/edit_user_roles.html b/website/agenda/planung/templates/edit-user-roles.html similarity index 91% rename from website/agenda/planung/templates/edit_user_roles.html rename to website/agenda/planung/templates/edit-user-roles.html index 8f15e19..485e1cb 100644 --- a/website/agenda/planung/templates/edit_user_roles.html +++ b/website/agenda/planung/templates/edit-user-roles.html @@ -60,9 +60,9 @@
-
+
name
 
full name
 
password
 
@@ -77,7 +77,7 @@
password
email
- +
@@ -88,7 +88,7 @@
- +
+ diff --git a/website/agenda/planung/templates/upload_audio_recordings.html b/website/agenda/planung/templates/upload-audio-recordings.html similarity index 80% rename from website/agenda/planung/templates/upload_audio_recordings.html rename to website/agenda/planung/templates/upload-audio-recordings.html index ccda0bf..be8758f 100644 --- a/website/agenda/planung/templates/upload_audio_recordings.html +++ b/website/agenda/planung/templates/upload-audio-recordings.html @@ -5,7 +5,7 @@

,
-
+

@@ -18,9 +18,15 @@ @@ -34,17 +40,17 @@ Datei - - + + - + - " + " @@ -58,6 +64,8 @@ action name + uploaded by + uploaded at size in bytes event duration in seconds audio duration in seconds @@ -65,22 +73,22 @@ RMS R processed mastered - uploaded by - uploaded at + modified at - - + + - - - - - - - + + + + + + + +
@@ -116,7 +124,6 @@ --> -
- + diff --git a/website/agenda/planung/templates/user-active.html b/website/agenda/planung/templates/user-active.html new file mode 100644 index 0000000..98e7889 --- /dev/null +++ b/website/agenda/planung/templates/user-active.html @@ -0,0 +1,65 @@ + + + + + + +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + diff --git a/website/agenda/planung/templates/user-settings.html b/website/agenda/planung/templates/user-settings.html new file mode 100644 index 0000000..ce15608 --- /dev/null +++ b/website/agenda/planung/templates/user-settings.html @@ -0,0 +1,155 @@ + + + + +

+ +

+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + +
:
+ +
+ +
+ +
+ + + + +
+ +
+ + + + +
+
+ +
+

+ +

+ +
+ + + + + + + + + + + + +
+ +
+
+ + + diff --git a/website/agenda/planung/templates/user_stats.html b/website/agenda/planung/templates/user-stats.html similarity index 63% rename from website/agenda/planung/templates/user_stats.html rename to website/agenda/planung/templates/user-stats.html index cd08cc9..b855617 100644 --- a/website/agenda/planung/templates/user_stats.html +++ b/website/agenda/planung/templates/user-stats.html @@ -1,6 +1,4 @@ - - - - - -

- - -
- - - - - - - - - - - - - - - - - - -
- -
- -
:
- -
- - - -
- -
- - - - -
- - -

- -
- - - - - - -
- -
- - - diff --git a/website/agenda/planung/templates/users.html b/website/agenda/planung/templates/users.html index a39b604..9d2a223 100644 --- a/website/agenda/planung/templates/users.html +++ b/website/agenda/planung/templates/users.html @@ -7,14 +7,6 @@ color:#555; } -#content div.user{ - border:1px solid gray; - border-radius:1em; - margin:1em; - width:30em; - float:left; -} - #content .disabled{ color:#999; } @@ -82,7 +74,6 @@ } return false; } -

@@ -90,8 +81,8 @@
- -