/* EventCalendar. Copyright (C) 2005-2008, Alex Tingle. * This file is licensed under the GNU GPL. See LICENSE file for details. */ // Set in HTML file: // var ec3.start_of_week // var ec3.month_of_year // var ec3.month_abbrev // var ec3.myfiles // var ec3.home // var ec3.viewpostsfor /////////////////////////////////////////////////////////////////////////////// // namespace ec3 /////////////////////////////////////////////////////////////////////////////// var ec3 = { version:'3.2.beta2', /** Get today's date. * Note - DO THIS ONCE, so that the value of today never changes! */ today : new Date(), /** Global store for ec3.Calendar objects. */ calendars : [], allday : 'all day', ELEMENT_NODE: 1, TEXT_NODE: 3, init : function() { // Set-up calculated stuff about today. ec3.today_day_num = ec3.today.getDate(); ec3.today_month_num= ec3.today.getMonth() + 1; ec3.today_year_num = ec3.today.getFullYear(); // Pre-load image. ec3.imgwait=new Image(14,14); ec3.imgwait.src=ec3.myfiles+'/ec_load.gif'; // Convert strings from PHP into Unicode ec3.viewpostsfor=ec3.unencode(ec3.viewpostsfor); for(var i=0; i6) { tr=document.createElement('tr'); tbody.appendChild(tr); col=0; } if(col1 && !this.hide_logo) { a=document.createElement('a'); a.href='http://blog.firetree.net/?ec3_version='+ec3.version; a.title='Event Calendar '+ec3.version; td.style.verticalAlign='bottom'; td.appendChild(a); div=document.createElement('div'); div.className='ec3_ec'; div.align='right'; // keeps IE happy a.appendChild(div); } // set table's element id table.id=this.full_id('ec3_'+year_num+'_'+month_num); return table; }, // end create_calendar() /** Dispatch an XMLHttpRequest for a month of calendar entries. */ loadDates : function(month_num,year_num) { var req=new XMLHttpRequest(); if(req) { this.reqs.push(req); var self = this; req.onreadystatechange = function(){self.process_xml();}; var url=ec3.home+'/?feed=ec3xml&year='+year_num+'&monthnum='+month_num; if(this.is_listing) url+='&ec3_listing=events'; req.open("GET",url,true); this.set_spinner(1); req.send(null); } }, /** Obtain an array of all the calendar tables. */ get_calendars : function() { var result=new Array(); for(var i=0; i0) return result; else return 0; }, /** Changes the link text in the forward and backwards buttons. * Parameters are the 0-based month numbers. */ rewrite_controls : function(prev_month0,next_month0) { var prev=this.getElementById('ec3_prev'); if(prev && prev.firstChild && prev.firstChild.nodeType==ec3.TEXT_NODE) prev.firstChild.data='\u00ab\u00a0'+ec3.month_abbrev[prev_month0%12]; var next=this.getElementById('ec3_next'); if(next && next.firstChild && next.firstChild.nodeType==ec3.TEXT_NODE) next.firstChild.data=ec3.month_abbrev[next_month0%12]+'\u00a0\u00bb'; }, /** Turn the busy spinner on or off. */ set_spinner : function(on) { var spinner=this.getElementById('ec3_spinner'); var publish=this.getElementById('ec3_publish'); if(spinner) { if(on) { spinner.style.display='inline'; if(publish) publish.style.display='none'; } else { spinner.style.display='none'; if(publish) publish.style.display='inline'; } } }, /** Called when the user clicks the 'previous month' button. */ go_prev : function() { var calendars=this.get_calendars(); if(!calendars) return; var pn=calendars[0].parentNode; // calculate date of new calendar var id_array=this.short_id(calendars[0].id).split('_'); if(id_array.length<3) return; var year_num=parseInt(id_array[1]); var month_num=parseInt(id_array[2])-1; if(month_num==0) { month_num=12; year_num--; } // Get new calendar var newcal=this.getElementById('ec3_'+year_num+'_'+month_num); if(newcal) { // Add in the new first calendar newcal.style.display=this.calendar_display; } else { newcal=this.create_calendar(calendars[0],month_num,year_num); pn.insertBefore( newcal, calendars[0] ); this.loadDates(month_num,year_num); } // Hide the last calendar this.calendar_display=calendars[calendars.length-1].style.display; calendars[calendars.length-1].style.display='none'; // Re-write the forward & back buttons. this.rewrite_controls(month_num+10,month_num+calendars.length-1); }, /** Called when the user clicks the 'next month' button. */ go_next : function() { var calendars=this.get_calendars(); if(!calendars) return; var pn=calendars[0].parentNode; var last_cal=calendars[calendars.length-1]; // calculate date of new calendar var id_array=this.short_id(last_cal.id).split('_'); if(id_array.length<3) return; var year_num=parseInt(id_array[1]); var month_num=1+parseInt(id_array[2]); if(month_num==13) { month_num=1; year_num++; } // Get new calendar var newcal=this.getElementById('ec3_'+year_num+'_'+month_num); if(newcal) { // Add in the new last calendar newcal.style.display=this.calendar_display; } else { newcal=this.create_calendar(calendars[0],month_num,year_num); if(last_cal.nextSibling) pn.insertBefore(newcal,last_cal.nextSibling); else pn.appendChild(newcal); this.loadDates(month_num,year_num); } // Hide the first calendar this.calendar_display=calendars[0].style.display; calendars[0].style.display='none'; // Re-write the forward & back buttons. this.rewrite_controls(month_num-calendars.length+11,month_num); }, /** Triggered when the XML load is complete. Checks that load is OK, and then * updates calendar days. */ process_xml : function() { var busy=0; for(var i=0; i objects. */ details : [] } /////////////////////////////////////////////////////////////////////////////// /** xml.Calendar class - provides an easy to use interface to read the * XML loaded from ec3xml feeds. */ ec3.xml.Calendar = function(element) { this.element = element; this.init(); } ec3.xml.Calendar.prototype = { day : [], init : function() { var days=this.element.getElementsByTagName('day'); for(var i=0, len=days.length; i elements. */ ec3.xml.Day = function(calendar,element) { this.calendar = calendar; this.element = element; } ec3.xml.Day.prototype = { id : function(){ return this.element.getAttribute('id'); }, link : function(){ return this.element.getAttribute('link'); }, titles : function(){ return this.element.getAttribute('titles'); }, is_event: function(){ return ec3.attr2bool(this.element,'is_event'); }, /** Obtains the day's date as a Javascript Date object. */ date : function() { var d=this.element.getAttribute('date').split('-'); return new Date(parseInt(d[0],10),parseInt(d[1],10)-1,parseInt(d[2],10)); }, _events : function(result) { var all=this.element.getElementsByTagName('event'); if(all) { for(var i=0, len=all.length; i * elements. */ ec3.xml.Post = function(day,element) { this.day = day; this.element = element; } ec3.xml.Post.prototype = { kind : 'post', /** Returns a string intended to briefly summarise the post. */ brief : function() { return ''; }, // details link : function(){ return this._detail().getAttribute('link'); }, title : function(){ return this._detail().getAttribute('title'); }, excerpt: function() { var excerpts=this._detail().getElementsByTagName('excerpt'); if(excerpts) return excerpts[0].firstChild.data; else return ''; }, _detail : function() { return this.day.calendar._detail( this.element.getAttribute('post_id') ); } } /////////////////////////////////////////////////////////////////////////////// /** xml.Event class - provides an easy to use interface to read * elements. */ ec3.xml.Event = function(day,element) { this.day = day; this.element = element; } ec3.extend( ec3.xml.Event.prototype, ec3.xml.Post.prototype ); ec3.extend( ec3.xml.Event.prototype, { kind : 'event', allday : function(){ return ec3.attr2bool(this.element,'allday'); }, /** Returns a string intended to briefly summarise the event. */ brief : function() { if(this.allday()) return ec3.allday; var result = ''; var starts=this.element.getElementsByTagName('start'); var ends =this.element.getElementsByTagName('end'); if(starts && starts.length) { result = starts[0].getAttribute('time'); if(ends && ends.length) result += ' - ' + ends[0].getAttribute('time'); else result += '...'; } else { if(ends && ends.length) result = '...' + ends[0].getAttribute('time'); else result = '...'+ec3.allday+'...'; } return result; } });