Difference between revisions of "Widget:Calendar"

From Hackerspace ACKspace
Jump to: navigation, search
(added title per date support)
m (added multi-event dates support)
 
(28 intermediate revisions by the same user not shown)
Line 9: Line 9:
 
  <nowiki>{{#widget:</nowiki>{{PAGENAME}}<nowiki>
 
  <nowiki>{{#widget:</nowiki>{{PAGENAME}}<nowiki>
 
|date=february 26 2011
 
|date=february 26 2011
 +
|w=true
 
|hl.26 february 2011=blue
 
|hl.26 february 2011=blue
 
|hl.1 march 2011=red
 
|hl.1 march 2011=red
 +
|t.17 february 2011=First peek into ACKspace's new space
 
}}</nowiki>
 
}}</nowiki>
  
Line 16: Line 18:
 
{{#widget:{{PAGENAME}}
 
{{#widget:{{PAGENAME}}
 
|date=february 26 2011
 
|date=february 26 2011
 +
|w=true
 
|hl.26 february 2011=blue
 
|hl.26 february 2011=blue
 
|hl.1 march 2011=red
 
|hl.1 march 2011=red
 +
|t.17 february 2011=First peek into ACKspace's new space
 
}}<br/>
 
}}<br/>
  
Line 23: Line 27:
 
* all parameters are optional. If ''date'' is omitted, the current month will be displayed
 
* all parameters are optional. If ''date'' is omitted, the current month will be displayed
 
* you can highlight dates by using the ''hl'' parameter, followed by a dot and the date you want to highlight. Available colors are: red, green, blue, yellow, cyan and purple
 
* you can highlight dates by using the ''hl'' parameter, followed by a dot and the date you want to highlight. Available colors are: red, green, blue, yellow, cyan and purple
 +
* you can also add titles per-day using the 't' parameter, followed by a dot and the date you want to highlight.
 +
* w (show week numbers) is optional
  
 
== Copy to your site ==
 
== Copy to your site ==
Line 31: Line 37:
 
