MODx — собственный ajax календарь событий/новостей 2

    Выходные проходят сложно для моего здоровья, но я таки смог переписать свой календарь событий для ModX.

    Напомню, сниппет берет события из указанной директории MODx и генерирует календарь с событиями по дням, которые отображаются при наведении на нужный день.

    В чем же отличия от предыдущей версии?
    Самое главное — календарь отрисовывается не сторонним плагином jquery.datepicker, а php. К каждой ячейка прикрепляются css классы, в зависимости от их свойств. Все классы, имена дней недели, месяцы задаются в параметрах сниппета, что позволяет их легко менять.

    Картинка, для привлечения внимания.


    Оформление


    Итак, сгенерированный календарь имеет следующую html структуру:
    <div id='Calendar'>
        <table class='calendar'>
    		<tr>
                <td class='prev' name='номер пред.месяца-год'>пред месяц</td>
            	<td class='month' colspan='5'>Месяц год</td>
            	<td class='next' name='номер след.месяца-год'>след месяц</td>
            </tr>
            <tr>
            	<th class='dow'>День недели</th>
            </tr>
            <tr>
            	<td class='weekend isevent' id='calendar_1'>
                	    <div class='date'>Дата</div>
                        <div class='event'>Событие<div>
                </td>
            </tr>
        </table>
    </div>
    

    Как вы видите, событие находится в одной ячейке с датой и имеет собственный класс. Поэтому, его можно легко скрывать и отображать с помощью css.

    Почти без оформления, со скрытыми событиями, календарь выглядит так:


    Каждая ячейка таблицы, в зависимости от разных параметров снабжается классом css. Это вторая особенность календаря — внешний вид можно менять как угодно, а имена классов задаются в параметрах сниппета.

    Пора рассказать, какие классы используются по умолчанию:
    .calendar - Таблица с календарем
    .dow - Ячейка с именем дня недели
    .month - Ячейка с именем месяца и годом
    .workday - Рабочие дни
    .weekend - Выходные
    .today - Сегодня
    .isevent - Ячейка с событием
    .noevent - Ячейка без события
    .event - div  с событием
    .date - div с датой
    .emptyday - Пустая ячейка, без даты
    .prev - Кнопка перехода на следующий месяц
    .next - Кнопка перехода на предыдущий месяц
    

    Таким образом, вы можете легко настраивать календарь, присваивая этим классам нужное оформление. Хотите выделить выходные дни — просто сделайте им другой цвет, например красный. Месяц и дни недели можно сделать пожирнее, дни с событиями — синие, сегодняшний день — желтым.
    И получится примерно так:

    Красота!

    Для отображения скрытых дивов можно использовать qTip. Лучше обойтись без него.
            $('.isevent').live('mouseover',function() {
                id = this.id;
                $('#' + id + ' .event').show();
            })
            $('.isevent').live('mouseout',function() {
                id = this.id;
                $('#' + id + ' .event').hide();
            }) 
    

        .isevent {
            color: black;
            text-align: left;
            position:absolute;
            z-index: 10;
            display: none;
            background: #fff;
            border: 1px solid #AAA;
            padding: 5px;
            width: 250px;
            margin-top: -10px;
            margin-left: 10px;
        }
    

    Вот что получится:


    Див скрыт, при наведении на ячейку он отображается, а все оформление в css. Главное — position: absolute и z-index: 10.
    Все легко и просто.

    Сниппет


    Код сниппета я приводить не буду, зато я приведу все параметры и плейсхолдеры.

    Параметры

    &id
    	по умолчанию: нет, но обязателен
    	значение: [int]
    	описание: id существующего документа-контейнера MODx для выборки событий
    &month
    	по умолчанию: date('m')
    	значение: [int]
    	описание: Месяц для показа событий
    &year
    	по умолчанию: date('Y')
    	значение: [int]
    	описание: Год для показа событий
    &dateTV
    	по умолчанию: event_date
    	значение: [string]
    	описание: Имя существующего TV параметра для определения даты события
    &dateFormat
    	по умолчанию: '%d %b %Y %H:%M'
    	значение: [string]
    	описание: Формат даты, используется strftime()
    &tplEvent
    	по умолчанию: tplEvent
    	значение: [string]
    	описание: Имя существующего чанка MODx
    &tplMain
    	по умолчанию: tplCalendar
    	значение: [string]
    	описание: Имя существующего чанка MODx
    &calendar_id
    	по умолчанию: Calendar
    	значение: [string]
    	описание: Имя уникального идентификатора экземпляра календаря. Необходимо, если вызывается более одного календаря на странице
    &class_calendar
    	по умолчанию: calendar
    	значение: [string]
    	описание: Имя css класса для оформления таблицы календаря
    &class_dow
    	по умолчанию: dow
    	значение: [string]
    	описание: Имя css класса для оформления дней недели
    &class_month
    	по умолчанию: month
    	значение: [string]
    	описание: Имя css класса для оформления месяца и года
    &class_workday
    	по умолчанию: workday
    	значение: [string]
    	описание: Имя css класса для оформления рабочих дней
    &class_weekend
    	по умолчанию: weekend
    	значение: [string]
    	описание: Имя css класса для оформления выходных
    &class_today
    	по умолчанию: today
    	значение: [string]
    	описание: Имя css класса для оформления сегодня
    &class_event
    	по умолчанию: event
    	значение: [string]
    	описание: Имя css класса для оформления div с событием
    &class_isevent
    	по умолчанию: isevent
    	значение: [string]
    	описание: Имя css класса для оформления ячейки таблицы с событием
    &class_noevent
    	по умолчанию: noevent
    	значение: [string]
    	описание: Имя css класса для оформления ячейки таблицы без события
    &class_date
    	по умолчанию: date
    	значение: [string]
    	описание: Имя css класса для оформления даты календаря
    &class_emptyday
    	по умолчанию: emptyday
    	значение: [string]
    	описание: Имя css класса для оформления пустой ячейки, без даты
    &class_prev
    	по умолчанию: prev
    	значение: [string]
    	описание: Имя css класса для оформления кнопки перехода на предыдущий месяц
    &class_next
    	по умолчанию: next
    	значение: [string]
    	описание: Имя css класса для оформления кнопки перехода на следующий месяц
    
    &dow_names
    	по умолчанию: Зависит от &lang
    	значение: [string]
    	описание: Строка с сокращенными названиями дней недели, через запятую, без пробелов. Переопределит стандартную, для выбранного языка. 
    &month_names
    	по умолчанию: Зависит от &lang
    	значение: [string]
    	описание: Строка с названиями месяцев, через запятую, без пробелов. Переопределит стандартную, для выбранного языка.
    &btn_prev
    	по умолчанию: '«'
    	значение: [string]
    	описание: Текст кнопки перехода на предыдущий месяц
    &btn_next
    	по умолчанию: '»'
    	значение: [string]
    	описание: Текст кнопки перехода на следующий месяц
    
    &lang
    	по умолчанию: 'en'
    	значение: [en,ru]
    	описание: Язык для оформления календаря и вывода ошибок
    &show_errors
    	по умолчанию: 1
    	значение: [0|1]
    	описание: Показывать ошибки, по умолчанию - да
    &first_day
    	по умолчанию: 0
    	значение: [0|1]
    	описание: 0 - первый день - воскресенье. 1 - первый день - понедельник.
    


    Плейсхолдеры

    В сниппете используются служебные плейсхолдеры с именами классов css для оформления, менять их можно через параметры, которые я описал выше. Эти холдеры трогать не нужно.
    [+ec.Calendar+]
    	Экземпляр календаря, то есть таблица с датами
    [+ec.calendar_id+]
    	Уникальный идентификатор экземпляра календаря
    [+ec.class_calendar+]
    	css класс таблицы с календарем
    [+ec.class_dow+]
    	css класс дней недели
    [+ec.class_month+]
    	css класс месяца и года
    [+ec.class_workday+]
    	css класс рабочих дней
    [+ec.class_weekend+]
    	css класс выходных
    [+ec.class_today+]
    	css класс сегодня
    [+ec.class_event+]
    	css класс события
    [+ec.class_isevent+]
    	css класс ячейки с событием
    [+ec.class_noevent+]
    	css класс ячейки без события
    [+ec.class_date+]
    	css класс даты
    [+ec.class_emptyday+]
    	css класс пустой ячейки
    [+ec.class_prev+]
    	css класс кнопки предыдущего месяца
    [+ec.class_next+]
    	css класс  кнопки следующего месяца
    

    А также есть плейсходеры, для подстановки значений событий:
    [+ec.num+]
    	Номер события в дне. Актуально, только если у вас больше одного события в день. Для правильной нумерации необходимо, чтобы параметр даты публикации документа совпадал с TV параметром даты события. Иначе, нумерация может быть неверной.
    [+ec.date+]
    	Дата события.
    [+ec.url+]
    	Ссылка на событие.
    [+ec.title+]
    	Заголовок, берется из pagetitle документа MODx.
    [+ec.desc+]
    	Краткое описание, берется из introtext документа MODx.
    


    Теперь качаем архив и распаковываем. Создаем в админке MODx сниппет eventsCalendar2, в него копируем содержимое файла eventsCalendar2.snippet.php.
    Создаем два чанка, tplEvent2 и tplCalendar2, это eventsCalendar2.tplEvent.html и eventsCalendar.tplCalendar2.html соответственно.

    Создаем новый документ MODx и вызываем сниппет:
    [!eventsCalendar2?
        &id=`13`
        &calendar_id=`Cal1`
        &dateTV=`event_date`
        &dateFormat=`%d %b %Y %H:%M`
        &tplEvent=`tplEvent2`
        &tplMain=`tplCalendar2`
    !]
    

    Не забудьте, у вас на странице должен быть подключен qTip!

    Если хотите перевести календарь на английский — меняйте параметры названия дней и месяцев. Также, можно вызывать несколько календарей на одной странице — нужно только казать каждому свой &calendar_id.

    В чанке tplCalendar2 содержится все оформление календаря, можно менять как душе угодно, только не тройгайте названия плейсхолдеров!

    Недостатков предыдущего календаря теперь нет. Все работает шустро и гладко. Иногда может прогнать qTip и перестать показывать всплывашки — но это не моя вина. В принципе, скрытые дивы можно отображать и без него, методик полно.

    Если будут вопросы и пожелания — не стесняйтесь пишите, если что — дополню топик.
    Багрепорты пока постим сюда, если календарь понравится пользователям — отправим его в репозиторий MODx.

    Скачать архив со сниппетом и чанками.

    Посмотреть календарь в работе (версия для Revolution).

    UPD.
    Избавился от qTip, обновил топик и архив со сниппетом.

    UPD.2
    Добавил английский язык. Добавил 3 параметра: &lang, &first_day, &show_errors. Обновил описание параметров, залил новую версию сниппета.

    UPD.3
    Генерируемый код приведен в соответствие со стандартами W3C и проходит валидатор.
    Добавил в архив readme.html.
    Обновил ссылку в топике.

    UPD.4
    События теперь выбираются только для нужного месяца, что существеннно снижает нагрузку на систему.
    Добавлена возможность использовать в шаблонах любые TV параметры и свойства ресурсов.
    Добавлен параметр сдвига времени в часах &time_shift, для тех сайтов, где временная зона не совпадает с хостингом.
    Дефолтные настройки установлены для России. Неделя начинается в понедельник, язык русский.
    Изменен чанк tplEvent2, в соответствии с новыми плейсхолдерами.

    Проект уехал на code.google.com. Дальнейшее развитие будет там.


    UPD.5
    Переделал для Revolution, можно скачать на ГуглоКоде.
    Поделиться публикацией

    Похожие публикации

    Комментарии 20

      +1
      Я читаю новости за 1ое число, потом хочу прочитать за 5ое. При наведении курсора мышки на пятое число новости за первое не закрываются, за пятое не открываются. Это тоже не ошибка?
        0
        Это фокусы qTip. Он отвечает за всплывание. Видимо, надо его на что-то поменять.
          0
          Убрал эффект при появлении (effect: {length: 0}), глюки вроде пропали. Выглядит похуже, но работает лучше.

           $('.isevent').each(function() {
                  id = this.id; 
                  $(this).qtip({ 
                      content: $('#' + id + ' .event').html(),
                      show: {when: {event: 'mouseover'}, effect: {length: 0}, solo: true},
                      hide: {when: {event: 'unfocus'}, effect: {length: 0}}
                  }); 
              });
          
            0
            Сейчас работает значительно лучше, но при переходе с 3его на 4ое число опять ничего не меняется.
              0
              Выкинул qTip, топик сейчас обновлю.
                +1
                Вот теперь без qTip все работает отлично и быстро. Спасибо)
                  0
                  Очень рад. На здоровье!
          0
          Закончился срок хранения файла. Файл удален с сервиса.
            0
            Моя вина. В топике было 2 разных ссылки на одно и то же, поправил.

            Спасибо за информацию!
              0
              Проект переехал на code.google.com
              0
              При перелистывании месяцев и последующем наведении на активную дату, описания событий выводятся в неправильной кодировке.
              Не подскажете в чём дело?
                0
                А у вас поди БД в кодировке cp1251?
                jquery передает ajax только в utf-8. Пожтому нужно перекодировать данные перед возвратом.

                Кажется, нужно просто в функции getEvents() поменять строчку в конце
                return $dates;
                на
                 return iconv('utf8', 'cp1251', $dates);


                Проблема старая и известная, сделаю настройку перекодировки в сниппете в следующей версии.
                  0
                  В том-то и дело, что использую только utf-8.

                  Соответственно предложенный метод не помогает.
                    0
                    Других вариантов то нет. Раз не та кодировка приходит — значит что-то не так с кодировкой. Еще варианты?

                    Пришлите адрес сайта, где посмотреть вашу проблему можно. Мож у вас заголовки не те сервер отдает.
                      0
                        0
                        Ну явно не та кодировка. Проверяйте свою БД, соединение с ней и эксперементируйте с iconv().

                        Других вариантов не вижу.

                        Если есть желание — дайте в личку логин/пароль в админку — разберусь.
                          0
                          Вопрос решен. В конце сниппета
                          echo $Cal->generateCalendar($tmp[0], $tmp[1]);
                          

                          меняем на
                          $cal = $Cal->generateCalendar($tmp[0], $tmp[1]);
                          echo iconv('UTF-8', 'Windows-1251', $cal);
                          


                          Таки что-то у вас с кодировками.
                            0
                            Спасибо огромное :)
                  0
                  Спасибо за сниппет, сэкономил кучу времени!

                  Единственное дополнение: насколько я понимаю, у вас он принимает единственный документ-контейнер. Предлагаю ввести возможность указывать ID документов через запятую.

                  Мой вариант (в сниппете eventsCalendar2 строка 224):

                        $id = explode(',', $id);
                        $tmp = array();
                        foreach ($id as $page) {
                          $res = $modx->getChildIds($page);
                          foreach ($res as $key => $value) {
                            $tmp[$key] = $value;
                          }
                        }
                  
                    0
                    Спасибо! В версии для Revolution это уже есть.

                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                  Самое читаемое