Jump to content


Photo

Table-based calendar integration


  • Please log in to reply
8 replies to this topic

#1 MarcC

MarcC

    Sr. Member

  • Members
  • PipPipPipPip
  • 253 posts
  • 60

  • LocationCalifornia

Posted 10 November 2011 - 01:03 PM

A client has asked for a grid (table-based) calendar display on their website. I don't want to spend hours reinventing the wheel, so I thought I'd ask: Does anyone know of existing calendar software that could integrate with Processwire?

I found this example and it seems like it may be a good start, but I'm not sure how to use it with PW. Any suggestions would be welcome. Thanks.

I'm a freelance, processwire-using web designer based in california. work site | personal site | visuals


#2 Pete

Pete

    Administrator

  • Administrators
  • 1,756 posts
  • 658

  • LocationChester, England

Posted 10 November 2011 - 01:17 PM

If they don't mind using something a bit external, you can display a Google calendar in a web page pretty easily from what I remember. There are advantages and disadvantages to doing so (we're going back a few years here so it might just be advantages by now) but you certainly get the benefit of a calendar you can sync with a smartphone or your favourite email software rather than one that has to be updated manually on the website.

Beyond that, there seem to be a variety of calendar packages out there but none of the ones I've looked at were that straightforward.

#3 ryan

ryan

    Hero Member

  • Administrators
  • 5,771 posts
  • 3114

  • LocationAtlanta, GA

Posted 10 November 2011 - 03:22 PM

Here was Ryan's example code for calendar, until I (apeisa) modified it instead of quoting... :)

I got the original back from my editor, I post it here as reference. Ryan - sorry I lost your message here. You wrote something about that it is fun to code calendars :)

-apeisa


<?php
$year = (int) $input->urlSegment1; 
$month = (int) $input->urlSegment2; 

if(!$month) $month = date('n'); // if no month, use this month
if(!$year) $year = date('Y'); // if no year, use this year

$startTime = strtotime("$year-$month-01 00:00:00"); 
$endTime = strtotime("+1 month", $startTime); 

// find all events that fall in the given month and year
$events = $page->children("date>=$startTime, date<$endTime"); 

// get all the info you need to draw a grid calendar
$weekDayNames = array('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'); 
$firstDayName = date('D', $startTime); // i.e. Tue
$daysInMonth = date('t', $startTime); // 28 through 31

// make the calendar headline
$out = "<h1>" . date('F Y') . "</h1>"; // i.e. October 2011

// create the calendar header with weekday names
$out .= "<table><thead><tr>";
foreach($weekDayNames as $name) $out .= "<th>$name</th>";
$out .= "</tr></thead><tbody><tr>";

// fill in blank days from last month till we get to first day in this month
foreach($weekDayNames as $name) {
    if($name == $firstDayName) break;
    $out .= "<td>&nbsp;</td>";
} 

// draw the calendar
for($day = 1; $day <= $daysInMonth; $day++) {

    // get the time info that we need for this day
    $startTime = strtotime("$year-$month-$day 00:00:00"); 
    $endTime = strtotime("+1 day", $startTime); 
    $dayName = date('D', $startTime);

    // if we're at the beginning of a week, start a new row
    if($day > 1 && $dayName == 'Sun') $out .= "<tr>";

    // create the list of events for this day (if any)
    $list = '';
    foreach($events->find("date>=$startTime, date<$endTime") as $event) {
        $list .= "<li><a href='{$event->url}'>{$event->title}</a></li>";
    }

    // if any events were found for this day, wrap it in <ul> tag
    if($list) $list = "<ul>$list</ul>";

    // make the day column with day number as header and event list as body
    $out .= "<td><h2>$day</h2>$list</td>";

    // if last day in week, then close out the row
    if($dayName == 'Sun') $out .= "</tr>";
}

// finish out the week with blank days for next month
$key = array_search($dayName, $weekDayNames); 
while(isset($weekDayNames[++$key])) {
    $out .= "<td>&nbsp;</td>";
}

// close the last row and table
$out .= "</tr></tbody></table>";

// output the calendar
echo $out;


#4 MarcC

MarcC

    Sr. Member

  • Members
  • PipPipPipPip
  • 253 posts
  • 60

  • LocationCalifornia

Posted 11 November 2011 - 01:50 PM

Wow, thanks Ryan. I didn't even know URL segments existed :-) I'll have a look. Meanwhile, the client was asking for some pretty impressive features, so I asked for an example of what they needed. It turned out the example was a JPG image of an MS Publisher calendar on somebody's website.

"Can do" :-)

I'm a freelance, processwire-using web designer based in california. work site | personal site | visuals


#5 apeisa

