BLOG

Computer & Software => CMS => Thema gestartet von: Jo am 2017-03-08 | 23:58:22

Titel: MODX & FullCalendar
Beitrag von: Jo am 2017-03-08 | 23:58:22
Der FullCalendar (https://fullcalendar.io/) ist ein JavaScript-Event-Kalender, anpassbar und Open Source -> also genau richtig für MODX!
(getestet mit MODX 2.7.0 / 3.0.1 & FullCalendar 3.10.0 )

Ich nenne mein ganzes Code-Schnipsel hier zusammen: fcMODX 22.10.010  (Jahr.Monat.Version)
(https://secure.jolichter.de/smf/tutorials/fcMODX/miniFC.png)
(Demo Bild fcMODX mini-mode mit angepassten CSS von Mottie (https://jsfiddle.net/Mottie/G6K6Y/1482/))

Was kann fcMODX?

Snippet Platzhalter, um diese in Chunks auszugeben benutze ich nicht - sehe derzeit keinen Grund dafür.

Als ersten Schritt müsst ihr den Kalenders in MODX natürlich mit den richtigen JavaScript- und CSS-Dateien einbinden (Link: Basic Usage (https://fullcalendar.io/docs/usage/)). Dann kann der Kalender individuell nach eigenem Bedarf per TV, Chunks und Snippets in MODX ausgebaut werden. Wer Wischgesten (swipe) benutzen will muss auch hammer.js einbinden.

Anwendungsbeispiel - eure Parent-Res.-ID's müsst ihr anpassen (siehe pdoResources):

Aufruf des Kalenders ohne iCal-File
[[!$jsFullCalendar? &fcinstance=`calendar`]]

Aufruf des Kalenders mit einem iCal-File
[[!$jsFullCalendar? &fcinstance=`calendar` &icsurl=`assets/downloads/deineDatei.ics` &color=`#123`]]


TV's anlegen



Chunks

jsFullCalendar (Initialisierung, Optionen und Instanz Platzhalter des Kalenders)
<script>
    $(document).ready(function(){
        var initialLocaleCode = 'de';
        $('#[[+fcinstance]]').fullCalendar({
            contentHeight: 'auto',
            header: {
                left: 'prev,next today',
                center: 'title',
                right: 'month,agendaWeek,agendaDay,listMonth'
                //right: 'month,agendaWeek,agendaDay'
            },
            defaultDate: '[[!today]]',
            locale: initialLocaleCode,
            buttonIcons: false,
            weekNumbers: true,
            navLinks: true,
            editable: false,
            eventLimit: 3,
            eventOrder: '-color',
            events: [
                        [[!fcSomerWinterZeit]]
                          [[!$fcAddDays]]
                            [[!fcFeiertageEreignisse]]
                              [[!$fcResourcesWeb]]
                                [[!$fcResourcesMultiWeb]]
                                    [[!$dwdWetterChunkFC? &STATION=`K428` &T1=`[[!getTimeRoundH]]`]]
                                      [[!ics2calendar? &icsurl=[[+icsurl]] &color=[[+color]]]]
            ],
        eventRender: function(event, element, view){
            // Icon
            if(event.icon){
               if(event.allDay){
                 $(element).find('span:first').prepend('<img src="'+event.icon+'" height="72" width="72" />');
               }else{
                 $(element).find('.fc-time').prepend('<img src="'+event.icon+'" height="72" width="72" />');
               }
            }
            // Ende Icon
            // Bootstrap Tooltip
            //if (event.description) {
            //$(element).tooltip({title: event.description, placement: 'bottom', container: 'body'});
            //}
            // Tooltip Ende
            if(view.name === "agendaDay"){
            if (event.description) {
            element.find('.fc-title').append("<br/>" + event.description);
            }}},
            // Tooltip wenn kein Bootstrap
            eventMouseover: function (event, jsEvent, view){
                $(jsEvent.target).attr('title', event.description);
            },
            // Ende Tooltip
                eventDataTransform: function(event){
                    if(event.allDay) {
                    event.end = moment(event.end).add(1, 'days')
                    }
                    return event;
                    }
        });

                var recognizers=['pan', 'pinch', 'press', 'rotate', 'tap'];
                var myElement = document.getElementById('[[+fcinstance]]');
                var mc = new Hammer(myElement);
                for(i=0;i<recognizers.length;i++){
                    mc.get(recognizers[i]).set({enable:false});
                }
                mc.get('swipe').set({
                    direction: Hammer.DIRECTION_HORIZONTAL,
                    threshold: 30,
                    velocity: 0.5
                });
                mc.on('swipeleft swiperight', function(ev){
                    if(ev.type=='swipeleft'){
                    $('#[[+fcinstance]]').fullCalendar('next');
                    }else{
                    $('#[[+fcinstance]]').fullCalendar('prev');
                  }
                });

    });
</script>
[[!$webfcCSS:htmlToHead]]
<div id='[[+fcinstance]]'></div>







fcCSS (optional: Kalender nachträglich per CSS Chunk anpassen)
<style type="text/css">
[[+fcinstance:notempty=`
   #[[+fcinstance]] {max-width: 100%; margin: 0 auto; padding: 5px;}
      /* u.s.w. */
`]]
</style>

fcAddDays (Ferien in RLP und unser OneFreeDay 2017 ; )
PS "Schulferien": an alle Lehrer, warum kann man das nicht berechnen ;-(
{ start: '2017-10-31', end: '2017-10-31', title: 'Reformationstag', description: 'nur 2017 in RLP!', color: '#7e6025' },

{ start: '2017-04-10', end: '2017-04-21', allDay: true, title: 'Osterferien', color: '#7e2555' },
{ start: '2017-07-03', end: '2017-08-11', allDay: true, title: 'Sommerferien', color: '#7e2555' },
{ start: '2017-10-02', end: '2017-10-13', allDay: true, title: 'Herbstferien', color: '#7e2555' },
{ start: '2017-12-22', end: '2018-01-09', allDay: true, title: 'Weihnachtsferien', color: '#7e2555' },

{ start: '2018-03-26', end: '2018-04-06', allDay: true, title: 'Osterferien', color: '#7e2555' },
{ start: '2018-06-25', end: '2018-08-03', allDay: true, title: 'Sommerferien', color: '#7e2555' },
{ start: '2018-10-01', end: '2018-10-12', allDay: true, title: 'Herbstferien', color: '#7e2555' },
{ start: '2018-12-20', end: '2019-01-04', allDay: true, title: 'Weihnachtsferien', color: '#7e2555' },

{ start: '2019-02-25', end: '2019-03-01', allDay: true, title: 'Winterferien', color: '#7e2555' },
{ start: '2019-04-23', end: '2019-04-30', allDay: true, title: 'Osterferien', color: '#7e2555' },
{ start: '2019-07-01', end: '2019-08-09', allDay: true, title: 'Sommerferien', color: '#7e2555' },
{ start: '2019-09-30', end: '2019-10-11', allDay: true, title: 'Herbstferien', color: '#7e2555' },
{ start: '2019-12-23', end: '2020-01-06', allDay: true, title: 'Weihnachtsferien', color: '#7e2555' },

{ start: '2020-02-17', end: '2020-02-21', allDay: true, title: 'Winterferien', color: '#7e2555' },
{ start: '2020-04-09', end: '2020-04-17', allDay: true, title: 'Osterferien', color: '#7e2555' },
{ start: '2020-07-06', end: '2020-08-14', allDay: true, title: 'Sommerferien', color: '#7e2555' },
{ start: '2020-10-12', end: '2020-10-23', allDay: true, title: 'Herbstferien', color: '#7e2555' },
{ start: '2020-12-21', end: '2020-12-31', allDay: true, title: 'Weihnachtsferien', color: '#7e2555' },

{ start: '2021-03-29', end: '2021-04-06', allDay: true, title: 'Osterferien', color: '#7e2555' },
{ start: '2021-05-25', end: '2021-06-02', allDay: true, title: 'Pfingstferien', color: '#7e2555' },
{ start: '2021-07-19', end: '2021-08-27', allDay: true, title: 'Sommerferien', color: '#7e2555' },
{ start: '2021-10-11', end: '2021-10-22', allDay: true, title: 'Herbstferien', color: '#7e2555' },
{ start: '2021-12-23', end: '2021-12-31', allDay: true, title: 'Weihnachtsferien', color: '#7e2555' },

{ start: '2022-02-21', end: '2022-02-25', allDay: true, title: 'Winterferien', color: '#7e2555' },
{ start: '2022-04-13', end: '2022-04-22', allDay: true, title: 'Osterferien', color: '#7e2555' },
{ start: '2022-07-25', end: '2022-09-02', allDay: true, title: 'Sommerferien', color: '#7e2555' },
{ start: '2022-10-17', end: '2022-10-31', allDay: true, title: 'Herbstferien', color: '#7e2555' },
{ start: '2022-12-23', end: '2023-01-02', allDay: true, title: 'Weihnachtsferien', color: '#7e2555' },

fcResources
[[!pdoResources:default=``?
    &context=`web`
    &parents=`62,105,122`
    &depth=`0`
    &tpl=`tplFCRes`
    &limit=`0`
    &idx=`0`
    &includeContent=`0`
    &showUnpublished=`0`
    &includeTVs=`EventDateStart,EventDateEnd`
    &sortby=`menuindex`
    &sortdir=`asc`
    &tvFilters=``
]]
(sollte auch mit dem alten getResources funktionieren, jedoch: includeTVs=`1`)

tplFCRes (Zeilenumbruch mit "\n" wenn pagetitle zu lang)
{ start: '[[+tv.EventDateStart:strtotime:date=`%Y`]]-[[+tv.EventDateStart:strtotime:date=`%m`]]-[[+tv.EventDateStart:strtotime:date=`%d`]]T[[+tv.EventDateStart:strtotime:date=`%R`]]:00', [[+tv.EventDateEnd:notempty=` end: '[[+tv.EventDateEnd:strtotime:date=`%Y`]]-[[+tv.EventDateEnd:strtotime:date=`%m`]]-[[+tv.EventDateEnd:strtotime:date=`%d`]]T[[+tv.EventDateEnd:strtotime:date=`%R`]]:00', `]] title: '[[wordwrapN? &input=`[[+pagetitle]]` &options=`16`]]',  url: '[[~[[+id]]]]', description: '(Bericht klick hier)', color: '#257e4a' },

fcResourcesMulti
[[!pdoResources:default=``?
    &context=`web`
    &parents=`62,105,122`
    &depth=`0`
    &tpl=`tplFCResMulti`
    &limit=`0`
    &idx=`0`
    &includeContent=`0`
    &showUnpublished=`0`
    &includeTVs=`EventDateMulti`
    &sortby=`menuindex`
    &sortdir=`asc`
    &tvFilters=``
]]

tplFCResMulti (Zeilenumbruch mit "\n" wenn pagetitle zu lang)
[[!date2calendar? &param=`[[+tv.EventDateMulti]]` &title=`[[wordwrapN? &input=`[[+pagetitle]]` &options=`16`]]` &desc=`(Bericht klick hier)` &url=`[[~[[+id]]]]` &color=`#257e4a`]]



Snippets

today
<?php
$today 
date("Y-m-d");
return 
$today;

wordwrapN
<?php
# Zeilenumruch mit Tag "\n"
# wordwrap: Diese Funktion bricht ab einer gewissen Länge einen Satz um
# [[wordwrapN? &input=`[[+pagetitle]]` &options=`20`]]

$output '';
$input trim($input);

if (!empty(
$input) && !empty($options)) { 
         
$output wordwrap($input$options'\n');
  } else 
$output $input;

return 
$output;

date2calendar
<?php
# V 22.12.005
#
# Mit PHP ein Datums-Array für den JQuery-FullCalendar aufbereiten
#
# Beispiel Snippet Aufruf:
# [[!date2calendar? &param=`2017-03-04,2017-04-28,2017-04-11,2017-04-25` &title=`test` &desc=`blablabla` &url=`brauchtum/test.html &color=`#a23d3d`]]
#
$param $modx->getOption('param',$scriptProperties,'');
$title $modx->getOption('title',$scriptProperties,'');
$desc $modx->getOption('desc',$scriptProperties,'');
$url $modx->getOption('url',$scriptProperties,'');
$color $modx->getOption('color',$scriptProperties,'#257e4a');
$strAusgabe '';
$strTemp '';

if (empty(
$param)) {
    return 
'';
} else {

$param trim($param);

$paramArray explode(','$param);
foreach(
$paramArray as $p){
$strTemp $strTemp."{ start: '".$p."', end: '".$p."', allDay: true, title: '".$title."', description: '".$desc."', url: '".$url."', color: '".$color."' } ,";
}
$strAusgabe trim($strTemp);
return 
$strAusgabe;
}

fcSomerWinterZeit
<?php
# V 22.10.005
#
# Mit PHP Sommer/Winterzeit für den FullCalendar ermitteln
#
#
# Snippet Aufruf:
# [[!fcSomerWinterZeit`]]
#
$colorS '#257e4a'# Sommer
$colorW '#257e4a'# Winter
$yearstartdate("Y"); # starte ab aktuelles Jahr
$zb '\n'# Zeilenumbruch
$strAusgabe '';

# erstelle Liste für die nächsten 20 Jahre
for($i=0$i <= 20$i++) {
$year $yearstart+$i;

$sommer = new DateTime($year.'-03-31');
$sommer->modify('last sunday of this month');
$sommer $sommer->format('Y-m-d');
$winter = new DateTime($year.'-10-31');
$winter->modify('last sunday of this month');
$winter $winter->format('Y-m-d');

$strTemp "{ start: '".$sommer."', end: '".$sommer."', title: 'Zeitumstellung ".$zb." Sommerzeit', description: '(Link zu wikipedia)', url: 'https://de.wikipedia.org/wiki/Sommerzeit', color: '".$colorS."' },";
$strTemp $strTemp."{ start: '".$winter."', end: '".$winter."', title: 'Zeitumstellung ".$zb." Winterzeit', description: '(Link zu wikipedia)', url: 'https://de.wikipedia.org/wiki/Sommerzeit', color: '".$colorW."' },";

$strAusgabe $strAusgabe.$strTemp;
}

return 
$strAusgabe;

ics2calendar
<?php
# V 22.10.009
#
# Mit PHP iCalendar-Daten (*.ics) laden und für den JQuery-FullCalendar aufbereiten
#
# Beispiel Snippet Aufruf:
# [[!ics2calendar? &icsurl=`assets/downloads/deineDatei.ics` &color=`#123`]]
#

$icsColor '#3A87AD';
$strTargetURL $modx->getOption('icsurl',$scriptProperties,'');
$color $modx->getOption('color',$scriptProperties$icsColor);
$strReturn '';
$strADD '';

# wenn keine URL oder kein Platzhalter, dann mache nichts
if (empty($strTargetURL) or $strTargetURL == "[[+icsurl]]") {
    return 
'';
} else {

# wenn der Platzhalter +color nicht benutzt wird
if (empty($color) or $color == "[[+color]]") {
    
$color $icsColor;
}

# prüft ob es die Datei gibt
    
if (!file_exists($strTargetURL)) {
        
# exit("Your file doesn't exist");
                
$modx->log(modX::LOG_LEVEL_ERROR'[ics2calendar] Your ics file does not exist!');
                return;
    }
# Feldnamen Variablen
    
$strSearchSTART 'DTSTART';
    
$strSearchEND 'DTEND';
    
$strDat =':2'# hier fängt das Datum an
    
$strSearchSUM 'SUMMARY:';
    
$strSearchDESC 'DESCRIPTION:';
    
$strSearchEndEvent 'END:VEVENT'# Farbe am Event-Ende setzen


# liest Datei Zeilenbasierend
    
$strLines file($strTargetURL);

# prüft ob es eine iCal-Datei ist
    
$strTemp substr($strLines[0], 0,15);
    if (
$strTemp !== "BEGIN:VCALENDAR") {
        
# exit("Your file isn't an iCal-File");
                
$modx->log(modX::LOG_LEVEL_ERROR'[ics2calendar] Your file is not an iCal-File!');
                return;
    }

foreach (
$strLines as $strLine)
{
        
# Datumsformat z.B. "2017-02-01" oder "2017-02-12T10:30:00"
            
if(strpos($strLine$strSearchSTART) !== false)
            {
            
$strTemp strstr($strLine$strSearchSTART);
            
$strTemp strstr($strTemp$strDat);
            
$strTemp substr($strTemp1);
            
# $strADD = $strADD."{ start: '" . date('Y-m-d\TH:i:s', strtotime($strTemp))."', ";
            
$strADD $strADD."{ start: '" date('Y-m-d'strtotime($strTemp))."', ";
            }

            if(
strpos($strLine$strSearchEND) !== false)
            {
            
$strTemp strstr($strLine$strSearchEND);
            
$strTemp strstr($strTemp$strDat);
            
$strTemp substr($strTemp1);
            
# $strADD = $strADD." end: '" . date('Y-m-d\TH:i:s', strtotime($strTemp))."', ";
            
$strADD $strADD." end: '" date('Y-m-d'strtotime($strTemp))."', ";
            }

            if(
strpos($strLine$strSearchSUM) !== false)
            {
            
$strTemp strstr($strLine$strSearchSUM);
            
$strTemp htmlspecialchars(trim($strTemp));
                        
$strTemp str_replace('&amp;''&'$strTemp);
            
$strTemp substr($strTemp8);
                        
$strTemp wordwrap($strTemp25' \n ');
            
$strADD $strADD." title: '" $strTemp."', ";
            }

            
# Non-Standard Fields in FullCalendar!
            
if(strpos($strLine$strSearchDESC) !== false)
            {
            
$strTemp strstr($strLine$strSearchDESC);
            
$strTemp htmlspecialchars(trim($strTemp));
                        
$strTemp str_replace('&amp;''&'$strTemp);
            
$strTemp substr($strTemp12);
                        
# $strTemp = wordwrap($strTemp, 25, '<br/>');
            
$strADD $strADD." description: '" $strTemp."', ";
            }

            if(
strpos($strLine$strSearchEndEvent) !== false)
            {
                if (isset(
$color)) {
                
$strTemp " color: '" $color."'";
                
$strADD $strADD.$strTemp;
                }
            
$strADD $strADD." }, ";
            }

}

    
# entferne letze Leerstelle und Komma
    
$strReturn substr($strADD0, -2);

return 
$strReturn;
}

getEasterDate
<?php
# V 22.10.002
#
# Mit PHP Ostern berechnen um beweglichen Feiertage zu ermitteln
#
# Snippet Aufruf:
# [[!getEasterDate? &year=`2017`]]

$today date("Y");
$year $modx->getOption('year',$scriptProperties,$today);
$ostern '';

$base = new DateTime($year.'-03-21');
$days easter_days($year);
$base->add(new DateInterval('P'.$days.'D'));

$ostern $base->format('Y-m-d');
return 
$ostern;

fcFeiertageEreignisse
<?php
# V 22.10.010
#
# Mit PHP Feiertage für FullCalendar ermitteln (hier z.B. für Rheinland-Pfalz)
# Farbe + Feiertage sind leicht hinzuzufügen oder können mit einer Raute auskommentiert werden
#
# Snippet Aufruf:
# [[!fcFeiertageEreignisse`]]
#
#
$colorF '#7e6025'# Feiertag
$colorE '#257e4a'# Ereignis
$yearstartdate("Y"); # starte ab aktuelles Jahr
$zb '\n'# Zeilenumbruch
$strAusgabe '';

# erstelle Liste für die nächsten 20 Jahre
for($i=0$i <= 20$i++) {
$year $yearstart+$i;

$base = new DateTime($year.'-03-21');
$days easter_days($year);
$base->add(new DateInterval('P'.$days.'D'));

$ostern $base->format('Y-m-d');

   
# Weiberfastnacht findet immer am Donnerstag vor Aschermittwoch statt
   
$weiberfastnacht strtotime(date('Y-m-d'strtotime($ostern)).' -52 day');
$rosenmontag strtotime(date('Y-m-d'strtotime($ostern)).' -48 day');
$fastnacht strtotime(date('Y-m-d'strtotime($ostern)).' -47 day');
$aschermittwoch strtotime(date('Y-m-d'strtotime($ostern)).' -46 day');
   
# Am Sonntag nach Aschermittwoch wird in der Eifel die "Hütt" verbrannt
   
$huettenbrennen strtotime(date('Y-m-d'strtotime($ostern)).' -42 day');
$rosenmontag strtotime(date('Y-m-d'strtotime($ostern)).' -48 day');
$fastnacht strtotime(date('Y-m-d'strtotime($ostern)).' -47 day');
$aschermittwoch strtotime(date('Y-m-d'strtotime($ostern)).' -46 day');
$karfreitag strtotime(date('Y-m-d'strtotime($ostern)).' -2 day');
$ostersonntag strtotime(date('Y-m-d'strtotime($ostern)));
$ostermontag strtotime(date('Y-m-d'strtotime($ostern)).' +1 day');
$christihimmelfahrt strtotime(date('Y-m-d'strtotime($ostern)).' +39 day');
$pfingstsonntag strtotime(date('Y-m-d'strtotime($ostern)).' +49 day');
$pfingstmontag strtotime(date('Y-m-d'strtotime($ostern)).' +50 day');
$fronleichnam strtotime(date('Y-m-d'strtotime($ostern)).' +60 day');

$weiberfastnacht date('Y-m-d'$weiberfastnacht);
$rosenmontag date('Y-m-d'$rosenmontag);
$fastnacht date('Y-m-d'$fastnacht);
$aschermittwoch date('Y-m-d'$aschermittwoch);
$huettenbrennen date('Y-m-d'$huettenbrennen);
$karfreitag date('Y-m-d'$karfreitag);
$ostersonntag date('Y-m-d'$ostersonntag);
$ostermontag date('Y-m-d'$ostermontag);
$christihimmelfahrt date('Y-m-d'$christihimmelfahrt);
$pfingstsonntag date('Y-m-d'$pfingstsonntag);
$pfingstmontag date('Y-m-d'$pfingstmontag);
$fronleichnam date('Y-m-d'$fronleichnam);

$strTemp "
{ start: '
$weiberfastnacht', end: '$weiberfastnacht', title: 'Weiberfastnacht', color: '".$colorE."' },
{ start: '
$rosenmontag', end: '$rosenmontag', title: 'Rosenmontag', color: '".$colorE."' },
{ start: '
$fastnacht', end: '$fastnacht', title: 'Fastnacht', color: '".$colorE."' },
{ start: '
$aschermittwoch', end: '$aschermittwoch', title: 'Aschermittwoch', color: '".$colorE."' },
{ start: '
{$huettenbrennen}T19:00:00', end: '{$huettenbrennen}T21:00:00', title: 'Hüttenbrennen', color: '".$colorE."' },
{ start: '
$karfreitag', end: '$karfreitag', title: 'Karfreitag', color: '".$colorF."' },
{ start: '
$ostersonntag', end: '$ostersonntag', title: 'Ostersonntag', color: '".$colorF."' },
{ start: '
$ostermontag', end: '$ostermontag', title: 'Ostermontag', color: '".$colorF."' },
{ start: '
$christihimmelfahrt', end: '$christihimmelfahrt', title: 'Christi Himmelfahrt', color: '".$colorF."' },
{ start: '
$pfingstsonntag', end: '$pfingstsonntag', title: 'Pfingstsonntag', color: '".$colorF."' },
{ start: '
$pfingstmontag', end: '$pfingstmontag', title: 'Pfingstmontag', color: '".$colorF."' },
{ start: '
$fronleichnam', end: '$fronleichnam', title: 'Fronleichnam', color: '".$colorF."' },


{ start: '
{$year}-01-01', end: '{$year}-01-01', title: 'Neujahr', color: '".$colorF."' },
{ start: '
{$year}-01-05', end: '{$year}-01-05', title: 'Heilige Drei Könige', color: '".$colorE."' },
{ start: '
{$year}-05-01', end: '{$year}-05-01', title: 'Tag der Arbeit', color: '".$colorF."' },
{ start: '
{$year}-06-23', end: '{$year}-06-23', title: 'Nationalfeiertag $zb in Luxemburg', color: '".$colorF."' },
{ start: '
{$year}-08-15', end: '{$year}-08-15', title: 'Maria Himmelfahrt $zb in Luxemburg', color: '".$colorF."' },
{ start: '
{$year}-10-03', end: '{$year}-10-03', title: 'Wiedervereinigung', color: '".$colorF."' },
{ start: '
{$year}-10-31', end: '{$year}-10-31', title: 'Reformationstag', color: '".$colorE."' },
{ start: '
{$year}-11-01', end: '{$year}-11-01', title: 'Allerheiligen', color: '".$colorF."' },
{ start: '
{$year}-11-11', end: '{$year}-11-11', title: 'Martinstag', color: '".$colorE."' },
{ start: '
{$year}-12-06', end: '{$year}-12-06', title: 'Nikolaus', color: '".$colorE."' },
{ start: '
{$year}-12-25', end: '{$year}-12-25', title: '1. Weihnachtsfeiertag', color: '".$colorF."' },
{ start: '
{$year}-12-26', end: '{$year}-12-26', title: '2. Weihnachtsfeiertag', color: '".$colorF."' },
{ start: '
{$year}-12-31', end: '{$year}-12-31', title: 'Silvester', color: '".$colorF."' },
"
;

$strAusgabe $strAusgabe.$strTemp;
}

return 
$strAusgabe;


(https://secure.jolichter.de/smf/tutorials/fcMODX/fcMODX-Backend.png)
(Demo Bild fcMODX Backend)
(https://secure.jolichter.de/smf/tutorials/fcMODX/fcMODX.png)
(Demo Bild fcMODX Frontpage)



Optional
EventDateMulti: Ein Custom TV-input-type mit jQuery Datepicker erstellen

Anstatt mit einer Text-TV die Daten per Hand einzugeben, benutze ich den Datepicker (http://keith-wood.name/datepick.html) von Keith Wood, der per Mehrfachmarkierung (Multiple Days) mehrere Tage in das Feld schreibt.

Dazu müsst ihr diese 2 Dateien wie folgt erstellen:
core/model/modx/processors/element/tv/renders/mgr/input/datepicker-multiple.class.php
manager/templates/default/element/tv/renders/input/datepicker-multiple.tpl

Nachtrag für MODX 3
Ort für "datepicker-multiple.class.php" ist wahrscheinlich (ungetestet!):
core/src/Revolution/Processors/Element/TemplateVar/Renders/mgr/input/
1) datepicker-multiple.class.php:
<?php
/**
* jQuery Datepicker
*/ 
class modTemplateVarInputRenderDatepickerMultiple extends modTemplateVarInputRender {
    public function 
getTemplate() {
        return 
'element/tv/renders/input/datepicker-multiple.tpl';
    }
}
return 
'modTemplateVarInputRenderDatepickerMultiple';

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/datepick/datepick.css" media="screen" />
<script src="../assets/js/jquery.min.js" type="text/javascript"></script>
<script src="../assets/datepick/datepick.js" type="text/javascript"></script>
<script src="../assets/datepick/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>


Die jQuery Datepicker Dateien sind hier im Anhang :-)