{
 
{
 
     "use strict";
 
     "use strict";
 +
 +
function getFirstWeekdayInMonth(year, month, dayOfWeek)
 +
{
 +
    var date = new Date(year, month, 1, 12);
 +
    date.setDate((dayOfWeek - date.getDay()+7) % 7 + 1);
 +
    return date;
 +
}
 +
function getLastWeekdayInMonth(year, month, dayOfWeek)
 +
{
 +
    var date = new Date(year, month+1, 0, 12);
 +
    date.setDate(date.getDate() - (date.getDay()+7-dayOfWeek) % 7);
 +
    return date;
 +
}
 +
  
 
     // ISO 8601 week number
 
     // ISO 8601 week number
Line 50: Line 70:
  
  
     if ( typeof Calendar === "undefined" )
+
     if ( typeof CalendarWidget === "undefined" )
 
     {
 
     {
         window.Calendar = function( _date )
+
        async function loadEvents()
 +
        {
 +
            const year = new Date().getFullYear();
 +
 
 +
            window.calendarEvents = Object.values((await (await fetch(`/wiki/Special:Ask/format%3Djson/limit%3D500/link%3Dall/headers%3Dshow/searchlabel%3DJSON/class%3Dsortable-20wikitable-20smwtable/sort%3D/order%3Dasc/offset%3D0/-5B-5BEventState::!Stalled-5D-5D-20-5B-5BEventStart::%E2%89%A431-20December-20${year}-5D-5D-20-5B-5BEventEnd::%E2%89%A51-20January-20${year}-5D-5D/-3FEventKind/-3FEventLocation/-3FURL/-3FEventStart/-3FEventEnd/mainlabel%3D/prettyprint%3Dtrue/unescape%3Dtrue`)).json()).results);
 +
 
 +
            // Repeating events: place at beginning of array to let other events override it.
 +
            const pizzaMeet = window.calendarEvents.find(event=>event.fulltext === "Pizza-meet");
 +
            const ackSession = window.calendarEvents.find(event=>event.fulltext === "ACKsession");
 +
 
 +
            // ACKsession: every month
 +
            window.calendarEvents.unshift(...Array(12).fill("").map((_, n)=>{
 +
                const item = JSON.parse(JSON.stringify(ackSession));
 +
                item.printouts.EventStart = item.printouts.EventEnd = [{ timestamp: getLastWeekdayInMonth(year,n,6) / 1000 }];
 +
                return item;
 +
            }));
 +
            // Pizza-meet: every quarter (0, 3, 6, 9)
 +
            window.calendarEvents.unshift(...[0, 3, 6, 9].map((n)=>{
 +
                const item = JSON.parse(JSON.stringify(pizzaMeet));
 +
                item.printouts.EventStart = item.printouts.EventEnd = [{ timestamp: getFirstWeekdayInMonth(year,n,6) / 1000 }];
 +
                return item;
 +
            }));
 +
            window.postMessage( window.calendarEvents, "*" );       
 +
        }
 +
        loadEvents();
 +
 
 +
         window.CalendarWidget = function( _date, _showWeekNumber )
 
         {
 
         {
 +
            // Listen for async calendarEvents
 +
            if ( !window.calendarEvents )
 +
                window.addEventListener( "message", this._update.bind( this ), false );
 +
 +
            this._showWeekNumber = _showWeekNumber || false;
 
             // Fill in the months and weekdays once
 
             // Fill in the months and weekdays once
             if ( !Calendar.prototype._arrMonths )
+
             if ( !CalendarWidget.prototype._arrMonths )
 
             {
 
             {
 
                 // Check for localization support
 
                 // Check for localization support
Line 61: Line 112:
 
                 {
 
                 {
 
                     var n;
 
                     var n;
                     Calendar.prototype._arrMonths = [];
+
                     CalendarWidget.prototype._arrMonths = [];
                     Calendar.prototype._arrWeekDays = [];
+
                     CalendarWidget.prototype._arrWeekDays = [];
 
              
 
              
 
                     for ( n = 0; n < 12; n++ )
 
                     for ( n = 0; n < 12; n++ )
                         Calendar.prototype._arrMonths.push( new Date( 1 + n + " 20 1970" ).toLocaleString( false, { month: "long" } ) );
+
                         CalendarWidget.prototype._arrMonths.push( new Date( 1 + n + " 20 1970" ).toLocaleString( false, { month: "long" } ) );
 
              
 
              
 
                     for ( n = 0; n < 7; n++ )
 
                     for ( n = 0; n < 7; n++ )
                         Calendar.prototype._arrWeekDays.push( new Date( 5 + n + " jan 1970" ).toLocaleString( false, { weekday: "short" } ) );
+
                         CalendarWidget.prototype._arrWeekDays.push( new Date( 5 + n + " jan 1970" ).toLocaleString( false, { weekday: "short" } ) );
 
                 }
 
                 }
 
                 else
 
                 else
 
                 {
 
                 {
                     Calendar.prototype._arrMonths = Calendar.prototype._arrMonths_en_us;
+
                     CalendarWidget.prototype._arrMonths = CalendarWidget.prototype._arrMonths_en_us;
                     Calendar.prototype._arrWeekDays = Calendar.prototype._arrWeekDays_en_us;
+
                     CalendarWidget.prototype._arrWeekDays = CalendarWidget.prototype._arrWeekDays_en_us;
 
                 }
 
                 }
 
             }
 
             }
Line 81: Line 132:
 
             this._tblCalendar = document.createElement( "table" );
 
             this._tblCalendar = document.createElement( "table" );
 
             this._today = new Date( );
 
             this._today = new Date( );
 +
            this._today.setHours( 0, 0, 0, 0 );
 
             this._date = _date ? new Date( _date ): this._today;
 
             this._date = _date ? new Date( _date ): this._today;
 
             this._date.setHours( 0, 0, 0, 0 );
 
             this._date.setHours( 0, 0, 0, 0 );
 
         }
 
         }
 
          
 
          
         Calendar.prototype._arrMonths = null;
+
         CalendarWidget.prototype._arrMonths = null;
         Calendar.prototype._arrWeekDays = null;
+
         CalendarWidget.prototype._arrWeekDays = null;
         Calendar.prototype._arrMonths_en_us = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ];
+
         CalendarWidget.prototype._arrMonths_en_us = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ];
         Calendar.prototype._arrWeekDays_en_us = [ "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" ];
+
         CalendarWidget.prototype._arrWeekDays_en_us = [ "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" ];
 
          
 
          
         Calendar.prototype._tblCalendar = null;
+
         CalendarWidget.prototype._tblCalendar = null;
         Calendar.prototype._today = null;
+
         CalendarWidget.prototype._today = null;
         Calendar.prototype._date = null;
+
         CalendarWidget.prototype._date = null;
         Calendar.prototype.hl = null;
+
         CalendarWidget.prototype.hl = null;
         Calendar.prototype.t = null;
+
         CalendarWidget.prototype.t = null;
 +
 
 +
        CalendarWidget.prototype._update = function( _event )
 +
        {
 +
            var oldTable = document.getElementById( this._tblCalendar.id );
 +
            this._tblCalendar = document.createElement( "table" );
 +
            this._gen( _event.data );
 +
            oldTable.parentNode.replaceChild( this._tblCalendar, oldTable );
 +
        }
  
         Calendar.prototype._gen = function( )
+
         CalendarWidget.prototype._gen = function( _dates )
 
         {
 
         {
 
             var date = new Date( this._date.getFullYear(), this._date.getMonth(), 1 );
 
             var date = new Date( this._date.getFullYear(), this._date.getMonth(), 1 );
Line 105: Line 165:
 
          
 
          
 
             this._tblCalendar.className = "calendar";
 
             this._tblCalendar.className = "calendar";
       
+
             this._tblCalendar.id = "c" + ( Math.random() * 10e8 | 0 );
            // Show week numbers
+
 
             var w = false;
 
       
 
 
             // Month and year
 
             // Month and year
 
             row = this._tblCalendar.appendChild( document.createElement( "tr" ) ).appendChild( document.createElement( "th" ) );
 
             row = this._tblCalendar.appendChild( document.createElement( "tr" ) ).appendChild( document.createElement( "th" ) );
             row.setAttribute( "colspan", w ? 8 : 7 );
+
             row.setAttribute( "colspan", this._showWeekNumber ? 8 : 7 );
 
             row.appendChild( document.createTextNode( this._arrMonths[ date.getMonth( ) ] + " " + date.getFullYear( ) ) );
 
             row.appendChild( document.createTextNode( this._arrMonths[ date.getMonth( ) ] + " " + date.getFullYear( ) ) );
 
          
 
          
 
             // Weekdays
 
             // Weekdays
 
             row = this._tblCalendar.appendChild( document.createElement( "tr" ) );
 
             row = this._tblCalendar.appendChild( document.createElement( "tr" ) );
             if ( w )
+
             if ( this._showWeekNumber )
 
                 row.appendChild( document.createElement( "th" ) ).appendChild( document.createTextNode( "w" ) );
 
                 row.appendChild( document.createElement( "th" ) ).appendChild( document.createTextNode( "w" ) );
 
             for ( var d = 0; d < 7; d++ )
 
             for ( var d = 0; d < 7; d++ )
Line 125: Line 183:
 
                 // create row
 
                 // create row
 
                 row = this._tblCalendar.appendChild( document.createElement( "tr" ) );
 
                 row = this._tblCalendar.appendChild( document.createElement( "tr" ) );
                 if ( w )
+
                 if ( this._showWeekNumber )
 
                     row.appendChild( document.createElement( "td" ) ).appendChild( document.createTextNode( "(" + curDate.getWeek() + ")" ) );
 
                     row.appendChild( document.createElement( "td" ) ).appendChild( document.createTextNode( "(" + curDate.getWeek() + ")" ) );
 
          
 
          
Line 133: Line 191:
 
                     // mark n/a if date is not part of the current month
 
                     // mark n/a if date is not part of the current month
 
                     td = document.createElement( "td" );
 
                     td = document.createElement( "td" );
 +
                    td.appendChild( document.createTextNode( curDate.getDate( ) ) );
 
          
 
          
 
                     if ( curDate.getMonth() !== date.getMonth() )
 
                     if ( curDate.getMonth() !== date.getMonth() )
Line 140: Line 199:
 
                     if ( curDate.getTime() in this.hl )
 
                     if ( curDate.getTime() in this.hl )
 
                         td.className += " " + this.hl[ curDate.getTime() ];
 
                         td.className += " " + this.hl[ curDate.getTime() ];
 +
                    else
 +
                        this._determineColor( td, curDate, _dates || [] );
 
                     if ( curDate.getTime() in this.t )
 
                     if ( curDate.getTime() in this.t )
 +
                    {
 
                         td.title = this.t[ curDate.getTime() ];
 
                         td.title = this.t[ curDate.getTime() ];
 +
                        td.className += " title";
 +
                    }
 +
                    else
 +
                        this._determineTitle( td, curDate, _dates || [] );
  
                     row.appendChild( td ).appendChild( document.createTextNode( curDate.getDate( ) ) );
+
                     row.appendChild( td );
 
                     curDate.setDate( curDate.getDate() + 1 );
 
                     curDate.setDate( curDate.getDate() + 1 );
 
                 }
 
                 }
 +
            }
 +
        };
 +
 +
        CalendarWidget.prototype._determineColor = function( _td, _curDate, _dates )
 +
        {
 +
            var eventKinds = _td.title = _dates.filter( function( _date )
 +
            {
 +
                return _date.printouts.EventStart.find((es,i) => {
 +
                    var start = new Date( _date.printouts.EventStart[i].timestamp*1000 );
 +
                    var end = new Date( _date.printouts.EventEnd[i].timestamp*1000 );
 +
                    // 'Fix' timezone
 +
                    start.setHours( 0, 0, 0, 0 );
 +
                    end.setHours( 0, 0, 0, 0 );
 +
                    return _curDate >= start && _curDate <= end;
 +
                });
 +
            } ).map( function( _date )
 +
            {
 +
                return _date.printouts.EventKind;
 +
            } ).join(",").split(",");
 +
 +
            if ( eventKinds.includes( "Conference" ) )
 +
                _td.className += " hl-purple";
 +
            else if ( eventKinds.includes( "Festival" ) || eventKinds.includes( "Party" ) )
 +
                _td.className += " hl-green";
 +
            else if ( eventKinds.includes( "Meeting" ) )
 +
                _td.className += " hl-yellow";
 +
            else if ( eventKinds.includes( "Lecture" ) )
 +
                _td.className += " hl-blue";
 +
            else if (eventKinds.join())
 +
                _td.className += " hl-red";
 +
        };
 +
 +
        CalendarWidget.prototype._determineTitle = function( _td, _curDate, _dates )
 +
        {
 +
            var dates = _dates.filter( function( _date )
 +
            {
 +
                return _date.printouts.EventStart.find((es,i) => {
 +
                    var start = new Date( _date.printouts.EventStart[i].timestamp*1000 );
 +
                    var end = new Date( _date.printouts.EventEnd[i].timestamp*1000 );
 +
                    // 'Fix' timezone
 +
                    start.setHours( 0, 0, 0, 0 );
 +
                    end.setHours( 0, 0, 0, 0 );
 +
                    return _curDate >= start && _curDate <= end;
 +
                });
 +
            } );
 +
            _td.title = dates.map( function( _date )
 +
            {
 +
                return _date.fulltext;
 +
            } ).join( ", " );
 +
            if ( _td.title )
 +
            {
 +
                _td.className += " title";
 +
                if ( dates.length === 1 )
 +
                    _td.innerHTML = '<a href="'+dates[0].fullurl+'">' + _td.innerHTML + '</a>';
 
             }
 
             }
 
         };
 
         };
 
          
 
          
         Calendar.prototype.place = function( _node )