apeisa

    Hero Member

  • Moderators
  • 2,521 posts
  • 848

  • LocationVihti, Finland

Posted 15 November 2011 - 06:41 AM

Ok, I tried to quote Ryan's post above, but accidentally modified it and overwrote with my own message. Ryan's code worked almost perfectly (it outputted sundays as their own row), so here is only minor changes to the original:

<?php
function renderCalendar($page, $year, $month, $field = 'startdate') {

    $year = (int) $year;
    $month = (int) $month;

    $startTime = strtotime("$year-$month-01 00:00:00");
    $endTime = strtotime("+1 month", $startTime);

    // find all events that fall in the given month and year
    $events = $page->children("$field>=$startTime,$field<$endTime");


    // get all the info you need to draw a grid calendar
    $weekDayNames = array('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun');
    $firstDayName = date('D', $startTime); // i.e. Tue
    $daysInMonth = date('t', $startTime); // 28 through 31

    // make the calendar headline
    // $out = "<h1>" . date('F Y') . "</h1>"; // i.e. October 2011

    // create the calendar header with weekday names
    $out .= "<table><thead><tr>";
    foreach($weekDayNames as $name) $out .= "<th>$name</th>";
    $out .= "</tr></thead><tbody><tr>";

    // fill in blank days from last month till we get to first day in this month
    foreach($weekDayNames as $name) {
        if($name == $firstDayName) break;
        $out .= "<td>&nbsp;</td>";
    }

    // draw the calendar
    for($day = 1; $day <= $daysInMonth; $day++) {

        // get the time info that we need for this day
        $startTime = strtotime("$year-$month-$day 00:00:00");
        $endTime = strtotime("+1 day", $startTime);
        $dayName = date('D', $startTime);

        // if we're at the beginning of a week, start a new row
        if($day > 1 && $dayName == 'Mon') $out .= "<tr>";

        // create the list of events for this day (if any)
        $list = '';
        foreach($page->children("$field>=$startTime, $field<$endTime") as $event) {
            $list .= "<li><a href='{$event->url}'>{$event->title}</a></li>";
        }

        // if any events were found for this day, wrap it in <ul> tag
        if($list) $list = "<ul>$list</ul>";

        // make the day column with day number as header and event list as body
        $out .= "<td><h2>$day</h2>$list</td>";

        // if last day in week, then close out the row
        if($dayName == 'Sun') $out .= "</tr>";
    }

    // finish out the week with blank days for next month
    $key = array_search($dayName, $weekDayNames);
    while(isset($weekDayNames[++$key])) {
        $out .= "<td>&nbsp;</td>";
    }

    // close the last row and table
    $out .= "</tr></tbody></table>";

    // output the calendar
    return $out;

}


#6 apeisa

apeisa

    Hero Member

  • Moderators
  • 2,521 posts
  • 848

  • LocationVihti, Finland

Posted 15 November 2011 - 08:45 AM

Updated this to support localized day titles and simple prev/next navigation.

