diff --git a/.gitignore b/.gitignore index 0e47aef..b105c66 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ lutim.db script/hypnotoad.pid local/* files/* +templates/data.html.ep diff --git a/README.md b/README.md index 6f50e55..156fc80 100644 --- a/README.md +++ b/README.md @@ -107,7 +107,7 @@ vim de.pm There's just a few sentences, so it will be quick to translate. Please consider to send me you language file in order to help the other users :smile:. ##Others projects dependancies -LUTIm is written in Perl with the Mojolicious framework, uses the Twitter bootstrap framework to look not too ugly, JQuery and JQuery File Uploader () to add some modernity. +LUTIm is written in Perl with the [Mojolicious](http://mojolicio.us) framework, uses the [Twitter bootstrap](http://getbootstrap.com) framework to look not too ugly, [JQuery](http://jquery.com) and [JQuery File Uploader](https://github.com/danielm/uploader/) (slightly modified) to add some modernity, [Raphaël](http://raphaeljs.com/) and [SimpleGraph](http://benaskins.github.io/simplegraph/) for stats graphs. ##Official instance You can see it working at http://lut.im. diff --git a/bootstrap-config.json b/bootstrap-config.json index f8d0d56..c8fa21f 100644 --- a/bootstrap-config.json +++ b/bootstrap-config.json @@ -362,6 +362,7 @@ "css": [ "print.less", "type.less", + "tables.less", "forms.less", "buttons.less", "input-groups.less", diff --git a/cpanfile b/cpanfile index d2361c8..469ce2c 100644 --- a/cpanfile +++ b/cpanfile @@ -4,3 +4,4 @@ requires 'Mojolicious::Plugin::I18N'; requires 'ORLite'; requires 'File::Type'; requires 'Text::Unidecode'; +requires 'DateTime'; diff --git a/cpanfile.snapshot b/cpanfile.snapshot index 6a8fe88..5a2ea6b 100644 --- a/cpanfile.snapshot +++ b/cpanfile.snapshot @@ -1,5 +1,31 @@ # carton snapshot format: version 1.0 DISTRIBUTIONS + Class-Load-0.21 + pathname: E/ET/ETHER/Class-Load-0.21.tar.gz + provides: + Class::Load 0.21 + Class::Load::PP 0.21 + requirements: + Carp 0 + Data::OptList 0 + Exporter 0 + ExtUtils::MakeMaker 6.30 + Module::Build::Tiny 0.034 + Module::Implementation 0.04 + Module::Runtime 0.012 + Package::Stash 0.14 + Scalar::Util 0 + Try::Tiny 0 + base 0 + perl 5.008 + strict 0 + warnings 0 + Class-Singleton-1.4 + pathname: A/AB/ABW/Class-Singleton-1.4.tar.gz + provides: + Class::Singleton 1.4 + requirements: + ExtUtils::MakeMaker 0 DBD-SQLite-1.40 pathname: I/IS/ISHIGAKI/DBD-SQLite-1.40.tar.gz provides: @@ -111,6 +137,17 @@ DISTRIBUTIONS ExtUtils::MakeMaker 6.48 Test::Simple 0.90 perl 5.008 + Data-OptList-0.109 + pathname: R/RJ/RJBS/Data-OptList-0.109.tar.gz + provides: + Data::OptList 0.109 + requirements: + ExtUtils::MakeMaker 6.30 + List::Util 0 + Params::Util 0 + Sub::Install 0.921 + strict 0 + warnings 0 Data-Validate-Domain-0.10 pathname: N/NE/NEELY/Data-Validate-Domain-0.10.tar.gz provides: @@ -138,6 +175,996 @@ DISTRIBUTIONS Data::Validate::Domain 0 Data::Validate::IP 0 ExtUtils::MakeMaker 0 + DateTime-1.07 + pathname: D/DR/DROLSKY/DateTime-1.07.tar.gz + provides: + DateTime 1.07 + DateTime::Duration 1.07 + DateTime::Helpers 1.07 + DateTime::Infinite 1.07 + DateTime::Infinite::Future 1.07 + DateTime::Infinite::Past 1.07 + DateTime::LeapSecond 1.07 + inc::MyModuleBuild undef + requirements: + Carp 0 + DateTime::Locale 0.41 + DateTime::TimeZone 1.09 + ExtUtils::CBuilder 0 + Module::Build 0.3601 + POSIX 0 + Params::Validate 0.76 + Scalar::Util 0 + Try::Tiny 0 + XSLoader 0 + base 0 + constant 0 + integer 0 + overload 0 + perl 5.008001 + strict 0 + vars 0 + warnings 0 + DateTime-Locale-0.45 + pathname: D/DR/DROLSKY/DateTime-Locale-0.45.tar.gz + provides: + DateTime::Locale 0.45 + DateTime::Locale::Base undef + DateTime::Locale::Catalog undef + DateTime::Locale::aa undef + DateTime::Locale::aa_DJ undef + DateTime::Locale::aa_ER undef + DateTime::Locale::aa_ER_SAAHO undef + DateTime::Locale::aa_ET undef + DateTime::Locale::af undef + DateTime::Locale::af_NA undef + DateTime::Locale::af_ZA undef + DateTime::Locale::ak undef + DateTime::Locale::ak_GH undef + DateTime::Locale::am undef + DateTime::Locale::am_ET undef + DateTime::Locale::ar undef + DateTime::Locale::ar_AE undef + DateTime::Locale::ar_BH undef + DateTime::Locale::ar_DZ undef + DateTime::Locale::ar_EG undef + DateTime::Locale::ar_IQ undef + DateTime::Locale::ar_JO undef + DateTime::Locale::ar_KW undef + DateTime::Locale::ar_LB undef + DateTime::Locale::ar_LY undef + DateTime::Locale::ar_MA undef + DateTime::Locale::ar_OM undef + DateTime::Locale::ar_QA undef + DateTime::Locale::ar_SA undef + DateTime::Locale::ar_SD undef + DateTime::Locale::ar_SY undef + DateTime::Locale::ar_TN undef + DateTime::Locale::ar_YE undef + DateTime::Locale::as undef + DateTime::Locale::as_IN undef + DateTime::Locale::az undef + DateTime::Locale::az_AZ undef + DateTime::Locale::az_Cyrl undef + DateTime::Locale::az_Cyrl_AZ undef + DateTime::Locale::az_Latn undef + DateTime::Locale::az_Latn_AZ undef + DateTime::Locale::be undef + DateTime::Locale::be_BY undef + DateTime::Locale::bg undef + DateTime::Locale::bg_BG undef + DateTime::Locale::bn undef + DateTime::Locale::bn_BD undef + DateTime::Locale::bn_IN undef + DateTime::Locale::bo undef + DateTime::Locale::bo_CN undef + DateTime::Locale::bo_IN undef + DateTime::Locale::bs undef + DateTime::Locale::bs_BA undef + DateTime::Locale::byn undef + DateTime::Locale::byn_ER undef + DateTime::Locale::ca undef + DateTime::Locale::ca_ES undef + DateTime::Locale::cch undef + DateTime::Locale::cch_NG undef + DateTime::Locale::cop undef + DateTime::Locale::cs undef + DateTime::Locale::cs_CZ undef + DateTime::Locale::cy undef + DateTime::Locale::cy_GB undef + DateTime::Locale::da undef + DateTime::Locale::da_DK undef + DateTime::Locale::de undef + DateTime::Locale::de_AT undef + DateTime::Locale::de_BE undef + DateTime::Locale::de_CH undef + DateTime::Locale::de_DE undef + DateTime::Locale::de_LI undef + DateTime::Locale::de_LU undef + DateTime::Locale::dv undef + DateTime::Locale::dv_MV undef + DateTime::Locale::dz undef + DateTime::Locale::dz_BT undef + DateTime::Locale::ee undef + DateTime::Locale::ee_GH undef + DateTime::Locale::ee_TG undef + DateTime::Locale::el undef + DateTime::Locale::el_CY undef + DateTime::Locale::el_GR undef + DateTime::Locale::el_POLYTON undef + DateTime::Locale::en undef + DateTime::Locale::en_AS undef + DateTime::Locale::en_AU undef + DateTime::Locale::en_BE undef + DateTime::Locale::en_BW undef + DateTime::Locale::en_BZ undef + DateTime::Locale::en_CA undef + DateTime::Locale::en_Dsrt undef + DateTime::Locale::en_Dsrt_US undef + DateTime::Locale::en_GB undef + DateTime::Locale::en_GU undef + DateTime::Locale::en_HK undef + DateTime::Locale::en_IE undef + DateTime::Locale::en_IN undef + DateTime::Locale::en_JM undef + DateTime::Locale::en_MH undef + DateTime::Locale::en_MP undef + DateTime::Locale::en_MT undef + DateTime::Locale::en_NA undef + DateTime::Locale::en_NZ undef + DateTime::Locale::en_PH undef + DateTime::Locale::en_PK undef + DateTime::Locale::en_SG undef + DateTime::Locale::en_Shaw undef + DateTime::Locale::en_TT undef + DateTime::Locale::en_UM undef + DateTime::Locale::en_US undef + DateTime::Locale::en_US_POSIX undef + DateTime::Locale::en_VI undef + DateTime::Locale::en_ZA undef + DateTime::Locale::en_ZW undef + DateTime::Locale::eo undef + DateTime::Locale::es undef + DateTime::Locale::es_AR undef + DateTime::Locale::es_BO undef + DateTime::Locale::es_CL undef + DateTime::Locale::es_CO undef + DateTime::Locale::es_CR undef + DateTime::Locale::es_DO undef + DateTime::Locale::es_EC undef + DateTime::Locale::es_ES undef + DateTime::Locale::es_GT undef + DateTime::Locale::es_HN undef + DateTime::Locale::es_MX undef + DateTime::Locale::es_NI undef + DateTime::Locale::es_PA undef + DateTime::Locale::es_PE undef + DateTime::Locale::es_PR undef + DateTime::Locale::es_PY undef + DateTime::Locale::es_SV undef + DateTime::Locale::es_US undef + DateTime::Locale::es_UY undef + DateTime::Locale::es_VE undef + DateTime::Locale::et undef + DateTime::Locale::et_EE undef + DateTime::Locale::eu undef + DateTime::Locale::eu_ES undef + DateTime::Locale::fa undef + DateTime::Locale::fa_AF undef + DateTime::Locale::fa_IR undef + DateTime::Locale::fi undef + DateTime::Locale::fi_FI undef + DateTime::Locale::fil undef + DateTime::Locale::fil_PH undef + DateTime::Locale::fo undef + DateTime::Locale::fo_FO undef + DateTime::Locale::fr undef + DateTime::Locale::fr_BE undef + DateTime::Locale::fr_CA undef + DateTime::Locale::fr_CH undef + DateTime::Locale::fr_FR undef + DateTime::Locale::fr_LU undef + DateTime::Locale::fr_MC undef + DateTime::Locale::fr_SN undef + DateTime::Locale::fur undef + DateTime::Locale::fur_IT undef + DateTime::Locale::ga undef + DateTime::Locale::ga_IE undef + DateTime::Locale::gaa undef + DateTime::Locale::gaa_GH undef + DateTime::Locale::gez undef + DateTime::Locale::gez_ER undef + DateTime::Locale::gez_ET undef + DateTime::Locale::gl undef + DateTime::Locale::gl_ES undef + DateTime::Locale::gsw undef + DateTime::Locale::gsw_CH undef + DateTime::Locale::gu undef + DateTime::Locale::gu_IN undef + DateTime::Locale::gv undef + DateTime::Locale::gv_GB undef + DateTime::Locale::ha undef + DateTime::Locale::ha_Arab undef + DateTime::Locale::ha_Arab_NG undef + DateTime::Locale::ha_Arab_SD undef + DateTime::Locale::ha_GH undef + DateTime::Locale::ha_Latn undef + DateTime::Locale::ha_Latn_GH undef + DateTime::Locale::ha_Latn_NE undef + DateTime::Locale::ha_Latn_NG undef + DateTime::Locale::ha_NE undef + DateTime::Locale::ha_NG undef + DateTime::Locale::ha_SD undef + DateTime::Locale::haw undef + DateTime::Locale::haw_US undef + DateTime::Locale::he undef + DateTime::Locale::he_IL undef + DateTime::Locale::hi undef + DateTime::Locale::hi_IN undef + DateTime::Locale::hr undef + DateTime::Locale::hr_HR undef + DateTime::Locale::hu undef + DateTime::Locale::hu_HU undef + DateTime::Locale::hy undef + DateTime::Locale::hy_AM undef + DateTime::Locale::hy_AM_REVISED undef + DateTime::Locale::ia undef + DateTime::Locale::id undef + DateTime::Locale::id_ID undef + DateTime::Locale::ig undef + DateTime::Locale::ig_NG undef + DateTime::Locale::ii undef + DateTime::Locale::ii_CN undef + DateTime::Locale::is undef + DateTime::Locale::is_IS undef + DateTime::Locale::it undef + DateTime::Locale::it_CH undef + DateTime::Locale::it_IT undef + DateTime::Locale::iu undef + DateTime::Locale::ja undef + DateTime::Locale::ja_JP undef + DateTime::Locale::ka undef + DateTime::Locale::ka_GE undef + DateTime::Locale::kaj undef + DateTime::Locale::kaj_NG undef + DateTime::Locale::kam undef + DateTime::Locale::kam_KE undef + DateTime::Locale::kcg undef + DateTime::Locale::kcg_NG undef + DateTime::Locale::kfo undef + DateTime::Locale::kfo_CI undef + DateTime::Locale::kk undef + DateTime::Locale::kk_Cyrl undef + DateTime::Locale::kk_Cyrl_KZ undef + DateTime::Locale::kk_KZ undef + DateTime::Locale::kl undef + DateTime::Locale::kl_GL undef + DateTime::Locale::km undef + DateTime::Locale::km_KH undef + DateTime::Locale::kn undef + DateTime::Locale::kn_IN undef + DateTime::Locale::ko undef + DateTime::Locale::ko_KR undef + DateTime::Locale::kok undef + DateTime::Locale::kok_IN undef + DateTime::Locale::kpe undef + DateTime::Locale::kpe_GN undef + DateTime::Locale::kpe_LR undef + DateTime::Locale::ku undef + DateTime::Locale::ku_Arab undef + DateTime::Locale::ku_Arab_IQ undef + DateTime::Locale::ku_Arab_IR undef + DateTime::Locale::ku_Arab_SY undef + DateTime::Locale::ku_IQ undef + DateTime::Locale::ku_IR undef + DateTime::Locale::ku_Latn undef + DateTime::Locale::ku_Latn_TR undef + DateTime::Locale::ku_SY undef + DateTime::Locale::ku_TR undef + DateTime::Locale::kw undef + DateTime::Locale::kw_GB undef + DateTime::Locale::ky undef + DateTime::Locale::ky_KG undef + DateTime::Locale::ln undef + DateTime::Locale::ln_CD undef + DateTime::Locale::ln_CG undef + DateTime::Locale::lo undef + DateTime::Locale::lo_LA undef + DateTime::Locale::lt undef + DateTime::Locale::lt_LT undef + DateTime::Locale::lv undef + DateTime::Locale::lv_LV undef + DateTime::Locale::mk undef + DateTime::Locale::mk_MK undef + DateTime::Locale::ml undef + DateTime::Locale::ml_IN undef + DateTime::Locale::mn undef + DateTime::Locale::mn_CN undef + DateTime::Locale::mn_Cyrl undef + DateTime::Locale::mn_Cyrl_MN undef + DateTime::Locale::mn_MN undef + DateTime::Locale::mn_Mong undef + DateTime::Locale::mn_Mong_CN undef + DateTime::Locale::mo undef + DateTime::Locale::mr undef + DateTime::Locale::mr_IN undef + DateTime::Locale::ms undef + DateTime::Locale::ms_BN undef + DateTime::Locale::ms_MY undef + DateTime::Locale::mt undef + DateTime::Locale::mt_MT undef + DateTime::Locale::my undef + DateTime::Locale::my_MM undef + DateTime::Locale::nb undef + DateTime::Locale::nb_NO undef + DateTime::Locale::nds undef + DateTime::Locale::nds_DE undef + DateTime::Locale::ne undef + DateTime::Locale::ne_IN undef + DateTime::Locale::ne_NP undef + DateTime::Locale::nl undef + DateTime::Locale::nl_BE undef + DateTime::Locale::nl_NL undef + DateTime::Locale::nn undef + DateTime::Locale::nn_NO undef + DateTime::Locale::no undef + DateTime::Locale::nr undef + DateTime::Locale::nr_ZA undef + DateTime::Locale::nso undef + DateTime::Locale::nso_ZA undef + DateTime::Locale::ny undef + DateTime::Locale::ny_MW undef + DateTime::Locale::oc undef + DateTime::Locale::oc_FR undef + DateTime::Locale::om undef + DateTime::Locale::om_ET undef + DateTime::Locale::om_KE undef + DateTime::Locale::or undef + DateTime::Locale::or_IN undef + DateTime::Locale::pa undef + DateTime::Locale::pa_Arab undef + DateTime::Locale::pa_Arab_PK undef + DateTime::Locale::pa_Guru undef + DateTime::Locale::pa_Guru_IN undef + DateTime::Locale::pa_IN undef + DateTime::Locale::pa_PK undef + DateTime::Locale::pl undef + DateTime::Locale::pl_PL undef + DateTime::Locale::ps undef + DateTime::Locale::ps_AF undef + DateTime::Locale::pt undef + DateTime::Locale::pt_BR undef + DateTime::Locale::pt_PT undef + DateTime::Locale::ro undef + DateTime::Locale::ro_MD undef + DateTime::Locale::ro_RO undef + DateTime::Locale::root undef + DateTime::Locale::ru undef + DateTime::Locale::ru_RU undef + DateTime::Locale::ru_UA undef + DateTime::Locale::rw undef + DateTime::Locale::rw_RW undef + DateTime::Locale::sa undef + DateTime::Locale::sa_IN undef + DateTime::Locale::se undef + DateTime::Locale::se_FI undef + DateTime::Locale::se_NO undef + DateTime::Locale::sh undef + DateTime::Locale::sh_BA undef + DateTime::Locale::sh_CS undef + DateTime::Locale::sh_YU undef + DateTime::Locale::si undef + DateTime::Locale::si_LK undef + DateTime::Locale::sid undef + DateTime::Locale::sid_ET undef + DateTime::Locale::sk undef + DateTime::Locale::sk_SK undef + DateTime::Locale::sl undef + DateTime::Locale::sl_SI undef + DateTime::Locale::so undef + DateTime::Locale::so_DJ undef + DateTime::Locale::so_ET undef + DateTime::Locale::so_KE undef + DateTime::Locale::so_SO undef + DateTime::Locale::sq undef + DateTime::Locale::sq_AL undef + DateTime::Locale::sr undef + DateTime::Locale::sr_BA undef + DateTime::Locale::sr_CS undef + DateTime::Locale::sr_Cyrl undef + DateTime::Locale::sr_Cyrl_BA undef + DateTime::Locale::sr_Cyrl_CS undef + DateTime::Locale::sr_Cyrl_ME undef + DateTime::Locale::sr_Cyrl_RS undef + DateTime::Locale::sr_Cyrl_YU undef + DateTime::Locale::sr_Latn undef + DateTime::Locale::sr_Latn_BA undef + DateTime::Locale::sr_Latn_CS undef + DateTime::Locale::sr_Latn_ME undef + DateTime::Locale::sr_Latn_RS undef + DateTime::Locale::sr_Latn_YU undef + DateTime::Locale::sr_ME undef + DateTime::Locale::sr_RS undef + DateTime::Locale::sr_YU undef + DateTime::Locale::ss undef + DateTime::Locale::ss_SZ undef + DateTime::Locale::ss_ZA undef + DateTime::Locale::st undef + DateTime::Locale::st_LS undef + DateTime::Locale::st_ZA undef + DateTime::Locale::sv undef + DateTime::Locale::sv_FI undef + DateTime::Locale::sv_SE undef + DateTime::Locale::sw undef + DateTime::Locale::sw_KE undef + DateTime::Locale::sw_TZ undef + DateTime::Locale::syr undef + DateTime::Locale::syr_SY undef + DateTime::Locale::ta undef + DateTime::Locale::ta_IN undef + DateTime::Locale::te undef + DateTime::Locale::te_IN undef + DateTime::Locale::tg undef + DateTime::Locale::tg_Cyrl undef + DateTime::Locale::tg_Cyrl_TJ undef + DateTime::Locale::tg_TJ undef + DateTime::Locale::th undef + DateTime::Locale::th_TH undef + DateTime::Locale::ti undef + DateTime::Locale::ti_ER undef + DateTime::Locale::ti_ET undef + DateTime::Locale::tig undef + DateTime::Locale::tig_ER undef + DateTime::Locale::tl undef + DateTime::Locale::tn undef + DateTime::Locale::tn_ZA undef + DateTime::Locale::to undef + DateTime::Locale::to_TO undef + DateTime::Locale::tr undef + DateTime::Locale::tr_TR undef + DateTime::Locale::trv undef + DateTime::Locale::trv_TW undef + DateTime::Locale::ts undef + DateTime::Locale::ts_ZA undef + DateTime::Locale::tt undef + DateTime::Locale::tt_RU undef + DateTime::Locale::ug undef + DateTime::Locale::ug_Arab undef + DateTime::Locale::ug_Arab_CN undef + DateTime::Locale::ug_CN undef + DateTime::Locale::uk undef + DateTime::Locale::uk_UA undef + DateTime::Locale::ur undef + DateTime::Locale::ur_IN undef + DateTime::Locale::ur_PK undef + DateTime::Locale::uz undef + DateTime::Locale::uz_AF undef + DateTime::Locale::uz_Arab undef + DateTime::Locale::uz_Arab_AF undef + DateTime::Locale::uz_Cyrl undef + DateTime::Locale::uz_Cyrl_UZ undef + DateTime::Locale::uz_Latn undef + DateTime::Locale::uz_Latn_UZ undef + DateTime::Locale::uz_UZ undef + DateTime::Locale::ve undef + DateTime::Locale::ve_ZA undef + DateTime::Locale::vi undef + DateTime::Locale::vi_VN undef + DateTime::Locale::wal undef + DateTime::Locale::wal_ET undef + DateTime::Locale::wo undef + DateTime::Locale::wo_Latn undef + DateTime::Locale::wo_Latn_SN undef + DateTime::Locale::wo_SN undef + DateTime::Locale::xh undef + DateTime::Locale::xh_ZA undef + DateTime::Locale::yo undef + DateTime::Locale::yo_NG undef + DateTime::Locale::zh undef + DateTime::Locale::zh_CN undef + DateTime::Locale::zh_HK undef + DateTime::Locale::zh_Hans undef + DateTime::Locale::zh_Hans_CN undef + DateTime::Locale::zh_Hans_HK undef + DateTime::Locale::zh_Hans_MO undef + DateTime::Locale::zh_Hans_SG undef + DateTime::Locale::zh_Hant undef + DateTime::Locale::zh_Hant_HK undef + DateTime::Locale::zh_Hant_MO undef + DateTime::Locale::zh_Hant_TW undef + DateTime::Locale::zh_MO undef + DateTime::Locale::zh_SG undef + DateTime::Locale::zh_TW undef + DateTime::Locale::zu undef + DateTime::Locale::zu_ZA undef + requirements: + List::MoreUtils 0 + Module::Build 0 + Params::Validate 0.91 + perl 5.006 + DateTime-TimeZone-1.64 + pathname: D/DR/DROLSKY/DateTime-TimeZone-1.64.tar.gz + provides: + DateTime::TimeZone 1.64 + DateTime::TimeZone::Africa::Abidjan 1.64 + DateTime::TimeZone::Africa::Accra 1.64 + DateTime::TimeZone::Africa::Addis_Ababa 1.64 + DateTime::TimeZone::Africa::Algiers 1.64 + DateTime::TimeZone::Africa::Asmara 1.64 + DateTime::TimeZone::Africa::Bamako 1.64 + DateTime::TimeZone::Africa::Bangui 1.64 + DateTime::TimeZone::Africa::Banjul 1.64 + DateTime::TimeZone::Africa::Bissau 1.64 + DateTime::TimeZone::Africa::Blantyre 1.64 + DateTime::TimeZone::Africa::Brazzaville 1.64 + DateTime::TimeZone::Africa::Bujumbura 1.64 + DateTime::TimeZone::Africa::Cairo 1.64 + DateTime::TimeZone::Africa::Casablanca 1.64 + DateTime::TimeZone::Africa::Ceuta 1.64 + DateTime::TimeZone::Africa::Conakry 1.64 + DateTime::TimeZone::Africa::Dakar 1.64 + DateTime::TimeZone::Africa::Dar_es_Salaam 1.64 + DateTime::TimeZone::Africa::Djibouti 1.64 + DateTime::TimeZone::Africa::Douala 1.64 + DateTime::TimeZone::Africa::El_Aaiun 1.64 + DateTime::TimeZone::Africa::Freetown 1.64 + DateTime::TimeZone::Africa::Gaborone 1.64 + DateTime::TimeZone::Africa::Harare 1.64 + DateTime::TimeZone::Africa::Johannesburg 1.64 + DateTime::TimeZone::Africa::Kampala 1.64 + DateTime::TimeZone::Africa::Khartoum 1.64 + DateTime::TimeZone::Africa::Kigali 1.64 + DateTime::TimeZone::Africa::Kinshasa 1.64 + DateTime::TimeZone::Africa::Lagos 1.64 + DateTime::TimeZone::Africa::Libreville 1.64 + DateTime::TimeZone::Africa::Lome 1.64 + DateTime::TimeZone::Africa::Luanda 1.64 + DateTime::TimeZone::Africa::Lubumbashi 1.64 + DateTime::TimeZone::Africa::Lusaka 1.64 + DateTime::TimeZone::Africa::Malabo 1.64 + DateTime::TimeZone::Africa::Maputo 1.64 + DateTime::TimeZone::Africa::Maseru 1.64 + DateTime::TimeZone::Africa::Mbabane 1.64 + DateTime::TimeZone::Africa::Mogadishu 1.64 + DateTime::TimeZone::Africa::Monrovia 1.64 + DateTime::TimeZone::Africa::Nairobi 1.64 + DateTime::TimeZone::Africa::Ndjamena 1.64 + DateTime::TimeZone::Africa::Niamey 1.64 + DateTime::TimeZone::Africa::Nouakchott 1.64 + DateTime::TimeZone::Africa::Ouagadougou 1.64 + DateTime::TimeZone::Africa::Porto_Novo 1.64 + DateTime::TimeZone::Africa::Sao_Tome 1.64 + DateTime::TimeZone::Africa::Tripoli 1.64 + DateTime::TimeZone::Africa::Tunis 1.64 + DateTime::TimeZone::Africa::Windhoek 1.64 + DateTime::TimeZone::America::Adak 1.64 + DateTime::TimeZone::America::Anchorage 1.64 + DateTime::TimeZone::America::Antigua 1.64 + DateTime::TimeZone::America::Araguaina 1.64 + DateTime::TimeZone::America::Argentina::Buenos_Aires 1.64 + DateTime::TimeZone::America::Argentina::Catamarca 1.64 + DateTime::TimeZone::America::Argentina::Cordoba 1.64 + DateTime::TimeZone::America::Argentina::Jujuy 1.64 + DateTime::TimeZone::America::Argentina::La_Rioja 1.64 + DateTime::TimeZone::America::Argentina::Mendoza 1.64 + DateTime::TimeZone::America::Argentina::Rio_Gallegos 1.64 + DateTime::TimeZone::America::Argentina::Salta 1.64 + DateTime::TimeZone::America::Argentina::San_Juan 1.64 + DateTime::TimeZone::America::Argentina::San_Luis 1.64 + DateTime::TimeZone::America::Argentina::Tucuman 1.64 + DateTime::TimeZone::America::Argentina::Ushuaia 1.64 + DateTime::TimeZone::America::Asuncion 1.64 + DateTime::TimeZone::America::Atikokan 1.64 + DateTime::TimeZone::America::Bahia 1.64 + DateTime::TimeZone::America::Bahia_Banderas 1.64 + DateTime::TimeZone::America::Barbados 1.64 + DateTime::TimeZone::America::Belem 1.64 + DateTime::TimeZone::America::Belize 1.64 + DateTime::TimeZone::America::Blanc_Sablon 1.64 + DateTime::TimeZone::America::Boa_Vista 1.64 + DateTime::TimeZone::America::Bogota 1.64 + DateTime::TimeZone::America::Boise 1.64 + DateTime::TimeZone::America::Cambridge_Bay 1.64 + DateTime::TimeZone::America::Campo_Grande 1.64 + DateTime::TimeZone::America::Cancun 1.64 + DateTime::TimeZone::America::Caracas 1.64 + DateTime::TimeZone::America::Cayenne 1.64 + DateTime::TimeZone::America::Cayman 1.64 + DateTime::TimeZone::America::Chicago 1.64 + DateTime::TimeZone::America::Chihuahua 1.64 + DateTime::TimeZone::America::Costa_Rica 1.64 + DateTime::TimeZone::America::Creston 1.64 + DateTime::TimeZone::America::Cuiaba 1.64 + DateTime::TimeZone::America::Curacao 1.64 + DateTime::TimeZone::America::Danmarkshavn 1.64 + DateTime::TimeZone::America::Dawson 1.64 + DateTime::TimeZone::America::Dawson_Creek 1.64 + DateTime::TimeZone::America::Denver 1.64 + DateTime::TimeZone::America::Detroit 1.64 + DateTime::TimeZone::America::Edmonton 1.64 + DateTime::TimeZone::America::Eirunepe 1.64 + DateTime::TimeZone::America::El_Salvador 1.64 + DateTime::TimeZone::America::Fortaleza 1.64 + DateTime::TimeZone::America::Glace_Bay 1.64 + DateTime::TimeZone::America::Godthab 1.64 + DateTime::TimeZone::America::Goose_Bay 1.64 + DateTime::TimeZone::America::Grand_Turk 1.64 + DateTime::TimeZone::America::Guatemala 1.64 + DateTime::TimeZone::America::Guayaquil 1.64 + DateTime::TimeZone::America::Guyana 1.64 + DateTime::TimeZone::America::Halifax 1.64 + DateTime::TimeZone::America::Havana 1.64 + DateTime::TimeZone::America::Hermosillo 1.64 + DateTime::TimeZone::America::Indiana::Indianapolis 1.64 + DateTime::TimeZone::America::Indiana::Knox 1.64 + DateTime::TimeZone::America::Indiana::Marengo 1.64 + DateTime::TimeZone::America::Indiana::Petersburg 1.64 + DateTime::TimeZone::America::Indiana::Tell_City 1.64 + DateTime::TimeZone::America::Indiana::Vevay 1.64 + DateTime::TimeZone::America::Indiana::Vincennes 1.64 + DateTime::TimeZone::America::Indiana::Winamac 1.64 + DateTime::TimeZone::America::Inuvik 1.64 + DateTime::TimeZone::America::Iqaluit 1.64 + DateTime::TimeZone::America::Jamaica 1.64 + DateTime::TimeZone::America::Juneau 1.64 + DateTime::TimeZone::America::Kentucky::Louisville 1.64 + DateTime::TimeZone::America::Kentucky::Monticello 1.64 + DateTime::TimeZone::America::La_Paz 1.64 + DateTime::TimeZone::America::Lima 1.64 + DateTime::TimeZone::America::Los_Angeles 1.64 + DateTime::TimeZone::America::Maceio 1.64 + DateTime::TimeZone::America::Managua 1.64 + DateTime::TimeZone::America::Manaus 1.64 + DateTime::TimeZone::America::Martinique 1.64 + DateTime::TimeZone::America::Matamoros 1.64 + DateTime::TimeZone::America::Mazatlan 1.64 + DateTime::TimeZone::America::Menominee 1.64 + DateTime::TimeZone::America::Merida 1.64 + DateTime::TimeZone::America::Metlakatla 1.64 + DateTime::TimeZone::America::Mexico_City 1.64 + DateTime::TimeZone::America::Miquelon 1.64 + DateTime::TimeZone::America::Moncton 1.64 + DateTime::TimeZone::America::Monterrey 1.64 + DateTime::TimeZone::America::Montevideo 1.64 + DateTime::TimeZone::America::Montreal 1.64 + DateTime::TimeZone::America::Nassau 1.64 + DateTime::TimeZone::America::New_York 1.64 + DateTime::TimeZone::America::Nipigon 1.64 + DateTime::TimeZone::America::Nome 1.64 + DateTime::TimeZone::America::Noronha 1.64 + DateTime::TimeZone::America::North_Dakota::Beulah 1.64 + DateTime::TimeZone::America::North_Dakota::Center 1.64 + DateTime::TimeZone::America::North_Dakota::New_Salem 1.64 + DateTime::TimeZone::America::Ojinaga 1.64 + DateTime::TimeZone::America::Panama 1.64 + DateTime::TimeZone::America::Pangnirtung 1.64 + DateTime::TimeZone::America::Paramaribo 1.64 + DateTime::TimeZone::America::Phoenix 1.64 + DateTime::TimeZone::America::Port_au_Prince 1.64 + DateTime::TimeZone::America::Port_of_Spain 1.64 + DateTime::TimeZone::America::Porto_Velho 1.64 + DateTime::TimeZone::America::Puerto_Rico 1.64 + DateTime::TimeZone::America::Rainy_River 1.64 + DateTime::TimeZone::America::Rankin_Inlet 1.64 + DateTime::TimeZone::America::Recife 1.64 + DateTime::TimeZone::America::Regina 1.64 + DateTime::TimeZone::America::Resolute 1.64 + DateTime::TimeZone::America::Rio_Branco 1.64 + DateTime::TimeZone::America::Santa_Isabel 1.64 + DateTime::TimeZone::America::Santarem 1.64 + DateTime::TimeZone::America::Santiago 1.64 + DateTime::TimeZone::America::Santo_Domingo 1.64 + DateTime::TimeZone::America::Sao_Paulo 1.64 + DateTime::TimeZone::America::Scoresbysund 1.64 + DateTime::TimeZone::America::Sitka 1.64 + DateTime::TimeZone::America::St_Johns 1.64 + DateTime::TimeZone::America::Swift_Current 1.64 + DateTime::TimeZone::America::Tegucigalpa 1.64 + DateTime::TimeZone::America::Thule 1.64 + DateTime::TimeZone::America::Thunder_Bay 1.64 + DateTime::TimeZone::America::Tijuana 1.64 + DateTime::TimeZone::America::Toronto 1.64 + DateTime::TimeZone::America::Vancouver 1.64 + DateTime::TimeZone::America::Whitehorse 1.64 + DateTime::TimeZone::America::Winnipeg 1.64 + DateTime::TimeZone::America::Yakutat 1.64 + DateTime::TimeZone::America::Yellowknife 1.64 + DateTime::TimeZone::Antarctica::Casey 1.64 + DateTime::TimeZone::Antarctica::Davis 1.64 + DateTime::TimeZone::Antarctica::DumontDUrville 1.64 + DateTime::TimeZone::Antarctica::Macquarie 1.64 + DateTime::TimeZone::Antarctica::Mawson 1.64 + DateTime::TimeZone::Antarctica::Palmer 1.64 + DateTime::TimeZone::Antarctica::Rothera 1.64 + DateTime::TimeZone::Antarctica::Syowa 1.64 + DateTime::TimeZone::Antarctica::Vostok 1.64 + DateTime::TimeZone::Asia::Aden 1.64 + DateTime::TimeZone::Asia::Almaty 1.64 + DateTime::TimeZone::Asia::Amman 1.64 + DateTime::TimeZone::Asia::Anadyr 1.64 + DateTime::TimeZone::Asia::Aqtau 1.64 + DateTime::TimeZone::Asia::Aqtobe 1.64 + DateTime::TimeZone::Asia::Ashgabat 1.64 + DateTime::TimeZone::Asia::Baghdad 1.64 + DateTime::TimeZone::Asia::Bahrain 1.64 + DateTime::TimeZone::Asia::Baku 1.64 + DateTime::TimeZone::Asia::Bangkok 1.64 + DateTime::TimeZone::Asia::Beirut 1.64 + DateTime::TimeZone::Asia::Bishkek 1.64 + DateTime::TimeZone::Asia::Brunei 1.64 + DateTime::TimeZone::Asia::Choibalsan 1.64 + DateTime::TimeZone::Asia::Chongqing 1.64 + DateTime::TimeZone::Asia::Colombo 1.64 + DateTime::TimeZone::Asia::Damascus 1.64 + DateTime::TimeZone::Asia::Dhaka 1.64 + DateTime::TimeZone::Asia::Dili 1.64 + DateTime::TimeZone::Asia::Dubai 1.64 + DateTime::TimeZone::Asia::Dushanbe 1.64 + DateTime::TimeZone::Asia::Gaza 1.64 + DateTime::TimeZone::Asia::Harbin 1.64 + DateTime::TimeZone::Asia::Hebron 1.64 + DateTime::TimeZone::Asia::Ho_Chi_Minh 1.64 + DateTime::TimeZone::Asia::Hong_Kong 1.64 + DateTime::TimeZone::Asia::Hovd 1.64 + DateTime::TimeZone::Asia::Irkutsk 1.64 + DateTime::TimeZone::Asia::Jakarta 1.64 + DateTime::TimeZone::Asia::Jayapura 1.64 + DateTime::TimeZone::Asia::Jerusalem 1.64 + DateTime::TimeZone::Asia::Kabul 1.64 + DateTime::TimeZone::Asia::Kamchatka 1.64 + DateTime::TimeZone::Asia::Karachi 1.64 + DateTime::TimeZone::Asia::Kashgar 1.64 + DateTime::TimeZone::Asia::Kathmandu 1.64 + DateTime::TimeZone::Asia::Khandyga 1.64 + DateTime::TimeZone::Asia::Kolkata 1.64 + DateTime::TimeZone::Asia::Krasnoyarsk 1.64 + DateTime::TimeZone::Asia::Kuala_Lumpur 1.64 + DateTime::TimeZone::Asia::Kuching 1.64 + DateTime::TimeZone::Asia::Kuwait 1.64 + DateTime::TimeZone::Asia::Macau 1.64 + DateTime::TimeZone::Asia::Magadan 1.64 + DateTime::TimeZone::Asia::Makassar 1.64 + DateTime::TimeZone::Asia::Manila 1.64 + DateTime::TimeZone::Asia::Muscat 1.64 + DateTime::TimeZone::Asia::Nicosia 1.64 + DateTime::TimeZone::Asia::Novokuznetsk 1.64 + DateTime::TimeZone::Asia::Novosibirsk 1.64 + DateTime::TimeZone::Asia::Omsk 1.64 + DateTime::TimeZone::Asia::Oral 1.64 + DateTime::TimeZone::Asia::Phnom_Penh 1.64 + DateTime::TimeZone::Asia::Pontianak 1.64 + DateTime::TimeZone::Asia::Pyongyang 1.64 + DateTime::TimeZone::Asia::Qatar 1.64 + DateTime::TimeZone::Asia::Qyzylorda 1.64 + DateTime::TimeZone::Asia::Rangoon 1.64 + DateTime::TimeZone::Asia::Riyadh 1.64 + DateTime::TimeZone::Asia::Sakhalin 1.64 + DateTime::TimeZone::Asia::Samarkand 1.64 + DateTime::TimeZone::Asia::Seoul 1.64 + DateTime::TimeZone::Asia::Shanghai 1.64 + DateTime::TimeZone::Asia::Singapore 1.64 + DateTime::TimeZone::Asia::Taipei 1.64 + DateTime::TimeZone::Asia::Tashkent 1.64 + DateTime::TimeZone::Asia::Tbilisi 1.64 + DateTime::TimeZone::Asia::Tehran 1.64 + DateTime::TimeZone::Asia::Thimphu 1.64 + DateTime::TimeZone::Asia::Tokyo 1.64 + DateTime::TimeZone::Asia::Ulaanbaatar 1.64 + DateTime::TimeZone::Asia::Urumqi 1.64 + DateTime::TimeZone::Asia::Ust_Nera 1.64 + DateTime::TimeZone::Asia::Vientiane 1.64 + DateTime::TimeZone::Asia::Vladivostok 1.64 + DateTime::TimeZone::Asia::Yakutsk 1.64 + DateTime::TimeZone::Asia::Yekaterinburg 1.64 + DateTime::TimeZone::Asia::Yerevan 1.64 + DateTime::TimeZone::Atlantic::Azores 1.64 + DateTime::TimeZone::Atlantic::Bermuda 1.64 + DateTime::TimeZone::Atlantic::Canary 1.64 + DateTime::TimeZone::Atlantic::Cape_Verde 1.64 + DateTime::TimeZone::Atlantic::Faroe 1.64 + DateTime::TimeZone::Atlantic::Madeira 1.64 + DateTime::TimeZone::Atlantic::Reykjavik 1.64 + DateTime::TimeZone::Atlantic::South_Georgia 1.64 + DateTime::TimeZone::Atlantic::St_Helena 1.64 + DateTime::TimeZone::Atlantic::Stanley 1.64 + DateTime::TimeZone::Australia::Adelaide 1.64 + DateTime::TimeZone::Australia::Brisbane 1.64 + DateTime::TimeZone::Australia::Broken_Hill 1.64 + DateTime::TimeZone::Australia::Currie 1.64 + DateTime::TimeZone::Australia::Darwin 1.64 + DateTime::TimeZone::Australia::Eucla 1.64 + DateTime::TimeZone::Australia::Hobart 1.64 + DateTime::TimeZone::Australia::Lindeman 1.64 + DateTime::TimeZone::Australia::Lord_Howe 1.64 + DateTime::TimeZone::Australia::Melbourne 1.64 + DateTime::TimeZone::Australia::Perth 1.64 + DateTime::TimeZone::Australia::Sydney 1.64 + DateTime::TimeZone::CET 1.64 + DateTime::TimeZone::CST6CDT 1.64 + DateTime::TimeZone::Catalog 1.64 + DateTime::TimeZone::EET 1.64 + DateTime::TimeZone::EST 1.64 + DateTime::TimeZone::EST5EDT 1.64 + DateTime::TimeZone::Europe::Amsterdam 1.64 + DateTime::TimeZone::Europe::Andorra 1.64 + DateTime::TimeZone::Europe::Athens 1.64 + DateTime::TimeZone::Europe::Belgrade 1.64 + DateTime::TimeZone::Europe::Berlin 1.64 + DateTime::TimeZone::Europe::Brussels 1.64 + DateTime::TimeZone::Europe::Bucharest 1.64 + DateTime::TimeZone::Europe::Budapest 1.64 + DateTime::TimeZone::Europe::Chisinau 1.64 + DateTime::TimeZone::Europe::Copenhagen 1.64 + DateTime::TimeZone::Europe::Dublin 1.64 + DateTime::TimeZone::Europe::Gibraltar 1.64 + DateTime::TimeZone::Europe::Helsinki 1.64 + DateTime::TimeZone::Europe::Istanbul 1.64 + DateTime::TimeZone::Europe::Kaliningrad 1.64 + DateTime::TimeZone::Europe::Kiev 1.64 + DateTime::TimeZone::Europe::Lisbon 1.64 + DateTime::TimeZone::Europe::London 1.64 + DateTime::TimeZone::Europe::Luxembourg 1.64 + DateTime::TimeZone::Europe::Madrid 1.64 + DateTime::TimeZone::Europe::Malta 1.64 + DateTime::TimeZone::Europe::Minsk 1.64 + DateTime::TimeZone::Europe::Monaco 1.64 + DateTime::TimeZone::Europe::Moscow 1.64 + DateTime::TimeZone::Europe::Oslo 1.64 + DateTime::TimeZone::Europe::Paris 1.64 + DateTime::TimeZone::Europe::Prague 1.64 + DateTime::TimeZone::Europe::Riga 1.64 + DateTime::TimeZone::Europe::Rome 1.64 + DateTime::TimeZone::Europe::Samara 1.64 + DateTime::TimeZone::Europe::Simferopol 1.64 + DateTime::TimeZone::Europe::Sofia 1.64 + DateTime::TimeZone::Europe::Stockholm 1.64 + DateTime::TimeZone::Europe::Tallinn 1.64 + DateTime::TimeZone::Europe::Tirane 1.64 + DateTime::TimeZone::Europe::Uzhgorod 1.64 + DateTime::TimeZone::Europe::Vienna 1.64 + DateTime::TimeZone::Europe::Vilnius 1.64 + DateTime::TimeZone::Europe::Volgograd 1.64 + DateTime::TimeZone::Europe::Warsaw 1.64 + DateTime::TimeZone::Europe::Zaporozhye 1.64 + DateTime::TimeZone::Europe::Zurich 1.64 + DateTime::TimeZone::Floating 1.64 + DateTime::TimeZone::HST 1.64 + DateTime::TimeZone::Indian::Antananarivo 1.64 + DateTime::TimeZone::Indian::Chagos 1.64 + DateTime::TimeZone::Indian::Christmas 1.64 + DateTime::TimeZone::Indian::Cocos 1.64 + DateTime::TimeZone::Indian::Comoro 1.64 + DateTime::TimeZone::Indian::Kerguelen 1.64 + DateTime::TimeZone::Indian::Mahe 1.64 + DateTime::TimeZone::Indian::Maldives 1.64 + DateTime::TimeZone::Indian::Mauritius 1.64 + DateTime::TimeZone::Indian::Mayotte 1.64 + DateTime::TimeZone::Indian::Reunion 1.64 + DateTime::TimeZone::Local 1.64 + DateTime::TimeZone::Local::Unix 1.64 + DateTime::TimeZone::Local::VMS 1.64 + DateTime::TimeZone::Local::Win32 1.64 + DateTime::TimeZone::MET 1.64 + DateTime::TimeZone::MST 1.64 + DateTime::TimeZone::MST7MDT 1.64 + DateTime::TimeZone::OffsetOnly 1.64 + DateTime::TimeZone::OlsonDB 1.64 + DateTime::TimeZone::OlsonDB::Change 1.64 + DateTime::TimeZone::OlsonDB::Observance 1.64 + DateTime::TimeZone::OlsonDB::Rule 1.64 + DateTime::TimeZone::OlsonDB::Zone 1.64 + DateTime::TimeZone::PST8PDT 1.64 + DateTime::TimeZone::Pacific::Apia 1.64 + DateTime::TimeZone::Pacific::Auckland 1.64 + DateTime::TimeZone::Pacific::Chatham 1.64 + DateTime::TimeZone::Pacific::Chuuk 1.64 + DateTime::TimeZone::Pacific::Easter 1.64 + DateTime::TimeZone::Pacific::Efate 1.64 + DateTime::TimeZone::Pacific::Enderbury 1.64 + DateTime::TimeZone::Pacific::Fakaofo 1.64 + DateTime::TimeZone::Pacific::Fiji 1.64 + DateTime::TimeZone::Pacific::Funafuti 1.64 + DateTime::TimeZone::Pacific::Galapagos 1.64 + DateTime::TimeZone::Pacific::Gambier 1.64 + DateTime::TimeZone::Pacific::Guadalcanal 1.64 + DateTime::TimeZone::Pacific::Guam 1.64 + DateTime::TimeZone::Pacific::Honolulu 1.64 + DateTime::TimeZone::Pacific::Kiritimati 1.64 + DateTime::TimeZone::Pacific::Kosrae 1.64 + DateTime::TimeZone::Pacific::Kwajalein 1.64 + DateTime::TimeZone::Pacific::Majuro 1.64 + DateTime::TimeZone::Pacific::Marquesas 1.64 + DateTime::TimeZone::Pacific::Midway 1.64 + DateTime::TimeZone::Pacific::Nauru 1.64 + DateTime::TimeZone::Pacific::Niue 1.64 + DateTime::TimeZone::Pacific::Norfolk 1.64 + DateTime::TimeZone::Pacific::Noumea 1.64 + DateTime::TimeZone::Pacific::Pago_Pago 1.64 + DateTime::TimeZone::Pacific::Palau 1.64 + DateTime::TimeZone::Pacific::Pitcairn 1.64 + DateTime::TimeZone::Pacific::Pohnpei 1.64 + DateTime::TimeZone::Pacific::Port_Moresby 1.64 + DateTime::TimeZone::Pacific::Rarotonga 1.64 + DateTime::TimeZone::Pacific::Saipan 1.64 + DateTime::TimeZone::Pacific::Tahiti 1.64 + DateTime::TimeZone::Pacific::Tarawa 1.64 + DateTime::TimeZone::Pacific::Tongatapu 1.64 + DateTime::TimeZone::Pacific::Wake 1.64 + DateTime::TimeZone::Pacific::Wallis 1.64 + DateTime::TimeZone::UTC 1.64 + DateTime::TimeZone::WET 1.64 + requirements: + Class::Load 0 + Class::Singleton 1.03 + Cwd 3 + ExtUtils::MakeMaker 6.30 + File::Basename 0 + File::Compare 0 + File::Find 0 + File::Spec 0 + List::Util 0 + Params::Validate 0.72 + constant 0 + parent 0 + strict 0 + vars 0 + warnings 0 + Dist-CheckConflicts-0.10 + pathname: D/DO/DOY/Dist-CheckConflicts-0.10.tar.gz + provides: + Dist::CheckConflicts 0.10 + requirements: + Carp 0 + Exporter 0 + ExtUtils::MakeMaker 6.30 + List::MoreUtils 0.12 + Module::Runtime 0.009 + base 0 + strict 0 + warnings 0 + ExtUtils-Config-0.007 + pathname: L/LE/LEONT/ExtUtils-Config-0.007.tar.gz + provides: + ExtUtils::Config 0.007 + requirements: + Config 0 + Data::Dumper 0 + ExtUtils::MakeMaker 6.30 + File::Find 0 + File::Temp 0 + Test::More 0.88 + strict 0 + warnings 0 + ExtUtils-Helpers-0.021 + pathname: L/LE/LEONT/ExtUtils-Helpers-0.021.tar.gz + provides: + ExtUtils::Helpers 0.021 + ExtUtils::Helpers::Unix 0.021 + ExtUtils::Helpers::VMS 0.021 + ExtUtils::Helpers::Windows 0.021 + requirements: + Carp 0 + Config 0 + Exporter 5.57 + ExtUtils::MakeMaker 6.30 + File::Basename 0 + File::Copy 0 + File::Spec::Functions 0 + Module::Load 0 + Text::ParseWords 3.24 + strict 0 + warnings 0 + ExtUtils-InstallPaths-0.010 + pathname: L/LE/LEONT/ExtUtils-InstallPaths-0.010.tar.gz + provides: + ExtUtils::InstallPaths 0.010 + requirements: + Carp 0 + ExtUtils::Config 0.002 + ExtUtils::MakeMaker 6.30 + File::Spec 0 + strict 0 + warnings 0 File-Remove-1.52 pathname: A/AD/ADAMK/File-Remove-1.52.tar.gz provides: @@ -164,6 +1191,15 @@ DISTRIBUTIONS ExtUtils::MakeMaker 0 Test::More 0.31 Time::HiRes 0 + List-MoreUtils-0.33 + pathname: A/AD/ADAMK/List-MoreUtils-0.33.tar.gz + provides: + List::MoreUtils 0.33 + requirements: + ExtUtils::CBuilder 0.27 + ExtUtils::MakeMaker 6.52 + Test::More 0.82 + perl 5.00503 Module-Build-0.4205 pathname: L/LE/LEONT/Module-Build-0.4205.tar.gz provides: @@ -219,8 +1255,58 @@ DISTRIBUTIONS Text::ParseWords 0 perl 5.006001 version 0.87 - Mojolicious-4.81 - pathname: S/SR/SRI/Mojolicious-4.81.tar.gz + Module-Build-Tiny-0.035 + pathname: L/LE/LEONT/Module-Build-Tiny-0.035.tar.gz + provides: + Module::Build::Tiny 0.035 + requirements: + CPAN::Meta 0 + DynaLoader 0 + Exporter 5.57 + ExtUtils::CBuilder 0 + ExtUtils::Config 0.003 + ExtUtils::Helpers 0.020 + ExtUtils::Install 0 + ExtUtils::InstallPaths 0.002 + ExtUtils::ParseXS 0 + File::Basename 0 + File::Find 0 + File::Path 0 + File::Spec::Functions 0 + Getopt::Long 2.36 + JSON::PP 2 + Pod::Man 0 + TAP::Harness::Env 0 + perl 5.006 + strict 0 + warnings 0 + Module-Implementation-0.07 + pathname: D/DR/DROLSKY/Module-Implementation-0.07.tar.gz + provides: + Module::Implementation 0.07 + T::Impl1 undef + T::Impl2 undef + T::ImplFails1 undef + T::ImplFails2 undef + requirements: + Carp 0 + ExtUtils::MakeMaker 6.30 + Module::Runtime 0.012 + Try::Tiny 0 + strict 0 + warnings 0 + Module-Runtime-0.014 + pathname: Z/ZE/ZEFRAM/Module-Runtime-0.014.tar.gz + provides: + Module::Runtime 0.014 + requirements: + Module::Build 0 + Test::More 0 + perl 5.006 + strict 0 + warnings 0 + Mojolicious-4.83 + pathname: S/SR/SRI/Mojolicious-4.83.tar.gz provides: Mojo undef Mojo::Asset undef @@ -283,7 +1369,7 @@ DISTRIBUTIONS Mojo::UserAgent::Server undef Mojo::UserAgent::Transactor undef Mojo::Util undef - Mojolicious 4.81 + Mojolicious 4.83 Mojolicious::Command undef Mojolicious::Command::cgi undef Mojolicious::Command::cpanify undef @@ -378,6 +1464,44 @@ DISTRIBUTIONS Test::More 0.47 Test::Script 1.06 perl 5.006 + Package-Stash-0.36 + pathname: D/DO/DOY/Package-Stash-0.36.tar.gz + provides: + Package::Stash 0.36 + Package::Stash::PP 0.36 + requirements: + B 0 + Carp 0 + Config 0 + Dist::CheckConflicts 0.02 + ExtUtils::MakeMaker 6.30 + File::Find 0 + File::Spec 0 + File::Temp 0 + Getopt::Long 0 + Module::Implementation 0.06 + Package::Stash::XS 0.26 + Scalar::Util 0 + Symbol 0 + Test::Fatal 0 + Test::More 0.88 + Test::Requires 0 + Text::ParseWords 0 + base 0 + constant 0 + lib 0 + strict 0 + warnings 0 + Package-Stash-XS-0.28 + pathname: D/DO/DOY/Package-Stash-XS-0.28.tar.gz + provides: + CompileTime undef + Package::Stash::XS 0.28 + requirements: + ExtUtils::MakeMaker 6.30 + XSLoader 0 + strict 0 + warnings 0 Params-Util-1.07 pathname: A/AD/ADAMK/Params-Util-1.07.tar.gz provides: @@ -389,6 +1513,41 @@ DISTRIBUTIONS Scalar::Util 1.18 Test::More 0.42 perl 5.00503 + Params-Validate-1.08 + pathname: D/DR/DROLSKY/Params-Validate-1.08.tar.gz + provides: + Attribute::Params::Validate 1.08 + Bar undef + Baz undef + Foo undef + PVTests undef + PVTests::Callbacks undef + PVTests::Defaults undef + PVTests::Regex undef + PVTests::Standard undef + PVTests::With undef + Params::Validate 1.08 + Params::Validate::Constants 1.08 + Params::Validate::PP 1.08 + Params::Validate::XS 1.08 + Quux undef + Testing::X undef + Yadda undef + inc::MyModuleBuild undef + requirements: + Attribute::Handlers 0.79 + Carp 0 + Exporter 0 + ExtUtils::CBuilder 0 + Module::Build 0.3601 + Module::Implementation 0 + Scalar::Util 1.10 + XSLoader 0 + attributes 0 + perl 5.008001 + strict 0 + vars 0 + warnings 0 Probe-Perl-0.03 pathname: K/KW/KWILLIAMS/Probe-Perl-0.03.tar.gz provides: @@ -398,6 +1557,94 @@ DISTRIBUTIONS ExtUtils::MakeMaker 6.30 File::Spec 0 strict 0 + Sub-Install-0.927 + pathname: R/RJ/RJBS/Sub-Install-0.927.tar.gz + provides: + Sub::Install 0.927 + requirements: + B 0 + Carp 0 + ExtUtils::MakeMaker 6.30 + Scalar::Util 0 + strict 0 + warnings 0 + Test-Fatal-0.013 + pathname: R/RJ/RJBS/Test-Fatal-0.013.tar.gz + provides: + Test::Fatal 0.013 + requirements: + Carp 0 + Exporter 5.57 + ExtUtils::MakeMaker 6.30 + Test::Builder 0 + Try::Tiny 0.07 + strict 0 + warnings 0 + Test-Harness-3.30 + pathname: L/LE/LEONT/Test-Harness-3.30.tar.gz + provides: + App::Prove 3.30 + App::Prove::State 3.30 + App::Prove::State::Result 3.30 + App::Prove::State::Result::Test 3.30 + TAP::Base 3.30 + TAP::Formatter::Base 3.30 + TAP::Formatter::Color 3.30 + TAP::Formatter::Console 3.30 + TAP::Formatter::Console::ParallelSession 3.30 + TAP::Formatter::Console::Session 3.30 + TAP::Formatter::File 3.30 + TAP::Formatter::File::Session 3.30 + TAP::Formatter::Session 3.30 + TAP::Harness 3.30 + TAP::Harness::Env 3.30 + TAP::Object 3.30 + TAP::Parser 3.30 + TAP::Parser::Aggregator 3.30 + TAP::Parser::Grammar 3.30 + TAP::Parser::Iterator 3.30 + TAP::Parser::Iterator::Array 3.30 + TAP::Parser::Iterator::Process 3.30 + TAP::Parser::Iterator::Stream 3.30 + TAP::Parser::IteratorFactory 3.30 + TAP::Parser::Multiplexer 3.30 + TAP::Parser::Result 3.30 + TAP::Parser::Result::Bailout 3.30 + TAP::Parser::Result::Comment 3.30 + TAP::Parser::Result::Plan 3.30 + TAP::Parser::Result::Pragma 3.30 + TAP::Parser::Result::Test 3.30 + TAP::Parser::Result::Unknown 3.30 + TAP::Parser::Result::Version 3.30 + TAP::Parser::Result::YAML 3.30 + TAP::Parser::ResultFactory 3.30 + TAP::Parser::Scheduler 3.30 + TAP::Parser::Scheduler::Job 3.30 + TAP::Parser::Scheduler::Spinner 3.30 + TAP::Parser::Source 3.30 + TAP::Parser::SourceHandler 3.30 + TAP::Parser::SourceHandler::Executable 3.30 + TAP::Parser::SourceHandler::File 3.30 + TAP::Parser::SourceHandler::Handle 3.30 + TAP::Parser::SourceHandler::Perl 3.30 + TAP::Parser::SourceHandler::RawTAP 3.30 + TAP::Parser::YAMLish::Reader 3.30 + TAP::Parser::YAMLish::Writer 3.30 + Test::Harness 3.30 + requirements: + ExtUtils::MakeMaker 0 + Test-Requires-0.07 + pathname: T/TO/TOKUHIROM/Test-Requires-0.07.tar.gz + provides: + Test::Requires 0.07 + requirements: + CPAN::Meta 0 + CPAN::Meta::Prereqs 0 + ExtUtils::MakeMaker 6.59 + Module::Build 0.38 + Test::Builder::Module 0 + Test::More 0.61 + perl 5.008_001 Test-Script-1.07 pathname: A/AD/ADAMK/Test-Script-1.07.tar.gz provides: @@ -417,3 +1664,14 @@ DISTRIBUTIONS Text::Unidecode 0.04 requirements: ExtUtils::MakeMaker 0 + Try-Tiny-0.19 + pathname: D/DO/DOY/Try-Tiny-0.19.tar.gz + provides: + Try::Tiny 0.19 + requirements: + Carp 0 + Exporter 5.57 + ExtUtils::MakeMaker 6.30 + constant 0 + strict 0 + warnings 0 diff --git a/lib/Lutim.pm b/lib/Lutim.pm index 8b374cb..b23c5ba 100644 --- a/lib/Lutim.pm +++ b/lib/Lutim.pm @@ -137,6 +137,22 @@ sub startup { } )->name('about'); + $r->get('/stats' => sub { + my $c = shift; + + $c->render( + template => 'stats', + total => LutimModel::Lutim->count('WHERE path IS NOT NULL') + ); + + # Check provisioning + $c->on(finish => sub { + shift->provisioning(); + } + ); + } + )->name('stats'); + $r->post('/' => sub { my $c = shift; my $upload = $c->param('file'); diff --git a/lib/Lutim/I18N/en.pm b/lib/Lutim/I18N/en.pm index e39858c..2951857 100644 --- a/lib/Lutim/I18N/en.pm +++ b/lib/Lutim/I18N/en.pm @@ -24,32 +24,35 @@ my $inf_body = < 'License:', - 'fork-me' => 'Fork me on Github !', - 'share-twitter' => 'Share on Twitter', - 'informations' => 'Informations', - 'informations-body' => $inf_body, - 'view-link' => 'View link:', - 'download-link' => 'Download link:', - 'twitter-link' => 'Link for put in a tweet:', - 'some-bad' => 'Something bad happened', - 'delete-first' => 'Delete at first view?', - 'delete-day' => 'Delete after 24 hours?', - 'upload_image' => 'Send an image', - 'image-only' => 'Only images are allowed', - 'go' => 'Let\'s go!', - 'drag-n-drop' => 'Drag & drop images here', - 'or' => '-or-', - 'file-browser' => 'Click to open the file browser', - 'image_not_found' => 'Unable to find the image', - 'no_more_short' => 'There is no more available URL. Retry or contact the administrator. [_1]', - 'no_valid_file' => 'The file [_1] is not an image.', - 'file_too_big' => 'The file exceed the size limit ([_1])', - 'no_time_limit' => 'No time limit', - '24_hours' => '24 hours', - '7_days' => '7 days', - '30_days' => '30 days', - '1_year' => 'One year', + 'license' => 'License:', + 'fork-me' => 'Fork me on Github !', + 'share-twitter' => 'Share on Twitter', + 'informations' => 'Informations', + 'informations-body' => $inf_body, + 'view-link' => 'View link:', + 'download-link' => 'Download link:', + 'twitter-link' => 'Link for put in a tweet:', + 'some-bad' => 'Something bad happened', + 'delete-first' => 'Delete at first view?', + 'delete-day' => 'Delete after 24 hours?', + 'upload_image' => 'Send an image', + 'image-only' => 'Only images are allowed', + 'go' => 'Let\'s go!', + 'drag-n-drop' => 'Drag & drop images here', + 'or' => '-or-', + 'file-browser' => 'Click to open the file browser', + 'image_not_found' => 'Unable to find the image', + 'no_more_short' => 'There is no more available URL. Retry or contact the administrator. [_1]', + 'no_valid_file' => 'The file [_1] is not an image.', + 'file_too_big' => 'The file exceed the size limit ([_1])', + 'no_time_limit' => 'No time limit', + '24_hours' => '24 hours', + '7_days' => '7 days', + '30_days' => '30 days', + '1_year' => 'One year', + 'pushed-images' => ' sent images on this instance from beginning.', + 'graph-data-once-a-day' => 'The graph\'s datas are not updated in real-time.', + 'lutim-stats' => 'LUTIm\'s statistics', 'back-to-index' => 'Back to homepage' ); diff --git a/lib/Lutim/I18N/fr.pm b/lib/Lutim/I18N/fr.pm index 4980e4d..d2898b6 100644 --- a/lib/Lutim/I18N/fr.pm +++ b/lib/Lutim/I18N/fr.pm @@ -24,32 +24,35 @@ my $inf_body = < 'Licence :', - 'fork-me' => 'Fork me on Github', - 'share-twitter' => 'Partager sur Twitter', - 'informations' => 'Informations', - 'informations-body' => $inf_body, - 'view-link' => 'Lien d\'affichage :', - 'download-link' => 'Lien de téléchargement :', - 'twitter-link' => 'Lien pour mettre dans un tweet :', - 'some-bad' => 'Un problème est survenu', - 'delete-first' => 'Supprimer au premier accès ?', - 'delete-day' => 'Supprimer après 24 heures ?', - 'upload_image' => 'Envoyez une image', - 'image-only' => 'Seules les images sont acceptées', - 'go' => 'Allons-y !', - 'drag-n-drop' => 'Déposez vos images ici', - 'or' => '-ou-', - 'file-browser' => 'Cliquez pour utiliser le navigateur de fichier', - 'image_not_found' => 'Impossible de trouver l\'image', - 'no_more_short' => 'Il n\'y a plus d\'URL disponible. Veuillez réessayer ou contactez l\'administrateur. [_1].', - 'no_valid_file' => 'Le fichier [_1] n\'est pas une image.', - 'file_too_big' => 'Le fichier dépasse la limite de taille ([_1])', - 'no_time_limit' => 'Pas de limitation de durée', - '24_hours' => '24 heures', - '7_days' => '7 jours', - '30_days' => '30 jours', - '1_year' => 'Un an', + 'license' => 'Licence :', + 'fork-me' => 'Fork me on Github', + 'share-twitter' => 'Partager sur Twitter', + 'informations' => 'Informations', + 'informations-body' => $inf_body, + 'view-link' => 'Lien d\'affichage :', + 'download-link' => 'Lien de téléchargement :', + 'twitter-link' => 'Lien pour mettre dans un tweet :', + 'some-bad' => 'Un problème est survenu', + 'delete-first' => 'Supprimer au premier accès ?', + 'delete-day' => 'Supprimer après 24 heures ?', + 'upload_image' => 'Envoyez une image', + 'image-only' => 'Seules les images sont acceptées', + 'go' => 'Allons-y !', + 'drag-n-drop' => 'Déposez vos images ici', + 'or' => '-ou-', + 'file-browser' => 'Cliquez pour utiliser le navigateur de fichier', + 'image_not_found' => 'Impossible de trouver l\'image', + 'no_more_short' => 'Il n\'y a plus d\'URL disponible. Veuillez réessayer ou contactez l\'administrateur. [_1].', + 'no_valid_file' => 'Le fichier [_1] n\'est pas une image.', + 'file_too_big' => 'Le fichier dépasse la limite de taille ([_1])', + 'no_time_limit' => 'Pas de limitation de durée', + '24_hours' => '24 heures', + '7_days' => '7 jours', + '30_days' => '30 jours', + '1_year' => 'Un an', + 'pushed-images' => ' images envoyées sur cette instance depuis le début.', + 'graph-data-once-a-day' => 'Les données du graphique ne sont pas mises à jour en temps réél.', + 'lutim-stats' => 'Statistiques de LUTIm', 'back-to-index' => 'Retour à la page d\'accueil' ); diff --git a/lib/Mojolicious/Command/cron.pm b/lib/Mojolicious/Command/cron.pm new file mode 100644 index 0000000..10a2820 --- /dev/null +++ b/lib/Mojolicious/Command/cron.pm @@ -0,0 +1,26 @@ +package Mojolicious::Command::cron; +use Mojo::Base 'Mojolicious::Commands'; + +has description => 'Execute tasks.'; +has hint => < sub { shift->extract_usage . "\nCron tasks:\n" }; +has namespaces => sub { ['Mojolicious::Command::cron'] }; + +sub help { shift->run(@_) } + +1; + +=encoding utf8 + +=head1 NAME + +Mojolicious::Command::cron - Cron commands + +=head1 SYNOPSIS + + Usage: script/lutim cron TASK [OPTIONS] + +=cut diff --git a/lib/Mojolicious/Command/cron/stats.pm b/lib/Mojolicious/Command/cron/stats.pm new file mode 100644 index 0000000..846fa05 --- /dev/null +++ b/lib/Mojolicious/Command/cron/stats.pm @@ -0,0 +1,64 @@ +package Mojolicious::Command::cron::stats; +use Mojo::Base 'Mojolicious::Command'; +use LutimModel; +use Mojo::DOM; +use Mojo::Util qw(slurp spurt decode); +use DateTime; +use Mojolicious::Plugin::Config; + +has description => 'Generate statistics about LUTIm.'; +has usage => sub { shift->extract_usage }; + +sub run { + my $c = shift; + + my $config = Mojolicious::Plugin::Config->parse(decode('UTF-8', slurp 'lutim.conf'), 'lutim.conf'); + $config->{stats_day_num} = (defined($config->{stats_day_num})) ? $config->{stats_day_num} : 365; + + my $text = slurp('templates/data.html.ep.template'); + my $dom = Mojo::DOM->new($text); + my $thead_tr = $dom->at('table thead tr'); + my $tbody_tr = $dom->at('table tbody tr'); + my $tbody_t2 = $tbody_tr->next; + + my $separation = time() - $config->{stats_day_num} * 86400; + + my %data; + for my $img (LutimModel::Lutim->select('WHERE path IS NOT NULL AND created_at > = ?', $separation)) { + my $time = DateTime->from_epoch(epoch => $img->created_at); + my ($year, $month, $day) = ($time->year(), $time->month(), $time->day()); + + if (defined($data{$year}->{$month}->{$day})) { + $data{$year}->{$month}->{$day} += 1; + } else { + $data{$year}->{$month}->{$day} = 1; + } + } + + my $total = LutimModel::Lutim->count('WHERE path IS NOT NULL AND created_at < ?', $separation); + for my $year (sort keys %data) { + for my $month (sort keys %{$data{$year}}) { + for my $day (sort keys %{$data{$year}->{$month}}) { + $thead_tr->append_content(''."$day/$month/$year".''."\n"); + $tbody_tr->append_content(''.$data{$year}->{$month}->{$day}.''."\n"); + $total += $data{$year}->{$month}->{$day}; + $tbody_t2->append_content(''.$total.''."\n"); + } + } + } + spurt $dom, 'templates/data.html.ep'; +} + +=encoding utf8 + +=head1 NAME + +Mojolicious::Command::cron::stats - Stats generator + +=head1 SYNOPSIS + + Usage: script/lutim cron stats + +=cut + +1; diff --git a/lutim.conf.template b/lutim.conf.template index 176b0da..1d33e89 100644 --- a/lutim.conf.template +++ b/lutim.conf.template @@ -12,8 +12,9 @@ length => 8, # optional provis_step => 5, # optional provisioning => 100, # optional - hosted_by => 'My super hoster Hoster logo', # optional tweet_card_via => '@framasky', # optional max_file_size => 10485760, # optional, size in octets, you can write it 10*1024*1024 - https => 0, # optional, set to 1 if you use Lutim behind a secure web server + #hosted_by => 'My super hoster Hoster logo', # optional + #https => 0, # optional, set to 1 if you use Lutim behind a secure web server + #stats_day_num => 365, # optional, number of days shown in /stats page }; diff --git a/public/css/bootstrap.css b/public/css/bootstrap.css index 10bb9af..e96f4f9 100644 --- a/public/css/bootstrap.css +++ b/public/css/bootstrap.css @@ -680,6 +680,235 @@ address { font-style: normal; line-height: 1.42857143; } +table { + max-width: 100%; + background-color: transparent; +} +th { + text-align: left; +} +.table { + width: 100%; + margin-bottom: 20px; +} +.table > thead > tr > th, +.table > tbody > tr > th, +.table > tfoot > tr > th, +.table > thead > tr > td, +.table > tbody > tr > td, +.table > tfoot > tr > td { + padding: 8px; + line-height: 1.42857143; + vertical-align: top; + border-top: 1px solid #dddddd; +} +.table > thead > tr > th { + vertical-align: bottom; + border-bottom: 2px solid #dddddd; +} +.table > caption + thead > tr:first-child > th, +.table > colgroup + thead > tr:first-child > th, +.table > thead:first-child > tr:first-child > th, +.table > caption + thead > tr:first-child > td, +.table > colgroup + thead > tr:first-child > td, +.table > thead:first-child > tr:first-child > td { + border-top: 0; +} +.table > tbody + tbody { + border-top: 2px solid #dddddd; +} +.table .table { + background-color: #ffffff; +} +.table-condensed > thead > tr > th, +.table-condensed > tbody > tr > th, +.table-condensed > tfoot > tr > th, +.table-condensed > thead > tr > td, +.table-condensed > tbody > tr > td, +.table-condensed > tfoot > tr > td { + padding: 5px; +} +.table-bordered { + border: 1px solid #dddddd; +} +.table-bordered > thead > tr > th, +.table-bordered > tbody > tr > th, +.table-bordered > tfoot > tr > th, +.table-bordered > thead > tr > td, +.table-bordered > tbody > tr > td, +.table-bordered > tfoot > tr > td { + border: 1px solid #dddddd; +} +.table-bordered > thead > tr > th, +.table-bordered > thead > tr > td { + border-bottom-width: 2px; +} +.table-striped > tbody > tr:nth-child(odd) > td, +.table-striped > tbody > tr:nth-child(odd) > th { + background-color: #f9f9f9; +} +.table-hover > tbody > tr:hover > td, +.table-hover > tbody > tr:hover > th { + background-color: #f5f5f5; +} +table col[class*="col-"] { + position: static; + float: none; + display: table-column; +} +table td[class*="col-"], +table th[class*="col-"] { + position: static; + float: none; + display: table-cell; +} +.table > thead > tr > td.active, +.table > tbody > tr > td.active, +.table > tfoot > tr > td.active, +.table > thead > tr > th.active, +.table > tbody > tr > th.active, +.table > tfoot > tr > th.active, +.table > thead > tr.active > td, +.table > tbody > tr.active > td, +.table > tfoot > tr.active > td, +.table > thead > tr.active > th, +.table > tbody > tr.active > th, +.table > tfoot > tr.active > th { + background-color: #f5f5f5; +} +.table-hover > tbody > tr > td.active:hover, +.table-hover > tbody > tr > th.active:hover, +.table-hover > tbody > tr.active:hover > td, +.table-hover > tbody > tr.active:hover > th { + background-color: #e8e8e8; +} +.table > thead > tr > td.success, +.table > tbody > tr > td.success, +.table > tfoot > tr > td.success, +.table > thead > tr > th.success, +.table > tbody > tr > th.success, +.table > tfoot > tr > th.success, +.table > thead > tr.success > td, +.table > tbody > tr.success > td, +.table > tfoot > tr.success > td, +.table > thead > tr.success > th, +.table > tbody > tr.success > th, +.table > tfoot > tr.success > th { + background-color: #dff0d8; +} +.table-hover > tbody > tr > td.success:hover, +.table-hover > tbody > tr > th.success:hover, +.table-hover > tbody > tr.success:hover > td, +.table-hover > tbody > tr.success:hover > th { + background-color: #d0e9c6; +} +.table > thead > tr > td.info, +.table > tbody > tr > td.info, +.table > tfoot > tr > td.info, +.table > thead > tr > th.info, +.table > tbody > tr > th.info, +.table > tfoot > tr > th.info, +.table > thead > tr.info > td, +.table > tbody > tr.info > td, +.table > tfoot > tr.info > td, +.table > thead > tr.info > th, +.table > tbody > tr.info > th, +.table > tfoot > tr.info > th { + background-color: #d9edf7; +} +.table-hover > tbody > tr > td.info:hover, +.table-hover > tbody > tr > th.info:hover, +.table-hover > tbody > tr.info:hover > td, +.table-hover > tbody > tr.info:hover > th { + background-color: #c4e3f3; +} +.table > thead > tr > td.warning, +.table > tbody > tr > td.warning, +.table > tfoot > tr > td.warning, +.table > thead > tr > th.warning, +.table > tbody > tr > th.warning, +.table > tfoot > tr > th.warning, +.table > thead > tr.warning > td, +.table > tbody > tr.warning > td, +.table > tfoot > tr.warning > td, +.table > thead > tr.warning > th, +.table > tbody > tr.warning > th, +.table > tfoot > tr.warning > th { + background-color: #fcf8e3; +} +.table-hover > tbody > tr > td.warning:hover, +.table-hover > tbody > tr > th.warning:hover, +.table-hover > tbody > tr.warning:hover > td, +.table-hover > tbody > tr.warning:hover > th { + background-color: #faf2cc; +} +.table > thead > tr > td.danger, +.table > tbody > tr > td.danger, +.table > tfoot > tr > td.danger, +.table > thead > tr > th.danger, +.table > tbody > tr > th.danger, +.table > tfoot > tr > th.danger, +.table > thead > tr.danger > td, +.table > tbody > tr.danger > td, +.table > tfoot > tr.danger > td, +.table > thead > tr.danger > th, +.table > tbody > tr.danger > th, +.table > tfoot > tr.danger > th { + background-color: #f2dede; +} +.table-hover > tbody > tr > td.danger:hover, +.table-hover > tbody > tr > th.danger:hover, +.table-hover > tbody > tr.danger:hover > td, +.table-hover > tbody > tr.danger:hover > th { + background-color: #ebcccc; +} +@media (max-width: 767px) { + .table-responsive { + width: 100%; + margin-bottom: 15px; + overflow-y: hidden; + overflow-x: scroll; + -ms-overflow-style: -ms-autohiding-scrollbar; + border: 1px solid #dddddd; + -webkit-overflow-scrolling: touch; + } + .table-responsive > .table { + margin-bottom: 0; + } + .table-responsive > .table > thead > tr > th, + .table-responsive > .table > tbody > tr > th, + .table-responsive > .table > tfoot > tr > th, + .table-responsive > .table > thead > tr > td, + .table-responsive > .table > tbody > tr > td, + .table-responsive > .table > tfoot > tr > td { + white-space: nowrap; + } + .table-responsive > .table-bordered { + border: 0; + } + .table-responsive > .table-bordered > thead > tr > th:first-child, + .table-responsive > .table-bordered > tbody > tr > th:first-child, + .table-responsive > .table-bordered > tfoot > tr > th:first-child, + .table-responsive > .table-bordered > thead > tr > td:first-child, + .table-responsive > .table-bordered > tbody > tr > td:first-child, + .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + .table-responsive > .table-bordered > thead > tr > th:last-child, + .table-responsive > .table-bordered > tbody > tr > th:last-child, + .table-responsive > .table-bordered > tfoot > tr > th:last-child, + .table-responsive > .table-bordered > thead > tr > td:last-child, + .table-responsive > .table-bordered > tbody > tr > td:last-child, + .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + .table-responsive > .table-bordered > tbody > tr:last-child > th, + .table-responsive > .table-bordered > tfoot > tr:last-child > th, + .table-responsive > .table-bordered > tbody > tr:last-child > td, + .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; + } +} fieldset { padding: 0; margin: 0; diff --git a/public/css/bootstrap.min.css b/public/css/bootstrap.min.css index fb0732d..a67de5c 100644 --- a/public/css/bootstrap.min.css +++ b/public/css/bootstrap.min.css @@ -4,4 +4,4 @@ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ -/*! normalize.css v3.0.0 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:0.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace, monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}@media print{*{text-shadow:none !important;color:#000 !important;background:transparent !important;box-shadow:none !important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff !important}.navbar{display:none}.table td,.table th{background-color:#fff !important}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000 !important}.label{border:1px solid #000}.table{border-collapse:collapse !important}.table-bordered th,.table-bordered td{border:1px solid #ddd !important}}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:62.5%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#428bca;text-decoration:none}a:hover,a:focus{color:#2a6496;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:normal;line-height:1;color:#999}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:200;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}cite{font-style:normal}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-muted{color:#999}.text-primary{color:#428bca}a.text-primary:hover{color:#3071a9}.text-success{color:#3c763d}a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#428bca}a.bg-primary:hover{background-color:#3071a9}.bg-success{background-color:#dff0d8}a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin-left:-5px}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.42857143}dt{font-weight:bold}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.42857143;color:#999}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0;text-align:right}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}blockquote:before,blockquote:after{content:""}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}fieldset{padding:0;margin:0;border:0;min-width:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;margin-bottom:5px;font-weight:bold}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="file"]{display:block}input[type="range"]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee;opacity:1}textarea.form-control{height:auto}input[type="search"]{-webkit-appearance:none}input[type="date"]{line-height:34px}.form-group{margin-bottom:15px}.radio,.checkbox{display:block;min-height:20px;margin-top:10px;margin-bottom:10px;padding-left:20px}.radio label,.checkbox label{display:inline;font-weight:normal;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{float:left;margin-left:-20px}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:normal;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type="radio"][disabled],input[type="checkbox"][disabled],.radio[disabled],.radio-inline[disabled],.checkbox[disabled],.checkbox-inline[disabled],fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"],fieldset[disabled] .radio,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm,select[multiple].input-sm{height:auto}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-lg{height:46px;line-height:46px}textarea.input-lg,select[multiple].input-lg{height:auto}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.has-feedback .form-control-feedback{position:absolute;top:25px;right:0;display:block;width:34px;height:34px;line-height:34px;text-align:center}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;border-color:#3c763d;background-color:#dff0d8}.has-success .form-control-feedback{color:#3c763d}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;border-color:#8a6d3b;background-color:#fcf8e3}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;border-color:#a94442;background-color:#f2dede}.has-error .form-control-feedback{color:#a94442}.form-control-static{margin-bottom:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;padding-left:0;vertical-align:middle}.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:none;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .control-label,.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:0;margin-bottom:0;padding-top:7px}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}.form-horizontal .form-control-static{padding-top:7px}@media (min-width:768px){.form-horizontal .control-label{text-align:right}}.form-horizontal .has-feedback .form-control-feedback{top:0;right:15px}.btn{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn:focus,.btn:active:focus,.btn.active:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus{color:#333;text-decoration:none}.btn:active,.btn.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;pointer-events:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{color:#333;background-color:#ebebeb;border-color:#adadad}.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#428bca;border-color:#357ebd}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{color:#fff;background-color:#3276b1;border-color:#285e8e}.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#428bca;border-color:#357ebd}.btn-primary .badge{color:#428bca;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{color:#fff;background-color:#47a447;border-color:#398439}.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{color:#fff;background-color:#39b3d7;border-color:#269abc}.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{color:#fff;background-color:#ed9c28;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{color:#fff;background-color:#d2322d;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{color:#428bca;font-weight:normal;cursor:pointer;border-radius:0}.btn-link,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#2a6496;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#999;text-decoration:none}.btn-lg{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%;padding-left:0;padding-right:0}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;transition:height .35s ease}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*="col-"]{float:none;padding-left:0;padding-right:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:normal;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type="radio"],.input-group-addon input[type="checkbox"]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{margin-left:-1px}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:bold}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable{padding-right:35px}.alert-dismissable .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#3c763d}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#31708f}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{background-color:#fcf8e3;border-color:#faebcc;color:#8a6d3b}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{background-color:#f2dede;border-color:#ebccd1;color:#a94442}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{overflow:hidden;height:20px;margin-bottom:20px;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress-bar{float:left;width:0%;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#428bca;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-size:40px 40px}.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.close{float:right;font-size:21px;font-weight:bold;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{display:none;overflow:auto;overflow-y:scroll;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate(0, -25%);-ms-transform:translate(0, -25%);transform:translate(0, -25%);-webkit-transition:-webkit-transform 0.3s ease-out;-moz-transition:-moz-transform 0.3s ease-out;-o-transition:-o-transform 0.3s ease-out;transition:transform 0.3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0, 0);-ms-transform:translate(0, 0);transform:translate(0, 0)}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.2);border-radius:6px;-webkit-box-shadow:0 3px 9px rgba(0,0,0,0.5);box-shadow:0 3px 9px rgba(0,0,0,0.5);background-clip:padding-box;outline:none}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5;min-height:16.42857143px}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:20px}.modal-footer{margin-top:15px;padding:19px 20px 20px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,0.5);box-shadow:0 5px 15px rgba(0,0,0,0.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.clearfix:before,.clearfix:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.modal-footer:before,.modal-footer:after{content:" ";display:table}.clearfix:after,.form-horizontal .form-group:after,.modal-footer:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right !important}.pull-left{float:left !important}.hide{display:none !important}.show{display:block !important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none !important;visibility:hidden !important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg{display:none !important}@media (max-width:767px){.visible-xs{display:block !important}table.visible-xs{display:table}tr.visible-xs{display:table-row !important}th.visible-xs,td.visible-xs{display:table-cell !important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block !important}table.visible-sm{display:table}tr.visible-sm{display:table-row !important}th.visible-sm,td.visible-sm{display:table-cell !important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block !important}table.visible-md{display:table}tr.visible-md{display:table-row !important}th.visible-md,td.visible-md{display:table-cell !important}}@media (min-width:1200px){.visible-lg{display:block !important}table.visible-lg{display:table}tr.visible-lg{display:table-row !important}th.visible-lg,td.visible-lg{display:table-cell !important}}@media (max-width:767px){.hidden-xs{display:none !important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none !important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none !important}}@media (min-width:1200px){.hidden-lg{display:none !important}}.visible-print{display:none !important}@media print{.visible-print{display:block !important}table.visible-print{display:table}tr.visible-print{display:table-row !important}th.visible-print,td.visible-print{display:table-cell !important}}@media print{.hidden-print{display:none !important}} \ No newline at end of file +/*! normalize.css v3.0.0 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:0.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace, monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}@media print{*{text-shadow:none !important;color:#000 !important;background:transparent !important;box-shadow:none !important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff !important}.navbar{display:none}.table td,.table th{background-color:#fff !important}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000 !important}.label{border:1px solid #000}.table{border-collapse:collapse !important}.table-bordered th,.table-bordered td{border:1px solid #ddd !important}}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:62.5%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#428bca;text-decoration:none}a:hover,a:focus{color:#2a6496;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:normal;line-height:1;color:#999}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:200;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}cite{font-style:normal}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-muted{color:#999}.text-primary{color:#428bca}a.text-primary:hover{color:#3071a9}.text-success{color:#3c763d}a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#428bca}a.bg-primary:hover{background-color:#3071a9}.bg-success{background-color:#dff0d8}a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin-left:-5px}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.42857143}dt{font-weight:bold}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.42857143;color:#999}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0;text-align:right}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}blockquote:before,blockquote:after{content:""}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}table{max-width:100%;background-color:transparent}th{text-align:left}.table{width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-child(odd)>td,.table-striped>tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover>tbody>tr:hover>td,.table-hover>tbody>tr:hover>th{background-color:#f5f5f5}table col[class*="col-"]{position:static;float:none;display:table-column}table td[class*="col-"],table th[class*="col-"]{position:static;float:none;display:table-cell}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}@media (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;overflow-x:scroll;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd;-webkit-overflow-scrolling:touch}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0;min-width:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;margin-bottom:5px;font-weight:bold}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="file"]{display:block}input[type="range"]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee;opacity:1}textarea.form-control{height:auto}input[type="search"]{-webkit-appearance:none}input[type="date"]{line-height:34px}.form-group{margin-bottom:15px}.radio,.checkbox{display:block;min-height:20px;margin-top:10px;margin-bottom:10px;padding-left:20px}.radio label,.checkbox label{display:inline;font-weight:normal;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{float:left;margin-left:-20px}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:normal;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type="radio"][disabled],input[type="checkbox"][disabled],.radio[disabled],.radio-inline[disabled],.checkbox[disabled],.checkbox-inline[disabled],fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"],fieldset[disabled] .radio,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm,select[multiple].input-sm{height:auto}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-lg{height:46px;line-height:46px}textarea.input-lg,select[multiple].input-lg{height:auto}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.has-feedback .form-control-feedback{position:absolute;top:25px;right:0;display:block;width:34px;height:34px;line-height:34px;text-align:center}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;border-color:#3c763d;background-color:#dff0d8}.has-success .form-control-feedback{color:#3c763d}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;border-color:#8a6d3b;background-color:#fcf8e3}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;border-color:#a94442;background-color:#f2dede}.has-error .form-control-feedback{color:#a94442}.form-control-static{margin-bottom:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;padding-left:0;vertical-align:middle}.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:none;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .control-label,.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:0;margin-bottom:0;padding-top:7px}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}.form-horizontal .form-control-static{padding-top:7px}@media (min-width:768px){.form-horizontal .control-label{text-align:right}}.form-horizontal .has-feedback .form-control-feedback{top:0;right:15px}.btn{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn:focus,.btn:active:focus,.btn.active:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus{color:#333;text-decoration:none}.btn:active,.btn.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;pointer-events:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{color:#333;background-color:#ebebeb;border-color:#adadad}.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#428bca;border-color:#357ebd}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{color:#fff;background-color:#3276b1;border-color:#285e8e}.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#428bca;border-color:#357ebd}.btn-primary .badge{color:#428bca;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{color:#fff;background-color:#47a447;border-color:#398439}.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{color:#fff;background-color:#39b3d7;border-color:#269abc}.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{color:#fff;background-color:#ed9c28;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{color:#fff;background-color:#d2322d;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{color:#428bca;font-weight:normal;cursor:pointer;border-radius:0}.btn-link,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#2a6496;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#999;text-decoration:none}.btn-lg{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%;padding-left:0;padding-right:0}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;transition:height .35s ease}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*="col-"]{float:none;padding-left:0;padding-right:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:normal;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type="radio"],.input-group-addon input[type="checkbox"]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{margin-left:-1px}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:bold}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable{padding-right:35px}.alert-dismissable .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#3c763d}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#31708f}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{background-color:#fcf8e3;border-color:#faebcc;color:#8a6d3b}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{background-color:#f2dede;border-color:#ebccd1;color:#a94442}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{overflow:hidden;height:20px;margin-bottom:20px;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress-bar{float:left;width:0%;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#428bca;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-size:40px 40px}.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.close{float:right;font-size:21px;font-weight:bold;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{display:none;overflow:auto;overflow-y:scroll;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate(0, -25%);-ms-transform:translate(0, -25%);transform:translate(0, -25%);-webkit-transition:-webkit-transform 0.3s ease-out;-moz-transition:-moz-transform 0.3s ease-out;-o-transition:-o-transform 0.3s ease-out;transition:transform 0.3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0, 0);-ms-transform:translate(0, 0);transform:translate(0, 0)}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.2);border-radius:6px;-webkit-box-shadow:0 3px 9px rgba(0,0,0,0.5);box-shadow:0 3px 9px rgba(0,0,0,0.5);background-clip:padding-box;outline:none}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5;min-height:16.42857143px}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:20px}.modal-footer{margin-top:15px;padding:19px 20px 20px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,0.5);box-shadow:0 5px 15px rgba(0,0,0,0.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.clearfix:before,.clearfix:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.modal-footer:before,.modal-footer:after{content:" ";display:table}.clearfix:after,.form-horizontal .form-group:after,.modal-footer:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right !important}.pull-left{float:left !important}.hide{display:none !important}.show{display:block !important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none !important;visibility:hidden !important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg{display:none !important}@media (max-width:767px){.visible-xs{display:block !important}table.visible-xs{display:table}tr.visible-xs{display:table-row !important}th.visible-xs,td.visible-xs{display:table-cell !important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block !important}table.visible-sm{display:table}tr.visible-sm{display:table-row !important}th.visible-sm,td.visible-sm{display:table-cell !important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block !important}table.visible-md{display:table}tr.visible-md{display:table-row !important}th.visible-md,td.visible-md{display:table-cell !important}}@media (min-width:1200px){.visible-lg{display:block !important}table.visible-lg{display:table}tr.visible-lg{display:table-row !important}th.visible-lg,td.visible-lg{display:table-cell !important}}@media (max-width:767px){.hidden-xs{display:none !important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none !important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none !important}}@media (min-width:1200px){.hidden-lg{display:none !important}}.visible-print{display:none !important}@media print{.visible-print{display:block !important}table.visible-print{display:table}tr.visible-print{display:table-row !important}th.visible-print,td.visible-print{display:table-cell !important}}@media print{.hidden-print{display:none !important}} \ No newline at end of file diff --git a/public/js/jquery.simplegraph.js b/public/js/jquery.simplegraph.js new file mode 100644 index 0000000..bd17c8a --- /dev/null +++ b/public/js/jquery.simplegraph.js @@ -0,0 +1,346 @@ +function SimpleGraph(data, labels, canvas, settings) { + + this.settings = settings; + + setStyleDefaults(settings); + + this.dataSet = new DataSet(data, labels, this.settings); + this.grid = new Grid(this.dataSet, this.settings); + this.canvas = canvas; + + this.draw = function() { + if (this.settings.drawGrid) { + this.grid.draw(this.canvas); + } + if (this.settings.yAxisCaption) { + this.dataSet.labelYAxis(this.grid, this.canvas); + } + this.dataSet.labelXAxis(this.grid, this.canvas); + this.dataSet.plot(this.grid, this.canvas); + }; + + this.replaceDataSet = function(dataSet) { + this.dataSet = new DataSet(dataSet, dataSet.labels, this.settings); + this.grid = new Grid(this.dataSet, this.settings); + }; + + this.plotCurrentDataSet = function() { + this.dataSet.plot(this.grid, this.canvas); + }; + + function setStyleDefaults(settings) { + var targets = ["xAxisLabel", "yAxisLabel", "yAxisCaption", "hoverLabel", "hoverValue"]; + var types = ["Color", "Font", "FontSize", "FontWeight"]; + jQuery.each(targets, function(index, target) { + jQuery.each(types, function(index, type) { + if (!settings[target + type]) { + settings[target + type] = settings["label" + type]; + } + }); + }); + + settings.labelStyle = { + font: settings.labelFontSize + '"' + settings.labelFont + '"', + fill: settings.labelColor + }; + + jQuery.each(targets, function(index, target) { + settings[target + "Style"] = { + font: settings[target + "FontSize"] + ' ' + settings[target + "Font"], + fill: settings[target + "Color"], + "font-weight": settings[target + "FontWeight"] + }; + }); + } +} + +// Holds the data and labels to be plotted, provides methods for labelling the x and y axes, +// and for plotting it's own points. Each method requires a grid object for translating values to +// x,y pixel coordinates and a canvas object on which to draw. +function DataSet(data, labels, settings) { + this.data = data; + this.labels = labels; + this.settings = settings; + + this.labelXAxis = function(grid, canvas) { + (function(ds) { + jQuery.each(ds.labels, function(i, label) { + var x = grid.x(i); + canvas.text(x + ds.settings.xAxisLabelOffset, ds.settings.height - 6, label).attr(ds.settings.xAxisLabelStyle); + }); + })(this); + }; + + this.labelYAxis = function(grid, canvas) { + // Legend + canvas.rect( + grid.leftEdge - (30 + this.settings.yAxisOffset), //TODO PARAM - Label Colum Width + grid.topEdge, + 30, //TODO PARAM - Label Column Width + grid.height + ).attr({stroke: this.settings.lineColor, fill: this.settings.lineColor, opacity: 0.3}); //TODO PARAMS - legend border and fill style + + for (var i = 1, ii = (grid.rows); i < (ii - this.settings.lowerBound/2); i = i + 2) { + var value = (ii - i)*2, + y = grid.y(value) + 4, // TODO: Value of 4 works for default dimensions, expect will need to scale + x = grid.leftEdge - (6 + this.settings.yAxisOffset); + canvas.text(x, y, value).attr(this.settings.yAxisLabelStyle); + } + var caption = canvas.text( + grid.leftEdge - (20 + this.settings.yAxisOffset), + (grid.height/2) + (this.settings.yAxisCaption.length / 2), + this.settings.yAxisCaption + " (" + this.settings.units + ")").attr(this.settings.yAxisCaptionStyle).rotate(270); + // Increase the offset for the next caption (if any) + this.settings.yAxisOffset = this.settings.yAxisOffset + 30; + }; + + this.plot = function(grid, canvas) { + var line_path = canvas.path({ + stroke: this.settings.lineColor, + "stroke-width": this.settings.lineWidth, + "stroke-linejoin": this.settings.lineJoin + }); + + var fill_path = canvas.path({ + stroke: "none", + fill: this.settings.fillColor, + opacity: this.settings.fillOpacity + }).moveTo(this.settings.leftGutter, this.settings.height - this.settings.bottomGutter); + + var bars = canvas.group(), + dots = canvas.group(), + cover = canvas.group(); + + var hoverFrame = dots.rect(10, 10, 100, 40, 5).attr({ + fill: "#fff", stroke: "#474747", "stroke-width": 2}).hide(); //TODO PARAM - fill colour, border colour, border width + var hoverText = []; + hoverText[0] = canvas.text(60, 25, "").attr(this.settings.hoverValueStyle).hide(); + hoverText[1] = canvas.text(60, 40, "").attr(this.settings.hoverLabelStyle).hide(); + + // Plot the points + (function(dataSet) { + jQuery.each(dataSet.data, function(i, value) { + var y = grid.y(value), + x = grid.x(i), + label = dataSet.labels ? dataSet.labels[i] : " "; + + if (dataSet.settings.drawPoints) { + var dot = dots.circle(x, y, dataSet.settings.pointRadius).attr({fill: dataSet.settings.pointColor, stroke: dataSet.settings.pointColor}); + } + if (dataSet.settings.drawBars) { + bars.rect(x + dataSet.settings.barOffset, y, dataSet.settings.barWidth, (dataSet.settings.height - dataSet.settings.bottomGutter) - y).attr({fill: dataSet.settings.barColor, stroke: "none"}); + } + if (dataSet.settings.drawLine) { + line_path[i == 0 ? "moveTo" : "cplineTo"](x, y, 5); + } + if (dataSet.settings.fillUnderLine) { + fill_path[i == 0 ? "lineTo" : "cplineTo"](x, y, 5); + } + if (dataSet.settings.addHover) { + var rect = canvas.rect(x - 50, y - 50, 100, 100).attr({stroke: "none", fill: "#fff", opacity: 0}); //TODO PARAM - hover target width / height + jQuery(rect[0]).hover( function() { + jQuery.fn.simplegraph.hoverIn(canvas, value, label, x, y, hoverFrame, hoverText, dot, dataSet.settings); + }, + function() { + jQuery.fn.simplegraph.hoverOut(canvas, hoverFrame, hoverText, dot, dataSet.settings); + }); + } + }); + })(this); + + if (this.settings.fillUnderLine) { + fill_path.lineTo(grid.x(this.data.length - 1), this.settings.height - this.settings.bottomGutter).andClose(); + } + hoverFrame.toFront(); + }; +} + +// Holds the dimensions of the grid, and provides methods to convert values into x,y +// pixel coordinates. Also, provides a method to draw a grid on a supplied canvas. +function Grid(dataSet, settings) { + this.dataSet = dataSet; + this.settings = settings; + + this.calculateMaxYAxis = function() { + var max = Math.max.apply(Math, this.dataSet.data), + maxOveride = this.settings.minYAxisValue; + if (maxOveride && maxOveride > max) { + max = maxOveride; + } + return max; + }; + + this.setYAxis = function() { + this.height = this.settings.height - this.settings.topGutter - this.settings.bottomGutter; + this.maxValueYAxis = this.calculateMaxYAxis(); + this.Y = this.height / (this.maxValueYAxis - this.settings.lowerBound); + }; + + this.setXAxis = function() { + this.X = (this.settings.width - this.settings.leftGutter) / (this.dataSet.data.length - 0.4); + }; + + this.setDimensions = function() { + this.leftEdge = this.settings.leftGutter; + this.topEdge = this.settings.topGutter; + this.width = this.settings.width - this.settings.leftGutter - this.X; + this.columns = this.dataSet.data.length - 1; + this.rows = (this.maxValueYAxis - this.settings.lowerBound) / 2; //TODO PARAM - steps per row + }; + + this.draw = function(canvas) { + canvas.drawGrid( + this.leftEdge, + this.topEdge, + this.width, + this.height, + this.columns, + this.rows, + this.settings.gridBorderColor + ); + }; + + this.x = function(value) { + return this.settings.leftGutter + this.X * value; + }; + + this.y = function(value) { + return this.settings.height - this.settings.bottomGutter - this.Y * (value - this.settings.lowerBound); + }; + + this.setYAxis(); + this.setXAxis(); + this.setDimensions(); + +}; + +(function($) { + + //- required to implement hover function + var isLabelVisible; + var leaveTimer; + + $.fn.simplegraph = function(data, labels, options) { + var settings = $.extend({}, $.fn.simplegraph.defaults, options); + setPenColor(settings); + + return this.each( function() { + var canvas = Raphael(this, settings.width, settings.height); + var simplegraph = new SimpleGraph(data, labels, canvas, settings); + + simplegraph.draw(); + + // Stash simplegraph object away for future reference + $.data(this, "simplegraph", simplegraph); + }); + }; + + // Plot another set of values on an existing graph, use it like this: + // $("#target").simplegraph(data, labels).simplegraph_more(moreData); + $.fn.simplegraph_more = function(data, options) { + return this.each( function() { + var sg = $.data(this, "simplegraph"); + sg.dataSet = new DataSet(data, sg.dataSet.labels, sg.settings); + sg.settings.penColor = options.penColor; + setPenColor(sg.settings); + sg.settings = $.extend(sg.settings, options); + sg.grid = new Grid(sg.dataSet, sg.settings); + sg.dataSet.labelYAxis(sg.grid, sg.canvas); + sg.dataSet.plot(sg.grid, sg.canvas); + }); + }; + + // Public + + $.fn.simplegraph.defaults = { + drawGrid: false, + units: "", + // Dimensions + width: 600, + height: 250, + leftGutter: 30, + bottomGutter: 20, + topGutter: 20, + // Label Style + labelColor: "#000", + labelFont: "Helvetica", + labelFontSize: "10px", + labelFontWeight: "normal", + // Grid Style + gridBorderColor: "#ccc", + // -- Y Axis Captions + yAxisOffset: 0, + // -- Y Axis Captions + xAxisLabelOffset: 0, + // Graph Style + // -- Points + drawPoints: false, + pointColor: "#000", + pointRadius: 3, + activePointRadius: 5, + // -- Line + drawLine: true, + lineColor: "#000", + lineWidth: 3, + lineJoin: "round", + // -- Bars + drawBars: false, + barColor: "#000", + barWidth: 10, + barOffset: 0, + // -- Fill + fillUnderLine: false, + fillColor: "#000", + fillOpacity: 0.2, + // -- Hover + addHover: true, + // Calculations + lowerBound: 0 + }; + + // Default hoverIn callback, this is public and as such can be overwritten. You can write your + // own call back with the same signature if you want different behaviour. + $.fn.simplegraph.hoverIn = function(canvas, value, label, x, y, frame, hoverLabel, dot, settings) { + clearTimeout(leaveTimer); + var newcoord = {x: x * 1 + 7.5, y: y - 19}; + if (newcoord.x + 100 > settings.width) { + newcoord.x -= 114; + } + hoverLabel[0].attr({text: value}).show().animate({x : newcoord.x + 50, y : newcoord.y + 15}, (isLabelVisible ? 100 : 0)); + hoverLabel[1].attr({text: label}).show().animate({x : newcoord.x + 50, y : newcoord.y + 30}, (isLabelVisible ? 100 : 0)); + frame.show().animate({x: newcoord.x, y: newcoord.y}, (isLabelVisible ? 100 : 0)); + if (settings.drawPoints) { + dot.attr("r", settings.activePointRadius); + } + isLabelVisible = true; + canvas.safari(); + }; + + // Default hoverOut callback, this is public and as such can be overwritten. You can write your + // own call back with the same signature if you want different behaviour. + $.fn.simplegraph.hoverOut = function(canvas, frame, label, dot, settings) { + if (settings.drawPoints) { + dot.attr("r", settings.pointRadius); + } + canvas.safari(); + leaveTimer = setTimeout(function () { + isLabelVisible = false; + frame.hide(); + label[0].hide(); + label[1].hide(); + canvas.safari(); + }, 1); + }; + + // Private + + function setPenColor(settings) { + if (settings.penColor) { + settings.lineColor = settings.penColor; + settings.pointColor = settings.penColor; + settings.fillColor = settings.penColor; + settings.barColor = settings.penColor; + } + } + +})(jQuery); diff --git a/public/js/raphael.js b/public/js/raphael.js new file mode 100644 index 0000000..3a29d8f --- /dev/null +++ b/public/js/raphael.js @@ -0,0 +1,2215 @@ +/* + * Raphael 0.6.4 - JavaScript Vector Library + * + * Copyright (c) 2008 – 2009 Dmitry Baranovskiy (http://raphaeljs.com) + * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license. + */ +var Raphael = (function (type) { + var r = function () { + return r._create.apply(r, arguments); + }; + r.version = "0.6.4"; + r.type = type; + var availableAttrs = {cx: 0, cy: 0, fill: "#fff", "fill-opacity": 1, font: '16px "Arial"', "font-family": '"Arial"', "font-size": "16", gradient: 0, height: 0, opacity: 1, path: "M0,0", r: 0, rotation: 0, rx: 0, ry: 0, scale: "1 1", stroke: "#000", "stroke-dasharray": "", "stroke-linecap": "butt", "stroke-linejoin": "butt", "stroke-miterlimit": 0, "stroke-opacity": 1, "stroke-width": 1, translation: "0 0", width: 0, x: 0, y: 0}, + availableAnimAttrs = {cx: "number", cy: "number", fill: "colour", "fill-opacity": "number", "font-size": "number", height: "number", opacity: "number", path: "path", r: "number", rotation: "number", rx: "number", ry: "number", scale: "csv", stroke: "colour", "stroke-opacity": "number", "stroke-width": "number", translation: "csv", width: "number", x: "number", y: "number"}, + C = {}; + + if (type == "VML") { + var thePath = function (params, pathString, VML) { + var g = document.createElement("rvml:group"), gl = g.style; + gl.position = "absolute"; + gl.left = 0; + gl.top = 0; + gl.width = VML.width + "px"; + gl.height = VML.height + "px"; + var el = document.createElement("rvml:shape"), ol = el.style; + ol.width = VML.width + "px"; + ol.height = VML.height + "px"; + el.path = ""; + if (params["class"]) { + el.className = params["class"]; + } + el.coordsize = this.coordsize; + el.coordorigin = this.coordorigin; + g.appendChild(el); + VML.canvas.appendChild(g); + var p = new Element(el, g, VML); + p.isAbsolute = true; + p.type = "path"; + p.path = []; + p.last = {x: 0, y: 0, bx: 0, by: 0, isAbsolute: true}; + p.Path = ""; + p.absolutely = function () { + this.isAbsolute = true; + return this; + }; + p.relatively = function () { + this.isAbsolute = false; + return this; + }; + p.moveTo = function (x, y) { + var d = this.isAbsolute?"m":"t"; + d += Math.round(parseFloat(x, 10)) + " " + Math.round(parseFloat(y, 10)); + this.node.path = this.Path += d; + this.last.x = (this.isAbsolute ? 0 : this.last.x) + parseFloat(x, 10); + this.last.y = (this.isAbsolute ? 0 : this.last.y) + parseFloat(y, 10); + this.last.isAbsolute = this.isAbsolute; + this.attrs.path += (this.isAbsolute ? "M" : "m") + [x, y]; + return this; + }; + p.lineTo = function (x, y) { + var d = this.isAbsolute?"l":"r"; + d += Math.round(parseFloat(x, 10)) + " " + Math.round(parseFloat(y, 10)); + this[0].path = this.Path += d; + this.last.x = (this.isAbsolute ? 0 : this.last.x) + parseFloat(x, 10); + this.last.y = (this.isAbsolute ? 0 : this.last.y) + parseFloat(y, 10); + this.last.isAbsolute = this.isAbsolute; + this.attrs.path += (this.isAbsolute ? "L" : "l") + [x, y]; + return this; + }; + p.arcTo = function (rx, ry, large_arc_flag, sweep_flag, x2, y2) { + // for more information of where this math came from visit: + // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes + x2 = (this.isAbsolute ? 0 : this.last.x) + x2; + y2 = (this.isAbsolute ? 0 : this.last.y) + y2; + var x1 = this.last.x, + y1 = this.last.y, + x = (x1 - x2) / 2, + y = (y1 - y2) / 2, + k = (large_arc_flag == sweep_flag ? -1 : 1) * + Math.sqrt(Math.abs(rx * rx * ry * ry - rx * rx * y * y - ry * ry * x * x) / (rx * rx * y * y + ry * ry * x * x)), + cx = k * rx * y / ry + (x1 + x2) / 2, + cy = k * -ry * x / rx + (y1 + y2) / 2, + d = sweep_flag ? (this.isAbsolute ? "wa" : "wr") : (this.isAbsolute ? "at" : "ar"), + left = Math.round(cx - rx), + top = Math.round(cy - ry); + d += [left, top, Math.round(left + rx * 2), Math.round(top + ry * 2), Math.round(x1), Math.round(y1), Math.round(parseFloat(x2, 10)), Math.round(parseFloat(y2, 10))].join(", "); + this.node.path = this.Path += d; + this.last.x = (this.isAbsolute ? 0 : this.last.x) + parseFloat(x2, 10); + this.last.y = (this.isAbsolute ? 0 : this.last.y) + parseFloat(y2, 10); + this.last.isAbsolute = this.isAbsolute; + this.attrs.path += (this.isAbsolute ? "A" : "a") + [rx, ry, 0, large_arc_flag, sweep_flag, x2, y2]; + return this; + }; + p.cplineTo = function (x1, y1, w1) { + if (!w1) { + return this.lineTo(x1, y1); + } else { + var x = Math.round(Math.round(parseFloat(x1, 10) * 100) / 100), + y = Math.round(Math.round(parseFloat(y1, 10) * 100) / 100), + w = Math.round(Math.round(parseFloat(w1, 10) * 100) / 100), + d = this.isAbsolute ? "c" : "v", + attr = [Math.round(this.last.x) + w, Math.round(this.last.y), x - w, y, x, y], + svgattr = [this.last.x + w1, this.last.y, x1 - w1, y1, x1, y1]; + d += attr.join(" ") + " "; + this.last.x = (this.isAbsolute ? 0 : this.last.x) + attr[4]; + this.last.y = (this.isAbsolute ? 0 : this.last.y) + attr[5]; + this.last.bx = attr[2]; + this.last.by = attr[3]; + this.node.path = this.Path += d; + this.attrs.path += (this.isAbsolute ? "C" : "c") + svgattr; + return this; + } + }; + p.curveTo = function () { + var d = this.isAbsolute ? "c" : "v"; + if (arguments.length == 6) { + this.last.bx = (this.isAbsolute ? 0 : this.last.x) + parseFloat(arguments[2], 10); + this.last.by = (this.isAbsolute ? 0 : this.last.y) + parseFloat(arguments[3], 10); + this.last.x = (this.isAbsolute ? 0 : this.last.x) + parseFloat(arguments[4], 10); + this.last.y = (this.isAbsolute ? 0 : this.last.y) + parseFloat(arguments[5], 10); + d += [Math.round(parseFloat(arguments[0], 10)), + Math.round(parseFloat(arguments[1], 10)), + Math.round(parseFloat(arguments[2], 10)), + Math.round(parseFloat(arguments[3], 10)), + Math.round(parseFloat(arguments[4], 10)), + Math.round(parseFloat(arguments[5], 10))].join(" ") + " "; + this.last.isAbsolute = this.isAbsolute; + this.attrs.path += (this.isAbsolute ? "C" : "c") + Array.prototype.splice.call(arguments, 0, arguments.length); + } + if (arguments.length == 4) { + var bx = this.last.x * 2 - this.last.bx; + var by = this.last.y * 2 - this.last.by; + this.last.bx = (this.isAbsolute ? 0 : this.last.x) + parseFloat(arguments[0], 10); + this.last.by = (this.isAbsolute ? 0 : this.last.y) + parseFloat(arguments[1], 10); + this.last.x = (this.isAbsolute ? 0 : this.last.x) + parseFloat(arguments[2], 10); + this.last.y = (this.isAbsolute ? 0 : this.last.y) + parseFloat(arguments[3], 10); + d += [Math.round(bx), Math.round(by), + Math.round(parseFloat(arguments[0], 10)), + Math.round(parseFloat(arguments[1], 10)), + Math.round(parseFloat(arguments[2], 10)), + Math.round(parseFloat(arguments[3], 10))].join(" ") + " "; + this.attrs.path += (this.isAbsolute ? "S" : "s") + Array.prototype.splice.call(arguments, 0, arguments.length); + } + this.node.path = this.Path += d; + return this; + }; + p.qcurveTo = function () { + var d = "qb"; + if (arguments.length == 4) { + this.last.qx = (this.isAbsolute ? 0 : this.last.x) + parseFloat(arguments[0], 10); + this.last.qy = (this.isAbsolute ? 0 : this.last.y) + parseFloat(arguments[1], 10); + this.last.x = (this.isAbsolute ? 0 : this.last.x) + parseFloat(arguments[2], 10); + this.last.y = (this.isAbsolute ? 0 : this.last.y) + parseFloat(arguments[3], 10); + d += [Math.round(this.last.qx), + Math.round(this.last.qy), + Math.round(this.last.x), + Math.round(this.last.y)].join(" ") + " "; + this.last.isAbsolute = this.isAbsolute; + this.attrs.path += (this.isAbsolute ? "Q" : "q") + Array.prototype.splice.call(arguments, 0, arguments.length); + } + if (arguments.length == 2) { + this.last.qx = this.last.x * 2 - this.last.qx; + this.last.qy = this.last.y * 2 - this.last.qy; + this.last.x = (this.isAbsolute ? 0 : this.last.x) + parseFloat(arguments[2], 10); + this.last.y = (this.isAbsolute ? 0 : this.last.y) + parseFloat(arguments[3], 10); + d += [Math.round(this.last.qx), + Math.round(this.last.qy), + Math.round(this.last.x), + Math.round(this.last.y)].join(" ") + " "; + this.attrs.path += (this.isAbsolute ? "T" : "t") + Array.prototype.splice.call(arguments, 0, arguments.length); + } + this.node.path = this.Path += d; + this.path.push({type: "qcurve", arg: [].slice.call(arguments, 0), pos: this.isAbsolute}); + return this; + }; + p.addRoundedCorner = function (r, dir) { + var R = .5522 * r, rollback = this.isAbsolute, o = this; + if (rollback) { + this.relatively(); + rollback = function () { + o.absolutely(); + }; + } else { + rollback = function () {}; + } + var actions = { + l: function () { + return { + u: function () { + o.curveTo(-R, 0, -r, -(r - R), -r, -r); + }, + d: function () { + o.curveTo(-R, 0, -r, r - R, -r, r); + } + }; + }, + r: function () { + return { + u: function () { + o.curveTo(R, 0, r, -(r - R), r, -r); + }, + d: function () { + o.curveTo(R, 0, r, r - R, r, r); + } + }; + }, + u: function () { + return { + r: function () { + o.curveTo(0, -R, -(R - r), -r, r, -r); + }, + l: function () { + o.curveTo(0, -R, R - r, -r, -r, -r); + } + }; + }, + d: function () { + return { + r: function () { + o.curveTo(0, R, -(R - r), r, r, r); + }, + l: function () { + o.curveTo(0, R, R - r, r, -r, r); + } + }; + } + }; + actions[dir.charAt(0)]()[dir.charAt(1)](); + rollback(); + return o; + }; + p.andClose = function () { + this.node.path = (this.Path += "x e"); + this.attrs.path += "z"; + return this; + }; + if (pathString) { + p.absolutely(); + p.attrs.path = ""; + C.pathfinder(p, "" + pathString); + } + p.setBox(); + setFillAndStroke(p, params); + if (params.gradient) { + addGrdientFill(p, params.gradient); + } + return p; + }; + var setFillAndStroke = function (o, params) { + var s = o[0].style; + o.attrs = o.attrs || {}; + for (var par in params) { + o.attrs[par] = params[par]; + } + if (params.path && o.type == "path") { + o.Path = ""; + o.path = []; + C.pathfinder(o, params.path); + } + if (params.rotation != null) { + o.Group.style.rotation = params.rotation; + } + if (params.translation) { + var xy = params.translation.split(/[, ]+/); + o.translate(xy[0], xy[1]); + } + if (params.scale) { + var xy = params.scale.split(/[, ]+/); + o.scale(xy[0], xy[1]); + } + if (o.type == "image" && params.opacity) { + o.node.filterOpacity = " progid:DXImageTransform.Microsoft.Alpha(opacity=" + (params.opacity * 100) + ")"; + o.node.style.filter = (o.node.filterMatrix || "") + (o.node.filterOpacity || ""); + } + params["font-family"] && (s.fontFamily = params["font-family"]); + params["font-size"] && (s.fontSize = params["font-size"]); + params["font"] && (s.font = params["font"]); + params["font-weight"] && (s.fontWeight = params["font-weight"]); + if (typeof params.opacity != "undefined" || typeof params["stroke-width"] != "undefined" || typeof params.fill != "undefined" || typeof params.stroke != "undefined") { + o = o.shape || o.node; + var fill = (o.getElementsByTagName("fill") && o.getElementsByTagName("fill")[0]) || document.createElement("rvml:fill"); + if ("fill-opacity" in params || "opacity" in params) { + fill.opacity = ((params["fill-opacity"] + 1 || 2) - 1) * ((params.opacity + 1 || 2) - 1); + } + if (params.fill) { + fill.on = true; + } + if (fill.on == undefined || params.fill == "none") { + fill.on = false; + } + if (fill.on && params.fill) { + var isURL = params.fill.match(/^url\(([^\)]+)\)$/i); + if (isURL) { + fill.src = isURL[1]; + fill.type = "tile"; + } else { + fill.color = params.fill; + fill.src = ""; + fill.type = "solid"; + } + } + o.appendChild(fill); + var stroke = (o.getElementsByTagName("stroke") && o.getElementsByTagName("stroke")[0]) || document.createElement("rvml:stroke"); + if ((params.stroke && params.stroke != "none") || params["stroke-width"] || params["stroke-opacity"] || params["stroke-dasharray"]) { + stroke.on = true; + } + if (params.stroke == "none" || typeof stroke.on == "undefined") { + stroke.on = false; + } + if (stroke.on && params.stroke) { + stroke.color = params.stroke; + } + stroke.opacity = ((params["stroke-opacity"] + 1 || 2) - 1) * ((params.opacity + 1 || 2) - 1); + params["stroke-linejoin"] && (stroke.joinstyle = params["stroke-linejoin"] || "miter"); + stroke.miterlimit = params["stroke-miterlimit"] || 8; + params["stroke-linecap"] && (stroke.endcap = {butt: "flat", square: "square", round: "round"}[params["stroke-linecap"]] || "miter"); + params["stroke-width"] && (stroke.weight = (parseFloat(params["stroke-width"], 10) || 1) * 12 / 16); + if (params["stroke-dasharray"]) { + var dasharray = { + "-": "shortdash", + ".": "shortdot", + "-.": "shortdashdot", + "-..": "shortdashdotdot", + ". ": "dot", + "- ": "dash", + "--": "longdash", + "- .": "dashdot", + "--.": "longdashdot", + "--..": "longdashdotdot" + }; + stroke.dashstyle = dasharray[params["stroke-dasharray"]] || ""; + } + o.appendChild(stroke); + } + }; + var addGrdientFill = function (o, gradient) { + o.attrs = o.attrs || {}; + o.attrs.gradient = gradient; + o = o.shape || o[0]; + var fill = o.getElementsByTagName("fill"); + if (fill.length) { + fill = fill[0]; + } else { + fill = document.createElement("rvml:fill"); + } + if (gradient.dots.length) { + fill.on = true; + fill.method = "none"; + fill.type = (gradient.type.toLowerCase() == "linear") ? "gradient" : "gradientTitle"; + if (typeof gradient.dots[0].color != "undefined") { + fill.color = gradient.dots[0].color || "#000"; + } + if (typeof gradient.dots[gradient.dots.length - 1].color != "undefined") { + fill.color2 = gradient.dots[gradient.dots.length - 1].color || "#000"; + } + var colors = []; + for (var i = 0, ii = gradient.dots.length; i < ii; i++) { + if (gradient.dots[i].offset) { + colors.push(gradient.dots[i].offset + " " + gradient.dots[i].color); + } + }; + var fillOpacity = gradient.dots[0].opacity || 1; + var fillOpacity2 = gradient.dots[gradient.dots.length - 1].opacity || 1; + if (colors) { + fill.colors.value = colors.join(","); + fillOpacity2 += fillOpacity; + fillOpacity = fillOpacity2 - fillOpacity; + fillOpacity2 -= fillOpacity; + } + fill.setAttribute("opacity", fillOpacity); + fill.setAttribute("opacity2", fillOpacity2); + if (gradient.vector) { + var angle = Math.round(Math.atan((parseFloat(gradient.vector[3], 10) - parseFloat(gradient.vector[1], 10)) / (parseFloat(gradient.vector[2], 10) - parseFloat(gradient.vector[0], 10))) * 57.29) || 0; + fill.angle = 270 - angle; + } + if (gradient.type.toLowerCase() == "radial") { + fill.focus = "100%"; + fill.focusposition = "0.5 0.5"; + } + } + }; + var Element = function (node, group, vml) { + var Rotation = 0, + RotX = 0, + RotY = 0, + Scale = 1; + this[0] = node; + this.node = node; + this.X = 0; + this.Y = 0; + this.attrs = {}; + this.Group = group; + this.vml = vml; + this._ = { + tx: 0, + ty: 0, + rt: 0, + sx: 1, + sy: 1 + }; + }; + Element.prototype.rotate = function (deg, isAbsolute) { + if (deg == undefined) { + return this._.rt; + } + if (isAbsolute) { + this._.rt = deg; + } else { + this._.rt += deg; + } + this.Group.style.rotation = this._.rt; + return this; + }; + Element.prototype.setBox = function (params) { + var gs = this.Group.style, + os = this[0].style; + for (var i in params) { + this.attrs[i] = params[i]; + } + var attr = this.attrs, x, y, w, h; + switch (this.type) { + case "circle": + x = attr.cx - attr.r; + y = attr.cy - attr.r; + w = h = attr.r * 2; + break; + case "ellipse": + x = attr.cx - attr.rx; + y = attr.cy - attr.ry; + w = attr.rx * 2; + h = attr.ry * 2; + break; + case "rect": + case "image": + x = attr.x; + y = attr.y; + w = attr.width || 0; + h = attr.height || 0; + break; + case "text": + this.textpath.v = ["m", Math.round(attr.x), ", ", Math.round(attr.y - 2), "l", Math.round(attr.x) + 1, ", ", Math.round(attr.y - 2)].join(""); + return; + case "path": + if (!this.attrs.path) { + x = 0; + y = 0; + w = this.vml.width; + h = this.vml.height; + } else { + var dim = Raphael.pathDimensions(this.attrs.path), + x = dim.x; + y = dim.y; + w = dim.width; + h = dim.height; + } + break; + default: + x = 0; + y = 0; + w = this.vml.width; + h = this.vml.height; + break; + } + if (this.type == "path") { + var left = Math.round(this.vml.width / 2 - w / 2 - x), + top = Math.round(this.vml.height / 2 - h / 2 - y); + gs.left = - left + "px"; + gs.top = - top + "px"; + this.X = left; + this.Y = top; + this.W = w; + this.H = h; + os.top = top + "px"; + os.left = left + "px"; + } else { + var left = this.vml.width / 2 - w / 2, + top = this.vml.height / 2 - h / 2; + gs.position = "absolute"; + gs.left = x - left + "px"; + gs.top = y - top + "px"; + this.X = x - left; + this.Y = y - top; + this.W = w; + this.H = h; + gs.width = this.vml.width + "px"; + gs.height = this.vml.height + "px"; + os.position = "absolute"; + os.top = top + "px"; + os.left = left + "px"; + os.width = w + "px"; + os.height = h + "px"; + } + }; + Element.prototype.hide = function () { + this.Group.style.display = "none"; + return this; + }; + Element.prototype.show = function () { + this.Group.style.display = "block"; + return this; + }; + Element.prototype.translate = function (x, y) { + if (x == undefined && y == undefined) { + return {x: this._.tx, y: this._.ty}; + } + this._.tx += +x; + this._.ty += +y; + if (this.type == "path") { + var path = this.attrs.path; + path = Raphael.pathToRelative(path); + path[0][1] += +x; + path[0][2] += +y; + this.attr({path: path.join(" ")}); + } + this.setBox({x: this._.tx, y: this._.ty}); + return this; + }; + Element.prototype.getBBox = function () { + return { + x: this.X, + y: this.Y, + width: this.W, + height: this.H + }; + }; + Element.prototype.remove = function () { + this[0].parentNode.removeChild(this[0]); + this.Group.parentNode.removeChild(this.Group); + this.shape && this.shape.parentNode.removeChild(this.shape); + }; + Element.prototype.attr = function () { + if (arguments.length == 1 && typeof arguments[0] == "string") { + if (arguments[0] == "translation") { + return this.translate(); + } + return this.attrs[arguments[0]]; + } + if (this.attrs && arguments.length == 1 && arguments[0] instanceof Array) { + var values = {}; + for (var i = 0, ii = arguments[0].length; i < ii; i++) { + values[arguments[0][i]] = this.attrs[arguments[0][i]]; + }; + return values; + } + if (this[0].tagName.toLowerCase() == "group") { + var children = this[0].childNodes; + this.attrs = this.attrs || {}; + if (arguments.length == 2) { + this.attrs[arguments[0]] = arguments[1]; + } else if (arguments.length == 1 || typeof arguments[0] == "object") { + for (var j in arguments[0]) { + this.attrs[j] = arguments[0][j]; + } + } + for (var i = 0, ii = children.length; i < ii; i++) { + this.attr.apply(new item(children[i], this[0], this.vml), arguments); + } + } else { + var params; + if (arguments.length == 2) { + params = {}; + params[arguments[0]] = arguments[1]; + } + if (arguments.length == 1 && typeof arguments[0] == "object") { + params = arguments[0]; + } + if (params) { + setFillAndStroke(this, params); + this.setBox(params); + if (params.gradient) { + addGrdientFill(this, params.gradient); + } + if (params.text && this.type == "text") { + this[0].string = params.text; + } + if (params.id) { + this[0].id = params.id; + } + } + } + return this; + }; + Element.prototype.toFront = function () { + this.Group.parentNode.appendChild(this.Group); + return this; + }; + Element.prototype.toBack = function () { + if (this.Group.parentNode.firstChild != this.Group) { + this.Group.parentNode.insertBefore(this.Group, this.Group.parentNode.firstChild); + } + return this; + }; + Element.prototype.insertAfter = function (element) { + if (element.Group.nextSibling) { + element.Group.parentNode.insertBefore(this.Group, element.Group.nextSibling); + } else { + element.Group.parentNode.appendChild(this.Group); + } + return this; + }; + Element.prototype.insertBefore = function (element) { + element.Group.parentNode.insertBefore(this.Group, element.Group); + return this; + }; + var theCircle = function (vml, x, y, r) { + var g = document.createElement("rvml:group"); + var o = document.createElement("rvml:oval"); + g.appendChild(o); + vml.canvas.appendChild(g); + var res = new Element(o, g, vml); + setFillAndStroke(res, {stroke: "#000", fill: "none"}); + res.setBox({x: x - r, y: y - r, width: r * 2, height: r * 2}); + res.attrs.cx = x; + res.attrs.cy = y; + res.attrs.r = r; + res.type = "circle"; + return res; + }; + var theRect = function (vml, x, y, w, h, r) { + var g = document.createElement("rvml:group"); + var o = document.createElement(r ? "rvml:roundrect" : "rvml:rect"); + if (r) { + o.arcsize = r / (Math.min(w, h)); + } + g.appendChild(o); + vml.canvas.appendChild(g); + var res = new Element(o, g, vml); + setFillAndStroke(res, {stroke: "#000"}); + res.setBox({x: x, y: y, width: w, height: h}); + res.attrs.x = x; + res.attrs.y = y; + res.attrs.w = w; + res.attrs.h = h; + res.attrs.r = r; + res.type = "rect"; + return res; + }; + var theEllipse = function (vml, x, y, rx, ry) { + var g = document.createElement("rvml:group"); + var o = document.createElement("rvml:oval"); + g.appendChild(o); + vml.canvas.appendChild(g); + var res = new Element(o, g, vml); + setFillAndStroke(res, {stroke: "#000"}); + res.setBox({x: x - rx, y: y - ry, width: rx * 2, height: ry * 2}); + res.attrs.cx = x; + res.attrs.cy = y; + res.attrs.rx = rx; + res.attrs.ry = ry; + res.type = "ellipse"; + return res; + }; + var theImage = function (vml, src, x, y, w, h) { + var g = document.createElement("rvml:group"); + var o = document.createElement("rvml:image"); + o.src = src; + g.appendChild(o); + vml.canvas.appendChild(g); + var res = new Element(o, g, vml); + res.type = "image"; + res.setBox({x: x, y: y, width: w, height: h}); + res.attrs.x = x; + res.attrs.y = y; + res.attrs.w = w; + res.attrs.h = h; + return res; + }; + var theText = function (vml, x, y, text) { + // @TODO: setTheBox + var g = document.createElement("rvml:group"), gs = g.style; + var el = document.createElement("rvml:shape"), ol = el.style; + var path = document.createElement("rvml:path"), ps = path.style; + path.v = ["m", Math.round(x), ", ", Math.round(y - 2), "l", Math.round(x) + 1, ", ", Math.round(y - 2)].join(""); + path.textpathok = true; + ol.width = vml.width; + ol.height = vml.height; + gs.position = "absolute"; + gs.left = 0; + gs.top = 0; + gs.width = vml.width; + gs.height = vml.height; + var o = document.createElement("rvml:textpath"); + o.string = text; + o.on = true; + o.coordsize = vml.coordsize; + o.coordorigin = vml.coordorigin; + el.appendChild(o); + el.appendChild(path); + g.appendChild(el); + vml.canvas.appendChild(g); + var res = new Element(o, g, vml); + res.shape = el; + res.textpath = path; + res.type = "text"; + res.attrs.x = x; + res.attrs.y = y; + res.attrs.w = 1; + res.attrs.h = 1; + setFillAndStroke(res, {stroke: "none", fill: "#000"}); + return res; + }; + var theGroup = function (vml) { + var el = document.createElement("rvml:group"), els = el.style; + els.position = "absolute"; + els.left = 0; + els.top = 0; + els.width = vml.width; + els.height = vml.height; + if (vml.canvas) { + vml.canvas.appendChild(el); + } + var res = new Element(el, el, vml); + for (var f in vml) { + if (f.charAt(0) != "_" && typeof vml[f] == "function") { + res[f] = (function (f) { + return function () { + var e = vml[f].apply(vml, arguments); + el.appendChild(e[0].parentNode); + return e; + }; + })(f); + } + } + res.type = "group"; + return res; + }; + r._create = function () { + // container, width, height + // x, y, width, height + var container, width, height; + if (typeof arguments[0] == "string") { + container = document.getElementById(arguments[0]); + width = arguments[1]; + height = arguments[2]; + } + if (typeof arguments[0] == "object") { + container = arguments[0]; + width = arguments[1]; + height = arguments[2]; + } + if (typeof arguments[0] == "number") { + container = 1; + x = arguments[0]; + y = arguments[1]; + width = arguments[2]; + height = arguments[3]; + } + if (!container) { + throw new Error("VML container not found."); + } + if (!document.namespaces["rvml"]) { + document.namespaces.add("rvml","urn:schemas-microsoft-com:vml"); + document.createStyleSheet().addRule("rvml\\:*", "behavior:url(#default#VML)"); + } + var c = document.createElement("div"), + d = document.createElement("div"), + r = C.canvas = document.createElement("rvml:group"), + cs = c.style, rs = r.style; + C.width = width; + C.height = height; + width = width || "320px"; + height = height || "200px"; + cs.clip = "rect(0 " + width + " " + height + " 0)"; + cs.top = "-2px"; + cs.left = "-2px"; + cs.position = "absolute"; + rs.position = "absolute"; + d.style.position = "relative"; + rs.width = width; + rs.height = height; + r.coordsize = (width == "100%" ? width : parseFloat(width)) + " " + (height == "100%" ? height : parseFloat(height)); + r.coordorigin = "0 0"; + + var b = document.createElement("rvml:rect"), bs = b.style; + bs.left = bs.top = 0; + bs.width = rs.width; + bs.height = rs.height; + b.filled = b.stroked = "f"; + + r.appendChild(b); + c.appendChild(r); + d.appendChild(c); + if (container == 1) { + document.body.appendChild(d); + cs.position = "absolute"; + cs.left = x + "px"; + cs.top = y + "px"; + cs.width = width; + cs.height = height; + container = { + style: { + width: width, + height: height + } + }; + } else { + cs.width = container.style.width = width; + cs.height = container.style.height = height; + if (container.firstChild) { + container.insertBefore(d, container.firstChild); + } else { + container.appendChild(d); + } + } + for (var prop in C) { + container[prop] = C[prop]; + } + container.clear = function () { + var todel = []; + for (var i = 0, ii = r.childNodes.length; i < ii; i++) { + if (r.childNodes[i] != b) { + todel.push(r.childNodes[i]); + } + } + for (i = 0, ii = todel.length; i < ii; i++) { + r.removeChild(todel[i]); + } + }; + return container; + }; + C.remove = function () { + C.canvas.parentNode.parentNode.parentNode.removeChild(C.canvas.parentNode.parentNode); + }; + } + if (type == "SVG") { + var thePath = function (params, pathString, SVG) { + var el = document.createElementNS(SVG.svgns, "path"); + el.setAttribute("fill", "none"); + if (SVG.canvas) { + SVG.canvas.appendChild(el); + } + var p = new Element(el, SVG); + p.isAbsolute = true; + p.type = "path"; + p.last = {x: 0, y: 0, bx: 0, by: 0}; + p.absolutely = function () { + this.isAbsolute = true; + return this; + }; + p.relatively = function () { + this.isAbsolute = false; + return this; + }; + p.moveTo = function (x, y) { + var d = this.isAbsolute?"M":"m"; + d += parseFloat(x, 10).toFixed(3) + " " + parseFloat(y, 10).toFixed(3) + " "; + var oldD = this[0].getAttribute("d") || ""; + (oldD == "M0,0") && (oldD = ""); + this[0].setAttribute("d", oldD + d); + this.last.x = (this.isAbsolute ? 0 : this.last.x) + parseFloat(x, 10); + this.last.y = (this.isAbsolute ? 0 : this.last.y) + parseFloat(y, 10); + this.attrs.path = oldD + d; + return this; + }; + p.lineTo = function (x, y) { + this.last.x = (this.isAbsolute ? 0 : this.last.x) + parseFloat(x, 10); + this.last.y = (this.isAbsolute ? 0 : this.last.y) + parseFloat(y, 10); + var d = this.isAbsolute?"L":"l"; + d += parseFloat(x, 10).toFixed(3) + " " + parseFloat(y, 10).toFixed(3) + " "; + var oldD = this[0].getAttribute("d") || ""; + this[0].setAttribute("d", oldD + d); + this.attrs.path = oldD + d; + return this; + }; + p.arcTo = function (rx, ry, large_arc_flag, sweep_flag, x, y) { + var d = this.isAbsolute ? "A" : "a"; + d += [parseFloat(rx, 10).toFixed(3), parseFloat(ry, 10).toFixed(3), 0, large_arc_flag, sweep_flag, parseFloat(x, 10).toFixed(3), parseFloat(y, 10).toFixed(3)].join(" "); + var oldD = this[0].getAttribute("d") || ""; + this[0].setAttribute("d", oldD + d); + this.last.x = parseFloat(x, 10); + this.last.y = parseFloat(y, 10); + this.attrs.path = oldD + d; + return this; + }; + p.cplineTo = function (x1, y1, w1) { + if (!w1) { + return this.lineTo(x1, y1); + } else { + var p = {}; + var x = parseFloat(x1, 10); + var y = parseFloat(y1, 10); + var w = parseFloat(w1, 10); + var d = this.isAbsolute?"C":"c"; + var attr = [+this.last.x + w, +this.last.y, x - w, y, x, y]; + for (var i = 0, ii = attr.length; i < ii; i++) { + d += attr[i].toFixed(3) + " "; + } + this.last.x = (this.isAbsolute ? 0 : this.last.x) + attr[4]; + this.last.y = (this.isAbsolute ? 0 : this.last.y) + attr[5]; + this.last.bx = attr[2]; + this.last.by = attr[3]; + var oldD = this[0].getAttribute("d") || ""; + this[0].setAttribute("d", oldD + d); + this.attrs.path = oldD + d; + return this; + } + }; + p.curveTo = function () { + var p = {}, + command = [0, 1, 2, 3, "s", 5, "c"]; + + var d = command[arguments.length]; + if (this.isAbsolute) { + d = d.toUpperCase(); + } + for (var i = 0, ii = arguments.length; i < ii; i++) { + d += parseFloat(arguments[i], 10).toFixed(3) + " "; + } + this.last.x = (this.isAbsolute ? 0 : this.last.x) + parseFloat(arguments[arguments.length - 2], 10); + this.last.y = (this.isAbsolute ? 0 : this.last.y) + parseFloat(arguments[arguments.length - 1], 10); + this.last.bx = parseFloat(arguments[arguments.length - 4], 10); + this.last.by = parseFloat(arguments[arguments.length - 3], 10); + var oldD = this.node.getAttribute("d") || ""; + this.node.setAttribute("d", oldD + d); + this.attrs.path = oldD + d; + return this; + }; + p.qcurveTo = function () { + var p = {}, + command = [0, 1, "t", 3, "q"]; + + var d = command[arguments.length]; + if (this.isAbsolute) { + d = d.toUpperCase(); + } + for (var i = 0, ii = arguments.length; i < ii; i++) { + d += parseFloat(arguments[i], 10).toFixed(3) + " "; + } + this.last.x = (this.isAbsolute ? 0 : this.last.x) + parseFloat(arguments[arguments.length - 2], 10); + this.last.y = (this.isAbsolute ? 0 : this.last.y) + parseFloat(arguments[arguments.length - 1], 10); + if (arguments.length != 2) { + this.last.qx = parseFloat(arguments[arguments.length - 4], 10); + this.last.qy = parseFloat(arguments[arguments.length - 3], 10); + } + var oldD = this.node.getAttribute("d") || ""; + this.node.setAttribute("d", oldD + d); + this.attrs.path = oldD + d; + return this; + }; + p.addRoundedCorner = function (r, dir) { + var R = .5522 * r, rollback = this.isAbsolute, o = this; + if (rollback) { + this.relatively(); + rollback = function () { + o.absolutely(); + }; + } else { + rollback = function () {}; + } + var actions = { + l: function () { + return { + u: function () { + o.curveTo(-R, 0, -r, -(r - R), -r, -r); + }, + d: function () { + o.curveTo(-R, 0, -r, r - R, -r, r); + } + }; + }, + r: function () { + return { + u: function () { + o.curveTo(R, 0, r, -(r - R), r, -r); + }, + d: function () { + o.curveTo(R, 0, r, r - R, r, r); + } + }; + }, + u: function () { + return { + r: function () { + o.curveTo(0, -R, -(R - r), -r, r, -r); + }, + l: function () { + o.curveTo(0, -R, R - r, -r, -r, -r); + } + }; + }, + d: function () { + return { + r: function () { + o.curveTo(0, R, -(R - r), r, r, r); + }, + l: function () { + o.curveTo(0, R, R - r, r, -r, r); + } + }; + } + }; + actions[dir[0]]()[dir[1]](); + rollback(); + return o; + }; + p.andClose = function () { + var oldD = this[0].getAttribute("d") || ""; + this[0].setAttribute("d", oldD + "Z "); + this.attrs.path = oldD + "Z "; + return this; + }; + if (pathString) { + p.attrs.path = "" + pathString; + p.absolutely(); + C.pathfinder(p, p.attrs.path); + } + if (params) { + setFillAndStroke(p, params); + } + return p; + }; + var addGrdientFill = function (o, gradient, SVG) { + var el = document.createElementNS(SVG.svgns, gradient.type + "Gradient"); + el.id = "raphael-gradient-" + SVG.gradients++; + if (gradient.vector && gradient.vector.length) { + el.setAttribute("x1", gradient.vector[0]); + el.setAttribute("y1", gradient.vector[1]); + el.setAttribute("x2", gradient.vector[2]); + el.setAttribute("y2", gradient.vector[3]); + } + SVG.defs.appendChild(el); + for (var i = 0, ii = gradient.dots.length; i < ii; i++) { + var stop = document.createElementNS(SVG.svgns, "stop"); + stop.setAttribute("offset", gradient.dots[i].offset ? gradient.dots[i].offset : (i == 0) ? "0%" : "100%"); + stop.setAttribute("stop-color", gradient.dots[i].color || "#fff"); + if (typeof gradient.dots[i].opacity != "undefined") { + stop.setAttribute("stop-opacity", gradient.dots[i].opacity); + } + el.appendChild(stop); + }; + o.setAttribute("fill", "url(#" + el.id + ")"); + }; + var updatePosition = function (o) { + if (o.pattern) { + var bbox = o.node.getBBox(); + o.pattern.setAttribute("patternTransform", "translate(" + [bbox.x, bbox.y].join(",") + ")"); + } + }; + var setFillAndStroke = function (o, params) { + var dasharray = { + "-": [3, 1], + ".": [1, 1], + "-.": [3, 1, 1, 1], + "-..": [3, 1, 1, 1, 1, 1], + ". ": [1, 3], + "- ": [4, 3], + "--": [8, 3], + "- .": [4, 3, 1, 3], + "--.": [8, 3, 1, 3], + "--..": [8, 3, 1, 3, 1, 3] + }, + addDashes = function (o, value) { + value = dasharray[value.toString().toLowerCase()]; + if (value) { + var width = o.attrs["stroke-width"] || "1", + butt = {round: width, square: width, butt: 0}[o.attrs["stroke-linecap"] || params["stroke-linecap"]] || 0, + dashes = []; + for (var i = 0, ii = value.length; i < ii; i++) { + dashes.push(value[i] * width + ((i % 2) ? 1 : -1) * butt); + } + value = dashes.join(","); + o.node.setAttribute("stroke-dasharray", value); + } + }; + for (var att in params) { + var value = params[att]; + o.attrs[att] = value; + switch (att) { + case "path": + if (o.type == "path") { + o.node.setAttribute("d", "M0,0"); + C.pathfinder(o, value); + } + case "rx": + case "cx": + case "x": + o.node.setAttribute(att, value); + updatePosition(o); + break; + case "ry": + case "cy": + case "y": + o.node.setAttribute(att, value); + updatePosition(o); + break; + case "width": + o.node.setAttribute(att, value); + break; + case "height": + o.node.setAttribute(att, value); + break; + case "gradient": + addGrdientFill(o.node, value, o.svg); + break; + case "stroke-width": + o.node.style.strokeWidth = value; + // Need following line for Firefox + o.node.setAttribute(att, value); + if (o.attrs["stroke-dasharray"]) { + addDashes(o, o.attrs["stroke-dasharray"]); + } + break; + case "stroke-dasharray": + addDashes(o, value); + break; + case "text": + if (o.type == "text") { + o.node.childNodes.length && o.node.removeChild(o.node.firstChild); + o.node.appendChild(document.createTextNode(value)); + } + break; + case "rotation": + o.rotate(value, true); + break; + case "translation": + var xy = value.split(/[, ]+/); + o.translate(xy[0], xy[1]); + break; + case "scale": + var xy = value.split(/[, ]+/); + o.scale(xy[0], xy[1]); + break; + case "fill": + var isURL = value.match(/^url\(([^\)]+)\)$/i); + if (isURL) { + var el = document.createElementNS(o.svg.svgns, "pattern"); + var ig = document.createElementNS(o.svg.svgns, "image"); + el.id = "raphael-pattern-" + o.svg.gradients++; + el.setAttribute("x", 0); + el.setAttribute("y", 0); + el.setAttribute("patternUnits", "userSpaceOnUse"); + ig.setAttribute("x", 0); + ig.setAttribute("y", 0); + ig.setAttributeNS(o.svg.xlink, "href", isURL[1]); + el.appendChild(ig); + + var img = document.createElement("img"); + img.style.position = "absolute"; + img.style.top = "-9999em"; + img.style.left = "-9999em"; + img.onload = function () { + el.setAttribute("width", this.offsetWidth); + el.setAttribute("height", this.offsetHeight); + ig.setAttribute("width", this.offsetWidth); + ig.setAttribute("height", this.offsetHeight); + document.body.removeChild(this); + C.safari(); + }; + document.body.appendChild(img); + img.src = isURL[1]; + o.svg.defs.appendChild(el); + o.node.style.fill = "url(#" + el.id + ")"; + o.node.setAttribute("fill", "url(#" + el.id + ")"); + o.pattern = el; + updatePosition(o); + break; + } + default : + var cssrule = att.replace(/(\-.)/g, function (w) { + return w.substring(1).toUpperCase(); + }); + o.node.style[cssrule] = value; + // Need following line for Firefox + o.node.setAttribute(att, value); + break; + } + } + }; + var Element = function (node, svg) { + var X = 0, + Y = 0; + this[0] = node; + this.node = node; + this.svg = svg; + this.attrs = this.attrs || {}; + this.transformations = []; // rotate, translate, scale + this._ = { + tx: 0, + ty: 0, + rt: {deg: 0, x: 0, y: 0}, + sx: 1, + sy: 1 + }; + }; + Element.prototype.translate = function (x, y) { + if (x == undefined && y == undefined) { + return {x: this._.tx, y: this._.ty}; + } + this._.tx += +x; + this._.ty += +y; + switch (this.type) { + case "circle": + case "ellipse": + this.attr({cx: this.attrs.cx + x, cy: this.attrs.cy + y}); + break; + case "rect": + case "image": + case "text": + this.attr({x: this.attrs.x + x, y: this.attrs.y + y}); + break; + case "path": + var path = Raphael.pathToRelative(this.attrs.path); + path[0][1] += +x; + path[0][2] += +y; + this.attr({path: path.join(" ")}); + break; + } + return this; + }; + Element.prototype.rotate = function (deg, isAbsolute) { + if (deg == undefined) { + return this._.rt.deg; + } + var bbox = this.getBBox(); + if (isAbsolute) { + this._.rt.deg = deg; + } else { + this._.rt.deg += deg; + } + + if (this._.rt.deg) { + this.transformations[0] = ("rotate(" + this._.rt.deg + " " + (bbox.x + bbox.width / 2) + " " + (bbox.y + bbox.height / 2) + ")"); + } else { + this.transformations[0] = ""; + } + this.node.setAttribute("transform", this.transformations.join(" ")); + return this; + }; + Element.prototype.hide = function () { + this.node.style.display = "none"; + return this; + }; + Element.prototype.show = function () { + this.node.style.display = "block"; + return this; + }; + Element.prototype.remove = function () { + this.node.parentNode.removeChild(this.node); + }; + Element.prototype.getBBox = function () { + return this.node.getBBox(); + }; + Element.prototype.attr = function () { + if (arguments.length == 1 && typeof arguments[0] == "string") { + if (arguments[0] == "translation") { + return this.translate(); + } + return this.attrs[arguments[0]]; + } + if (arguments.length == 1 && arguments[0] instanceof Array) { + var values = {}; + for (var j in arguments[0]) { + values[arguments[0][j]] = this.attrs[arguments[0][j]]; + } + return values; + } + if (arguments.length == 2) { + var params = {}; + params[arguments[0]] = arguments[1]; + setFillAndStroke(this, params); + } else if (arguments.length == 1 && typeof arguments[0] == "object") { + setFillAndStroke(this, arguments[0]); + } + return this; + }; + Element.prototype.toFront = function () { + this.node.parentNode.appendChild(this.node); + return this; + }; + Element.prototype.toBack = function () { + if (this.node.parentNode.firstChild != this.node) { + this.node.parentNode.insertBefore(this.node, this.node.parentNode.firstChild); + } + return this; + }; + Element.prototype.insertAfter = function (element) { + if (element.node.nextSibling) { + element.node.parentNode.insertBefore(this.node, element.node.nextSibling); + } else { + element.node.parentNode.appendChild(this.node); + } + return this; + }; + Element.prototype.insertBefore = function (element) { + element.node.parentNode.insertBefore(this.node, element.node); + return this; + }; + var theCircle = function (svg, x, y, r) { + var el = document.createElementNS(svg.svgns, "circle"); + el.setAttribute("cx", x); + el.setAttribute("cy", y); + el.setAttribute("r", r); + el.setAttribute("fill", "none"); + el.setAttribute("stroke", "#000"); + if (svg.canvas) { + svg.canvas.appendChild(el); + } + var res = new Element(el, svg); + res.attrs = res.attrs || {}; + res.attrs.cx = x; + res.attrs.cy = y; + res.attrs.r = r; + res.attrs.stroke = "#000"; + res.type = "circle"; + return res; + }; + var theRect = function (svg, x, y, w, h, r) { + var el = document.createElementNS(svg.svgns, "rect"); + el.setAttribute("x", x); + el.setAttribute("y", y); + el.setAttribute("width", w); + el.setAttribute("height", h); + if (r) { + el.setAttribute("rx", r); + el.setAttribute("ry", r); + } + el.setAttribute("fill", "none"); + el.setAttribute("stroke", "#000"); + if (svg.canvas) { + svg.canvas.appendChild(el); + } + var res = new Element(el, svg); + res.attrs = res.attrs || {}; + res.attrs.x = x; + res.attrs.y = y; + res.attrs.width = w; + res.attrs.height = h; + res.attrs.stroke = "#000"; + if (r) { + res.attrs.rx = res.attrs.ry = r; + } + res.type = "rect"; + return res; + }; + var theEllipse = function (svg, x, y, rx, ry) { + var el = document.createElementNS(svg.svgns, "ellipse"); + el.setAttribute("cx", x); + el.setAttribute("cy", y); + el.setAttribute("rx", rx); + el.setAttribute("ry", ry); + el.setAttribute("fill", "none"); + el.setAttribute("stroke", "#000"); + if (svg.canvas) { + svg.canvas.appendChild(el); + } + var res = new Element(el, svg); + res.attrs = res.attrs || {}; + res.attrs.cx = x; + res.attrs.cy = y; + res.attrs.rx = rx; + res.attrs.ry = ry; + res.attrs.stroke = "#000"; + res.type = "ellipse"; + return res; + }; + var theImage = function (svg, src, x, y, w, h) { + var el = document.createElementNS(svg.svgns, "image"); + el.setAttribute("x", x); + el.setAttribute("y", y); + el.setAttribute("width", w); + el.setAttribute("height", h); + el.setAttribute("preserveAspectRatio", "none"); + el.setAttributeNS(svg.xlink, "href", src); + if (svg.canvas) { + svg.canvas.appendChild(el); + } + var res = new Element(el, svg); + res.attrs = res.attrs || {}; + res.attrs.x = x; + res.attrs.y = y; + res.attrs.width = w; + res.attrs.height = h; + res.type = "image"; + return res; + }; + var theText = function (svg, x, y, text) { + var el = document.createElementNS(svg.svgns, "text"); + el.setAttribute("x", x); + el.setAttribute("y", y); + el.setAttribute("text-anchor", "middle"); + el.setAttribute("fill", "#000"); + if (text) { + el.appendChild(document.createTextNode(text)); + } + if (svg.canvas) { + svg.canvas.appendChild(el); + } + var res = new Element(el, svg); + res.attrs = res.attrs || {}; + res.attrs.x = x; + res.attrs.y = y; + res.attrs.fill = "#000"; + res.type = "text"; + return res; + }; + var theGroup = function (svg) { + var el = document.createElementNS(svg.svgns, "g"); + if (svg.canvas) { + svg.canvas.appendChild(el); + } + var i = new Element(el, svg); + for (var f in svg) { + if (f[0] != "_" && typeof svg[f] == "function") { + i[f] = (function (f) { + return function () { + var e = svg[f].apply(svg, arguments); + el.appendChild(e[0]); + return e; + }; + })(f); + } + } + i.type = "group"; + return i; + }; + r._create = function () { + // container, width, height + // x, y, width, height + if (typeof arguments[0] == "string") { + var container = document.getElementById(arguments[0]); + var width = arguments[1]; + var height = arguments[2]; + } + if (typeof arguments[0] == "object") { + var container = arguments[0]; + var width = arguments[1]; + var height = arguments[2]; + } + if (typeof arguments[0] == "number") { + var container = 1, + x = arguments[0], + y = arguments[1], + width = arguments[2], + height = arguments[3]; + } + if (!container) { + throw new Error("SVG container not found."); + } + C.canvas = document.createElementNS(C.svgns, "svg"); + C.canvas.setAttribute("width", width || 320); + C.width = width || 320; + C.canvas.setAttribute("height", height || 200); + C.height = height || 200; + if (container == 1) { + document.body.appendChild(C.canvas); + C.canvas.style.position = "absolute"; + C.canvas.style.left = x + "px"; + C.canvas.style.top = y + "px"; + } else { + if (container.firstChild) { + container.insertBefore(C.canvas, container.firstChild); + } else { + container.appendChild(C.canvas); + } + } + container = { + canvas: C.canvas, + clear: function () { + while (this.canvas.firstChild) { + this.canvas.removeChild(this.canvas.firstChild); + } + this.defs = document.createElementNS(C.svgns, "defs"); + this.gradients = 0; + this.canvas.appendChild(this.defs); + } + }; + for (var prop in C) { + if (prop != "create") { + container[prop] = C[prop]; + } + } + container.clear(); + return container; + }; + C.remove = function () { + C.canvas.parentNode.removeChild(C.canvas); + }; + C.svgns = "http://www.w3.org/2000/svg"; + C.xlink = "http://www.w3.org/1999/xlink"; + } + if (type == "VML" || type == "SVG") { + C.circle = function (x, y, r) { + return theCircle(this, x, y, r); + }; + C.rect = function (x, y, w, h, r) { + return theRect(this, x, y, w, h, r); + }; + C.ellipse = function (x, y, rx, ry) { + return theEllipse(this, x, y, rx, ry); + }; + C.path = function (params, pathString) { + return thePath(params, pathString, this); + }; + C.image = function (src, x, y, w, h) { + return theImage(this, src, x, y, w, h); + }; + C.text = function (x, y, text) { + return theText(this, x, y, text); + }; + C.group = function () { + return theGroup(this); + }; + C.drawGrid = function (x, y, w, h, wv, hv, color) { + color = color || "#000"; + var p = this.path({stroke: color, "stroke-width": 1}) + .moveTo(x, y).lineTo(x + w, y).lineTo(x + w, y + h).lineTo(x, y + h).lineTo(x, y), + rowHeight = h / hv, + columnWidth = w / wv; + for (var i = 1; i < hv; i++) { + p.moveTo(x, y + i * rowHeight).lineTo(x + w, y + i * rowHeight); + } + for (var i = 1; i < wv; i++) { + p.moveTo(x + i * columnWidth, y).lineTo(x + i * columnWidth, y + h); + } + return p; + }; + C.safari = function () { + if (navigator.vendor == "Apple Computer, Inc.") { + var rect = C.rect(-C.width, -C.height, C.width * 3, C.height * 3).attr({stroke: "none"}); + setTimeout(function () {rect.remove();}, 0); + } + }; + Element.prototype.stop = function () { + clearTimeout(this.animation_in_progress); + }; + Element.prototype.scale = function (x, y) { + if (x == undefined && y == undefined) { + return {x: this._.sx, y: this._.sy}; + } + y = y || x; + var dx, dy, cx, cy; + if (x != 0 && !(x == 1 && y == 1)) { + var dirx = Math.round(x / Math.abs(x)), + diry = Math.round(y / Math.abs(y)), + s = this.node.style; + dx = this.attr("x"); + dy = this.attr("y"); + cx = this.attr("cx"); + cy = this.attr("cy"); + if (dirx != 1 || diry != 1) { + if (this.transformations) { + this.transformations[2] = "scale(" + [dirx, diry] + ")"; + this.node.setAttribute("transform", this.transformations.join(" ")); + dx = (dirx < 0) ? -this.attr("x") - this.attrs.width * x * dirx / this._.sx : this.attr("x"); + dy = (diry < 0) ? -this.attr("y") - this.attrs.height * y * diry / this._.sy : this.attr("y"); + cx = this.attr("cx") * dirx; + cy = this.attr("cy") * diry; + } else { + this.node.filterMatrix = " progid:DXImageTransform.Microsoft.Matrix(M11=" + dirx + + ", M12=0, M21=0, M22=" + diry + + ", Dx=0, Dy=0, sizingmethod='auto expand', filtertype='bilinear')"; + s.filter = (this.node.filterMatrix || "") + (this.node.filterOpacity || ""); + } + } else { + if (this.transformations) { + this.transformations[2] = ""; + this.node.setAttribute("transform", this.transformations.join(" ")); + } else { + this.node.filterMatrix = ""; + s.filter = (this.node.filterMatrix || "") + (this.node.filterOpacity || ""); + } + } + switch (this.type) { + case "rect": + case "image": + this.attr({ + width: this.attrs.width * x * dirx / this._.sx, + height: this.attrs.height * y * diry / this._.sy, + x: dx, + y: dy + }); + break; + case "circle": + case "ellipse": + this.attr({ + rx: this.attrs.rx * x * dirx / this._.sx, + ry: this.attrs.ry * y * diry / this._.sy, + r: this.attrs.r * x * diry / this._.sx, + cx: cx, + cy: cy + }); + break; + case "path": + var path = Raphael.pathToRelative(Raphael.parsePathString(this.attr("path"))), + skip = true, + dim = Raphael.pathDimensions(this.attrs.path), + dx = -dim.width * (x - 1) / 2, + dy = -dim.height * (y - 1) / 2; + for (var i = 0, ii = path.length; i < ii; i++) { + if (path[i][0].toUpperCase() == "M" && skip) { + continue; + } else { + skip = false; + } + if (path[i][0].toUpperCase() == "A") { + path[i][path[i].length - 2] *= x * dirx; + path[i][path[i].length - 1] *= y * diry; + } else { + for (var j = 1, jj = path[i].length; j < jj; j++) { + path[i][j] *= (j % 2) ? x * dirx / this._.sx : y * diry / this._.sy; + } + } + } + var dim2 = Raphael.pathDimensions(path), + dx = dim.x + dim.width / 2 - dim2.x - dim2.width / 2, + dy = dim.y + dim.height / 2 - dim2.y - dim2.height / 2; + path = Raphael.pathToRelative(path); + path[0][1] += dx; + path[0][2] += dy; + + this.attr({path: path.join(" ")}); + } + } + this._.sx = x; + this._.sy = y; + return this; + }; + Element.prototype.animate = function (params, ms, callback) { + clearTimeout(this.animation_in_progress); + var from = {}, to = {}, diff = {}, t = {x: 0, y: 0}; + for (var attr in params) { + if (attr in availableAnimAttrs) { + from[attr] = this.attr(attr); + if (typeof from[attr] == "undefined") { + from[attr] = availableAttrs[attr]; + } + to[attr] = params[attr]; + switch (availableAnimAttrs[attr]) { + case "number": + diff[attr] = (to[attr] - from[attr]) / ms; + break; + case "colour": + from[attr] = Raphael.getRGB(from[attr]); + var toColour = Raphael.getRGB(to[attr]); + diff[attr] = { + r: (toColour.r - from[attr].r) / ms, + g: (toColour.g - from[attr].g) / ms, + b: (toColour.b - from[attr].b) / ms + }; + break; + case "path": + var pathes = Raphael.pathEqualiser(from[attr], to[attr]); + from[attr] = pathes[0]; + to[attr] = pathes[1]; + diff[attr] = []; + for (var i = 0, ii = from[attr].length; i < ii; i++) { + diff[attr][i] = [0]; + for (var j = 1, jj = from[attr][i].length; j < jj; j++) { + diff[attr][i][j] = (to[attr][i][j] - from[attr][i][j]) / ms; + } + } + break; + case "csv": + var values = params[attr].split(/[, ]+/); + if (attr == "translation") { + from[attr] = [0, 0]; + diff[attr] = [values[0] / ms, values[1] / ms]; + } else { + from[attr] = from[attr].split(/[, ]+/); + diff[attr] = [(values[0] - from[attr][0]) / ms, (values[1] - from[attr][0]) / ms]; + } + to[attr] = values; + } + } + } + var start = new Date(), + prev = 0, + that = this; + (function () { + var time = (new Date()).getTime() - start.getTime(), + set = {}, + now; + if (time < ms) { + for (var attr in from) { + switch (availableAnimAttrs[attr]) { + case "number": + now = +from[attr] + time * diff[attr]; + break; + case "colour": + now = "rgb(" + [ + Math.round(from[attr].r + time * diff[attr].r), + Math.round(from[attr].g + time * diff[attr].g), + Math.round(from[attr].b + time * diff[attr].b) + ].join(",") + ")"; + break; + case "path": + now = []; + for (var i = 0, ii = from[attr].length; i < ii; i++) { + now[i] = [from[attr][i][0]]; + for (var j = 1, jj = from[attr][i].length; j < jj; j++) { + now[i][j] = from[attr][i][j] + time * diff[attr][i][j]; + } + now[i] = now[i].join(" "); + } + now = now.join(" "); + break; + case "csv": + if (attr == "translation") { + var x = diff[attr][0] * (time - prev), + y = diff[attr][1] * (time - prev); + t.x += x; + t.y += y; + now = [x, y].join(" "); + } else { + now = [+from[attr][0] + time * diff[attr][0], +from[attr][1] + time * diff[attr][1]].join(" "); + } + break; + } + if (attr == "font-size") { + set[attr] = now + "px"; + } else { + set[attr] = now; + } + } + that.attr(set); + that.animation_in_progress = setTimeout(arguments.callee, 0); + C.safari(); + } else { + if (t.x || t.y) { + that.translate(-t.x, -t.y); + } + that.attr(params); + clearTimeout(that.animation_in_progress); + C.safari(); + (typeof callback == "function") && callback.call(that); + } + prev = time; + })(); + return this; + }; + + C.pathfinder = function (p, path) { + var commands = { + M: function (x, y) { + this.moveTo(x, y); + }, + C: function (x1, y1, x2, y2, x3, y3) { + this.curveTo(x1, y1, x2, y2, x3, y3); + }, + Q: function (x1, y1, x2, y2) { + this.qcurveTo(x1, y1, x2, y2); + }, + T: function (x, y) { + this.qcurveTo(x, y); + }, + S: function (x1, y1, x2, y2) { + p.curveTo(x1, y1, x2, y2); + }, + L: function (x, y) { + p.lineTo(x, y); + }, + H: function (x) { + this.lineTo(x, this.last.y); + }, + V: function (y) { + this.lineTo(this.last.x, y); + }, + A: function (rx, ry, xaxisrotation, largearcflag, sweepflag, x, y) { + this.arcTo(rx, ry, largearcflag, sweepflag, x, y); + }, + Z: function () { + this.andClose(); + } + }; + + path = Raphael.pathToAbsolute(path); + for (var i = 0, ii = path.length; i < ii; i++) { + var b = path[i].shift(); + commands[b].apply(p, path[i]); + } + }; + return r; + } else { + return function () {}; + } + })((!window.SVGAngle) ? "VML" : "SVG"); + + +Raphael.vml = !(Raphael.svg = (Raphael.type == "SVG")); +if (Raphael.vml && window.CanvasRenderingContext2D) { + Raphael.type = "Canvas only"; + Raphael.vml = Raphael.svg = false; +} +Raphael.toString = function () { + return "Your browser " + (this.vml ? "doesn't ": "") + "support" + (this.svg ? "s": "") + + " SVG.\nYou are running " + unescape("Rapha%EBl%20") + this.version; +}; +// generic utilities +Raphael.hsb2rgb = function (hue, saturation, brightness) { + if (typeof hue == "object" && "h" in hue && "s" in hue && "b" in hue) { + brightness = hue.b; + saturation = hue.s; + hue = hue.h; + } + var red, + green, + blue; + if (brightness == 0) { + return {r: 0, g: 0, b: 0, hex: "#000"}; + } else { + var i = Math.floor(hue * 6), + f = (hue * 6) - i, + p = brightness * (1 - saturation), + q = brightness * (1 - (saturation * f)), + t = brightness * (1 - (saturation * (1 - f))); + [ + function () {red = brightness; green = t; blue = p;}, + function () {red = q; green = brightness; blue = p;}, + function () {red = p; green = brightness; blue = t;}, + function () {red = p; green = q; blue = brightness;}, + function () {red = t; green = p; blue = brightness;}, + function () {red = brightness; green = p; blue = q;}, + function () {red = brightness; green = t; blue = p;} + ][i](); + } + var rgb = {r: red, g: green, b: blue}; + red *= 255; + green *= 255; + blue *= 255; + var r = Math.round(red).toString(16); + if (r.length == 1) { + r = "0" + r; + } + var g = Math.round(green).toString(16); + if (g.length == 1) { + g = "0" + g; + } + var b = Math.round(blue).toString(16); + if (b.length == 1) { + b = "0" + b; + } + rgb.hex = "#" + r + g + b; + return rgb; +}; +Raphael.rgb2hsb = function (red, green, blue) { + if (typeof red == "object" && "r" in red && "g" in red && "b" in red) { + blue = red.b; + green = red.g; + red = red.r; + } + if (typeof red == "string" && red.charAt(0) == "#") { + if (red.length == 4) { + blue = parseInt(red.substring(3), 16); + green = parseInt(red.substring(2, 3), 16); + red = parseInt(red.substring(1, 2), 16); + } else { + blue = parseInt(red.substring(5), 16); + green = parseInt(red.substring(3, 5), 16); + red = parseInt(red.substring(1, 3), 16); + } + } + if (red > 1 || green > 1 || blue > 1) { + red /= 255; + green /= 255; + blue /= 255; + } + var max = Math.max(red, green, blue), + min = Math.min(red, green, blue), + hue, + saturation, + brightness = max; + if (min == max) { + return {h: 0, s: 0, b: max}; + } else { + var delta = (max - min); + saturation = delta / max; + if (red == max) { + hue = (green - blue) / delta; + } else if (green == max) { + hue = 2 + ((blue - red) / delta); + } else { + hue = 4 + ((red - green) / delta); + } + hue /= 6; + if (hue < 0) { + hue += 1; + } + if (hue > 1) { + hue -= 1; + } + } + return {h: hue, s: saturation, b: brightness}; +}; +Raphael.getRGB = function (colour) { + var red, green, blue, + rgb = colour.match(/^\s*((#[a-f\d]{6})|(#[a-f\d]{3})|rgb\(\s*(\d+,\s*\d+,\s*\d+)\s*\)|rgb\(\s*(\d+%,\s*\d+%,\s*\d+%)\s*\)|hsb\(\s*(\d+,\s*\d+,\s*\d+)\s*\)|hsb\(\s*(\d+%,\s*\d+%,\s*\d+%)\s*\))\s*$/i); + if (rgb) { + if (rgb[2]) { + blue = parseInt(rgb[2].substring(5), 16); + green = parseInt(rgb[2].substring(3, 5), 16); + red = parseInt(rgb[2].substring(1, 3), 16); + } + if (rgb[3]) { + blue = parseInt(rgb[3].substring(3) + rgb[3].substring(3), 16); + green = parseInt(rgb[3].substring(2, 3) + rgb[3].substring(2, 3), 16); + red = parseInt(rgb[3].substring(1, 2) + rgb[3].substring(1, 2), 16); + } + if (rgb[4]) { + rgb = rgb[4].split(/\s*,\s*/); + red = parseInt(rgb[0], 10); + green = parseInt(rgb[1], 10); + blue = parseInt(rgb[2], 10); + } + if (rgb[5]) { + rgb = rgb[5].split(/\s*,\s*/); + red = parseInt(rgb[0], 10) * 2.55; + green = parseInt(rgb[1], 10) * 2.55; + blue = parseInt(rgb[2], 10) * 2.55; + } + if (rgb[6]) { + rgb = rgb[6].split(/\s*,\s*/); + red = parseInt(rgb[0], 10); + green = parseInt(rgb[1], 10); + blue = parseInt(rgb[2], 10); + return this.hsb2rgb(red, green, blue); + } + if (rgb[7]) { + rgb = rgb[7].split(/\s*,\s*/); + red = parseInt(rgb[0], 10) * 2.55; + green = parseInt(rgb[1], 10) * 2.55; + blue = parseInt(rgb[2], 10) * 2.55; + return this.hsb2rgb(red, green, blue); + } + var rgb = {r: red, g: green, b: blue}; + var r = Math.round(red).toString(16); + (r.length == 1) && (r = "0" + r); + var g = Math.round(green).toString(16); + (g.length == 1) && (g = "0" + g); + var b = Math.round(blue).toString(16); + (b.length == 1) && (b = "0" + b); + rgb.hex = "#" + r + g + b; + return rgb; + } +}; +Raphael.getColor = function (value) { + var start = arguments.callee.start = arguments.callee.start || {h: 0, s: 1, b: value || .75}; + var rgb = this.hsb2rgb(start.h, start.s, start.b); + start.h += .075; + if (start.h > 1) { + start.h = 0; + start.s -= .2; + if (start.s <= 0) { + arguments.callee.start = {h: 0, s: 1, b: start.b}; + } + } + return rgb.hex; +}; +Raphael.getColor.reset = function () { + this.start = undefined; +}; +Raphael.parsePathString = function (pathString) { + var paramCounts = {a: 7, c: 6, h: 1, l: 2, m: 2, q: 4, s: 4, t: 2, v: 1, z: 0}, + data = [], + toString = function () { + var res = ""; + for (var i = 0, ii = this.length; i < ii; i++) { + res += this[i][0] + this[i].join(",").substring(2); + } + return res; + }; + if (pathString.toString.toString() == toString.toString()) { + return pathString; + } + pathString.replace(/([achlmqstvz])[\s,]*((-?\d*\.?\d*\s*,?\s*)+)/ig, function (a, b, c) { + var params = [], name = b.toLowerCase(); + c.replace(/(-?\d*\.?\d*)\s*,?\s*/ig, function (a, b) { + b && params.push(+b); + }); + while (params.length >= paramCounts[name]) { + data.push([b].concat(params.splice(0, paramCounts[name]))); + if (!paramCounts[name]) { + break; + }; + } + }); + data.toString = toString; + return data; +}; +Raphael.pathDimensions = function (path) { + var pathArray = path; + if (typeof path == "string") { + pathArray = this.parsePathString(path); + } + pathArray = this.pathToAbsolute(pathArray); + var x = [], y = [], length = 0; + for (var i = 0, ii = pathArray.length; i < ii; i++) { + switch (pathArray[i][0]) { + case "Z": + break; + case "A": + x.push(pathArray[i][pathArray[i].length - 2]); + y.push(pathArray[i][pathArray[i].length - 1]); + break; + default: + for (var j = 1, jj = pathArray[i].length; j < jj; j++) { + if (j % 2) { + x.push(pathArray[i][j]); + } else { + y.push(pathArray[i][j]); + } + } + } + } + var minx = Math.min.apply(Math, x), + miny = Math.min.apply(Math, y); + return { + x: minx, + y: miny, + width: Math.max.apply(Math, x) - minx, + height: Math.max.apply(Math, y) - miny, + X: x, + Y: y + }; +}; +Raphael.pathToRelative = function (pathArray) { + var res = []; + if (typeof pathArray == "string") { + pathArray = this.parsePathString(pathArray); + } + var x = 0, y = 0, start = 0; + if (pathArray[0][0] == "M") { + x = pathArray[0][1]; + y = pathArray[0][2]; + start++; + res.push(pathArray[0]); + } + for (var i = start, ii = pathArray.length; i < ii; i++) { + res[i] = []; + if (pathArray[i][0] != pathArray[i][0].toLowerCase()) { + res[i][0] = pathArray[i][0].toLowerCase(); + switch (res[i][0]) { + case "a": + res[i][1] = pathArray[i][1]; + res[i][2] = pathArray[i][2]; + res[i][3] = 0; + res[i][4] = pathArray[i][4]; + res[i][5] = pathArray[i][5]; + res[i][6] = +(pathArray[i][6] - x).toFixed(3); + res[i][7] = +(pathArray[i][7] - y).toFixed(3); + break; + case "v": + res[i][1] = +(pathArray[i][1] - y).toFixed(3); + break; + default: + for (var j = 1, jj = pathArray[i].length; j < jj; j++) { + res[i][j] = +(pathArray[i][j] - ((j % 2) ? x : y)).toFixed(3); + } + } + } else { + res[i] = pathArray[i]; + } + switch (res[i][0]) { + case "z": + break; + case "h": + x += res[i][res[i].length - 1]; + break; + case "v": + y += res[i][res[i].length - 1]; + break; + default: + x += res[i][res[i].length - 2]; + y += res[i][res[i].length - 1]; + } + } + res.toString = pathArray.toString; + return res; +}; +Raphael.pathToAbsolute = function (pathArray) { + var res = []; + if (typeof pathArray == "string") { + pathArray = this.parsePathString(pathArray); + } + var x = 0, y = 0, start = 0; + if (pathArray[0][0] == "M") { + x = +pathArray[0][1]; + y = +pathArray[0][2]; + start++; + res[0] = pathArray[0]; + } + for (var i = start, ii = pathArray.length; i < ii; i++) { + res[i] = []; + if (pathArray[i][0] != pathArray[i][0].toUpperCase()) { + res[i][0] = pathArray[i][0].toUpperCase(); + switch (res[i][0]) { + case "A": + res[i][1] = pathArray[i][1]; + res[i][2] = pathArray[i][2]; + res[i][3] = 0; + res[i][4] = pathArray[i][4]; + res[i][5] = pathArray[i][5]; + res[i][6] = +(pathArray[i][6] + x).toFixed(3); + res[i][7] = +(pathArray[i][7] + y).toFixed(3); + break; + case "V": + res[i][1] = +pathArray[i][1] + y; + break; + default: + for (var j = 1, jj = pathArray[i].length; j < jj; j++) { + res[i][j] = +pathArray[i][j] + ((j % 2) ? x : y); + } + } + } else { + res[i] = pathArray[i]; + } + switch (res[i][0]) { + case "Z": + break; + case "H": + x = res[i][1]; + break; + case "V": + y = res[i][1]; + break; + default: + x = res[i][res[i].length - 2]; + y = res[i][res[i].length - 1]; + } + } + res.toString = pathArray.toString; + return res; +}; +Raphael.pathEqualiser = function (path1, path2) { + var data = [this.pathToAbsolute(this.parsePathString(path1)), this.pathToAbsolute(this.parsePathString(path2))], + attrs = [{x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0}, {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0}], + processPath = function (path, d) { + if (!path) { + return ["U"]; + } + switch (path[0]) { + case "M": + d.X = path[1]; + d.Y = path[2]; + break; + case "S": + var nx = d.x + (d.x - (d.bx || d.x)); + var ny = d.y + (d.y - (d.by || d.y)); + path = ["C", nx, ny, path[1], path[2], path[3], path[4]]; + break; + case "T": + var nx = d.x + (d.x - (d.bx || d.x)); + var ny = d.y + (d.y - (d.by || d.y)); + path = ["Q", nx, ny, path[1], path[2]]; + break; + case "H": + path = ["L", path[1], d.y]; + break; + case "V": + path = ["L", d.x, path[1]]; + break; + case "Z": + path = ["L", d.X, d.Y]; + break; + } + return path; + }, + edgeCases = function (a, b, i) { + if (data[a][i][0] == "M" && data[b][i][0] != "M") { + data[b].splice(i, 0, ["M", attrs[b].x, attrs[b].y]); + attrs[a].bx = data[a][i][data[a][i].length - 4] || 0; + attrs[a].by = data[a][i][data[a][i].length - 3] || 0; + attrs[a].x = data[a][i][data[a][i].length - 2]; + attrs[a].y = data[a][i][data[a][i].length - 1]; + return true; + } else if (data[a][i][0] == "L" && data[b][i][0] == "C") { + data[a][i] = ["C", attrs[a].x, attrs[a].y, data[a][i][1], data[a][i][2], data[a][i][1], data[a][i][2]]; + } else if (data[a][i][0] == "L" && data[b][i][0] == "Q") { + data[a][i] = ["Q", data[a][i][1], data[a][i][2], data[a][i][1], data[a][i][2]]; + } else if (data[a][i][0] == "Q" && data[b][i][0] == "C") { + var x = data[b][i][data[b][i].length - 2]; + var y = data[b][i][data[b][i].length - 1]; + data[b].splice(i + 1, 0, ["Q", x, y, x, y]); + data[a].splice(i, 0, ["C", attrs[a].x, attrs[a].y, attrs[a].x, attrs[a].y, attrs[a].x, attrs[a].y]); + i++; + attrs[b].bx = data[b][i][data[b][i].length - 4] || 0; + attrs[b].by = data[b][i][data[b][i].length - 3] || 0; + attrs[b].x = data[b][i][data[b][i].length - 2]; + attrs[b].y = data[b][i][data[b][i].length - 1]; + return true; + } else if (data[a][i][0] == "A" && data[b][i][0] == "C") { + var x = data[b][i][data[b][i].length - 2]; + var y = data[b][i][data[b][i].length - 1]; + data[b].splice(i + 1, 0, ["A", 0, 0, data[a][i][3], data[a][i][4], data[a][i][5], x, y]); + data[a].splice(i, 0, ["C", attrs[a].x, attrs[a].y, attrs[a].x, attrs[a].y, attrs[a].x, attrs[a].y]); + i++; + attrs[b].bx = data[b][i][data[b][i].length - 4] || 0; + attrs[b].by = data[b][i][data[b][i].length - 3] || 0; + attrs[b].x = data[b][i][data[b][i].length - 2]; + attrs[b].y = data[b][i][data[b][i].length - 1]; + return true; + } else if (data[a][i][0] == "U") { + data[a][i][0] = data[b][i][0]; + for (var j = 1, jj = data[b][i].length; j < jj; j++) { + data[a][i][j] = (j % 2) ? attrs[a].x : attrs[a].y; + } + } + return false; + }; + for (var i = 0; i < Math.max(data[0].length, data[1].length); i++) { + data[0][i] = processPath(data[0][i], attrs[0]); + data[1][i] = processPath(data[1][i], attrs[1]); + if (data[0][i][0] != data[1][i][0] && (edgeCases(0, 1, i) || edgeCases(1, 0, i))) { + continue; + } + attrs[0].bx = data[0][i][data[0][i].length - 4] || 0; + attrs[0].by = data[0][i][data[0][i].length - 3] || 0; + attrs[0].x = data[0][i][data[0][i].length - 2]; + attrs[0].y = data[0][i][data[0][i].length - 1]; + attrs[1].bx = data[1][i][data[1][i].length - 4] || 0; + attrs[1].by = data[1][i][data[1][i].length - 3] || 0; + attrs[1].x = data[1][i][data[1][i].length - 2]; + attrs[1].y = data[1][i][data[1][i].length - 1]; + } + return data; +}; diff --git a/public/js/raphael.path.methods.js b/public/js/raphael.path.methods.js new file mode 100644 index 0000000..bce7036 --- /dev/null +++ b/public/js/raphael.path.methods.js @@ -0,0 +1,53 @@ +Raphael.el.isAbsolute = true; +Raphael.el.absolutely = function () { + this.isAbsolute = 1; + return this; +}; +Raphael.el.relatively = function () { + this.isAbsolute = 0; + return this; +}; +Raphael.el.moveTo = function (x, y) { + this._last = {x: x, y: y}; + return this.attr({path: this.attrs.path + ["m", "M"][+this.isAbsolute] + parseFloat(x) + " " + parseFloat(y)}); +}; +Raphael.el.lineTo = function (x, y) { + this._last = {x: x, y: y}; + return this.attr({path: this.attrs.path + ["l", "L"][+this.isAbsolute] + parseFloat(x) + " " + parseFloat(y)}); +}; +Raphael.el.arcTo = function (rx, ry, large_arc_flag, sweep_flag, x, y, angle) { + this._last = {x: x, y: y}; + return this.attr({path: this.attrs.path + ["a", "A"][+this.isAbsolute] + [parseFloat(rx), parseFloat(ry), +angle, large_arc_flag, sweep_flag, parseFloat(x), parseFloat(y)].join(" ")}); +}; +Raphael.el.curveTo = function () { + var args = Array.prototype.splice.call(arguments, 0, arguments.length), + d = [0, 0, 0, 0, "s", 0, "c"][args.length] || ""; + this.isAbsolute && (d = d.toUpperCase()); + this._last = {x: args[args.length - 2], y: args[args.length - 1]}; + return this.attr({path: this.attrs.path + d + args}); +}; +Raphael.el.cplineTo = function (x, y, w) { + this.attr({path: this.attrs.path + ["C", this._last.x + w, this._last.y, x - w, y, x, y]}); + this._last = {x: x, y: y}; + return this; +}; +Raphael.el.qcurveTo = function () { + var d = [0, 1, "t", 3, "q"][arguments.length], + args = Array.prototype.splice.call(arguments, 0, arguments.length); + if (this.isAbsolute) { + d = d.toUpperCase(); + } + this._last = {x: args[args.length - 2], y: args[args.length - 1]}; + return this.attr({path: this.attrs.path + d + args}); +}; +Raphael.el.addRoundedCorner = function (r, dir) { + var rollback = this.isAbsolute; + rollback && this.relatively(); + this._last = {x: r * (!!(dir.indexOf("r") + 1) * 2 - 1), y: r * (!!(dir.indexOf("d") + 1) * 2 - 1)}; + this.arcTo(r, r, 0, {"lu": 1, "rd": 1, "ur": 1, "dl": 1}[dir] || 0, this._last.x, this._last.y); + rollback && this.absolutely(); + return this; +}; +Raphael.el.andClose = function () { + return this.attr({path: this.attrs.path + "z"}); +}; diff --git a/templates/data.html.ep.template b/templates/data.html.ep.template new file mode 100644 index 0000000..0484c99 --- /dev/null +++ b/templates/data.html.ep.template @@ -0,0 +1,14 @@ +
+ + + + + + + + + + + +
+
diff --git a/templates/index.html.ep b/templates/index.html.ep index c4e2c75..50abb4c 100644 --- a/templates/index.html.ep +++ b/templates/index.html.ep @@ -83,6 +83,7 @@ +%= javascript 'js/dmuploader.min.js' %= javascript begin function link(url, dl) { if (dl !== '') { diff --git a/templates/layouts/default.html.ep b/templates/layouts/default.html.ep index 0000a1f..b73e1dc 100644 --- a/templates/layouts/default.html.ep +++ b/templates/layouts/default.html.ep @@ -34,7 +34,6 @@ % end %= javascript 'js/jquery-2.1.0.min.js' %= javascript 'js/bootstrap.min.js' - %= javascript 'js/dmuploader.min.js'
diff --git a/templates/stats.html.ep b/templates/stats.html.ep new file mode 100644 index 0000000..58b49c6 --- /dev/null +++ b/templates/stats.html.ep @@ -0,0 +1,63 @@ +% # vim:set sts=4 sw=4 ts=4 ft=html.epl expandtab: +%= javascript 'js/raphael.js' +%= javascript 'js/raphael.path.methods.js' +%= javascript 'js/jquery.simplegraph.js' +%= include 'data' +
+
+

<%=l 'graph-data-once-a-day' %>

+ +

<%= $total %><%=l 'pushed-images' %>

+ +%= javascript begin + function graph(stats_data, stats_labels, stats_total) { + // Plot the data + // - Temperature Graph - adds colour, fill, and a minimum value for the y axis + $("#evol-holder").simplegraph( + stats_data, + stats_labels, + { + addHover: true, + penColor: "#f00", + fillUnderLine: true, + drawPoints: true, + width: document.body.offsetWidth - 50 + } + ) + $("#total-holder").simplegraph( + stats_total, + stats_labels, + { + addHover: true, + penColor: "#00f", + fillUnderLine: true, + drawPoints: true, + width: document.body.offsetWidth - 50 + } + ); + } + $(document).ready(function() { + // Get the data + var stats_labels = [], stats_data = [], stats_total = []; + $("#stats-data thead th").each(function () { + stats_labels.push($(this).html()); + }); + $("#stats-data tbody tr:first-child td").each(function () { + stats_data.push($(this).html()); + }); + $("#stats-data tbody tr:nth-child(2) td").each(function () { + stats_total.push($(this).html()); + }); + + // Hide the data + $("#stats-data").hide(); + + graph(stats_data, stats_labels, stats_total); + + $(window).resize(function() { + $("#evol-holder").empty(); + $("#total-holder").empty(); + graph(stats_data, stats_labels, stats_total); + }); + }); +% end