+
         CalendarWidget.prototype.place = function( _node )
 
         {
 
         {
 
             this._gen();
 
             this._gen();
Line 155: Line 275:
 
         }
 
         }
  
         Calendar.prototype.toString = function( )
+
         CalendarWidget.prototype.toString = function( )
 
         {
 
         {
 
             this._gen();
 
             this._gen();
Line 162: Line 282:
 
     }
 
     }
  
     var calendar = new Calendar( "<!--{$date|escape:html}-->" );
+
     var calendar = new CalendarWidget( "<!--{$date|escape:html}-->", "<!--{$w|escape:html}-->" );
 
<!--{foreach from=$hl key=d item=col}-->
 
<!--{foreach from=$hl key=d item=col}-->
 
     calendar.hl[ new Date( "<!--{$d|escape:'html'}-->" ).getTime() ] = "hl-<!--{$col|escape:'html'}-->";
 
     calendar.hl[ new Date( "<!--{$d|escape:'html'}-->" ).getTime() ] = "hl-<!--{$col|escape:'html'}-->";
 
<!--{/foreach}-->
 
<!--{/foreach}-->
 
<!--{foreach from=$t key=d item=text}-->
 
<!--{foreach from=$t key=d item=text}-->
     calendar.t[ new Date( "<!--{$d|escape:'html'}-->" ).getTime() ] = "hl-<!--{$text|escape:'html'}-->";
+
     calendar.t[ new Date( "<!--{$d|escape:'html'}-->" ).getTime() ] = "<!--{$text|escape:'quotes'}-->";
 
<!--{/foreach}-->
 
<!--{/foreach}-->
 
     document.write( calendar );
 
     document.write( calendar );

Latest revision as of 21:40, 14 October 2023

This widget allows you to display a calendar

Created by Xopr

Using this widget

To insert this widget, use the following code:

{{#widget:Calendar
|date=february 26 2011
|w=true
|hl.26 february 2011=blue
|hl.1 march 2011=red
|t.17 february 2011=First peek into ACKspace's new space
}}

This will give the following result:

Note:

  • all parameters are optional. If date is omitted, the current month will be displayed
  • you can highlight dates by using the hl parameter, followed by a dot and the date you want to highlight. Available colors are: red, green, blue, yellow, cyan and purple
  • you can also add titles per-day using the 't' parameter, followed by a dot and the date you want to highlight.
  • w (show week numbers) is optional

Copy to your site

To use this widget on your site, just install MediaWiki Widgets extension and copy full source code of this page to your wiki as Widget:Calendar article.