<?php
function renderCalendar($page, $year, $month, $field = 'startdate') {

    // This feels little dirty, there is probably much more efficient way to get local day name?
    $mon = strftime('%a', strtotime("2011-11-14 00:00:00"));
    $tue = strftime('%a', strtotime("2011-11-15 00:00:00"));
    $wed = strftime('%a', strtotime("2011-11-16 00:00:00"));
    $thu = strftime('%a', strtotime("2011-11-17 00:00:00"));
    $fri = strftime('%a', strtotime("2011-11-18 00:00:00"));
    $sat = strftime('%a', strtotime("2011-11-19 00:00:00"));
    $sun = strftime('%a', strtotime("2011-11-20 00:00:00"));

    $year = (int) $year;
    $month = (int) $month;

    $startTime = strtotime("$year-$month-01 00:00:00");
    $endTime = strtotime("+1 month", $startTime);
    $lastMonth = strtotime("-1 month", $startTime);

    // find all events that fall in the given month and year
    $events = $page->children("$field>=$startTime,$field<$endTime");

    // get all the info you need to draw a grid calendar
    $weekDayNames = array($mon, $tue, $wed, $thu, $fri, $sat, $sun);
    $firstDayName = strftime('%a', $startTime); // i.e. "Tue" (Eng) or "ti" (Fin)
    $daysInMonth = date('t', $startTime); // 28 through 31

    // make the calendar headline
    $out = "<h1>" . strftime('%B %Y', $startTime) . "</h1>"; // i.e. October 2011

    $out .= "<div class='nav'>";
    $out .= "<a href='../../". date('Y', $lastMonth) ."/".  date('m', $lastMonth) ."/'>&larr;</a>";
    $out .= "<a href='../../". date('Y', $endTime) ."/". date('m', $endTime) ."/'>&rarr;</a>";
    $out .= "</div>";

    // create the calendar header with weekday names
    $out .= "<table class='calendar'><thead><tr>";
    foreach($weekDayNames as $name) $out .= "<th>$name</th>";
    $out .= "</tr></thead><tbody><tr>";

    // fill in blank days from last month till we get to first day in this month
    foreach($weekDayNames as $name) {
        if($name == $firstDayName) break;
        $out .= "<td>&nbsp;</td>";
    }

    // draw the calendar
    for($day = 1; $day <= $daysInMonth; $day++) {

        // get the time info that we need for this day
        $startTime = strtotime("$year-$month-$day 00:00:00");
        $endTime = strtotime("+1 day", $startTime);
        $dayName = strftime('%a', $startTime);

        // if we're at the beginning of a week, start a new row
        if($day > 1 && $dayName == $mon) $out .= "<tr>";

        // create the list of events for this day (if any)
        $list = '';
        foreach($page->children("$field>=$startTime, $field<$endTime") as $event) {
            $list .= "<li><a href='{$event->url}'>{$event->title}</a><p>{$event->location->title}, <span class='city'>{$event->location->city->title}</span></p></li>";
        }

        // if any events were found for this day, wrap it in <ul> tag
        if($list) $list = "<ul>$list</ul>";

        // make the day column with day number as header and event list as body
        $out .= "<td valign='top'><h2>$day</h2>$list</td>";

        // if last day in week, then close out the row
        if($dayName == $sun) $out .= "</tr>";
    }

    // finish out the week with blank days for next month
    $key = array_search($dayName, $weekDayNames);
    while(isset($weekDayNames[++$key])) {
        $out .= "<td>&nbsp;</td>";
    }

    // close the last row and table
    $out .= "</tr></tbody></table>";


    // output the calendar
    return $out;

}


#7 ryan

ryan

    Hero Member

  • Administrators
  • 5,771 posts
  • 3114

  • LocationAtlanta, GA

Posted 15 November 2011 - 09:11 AM

Nice update for localization! I don't know of a better way to get those local day names, but this would be one way to potentially improve the existing method. In this snippet, I'm just putting the localized day names directly into the $weekDayNames array, since that's where they go anyway.

<?php
$weekDayNames = array();
$time = strtotime("2011-11-14 00:00:00"); // a known Monday
for($day = 1; $day <= 7; $day++) {
    $weekDayNames[$day] = strftime('%a', $time);
    $time += 86400; // +1 day
}


#8 kixe

kixe

    Jr. Member

  • Members
  • PipPip
  • 15 posts
  • 4

  • LocationCologne, Germany

Posted 26 April 2013 - 09:10 AM

A known monday is also the day after last sunday! Isn't it? ???

 

 

 

   $weekDayNames=array();
    $i=0;
    while($i++ < 7) array_push($weekDayNames, strftime('%a', strtotime('last Sunday + '.$i.' day')));


 
 
 

 

 change this 


 

 

  // if we're at the beginning of a week, start a new row
        if($day > 1 && $dayName == $weekDayNames[0]) $out .= "<tr>";

 

and that
 

 

      // if last day in week, then close out the row
        if($dayName == $weekDayNames[6]) $out .= "</tr>";

 

kixe



#9 kixe

kixe

    Jr. Member

  • Members
  • PipPip
  • 15 posts
  • 4

  • LocationCologne, Germany

Posted 26 April 2013 - 01:00 PM

While trying out language switcher together with the calendar. I put this to the beginning of the script:
 

 

   $lang = substr($page->url,1,2);
    $lang_code = ($lang=='en')?'en_US':$lang.'_'.strtoupper($lang);//works not for all countries but most of them (fr, de, it, nl, is, ru, es, tr)
    setlocale(LC_TIME, $lang_code);

 

and changed the forward backward links:

 

   $out .= "<a href='/".$lang."/calendar/". date('Y', $lastMonth) ."/".  date('m', $lastMonth) ."/'>&larr;</a>";
    $out .= "<a href='/".$lang."/calendar/". date('Y', $endTime) ."/". date('m', $endTime) ."/'>&rarr;</a>";

 

I am using url-segments for year and month, like ryan recommended

 

$year = ($input->urlSegment1)?$input->urlSegment1:date('Y');
$month = ($input->urlSegment2)?$input->urlSegment2:date('m');

 

 

this will put out the current month as standard under the url en/calendar/

 

echo renderCalendar($page, $year, $month, $field = 'startdate');

 

 

its good to have such an easy going calendar. Thanks. Fun (while working with PW) has already started. ::)
kixe






0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users