Neuigkeiten:

Privates MODX und LINUX BLOG, User Registrierung ist deaktiviert! Fragen oder Tipps? Bitte per Matrix: @jolichter:tchncs.de

Hauptmenü

eventsCalendar2 Multidays

Begonnen von Jo, 2012-03-11 | 00:00:36

« vorheriges - nächstes »

Jo

Update
Seit 2017 benutze ich nur noch den FullCalendar.
Dieser lässt sich leicht in MODX einbinden und Multidays sind ohne 'dirty hack' möglich!





Der eventsCalendar2 für MODx Revo ist eine Ajax-Anwendung und Monatswechsel werden daher ohne 'site refresh' geladen. Es ist sehr einfach Ressourcen in den Kalender einzubinden. Er ist klein, übersichtlich und gefällt einfach.

Leider hat der Entwickler bezumkin kein Interesse diesen für mehrere Event-Tage anzupassen. Daher habe ich den Code per 'dirty hack' angepasst:

  • &dateSource -> wie gehabt als Date TV
  • &dateSource2 -> End Datum als Date TV
  • &dateSourceEx -> Optional, ausklammern von beliebig vielen Daten als Text TV (durch Komma getrennt), z.B.: 2012-03-05,2012-03-08

Hier meine Änderungen am eventsCalendar2 2.2.4-pl (05.06.2013):
Ohne Garantie!

Aufruf z.B.
[[!eventsCalendar2?
    &parents=`42`
    &theme=`mein_theme`
    &first_day=`1`
    &dateSource=`eventDateStart`
    &dateSource2=`eventDateEnd`
    &dateSourceEx=`eventDateExclude`
    &dateFormat=`%Y-%m-%d`
    &includeContent=`0`
]]



fügt im Snippet eventsCalendar2 hinter
$c['dateSource'] = !empty($dateSource) ? $dateSource : 'createdon';
diese 2 Zeilen
$c['dateSource2'] = !empty($dateSource2) ? $dateSource2 : '';
$c['dateSourceEx'] = !empty($dateSourceEx) ? $dateSourceEx : '';

hinzu. (das 'createdon' ist für mich unwichtig, da ich nur mit TVs arbeite ;- )


ersetzt die Zeilen in core/components/eventscalendar2/model/eventscalendar2/eventscalendar2.class.php:
$resources = $this->modx->getCollection('modResource', $query, false);
foreach ($resources as $resource) {
if ($this->isTV) {
$tv = $this->modx->getObject('modTemplateVar', array('name' => $this->config['dateSource']));
if (!empty($tv)) {
$date = $tv->getValue($resource->get('id'));
}
else {
$this->error('no_tv');
break;
}
}
else {
$date = $resource->get($this->config['dateSource']);
}

// Если ресурс подходит по дате - достаем (или нет) для него ТВ и сохраняем.
if (date('Y-n', strtotime($date)) == "$year-$month") {
$resource->set('date', $date);

// Обработка ТВ, если нужно
$tvs = array();
if (!empty($this->config['includeTVs'])) {
// Если список нужных ТВ не был указан - извлекаем ВСЕ ТВ для ресурса
if (empty($this->config['includeTVList'])) {
$templateVars = $resource->getMany('TemplateVars');
}
// Обрабатываем ТВ
foreach ($templateVars as $tvId => $templateVar) {
if (!empty($this->config['includeTVList']) && !in_array($templateVar->get('name'), $this->config['includeTVList'])) {continue;}
// Рендерить ли ТВ?
// Да
if ($this->config['processTVs'] && (empty($this->config['processTVList']) || in_array($templateVar->get('name'), $this->config['processTVList']))) {
$tvs[$templateVar->get('name')] = $templateVar->renderOutput($resource->get('id'));
// Нет
} else {
$tvs[$templateVar->get('name')] = $templateVar->getValue($resource->get('id'));
}
}
}

$content[] = array_merge($resource->toArray(), $tvs);
}
}
        return $content;
    }

