From 63a1381c12de84339189e0a911d6bdd60eac3923 Mon Sep 17 00:00:00 2001 From: Repellent Date: Wed, 18 Feb 2026 23:16:43 +0500 Subject: [PATCH] Initial commit --- README.md | 38 +- class/unicalendar.php | 632 +++++ css/eventCalendar.css | 99 + css/eventCalendar_theme_responsive.css | 602 +++++ css/eventCalendar_theme_responsive_min.css | 1 + css/index.php | 4 + images/css_sprites.png | Bin 0 -> 22842 bytes images/index.php | 4 + images/question_alert.png | Bin 0 -> 1219 bytes images/question_select.png | Bin 0 -> 1208 bytes images/question_start_one.png | Bin 0 -> 1222 bytes index.php | 4 + info.php | 20 + js/data-files/index.php | 4 + js/index.php | 4 + js/jquery.eventCalendar.js | 516 ++++ js/jquery.eventCalendar.min.js | 13 + js/moment.js | 2856 ++++++++++++++++++++ lang/bg.php | 16 + lang/bg.txt | 64 + lang/index.php | 4 + lang/ru.php | 16 + lang/ru.txt | 82 + module.php | 79 + sql.php | 90 + templates/admin_unicalendar_edit.tpl | 584 ++++ templates/admin_unicalendar_list.tpl | 636 +++++ templates/index.php | 4 + templates/unicalendar.tpl | 1 + 29 files changed, 6371 insertions(+), 2 deletions(-) create mode 100644 class/unicalendar.php create mode 100644 css/eventCalendar.css create mode 100644 css/eventCalendar_theme_responsive.css create mode 100644 css/eventCalendar_theme_responsive_min.css create mode 100644 css/index.php create mode 100644 images/css_sprites.png create mode 100644 images/index.php create mode 100644 images/question_alert.png create mode 100644 images/question_select.png create mode 100644 images/question_start_one.png create mode 100644 index.php create mode 100644 info.php create mode 100644 js/data-files/index.php create mode 100644 js/index.php create mode 100644 js/jquery.eventCalendar.js create mode 100644 js/jquery.eventCalendar.min.js create mode 100644 js/moment.js create mode 100644 lang/bg.php create mode 100644 lang/bg.txt create mode 100644 lang/index.php create mode 100644 lang/ru.php create mode 100644 lang/ru.txt create mode 100644 module.php create mode 100644 sql.php create mode 100644 templates/admin_unicalendar_edit.tpl create mode 100644 templates/admin_unicalendar_list.tpl create mode 100644 templates/index.php create mode 100644 templates/unicalendar.tpl diff --git a/README.md b/README.md index 5005964..9536591 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,37 @@ -# unicalendar +### Unicalendar -Модуль календарь событий Только для AVE.CMS ALT \ No newline at end of file +## Модуль Unicalendar - календарь событий + +#### адаптирован для AVE.CMS v3.26 + +### Модуль позволяет создавать календари, событиями которых являются документы из заданной рубрики либо определенные документы из заданной рубрики. + +##### Changelog: + +##### 05.09.2019 - обновление модуля - версия 1.26.8 - адаптация для версии ave.cms 3.26, замена устаревшего size() на length + +##### 08.09.2017 - обновление модуля - версия 1.2.8 - Fix регулярного выражения для сохранения в файл (dataX.js) в кодировке UTF-8 + +##### 04.09.2017 - обновление модуля - версия 1.2.7 - Добавлено создание тизера событий из существующих полей в документе (изображение, описание, место) + +##### 01.07.2017 - обновление модуля - версия 1.2.6 - Добавлен лимит вывода событий при перелистывании месяцев в календаре (лимит не распространяется на клик по дате с событиями) + +##### 25.06.2017 - обновление модуля - версия 1.2.5 - Добавлен выбор формата даты для публичной части календаря, проверка условий при создании календаря + +##### 15.05.2017 - обновление модуля - версия 1.2.4 - Исправлено: jQuery Form Styler - ограничивал раскрытие select по высоте; Исправлено ленг файл .php будет подключаться, в зависимости от языка Администратора (в админ-панели) и Пользователя (в публичной части) + +##### 14.05.2017 - обновление модуля - версия 1.2.3 - изменен алгоритм проверки актуальности календарей + +##### 09.05.2017 - обновление модуля - версия 1.2.2 - добавлена проверка актуальности календарей при изменении количества документов в рубрике после создания календаря + +##### 06.05.2017 - обновление модуля - версия 1.2.1 - оптимизация запросов БД для публичной части модуля + +##### 05.05.2017 - обновление модуля - версия 1.2 - исправление ошибок, добавлено редактирование календарей, скрипты вынесены в секцию + +##### 10.04.2017 - обновление модуля - версия 1.1.2 - fix вывода документа - ошибка 404. + +##### 10.04.2017 - обновление модуля - версия 1.1.1 - fix для корректной работы модуля с версиями php начиная с =>5.3.13 + +##### 09.04.2017 - обновление модуля - версия 1.1 (требуется чистая установка: полное удаление версии 1.0 и вместо нее залить все файлы v1.1) + +##### 09.04.2017 - инициализация модуля - версия 1.0 \ No newline at end of file diff --git a/class/unicalendar.php b/class/unicalendar.php new file mode 100644 index 0000000..37d3f3a --- /dev/null +++ b/class/unicalendar.php @@ -0,0 +1,632 @@ +'; + $eventCalendar_theme_responsive_css = ''; + $moment_js = ''; + $jquery_eventCalendar_js = ''; + $GLOBALS['user_header']['module_unicalendar_'] = $eventCalendar_css."\n".$eventCalendar_theme_responsive_css."\n".$moment_js."\n".$jquery_eventCalendar_js; + // подключаем в секции js файл с данным , согласно Id календаря + $data_dir = "/modules/unicalendar/js/data-files"; + $filename = BASE_DIR .$data_dir."/data".$id.".js"; + if (file_exists($filename)) + { + $GLOBALS['user_header']['module_unicalendar_' . $id] = ''; + } + else { + echo $uca_file_not_found.$id.".js"; // если не смогли подключить файл -выводим сообщение-подсказку + }; + global $AVE_Template; + $AVE_Template->assign('id', $id); + $AVE_Template->display($tpl_dir . 'unicalendar.tpl'); + } + + /** + * ФУНКЦИИ АДМИНИСТРАТИВНОЙ ЧАСТИ + */ + + + /** + * Вывод списка календарей + * + * @param string $tpl_dir - путь к папке с шаблонами модуля + */ + function unicalendarList($tpl_dir) + { + global $AVE_DB, $AVE_Template; + + $unicalendars = array(); + + $limit = 20; + $start = get_current_page() * $limit - $limit; + + $sql = $AVE_DB->Query(" + SELECT SQL_CALC_FOUND_ROWS + u.*, + COUNT(u.id) AS uca_count + FROM + " . PREFIX . "_module_unicalendar AS u + GROUP BY u.id + ORDER BY u.id ASC + LIMIT " . $start . "," . $limit . " + "); + + $sql_num = $AVE_DB->Query("SELECT FOUND_ROWS()"); + $num = $sql_num->GetCell(); + + while($row = $sql->FetchAssocArray()) + { + array_push($unicalendars, $row); + } + + if ($num > $limit) + { + $page_nav = "
  • {t}
  • "; + $page_nav = get_pagination(ceil($num / $limit), 'page', $page_nav); + } + else + { + $page_nav = ''; + } + + $AVE_Template->assign('page_nav', $page_nav); + + if (!empty($_REQUEST['alert'])) + { + $AVE_Template->assign('alert', htmlspecialchars(stripslashes($_REQUEST['alert']))); + } + + $AVE_Template->assign('unicalendars', $unicalendars); + $AVE_Template->assign('formaction', 'index.php?do=modules&action=modedit&mod=unicalendar&moduleaction=new&sub=save&cp=' . SESSION); + $AVE_Template->assign('content', $AVE_Template->fetch($tpl_dir . 'admin_unicalendar_list.tpl')); + } + + /** + * Создание календаря + * + */ + function unicalendarNew() + { + if (isset($_REQUEST['sub']) && $_REQUEST['sub'] == 'save') + { + global $AVE_DB; + $cont = true; + $alert = ''; + if (empty($_POST['uca_title'])) + { + $alert = '&alert=empty_uca_title'; + $cont = false; + } + if ($cont) + { + $AVE_DB->Query(" + INSERT + INTO " . PREFIX . "_module_unicalendar + SET + id = '', + uca_title = '" . $_POST['uca_title'] . "', + uca_date_format = '" . $_POST['uca_date_format'] . "', + uca_events = '" . $_POST['uca_events'] . "', + uca_rubric_id = '" . $_POST['uca_rubric_id'] . "', + uca_rubric_title = '" . $_POST['uca_rubric_title'] . "', + uca_doc_id = '" . $_POST['uca_doc_id'] . "', + uca_link = '" . $_POST['uca_link'] . "', + uca_day = '" . $_POST['uca_day'] . "', + uca_scroll = '" . $_POST['uca_scroll'] . "', + uca_descript = '" . $_POST['uca_descript'] . "', + uca_events_limit = '" . $_POST['uca_events_limit'] . "', + uca_img_field = '" . $_POST['i_uca_img_field'] . "', + uca_dsc_field = '" . $_POST['i_uca_dsc_field'] . "', + uca_place_field = '" . $_POST['i_uca_place_field'] . "' + "); + + // Получаем обновленные данные календаря + require(BASE_DIR . '/modules/unicalendar/lang/'.$_SESSION['admin_language'].'.php'); // загружаем файл ленгов для php переменных + $sql = $AVE_DB->Query(" + SELECT * + FROM " . PREFIX . "_module_unicalendar + WHERE id = '".$AVE_DB->InsertId()."' + "); + $unicalendars = array(); + while ($row = $sql->FetchAssocArray()) + { + array_push($unicalendars, $row); + } + foreach ( $unicalendars as $k=>$v ) + { + $uca_id = $v['id']; + $uca_dfrm = $v['uca_date_format']; + $uevents = $v['uca_events']; + $urubric_id = $v['uca_rubric_id']; + $udoc_id = $v['uca_doc_id']; + $uca_day = $v['uca_day']; + $uca_scroll = $v['uca_scroll']; + $uca_link = $v['uca_link']; + $uca_descript = $v['uca_descript']; + $uca_events_limit = $v['uca_events_limit']; + $uca_img_field = $v['uca_img_field']; + $uca_dsc_field = $v['uca_dsc_field']; + $uca_place_field = $v['uca_place_field']; + } + if ($uca_dsc_field != 0) {$ellipsis = '… ';} else {$ellipsis = '';};// если описания нет не добавляем многоточие при выводе description + // Если выбрали вывести все документы из заданной рубрики - документы с Id=1 (Главная) и 404 страница - выводиться не будут! + if ($uevents !='' && $uevents == '1'){ + $sql = $AVE_DB->Query(" + SELECT Id, document_alias, document_title, document_published, document_expire, document_meta_description + FROM " . PREFIX . "_documents + WHERE rubric_id = '" . $urubric_id . "' AND Id !=1 && Id != '".PAGE_NOT_FOUND_ID."' + "); + $results = array(); + while ($row = $sql->FetchAssocArray()) + { + array_push($results, $row); + } + //получаем данные всех документов из заданной рубрики циклом, формируем строку JSON + foreach ( $results as $k=>$v ) + { + $uni_data .= "{ \"date\": \"".pretty_date(strftime('%Y-%m-%d %H:%M:%S', $v['document_published']))."\", \"expire_date\": \"".pretty_date(strftime('%Y-%m-%d %H:%M:%S', $v['document_expire']))."\", \"title\": \"".$v['document_title']."\", \"image\": \"".strstr(get_document_field($v['Id'], $uca_img_field), '|', true)."\", \"description\": \"".rtrim(mb_substr(preg_replace('|[\s]+|su', ' ', strip_tags(get_document_field($v['Id'], $uca_dsc_field))), 0, 255, 'UTF-8'), "!,.-").$ellipsis."\", \"location\": \"".mb_substr(preg_replace('|[\s]+|su', ' ', strip_tags(get_document_field($v['Id'], $uca_place_field))), 0, 300, 'UTF-8')."\", \"url\": \"".$v['document_alias']."\" },"; + $rubric_count .= $v['Id']." OR Id="; + } + $js_data_files = "$(function(){"."var data".$uca_id." = [".$uni_data."]; $(\"#eventCalendar".$uca_id."\").eventCalendar({jsonData: data".$uca_id.", jsonDateFormat: \"human\", startWeekOnMonday: ".$uca_day.", eventsScrollable: ".$uca_scroll.", openEventInNewWindow: ".$uca_link.", dateFormat: \"".$uca_dfrm."\", showDescription: ".$uca_descript.", eventsLimit: ".$uca_events_limit.", locales: {locale: \"".$uca_locale."\", txt_noEvents: \"".$uca_no_events."\", txt_SpecificEvents_prev: \"\", txt_SpecificEvents_after: \"".$uca_real_events."\", txt_NextEvents: \"".$uca_next_events."\", txt_GoToEventUrl: \"".$uca_look_events."\", moment: {\"months\" : ".$uca_months_events.", \"monthsShort\" : ".$uca_monshort_events.", \"weekdays\" : ".$uca_weekdays_events.", \"weekdaysShort\" : ".$uca_wdayshort_events.", \"weekdaysMin\" : ".$uca_wdaymin_events."}}});});"; + + // Получаем Id документов в категории на момент создания календаря и записываем значение в БД + $rubric_count ='Id='.$rubric_count; + $rubric_count = chop($rubric_count, ' OR Id='); + + $AVE_DB->Query(" + UPDATE + " . PREFIX . "_module_unicalendar + SET + uca_doc_id = '" . $rubric_count . "' + WHERE id = '" . $uca_id . "' + "); + + // Создаем js файл для календаря с названием dataXXX.js - где XXX = Id календаря + $fdir = "/modules/unicalendar/js/data-files/"; + mkdir(BASE_DIR . $fdir, 0777, true); + chmod(BASE_DIR . $fdir, 0777); + $df = fopen(BASE_DIR . "/modules/unicalendar/js/data-files/data".$uca_id.".js", "w") + or die($uca_not_write_file);// ругаемся если нет прав на запись в директорию data-files ! + flock($df,2); + fwrite($df, $js_data_files); + flock($df,3); + fclose($df); + } + + // Если выбрали вывести выбранные документы из заданной рубрики - документы с Id=1 (Главная) и 404 страница - выводиться не будут! + if ($uevents !='' && $uevents == '2'){ + $sql = $AVE_DB->Query(" + SELECT Id, document_alias, document_title, document_published, document_expire, document_meta_description + FROM " . PREFIX . "_documents + WHERE rubric_id = '" . $urubric_id . "' AND Id !=1 && Id != '".PAGE_NOT_FOUND_ID."' AND ".$udoc_id." + "); + $results = array(); + while ($row = $sql->FetchAssocArray()) + { + array_push($results, $row); + } + //получаем данные выбранных документов из заданной рубрики циклом, формируем строку JSON + foreach ( $results as $k=>$v ) + { + $uni_data .= "{ \"date\": \"".pretty_date(strftime('%Y-%m-%d %H:%M:%S', $v['document_published']))."\", \"expire_date\": \"".pretty_date(strftime('%Y-%m-%d %H:%M:%S', $v['document_expire']))."\", \"title\": \"".$v['document_title']."\", \"image\": \"".strstr(get_document_field($v['Id'], $uca_img_field), '|', true)."\", \"description\": \"".rtrim(mb_substr(preg_replace('|[\s]+|su', ' ', strip_tags(get_document_field($v['Id'], $uca_dsc_field))), 0, 255, 'UTF-8'), "!,.-").$ellipsis."\", \"location\": \"".mb_substr(preg_replace('|[\s]+|su', ' ', strip_tags(get_document_field($v['Id'], $uca_place_field))), 0, 300, 'UTF-8')."\", \"url\": \"".$v['document_alias']."\" },"; + $rubric_count .= $v['Id'].","; + } + $js_data_files = "$(function(){"."var data".$uca_id." = [".$uni_data."]; $(\"#eventCalendar".$uca_id."\").eventCalendar({jsonData: data".$uca_id.", jsonDateFormat: \"human\", startWeekOnMonday: ".$uca_day.", eventsScrollable: ".$uca_scroll.", openEventInNewWindow: ".$uca_link.", dateFormat: \"".$uca_dfrm."\", showDescription: ".$uca_descript.", eventsLimit: ".$uca_events_limit.", locales: {locale: \"".$uca_locale."\", txt_noEvents: \"".$uca_no_events."\", txt_SpecificEvents_prev: \"\", txt_SpecificEvents_after: \"".$uca_real_events."\", txt_NextEvents: \"".$uca_next_events."\", txt_GoToEventUrl: \"".$uca_look_events."\", moment: {\"months\" : ".$uca_months_events.", \"monthsShort\" : ".$uca_monshort_events.", \"weekdays\" : ".$uca_weekdays_events.", \"weekdaysShort\" : ".$uca_wdayshort_events.", \"weekdaysMin\" : ".$uca_wdaymin_events."}}});});"; + + // Создаем js файл для календаря с названием dataXXX.js - где XXX = Id календаря + $fdir = "/modules/unicalendar/js/data-files/"; + mkdir(BASE_DIR . $fdir, 0777, true); + chmod(BASE_DIR . $fdir, 0777); + $df = fopen(BASE_DIR . "/modules/unicalendar/js/data-files/data".$uca_id.".js", "w") + or die($uca_not_write_file);// ругаемся если нет прав на запись в директорию data-files ! + flock($df,2); + fwrite($df, $js_data_files); + flock($df,3); + fclose($df); + } + } + header('Location:index.php?do=modules&action=modedit&mod=unicalendar&moduleaction=1'. $alert); + exit; + } + } + + /** + * Редактирование календаря + * @param int $unicalendar_id - идентификатор календаря + */ + function unicalendarEdit($tpl_dir, $unicalendar_id) + { + global $AVE_DB, $AVE_Template; + $sql = $AVE_DB->Query(" + SELECT * + FROM " . PREFIX . "_module_unicalendar + WHERE id = '" . $unicalendar_id . "' + "); + $unicalendars = array(); + while ($row = $sql->FetchAssocArray()) + { + array_push($unicalendars, $row); + } + foreach ( $unicalendars as $k=>$v ) + { + $uevents = $v['uca_events']; + $urubric_id = $v['uca_rubric_id']; + $udoc_id = $v['uca_doc_id']; + } + + if($uevents == 2) + { + $sql = $AVE_DB->Query(" + SELECT Id, document_alias, document_title, document_published, document_expire, document_meta_description + FROM " . PREFIX . "_documents + WHERE rubric_id = '" . $urubric_id . "' AND Id !=1 && Id != '".PAGE_NOT_FOUND_ID."' + "); + $unidocs = array(); + while ($row = $sql->FetchAssocArray()) + { + array_push($unidocs, $row); + } + $AVE_Template->assign('unidocs', $unidocs); + + $sql = $AVE_DB->Query(" + SELECT Id + FROM " . PREFIX . "_documents + WHERE rubric_id = '" . $urubric_id . "' AND Id !=1 && Id != '".PAGE_NOT_FOUND_ID."' AND ".$udoc_id." + "); + $check_docs = array(); + while ($row = $sql->FetchAssocArray()) + { + array_push($check_docs, $row); + } + $AVE_Template->assign('check_docs', $check_docs); + } + + //$AVE_Template->assign('uca_rub_fields', $uca_rub_fields); + $AVE_Template->assign('unicalendars', $unicalendars); + $AVE_Template->assign('content', $AVE_Template->fetch($tpl_dir . 'admin_unicalendar_edit.tpl')); + + } + + /** + * Сохранение календаря после редактирования + * @param int $unicalendar_id - идентификатор календаря + */ + function unicalendarEditSave($unicalendar_id) + { + global $AVE_DB; + $AVE_DB->Query(" + UPDATE + " . PREFIX . "_module_unicalendar + SET + uca_title = '" . $_POST['uca_title'] . "', + uca_date_format = '" . $_POST['uca_date_format'] . "', + uca_doc_id = '" . $_POST['uca_doc_id'] . "', + uca_events = '" . $_POST['uca_events'] . "', + uca_rubric_id = '" . $_POST['uca_rubric_id'] . "', + uca_rubric_title = '" . $_POST['uca_rubric_title'] . "', + uca_link = '" . $_POST['uca_link'] . "', + uca_day = '" . $_POST['uca_day'] . "', + uca_scroll = '" . $_POST['uca_scroll'] . "', + uca_descript = '" . $_POST['uca_descript'] . "', + uca_events_limit = '" . $_POST['uca_events_limit'] . "', + uca_img_field = '" . $_POST['send_uca_img_field'] . "', + uca_dsc_field = '" . $_POST['send_uca_dsc_field'] . "', + uca_place_field = '" . $_POST['send_uca_place_field'] . "' + WHERE id = '" . $unicalendar_id . "' + "); + $as = array(); + $as->$_POST['uca_title']; + $as->$_POST['uca_rubric_title']; + echo json_encode($as); + // Получаем обновленные данные календаря + require(BASE_DIR . '/modules/unicalendar/lang/'.$_SESSION['admin_language'].'.php'); // загружаем файл ленгов для php переменных + $sql = $AVE_DB->Query(" + SELECT * + FROM " . PREFIX . "_module_unicalendar + WHERE id = '" . $unicalendar_id . "' + "); + $unicalendars = array(); + while ($row = $sql->FetchAssocArray()) + { + array_push($unicalendars, $row); + } + foreach ( $unicalendars as $k=>$v ) + { + $uevents = $v['uca_events']; + $uca_dfrm = $v['uca_date_format']; + $urubric_id = $v['uca_rubric_id']; + $udoc_id = $v['uca_doc_id']; + $uca_day = $v['uca_day']; + $uca_scroll = $v['uca_scroll']; + $uca_link = $v['uca_link']; + $uca_descript = $v['uca_descript']; + $uca_events_limit = $v['uca_events_limit']; + $uca_img_field = $v['uca_img_field']; + $uca_dsc_field = $v['uca_dsc_field']; + $uca_place_field = $v['uca_place_field']; + } + if ($uca_dsc_field != 0) {$ellipsis = '… ';} else {$ellipsis = '';};// если описания нет не добавляем многоточие при выводе description + // Если выбрали вывести все документы из заданной рубрики - документы с Id=1 (Главная) и 404 страница - выводиться не будут! + if ($uevents !='' && $uevents == '1'){ + $sql = $AVE_DB->Query(" + SELECT Id, document_alias, document_title, document_published, document_expire, document_meta_description + FROM " . PREFIX . "_documents + WHERE rubric_id = '" . $urubric_id . "' AND Id !=1 && Id != '".PAGE_NOT_FOUND_ID."' + "); + $results = array(); + while ($row = $sql->FetchAssocArray()) + { + array_push($results, $row); + } + //получаем данные всех документов из заданной рубрики циклом, формируем строку JSON + foreach ( $results as $k=>$v ) + { + $uni_data .= "{ \"date\": \"".pretty_date(strftime('%Y-%m-%d %H:%M:%S', $v['document_published']))."\", \"expire_date\": \"".pretty_date(strftime('%Y-%m-%d %H:%M:%S', $v['document_expire']))."\", \"title\": \"".$v['document_title']."\", \"image\": \"".strstr(get_document_field($v['Id'], $uca_img_field), '|', true)."\", \"description\": \"".rtrim(mb_substr(preg_replace('|[\s]+|su', ' ', strip_tags(get_document_field($v['Id'], $uca_dsc_field))), 0, 255, 'UTF-8'), "!,.-").$ellipsis."\", \"location\": \"".mb_substr(preg_replace('|[\s]+|su', ' ', strip_tags(get_document_field($v['Id'], $uca_place_field))), 0, 300, 'UTF-8')."\", \"url\": \"".$v['document_alias']."\" },"; + $rubric_count .= $v['Id']." OR Id="; + } + $js_data_files = "$(function(){"."var data".$unicalendar_id." = [".$uni_data."]; $(\"#eventCalendar".$unicalendar_id."\").eventCalendar({jsonData: data".$unicalendar_id.", jsonDateFormat: \"human\", startWeekOnMonday: ".$uca_day.", eventsScrollable: ".$uca_scroll.", openEventInNewWindow: ".$uca_link.", dateFormat: \"".$uca_dfrm."\", showDescription: ".$uca_descript.", eventsLimit: ".$uca_events_limit.", locales: {locale: \"".$uca_locale."\", txt_noEvents: \"".$uca_no_events."\", txt_SpecificEvents_prev: \"\", txt_SpecificEvents_after: \"".$uca_real_events."\", txt_NextEvents: \"".$uca_next_events."\", txt_GoToEventUrl: \"".$uca_look_events."\", moment: {\"months\" : ".$uca_months_events.", \"monthsShort\" : ".$uca_monshort_events.", \"weekdays\" : ".$uca_weekdays_events.", \"weekdaysShort\" : ".$uca_wdayshort_events.", \"weekdaysMin\" : ".$uca_wdaymin_events."}}});});"; + + // Получаем Id документов в категории на момент создания календаря и записываем значение в БД + $rubric_count ='Id='.$rubric_count; + $rubric_count = chop($rubric_count, ' OR Id='); + + $AVE_DB->Query(" + UPDATE + " . PREFIX . "_module_unicalendar + SET + uca_doc_id = '" . $rubric_count . "' + WHERE id = '" . $unicalendar_id . "' + "); + + // Создаем js файл для календаря с названием dataXXX.js - где XXX = Id календаря + $fdir = "/modules/unicalendar/js/data-files/"; + mkdir(BASE_DIR . $fdir, 0777, true); + chmod(BASE_DIR . $fdir, 0777); + $df = fopen(BASE_DIR . "/modules/unicalendar/js/data-files/data".$unicalendar_id.".js", "w") + or die($uca_not_write_file);// ругаемся если нет прав на запись в директорию data-files ! + flock($df,2); + fwrite($df, $js_data_files); + flock($df,3); + fclose($df); + } + + // Если выбрали вывести выбранные документы из заданной рубрики - документы с Id=1 (Главная) и 404 страница - выводиться не будут! + if ($uevents !='' && $uevents == '2'){ + $sql = $AVE_DB->Query(" + SELECT Id, document_alias, document_title, document_published, document_expire, document_meta_description + FROM " . PREFIX . "_documents + WHERE rubric_id = '" . $urubric_id . "' AND Id !=1 && Id != '".PAGE_NOT_FOUND_ID."' AND ".$udoc_id." + "); + $results = array(); + while ($row = $sql->FetchAssocArray()) + { + array_push($results, $row); + } + //получаем данные выбранных документов из заданной рубрики циклом, формируем строку JSON + foreach ( $results as $k=>$v ) + { + $uni_data .= "{ \"date\": \"".pretty_date(strftime('%Y-%m-%d %H:%M:%S', $v['document_published']))."\", \"expire_date\": \"".pretty_date(strftime('%Y-%m-%d %H:%M:%S', $v['document_expire']))."\", \"title\": \"".$v['document_title']."\", \"image\": \"".strstr(get_document_field($v['Id'], $uca_img_field), '|', true)."\", \"description\": \"".rtrim(mb_substr(preg_replace('|[\s]+|su', ' ', strip_tags(get_document_field($v['Id'], $uca_dsc_field))), 0, 255, 'UTF-8'), "!,.-").$ellipsis."\", \"location\": \"".mb_substr(preg_replace('|[\s]+|su', ' ', strip_tags(get_document_field($v['Id'], $uca_place_field))), 0, 300, 'UTF-8')."\", \"url\": \"".$v['document_alias']."\" },"; + $rubric_count .= $v['Id'].","; + } + $js_data_files = "$(function(){"."var data".$unicalendar_id." = [".$uni_data."]; $(\"#eventCalendar".$unicalendar_id."\").eventCalendar({jsonData: data".$unicalendar_id.", jsonDateFormat: \"human\", startWeekOnMonday: ".$uca_day.", eventsScrollable: ".$uca_scroll.", openEventInNewWindow: ".$uca_link.", dateFormat: \"".$uca_dfrm."\", showDescription: ".$uca_descript.", eventsLimit: ".$uca_events_limit.", locales: {locale: \"".$uca_locale."\", txt_noEvents: \"".$uca_no_events."\", txt_SpecificEvents_prev: \"\", txt_SpecificEvents_after: \"".$uca_real_events."\", txt_NextEvents: \"".$uca_next_events."\", txt_GoToEventUrl: \"".$uca_look_events."\", moment: {\"months\" : ".$uca_months_events.", \"monthsShort\" : ".$uca_monshort_events.", \"weekdays\" : ".$uca_weekdays_events.", \"weekdaysShort\" : ".$uca_wdayshort_events.", \"weekdaysMin\" : ".$uca_wdaymin_events."}}});});"; + + // Создаем js файл для календаря с названием dataXXX.js - где XXX = Id календаря + $fdir = "/modules/unicalendar/js/data-files/"; + mkdir(BASE_DIR . $fdir, 0777, true); + chmod(BASE_DIR . $fdir, 0777); + $df = fopen(BASE_DIR . "/modules/unicalendar/js/data-files/data".$unicalendar_id.".js", "w") + or die($uca_not_write_file);// ругаемся если нет прав на запись в директорию data-files ! + flock($df,2); + fwrite($df, $js_data_files); + flock($df,3); + fclose($df); + } + + exit; + } + + /** + * Выбор событий календаря + * + */ + + function unicalendarEventsNew() + { + require_once(BASE_DIR . '/modules/unicalendar/lang/'.$_SESSION['admin_language'].'.php'); // загружаем файл ленгов для php переменных + + if (isset($_POST['c'])) // если пришел запрос вывести все категории, получаем данные и отдаем их в шаблон (выпадающий список) + { + global $AVE_DB; + $sql = $AVE_DB->Query(" + SELECT Id, rubric_title + FROM " . PREFIX . "_rubrics + "); + echo ""; + while($result = $sql->FetchRow()) + { + echo ""; + }; + } + + if (isset($_POST['a'])) // если пришел запрос вывести все документы (не будет выведен документ с Id=1 это Главная страница и документ Ошибка 404), получаем и выводим чекбоксами + { + global $AVE_DB; + $sql = $AVE_DB->Query(" + SELECT Id, document_alias, document_title, document_published, document_expire, document_meta_description + FROM " . PREFIX . "_documents + WHERE rubric_id = '" . $_POST['b'] . "' AND Id !=1 && Id != '".PAGE_NOT_FOUND_ID."' + "); + $u_sel_doc = array(); + while ($row = $sql->FetchAssocArray()) + { + array_push($u_sel_doc, $row); + } + foreach ( $u_sel_doc as $k=>$v ) + { + echo ""."".$v['Id'].""."".$v['document_title'].""."".$v['document_published'] = pretty_date(strftime(TIME_FORMAT, $v['document_published'])).""."".$v['document_expire'] = pretty_date(strftime(TIME_FORMAT, $v['document_expire'])).""; + } + } + + + if (isset($_POST['uca_rub_field'])) // если пришел запрос вывести поля категории, получаем данные и отдаем их в шаблон (выпадающий список) + { + global $AVE_DB; + $sql = $AVE_DB->Query(" + SELECT Id, rubric_field_title + FROM " . PREFIX . "_rubric_fields + WHERE rubric_id = '" . $_POST['uca_frub_id'] . "' + "); + while($result = $sql->FetchRow()) + { + echo ""; + }; + } + + global $AVE_DB; + $sql = $AVE_DB->Query(" + SELECT * + FROM " . PREFIX . "_module_unicalendar + WHERE id = '".intval($_REQUEST['id'])."' + "); + $unica = array(); + while ($row = $sql->FetchAssocArray()) + { + array_push($unica, $row); + } + foreach ( $unica as $k=>$v ) + { + $uca_img_field = $v['uca_img_field']; + $uca_dsc_field = $v['uca_dsc_field']; + $uca_place_field = $v['uca_place_field']; + } + + if (isset($_POST['uca_edit_rub_field_img'])) // если пришел запрос вывести поля изображение при редактировании, получаем данные и отдаем их в шаблон (выпадающий список) + { + global $AVE_DB; + $sql = $AVE_DB->Query(" + SELECT Id, rubric_field_title + FROM " . PREFIX . "_rubric_fields + WHERE rubric_id = '" . $_POST['uca_frub_id'] . "' + "); + while($result = $sql->FetchRow()) + { + if($result->Id == $uca_img_field) {$sel = 'selected=\'selected\'';} else {$sel = '';}; + echo ""; + }; + } + + if (isset($_POST['uca_edit_rub_field_dsc'])) // если пришел запрос вывести поля описание при редактировании, получаем данные и отдаем их в шаблон (выпадающий список) + { + global $AVE_DB; + $sql = $AVE_DB->Query(" + SELECT Id, rubric_field_title + FROM " . PREFIX . "_rubric_fields + WHERE rubric_id = '" . $_POST['uca_frub_id'] . "' + "); + while($result = $sql->FetchRow()) + { + if($result->Id == $uca_dsc_field) {$sel = 'selected=\'selected\'';} else {$sel = '';}; + echo ""; + }; + } + + if (isset($_POST['uca_edit_rub_field_plc'])) // если пришел запрос вывести поля место при редактировании, получаем данные и отдаем их в шаблон (выпадающий список) + { + global $AVE_DB; + $sql = $AVE_DB->Query(" + SELECT Id, rubric_field_title + FROM " . PREFIX . "_rubric_fields + WHERE rubric_id = '" . $_POST['uca_frub_id'] . "' + "); + while($result = $sql->FetchRow()) + { + if($result->Id == $uca_place_field) {$sel = 'selected=\'selected\'';} else {$sel = '';}; + echo ""; + }; + } + + + if (isset($_POST['check_rel'])) // если пришел запрос-проверка актуальности календаря (не будет выведен документ с Id=1 это Главная страница и документ Ошибка 404) + { + global $AVE_DB; + $sql = $AVE_DB->Query(" + SELECT Id + FROM " . PREFIX . "_documents + WHERE rubric_id = '" . $_POST['r_id'] . "' AND Id !=1 && Id != '".PAGE_NOT_FOUND_ID."' + "); + $all_doc_rub = array(); + while ($row = $sql->FetchAssocArray()) + { + array_push($all_doc_rub, $row); + } + foreach ( $all_doc_rub as $k=>$v ) + { + $doc_count .= $v['Id'].","; + } + echo $doc_count = chop($doc_count, ' ,'); + } + if (isset($_POST['allowed_rub'])) //если пришел запрос "проверяем и запрещаем создавать календарь, если рубрика содержит только один или два документа, Id которых равны либо главной странице либо странице 404 , либо и то и другое" + { + global $AVE_DB; + $sql = $AVE_DB->Query(" + SELECT Id + FROM " . PREFIX . "_documents + WHERE rubric_id = '" . $_POST['allowed_rub_id'] . "' + "); + $all_doc_rub = array(); + while ($row = $sql->FetchAssocArray()) + { + array_push($all_doc_rub, $row); + } + foreach ( $all_doc_rub as $k=>$v ) + { + $doc_count .= $v['Id'].","; + } + echo $doc_count = chop($doc_count, ' ,'); + } + exit; + } + + /** + * Удаление календаря + * + * @param int $unicalendar_id - идентификатор календаря + */ + function unicalendarDelete($unicalendar_id) + { + global $AVE_DB; + $AVE_DB->Query("DELETE FROM " . PREFIX . "_module_unicalendar WHERE id = '" . $unicalendar_id . "'"); + // Удаляем js файл с данными из директории /modules/unicalendar/js/data-files/ + $data_dir = "/modules/unicalendar/js/data-files"; + $filename = BASE_DIR .$data_dir."/data".$unicalendar_id.".js"; + if (file_exists($filename)) + { + unlink($filename); + } + header('Location:index.php?do=modules&action=modedit&mod=unicalendar&moduleaction=1&cp=' . SESSION); + exit; + } +} +?> \ No newline at end of file diff --git a/css/eventCalendar.css b/css/eventCalendar.css new file mode 100644 index 0000000..a24865f --- /dev/null +++ b/css/eventCalendar.css @@ -0,0 +1,99 @@ +/*= CORE CSS */ + +.eventCalendar-hidden { + display: none; +} + +.eventCalendar-wrap { + position: relative; + overflow: hidden; +} + +.eventCalendar-arrow { + position: absolute; + z-index: 5; + top: 3px; +} + +.eventCalendar-prev { + left: 3px; +} + +.eventCalendar-next { + right: 3px; +} + +.eventCalendar-monthTitle { + display: block; + text-align: center; +} + +.eventCalendar-monthWrap { + position: absolute; + top: 0; + left: 0; + z-index: 2; +} + +.eventCalendar-currentMonth { + z-index: 1; +} + +.eventCalendar-daysList { + display: table; + width: 100%; +} + +.eventCalendar-showAsWeek { + display: block; +} + +.eventCalendar-daysList li { + display: table-cell; +} + +.eventCalendar-dayWithEvents { + background: rgba(0, 0, 0, 0.15); +} + +.eventCalendar-current { + background: rgba(0, 0, 0, 0.35); +} + +.eventCalendar-showAsWeek li { + display: block; + float: left; + width: 14.28%; + height: 20px; +} + +.eventCalendar-daysList a { + padding: 0; + display: block; + text-align: center; + font-size: 8px; + min-width: 7px; +} + +.eventCalendar-loading { + display: block; + min-width: 100px; + height: 40px; + line-height: 40px; +} + +.eventCalendar-list { + position: relative; + z-index: 1; +} + +.eventCalendar-oldEventList { + z-index: 2; +} + +.eventCalendar-subtitle { + padding-left: 5px; + font-weight: bold; + font-size: 120%; +} +/* end of core CSS */ \ No newline at end of file diff --git a/css/eventCalendar_theme_responsive.css b/css/eventCalendar_theme_responsive.css new file mode 100644 index 0000000..f76258e --- /dev/null +++ b/css/eventCalendar_theme_responsive.css @@ -0,0 +1,602 @@ + /* Theme CSS */ + /*html { + background-color:#eee; + } + body { + font-family: Arial, "Lucida Grande", sans-serif; + font-size: 13px; + line-height: 18px; + color: #555; + background-color:#fff; + }*/ +.eventCalendar-wrap { + border:solid 1px #d3d3d3; + box-shadow:0 0 15px #999; + border-radius:5px; + margin-bottom:20px; + background-color:#fff; + color:#807E7E; +} + .eventCalendar-wrap .eventCalendar-arrow { + text-decoration:none; + color:#fff; + padding:0 5px; + line-height:28px; + top:9px; + padding:8px 10px; + } + .eventCalendar-wrap .eventCalendar-arrow.prev { + + } + .eventCalendar-wrap .eventCalendar-arrow:hover { opacity:0.7;} + .eventCalendar-wrap .eventCalendar-arrow span { + height: 0; + width: 0; + font-size: 0; + line-height: 0; + border-top: 6px solid transparent; + border-bottom: 6px solid transparent; + border-left: 6px solid #fff; + float:left; + text-indent:-5000px; + } + .eventCalendar-wrap .eventCalendar-arrow.eventCalendar-prev span { + border-left-width:0; + border-right: 6px solid #fff; + } + .eventCalendar-slider { height:80px;} + + .eventCalendar-monthWrap { + border-radius:5px; + top:10px; + left:0px; + } + .eventCalendar-currentTitle { + line-height:25px; + background-color:#138DA5; + outline:1px solid #138DA5; + border:1px solid #E3E3E3; + border-width:1px 0; + } + .eventCalendar-currentTitle .eventCalendar-monthTitle { + font-size:110%; + text-decoration:none; + font-weight:bold; + color:#fff; + } + + .eventCalendar-daysList { + zoom: 1; + padding:0; + width:100%; + + } + .eventCalendar-daysList.eventCalendar-showAsWeek { + margin:10px 5px; + width:auto; + + border:solid 1px #BCBCBC; + border-bottom-width:0; + border-radius:0; + background-color:#CCCCCC; + background-image: linear-gradient(top, #EEEEEE 42%, #CCCCCC 71%); + background-image: -o-linear-gradient(top, #EEEEEE 42%, #CCCCCC 71%); + background-image: -moz-linear-gradient(top, #EEEEEE 42%, #CCCCCC 71%); + background-image: -webkit-linear-gradient(top, #EEEEEE 42%, #CCCCCC 71%); + background-image: -ms-linear-gradient(top, #EEEEEE 42%, #CCCCCC 71%); + + background-image: -webkit-gradient( + linear, + left top, + left bottom, + color-stop(0.42, #EEEEEE), + color-stop(0.71, #CCCCCC) + ); + + } + .eventCalendar-daysList.showDayNames.eventCalendar-showAsWeek { + + border-radius:5px 5px 0 0; + } + .eventCalendar-daysList:before, .eventCalendar-daysList:after { content:""; display:table; } + .eventCalendar-daysList:after { clear: both; } + .eventCalendar-day-header { + text-transform:lowercase; + text-align:center; + font-size:12px; + border-bottom:solid 1px #BCBCBC; + } + .eventCalendar-daysList.eventCalendar-showAsWeek li { + height:auto; margin:0; + } + .eventCalendar-daysList.eventCalendar-showAsWeek li.eventCalendar-empty { + background-color: #ccc; + min-height:27px; + border-top: solid 1px #ccc; + } + .eventCalendar-day a { + text-decoration:none; + font-size:10px; + color:#424242; + } + .eventCalendar-day { + border-left:solid 1px #BCBCBC; + } + .eventCalendar-day a { + border:solid 1px #BCBCBC; + border-width:0 1px 1px 0; + } + .eventCalendar-showAsWeek .eventCalendar-day { border-left-width:0;} + .eventCalendar-showAsWeek .eventCalendar-day a { + border:solid 1px red; + border-color:#fff #BCBCBC #BCBCBC #eee; + line-height:27px; + font-size:11px; + + } + .eventCalendar-day a:hover { + background-color:#E4E4E4; + /* box-shadow:inset 5px 5px 10px #C1C1C1; + text-shadow: 2px 2px 2px #C1C1C1;*/ + } + .eventCalendar-daysList li.today a { + color:#fff; + background:#aaa; + /* box-shadow:inset 5px 5px 10px #777; + text-shadow: 2px 2px 2px #777;*/ + } + li.eventCalendar-day.today a:hover { + background-color:#ccc; + /*box-shadow:inset 5px 5px 10px #999;*/ + } + + .eventCalendar-daysList li.eventCalendar-dayWithEvents a { + background:#89B814; + /*box-shadow:inset 5px 5px 10px #698B10; + text-shadow: 2px 2px 2px #698B10;*/ + color:#fff; + } + li.eventCalendar-day.eventCalendar-dayWithEvents a:hover { + background-color:#C2D374; + /*box-shadow:inset 5px 5px 10px #89B814; + text-shadow: 2px 2px 2px #89B814;*/ + } + + + .eventCalendar-daysList li.current a { + color:#fff; + background:#449FB2; + box-shadow:inset 5px 5px 10px #216B7A; + text-shadow: 2px 2px 2px #216B7A; + } + li.eventCalendar-day.current a:hover { + background-color:#79BDCC; + box-shadow:inset 5px 5px 10px #449FB2; + text-shadow: 2px 2px 2px #449FB2; + } + .eventCalendar-loading { + border-radius:4px; + margin:5px auto; + padding:0 10px; + background-color:#ccc; + color:#fff; + text-align:center; + font-weight:bold; + box-shadow:0 0 10px #ccc; + text-shadow:0 0 3px #aaa; + position:absolute; + z-index:4; + top:25px; + left:5px; + } + .eventCalendar-loading.error { + background-color:red; + } + +.eventCalendar-subtitle { padding-top:10px;} +.eventCalendar-list-wrap { + min-height:100px; + position:relative; +} + .eventCalendar-list-content.scrollable { + + height:100px; + overflow-y:auto; + margin:0 5px 5px 0; + } + .eventCalendar-list { + margin:0; padding:0; list-style-type:none; + } + .eventCalendar-list li { + padding:0 5px 15px; + margin:0; + clear:both; + } + .eventCalendar-list li time { + font-size:10px; + line-height:13px; + } + .eventCalendar-list li time em { + float:left; + font-style:normal; + } + .eventCalendar-list li time small { + font-size:10px; + float:left; + background-color:#807E7E; + color:#fff; + padding:0 5px 0 4px; + margin:0 0 0 3px; + } + .eventCalendar-list li .eventCalendar-eventTitle { + display:block; + clear:both; + + font-weight:bold; + text-decoration:none; + } + .eventCalendar-list li a.eventCalendar-eventTitle { + color:#0E8EAB; + outline: none; + } + .eventCalendar-list li a.eventCalendar-eventTitle:hover { text-decoration:underline;} + .eventCalendar-list li .eventDesc { + clear: both; + margin:0 0 5px 0; + font-size:80%; + line-height:1.2em; + + } + .eventCalendar-list .eventCalendar-noEvents { + font-size:120%; + border-radius:4px; + margin:5px; + padding:5px; + + background-color:#ccc; + color:#fff; + text-align:center; + font-weight:bold; + box-shadow:0 0 10px #ccc; + text-shadow:0 0 3px #aaa; + } + +.bt { + font-size:14px; + display:block; + clear:both; + text-align: center; + margin-top:10px; + padding: 9px 34px 11px; + text-decoration: none; + font-weight: bold; + line-height: 1; + outline: none; + + + color: #ffffff; + background-color: #138DA5; + background-repeat: repeat-x; + + background-image: -khtml-gradient(linear, left top, left bottom, from(#138DA5), to(#138DA5)); + background-image: -moz-linear-gradient(top, #138DA5, #138DA5); + background-image: -ms-linear-gradient(top, #138DA5, #138DA5); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #138DA5), color-stop(100%, #138DA5)); + background-image: -webkit-linear-gradient(top, #138DA5, #138DA5); + background-image: -o-linear-gradient(top, #138DA5, #138DA5); + background-image: linear-gradient(top, #138DA5, #138DA5); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#138DA5', endColorstr='#138DA5', GradientType=0); + + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + + border: 0px solid #138DA5; + border-color: #138DA5 #138DA5 #138DA5; + + border-radius: 0px; + + + + -webkit-transition: 0.1s linear all; + -moz-transition: 0.1s linear all; + -ms-transition: 0.1s linear all; + -o-transition: 0.1s linear all; + transition: 0.1s linear all; +} +.bt:hover { + background-position: 0 -15px; + text-decoration: none; + color: #ffffff; + } +.bt:visited { + color: #ffffff; + text-decoration: none !important; + } + +/* Правила, использующиеся в JS файле jquery.eventCalendar.js */ + +/*Изображение*/ + +.uca_img { + width:100%; + margin-top: 10px; + margin-bottom: 10px; + /*box-shadow:0 0 15px #999;*/ +} + +/*Заголовок*/ +.eventCalendar-eventTitle { + font-size: 18px; + font-weight: normal !important; + text-decoration: none !important; + +} + +/*Позиционирование divОв - оберток с иконками дата и время*/ +.uca-date-icon { + margin-top: 8px; + margin-bottom: 8px; +} +/*Дата и время после иконки*/ +.uca-date-txt { + margin-left:20px; + white-space: nowrap; + font: 10pt sans-serif; + color: #2A3C63; + font-weight: 400; +} + + +/*Иконки (спрайт)*/ + +.bg-blue_calendar { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -46px -10px; +} + +.bg-blue_caret_right { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -190px -10px; +} + +.bg-blue_check { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -10px -46px; +} + +.bg-blue_clock { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -46px -46px; +} + +.bg-blue_globe { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -82px -10px; +} + +.bg-blue_map { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -82px -46px; +} + +.bg-blue_menu { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -10px -82px; +} + +.bg-blue_phone { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -46px -82px; +} + +.bg-blue_podcast { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -82px -82px; +} + +.bg-dlue_bullhom { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -118px -10px; +} + +.bg-gray_bullhom { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -118px -46px; +} + +.bg-gray_calendar { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -118px -82px; +} + +.bg-gray_caret_right { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -10px -118px; +} + +.bg-gray_check { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -46px -118px; +} + +.bg-gray_clock { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -82px -118px; +} + +.bg-gray_globe { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -118px -118px; +} + +x +.bg-gray_map { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -154px -10px; +} + +.bg-gray_menu { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -154px -46px; +} + +.bg-gray_phone { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -154px -82px; +} + +.bg-gray_podcast { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -154px -118px; +} + +.bg-green_bullhom { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -10px -154px; +} + +.bg-green_calendar { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -46px -154px; +} + +.bg-green_caret_right { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -82px -154px; +} + +.bg-green_check { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -118px -154px; +} + +.bg-green_clock { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -154px -154px; +} + +.bg-green_globe { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -10px -10px; +} + +.bg-green_map { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -190px -46px; +} + +.bg-green_menu { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -190px -82px; +} + +.bg-green_phone { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -190px -118px; +} + +.bg-green_podcast { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -190px -154px; +} + +.bg-orange_bullhom { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -10px -190px; +} + +.bg-orange_calendar { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -46px -190px; +} + +.bg-orange_caret_right { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -82px -190px; +} + +.bg-orange_check { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -118px -190px; +} + +.bg-orange_clock { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -154px -190px; +} + +.bg-orange_globe { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -190px -190px; +} + +.bg-orange_map { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -226px -10px; +} + +.bg-orange_menu { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -226px -46px; +} + +.bg-orange_phone { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -226px -82px; +} + +.bg-orange_podcast { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -226px -118px; +} + +.bg-red_bullhom { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -226px -154px; +} + +.bg-red_calendar { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -226px -190px; +} + +.bg-red_caret_right { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -10px -226px; +} + +.bg-red_check { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -46px -226px; +} + +.bg-red_clock { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -82px -226px; +} + +.bg-red_globe { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -118px -226px; +} + +.bg-red_map { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -154px -226px; +} + +.bg-red_menu { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -190px -226px; +} + +.bg-red_phone { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -226px -226px; +} + +.bg-red_podcast { + width: 16px; height: 16px; + background: url('../images/css_sprites.png') -262px -10px; +} + +/* end of theme css */ \ No newline at end of file diff --git a/css/eventCalendar_theme_responsive_min.css b/css/eventCalendar_theme_responsive_min.css new file mode 100644 index 0000000..f93f0ed --- /dev/null +++ b/css/eventCalendar_theme_responsive_min.css @@ -0,0 +1 @@ +.eventCalendar-wrap{border:solid 1px #d3d3d3;box-shadow:0 0 15px #999;border-radius:5px;margin-bottom:20px;background-color:#fff;color:#807E7E;}.eventCalendar-wrap .eventCalendar-arrow{text-decoration:none;color:#fff;padding:0 5px;line-height:28px;top:9px;padding:8px 10px;}.eventCalendar-wrap .eventCalendar-arrow.prev{}.eventCalendar-wrap .eventCalendar-arrow:hover{opacity:0.7;}.eventCalendar-wrap .eventCalendar-arrow span{height:0;width:0;font-size:0;line-height:0;border-top:6px solid transparent;border-bottom:6px solid transparent;border-left:6px solid #fff;float:left;text-indent:-5000px;}.eventCalendar-wrap .eventCalendar-arrow.eventCalendar-prev span{border-left-width:0;border-right:6px solid #fff;}.eventCalendar-slider{height:80px;}.eventCalendar-monthWrap{border-radius:5px;top:10px;left:0px;}.eventCalendar-currentTitle{line-height:25px;background-color:#138DA5;outline:1px solid #138DA5;border:1px solid #E3E3E3;border-width:1px 0;}.eventCalendar-currentTitle .eventCalendar-monthTitle{font-size:110%;text-decoration:none;font-weight:bold;color:#fff;}.eventCalendar-daysList{zoom:1;padding:0;width:100%;}.eventCalendar-daysList.eventCalendar-showAsWeek{margin:10px 5px;width:auto;border:solid 1px #BCBCBC;border-bottom-width:0;border-radius:0;background-color:#CCCCCC;background-image:linear-gradient(top,#EEEEEE 42%,#CCCCCC 71%);background-image:-o-linear-gradient(top,#EEEEEE 42%,#CCCCCC 71%);background-image:-moz-linear-gradient(top,#EEEEEE 42%,#CCCCCC 71%);background-image:-webkit-linear-gradient(top,#EEEEEE 42%,#CCCCCC 71%);background-image:-ms-linear-gradient(top,#EEEEEE 42%,#CCCCCC 71%);background-image:-webkit-gradient( linear,left top,left bottom,color-stop(0.42,#EEEEEE),color-stop(0.71,#CCCCCC) );}.eventCalendar-daysList.showDayNames.eventCalendar-showAsWeek{border-radius:5px 5px 0 0;}.eventCalendar-daysList:before,.eventCalendar-daysList:after{content:"";display:table;}.eventCalendar-daysList:after{clear:both;}.eventCalendar-day-header{text-transform:lowercase;text-align:center;font-size:12px;border-bottom:solid 1px #BCBCBC;}.eventCalendar-daysList.eventCalendar-showAsWeek li{height:auto;margin:0;}.eventCalendar-daysList.eventCalendar-showAsWeek li.eventCalendar-empty{background-color:#ccc;min-height:27px;border-top:solid 1px #ccc;}.eventCalendar-day a{text-decoration:none;font-size:10px;color:#424242;}.eventCalendar-day{border-left:solid 1px #BCBCBC;}.eventCalendar-day a{border:solid 1px #BCBCBC;border-width:0 1px 1px 0;}.eventCalendar-showAsWeek .eventCalendar-day{border-left-width:0;}.eventCalendar-showAsWeek .eventCalendar-day a{border:solid 1px red;border-color:#fff #BCBCBC #BCBCBC #eee;line-height:27px;font-size:11px;}.eventCalendar-day a:hover{background-color:#E4E4E4;}.eventCalendar-daysList li.today a{color:#fff;background:#aaa;}li.eventCalendar-day.today a:hover{background-color:#ccc;}.eventCalendar-daysList li.eventCalendar-dayWithEvents a{background:#89B814;color:#fff;}li.eventCalendar-day.eventCalendar-dayWithEvents a:hover{background-color:#C2D374;}.eventCalendar-daysList li.current a{color:#fff;background:#449FB2;box-shadow:inset 5px 5px 10px #216B7A;text-shadow:2px 2px 2px #216B7A;}li.eventCalendar-day.current a:hover{background-color:#79BDCC;box-shadow:inset 5px 5px 10px #449FB2;text-shadow:2px 2px 2px #449FB2;}.eventCalendar-loading{border-radius:4px;margin:5px auto;padding:0 10px;background-color:#ccc;color:#fff;text-align:center;font-weight:bold;box-shadow:0 0 10px #ccc;text-shadow:0 0 3px #aaa;position:absolute;z-index:4;top:25px;left:5px;}.eventCalendar-loading.error{background-color:red;}.eventCalendar-subtitle{padding-top:10px;}.eventCalendar-list-wrap{min-height:100px;position:relative;}.eventCalendar-list-content.scrollable{height:100px;overflow-y:auto;margin:0 5px 5px 0;}.eventCalendar-list{margin:0;padding:0;list-style-type:none;}.eventCalendar-list li{padding:0 5px 15px;margin:0;clear:both;}.eventCalendar-list li time{font-size:10px;line-height:13px;}.eventCalendar-list li time em{float:left;font-style:normal;}.eventCalendar-list li time small{font-size:10px;float:left;background-color:#807E7E;color:#fff;padding:0 5px 0 4px;margin:0 0 0 3px;}.eventCalendar-list li .eventCalendar-eventTitle{display:block;clear:both;font-weight:bold;text-decoration:none;}.eventCalendar-list li a.eventCalendar-eventTitle{color:#0E8EAB;}.eventCalendar-list li a.eventCalendar-eventTitle:hover{text-decoration:underline;}.eventCalendar-list li .eventDesc{clear:both;margin:0 0 5px 0;font-size:80%;line-height:1.2em;}.eventCalendar-list .eventCalendar-noEvents{font-size:120%;border-radius:4px;margin:5px;padding:5px;background-color:#ccc;color:#fff;text-align:center;font-weight:bold;box-shadow:0 0 10px #ccc;text-shadow:0 0 3px #aaa;}.bt{font-size:12px;display:block;clear:both;text-align:center;margin-top:10px;padding:9px 34px 11px;text-decoration:none;font-weight:bold;line-height:1;color:#ffffff;background-color:#698B10;background-repeat:repeat-x;background-image:-khtml-gradient(linear,left top,left bottom,from(#89B814),to(#698B10));background-image:-moz-linear-gradient(top,#89B814,#698B10);background-image:-ms-linear-gradient(top,#89B814,#698B10);background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#89B814),color-stop(100%,#698B10));background-image:-webkit-linear-gradient(top,#89B814,#698B10);background-image:-o-linear-gradient(top,#89B814,#698B10);background-image:linear-gradient(top,#89B814,#698B10);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#89B814',endColorstr='#698B10',GradientType=0);text-shadow:0 -1px 0 rgba(0,0,0,0.25);border:1px solid #698B10;border-color:#698B10 #698B10 #465F05;border-radius:4px;box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-webkit-transition:0.1s linear all;-moz-transition:0.1s linear all;-ms-transition:0.1s linear all;-o-transition:0.1s linear all;transition:0.1s linear all;}.bt:hover{background-position:0 -15px;text-decoration:none;color:#E4E4E4;}.bt:visited{color:#E4E4E4;}body{}a{color:#0E8EAB}.features li{margin-bottom:3px;}#thanksPanel li{margin-bottom:0;}#introPanel{padding-top:20px;}.poweredBy img{float:left;margin-right:3px;}.poweredBy .data{float:left;}.poweredBy .name{font-weight:bold;color:#555;text-decoration:none;display:block;margin-top:28px;}.poweredBy .twitter{text-decoration:none;display:block;float:left;}.features{padding-left:20px;float:left;}#appLogo{margin-right:30px;}pre{clear:both;background-color:#FFFFCC;padding:5px;border:solid 1px #FED17E;overflow:auto;}#license{width:300px;float:right;font-size:10px;line-height:12px;text-align:center;}Paste your CSS here to minify \ No newline at end of file diff --git a/css/index.php b/css/index.php new file mode 100644 index 0000000..4ca25aa --- /dev/null +++ b/css/index.php @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/images/css_sprites.png b/images/css_sprites.png new file mode 100644 index 0000000000000000000000000000000000000000..545ad8904877256ea105c146c09d4f9159c700a3 GIT binary patch literal 22842 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ℜdkGR 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 literal 0 HcmV?d00001 diff --git a/images/index.php b/images/index.php new file mode 100644 index 0000000..4ca25aa --- /dev/null +++ b/images/index.php @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/images/question_alert.png b/images/question_alert.png new file mode 100644 index 0000000000000000000000000000000000000000..f2af96136f39564f941ed4b4acbafad3ab32ae0f GIT binary patch literal 1219 zcmaJ>TWB0r7@kezHc3soRcv|*^mG!mmF!&hGMgQClfBHw40J-+tY!tNnVmV=9h12@ zGjV4lgiVFIg<_(VA}RqNN_{9k)=D2@aWSS~u=GWOpe`c5l^}#ZsP#;mO?_}3X69V@ zzVHA4^M9O66XP#+cb(|MFsz#&zi#~<8Y!+|2l z@u{#t2}T;0l(7X9PA-h+q=i{2D&r%=Am*@0K!vsl9Cc2!SSOC}>au9=Zj(6Jh1j!k z{BcrwVFILe6M`@i^h*>?1BM~!P?%xpK@gzm07;>j@zWtT%&>t7*n4mk&6H=@EH}Cr z3$5aK$+iuaB+KP8Q4SKiStRLbH0o*u0)B+>TNTX~9lvJvHx)Q&Nv2}himm}yQ7q{5 zb{t2UJ}yBu_GL9|@0iemk&bAPG(ou~HGzWg|4>!kM_YClKFRk#g{@r0fMgb0`n)Nj z#?AD*p$s-{LebXEoUYF`PjRB8+qzZK4UnE>z?msUll8K7b{8)QEU#I%s7a9L;y6+u z6h&sKXduIJAu5nghiN(!8H$b$CBqa)rvjlsFr8|0IbE7pp=LL^@)IuIlIvPQHBe*@ zn#x;H9yN6p?3TOhTLu< zTYtuHDH!I7@LV$IY!zaK^=i-MrJaRyVcfVK{vHowX#r#03>Kw`rR(_#=jz1e(z2`aQ(=UFrHV~RG99U0! z&#j;SviIy}v2A;C@Qvr+dHPm|u=@LS|CRHe`t54oD=Z#4^T~9@bLHmCOFwk;$u{5X z2OAF9seka*Gj~3%T|Id{ai1Ng4%a5D4@YkP*kNv%;5|>_g%b9+w=wm7uJi8Z!Id!9 Zehlm2BJZv>mVa}v6+Sc0eV&@W@DJKpjnDu9 literal 0 HcmV?d00001 diff --git a/images/question_select.png b/images/question_select.png new file mode 100644 index 0000000000000000000000000000000000000000..09b59ae169a17743b3eea6e2d7121d7d5874b08d GIT binary patch literal 1208 zcmaJ>ZA=?w9KV7P2U5G3fh?6h-f+IH_ty4+3*9Kajx|_9+AcKl3)j1+^aA(7-LW1p zlWSvUo6QJIOg6r_81<7H*_WAUgg6$|#J~rm&JQMTi;16bAzApa1fOG+`N4X*yXPgp z-|zqbKmT8z>gdQ&Tg%ZF48z(IXZaKweeU;kGx{If-WAZ$X~nZvTFYBS!GKs)(sB?a z6k!6Updigoe-HaHtPz(pSu2}-gA+A{5L^slD>`ChSpR8T7sN?ufgGHW)d;@z)d~(| zDT0rMlT=cV!Ge5t&VcE;k&HMuDfUVD=~JNJ=8%8_EdkidlxlKz1mDx;(A?c7aj*xm zCL{Rcq_W9T5Yr3@!bC72QZx-%mY_pnmZeVuhN2mgLN6PjLtL2Um>#hI;3%3Q<+&7p zW&@;3(6_B`ErVtZMEb6FM-`7Icy(D7T~V^T%SL%79E#E5p1~TI*TfkGs#c9FJ>jx-xvmuy z9YyA$A)klR8ADURUdfzXKbK%#y?w4!KbKHlE{T#M-Nyc_(X}n)9(Q_RTeLVZK2(w0 z4P@(~7oR(ZVV;u-KAN$A%SqW=j`wn@x4oj2vfkGoK3{pS;Xw+VDt&tO@Q+RxAo8ov ze$p`Qy?pEK?q%;ge~JT-x~dC2#RquhD@-Ss=v?$Y?; za8oYb4i>BHD?`pstMAeu3manjB1^0`t@SuNA@A()f+v;j{-$BN)%Ut*IpQ0;OAS;G z`QN`f{?bpoTh}kl`6cmEFRfbs zEAxwYFP!jgt$&zjzH=^Z-miMu!M~0SeBD}soA*0P-&UJ`@O-SC1LtF@1#In?Qg2r! zvfTXzKXpxR34M02aog!_s_cqE$FuZMbbdW_)LAL*90{E(-`Ms@w=qvM=4`MZ{rnc) P?cODc_z3^`;CT5Tp(Buj literal 0 HcmV?d00001 diff --git a/images/question_start_one.png b/images/question_start_one.png new file mode 100644 index 0000000000000000000000000000000000000000..3b1008b86ebbc1ab17d7600eda9559ea5aabde85 GIT binary patch literal 1222 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+n3Xa^B1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxSU1_g&``n5OwZ87 z)XdCKN5ROz&`93^h|F{iO{`4Ktc=VRpg;*|TTx1yRgjAt)Gi>;Rw<*Tq`*pFzr4I$ zuiRKKzbIYb(9+TpWQLKEE>MMTab;dfVufyAu`f(~1RD^r68eAMwS&*t9 zlvv ztM~P_^2{qPNz6-5^>ndS0-B(gnVDi`Y2aky>Sk11T=YzY)Fb8&OD zuyljzb;(aI%}vcKf$2>_=rzZw7nBro3xGDeq!wkCrKY$Q<>xAZy=;|<+bt$I&4cPq z!R;1PoO<Mz)#~_tvqnRy^m)2{1x_u>IMWoq2lE)~r$4rH-S%}TcM~UtKsg$H} zw&weXQXW*7)Rpc&XZiKz*Lyp^@A>}D)||WBU9pp|XOZ~XUvEUW-#F}SvqNjs{bkD!bantd{1B0iHT=2R({@KSjlFqp?3cF##qe@&-Pfl{J)*~WZ4DP zYy;UpI}WP9n)|0_-Riflrg0x$JlVa}Ve!Nthq$5w4onJO5XP0__9)>0f9LnyevLj{ zdn7xB&Mk`7vSK~8^Ifr&sm0a5`4`@8c@)Q$V|DU$#`*09sXdXCnf!0f%bfG#E5q{) zuTQ%-`Ayxdu=j3PW5xlCd4_F@iw~+@I&9KW`nI$)_4)NOgHHL^Ca0#qNoJ|t)o{P! j`noBPYh?X@h$b*3A2lyX*tl#NsATbU^>bP0l+XkK2;sJx literal 0 HcmV?d00001 diff --git a/index.php b/index.php new file mode 100644 index 0000000..4ca25aa --- /dev/null +++ b/index.php @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/info.php b/info.php new file mode 100644 index 0000000..d6ca988 --- /dev/null +++ b/info.php @@ -0,0 +1,20 @@ + 'unicalendar', + 'ModuleVersion' => '1.26.8', + 'ModuleAutor' => 'Repellent', + 'ModuleCopyright' => '© 2007-' . date('Y') . ' AVE.cms', + 'ModuleStatus' => 1, + 'ModuleIsFunction' => 1, + 'ModuleTemplate' => 0, + 'ModuleAdminEdit' => 1, + 'ModuleFunction' => 'mod_unicalendar', + 'ModuleTag' => '[mod_unicalendar:XXX]', + 'ModuleTagLink' => null, + 'ModuleAveTag' => '#\\\[mod_unicalendar:([\\\d-]+)]#', + 'ModulePHPTag' => "" + ); +?> \ No newline at end of file diff --git a/js/data-files/index.php b/js/data-files/index.php new file mode 100644 index 0000000..4ca25aa --- /dev/null +++ b/js/data-files/index.php @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/js/index.php b/js/index.php new file mode 100644 index 0000000..4ca25aa --- /dev/null +++ b/js/index.php @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/js/jquery.eventCalendar.js b/js/jquery.eventCalendar.js new file mode 100644 index 0000000..e0a5058 --- /dev/null +++ b/js/jquery.eventCalendar.js @@ -0,0 +1,516 @@ +/* = + jquery.eventCalendar.js + version: 0.7 + date: 13-08-2015 + author: + Jaime Fernandez (@vissit) + company: + Paradigma Tecnologico (@paradigmate) + url: + http://www.vissit.com/projects/eventCalendar/ +*/ +;(function( $ ) { + $.fn.eventCalendar = function(options){ + var calendar = this; + + if ( options.locales && typeof(options.locales) == 'string' ) { + $.getJSON(options.locales, function(data) { + options.locales = $.extend({}, $.fn.eventCalendar.defaults.locales, data); + moment.locale(data.locale, options.locales.moment); + moment.locale(data.locale); + + initEventCalendar(calendar, options); + }).error(function() { + showError("error getting locale json", $(this)); + }); + } else { + if ( options.locales && options.locales.locale ) { + options.locales = $.extend({}, $.fn.eventCalendar.defaults.locales, options.locales); + moment.locale(options.locales.locale, options.locales.moment); + moment.locale(options.locales.locale); + } + initEventCalendar(calendar, options); + } + + + }; + + + // define the parameters with the default values of the function + $.fn.eventCalendar.defaults = { + eventsjson: 'js/events.json', + eventsLimit: 4, + locales: { + locale: "en", + txt_noEvents: "There are no events in this period", + txt_SpecificEvents_prev: "", + txt_SpecificEvents_after: "events:", + txt_next: "next", + txt_prev: "prev", + txt_NextEvents: "Next events:", + txt_GoToEventUrl: "See the event", + txt_loading: "loading..." + }, + showDayAsWeeks: true, + startWeekOnMonday: true, + showDayNameInCalendar: true, + showDescription: false, + onlyOneDescription: true, + openEventInNewWindow: false, + eventsScrollable: false, + dateFormat: "D/MM/YYYY", + jsonDateFormat: 'timestamp', // you can use also "human" 'YYYY-MM-DD HH:MM:SS' + moveSpeed: 500, // speed of month move when you clic on a new date + moveOpacity: 0.15, // month and events fadeOut to this opacity + jsonData: "", // to load and inline json (not ajax calls) + cacheJson: true // if true plugin get a json only first time and after plugin filter events + // if false plugin get a new json on each date change + }; + + function initEventCalendar(that, options) { + var eventsOpts = $.extend({}, $.fn.eventCalendar.defaults, options); + + // define global vars for the function + var flags = { + wrap: "", + directionLeftMove: "300", + eventsJson: {} + }; + + // each eventCalendar will execute this function + that.each(function(){ + + flags.wrap = $(this); + flags.wrap.addClass('eventCalendar-wrap').append("

    "+eventsOpts.locales.txt_loading+"
      "); + + if (eventsOpts.eventsScrollable) { + flags.wrap.find('.eventCalendar-list-content').addClass('scrollable'); + } + + setCalendarWidth(flags); + $(window).resize(function(){ + setCalendarWidth(flags); + }); + //flags.directionLeftMove = flags.wrap.width(); + + // show current month + dateSlider("current", flags, eventsOpts); + + getEvents(flags, eventsOpts, eventsOpts.eventsLimit,false,false,false,false); + + changeMonth(flags, eventsOpts); + + flags.wrap.on('click','.eventCalendar-day a',function(e){ + //flags.wrap.find('.eventCalendar-day a').live('click',function(e){ + e.preventDefault(); + var year = flags.wrap.attr('data-current-year'), + month = flags.wrap.attr('data-current-month'), + day = $(this).parent().attr('rel'); + + getEvents(flags, eventsOpts, false, year, month,day, "day"); + }); + flags.wrap.on('click','.eventCalendar-monthTitle', function(e){ + //flags.wrap.find('.eventCalendar-monthTitle').live('click',function(e){ + e.preventDefault(); + var year = flags.wrap.attr('data-current-year'), + month = flags.wrap.attr('data-current-month'); + + getEvents(flags, eventsOpts, eventsOpts.eventsLimit, year, month,false, "month"); + }); + }); + + // show event description + flags.wrap.find('.eventCalendar-list').on('click','.eventCalendar-eventTitle',function(e){ + //flags.wrap.find('.eventCalendar-list .eventCalendar-eventTitle').live('click',function(e){ + if(!eventsOpts.showDescription) { + e.preventDefault(); + var desc = $(this).parent().find('.eventCalendar-eventDesc'); + + if (!desc.find('a').length) { + var eventUrl = $(this).attr('href'); + var eventTarget = $(this).attr('target'); + + // create a button to go to event url + if(eventUrl){ + desc.append(''+eventsOpts.locales.txt_GoToEventUrl+''); + } + + } + + if ( desc.is(':visible') ) { + desc.slideUp(); + } else { + if(eventsOpts.onlyOneDescription) { + flags.wrap.find('.eventCalendar-eventDesc').slideUp(); + } + desc.slideDown(); + } + + } + }); + } + + function sortJson(a, b){ + if ( typeof a.date === 'string' ) { + return a.date.toLowerCase() > b.date.toLowerCase() ? 1 : -1; + } + return a.date > b.date ? 1 : -1; + } + + function dateSlider(show, flags, eventsOpts) { + var $eventsCalendarSlider = $("
      "), + $eventsCalendarMonthWrap = $("
      "), + $eventsCalendarTitle = $("
      "), + $eventsCalendarArrows = $("" + eventsOpts.locales.txt_prev + "" + eventsOpts.locales.txt_next + ""); + $eventsCalendarDaysList = $("
        "), + date = new Date(); + + if ( !flags.wrap.find('.eventCalendar-slider').length ) { + flags.wrap.prepend($eventsCalendarSlider); + $eventsCalendarSlider.append($eventsCalendarMonthWrap); + } else { + flags.wrap.find('.eventCalendar-slider').append($eventsCalendarMonthWrap); + } + + flags.wrap.find('.eventCalendar-monthWrap.eventCalendar-currentMonth').removeClass('eventCalendar-currentMonth').addClass('eventCalendar-oldMonth'); + $eventsCalendarMonthWrap.addClass('eventCalendar-currentMonth').append($eventsCalendarTitle, $eventsCalendarDaysList); + + + + // if current show current month & day + if (show === "current") { + day = date.getDate(); + $eventsCalendarSlider.append($eventsCalendarArrows); + + } else { + date = new Date(flags.wrap.attr('data-current-year'),flags.wrap.attr('data-current-month'),1,0,0,0); // current visible month + day = 0; // not show current day in days list + + moveOfMonth = 1; + if (show === "prev") { + moveOfMonth = -1; + } + date.setMonth( date.getMonth() + moveOfMonth ); + + var tmpDate = new Date(); + if (date.getMonth() === tmpDate.getMonth()) { + day = tmpDate.getDate(); + } + + } + + // get date portions + var year = date.getFullYear(), // year of the events + currentYear = new Date().getFullYear(), // current year + month = date.getMonth(), // 0-11 + monthToShow = month + 1; + + if (show != "current") { + // month change + getEvents(flags, eventsOpts, eventsOpts.eventsLimit, year, month,false, show); + } + + flags.wrap.attr('data-current-month',month) + .attr('data-current-year',year); + + // add current date info + moment.locale(eventsOpts.locales.locale); + + var formatedDate = moment(year+" "+monthToShow, "YYYY MM").format("MMMM YYYY"); + $eventsCalendarTitle.find('.eventCalendar-monthTitle').html(formatedDate); + + // print all month days + var daysOnTheMonth = 32 - new Date(year, month, 32).getDate(); + var daysList = [], + i; + if (eventsOpts.showDayAsWeeks) { + $eventsCalendarDaysList.addClass('eventCalendar-showAsWeek'); + + // show day name in top of calendar + if (eventsOpts.showDayNameInCalendar) { + $eventsCalendarDaysList.addClass('eventCalendar-showDayNames'); + + i = 0; + // if week start on monday + if (eventsOpts.startWeekOnMonday) { + i = 1; + } + + for (; i < 7; i++) { + daysList.push('
      • '+moment()._locale._weekdaysShort[i]+'
      • '); + + if (i === 6 && eventsOpts.startWeekOnMonday) { + // print sunday header + daysList.push('
      • '+moment()._locale._weekdaysShort[0]+'
      • '); + } + + } + } + + dt=new Date(year, month, 01); + var weekDay = dt.getDay(); // day of the week where month starts + + if (eventsOpts.startWeekOnMonday) { + weekDay = dt.getDay() - 1; + } + if (weekDay < 0) { weekDay = 6; } // if -1 is because day starts on sunday(0) and week starts on monday + + for (i = weekDay; i > 0; i--) { + daysList.push('
      • '); + } + } + for (dayCount = 1; dayCount <= daysOnTheMonth; dayCount++) { + var dayClass = ""; + + if (day > 0 && dayCount === day && year === currentYear) { + dayClass = "today"; + } + daysList.push('
      • ' + dayCount + '
      • '); + } + $eventsCalendarDaysList.append(daysList.join('')); + + $eventsCalendarSlider.css('height',$eventsCalendarMonthWrap.height()+'px'); + } + + function getEvents(flags, eventsOpts, limit, year, month, day, direction) { + limit = limit || 0; + year = year || ''; + day = day || ''; + + // to avoid problem with january (month = 0) + + if (typeof month != 'undefined') { + month = month; + } else { + month = ''; + } + + //var month = month || ''; + flags.wrap.find('.eventCalendar-loading').fadeIn(); + + if (eventsOpts.jsonData) { + // user send a json in the plugin params + eventsOpts.cacheJson = true; + + flags.eventsJson = eventsOpts.jsonData; + getEventsData(flags, eventsOpts, flags.eventsJson, limit, year, month, day, direction); + + } else if (!eventsOpts.cacheJson || !direction) { + // first load: load json and save it to future filters + $.getJSON(eventsOpts.eventsjson + "?limit="+limit+"&year="+year+"&month="+month+"&day="+day, function(data) { + flags.eventsJson = data; // save data to future filters + getEventsData(flags, eventsOpts, flags.eventsJson, limit, year, month, day, direction); + }).error(function() { + showError("error getting json: ", flags.wrap); + }); + } else { + // filter previus saved json + getEventsData(flags, eventsOpts, flags.eventsJson, limit, year, month, day, direction); + } + + if (day > '') { + flags.wrap.find('.eventCalendar-current').removeClass('eventCalendar-current'); + flags.wrap.find('#dayList_'+day).addClass('eventCalendar-current'); + } + } + + function getEventsData(flags, eventsOpts, data, limit, year, month, day, direction){ + directionLeftMove = "-=" + flags.directionLeftMove; + eventContentHeight = "auto"; + + subtitle = flags.wrap.find('.eventCalendar-list-wrap .eventCalendar-subtitle'); + + if ( !direction ) { + // first load + subtitle.html(eventsOpts.locales.txt_NextEvents); + eventContentHeight = "auto"; + directionLeftMove = "-=0"; + } else { + var jsMonth = parseInt(month) + 1, + formatedDate; + moment.locale(eventsOpts.locales.locale); + + if (day !== '') { + formatedDate = moment(year+" "+jsMonth+" "+day, "YYYY MM DD").format("LL"); + subtitle.html(eventsOpts.locales.txt_SpecificEvents_prev + formatedDate + " " + eventsOpts.locales.txt_SpecificEvents_after); + //eventStringDate = moment(eventDate).format(eventsOpts.dateFormat); + } else { + formatedDate = moment(year+" "+jsMonth, "YYYY MM").format("MMMM"); + subtitle.html(eventsOpts.locales.txt_SpecificEvents_prev + formatedDate + " " + eventsOpts.locales.txt_SpecificEvents_after); + } + + if (direction === 'eventCalendar-prev') { + directionLeftMove = "+=" + flags.directionLeftMove; + } else if (direction === 'day' || direction === 'month') { + directionLeftMove = "+=0"; + eventContentHeight = 0; + } + } + + flags.wrap.find('.eventCalendar-list').animate({ + opacity: eventsOpts.moveOpacity, + left: directionLeftMove, + height: eventContentHeight + }, eventsOpts.moveSpeed, function() { + flags.wrap.find('.eventCalendar-list').css({'left':0, 'height': 'auto'}).hide(); + //wrap.find('.eventCalendar-list li').fadeIn(); + + var events = []; + + data = $(data).sort(sortJson); // sort event by dates + // each event + if ( data.length ) { + + // show or hide event description + var eventDescClass = ''; + if(!eventsOpts.showDescription) { + eventDescClass = 'eventCalendar-hidden'; + } + var eventLinkTarget = "_self"; + if(eventsOpts.openEventInNewWindow) { + eventLinkTarget = '_target'; + } + + var i = 0; + $.each(data, function(key, event) { + var eventDateTime, eventDate, eventTime, eventYear, eventMonth, eventDay, + eventMonthToShow, eventHour, eventMinute, eventSeconds; + if (eventsOpts.jsonDateFormat == 'human') { + eventDateTime = event.date.split(" "); + eventDate = eventDateTime[0].split("-"); + eventTime = eventDateTime[1].split(":"); + eventYear = eventDate[0]; + eventMonth = parseInt(eventDate[1]) - 1; + eventDay = parseInt(eventDate[2]); + //eventMonthToShow = eventMonth; + eventMonthToShow = parseInt(eventMonth) + 1; + eventHour = eventTime[0]; + eventMinute = eventTime[1]; + eventSeconds = eventTime[2]; + eventDate = new Date(eventYear, eventMonth, eventDay, eventHour, eventMinute, eventSeconds); + } else { + eventDate = new Date(parseInt(event.date)); + eventYear = eventDate.getFullYear(); + eventMonth = eventDate.getMonth(); + eventDay = eventDate.getDate(); + eventMonthToShow = eventMonth + 1; + eventHour = eventDate.getHours(); + eventMinute = eventDate.getMinutes(); + + } + + if (parseInt(eventMinute) <= 9) { + eventMinute = "0" + parseInt(eventMinute); + } + // Проверка на пустоту значений Тизера события (изображение, описание, место) + + if(event.image != '')// Start проверяем на пустоту значение переменной Изображение + { + var eventImage = ''; + } else { + var eventImage = ''; + }// End проверяем на пустоту значение переменной Изображение + + if(event.description != '')// Start проверяем на пустоту значение переменной Описание + { + var eventDescription = event.description; + } else { + var eventDescription = ''; + }// End проверяем на пустоту значение переменной Описание + + if(event.location != '')// Start проверяем на пустоту значение переменной Место + { + var eventLocation = '
        ' + event.location + '
        '; + } else { + var eventLocation = ''; + }// End проверяем на пустоту значение переменной Место + + if (limit === 0 || limit > i) { + // if month or day exist then only show matched events + + if ((month === false || month == eventMonth) && (day === '' || day == eventDay) && (year === '' || year == eventYear) ) { + // if initial load then load only future events + if (month === false && eventDate < new Date()) { + } else { + moment.locale(eventsOpts.locales.locale); + //eventStringDate = eventDay + "/" + eventMonthToShow + "/" + eventYear; + eventStringDate = moment(eventDate).format(eventsOpts.dateFormat); + var eventTitle; + + if (event.url) { + eventTitle = '' + event.title + ''; + } else { + eventTitle = ''+event.title+''; + } + events.push('
      • '+ eventImage + eventTitle +'
        ' + '
        ' + eventStringDate + '
        '+eventHour+':'+eventMinute+'
        '+eventLocation + eventDescription + '
      • '); + i++; + } + } + } + + // add mark in the dayList to the days with events + if (eventYear == flags.wrap.attr('data-current-year') && eventMonth == flags.wrap.attr('data-current-month')) { + flags.wrap.find('.eventCalendar-currentMonth .eventCalendar-daysList #dayList_' + parseInt(eventDay)).addClass('eventCalendar-dayWithEvents'); + } + + }); + } + + // there is no events on this period + if (!events.length) { + events.push('
      • ' + eventsOpts.locales.txt_noEvents + '

      • '); + } + flags.wrap.find('.eventCalendar-loading').hide(); + + flags.wrap.find('.eventCalendar-list') + .html(events.join('')); + + flags.wrap.find('.eventCalendar-list').animate({ + opacity: 1, + height: "toggle" + }, eventsOpts.moveSpeed); + + + }); + setCalendarWidth(flags); + } + + function changeMonth(flags, eventsOpts) { + flags.wrap.find('.eventCalendar-arrow').click(function(e){ + e.preventDefault(); + var lastMonthMove; + + if ($(this).hasClass('eventCalendar-next')) { + dateSlider("next", flags, eventsOpts); + lastMonthMove = '-=' + flags.directionLeftMove; + + } else { + dateSlider("prev", flags, eventsOpts); + lastMonthMove = '+=' + flags.directionLeftMove; + } + + flags.wrap.find('.eventCalendar-monthWrap.eventCalendar-oldMonth').animate({ + opacity: eventsOpts.moveOpacity, + left: lastMonthMove + }, eventsOpts.moveSpeed, function() { + flags.wrap.find('.eventCalendar-monthWrap.eventCalendar-oldMonth').remove(); + }); + }); + } + + function showError(msg, wrap) { + wrap.find('.eventCalendar-list-wrap').html(""+msg+""); + } + + function setCalendarWidth(flags){ + // resize calendar width on window resize + flags.directionLeftMove = flags.wrap.width(); + flags.wrap.find('.eventCalendar-monthWrap').width(flags.wrap.width() + 'px'); + + flags.wrap.find('.eventCalendar-list-wrap').width(flags.wrap.width() + 'px'); + + } + + +})( jQuery ); + diff --git a/js/jquery.eventCalendar.min.js b/js/jquery.eventCalendar.min.js new file mode 100644 index 0000000..44d1d86 --- /dev/null +++ b/js/jquery.eventCalendar.min.js @@ -0,0 +1,13 @@ +/* = + jquery.eventCalendar.js + version: 0.68 + date: 17-07-2015 + author: + Jaime Fernandez (@vissit) + company: + Paradigma Tecnologico (@paradigmate) + url: + http://www.vissit.com/projects/eventCalendar/ +*/ + +;!function(e){function t(t,a){var l=e.extend({},e.fn.eventCalendar.defaults,a),o={wrap:"",directionLeftMove:"300",eventsJson:{}};t.each(function(){o.wrap=e(this),o.wrap.addClass("eventCalendar-wrap").append("

        "+l.locales.txt_loading+"
          "),l.eventsScrollable&&o.wrap.find(".eventCalendar-list-content").addClass("scrollable"),d(o),e(window).resize(function(){d(o)}),n("current",o,l),r(o,l,l.eventsLimit,!1,!1,!1,!1),s(o,l),o.wrap.on("click",".eventCalendar-day a",function(t){t.preventDefault();var a=o.wrap.attr("data-current-year"),n=o.wrap.attr("data-current-month"),s=e(this).parent().attr("rel");r(o,l,!1,a,n,s,"day")}),o.wrap.on("click",".eventCalendar-monthTitle",function(e){e.preventDefault();var t=o.wrap.attr("data-current-year"),a=o.wrap.attr("data-current-month");r(o,l,l.eventsLimit,t,a,!1,"month")})}),o.wrap.find(".eventCalendar-list").on("click",".eventCalendar-eventTitle",function(t){if(!l.showDescription){t.preventDefault();var a=e(this).parent().find(".eventCalendar-eventDesc");if(!a.find("a").size()){var n=e(this).attr("href"),r=e(this).attr("target");a.append(''+l.locales.txt_GoToEventUrl+"")}a.is(":visible")?a.slideUp():(l.onlyOneDescription&&o.wrap.find(".eventCalendar-eventDesc").slideUp(),a.slideDown())}})}function a(e,t){return"string"==typeof e.date?e.date.toLowerCase()>t.date.toLowerCase()?1:-1:e.date>t.date?1:-1}function n(t,a,n){var l=e("
          "),s=e("
          "),o=e("
          "),d=e(""+n.locales.txt_prev+""+n.locales.txt_next+"");if($eventsCalendarDaysList=e("
            "),date=new Date,a.wrap.find(".eventCalendar-slider").length?a.wrap.find(".eventCalendar-slider").append(s):(a.wrap.prepend(l),l.append(s)),a.wrap.find(".eventCalendar-monthWrap.eventCalendar-currentMonth").removeClass("eventCalendar-currentMonth").addClass("eventCalendar-oldMonth"),s.addClass("eventCalendar-currentMonth").append(o,$eventsCalendarDaysList),"current"===t)day=date.getDate(),l.append(d);else{date=new Date(a.wrap.attr("data-current-year"),a.wrap.attr("data-current-month"),1,0,0,0),day=0,moveOfMonth=1,"prev"===t&&(moveOfMonth=-1),date.setMonth(date.getMonth()+moveOfMonth);var i=new Date;date.getMonth()===i.getMonth()&&(day=i.getDate())}var v=date.getFullYear(),c=(new Date).getFullYear(),p=date.getMonth(),f=p+1;"current"!=t&&r(a,n,n.eventsLimit,v,p,!1,t),a.wrap.attr("data-current-month",p).attr("data-current-year",v),moment.locale(n.locales.locale);var h=moment(v+" "+f,"YYYY MM").format("MMMM YYYY");o.find(".eventCalendar-monthTitle").html(h);var C,m=32-new Date(v,p,32).getDate(),u=[];if(n.showDayAsWeeks){if($eventsCalendarDaysList.addClass("eventCalendar-showAsWeek"),n.showDayNameInCalendar)for($eventsCalendarDaysList.addClass("eventCalendar-showDayNames"),C=0,n.startWeekOnMonday&&(C=1);7>C;C++)u.push('
          • '+moment()._locale._weekdaysShort[C]+"
          • "),6===C&&n.startWeekOnMonday&&u.push('
          • '+moment()._locale._weekdaysShort[0]+"
          • ");dt=new Date(v,p,1);var w=dt.getDay();for(n.startWeekOnMonday&&(w=dt.getDay()-1),0>w&&(w=6),C=w;C>0;C--)u.push('
          • ')}for(dayCount=1;m>=dayCount;dayCount++){var y="";day>0&&dayCount===day&&v===c&&(y="today"),u.push('
          • '+dayCount+"
          • ")}$eventsCalendarDaysList.append(u.join("")),l.css("height",s.height()+"px")}function r(t,a,n,r,s,d,i){n=n||0,r=r||"",d=d||"",s="undefined"!=typeof s?s:"",t.wrap.find(".eventCalendar-loading").fadeIn(),a.jsonData?(a.cacheJson=!0,t.eventsJson=a.jsonData,l(t,a,t.eventsJson,n,r,s,d,i)):a.cacheJson&&i?l(t,a,t.eventsJson,n,r,s,d,i):e.getJSON(a.eventsjson+"?limit="+n+"&year="+r+"&month="+s+"&day="+d,function(e){t.eventsJson=e,l(t,a,t.eventsJson,n,r,s,d,i)}).error(function(){o("error getting json: ",t.wrap)}),d>""&&(t.wrap.find(".eventCalendar-current").removeClass("eventCalendar-current"),t.wrap.find("#dayList_"+d).addClass("eventCalendar-current"))}function l(t,n,r,l,s,o,i,v){if(directionLeftMove="-="+t.directionLeftMove,eventContentHeight="auto",subtitle=t.wrap.find(".eventCalendar-list-wrap .eventCalendar-subtitle"),v){var c,p=parseInt(o)+1;moment.locale(n.locales.locale),""!==i?(c=moment(s+" "+p+" "+i,"YYYY MM DD").format("LL"),subtitle.html(n.locales.txt_SpecificEvents_prev+c+" "+n.locales.txt_SpecificEvents_after)):(c=moment(s+" "+p,"YYYY MM").format("MMMM"),subtitle.html(n.locales.txt_SpecificEvents_prev+c+" "+n.locales.txt_SpecificEvents_after)),"eventCalendar-prev"===v?directionLeftMove="+="+t.directionLeftMove:("day"===v||"month"===v)&&(directionLeftMove="+=0",eventContentHeight=0)}else subtitle.html(n.locales.txt_NextEvents),eventContentHeight="auto",directionLeftMove="-=0";t.wrap.find(".eventCalendar-list").animate({opacity:n.moveOpacity,left:directionLeftMove,height:eventContentHeight},n.moveSpeed,function(){t.wrap.find(".eventCalendar-list").css({left:0,height:"auto"}).hide();var d=[];if(r=e(r).sort(a),r.length){var v="";n.showDescription||(v="eventCalendar-hidden");var c="_self";n.openEventInNewWindow&&(c="_target");var p=0;e.each(r,function(e,a){var r,f,h,C,m,u,w,y,g,D;if("human"==n.jsonDateFormat?(r=a.date.split(" "),f=r[0].split("-"),h=r[1].split(":"),C=f[0],m=parseInt(f[1])-1,u=parseInt(f[2]),w=parseInt(m)+1,y=h[0],g=h[1],D=h[2],f=new Date(C,m,u,y,g,D)):(f=new Date(parseInt(a.date)),C=f.getFullYear(),m=f.getMonth(),u=f.getDate(),w=m+1,y=f.getHours(),g=f.getMinutes()),parseInt(g)<=9&&(g="0"+parseInt(g)),(0===l||l>p)&&!(o!==!1&&o!=m||""!==i&&i!=u||""!==s&&s!=C))if(o===!1&&f'+a.title+"":''+a.title+"",d.push('
          • "+M+'

            '+a.description+"

          • "),p++}C==t.wrap.attr("data-current-year")&&m==t.wrap.attr("data-current-month")&&t.wrap.find(".eventCalendar-currentMonth .eventCalendar-daysList #dayList_"+parseInt(u)).addClass("eventCalendar-dayWithEvents")})}d.length||d.push('
          • '+n.locales.txt_noEvents+"

          • "),t.wrap.find(".eventCalendar-loading").hide(),t.wrap.find(".eventCalendar-list").html(d.join("")),t.wrap.find(".eventCalendar-list").animate({opacity:1,height:"toggle"},n.moveSpeed)}),d(t)}function s(t,a){t.wrap.find(".eventCalendar-arrow").click(function(r){r.preventDefault();var l;e(this).hasClass("eventCalendar-next")?(n("next",t,a),l="-="+t.directionLeftMove):(n("prev",t,a),l="+="+t.directionLeftMove),t.wrap.find(".eventCalendar-monthWrap.eventCalendar-oldMonth").animate({opacity:a.moveOpacity,left:l},a.moveSpeed,function(){t.wrap.find(".eventCalendar-monthWrap.eventCalendar-oldMonth").remove()})})}function o(e,t){t.find(".eventCalendar-list-wrap").html(""+e+"")}function d(e){e.directionLeftMove=e.wrap.width(),e.wrap.find(".eventCalendar-monthWrap").width(e.wrap.width()+"px"),e.wrap.find(".eventCalendar-list-wrap").width(e.wrap.width()+"px")}e.fn.eventCalendar=function(a){var n=this;a.locales&&"string"==typeof a.locales?e.getJSON(a.locales,function(r){a.locales=e.extend({},e.fn.eventCalendar.defaults.locales,r),moment.locale(r.locale,a.locales.moment),moment.locale(r.locale),t(n,a)}).error(function(){o("error getting locale json",e(this))}):(a.locales&&a.locales.locale&&(a.locales=e.extend({},e.fn.eventCalendar.defaults.locales,a.locales),moment.locale(a.locales.locale,a.locales.moment),moment.locale(a.locales.locale)),t(n,a))},e.fn.eventCalendar.defaults={eventsjson:"js/events.json",eventsLimit:4,locales:{locale:"en",txt_noEvents:"There are no events in this period",txt_SpecificEvents_prev:"",txt_SpecificEvents_after:"events:",txt_next:"next",txt_prev:"prev",txt_NextEvents:"Next events:",txt_GoToEventUrl:"See the event",txt_loading:"loading..."},showDayAsWeeks:!0,startWeekOnMonday:!0,showDayNameInCalendar:!0,showDescription:!1,onlyOneDescription:!0,openEventInNewWindow:!1,eventsScrollable:!1,dateFormat:"D/MM/YYYY",jsonDateFormat:"timestamp",moveSpeed:500,moveOpacity:.15,jsonData:"",cacheJson:!0}}(jQuery); \ No newline at end of file diff --git a/js/moment.js b/js/moment.js new file mode 100644 index 0000000..96922ff --- /dev/null +++ b/js/moment.js @@ -0,0 +1,2856 @@ +//! moment.js +//! version : 2.8.3 +//! authors : Tim Wood, Iskren Chernev, Moment.js contributors +//! license : MIT +//! momentjs.com + +(function (undefined) { + /************************************ + Constants + ************************************/ + + var moment, + VERSION = '2.8.3', + // the global-scope this is NOT the global object in Node.js + globalScope = typeof global !== 'undefined' ? global : this, + oldGlobalMoment, + round = Math.round, + hasOwnProperty = Object.prototype.hasOwnProperty, + i, + + YEAR = 0, + MONTH = 1, + DATE = 2, + HOUR = 3, + MINUTE = 4, + SECOND = 5, + MILLISECOND = 6, + + // internal storage for locale config files + locales = {}, + + // extra moment internal properties (plugins register props here) + momentProperties = [], + + // check for nodeJS + hasModule = (typeof module !== 'undefined' && module.exports), + + // ASP.NET json date format regex + aspNetJsonRegex = /^\/?Date\((\-?\d+)/i, + aspNetTimeSpanJsonRegex = /(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/, + + // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html + // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere + isoDurationRegex = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/, + + // format tokens + formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Q|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|X|zz?|ZZ?|.)/g, + localFormattingTokens = /(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g, + + // parsing token regexes + parseTokenOneOrTwoDigits = /\d\d?/, // 0 - 99 + parseTokenOneToThreeDigits = /\d{1,3}/, // 0 - 999 + parseTokenOneToFourDigits = /\d{1,4}/, // 0 - 9999 + parseTokenOneToSixDigits = /[+\-]?\d{1,6}/, // -999,999 - 999,999 + parseTokenDigits = /\d+/, // nonzero number of digits + parseTokenWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i, // any word (or two) characters or numbers including two/three word month in arabic. + parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/gi, // +00:00 -00:00 +0000 -0000 or Z + parseTokenT = /T/i, // T (ISO separator) + parseTokenTimestampMs = /[\+\-]?\d+(\.\d{1,3})?/, // 123456789 123456789.123 + parseTokenOrdinal = /\d{1,2}/, + + //strict parsing regexes + parseTokenOneDigit = /\d/, // 0 - 9 + parseTokenTwoDigits = /\d\d/, // 00 - 99 + parseTokenThreeDigits = /\d{3}/, // 000 - 999 + parseTokenFourDigits = /\d{4}/, // 0000 - 9999 + parseTokenSixDigits = /[+-]?\d{6}/, // -999,999 - 999,999 + parseTokenSignedNumber = /[+-]?\d+/, // -inf - inf + + // iso 8601 regex + // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00) + isoRegex = /^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/, + + isoFormat = 'YYYY-MM-DDTHH:mm:ssZ', + + isoDates = [ + ['YYYYYY-MM-DD', /[+-]\d{6}-\d{2}-\d{2}/], + ['YYYY-MM-DD', /\d{4}-\d{2}-\d{2}/], + ['GGGG-[W]WW-E', /\d{4}-W\d{2}-\d/], + ['GGGG-[W]WW', /\d{4}-W\d{2}/], + ['YYYY-DDD', /\d{4}-\d{3}/] + ], + + // iso time formats and regexes + isoTimes = [ + ['HH:mm:ss.SSSS', /(T| )\d\d:\d\d:\d\d\.\d+/], + ['HH:mm:ss', /(T| )\d\d:\d\d:\d\d/], + ['HH:mm', /(T| )\d\d:\d\d/], + ['HH', /(T| )\d\d/] + ], + + // timezone chunker '+10:00' > ['10', '00'] or '-1530' > ['-15', '30'] + parseTimezoneChunker = /([\+\-]|\d\d)/gi, + + // getter and setter names + proxyGettersAndSetters = 'Date|Hours|Minutes|Seconds|Milliseconds'.split('|'), + unitMillisecondFactors = { + 'Milliseconds' : 1, + 'Seconds' : 1e3, + 'Minutes' : 6e4, + 'Hours' : 36e5, + 'Days' : 864e5, + 'Months' : 2592e6, + 'Years' : 31536e6 + }, + + unitAliases = { + ms : 'millisecond', + s : 'second', + m : 'minute', + h : 'hour', + d : 'day', + D : 'date', + w : 'week', + W : 'isoWeek', + M : 'month', + Q : 'quarter', + y : 'year', + DDD : 'dayOfYear', + e : 'weekday', + E : 'isoWeekday', + gg: 'weekYear', + GG: 'isoWeekYear' + }, + + camelFunctions = { + dayofyear : 'dayOfYear', + isoweekday : 'isoWeekday', + isoweek : 'isoWeek', + weekyear : 'weekYear', + isoweekyear : 'isoWeekYear' + }, + + // format function strings + formatFunctions = {}, + + // default relative time thresholds + relativeTimeThresholds = { + s: 45, // seconds to minute + m: 45, // minutes to hour + h: 22, // hours to day + d: 26, // days to month + M: 11 // months to year + }, + + // tokens to ordinalize and pad + ordinalizeTokens = 'DDD w W M D d'.split(' '), + paddedTokens = 'M D H h m s w W'.split(' '), + + formatTokenFunctions = { + M : function () { + return this.month() + 1; + }, + MMM : function (format) { + return this.localeData().monthsShort(this, format); + }, + MMMM : function (format) { + return this.localeData().months(this, format); + }, + D : function () { + return this.date(); + }, + DDD : function () { + return this.dayOfYear(); + }, + d : function () { + return this.day(); + }, + dd : function (format) { + return this.localeData().weekdaysMin(this, format); + }, + ddd : function (format) { + return this.localeData().weekdaysShort(this, format); + }, + dddd : function (format) { + return this.localeData().weekdays(this, format); + }, + w : function () { + return this.week(); + }, + W : function () { + return this.isoWeek(); + }, + YY : function () { + return leftZeroFill(this.year() % 100, 2); + }, + YYYY : function () { + return leftZeroFill(this.year(), 4); + }, + YYYYY : function () { + return leftZeroFill(this.year(), 5); + }, + YYYYYY : function () { + var y = this.year(), sign = y >= 0 ? '+' : '-'; + return sign + leftZeroFill(Math.abs(y), 6); + }, + gg : function () { + return leftZeroFill(this.weekYear() % 100, 2); + }, + gggg : function () { + return leftZeroFill(this.weekYear(), 4); + }, + ggggg : function () { + return leftZeroFill(this.weekYear(), 5); + }, + GG : function () { + return leftZeroFill(this.isoWeekYear() % 100, 2); + }, + GGGG : function () { + return leftZeroFill(this.isoWeekYear(), 4); + }, + GGGGG : function () { + return leftZeroFill(this.isoWeekYear(), 5); + }, + e : function () { + return this.weekday(); + }, + E : function () { + return this.isoWeekday(); + }, + a : function () { + return this.localeData().meridiem(this.hours(), this.minutes(), true); + }, + A : function () { + return this.localeData().meridiem(this.hours(), this.minutes(), false); + }, + H : function () { + return this.hours(); + }, + h : function () { + return this.hours() % 12 || 12; + }, + m : function () { + return this.minutes(); + }, + s : function () { + return this.seconds(); + }, + S : function () { + return toInt(this.milliseconds() / 100); + }, + SS : function () { + return leftZeroFill(toInt(this.milliseconds() / 10), 2); + }, + SSS : function () { + return leftZeroFill(this.milliseconds(), 3); + }, + SSSS : function () { + return leftZeroFill(this.milliseconds(), 3); + }, + Z : function () { + var a = -this.zone(), + b = '+'; + if (a < 0) { + a = -a; + b = '-'; + } + return b + leftZeroFill(toInt(a / 60), 2) + ':' + leftZeroFill(toInt(a) % 60, 2); + }, + ZZ : function () { + var a = -this.zone(), + b = '+'; + if (a < 0) { + a = -a; + b = '-'; + } + return b + leftZeroFill(toInt(a / 60), 2) + leftZeroFill(toInt(a) % 60, 2); + }, + z : function () { + return this.zoneAbbr(); + }, + zz : function () { + return this.zoneName(); + }, + X : function () { + return this.unix(); + }, + Q : function () { + return this.quarter(); + } + }, + + deprecations = {}, + + lists = ['months', 'monthsShort', 'weekdays', 'weekdaysShort', 'weekdaysMin']; + + // Pick the first defined of two or three arguments. dfl comes from + // default. + function dfl(a, b, c) { + switch (arguments.length) { + case 2: return a != null ? a : b; + case 3: return a != null ? a : b != null ? b : c; + default: throw new Error('Implement me'); + } + } + + function hasOwnProp(a, b) { + return hasOwnProperty.call(a, b); + } + + function defaultParsingFlags() { + // We need to deep clone this object, and es5 standard is not very + // helpful. + return { + empty : false, + unusedTokens : [], + unusedInput : [], + overflow : -2, + charsLeftOver : 0, + nullInput : false, + invalidMonth : null, + invalidFormat : false, + userInvalidated : false, + iso: false + }; + } + + function printMsg(msg) { + if (moment.suppressDeprecationWarnings === false && + typeof console !== 'undefined' && console.warn) { + console.warn('Deprecation warning: ' + msg); + } + } + + function deprecate(msg, fn) { + var firstTime = true; + return extend(function () { + if (firstTime) { + printMsg(msg); + firstTime = false; + } + return fn.apply(this, arguments); + }, fn); + } + + function deprecateSimple(name, msg) { + if (!deprecations[name]) { + printMsg(msg); + deprecations[name] = true; + } + } + + function padToken(func, count) { + return function (a) { + return leftZeroFill(func.call(this, a), count); + }; + } + function ordinalizeToken(func, period) { + return function (a) { + return this.localeData().ordinal(func.call(this, a), period); + }; + } + + while (ordinalizeTokens.length) { + i = ordinalizeTokens.pop(); + formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i], i); + } + while (paddedTokens.length) { + i = paddedTokens.pop(); + formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2); + } + formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3); + + + /************************************ + Constructors + ************************************/ + + function Locale() { + } + + // Moment prototype object + function Moment(config, skipOverflow) { + if (skipOverflow !== false) { + checkOverflow(config); + } + copyConfig(this, config); + this._d = new Date(+config._d); + } + + // Duration Constructor + function Duration(duration) { + var normalizedInput = normalizeObjectUnits(duration), + years = normalizedInput.year || 0, + quarters = normalizedInput.quarter || 0, + months = normalizedInput.month || 0, + weeks = normalizedInput.week || 0, + days = normalizedInput.day || 0, + hours = normalizedInput.hour || 0, + minutes = normalizedInput.minute || 0, + seconds = normalizedInput.second || 0, + milliseconds = normalizedInput.millisecond || 0; + + // representation for dateAddRemove + this._milliseconds = +milliseconds + + seconds * 1e3 + // 1000 + minutes * 6e4 + // 1000 * 60 + hours * 36e5; // 1000 * 60 * 60 + // Because of dateAddRemove treats 24 hours as different from a + // day when working around DST, we need to store them separately + this._days = +days + + weeks * 7; + // It is impossible translate months into days without knowing + // which months you are are talking about, so we have to store + // it separately. + this._months = +months + + quarters * 3 + + years * 12; + + this._data = {}; + + this._locale = moment.localeData(); + + this._bubble(); + } + + /************************************ + Helpers + ************************************/ + + + function extend(a, b) { + for (var i in b) { + if (hasOwnProp(b, i)) { + a[i] = b[i]; + } + } + + if (hasOwnProp(b, 'toString')) { + a.toString = b.toString; + } + + if (hasOwnProp(b, 'valueOf')) { + a.valueOf = b.valueOf; + } + + return a; + } + + function copyConfig(to, from) { + var i, prop, val; + + if (typeof from._isAMomentObject !== 'undefined') { + to._isAMomentObject = from._isAMomentObject; + } + if (typeof from._i !== 'undefined') { + to._i = from._i; + } + if (typeof from._f !== 'undefined') { + to._f = from._f; + } + if (typeof from._l !== 'undefined') { + to._l = from._l; + } + if (typeof from._strict !== 'undefined') { + to._strict = from._strict; + } + if (typeof from._tzm !== 'undefined') { + to._tzm = from._tzm; + } + if (typeof from._isUTC !== 'undefined') { + to._isUTC = from._isUTC; + } + if (typeof from._offset !== 'undefined') { + to._offset = from._offset; + } + if (typeof from._pf !== 'undefined') { + to._pf = from._pf; + } + if (typeof from._locale !== 'undefined') { + to._locale = from._locale; + } + + if (momentProperties.length > 0) { + for (i in momentProperties) { + prop = momentProperties[i]; + val = from[prop]; + if (typeof val !== 'undefined') { + to[prop] = val; + } + } + } + + return to; + } + + function absRound(number) { + if (number < 0) { + return Math.ceil(number); + } else { + return Math.floor(number); + } + } + + // left zero fill a number + // see http://jsperf.com/left-zero-filling for performance comparison + function leftZeroFill(number, targetLength, forceSign) { + var output = '' + Math.abs(number), + sign = number >= 0; + + while (output.length < targetLength) { + output = '0' + output; + } + return (sign ? (forceSign ? '+' : '') : '-') + output; + } + + function positiveMomentsDifference(base, other) { + var res = {milliseconds: 0, months: 0}; + + res.months = other.month() - base.month() + + (other.year() - base.year()) * 12; + if (base.clone().add(res.months, 'M').isAfter(other)) { + --res.months; + } + + res.milliseconds = +other - +(base.clone().add(res.months, 'M')); + + return res; + } + + function momentsDifference(base, other) { + var res; + other = makeAs(other, base); + if (base.isBefore(other)) { + res = positiveMomentsDifference(base, other); + } else { + res = positiveMomentsDifference(other, base); + res.milliseconds = -res.milliseconds; + res.months = -res.months; + } + + return res; + } + + // TODO: remove 'name' arg after deprecation is removed + function createAdder(direction, name) { + return function (val, period) { + var dur, tmp; + //invert the arguments, but complain about it + if (period !== null && !isNaN(+period)) { + deprecateSimple(name, 'moment().' + name + '(period, number) is deprecated. Please use moment().' + name + '(number, period).'); + tmp = val; val = period; period = tmp; + } + + val = typeof val === 'string' ? +val : val; + dur = moment.duration(val, period); + addOrSubtractDurationFromMoment(this, dur, direction); + return this; + }; + } + + function addOrSubtractDurationFromMoment(mom, duration, isAdding, updateOffset) { + var milliseconds = duration._milliseconds, + days = duration._days, + months = duration._months; + updateOffset = updateOffset == null ? true : updateOffset; + + if (milliseconds) { + mom._d.setTime(+mom._d + milliseconds * isAdding); + } + if (days) { + rawSetter(mom, 'Date', rawGetter(mom, 'Date') + days * isAdding); + } + if (months) { + rawMonthSetter(mom, rawGetter(mom, 'Month') + months * isAdding); + } + if (updateOffset) { + moment.updateOffset(mom, days || months); + } + } + + // check if is an array + function isArray(input) { + return Object.prototype.toString.call(input) === '[object Array]'; + } + + function isDate(input) { + return Object.prototype.toString.call(input) === '[object Date]' || + input instanceof Date; + } + + // compare two arrays, return the number of differences + function compareArrays(array1, array2, dontConvert) { + var len = Math.min(array1.length, array2.length), + lengthDiff = Math.abs(array1.length - array2.length), + diffs = 0, + i; + for (i = 0; i < len; i++) { + if ((dontConvert && array1[i] !== array2[i]) || + (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) { + diffs++; + } + } + return diffs + lengthDiff; + } + + function normalizeUnits(units) { + if (units) { + var lowered = units.toLowerCase().replace(/(.)s$/, '$1'); + units = unitAliases[units] || camelFunctions[lowered] || lowered; + } + return units; + } + + function normalizeObjectUnits(inputObject) { + var normalizedInput = {}, + normalizedProp, + prop; + + for (prop in inputObject) { + if (hasOwnProp(inputObject, prop)) { + normalizedProp = normalizeUnits(prop); + if (normalizedProp) { + normalizedInput[normalizedProp] = inputObject[prop]; + } + } + } + + return normalizedInput; + } + + function makeList(field) { + var count, setter; + + if (field.indexOf('week') === 0) { + count = 7; + setter = 'day'; + } + else if (field.indexOf('month') === 0) { + count = 12; + setter = 'month'; + } + else { + return; + } + + moment[field] = function (format, index) { + var i, getter, + method = moment._locale[field], + results = []; + + if (typeof format === 'number') { + index = format; + format = undefined; + } + + getter = function (i) { + var m = moment().utc().set(setter, i); + return method.call(moment._locale, m, format || ''); + }; + + if (index != null) { + return getter(index); + } + else { + for (i = 0; i < count; i++) { + results.push(getter(i)); + } + return results; + } + }; + } + + function toInt(argumentForCoercion) { + var coercedNumber = +argumentForCoercion, + value = 0; + + if (coercedNumber !== 0 && isFinite(coercedNumber)) { + if (coercedNumber >= 0) { + value = Math.floor(coercedNumber); + } else { + value = Math.ceil(coercedNumber); + } + } + + return value; + } + + function daysInMonth(year, month) { + return new Date(Date.UTC(year, month + 1, 0)).getUTCDate(); + } + + function weeksInYear(year, dow, doy) { + return weekOfYear(moment([year, 11, 31 + dow - doy]), dow, doy).week; + } + + function daysInYear(year) { + return isLeapYear(year) ? 366 : 365; + } + + function isLeapYear(year) { + return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; + } + + function checkOverflow(m) { + var overflow; + if (m._a && m._pf.overflow === -2) { + overflow = + m._a[MONTH] < 0 || m._a[MONTH] > 11 ? MONTH : + m._a[DATE] < 1 || m._a[DATE] > daysInMonth(m._a[YEAR], m._a[MONTH]) ? DATE : + m._a[HOUR] < 0 || m._a[HOUR] > 23 ? HOUR : + m._a[MINUTE] < 0 || m._a[MINUTE] > 59 ? MINUTE : + m._a[SECOND] < 0 || m._a[SECOND] > 59 ? SECOND : + m._a[MILLISECOND] < 0 || m._a[MILLISECOND] > 999 ? MILLISECOND : + -1; + + if (m._pf._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) { + overflow = DATE; + } + + m._pf.overflow = overflow; + } + } + + function isValid(m) { + if (m._isValid == null) { + m._isValid = !isNaN(m._d.getTime()) && + m._pf.overflow < 0 && + !m._pf.empty && + !m._pf.invalidMonth && + !m._pf.nullInput && + !m._pf.invalidFormat && + !m._pf.userInvalidated; + + if (m._strict) { + m._isValid = m._isValid && + m._pf.charsLeftOver === 0 && + m._pf.unusedTokens.length === 0; + } + } + return m._isValid; + } + + function normalizeLocale(key) { + return key ? key.toLowerCase().replace('_', '-') : key; + } + + // pick the locale from the array + // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each + // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root + function chooseLocale(names) { + var i = 0, j, next, locale, split; + + while (i < names.length) { + split = normalizeLocale(names[i]).split('-'); + j = split.length; + next = normalizeLocale(names[i + 1]); + next = next ? next.split('-') : null; + while (j > 0) { + locale = loadLocale(split.slice(0, j).join('-')); + if (locale) { + return locale; + } + if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) { + //the next array item is better than a shallower substring of this one + break; + } + j--; + } + i++; + } + return null; + } + + function loadLocale(name) { + var oldLocale = null; + if (!locales[name] && hasModule) { + try { + oldLocale = moment.locale(); + require('./locale/' + name); + // because defineLocale currently also sets the global locale, we want to undo that for lazy loaded locales + moment.locale(oldLocale); + } catch (e) { } + } + return locales[name]; + } + + // Return a moment from input, that is local/utc/zone equivalent to model. + function makeAs(input, model) { + return model._isUTC ? moment(input).zone(model._offset || 0) : + moment(input).local(); + } + + /************************************ + Locale + ************************************/ + + + extend(Locale.prototype, { + + set : function (config) { + var prop, i; + for (i in config) { + prop = config[i]; + if (typeof prop === 'function') { + this[i] = prop; + } else { + this['_' + i] = prop; + } + } + }, + + _months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'), + months : function (m) { + return this._months[m.month()]; + }, + + _monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'), + monthsShort : function (m) { + return this._monthsShort[m.month()]; + }, + + monthsParse : function (monthName) { + var i, mom, regex; + + if (!this._monthsParse) { + this._monthsParse = []; + } + + for (i = 0; i < 12; i++) { + // make the regex if we don't have it already + if (!this._monthsParse[i]) { + mom = moment.utc([2000, i]); + regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, ''); + this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i'); + } + // test the regex + if (this._monthsParse[i].test(monthName)) { + return i; + } + } + }, + + _weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'), + weekdays : function (m) { + return this._weekdays[m.day()]; + }, + + _weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'), + weekdaysShort : function (m) { + return this._weekdaysShort[m.day()]; + }, + + _weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'), + weekdaysMin : function (m) { + return this._weekdaysMin[m.day()]; + }, + + weekdaysParse : function (weekdayName) { + var i, mom, regex; + + if (!this._weekdaysParse) { + this._weekdaysParse = []; + } + + for (i = 0; i < 7; i++) { + // make the regex if we don't have it already + if (!this._weekdaysParse[i]) { + mom = moment([2000, 1]).day(i); + regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, ''); + this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i'); + } + // test the regex + if (this._weekdaysParse[i].test(weekdayName)) { + return i; + } + } + }, + + _longDateFormat : { + LT : 'h:mm A', + L : 'MM/DD/YYYY', + LL : 'MMMM D, YYYY', + LLL : 'MMMM D, YYYY LT', + LLLL : 'dddd, MMMM D, YYYY LT' + }, + longDateFormat : function (key) { + var output = this._longDateFormat[key]; + if (!output && this._longDateFormat[key.toUpperCase()]) { + output = this._longDateFormat[key.toUpperCase()].replace(/MMMM|MM|DD|dddd/g, function (val) { + return val.slice(1); + }); + this._longDateFormat[key] = output; + } + return output; + }, + + isPM : function (input) { + // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays + // Using charAt should be more compatible. + return ((input + '').toLowerCase().charAt(0) === 'p'); + }, + + _meridiemParse : /[ap]\.?m?\.?/i, + meridiem : function (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'pm' : 'PM'; + } else { + return isLower ? 'am' : 'AM'; + } + }, + + _calendar : { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' + }, + calendar : function (key, mom) { + var output = this._calendar[key]; + return typeof output === 'function' ? output.apply(mom) : output; + }, + + _relativeTime : { + future : 'in %s', + past : '%s ago', + s : 'a few seconds', + m : 'a minute', + mm : '%d minutes', + h : 'an hour', + hh : '%d hours', + d : 'a day', + dd : '%d days', + M : 'a month', + MM : '%d months', + y : 'a year', + yy : '%d years' + }, + + relativeTime : function (number, withoutSuffix, string, isFuture) { + var output = this._relativeTime[string]; + return (typeof output === 'function') ? + output(number, withoutSuffix, string, isFuture) : + output.replace(/%d/i, number); + }, + + pastFuture : function (diff, output) { + var format = this._relativeTime[diff > 0 ? 'future' : 'past']; + return typeof format === 'function' ? format(output) : format.replace(/%s/i, output); + }, + + ordinal : function (number) { + return this._ordinal.replace('%d', number); + }, + _ordinal : '%d', + + preparse : function (string) { + return string; + }, + + postformat : function (string) { + return string; + }, + + week : function (mom) { + return weekOfYear(mom, this._week.dow, this._week.doy).week; + }, + + _week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + }, + + _invalidDate: 'Invalid date', + invalidDate: function () { + return this._invalidDate; + } + }); + + /************************************ + Formatting + ************************************/ + + + function removeFormattingTokens(input) { + if (input.match(/\[[\s\S]/)) { + return input.replace(/^\[|\]$/g, ''); + } + return input.replace(/\\/g, ''); + } + + function makeFormatFunction(format) { + var array = format.match(formattingTokens), i, length; + + for (i = 0, length = array.length; i < length; i++) { + if (formatTokenFunctions[array[i]]) { + array[i] = formatTokenFunctions[array[i]]; + } else { + array[i] = removeFormattingTokens(array[i]); + } + } + + return function (mom) { + var output = ''; + for (i = 0; i < length; i++) { + output += array[i] instanceof Function ? array[i].call(mom, format) : array[i]; + } + return output; + }; + } + + // format date using native date object + function formatMoment(m, format) { + if (!m.isValid()) { + return m.localeData().invalidDate(); + } + + format = expandFormat(format, m.localeData()); + + if (!formatFunctions[format]) { + formatFunctions[format] = makeFormatFunction(format); + } + + return formatFunctions[format](m); + } + + function expandFormat(format, locale) { + var i = 5; + + function replaceLongDateFormatTokens(input) { + return locale.longDateFormat(input) || input; + } + + localFormattingTokens.lastIndex = 0; + while (i >= 0 && localFormattingTokens.test(format)) { + format = format.replace(localFormattingTokens, replaceLongDateFormatTokens); + localFormattingTokens.lastIndex = 0; + i -= 1; + } + + return format; + } + + + /************************************ + Parsing + ************************************/ + + + // get the regex to find the next token + function getParseRegexForToken(token, config) { + var a, strict = config._strict; + switch (token) { + case 'Q': + return parseTokenOneDigit; + case 'DDDD': + return parseTokenThreeDigits; + case 'YYYY': + case 'GGGG': + case 'gggg': + return strict ? parseTokenFourDigits : parseTokenOneToFourDigits; + case 'Y': + case 'G': + case 'g': + return parseTokenSignedNumber; + case 'YYYYYY': + case 'YYYYY': + case 'GGGGG': + case 'ggggg': + return strict ? parseTokenSixDigits : parseTokenOneToSixDigits; + case 'S': + if (strict) { + return parseTokenOneDigit; + } + /* falls through */ + case 'SS': + if (strict) { + return parseTokenTwoDigits; + } + /* falls through */ + case 'SSS': + if (strict) { + return parseTokenThreeDigits; + } + /* falls through */ + case 'DDD': + return parseTokenOneToThreeDigits; + case 'MMM': + case 'MMMM': + case 'dd': + case 'ddd': + case 'dddd': + return parseTokenWord; + case 'a': + case 'A': + return config._locale._meridiemParse; + case 'X': + return parseTokenTimestampMs; + case 'Z': + case 'ZZ': + return parseTokenTimezone; + case 'T': + return parseTokenT; + case 'SSSS': + return parseTokenDigits; + case 'MM': + case 'DD': + case 'YY': + case 'GG': + case 'gg': + case 'HH': + case 'hh': + case 'mm': + case 'ss': + case 'ww': + case 'WW': + return strict ? parseTokenTwoDigits : parseTokenOneOrTwoDigits; + case 'M': + case 'D': + case 'd': + case 'H': + case 'h': + case 'm': + case 's': + case 'w': + case 'W': + case 'e': + case 'E': + return parseTokenOneOrTwoDigits; + case 'Do': + return parseTokenOrdinal; + default : + a = new RegExp(regexpEscape(unescapeFormat(token.replace('\\', '')), 'i')); + return a; + } + } + + function timezoneMinutesFromString(string) { + string = string || ''; + var possibleTzMatches = (string.match(parseTokenTimezone) || []), + tzChunk = possibleTzMatches[possibleTzMatches.length - 1] || [], + parts = (tzChunk + '').match(parseTimezoneChunker) || ['-', 0, 0], + minutes = +(parts[1] * 60) + toInt(parts[2]); + + return parts[0] === '+' ? -minutes : minutes; + } + + // function to convert string input to date + function addTimeToArrayFromToken(token, input, config) { + var a, datePartArray = config._a; + + switch (token) { + // QUARTER + case 'Q': + if (input != null) { + datePartArray[MONTH] = (toInt(input) - 1) * 3; + } + break; + // MONTH + case 'M' : // fall through to MM + case 'MM' : + if (input != null) { + datePartArray[MONTH] = toInt(input) - 1; + } + break; + case 'MMM' : // fall through to MMMM + case 'MMMM' : + a = config._locale.monthsParse(input); + // if we didn't find a month name, mark the date as invalid. + if (a != null) { + datePartArray[MONTH] = a; + } else { + config._pf.invalidMonth = input; + } + break; + // DAY OF MONTH + case 'D' : // fall through to DD + case 'DD' : + if (input != null) { + datePartArray[DATE] = toInt(input); + } + break; + case 'Do' : + if (input != null) { + datePartArray[DATE] = toInt(parseInt(input, 10)); + } + break; + // DAY OF YEAR + case 'DDD' : // fall through to DDDD + case 'DDDD' : + if (input != null) { + config._dayOfYear = toInt(input); + } + + break; + // YEAR + case 'YY' : + datePartArray[YEAR] = moment.parseTwoDigitYear(input); + break; + case 'YYYY' : + case 'YYYYY' : + case 'YYYYYY' : + datePartArray[YEAR] = toInt(input); + break; + // AM / PM + case 'a' : // fall through to A + case 'A' : + config._isPm = config._locale.isPM(input); + break; + // 24 HOUR + case 'H' : // fall through to hh + case 'HH' : // fall through to hh + case 'h' : // fall through to hh + case 'hh' : + datePartArray[HOUR] = toInt(input); + break; + // MINUTE + case 'm' : // fall through to mm + case 'mm' : + datePartArray[MINUTE] = toInt(input); + break; + // SECOND + case 's' : // fall through to ss + case 'ss' : + datePartArray[SECOND] = toInt(input); + break; + // MILLISECOND + case 'S' : + case 'SS' : + case 'SSS' : + case 'SSSS' : + datePartArray[MILLISECOND] = toInt(('0.' + input) * 1000); + break; + // UNIX TIMESTAMP WITH MS + case 'X': + config._d = new Date(parseFloat(input) * 1000); + break; + // TIMEZONE + case 'Z' : // fall through to ZZ + case 'ZZ' : + config._useUTC = true; + config._tzm = timezoneMinutesFromString(input); + break; + // WEEKDAY - human + case 'dd': + case 'ddd': + case 'dddd': + a = config._locale.weekdaysParse(input); + // if we didn't get a weekday name, mark the date as invalid + if (a != null) { + config._w = config._w || {}; + config._w['d'] = a; + } else { + config._pf.invalidWeekday = input; + } + break; + // WEEK, WEEK DAY - numeric + case 'w': + case 'ww': + case 'W': + case 'WW': + case 'd': + case 'e': + case 'E': + token = token.substr(0, 1); + /* falls through */ + case 'gggg': + case 'GGGG': + case 'GGGGG': + token = token.substr(0, 2); + if (input) { + config._w = config._w || {}; + config._w[token] = toInt(input); + } + break; + case 'gg': + case 'GG': + config._w = config._w || {}; + config._w[token] = moment.parseTwoDigitYear(input); + } + } + + function dayOfYearFromWeekInfo(config) { + var w, weekYear, week, weekday, dow, doy, temp; + + w = config._w; + if (w.GG != null || w.W != null || w.E != null) { + dow = 1; + doy = 4; + + // TODO: We need to take the current isoWeekYear, but that depends on + // how we interpret now (local, utc, fixed offset). So create + // a now version of current config (take local/utc/offset flags, and + // create now). + weekYear = dfl(w.GG, config._a[YEAR], weekOfYear(moment(), 1, 4).year); + week = dfl(w.W, 1); + weekday = dfl(w.E, 1); + } else { + dow = config._locale._week.dow; + doy = config._locale._week.doy; + + weekYear = dfl(w.gg, config._a[YEAR], weekOfYear(moment(), dow, doy).year); + week = dfl(w.w, 1); + + if (w.d != null) { + // weekday -- low day numbers are considered next week + weekday = w.d; + if (weekday < dow) { + ++week; + } + } else if (w.e != null) { + // local weekday -- counting starts from begining of week + weekday = w.e + dow; + } else { + // default to begining of week + weekday = dow; + } + } + temp = dayOfYearFromWeeks(weekYear, week, weekday, doy, dow); + + config._a[YEAR] = temp.year; + config._dayOfYear = temp.dayOfYear; + } + + // convert an array to a date. + // the array should mirror the parameters below + // note: all values past the year are optional and will default to the lowest possible value. + // [year, month, day , hour, minute, second, millisecond] + function dateFromConfig(config) { + var i, date, input = [], currentDate, yearToUse; + + if (config._d) { + return; + } + + currentDate = currentDateArray(config); + + //compute day of the year from weeks and weekdays + if (config._w && config._a[DATE] == null && config._a[MONTH] == null) { + dayOfYearFromWeekInfo(config); + } + + //if the day of the year is set, figure out what it is + if (config._dayOfYear) { + yearToUse = dfl(config._a[YEAR], currentDate[YEAR]); + + if (config._dayOfYear > daysInYear(yearToUse)) { + config._pf._overflowDayOfYear = true; + } + + date = makeUTCDate(yearToUse, 0, config._dayOfYear); + config._a[MONTH] = date.getUTCMonth(); + config._a[DATE] = date.getUTCDate(); + } + + // Default to current date. + // * if no year, month, day of month are given, default to today + // * if day of month is given, default month and year + // * if month is given, default only year + // * if year is given, don't default anything + for (i = 0; i < 3 && config._a[i] == null; ++i) { + config._a[i] = input[i] = currentDate[i]; + } + + // Zero out whatever was not defaulted, including time + for (; i < 7; i++) { + config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i]; + } + + config._d = (config._useUTC ? makeUTCDate : makeDate).apply(null, input); + // Apply timezone offset from input. The actual zone can be changed + // with parseZone. + if (config._tzm != null) { + config._d.setUTCMinutes(config._d.getUTCMinutes() + config._tzm); + } + } + + function dateFromObject(config) { + var normalizedInput; + + if (config._d) { + return; + } + + normalizedInput = normalizeObjectUnits(config._i); + config._a = [ + normalizedInput.year, + normalizedInput.month, + normalizedInput.day, + normalizedInput.hour, + normalizedInput.minute, + normalizedInput.second, + normalizedInput.millisecond + ]; + + dateFromConfig(config); + } + + function currentDateArray(config) { + var now = new Date(); + if (config._useUTC) { + return [ + now.getUTCFullYear(), + now.getUTCMonth(), + now.getUTCDate() + ]; + } else { + return [now.getFullYear(), now.getMonth(), now.getDate()]; + } + } + + // date from string and format string + function makeDateFromStringAndFormat(config) { + if (config._f === moment.ISO_8601) { + parseISO(config); + return; + } + + config._a = []; + config._pf.empty = true; + + // This array is used to make a Date, either with `new Date` or `Date.UTC` + var string = '' + config._i, + i, parsedInput, tokens, token, skipped, + stringLength = string.length, + totalParsedInputLength = 0; + + tokens = expandFormat(config._f, config._locale).match(formattingTokens) || []; + + for (i = 0; i < tokens.length; i++) { + token = tokens[i]; + parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0]; + if (parsedInput) { + skipped = string.substr(0, string.indexOf(parsedInput)); + if (skipped.length > 0) { + config._pf.unusedInput.push(skipped); + } + string = string.slice(string.indexOf(parsedInput) + parsedInput.length); + totalParsedInputLength += parsedInput.length; + } + // don't parse if it's not a known token + if (formatTokenFunctions[token]) { + if (parsedInput) { + config._pf.empty = false; + } + else { + config._pf.unusedTokens.push(token); + } + addTimeToArrayFromToken(token, parsedInput, config); + } + else if (config._strict && !parsedInput) { + config._pf.unusedTokens.push(token); + } + } + + // add remaining unparsed input length to the string + config._pf.charsLeftOver = stringLength - totalParsedInputLength; + if (string.length > 0) { + config._pf.unusedInput.push(string); + } + + // handle am pm + if (config._isPm && config._a[HOUR] < 12) { + config._a[HOUR] += 12; + } + // if is 12 am, change hours to 0 + if (config._isPm === false && config._a[HOUR] === 12) { + config._a[HOUR] = 0; + } + + dateFromConfig(config); + checkOverflow(config); + } + + function unescapeFormat(s) { + return s.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) { + return p1 || p2 || p3 || p4; + }); + } + + // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript + function regexpEscape(s) { + return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); + } + + // date from string and array of format strings + function makeDateFromStringAndArray(config) { + var tempConfig, + bestMoment, + + scoreToBeat, + i, + currentScore; + + if (config._f.length === 0) { + config._pf.invalidFormat = true; + config._d = new Date(NaN); + return; + } + + for (i = 0; i < config._f.length; i++) { + currentScore = 0; + tempConfig = copyConfig({}, config); + if (config._useUTC != null) { + tempConfig._useUTC = config._useUTC; + } + tempConfig._pf = defaultParsingFlags(); + tempConfig._f = config._f[i]; + makeDateFromStringAndFormat(tempConfig); + + if (!isValid(tempConfig)) { + continue; + } + + // if there is any input that was not parsed add a penalty for that format + currentScore += tempConfig._pf.charsLeftOver; + + //or tokens + currentScore += tempConfig._pf.unusedTokens.length * 10; + + tempConfig._pf.score = currentScore; + + if (scoreToBeat == null || currentScore < scoreToBeat) { + scoreToBeat = currentScore; + bestMoment = tempConfig; + } + } + + extend(config, bestMoment || tempConfig); + } + + // date from iso format + function parseISO(config) { + var i, l, + string = config._i, + match = isoRegex.exec(string); + + if (match) { + config._pf.iso = true; + for (i = 0, l = isoDates.length; i < l; i++) { + if (isoDates[i][1].exec(string)) { + // match[5] should be 'T' or undefined + config._f = isoDates[i][0] + (match[6] || ' '); + break; + } + } + for (i = 0, l = isoTimes.length; i < l; i++) { + if (isoTimes[i][1].exec(string)) { + config._f += isoTimes[i][0]; + break; + } + } + if (string.match(parseTokenTimezone)) { + config._f += 'Z'; + } + makeDateFromStringAndFormat(config); + } else { + config._isValid = false; + } + } + + // date from iso format or fallback + function makeDateFromString(config) { + parseISO(config); + if (config._isValid === false) { + delete config._isValid; + moment.createFromInputFallback(config); + } + } + + function map(arr, fn) { + var res = [], i; + for (i = 0; i < arr.length; ++i) { + res.push(fn(arr[i], i)); + } + return res; + } + + function makeDateFromInput(config) { + var input = config._i, matched; + if (input === undefined) { + config._d = new Date(); + } else if (isDate(input)) { + config._d = new Date(+input); + } else if ((matched = aspNetJsonRegex.exec(input)) !== null) { + config._d = new Date(+matched[1]); + } else if (typeof input === 'string') { + makeDateFromString(config); + } else if (isArray(input)) { + config._a = map(input.slice(0), function (obj) { + return parseInt(obj, 10); + }); + dateFromConfig(config); + } else if (typeof(input) === 'object') { + dateFromObject(config); + } else if (typeof(input) === 'number') { + // from milliseconds + config._d = new Date(input); + } else { + moment.createFromInputFallback(config); + } + } + + function makeDate(y, m, d, h, M, s, ms) { + //can't just apply() to create a date: + //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply + var date = new Date(y, m, d, h, M, s, ms); + + //the date constructor doesn't accept years < 1970 + if (y < 1970) { + date.setFullYear(y); + } + return date; + } + + function makeUTCDate(y) { + var date = new Date(Date.UTC.apply(null, arguments)); + if (y < 1970) { + date.setUTCFullYear(y); + } + return date; + } + + function parseWeekday(input, locale) { + if (typeof input === 'string') { + if (!isNaN(input)) { + input = parseInt(input, 10); + } + else { + input = locale.weekdaysParse(input); + if (typeof input !== 'number') { + return null; + } + } + } + return input; + } + + /************************************ + Relative Time + ************************************/ + + + // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize + function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) { + return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture); + } + + function relativeTime(posNegDuration, withoutSuffix, locale) { + var duration = moment.duration(posNegDuration).abs(), + seconds = round(duration.as('s')), + minutes = round(duration.as('m')), + hours = round(duration.as('h')), + days = round(duration.as('d')), + months = round(duration.as('M')), + years = round(duration.as('y')), + + args = seconds < relativeTimeThresholds.s && ['s', seconds] || + minutes === 1 && ['m'] || + minutes < relativeTimeThresholds.m && ['mm', minutes] || + hours === 1 && ['h'] || + hours < relativeTimeThresholds.h && ['hh', hours] || + days === 1 && ['d'] || + days < relativeTimeThresholds.d && ['dd', days] || + months === 1 && ['M'] || + months < relativeTimeThresholds.M && ['MM', months] || + years === 1 && ['y'] || ['yy', years]; + + args[2] = withoutSuffix; + args[3] = +posNegDuration > 0; + args[4] = locale; + return substituteTimeAgo.apply({}, args); + } + + + /************************************ + Week of Year + ************************************/ + + + // firstDayOfWeek 0 = sun, 6 = sat + // the day of the week that starts the week + // (usually sunday or monday) + // firstDayOfWeekOfYear 0 = sun, 6 = sat + // the first week is the week that contains the first + // of this day of the week + // (eg. ISO weeks use thursday (4)) + function weekOfYear(mom, firstDayOfWeek, firstDayOfWeekOfYear) { + var end = firstDayOfWeekOfYear - firstDayOfWeek, + daysToDayOfWeek = firstDayOfWeekOfYear - mom.day(), + adjustedMoment; + + + if (daysToDayOfWeek > end) { + daysToDayOfWeek -= 7; + } + + if (daysToDayOfWeek < end - 7) { + daysToDayOfWeek += 7; + } + + adjustedMoment = moment(mom).add(daysToDayOfWeek, 'd'); + return { + week: Math.ceil(adjustedMoment.dayOfYear() / 7), + year: adjustedMoment.year() + }; + } + + //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday + function dayOfYearFromWeeks(year, week, weekday, firstDayOfWeekOfYear, firstDayOfWeek) { + var d = makeUTCDate(year, 0, 1).getUTCDay(), daysToAdd, dayOfYear; + + d = d === 0 ? 7 : d; + weekday = weekday != null ? weekday : firstDayOfWeek; + daysToAdd = firstDayOfWeek - d + (d > firstDayOfWeekOfYear ? 7 : 0) - (d < firstDayOfWeek ? 7 : 0); + dayOfYear = 7 * (week - 1) + (weekday - firstDayOfWeek) + daysToAdd + 1; + + return { + year: dayOfYear > 0 ? year : year - 1, + dayOfYear: dayOfYear > 0 ? dayOfYear : daysInYear(year - 1) + dayOfYear + }; + } + + /************************************ + Top Level Functions + ************************************/ + + function makeMoment(config) { + var input = config._i, + format = config._f; + + config._locale = config._locale || moment.localeData(config._l); + + if (input === null || (format === undefined && input === '')) { + return moment.invalid({nullInput: true}); + } + + if (typeof input === 'string') { + config._i = input = config._locale.preparse(input); + } + + if (moment.isMoment(input)) { + return new Moment(input, true); + } else if (format) { + if (isArray(format)) { + makeDateFromStringAndArray(config); + } else { + makeDateFromStringAndFormat(config); + } + } else { + makeDateFromInput(config); + } + + return new Moment(config); + } + + moment = function (input, format, locale, strict) { + var c; + + if (typeof(locale) === 'boolean') { + strict = locale; + locale = undefined; + } + // object construction must be done this way. + // https://github.com/moment/moment/issues/1423 + c = {}; + c._isAMomentObject = true; + c._i = input; + c._f = format; + c._l = locale; + c._strict = strict; + c._isUTC = false; + c._pf = defaultParsingFlags(); + + return makeMoment(c); + }; + + moment.suppressDeprecationWarnings = false; + + moment.createFromInputFallback = deprecate( + 'moment construction falls back to js Date. This is ' + + 'discouraged and will be removed in upcoming major ' + + 'release. Please refer to ' + + 'https://github.com/moment/moment/issues/1407 for more info.', + function (config) { + config._d = new Date(config._i); + } + ); + + // Pick a moment m from moments so that m[fn](other) is true for all + // other. This relies on the function fn to be transitive. + // + // moments should either be an array of moment objects or an array, whose + // first element is an array of moment objects. + function pickBy(fn, moments) { + var res, i; + if (moments.length === 1 && isArray(moments[0])) { + moments = moments[0]; + } + if (!moments.length) { + return moment(); + } + res = moments[0]; + for (i = 1; i < moments.length; ++i) { + if (moments[i][fn](res)) { + res = moments[i]; + } + } + return res; + } + + moment.min = function () { + var args = [].slice.call(arguments, 0); + + return pickBy('isBefore', args); + }; + + moment.max = function () { + var args = [].slice.call(arguments, 0); + + return pickBy('isAfter', args); + }; + + // creating with utc + moment.utc = function (input, format, locale, strict) { + var c; + + if (typeof(locale) === 'boolean') { + strict = locale; + locale = undefined; + } + // object construction must be done this way. + // https://github.com/moment/moment/issues/1423 + c = {}; + c._isAMomentObject = true; + c._useUTC = true; + c._isUTC = true; + c._l = locale; + c._i = input; + c._f = format; + c._strict = strict; + c._pf = defaultParsingFlags(); + + return makeMoment(c).utc(); + }; + + // creating with unix timestamp (in seconds) + moment.unix = function (input) { + return moment(input * 1000); + }; + + // duration + moment.duration = function (input, key) { + var duration = input, + // matching against regexp is expensive, do it on demand + match = null, + sign, + ret, + parseIso, + diffRes; + + if (moment.isDuration(input)) { + duration = { + ms: input._milliseconds, + d: input._days, + M: input._months + }; + } else if (typeof input === 'number') { + duration = {}; + if (key) { + duration[key] = input; + } else { + duration.milliseconds = input; + } + } else if (!!(match = aspNetTimeSpanJsonRegex.exec(input))) { + sign = (match[1] === '-') ? -1 : 1; + duration = { + y: 0, + d: toInt(match[DATE]) * sign, + h: toInt(match[HOUR]) * sign, + m: toInt(match[MINUTE]) * sign, + s: toInt(match[SECOND]) * sign, + ms: toInt(match[MILLISECOND]) * sign + }; + } else if (!!(match = isoDurationRegex.exec(input))) { + sign = (match[1] === '-') ? -1 : 1; + parseIso = function (inp) { + // We'd normally use ~~inp for this, but unfortunately it also + // converts floats to ints. + // inp may be undefined, so careful calling replace on it. + var res = inp && parseFloat(inp.replace(',', '.')); + // apply sign while we're at it + return (isNaN(res) ? 0 : res) * sign; + }; + duration = { + y: parseIso(match[2]), + M: parseIso(match[3]), + d: parseIso(match[4]), + h: parseIso(match[5]), + m: parseIso(match[6]), + s: parseIso(match[7]), + w: parseIso(match[8]) + }; + } else if (typeof duration === 'object' && + ('from' in duration || 'to' in duration)) { + diffRes = momentsDifference(moment(duration.from), moment(duration.to)); + + duration = {}; + duration.ms = diffRes.milliseconds; + duration.M = diffRes.months; + } + + ret = new Duration(duration); + + if (moment.isDuration(input) && hasOwnProp(input, '_locale')) { + ret._locale = input._locale; + } + + return ret; + }; + + // version number + moment.version = VERSION; + + // default format + moment.defaultFormat = isoFormat; + + // constant that refers to the ISO standard + moment.ISO_8601 = function () {}; + + // Plugins that add properties should also add the key here (null value), + // so we can properly clone ourselves. + moment.momentProperties = momentProperties; + + // This function will be called whenever a moment is mutated. + // It is intended to keep the offset in sync with the timezone. + moment.updateOffset = function () {}; + + // This function allows you to set a threshold for relative time strings + moment.relativeTimeThreshold = function (threshold, limit) { + if (relativeTimeThresholds[threshold] === undefined) { + return false; + } + if (limit === undefined) { + return relativeTimeThresholds[threshold]; + } + relativeTimeThresholds[threshold] = limit; + return true; + }; + + moment.lang = deprecate( + 'moment.lang is deprecated. Use moment.locale instead.', + function (key, value) { + return moment.locale(key, value); + } + ); + + // This function will load locale and then set the global locale. If + // no arguments are passed in, it will simply return the current global + // locale key. + moment.locale = function (key, values) { + var data; + if (key) { + if (typeof(values) !== 'undefined') { + data = moment.defineLocale(key, values); + } + else { + data = moment.localeData(key); + } + + if (data) { + moment.duration._locale = moment._locale = data; + } + } + + return moment._locale._abbr; + }; + + moment.defineLocale = function (name, values) { + if (values !== null) { + values.abbr = name; + if (!locales[name]) { + locales[name] = new Locale(); + } + locales[name].set(values); + + // backwards compat for now: also set the locale + moment.locale(name); + + return locales[name]; + } else { + // useful for testing + delete locales[name]; + return null; + } + }; + + moment.langData = deprecate( + 'moment.langData is deprecated. Use moment.localeData instead.', + function (key) { + return moment.localeData(key); + } + ); + + // returns locale data + moment.localeData = function (key) { + var locale; + + if (key && key._locale && key._locale._abbr) { + key = key._locale._abbr; + } + + if (!key) { + return moment._locale; + } + + if (!isArray(key)) { + //short-circuit everything else + locale = loadLocale(key); + if (locale) { + return locale; + } + key = [key]; + } + + return chooseLocale(key); + }; + + // compare moment object + moment.isMoment = function (obj) { + return obj instanceof Moment || + (obj != null && hasOwnProp(obj, '_isAMomentObject')); + }; + + // for typechecking Duration objects + moment.isDuration = function (obj) { + return obj instanceof Duration; + }; + + for (i = lists.length - 1; i >= 0; --i) { + makeList(lists[i]); + } + + moment.normalizeUnits = function (units) { + return normalizeUnits(units); + }; + + moment.invalid = function (flags) { + var m = moment.utc(NaN); + if (flags != null) { + extend(m._pf, flags); + } + else { + m._pf.userInvalidated = true; + } + + return m; + }; + + moment.parseZone = function () { + return moment.apply(null, arguments).parseZone(); + }; + + moment.parseTwoDigitYear = function (input) { + return toInt(input) + (toInt(input) > 68 ? 1900 : 2000); + }; + + /************************************ + Moment Prototype + ************************************/ + + + extend(moment.fn = Moment.prototype, { + + clone : function () { + return moment(this); + }, + + valueOf : function () { + return +this._d + ((this._offset || 0) * 60000); + }, + + unix : function () { + return Math.floor(+this / 1000); + }, + + toString : function () { + return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ'); + }, + + toDate : function () { + return this._offset ? new Date(+this) : this._d; + }, + + toISOString : function () { + var m = moment(this).utc(); + if (0 < m.year() && m.year() <= 9999) { + return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); + } else { + return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); + } + }, + + toArray : function () { + var m = this; + return [ + m.year(), + m.month(), + m.date(), + m.hours(), + m.minutes(), + m.seconds(), + m.milliseconds() + ]; + }, + + isValid : function () { + return isValid(this); + }, + + isDSTShifted : function () { + if (this._a) { + return this.isValid() && compareArrays(this._a, (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray()) > 0; + } + + return false; + }, + + parsingFlags : function () { + return extend({}, this._pf); + }, + + invalidAt: function () { + return this._pf.overflow; + }, + + utc : function (keepLocalTime) { + return this.zone(0, keepLocalTime); + }, + + local : function (keepLocalTime) { + if (this._isUTC) { + this.zone(0, keepLocalTime); + this._isUTC = false; + + if (keepLocalTime) { + this.add(this._dateTzOffset(), 'm'); + } + } + return this; + }, + + format : function (inputString) { + var output = formatMoment(this, inputString || moment.defaultFormat); + return this.localeData().postformat(output); + }, + + add : createAdder(1, 'add'), + + subtract : createAdder(-1, 'subtract'), + + diff : function (input, units, asFloat) { + var that = makeAs(input, this), + zoneDiff = (this.zone() - that.zone()) * 6e4, + diff, output, daysAdjust; + + units = normalizeUnits(units); + + if (units === 'year' || units === 'month') { + // average number of days in the months in the given dates + diff = (this.daysInMonth() + that.daysInMonth()) * 432e5; // 24 * 60 * 60 * 1000 / 2 + // difference in months + output = ((this.year() - that.year()) * 12) + (this.month() - that.month()); + // adjust by taking difference in days, average number of days + // and dst in the given months. + daysAdjust = (this - moment(this).startOf('month')) - + (that - moment(that).startOf('month')); + // same as above but with zones, to negate all dst + daysAdjust -= ((this.zone() - moment(this).startOf('month').zone()) - + (that.zone() - moment(that).startOf('month').zone())) * 6e4; + output += daysAdjust / diff; + if (units === 'year') { + output = output / 12; + } + } else { + diff = (this - that); + output = units === 'second' ? diff / 1e3 : // 1000 + units === 'minute' ? diff / 6e4 : // 1000 * 60 + units === 'hour' ? diff / 36e5 : // 1000 * 60 * 60 + units === 'day' ? (diff - zoneDiff) / 864e5 : // 1000 * 60 * 60 * 24, negate dst + units === 'week' ? (diff - zoneDiff) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst + diff; + } + return asFloat ? output : absRound(output); + }, + + from : function (time, withoutSuffix) { + return moment.duration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix); + }, + + fromNow : function (withoutSuffix) { + return this.from(moment(), withoutSuffix); + }, + + calendar : function (time) { + // We want to compare the start of today, vs this. + // Getting start-of-today depends on whether we're zone'd or not. + var now = time || moment(), + sod = makeAs(now, this).startOf('day'), + diff = this.diff(sod, 'days', true), + format = diff < -6 ? 'sameElse' : + diff < -1 ? 'lastWeek' : + diff < 0 ? 'lastDay' : + diff < 1 ? 'sameDay' : + diff < 2 ? 'nextDay' : + diff < 7 ? 'nextWeek' : 'sameElse'; + return this.format(this.localeData().calendar(format, this)); + }, + + isLeapYear : function () { + return isLeapYear(this.year()); + }, + + isDST : function () { + return (this.zone() < this.clone().month(0).zone() || + this.zone() < this.clone().month(5).zone()); + }, + + day : function (input) { + var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay(); + if (input != null) { + input = parseWeekday(input, this.localeData()); + return this.add(input - day, 'd'); + } else { + return day; + } + }, + + month : makeAccessor('Month', true), + + startOf : function (units) { + units = normalizeUnits(units); + // the following switch intentionally omits break keywords + // to utilize falling through the cases. + switch (units) { + case 'year': + this.month(0); + /* falls through */ + case 'quarter': + case 'month': + this.date(1); + /* falls through */ + case 'week': + case 'isoWeek': + case 'day': + this.hours(0); + /* falls through */ + case 'hour': + this.minutes(0); + /* falls through */ + case 'minute': + this.seconds(0); + /* falls through */ + case 'second': + this.milliseconds(0); + /* falls through */ + } + + // weeks are a special case + if (units === 'week') { + this.weekday(0); + } else if (units === 'isoWeek') { + this.isoWeekday(1); + } + + // quarters are also special + if (units === 'quarter') { + this.month(Math.floor(this.month() / 3) * 3); + } + + return this; + }, + + endOf: function (units) { + units = normalizeUnits(units); + return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms'); + }, + + isAfter: function (input, units) { + units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond'); + if (units === 'millisecond') { + input = moment.isMoment(input) ? input : moment(input); + return +this > +input; + } else { + return +this.clone().startOf(units) > +moment(input).startOf(units); + } + }, + + isBefore: function (input, units) { + units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond'); + if (units === 'millisecond') { + input = moment.isMoment(input) ? input : moment(input); + return +this < +input; + } else { + return +this.clone().startOf(units) < +moment(input).startOf(units); + } + }, + + isSame: function (input, units) { + units = normalizeUnits(units || 'millisecond'); + if (units === 'millisecond') { + input = moment.isMoment(input) ? input : moment(input); + return +this === +input; + } else { + return +this.clone().startOf(units) === +makeAs(input, this).startOf(units); + } + }, + + min: deprecate( + 'moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548', + function (other) { + other = moment.apply(null, arguments); + return other < this ? this : other; + } + ), + + max: deprecate( + 'moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548', + function (other) { + other = moment.apply(null, arguments); + return other > this ? this : other; + } + ), + + // keepLocalTime = true means only change the timezone, without + // affecting the local hour. So 5:31:26 +0300 --[zone(2, true)]--> + // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist int zone + // +0200, so we adjust the time as needed, to be valid. + // + // Keeping the time actually adds/subtracts (one hour) + // from the actual represented time. That is why we call updateOffset + // a second time. In case it wants us to change the offset again + // _changeInProgress == true case, then we have to adjust, because + // there is no such time in the given timezone. + zone : function (input, keepLocalTime) { + var offset = this._offset || 0, + localAdjust; + if (input != null) { + if (typeof input === 'string') { + input = timezoneMinutesFromString(input); + } + if (Math.abs(input) < 16) { + input = input * 60; + } + if (!this._isUTC && keepLocalTime) { + localAdjust = this._dateTzOffset(); + } + this._offset = input; + this._isUTC = true; + if (localAdjust != null) { + this.subtract(localAdjust, 'm'); + } + if (offset !== input) { + if (!keepLocalTime || this._changeInProgress) { + addOrSubtractDurationFromMoment(this, + moment.duration(offset - input, 'm'), 1, false); + } else if (!this._changeInProgress) { + this._changeInProgress = true; + moment.updateOffset(this, true); + this._changeInProgress = null; + } + } + } else { + return this._isUTC ? offset : this._dateTzOffset(); + } + return this; + }, + + zoneAbbr : function () { + return this._isUTC ? 'UTC' : ''; + }, + + zoneName : function () { + return this._isUTC ? 'Coordinated Universal Time' : ''; + }, + + parseZone : function () { + if (this._tzm) { + this.zone(this._tzm); + } else if (typeof this._i === 'string') { + this.zone(this._i); + } + return this; + }, + + hasAlignedHourOffset : function (input) { + if (!input) { + input = 0; + } + else { + input = moment(input).zone(); + } + + return (this.zone() - input) % 60 === 0; + }, + + daysInMonth : function () { + return daysInMonth(this.year(), this.month()); + }, + + dayOfYear : function (input) { + var dayOfYear = round((moment(this).startOf('day') - moment(this).startOf('year')) / 864e5) + 1; + return input == null ? dayOfYear : this.add((input - dayOfYear), 'd'); + }, + + quarter : function (input) { + return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3); + }, + + weekYear : function (input) { + var year = weekOfYear(this, this.localeData()._week.dow, this.localeData()._week.doy).year; + return input == null ? year : this.add((input - year), 'y'); + }, + + isoWeekYear : function (input) { + var year = weekOfYear(this, 1, 4).year; + return input == null ? year : this.add((input - year), 'y'); + }, + + week : function (input) { + var week = this.localeData().week(this); + return input == null ? week : this.add((input - week) * 7, 'd'); + }, + + isoWeek : function (input) { + var week = weekOfYear(this, 1, 4).week; + return input == null ? week : this.add((input - week) * 7, 'd'); + }, + + weekday : function (input) { + var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7; + return input == null ? weekday : this.add(input - weekday, 'd'); + }, + + isoWeekday : function (input) { + // behaves the same as moment#day except + // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6) + // as a setter, sunday should belong to the previous week. + return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7); + }, + + isoWeeksInYear : function () { + return weeksInYear(this.year(), 1, 4); + }, + + weeksInYear : function () { + var weekInfo = this.localeData()._week; + return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy); + }, + + get : function (units) { + units = normalizeUnits(units); + return this[units](); + }, + + set : function (units, value) { + units = normalizeUnits(units); + if (typeof this[units] === 'function') { + this[units](value); + } + return this; + }, + + // If passed a locale key, it will set the locale for this + // instance. Otherwise, it will return the locale configuration + // variables for this instance. + locale : function (key) { + var newLocaleData; + + if (key === undefined) { + return this._locale._abbr; + } else { + newLocaleData = moment.localeData(key); + if (newLocaleData != null) { + this._locale = newLocaleData; + } + return this; + } + }, + + lang : deprecate( + 'moment().lang() is deprecated. Use moment().localeData() instead.', + function (key) { + if (key === undefined) { + return this.localeData(); + } else { + return this.locale(key); + } + } + ), + + localeData : function () { + return this._locale; + }, + + _dateTzOffset : function () { + // On Firefox.24 Date#getTimezoneOffset returns a floating point. + // https://github.com/moment/moment/pull/1871 + return Math.round(this._d.getTimezoneOffset() / 15) * 15; + } + }); + + function rawMonthSetter(mom, value) { + var dayOfMonth; + + // TODO: Move this out of here! + if (typeof value === 'string') { + value = mom.localeData().monthsParse(value); + // TODO: Another silent failure? + if (typeof value !== 'number') { + return mom; + } + } + + dayOfMonth = Math.min(mom.date(), + daysInMonth(mom.year(), value)); + mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth); + return mom; + } + + function rawGetter(mom, unit) { + return mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit](); + } + + function rawSetter(mom, unit, value) { + if (unit === 'Month') { + return rawMonthSetter(mom, value); + } else { + return mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value); + } + } + + function makeAccessor(unit, keepTime) { + return function (value) { + if (value != null) { + rawSetter(this, unit, value); + moment.updateOffset(this, keepTime); + return this; + } else { + return rawGetter(this, unit); + } + }; + } + + moment.fn.millisecond = moment.fn.milliseconds = makeAccessor('Milliseconds', false); + moment.fn.second = moment.fn.seconds = makeAccessor('Seconds', false); + moment.fn.minute = moment.fn.minutes = makeAccessor('Minutes', false); + // Setting the hour should keep the time, because the user explicitly + // specified which hour he wants. So trying to maintain the same hour (in + // a new timezone) makes sense. Adding/subtracting hours does not follow + // this rule. + moment.fn.hour = moment.fn.hours = makeAccessor('Hours', true); + // moment.fn.month is defined separately + moment.fn.date = makeAccessor('Date', true); + moment.fn.dates = deprecate('dates accessor is deprecated. Use date instead.', makeAccessor('Date', true)); + moment.fn.year = makeAccessor('FullYear', true); + moment.fn.years = deprecate('years accessor is deprecated. Use year instead.', makeAccessor('FullYear', true)); + + // add plural methods + moment.fn.days = moment.fn.day; + moment.fn.months = moment.fn.month; + moment.fn.weeks = moment.fn.week; + moment.fn.isoWeeks = moment.fn.isoWeek; + moment.fn.quarters = moment.fn.quarter; + + // add aliased format methods + moment.fn.toJSON = moment.fn.toISOString; + + /************************************ + Duration Prototype + ************************************/ + + + function daysToYears (days) { + // 400 years have 146097 days (taking into account leap year rules) + return days * 400 / 146097; + } + + function yearsToDays (years) { + // years * 365 + absRound(years / 4) - + // absRound(years / 100) + absRound(years / 400); + return years * 146097 / 400; + } + + extend(moment.duration.fn = Duration.prototype, { + + _bubble : function () { + var milliseconds = this._milliseconds, + days = this._days, + months = this._months, + data = this._data, + seconds, minutes, hours, years = 0; + + // The following code bubbles up values, see the tests for + // examples of what that means. + data.milliseconds = milliseconds % 1000; + + seconds = absRound(milliseconds / 1000); + data.seconds = seconds % 60; + + minutes = absRound(seconds / 60); + data.minutes = minutes % 60; + + hours = absRound(minutes / 60); + data.hours = hours % 24; + + days += absRound(hours / 24); + + // Accurately convert days to years, assume start from year 0. + years = absRound(daysToYears(days)); + days -= absRound(yearsToDays(years)); + + // 30 days to a month + // TODO (iskren): Use anchor date (like 1st Jan) to compute this. + months += absRound(days / 30); + days %= 30; + + // 12 months -> 1 year + years += absRound(months / 12); + months %= 12; + + data.days = days; + data.months = months; + data.years = years; + }, + + abs : function () { + this._milliseconds = Math.abs(this._milliseconds); + this._days = Math.abs(this._days); + this._months = Math.abs(this._months); + + this._data.milliseconds = Math.abs(this._data.milliseconds); + this._data.seconds = Math.abs(this._data.seconds); + this._data.minutes = Math.abs(this._data.minutes); + this._data.hours = Math.abs(this._data.hours); + this._data.months = Math.abs(this._data.months); + this._data.years = Math.abs(this._data.years); + + return this; + }, + + weeks : function () { + return absRound(this.days() / 7); + }, + + valueOf : function () { + return this._milliseconds + + this._days * 864e5 + + (this._months % 12) * 2592e6 + + toInt(this._months / 12) * 31536e6; + }, + + humanize : function (withSuffix) { + var output = relativeTime(this, !withSuffix, this.localeData()); + + if (withSuffix) { + output = this.localeData().pastFuture(+this, output); + } + + return this.localeData().postformat(output); + }, + + add : function (input, val) { + // supports only 2.0-style add(1, 's') or add(moment) + var dur = moment.duration(input, val); + + this._milliseconds += dur._milliseconds; + this._days += dur._days; + this._months += dur._months; + + this._bubble(); + + return this; + }, + + subtract : function (input, val) { + var dur = moment.duration(input, val); + + this._milliseconds -= dur._milliseconds; + this._days -= dur._days; + this._months -= dur._months; + + this._bubble(); + + return this; + }, + + get : function (units) { + units = normalizeUnits(units); + return this[units.toLowerCase() + 's'](); + }, + + as : function (units) { + var days, months; + units = normalizeUnits(units); + + if (units === 'month' || units === 'year') { + days = this._days + this._milliseconds / 864e5; + months = this._months + daysToYears(days) * 12; + return units === 'month' ? months : months / 12; + } else { + // handle milliseconds separately because of floating point math errors (issue #1867) + days = this._days + yearsToDays(this._months / 12); + switch (units) { + case 'week': return days / 7 + this._milliseconds / 6048e5; + case 'day': return days + this._milliseconds / 864e5; + case 'hour': return days * 24 + this._milliseconds / 36e5; + case 'minute': return days * 24 * 60 + this._milliseconds / 6e4; + case 'second': return days * 24 * 60 * 60 + this._milliseconds / 1000; + // Math.floor prevents floating point math errors here + case 'millisecond': return Math.floor(days * 24 * 60 * 60 * 1000) + this._milliseconds; + default: throw new Error('Unknown unit ' + units); + } + } + }, + + lang : moment.fn.lang, + locale : moment.fn.locale, + + toIsoString : deprecate( + 'toIsoString() is deprecated. Please use toISOString() instead ' + + '(notice the capitals)', + function () { + return this.toISOString(); + } + ), + + toISOString : function () { + // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js + var years = Math.abs(this.years()), + months = Math.abs(this.months()), + days = Math.abs(this.days()), + hours = Math.abs(this.hours()), + minutes = Math.abs(this.minutes()), + seconds = Math.abs(this.seconds() + this.milliseconds() / 1000); + + if (!this.asSeconds()) { + // this is the same as C#'s (Noda) and python (isodate)... + // but not other JS (goog.date) + return 'P0D'; + } + + return (this.asSeconds() < 0 ? '-' : '') + + 'P' + + (years ? years + 'Y' : '') + + (months ? months + 'M' : '') + + (days ? days + 'D' : '') + + ((hours || minutes || seconds) ? 'T' : '') + + (hours ? hours + 'H' : '') + + (minutes ? minutes + 'M' : '') + + (seconds ? seconds + 'S' : ''); + }, + + localeData : function () { + return this._locale; + } + }); + + moment.duration.fn.toString = moment.duration.fn.toISOString; + + function makeDurationGetter(name) { + moment.duration.fn[name] = function () { + return this._data[name]; + }; + } + + for (i in unitMillisecondFactors) { + if (hasOwnProp(unitMillisecondFactors, i)) { + makeDurationGetter(i.toLowerCase()); + } + } + + moment.duration.fn.asMilliseconds = function () { + return this.as('ms'); + }; + moment.duration.fn.asSeconds = function () { + return this.as('s'); + }; + moment.duration.fn.asMinutes = function () { + return this.as('m'); + }; + moment.duration.fn.asHours = function () { + return this.as('h'); + }; + moment.duration.fn.asDays = function () { + return this.as('d'); + }; + moment.duration.fn.asWeeks = function () { + return this.as('weeks'); + }; + moment.duration.fn.asMonths = function () { + return this.as('M'); + }; + moment.duration.fn.asYears = function () { + return this.as('y'); + }; + + /************************************ + Default Locale + ************************************/ + + + // Set default locale, other locale will inherit from English. + moment.locale('en', { + ordinal : function (number) { + var b = number % 10, + output = (toInt(number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + } + }); + + /* EMBED_LOCALES */ + + /************************************ + Exposing Moment + ************************************/ + + function makeGlobal(shouldDeprecate) { + /*global ender:false */ + if (typeof ender !== 'undefined') { + return; + } + oldGlobalMoment = globalScope.moment; + if (shouldDeprecate) { + globalScope.moment = deprecate( + 'Accessing Moment through the global scope is ' + + 'deprecated, and will be removed in an upcoming ' + + 'release.', + moment); + } else { + globalScope.moment = moment; + } + } + + // CommonJS module is defined + if (hasModule) { + module.exports = moment; + } else if (typeof define === 'function' && define.amd) { + define('moment', function (require, exports, module) { + if (module.config && module.config() && module.config().noGlobal === true) { + // release the global variable + globalScope.moment = oldGlobalMoment; + } + + return moment; + }); + makeGlobal(true); + } else { + makeGlobal(); + } +}).call(this); \ No newline at end of file diff --git a/lang/bg.php b/lang/bg.php new file mode 100644 index 0000000..e901f7e --- /dev/null +++ b/lang/bg.php @@ -0,0 +1,16 @@ + \ No newline at end of file diff --git a/lang/bg.txt b/lang/bg.txt new file mode 100644 index 0000000..e4963b3 --- /dev/null +++ b/lang/bg.txt @@ -0,0 +1,64 @@ +[name] +MODULE_NAME = "Универсальный календарь событий" +MODULE_DESCRIPTION = "
            Модуль позволяет создавать различные календари событий.
            Для вывода календаря используйте системный тег [mod_unicalendar:XXX]" + +[admin] +ModName = "Управление модул Unicalendar" +ModTitle = "В този раздел е списъка на всички календари.
            Както и да създадете нов календар." +UCA_LIST = "Списък календари" +UCA_NEW = "Създаване на нов календар" +UCA_NO_ITEMS = "Не е създаден нито един календар." +UCA_TITLE = "Наименование календар" +UCA_EVENTS = "Събития в календара" +UCA_EVENTS_SELECT = "Изберете типа на събитията в календара" +UCA_EVENTS_SELECT_A = "Всички документи от избраната рубрика" +UCA_EVENTS_SELECT_AC = "Избор на рубрика" +UCA_EVENTS_SELECT_DOC = "Маркирай за избора" +UCA_EVENTS_SELECT_B = "Избрани документи от дадената рубрика" +UCA_EVENTS_SELECT_C = "Избрани документи без свързване с рубрика" +UCA_BTN_CREATE = "Създаване" +UCA_CP_TAG = "Таг в системата" +UCA_COPY_BUFF = "Копирай тага в буфера" +UCA_ACTIONS = "Действия" +UCA_DELETE_UNICLN_A = "Сигурни ли сте, че желаете да изтриете този календар?" +UCA_LIST_ALLDOC_RUB = "Извежда всички документи от рубриката" +UCA_LIST_SELDOC_RUB = "Извежда всички документи от рубрика " +UCA_TITLE_WARNING = "Не е попълнено поле Наименование на календар" +UCA_EVENTS_WARNING = "Не са зададени събития за този календар..." +UCA_SEL_RUB_WARNING = "Не е избрана рубрика!" +UCA_SEL_DOC_WARNING = "Не е избран нито един документ!" +UCA_SEL_EVENTS_WARNING = "Не е избран типа на събитията за календара!" +UCA_OPEN_LIKS = "Събитията в календара се отварят в нов прозорец" +UCA_YES = "Да" +UCA_NO = "Не" +UCA_WEEK_START = "Показва началото на седмицата в календара" +UCA_WEEK_START_MONDAY = "От понеделник" +UCA_WEEK_START_SUNDAY = "От неделя" +UCA_SCROLL_BAR = "Включить полосу прокрутки в событиях" +UCA_DESCRIPTION = "Отвори съдържанието на всички събития веднана след зареждане" +UCA_EDIT = "Редактиране" +UCA_DELETE = "Изтриване" +UCA_EDIT_CALEND = "Редактиране на календара " +UCA_EDIT_INFO = "В този раздел вие може да редактирате календара" +UCA_ID = "Id = " +UCA_CHANGE_RUBRIC = "Смяна на рубрика" +UCA_SAVE_EDIT = "Запази промените" +UCA_ALERT_SAVE_EDIT = "Календар " +UCA_ALERT_SAVE_EDIT_S = "Промените са успешно записани" +UCA_ALERT_SAVE_EDIT_E = "Грешка при предаване на данните" +UCA_SET_CALENDAR = "Параметри на календара" +UCA_RETURN_LIST = "Връщане към списъка с календари" +UCA_ABLE_EDIT_DOC = "Отметьте или снимите уже отмеченные чекбоксы для выбора необходимых документов из списка для вывода их в календаре" +UCA_DISABLE_START_EDIT = "Действия с единственным выбранным документом заблокированы, для снятия блокировки, активируйте чекбоксы других документов" +UCA_REFRECH_DOC_RUBRIC = "Обновяване на списъка документи от рубрика " +UCA_ID_INF = "Id" +UCA_TITLE_INF = "Наименование на документ" +UCA_DATE_INF = "Дата на създаване" +UCA_SELECT_ALL_INF = "Марк./Разм. на всички чекбокса" +UCA_RELEV = "Актуалност" +UCA_ALERT_RELEV_YES = "Ок - данните на календара са актуални" +UCA_ALERT_RELEV_BAD = "Внимание - събитията в календара не са актуални! В момента на създаването на календара броят на документите в рубриката са билиповече на брой, отколкото в момента - т.с календара съдържа събития водещи към страници с грешка 404! За да отстраните грешката запишете/редактирайте календара!
            ОТЧЕТ:
            В рубриката :
            " +UCA_ALERT_RELEV_WAR = "Предупреждение - събитията в календара са неактуални! В момента на създаване на календара в рубриката е имало по-малко документи, отколкото в момента. За да актуализирате календара - направете минете през запис на календара." +UCA_ALERT_RELEV_BAD_SD = "Внимание - събитията в календара не са актуални! В момента на създаването на календара са били избрани документи, които в текущия момент не съществуват в рубриката - т.с календара съдържа събития, водещи към страница с грешка 404! За да отстраните - съхранете/редактирайте календара!
            ОТЧЕТ:
            В рубрика :
            " +UCA_ALERT_RELEV_BAD_SE = ",
            документ(и) с
            Id = " +UCA_ALERT_RELEV_BAD_SF = "  не е открит(и) !" \ No newline at end of file diff --git a/lang/index.php b/lang/index.php new file mode 100644 index 0000000..4ca25aa --- /dev/null +++ b/lang/index.php @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/lang/ru.php b/lang/ru.php new file mode 100644 index 0000000..04491ed --- /dev/null +++ b/lang/ru.php @@ -0,0 +1,16 @@ + \ No newline at end of file diff --git a/lang/ru.txt b/lang/ru.txt new file mode 100644 index 0000000..dd3c9d3 --- /dev/null +++ b/lang/ru.txt @@ -0,0 +1,82 @@ +[name] +MODULE_NAME = "Универсальный календарь событий" +MODULE_DESCRIPTION = "
            Модуль позволяет создавать различные календари событий.
            Для вывода календаря используйте системный тег [mod_unicalendar:XXX]" + +[admin] +ModName = "Управление модулем Unicalendar" +ModTitle = "В данном разделе находится список всех календарей.
            Так же, вы можете создать новый календарь.
            Внимание!
            Вы не можете создать календарь, если рубрика содержит:
            a) только два документа - Главная и Ошибка 404
            b) только один документ: или Главная или Ошибка 404
            В остальных случаях документы Главная страница и Ошибка 404 не будут выводиться при создании календарей." +UCA_LIST = "Список календарей" +UCA_NEW = "Создать новый календарь" +UCA_NO_ITEMS = "В настоящий момент не существует ни одного календаря." +UCA_TITLE = "Название календаря" +UCA_EVENTS = "События календаря" +UCA_EVENTS_SELECT = "Выберите тип событий календаря" +UCA_EVENTS_SELECT_A = "Все документы из заданной рубрики" +UCA_EVENTS_SELECT_AC = "Выбор рубрики" +UCA_EVENTS_SELECT_DOC = "Отметить для выбора" +UCA_EVENTS_SELECT_B = "Выбранные документы из заданной рубрики" +UCA_EVENTS_SELECT_C = "Выбранные документы без привязки к рубрикам" +UCA_BTN_CREATE = "Создать" +UCA_CP_TAG = "Тег в системе" +UCA_COPY_BUFF = "Скопировать тег в буфер обмена" +UCA_ACTIONS = "Действия" +UCA_DELETE_UNICLN_A = "Вы уверены, что хотите удалить этот календарь?" +UCA_LIST_ALLDOC_RUB = "Выводит все документы из рубрики " +UCA_LIST_SELDOC_RUB = "Выводит выбранные документы из рубрики " +UCA_TITLE_WARNING = "Не заполнено поле Название календаря" +UCA_EVENTS_WARNING = "События для этого календаря не заданы..." +UCA_SEL_RUB_WARNING = "Не выбрана рубрика!" +UCA_SEL_RUB_ID_DOC = "Вы не можете создать календарь из рубрики, которая либо содержит только два документа: Главная и Ошибка 404, либо только один документ: или Главная или Ошибка 404" +UCA_SEL_DOC_WARNING = "Не выбран ни один документ!" +UCA_SEL_EVENTS_WARNING = "Не выбран тип событий календаря!" +UCA_PUBLIC_DATE = "Формат даты публичной части календаря" +UCA_OPEN_LIKS = "Открывать ссылки событий календаря в новом окне" +UCA_YES = "Да" +UCA_NO = "Нет" +UCA_WEEK_START = "Отображать начало недели в календаре" +UCA_WEEK_START_MONDAY = "С понедельника" +UCA_WEEK_START_SUNDAY = "С воскресенья" +UCA_SCROLL_BAR = "Включить полосу прокрутки в событиях" +UCA_DESCRIPTION = "Раскрывать содержимое всех событий сразу после загрузки" +UCA_EVENTS_LIMIT = "Лимит вывода событий при перелистывании месяцев" +UCA_EDIT = "Редактировать" +UCA_DELETE = "Удалить" +UCA_EDIT_CALEND = "Редактирование календаря " +UCA_EDIT_INFO = "В данном разделе вы можете отредактировать календарь" +UCA_ID = "Id = " +UCA_CHANGE_RUBRIC = "Сменить рубрику" +UCA_SAVE_EDIT = "Сохранить изменения" +UCA_ALERT_SAVE_EDIT = "Календарь " +UCA_ALERT_SAVE_EDIT_S = "Изменения успешного сохранены" +UCA_ALERT_SAVE_EDIT_E = "Ошибка передачи данных" +UCA_SET_CALENDAR = "Параметры календаря" +UCA_RETURN_LIST = "Венуться к списку календарей" +UCA_ABLE_EDIT_DOC = "Отметьте или снимите уже отмеченные чекбоксы для выбора необходимых документов из списка для вывода их в календаре" +UCA_DISABLE_START_EDIT = "Действия с единственным выбранным документом заблокированы, для снятия блокировки, активируйте чекбоксы других документов" +UCA_REFRECH_DOC_RUBRIC = "Обновить список документов из рубрики " +UCA_ID_INF = "Id" +UCA_TITLE_INF = "Название документа" +UCA_DATE_INF = "Дата создания" +UCA_DATE_EXPIRE = "Дата истечения" +UCA_SELECT_ALL_INF = "Выбрать все" +UCA_SELECT_ALL_INF_CH = "± чекбоксы" +UCA_RELEV = "Актуальность" +UCA_ALERT_RELEV_YES = "Ок - данные календаря актуальны" +UCA_ALERT_RELEV_BAD = "Внимание - события в календаре неактуальны! На момент создания календаря документов в рубрике было больше, чем на текущий момент, это приводит к тому, что календарь содержит события, ведущие на страницу с ошибкой 404! Для устранения - пересохраните/отредактируйте календарь!
            ОТЧЕТ:
            В рубрике :
            " +UCA_ALERT_RELEV_WAR = "Предупреждение - события в календаре неактуальны! На момент создания календаря документов в рубрике было меньше, чем на текущий момент. Для устранения - пересохраните календарь." +UCA_ALERT_RELEV_BAD_SD = "Внимание - события в календаре неактуальны! На момент создания календаря был(и) выбран(ы) документ(ы), которые(ых) на текущий момент не существует в рубрике. Это приводит к тому, что календарь содержит события, ведущие на страницу с ошибкой 404! Для устранения - пересохраните/отредактируйте календарь!
            ОТЧЕТ:
            В рубрике :
            " +UCA_ALERT_RELEV_BAD_SE = ",
            документ(ы) с
            Id = " +UCA_ALERT_RELEV_BAD_SF = "  не найден(ы) !" +UCA_SEL_FIELD_BTN = "Выбрать" +UCA_SEL_FIELD_DATA_INF = "Выбор полей для создания тизера события" +UCA_SEL_FIELD_DATA_TTL = "Название события" +UCA_SEL_FIELD_TTL = "Аналогично названию документа (тег < title >)" +UCA_SEL_FIELD_H_IMG = "Изображение Изображение (Одиночное)\'> " +UCA_SEL_FIELD_IMG = "Выбрать поле" +UCA_SEL_FIELD_DATA_DSC = "Описание события Предупреждение:
            Все HTML теги (если они присутствуют в поле) будут вырезаны (естественно только в календаре), в тизере будет выведено не более 255 символов.\'> 
            " +UCA_SEL_FIELD_DSC = "Выбрать поле" +UCA_SEL_FIELD_DATA_PLW = "Место события Все HTML теги (если они присутствуют в поле) будут вырезаны (естественно только в календаре).
            Eсли вы не планируете указывать место, оставьте это значение пустым (не выбирайте никакого поля).\'> 
            " +UCA_SEL_FIELD_PLC = "Выбрать поле" +UCA_SEL_FIELD_DATA_STR = "Начало события" +UCA_SEL_FIELD_DATA_END = "Завершение события" +UCA_SEL_FIELD_SDOC = "Задано документом" diff --git a/module.php b/module.php new file mode 100644 index 0000000..e0d016b --- /dev/null +++ b/module.php @@ -0,0 +1,79 @@ +config_load($lang_file); + + $unicalendar->unicalendarShow($tpl_dir, $id); +} + +/** + * Админка + */ + +if (defined('ACP') && (isset($_REQUEST['moduleaction']))) +{ + // класс + require_once(BASE_DIR . '/modules/unicalendar/class/unicalendar.php'); + $unicalendar = new Unicalendar; + + // папка с шаблонами + $tpl_dir = BASE_DIR . '/modules/unicalendar/templates/'; + + // ленги + $AVE_Template->config_load(BASE_DIR . '/modules/unicalendar/lang/' . $_SESSION['admin_language'] . '.txt', 'admin'); + $AVE_Template->assign('config_vars', $AVE_Template->get_config_vars()); + + switch($_REQUEST['moduleaction']) + { + case '1': // Просмотр списка календарей + $unicalendar->unicalendarList($tpl_dir); + break; + case 'new': // Создать новый календарь + $unicalendar->unicalendarNew(); + break; + case 'events_new': // Выбор событий календаря + $unicalendar->unicalendarEventsNew(); + break; + case 'edit': // Редактировать календарь + $unicalendar->unicalendarEdit($tpl_dir, intval($_REQUEST['id'])); + break; + case 'edit_save': // Сохранение календаря после редактирования + $unicalendar->unicalendarEditSave(intval($_REQUEST['id'])); + break; + case 'delunicalendar': // Удаление календаря + $unicalendar->unicalendarDelete(intval($_REQUEST['id'])); + break; + } +} + // проверяем на наличие файла uca.res.php и если файл существует - удаляем его, начиная с версии >= v1.1.3 он не нужен + if (file_exists(BASE_DIR . '/modules/unicalendar/uca.res.php')) unlink(BASE_DIR . '/modules/unicalendar/uca.res.php'); + +?> \ No newline at end of file diff --git a/sql.php b/sql.php new file mode 100644 index 0000000..facd4c6 --- /dev/null +++ b/sql.php @@ -0,0 +1,90 @@ + \ No newline at end of file diff --git a/templates/admin_unicalendar_edit.tpl b/templates/admin_unicalendar_edit.tpl new file mode 100644 index 0000000..e932024 --- /dev/null +++ b/templates/admin_unicalendar_edit.tpl @@ -0,0 +1,584 @@ +
            {#ModName#}
            +
            +
            +
              +
            • {#UCA_EDIT_INFO#}
            • +
            +
            +
            + +{foreach from=$unicalendars item=unicalendars} +
            +
            +
            {#UCA_EDIT_CALEND#} - {$unicalendars.uca_title|escape}
            +
            +
            +
              +
            • {#UCA_SET_CALENDAR#}
            • +
            • {#UCA_ID#}  {$unicalendars.id}      {#UCA_EVENTS#} =   {if $unicalendars.uca_events == 1}{#UCA_LIST_ALLDOC_RUB#}   {$unicalendars.uca_rubric_title|escape}{elseif $unicalendars.uca_events == 2}{#UCA_LIST_SELDOC_RUB#}   {$unicalendars.uca_rubric_title|escape}{/if}
            • +
            +
            +
            + {if $unicalendars.uca_events == 1} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
            {#UCA_TITLE#} + +
            {#UCA_PUBLIC_DATE#} + + + + + + + + + + + + + +
            {#UCA_OPEN_LIKS#} + + + + + +
            {#UCA_WEEK_START#} + + + + + +
            {#UCA_SCROLL_BAR#} + + + + + +
            {#UCA_DESCRIPTION#} + + + + + +
            {#UCA_EVENTS_LIMIT#} + +
            {#UCA_EVENTS#}
            + + + {#UCA_LIST_ALLDOC_RUB#} {$unicalendars.uca_rubric_title|escape}      + {#UCA_CHANGE_RUBRIC#} +
            + +
            + + + + + +
            + +
            + {/if} + + {if $unicalendars.uca_events == 2} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
            + + +
            {#UCA_TITLE#} + +
            {#UCA_PUBLIC_DATE#} + + + + + + + + + + + + + +
            {#UCA_OPEN_LIKS#} + + + + + +
            {#UCA_WEEK_START#} + + + + + +
            {#UCA_SCROLL_BAR#} + + + + + +
            {#UCA_DESCRIPTION#} + + + + + +
            {#UCA_EVENTS_LIMIT#} + +
            {#UCA_EVENTS#}
            + + + {#UCA_LIST_SELDOC_RUB#} {$unicalendars.uca_rubric_title|escape}      + {*{#UCA_CHANGE_RUBRIC#}*} +
            + +
            + + + + + + + + + + + + + + + + + + + + + + + + {foreach from=$unidocs item=unidocs} + + + + + + + + {/foreach} + + +
            {#UCA_EVENTS_SELECT_DOC#}{#UCA_ID_INF#}{#UCA_TITLE_INF#}{#UCA_DATE_INF#}{#UCA_DATE_EXPIRE#}
            +
            +
            {$unidocs.Id}{$unidocs.document_title}{$unidocs.document_published|date_format:$TIME_FORMAT|pretty_date}{$unidocs.document_expire|date_format:$TIME_FORMAT|pretty_date}
            + + + + + +
            + +
            + {/if} + +{/foreach} + + \ No newline at end of file diff --git a/templates/admin_unicalendar_list.tpl b/templates/admin_unicalendar_list.tpl new file mode 100644 index 0000000..8c57723 --- /dev/null +++ b/templates/admin_unicalendar_list.tpl @@ -0,0 +1,636 @@ +
            {#ModName#}
            +
            +
            +
              +
            • {#ModTitle#}
            • +
            +
            +
            + +{if $page_nav} + +{/if} +
            + +
            +
            +
            + + + + + + + + + + + + + + + + + + + + + + + {foreach from=$unicalendars item=unicalendar} + + + + + + + + + + + {/foreach} + {if !$unicalendars} + + + + {/if} + + +
            Id{#UCA_TITLE#}{#UCA_EVENTS#}{#UCA_RELEV#}{#UCA_CP_TAG#}{#UCA_ACTIONS#}
            + {$unicalendar.id} + + {$unicalendar.uca_title|escape} + +
            + {if $unicalendar.uca_events == 1}{#UCA_LIST_ALLDOC_RUB#}  {$unicalendar.uca_rubric_title|escape} + {elseif $unicalendar.uca_events == 2}{#UCA_LIST_SELDOC_RUB#}  {$unicalendar.uca_rubric_title|escape} + {else}{#UCA_EVENTS_WARNING#} + {/if} +
            +
            + {* + *} +
            +
            +
            + + + +
            +
            + {#UCA_EDIT#} + + {#UCA_DELETE#} +
            +
              +
            • {#UCA_NO_ITEMS#}
            • +
            +
            + +
            + +
            +
            +
            +{if $page_nav} + +{/if} + \ No newline at end of file diff --git a/templates/index.php b/templates/index.php new file mode 100644 index 0000000..4ca25aa --- /dev/null +++ b/templates/index.php @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/templates/unicalendar.tpl b/templates/unicalendar.tpl new file mode 100644 index 0000000..1bf22c7 --- /dev/null +++ b/templates/unicalendar.tpl @@ -0,0 +1 @@ +