Newscoop 4 Cookbook

Calendars with jQuery

Usually you will want to use a calendar to show a visual presentation of published articles in the archive. In Newscoop, we added a special function to provide a Calendar control, which will highlight all days that have articles (or issues) published. When a user clicks on a date, a link action fires up to open a defined URL with an additional parameter date. It could be used to address an archive template and sort articles according to the provided date.

The calendar function is based on the jQueryUI widget Datepicker (http://jqueryui.com/demos/datepicker/). So the first thing to do will be to include all required jQuery libraries:

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/jquery-ui.min.js"></script> <link type="text/css" href="http://ajax.googleapis.com/ajax/dlibs/jqueryui/1.8.11/themes/base/jquery-ui.css" rel="stylesheet" /> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/i18n/jquery.ui.datepicker-ru.min.js"></script> 

As you can see in this example, we included all libraries from Google's CDN. You can use your own custom libraries, downloaded from the jQuery site. The last one is only required if you want to show a calendar in a language other than English. By default, the Calendar will be presented in the current site language. A function detects what language the website content is, and therefore what language the Calendar will be.

The following construction will create a Calendar control::

{{ calendar container="cal1Container" url="/?tpl=archive.tpl" style="my_calendar" min_date="2009-03-01" max_date="2009-03-31" clickable_dates="articles" }} 
  • container: This attribute is mandatory. It allows you to define an unique HTML identifier (id) for the calendar container.
  • url: This attribute is mandatory. Define the action link of the Calendar once the user clicks a date.
  • clickable_dates: This attribute is optional. There are two possible values for this attribute: "articles" and "issues", with the latter being the default. If you pass "articles", the Calendar will show as highlighted all dates where at least one article is published (publish_date). If you pass "issues" or nothing at all, thr Calendar will show as highlighted all dates when an issue has been published.
  • style: This attribute is optional. Sets a custom CSS class for the calendar container. If it is not defined, the default class "calendar" will be used.
  • min_date: This attribute is optional. It sets the Calendar's minimum selectable date. The date format should be "yyyy-mm-dd".
  • max_date: This attribute is optional. It sets the Calendar's maximum selectable date. The date format should be "yyyy-mm-dd".

The resulting output will be like this (remember, we included the Russian language in the example above):

You can then style the Calendar the way you want it to be (remember, we used the class name "my_calendar"). Also, the look is based on the UI theme that you use, so you can adjust the theme according to your needs (we used the base theme in this example).

The source code of the Calendar output is the following:

<!-- Begin Calendar widget //--> <div class="my_calendar"> <div id="cal1Container"></div> <script type="text/javascript"> $(function() {   var issueDates = new Array();   var articleDates = new Array("2009-03-27","2009-03-28");   $.datepicker.setDefaults($.datepicker.regional["en"]);   $("#cal1Container").datepicker({     dateFormat: "yy-mm-dd",     minDate: "2009-03-01",     maxDate: "2009-03-31",     beforeShowDay: function(displayedDate) {                   var dDate = "";                   var dDay = displayedDate.getDate();                   var dMonth = displayedDate.getMonth() + 1;                    if (dDay < 10) dDay = "0" + dDay;                   if (dMonth < 10) dMonth = "0" + dMonth;                   dDate = displayedDate.getFullYear() + "-" + dMonth + "-" + dDay;                    for (i = 0; i < issueDates.length; i++) {                       if (dDate == issueDates[i]) {                           return [false,"ui-state-active",""];                       }                   }                   for (i = 0; i < articleDates.length; i++) {                       if (dDate == articleDates[i]) {                           return [true, "ui-state-active", ""];                       }                   }                   return [false, ""]; // disable all other days               },onSelect: function(selectedDate) {                   var contentDates = new Array("2009-03-27","2009-03-28");                   for (var i in contentDates) {                       if (selectedDate == contentDates[i]) {                           var linkTo = "/?tpl=archive.tpl&date=" + selectedDate;                           window.location = linkTo;                       }                   }               }}); }); </script> </div> <!--End Calendar widget //--> 

Extending functionality

You can see that all the hard work of creating the visual presentation is given to jQuery UI Datepicker. All we need to do is provide dates in correct format. You can take this approach and provide any data you want. Just note that it should be readable by the plugin.

Of course, it is much more easier to use a Calendar function supplied in Newscoop, but sometimes you will need more. Here is how we made a Calendar of PDF versions in the archive. First we need to provide variables in JSON format. For that purpose we have made a small template (_json-pdf-items.tpl):

{ "pdf":{   {{list_articles constraints="type is pdf issue greater 1 section is 300 publish_date greater 1900-01-01"}}     "{{$gimme->article->publish_date|date_format:"%Y-%m-%d"}}":{       "link":         "{{list_article_attachments length="1"}}http://{{$gimme->publication->site}}{{uri options="articleAttachment"}}{{/list_article_attachments}}",         "title":" {{$gimme->issue->name}}({{$gimme->issue->number}})  {{$gimme->issue->publish_date|camp_date_format:"%d.%m.%Y"}} -  pdf"}{{if !$gimme->current_list->at_end}},{{/if}}{{/list_articles}}       } } 

Next, we need to read variables from that template and save them for jQuery. Actually, we use a cron-job to grab the data and put it into the .json file. But it could also be done directly, addressing the template:

/* Datepickers */ var pdf_date; $.ajax({async:false,dataType:'json',url:'/?tpl=_json-pdf-items.tpl',success: function(d){pdf_date=d;}}); 

The contents of the JSON-formatted file will be something like this:

{   "pdf":{     "2010-06-29":{"link":"http://ganc-chas.by/attachment/000000026.pdf","title":" 25(391)  17.06.2010 -  pdf"},     "2010-06-04":{"link":"http://ganc-chas.by/attachment/000000025.pdf","title":" 23(389)  04.06.2010 -  pdf"}   } } 

And here's a jQuery part of the stuff (we use a slightly modified version which could be found at http://ganc-chas.by/templates/js/functions.js):

// PDF Archive Calendar $("#PDFArchive").datepicker({   changeMonth: true,   changeYear: true,   beforeShowDay: function(d){     var date = $.datepicker.formatDate("yy-mm-dd",d);     show=false;;caption="";link="#";     if (pdf_date.pdf[date]){       show=true;       style="ui-state-attention active";       caption=pdf_date.pdf[date].title;       link=pdf_date.pdf[date].link;     }     return [show,style,caption,link];   } }); 

The final output will be a small nifty Calendar containing all your PDF versions (you can see it in action at http://ganc-chas.by/by/page/archive/):

Calendar interface using jQuery.