Jump to content
MarcC

Table-based calendar integration

Recommended Posts

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.

  • Like 2

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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> </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> </td>";
}

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

// output the calendar
echo $out;
  • Like 3

Share this post


Link to post
Share on other sites

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" :-)

Share this post


Link to post
Share on other sites

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> </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> </td>";
   }

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

   // output the calendar
   return $out;

}
  • Like 1

Share this post


Link to post
Share on other sites

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) ."/'>←</a>";
    $out .= "<a href='../../". date('Y', $endTime) ."/". date('m', $endTime) ."/'>→</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> </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> </td>";
    }

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

    // output the calendar
    return $out;

}
  • Like 2

Share this post


Link to post
Share on other sites

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
}

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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) ."/'>←</a>";
    $out .= "<a href='/".$lang."/calendar/". date('Y', $endTime) ."/". date('m', $endTime) ."/'>→</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. :rolleyes:
kixe

  • Like 2

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...