mit folgenden Code:
#--------------------------> multiday-hack ***START***
$resources = $this->modx->getCollection('modResource', $query, false);
foreach ($resources as $resource) {
if ($this->isTV) {

$tv1 = $this->modx->getObject('modTemplateVar', array('name' => $this->config['dateSource']));
$tv2 = $this->modx->getObject('modTemplateVar', array('name' => $this->config['dateSource2']));
$tvEx = $this->modx->getObject('modTemplateVar', array('name' => $this->config['dateSourceEx']));

if (!empty($tv1) && !empty($tv2)){
#START Multiday events
$intMultiday=1;

for($intDay=0; $intDay < $intMultiday; $intDay++) {

$date = $tv1->getValue($resource->get('id'));
$date = $date.'+'.$intDay.' day'; #add days

#how much days has the resources (tv2-tv1)?
if ($intMultiday == 1) {
$intMultiday1 = strtotime($tv1->getValue($resource->get('id')));
$intMultiday2 = strtotime($tv2->getValue($resource->get('id')));
$intMultiday = $intMultiday2 - $intMultiday1;
$intMultiday = intval($intMultiday / 86400) + 1;
}

        #maybe exclude dates? TV dateSourceEx to Array
if (!empty($tvEx)) {
            $strEx = explode(',',$tvEx->getValue($resource->get('id')));
foreach($strEx AS $datEx) {
$date = date('Y-m-d', strtotime($date));
if ($datEx === $date) { $date=null; } } }


#------------------------------------->(shifted!)
if (date('Y-n', strtotime($date)) == "$year-$month") {
$resource->set('date', $date);

$tvs = array();
if (!empty($this->config['includeTVs'])) {
if (empty($this->config['includeTVList'])) {
$templateVars = $resource->getMany('TemplateVars');
}

foreach ($templateVars as $tvId => $templateVar) {
if (!empty($this->config['includeTVList']) && !in_array($templateVar->get('name'), $this->config['includeTVList'])) {continue;}

if ($this->config['processTVs'] && (empty($this->config['processTVList']) || in_array($templateVar->get('name'), $this->config['processTVList']))) {
$tvs[$templateVar->get('name')] = $templateVar->renderOutput($resource->get('id'));

} else {
$tvs[$templateVar->get('name')] = $templateVar->getValue($resource->get('id'));
}
}
}
$content[] = array_merge($resource->toArray(), $tvs);
}
#-------------------------------------<(shifted!)

} #END "for loop" Multiday events


}
else {
$this->error('no_tv');
break;
}
}
else {
$date = $resource->get($this->config['dateSource']);
}

} #END of "foreach ($resources as $resource)"

return $content;
}
#--------------------------< multiday-hack ***END***



alles ohne Gewähr!

Info: Probleme wird es natürlich bei einem Update geben... dann müsst ihr das Update bleiben lassen oder wieder alles für 3 TVs anpassen.




Ein Custom TV-input-type mit jQuery Datepicker?

Komfortabler geht das wenn ihr anstatt einer Text-TV den Datepicker von Keith Wood benutzt, der per Mehrfachmarkierung (Multiple Days) Tage markieren kann (siehe Anhang).

Dazu müsst ihr diese 2 Dateien wie folgt erstellen
(Achtung: das ist alt! Update als PHP Klasse siehe FullCalendar)

core/model/modx/processors/element/tv/renders/mgr/input/datepicker-multiple.php
manager/templates/default/element/tv/renders/input/datepicker-multiple.tpl


1) datepicker-multiple.php:
<?php
/**
* jQuery Datepicker
*/
$this->xpdo->lexicon->load('tv_widget');

return 
$this->xpdo->smarty->fetch('element/tv/renders/input/datepicker-multiple.tpl');


2) datepicker-multiple.tpl (CSS und JS Pfade anpassen):
{* Smarty-Syntax *}
{* popupDatepicker with configure the date format to match mysql date *}

<link rel="stylesheet" type="text/css" href="../assets/templates/datepick.css" media="screen" />
<script src="../assets/script/jQuery/jquery.js" type="text/javascript"></script>
<script src="../assets/script/jQuery/datepick.js" type="text/javascript"></script>
<script src="../assets/script/jQuery/datepick-de.js" type="text/javascript"></script>

<input id="tv{$tv->id}" name="tv{$tv->id}"
type="text" class="textfield"
        value="{$tv->get('value')|escape}"
{$style}
tvtype="{$tv->type}"
onblur="MODx.fireResourceFormChange();"/>

<script type="text/javascript">
// <![CDATA[
{literal}
$(function() {
$('#{/literal}tv{$tv->id}{literal}').datepick({dateFormat:'yyyy-mm-dd', multiSelect:99, monthsToShow:2, firstDay:1});
});
$(function() {
    var fld = MODx.load({
    {/literal}
        xtype: 'textfield'
        ,applyTo: 'tv{$tv->id}'
        ,width: '97%'
    {literal}
    });
    Ext.getCmp('modx-panel-resource').getForm().add(fld);
    MODx.makeDroppable(fld);
});
{/literal}
// ]]>
</script>


Nachtrag:
Wer keine 3 TVs will und nur ein &dateSource haben möchte, kann den
eventscalendar2.class.php code so anpassen, dass der Datepicker &dateSource seine Daten als Array übergibt.

Viel Erfolg!  :-[


Jo

#1
und noch ein Nachtrag für eine schöne W3C-Validation-Korrektur an der eventscalendar2.class.php

Ersetzt:
$thead['link_prev'] = $self.'?action=refreshCalendar&month='.$prev_month.'&year='.$prev_year;
$thead['link_next'] = $self.'?action=refreshCalendar&month='.$next_month.'&year='.$next_year;

mit:
$thead['link_prev'] = $self.'?action=refreshCalendar&amp;month='.$prev_month.'&amp;year='.$prev_year;
$thead['link_next'] = $self.'?action=refreshCalendar&amp;month='.$next_month.'&amp;year='.$next_year;