diff options
| author | Unknown <Alee14498@gmail.com> | 2017-10-01 00:24:20 -0400 |
|---|---|---|
| committer | Unknown <Alee14498@gmail.com> | 2017-10-01 00:24:20 -0400 |
| commit | 78f3c0e9893d36e0ce039c2b79ede8a92ebe468a (patch) | |
| tree | 8479930f9372a1e9998b6750651565cf52b81ca8 /apps/calendar/lib.js | |
| parent | d8ba59582c137de474789690e777d8c029e08fe6 (diff) | |
| download | windows8online-78f3c0e9893d36e0ce039c2b79ede8a92ebe468a.tar.gz windows8online-78f3c0e9893d36e0ce039c2b79ede8a92ebe468a.tar.bz2 windows8online-78f3c0e9893d36e0ce039c2b79ede8a92ebe468a.zip | |
Adding the code
Diffstat (limited to 'apps/calendar/lib.js')
| -rw-r--r-- | apps/calendar/lib.js | 585 |
1 files changed, 585 insertions, 0 deletions
diff --git a/apps/calendar/lib.js b/apps/calendar/lib.js new file mode 100644 index 0000000..43327cc --- /dev/null +++ b/apps/calendar/lib.js @@ -0,0 +1,585 @@ +/* + Simple Planner + A localStorage based personal planner prototype + Made for 10K Apart + + Kailash Nadh, http://kailashnadh.name (August 2011) +*/ +var Planner = { + DAYS: ['Monday','Tuesday','Wednesday','Thursday','Friday','Saturday', 'Sunday'], + MONTHS: ['January','February','March','April','May','June','July','August','September','October','November','December'], + LABELS: ['todo', 'personal', 'work', 'important', 'misc'], + Date: new Date(), + UI: null, + EVENTS: {}, + diary_open: false, + + init: function() { + this.EVENTS = localStorage['events']; + if(!this.EVENTS) { + this.EVENTS = {}; + if(!localStorage.setup) { + // initial setup + var holidays = {'1-0': 'New Year', '8-2': 'Commonwealth Day', '17-2': 'St. Patrick\'s Day', '1-3': 'April fools', '22-3': 'Earth Day', '1-4': 'May Day', '5-4': 'Cinco de Mayo', '4-6': 'Independence Day (US)', '3-7': 'Friendship Day', '10-7': 'Rollercoaster Day', '17-8': 'International Day of Peace', '16-9': 'World Food Day', '31-9': 'Halloween', '4-10': 'Diwali', '17-10': 'World Peace Day', '22-10': 'Thanksgiving', '25-11': 'Christmas'}; + + for(var year=this.Date.getFullYear(); year<=this.Date.getFullYear()+1; year++) { + for(var id in holidays) { + this.createEvent( + id + '-' + year, + '00', + '00', + holidays[id], + 'misc' + ); + } + } + + // random entries + for(var i=0; i<7; i++) { + this.createEvent( + Math.floor(Math.random()*28) + '-'+ this.Date.getMonth() + '-'+ this.Date.getFullYear(), + Math.floor(Math.random()*23).pad(2), + '00', + 'This is a dummy event. The number ' + i + ' is cool!', + this.LABELS[Math.floor(Math.random()*(this.LABELS.length-1))] + ); + } + localStorage.setup = 1; + } + } else { + try{ + this.EVENTS = JSON.parse(this.EVENTS); + } catch(e) { + localStorage.clear(); + this.EVENTS = {}; + } + } + + this.phone = navigator.userAgent.match(/phone/i) || navigator.userAgent.match(/android/i); + + this.setDate(); + this.initUI(); + + // what month to render first? + var hash = document.location.href.match(/([0-9]{1,2})\-([0-9]{4})/i); + if(hash && hash[1] >= 1 && hash[1] <= 12 && hash[2] >= 1900 && hash[2] <= 2050) { + this.specificMonth(hash[1], hash[2]); + } else { + this.today(); + } + + // only load the diary on pageload if there's enough space to render it + Planner.renderDiary( $('.day' + this.date).data('id') ); + this.UI.resize(); + + Planner.UI.diary_wrap.show(); + var covered = (Planner.UI.diary_wrap.offset().left - Planner.UI.calendar_wrap.innerWidth()); + Planner.UI.diary_wrap.hide(); + if(!this.phone && covered > -35 && new Date().getMonth() == this.month ) { + Planner.showDiary(); + } + }, + initUI: function() { + this.UI = { + themes: ['Switch to dark theme', 'Switch to light theme'], + 'calendar': $('#calendar'), + 'dialog': $('#dialog'), + 'add': $('#add'), + 'calendar_wrap': $('#calendar-wrap'), + 'diary_wrap': $('#diary-wrap'), + 'event_label': $('#event-label'), + 'event_hour': $('#event-hour'), + 'event_minute': $('#event-minute'), + 'event_description': $('#event-description'), + 'event_delete': $('#event-delete'), + 'event_tweet': $('#event-tweet'), + 'diary': $('#diary') + }; + + // time in create event dialog + var val = ''; + for(i=0; i<24; i++) { + val = i.pad(2); + this.UI.event_hour.append( $('<option value="'+val+'">').html(val) ); + } + for(i=0; i<60; i+=15) { + val = i.pad(2); + val = val.substr(val.length-2); + this.UI.event_minute.append( $('<option value="'+val+'">').html(val) ); + } + + // label colors in create event dialog + var labels = $('<div class="labels">'), lbl = ''; + for(var i in this.LABELS) { + lbl = this.LABELS[i]; + labels.append( $('<label class="'+lbl+' label" for="label-'+lbl+'">'+lbl+' <input type="radio" name="event-label" value="'+lbl+'" id="label-'+lbl+'" class="'+ lbl +'"></label>') ); + } + this.UI.event_label.append(labels); + + // day names + var html = ''; + for(var i=0; i<7; i++) { + html += '<td>'+this.DAYS[i]+'</td>'; + } + $('thead').append( $('<tr>').html(html) ); + + // close add prompt + $('#event-close').click(function() { + Planner.closeAddPrompt(); + }); + $('#dialog-close').click(function() { + Planner.closeDialog(); + return false; + }); + $(document).keyup(function(e) { + if(e.altKey) return; + + if (e.keyCode == 27) { + Planner.closeAddPrompt(); + } else if (e.keyCode == 37) { + Planner.previousMonth(); + } else if (e.keyCode == 39) { + Planner.nextMonth(); + } else if (e.keyCode == 38 || e.keyCode == 40) { + Planner.today(); + } + }); + + + // event form add + this.UI.add.submit(function() { + Planner.createEvent( + Planner.new_id, + Planner.UI.event_hour.val(), + Planner.UI.event_minute.val(), + Planner.UI.event_description.val().replace(/<\/?(?!\!)[^>]*>/gi, ''), + Planner.UI.event_label.find('input[name="event-label"]:checked').val(), + Planner.event_i + ); + Planner.closeAddPrompt(); + Planner.renderEvents(); + if(Planner.diary_open) { + Planner.renderDiary(Planner.new_id); + } + return false; + }); + + this.UI.event_delete.click(function() { + var id = $(this).data('id'); + Planner.deleteEvent( id, $(this).data('i') ); + Planner.closeDialog(); + Planner.renderCalendar(); + Planner.renderDiary(id); + return false; + }); + + this.UI.event_tweet.click(function() { + var id = $(this).data('id'); + var tweet = Planner.EVENTS[id][$(this).data('i')]; + + window.open('http://twitter.com/home?status=' + escape(tweet.description + ' @ ' + tweet.hour + ':' + tweet.minute + ', ' + Planner.dateStringID(id)) ); + return false; + }); + + // previous and next buttons + $('#btn-previous').click(function() { + Planner.previousMonth(); + return false; + }); + $('#btn-next').click(function() { + Planner.nextMonth(); + return false; + }); + $('#btn-today').click(function() { + Planner.today(); + return false; + }); + + // theme + $('#btn-theme').click(function() { + var t = (parseInt($(this).data('theme'))+1) % 2; + localStorage.theme = t; + + Planner.theme(t); + $(this).data('theme', t).html( Planner.UI.themes[ (t+1)%2 ] ); + return false; + }); + if(localStorage.theme) { + Planner.theme(localStorage.theme); + $('#btn-theme').data('theme', localStorage.theme).html( this.UI.themes[(parseInt(localStorage.theme)+1) % 2] ); + } else { + $('#btn-theme').data('theme', 0 ).html( this.UI.themes[1] ); + } + + // ical + $('#ical-data').click(function() { + $(this).select(); + }); + $('#btn-ical').click(function() { + $('#ical-data').text(Planner.exportIcal()); + return false; + }); + + // diary close + $('#diary-close').click(function() { + this.diary_open = true; + Planner.UI.diary_wrap.hide(); + return false; + }); + + this.updateTime(); + window.setInterval(function() { + Planner.updateTime(); + }, 1000); + + this.UI.resize = function() { + var wh = $(window).height(), + ww = $(window).width(), + ch = 0; + var min = ( Math.min(ww, wh) ); + min = ( Math.max(min, 400) ); + + ch = min/1.2; + Planner.UI.calendar.width( ch + 105); + Planner.UI.calendar.height( ch + 105); + + $('td').css('width', ch/7); + + Planner.UI.diary_wrap.height('auto'); + Planner.UI.calendar_wrap.height('auto'); + + var box_height = Math.max(Planner.UI.calendar_wrap.outerHeight(), Planner.UI.diary_wrap.outerHeight(), wh); + + Planner.UI.calendar_wrap.height( box_height ); + Planner.UI.diary_wrap.height( box_height ); + + Planner.UI.diary_wrap.width('auto'); + + if( Planner.UI.calendar_wrap.outerWidth() + Planner.UI.diary_wrap.outerWidth() > ww ) { + $('body').addClass('compact'); + } else { + $('body').removeClass('compact'); + } + }; + $(window).resize(function() { + Planner.UI.resize(); + }); + }, + renderCalendar: function() { + document.location.href = '#' + ( this.month+1 + '-' + this.year ); + + // rest of the days + var wn = 0, + tblweek = null, + table = $('<tbody class="month'+this.month+'">'); + + if(this.weekstart > 0) { + tblweek = $('<tr>').addClass('w0'); + + // blank days + for(var i=0; i<this.weekstart; i++) { + tblweek.append($('<td class="day">')); + } + table.append(tblweek); + wn++; + } + + for(var d=1; d <=this.num_days; d++) { + var w = (this.weekstart+d-1)%7; + if(w == 0) { // new week + tblweek = $('<tr>'); + table.append(tblweek); + wn++; + } + + var id = d+'-'+this.month+'-'+this.year; + tblweek.append( + $('<td valign="top" class="day">').addClass('day'+d).addClass('day'+id) + .append( $('<div class="'+id+'">') + .append( $('<span class="d">').html(d) ) + .append( + $('<a href="#" title="add an event" class="add"></a>') + .data('id', id) + .click(function() { + Planner.addPrompt($(this).data('id')); + return false; + }) + ) + ).data('id', id).click(function() { + Planner.renderDiary( $(this).data('id') ); + Planner.showDiary(); + }) + ); + } + $('#calendar-title').html(this.MONTHS[this.month] + ' ' + this.year); + $('tbody').replaceWith(table); + + // today + $('.month' + new Date().getMonth() + ' .day' + this.date).addClass('today'); + $('.month' + this.month + ' .day' + this.date).addClass('marked'); + + + $('td.day').hover(function() { + $(this).find('.add').stop().animate({opacity: 1}, 300); + }, function() { + $(this).find('.add').stop().animate({opacity: 0}, 200); + }); + + this.renderEvents(); + }, + renderEvents: function() { + $('.d .events').remove(); + + for(var id in this.EVENTS) { + var ul = $('<ul>'); + $.each(this.EVENTS[id], function() { + ul.append( + $('<li class="label '+this.label+'">').append( + $('<span class="time">' + this.hour + ':' + this.minute + '</span>') + ).append( + $('<span class="desc">' + this.description + '</span>') + ) + ); + }); + + $('.'+id).append(ul); + } + + var stats = this.stats(); + $('#stats').html( stats.future + ' upcoming events and ' + stats.past + ' past events' ); + }, + showDiary: function() { + this.diary_open = true; + this.UI.diary_wrap.show(); + }, + renderDiary: function(id) { + $('#diary li').remove(); + $('#diary-title').html( this.dateStringID(id) ); + + $('.day').removeClass('selected'); + $('.day'+id).addClass('selected'); + + for(var i=0; i<24; i++) { + var hour = ('0' + i); + hour = hour.substr(hour.length-2); + + $('#diary').append( + $('<li>').append( + $('<a href="#" class="time">' + hour + ':00</a>').data({hour: hour, minute: '00'}) + .data('hour', hour) + .click(function() { + Planner.addPrompt(id, null, $(this).data('hour'), '00'); + return false; + }) + ).append('<div class="clear"> </div>') + .addClass('hour'+hour) + ); + } + + if(!this.EVENTS[id]) return; + + var removals={}; + $.each(this.EVENTS[id], function(i) { + $('#diary .hour'+this.hour).after( + $('<li>').append( + $('<a href="#" class="time label '+this.label+'">' + this.hour + ':' + this.minute + '</a>') + .click(function() { + Planner.addPrompt(id, i); + return false; + }) + ).append( + $('<span class="desc">' + this.description + ' </span>') + ).append('<div class="clear"> </div>') + ); + if(parseInt(this.minute) === 0) { + removals[this.hour] = true; + } + }); + + // remove redundant hours + for(var r in removals) { + $('#diary .hour' + r).remove(); + } + }, + dialog: function(target) { + this.UI.dialog.find('.target').hide(); + target.show(); + + // position + this.UI.dialog.width( this.UI.calendar.width()/2 ); + this.UI.dialog.css('top', ( $(window).height() - this.UI.dialog.height())/2) + .css('left', ( this.UI.calendar.width() - this.UI.dialog.width())/2); + + this.UI.dialog.show(); + }, + closeDialog: function() { + this.UI.dialog.hide(); + }, + addPrompt: function(id, i, hour, minute) { + this.new_id = id; + this.event_i = null; + + this.UI.event_description.val(''); + this.UI.event_label.find('input:first').attr('checked', 'checked'); + + this.UI.event_tweet.hide(); + this.UI.event_delete.hide(); + + // passing an existing item + if(id && i != null&& this.EVENTS[id][i]) { + this.UI.event_description.val( this.EVENTS[id][i].description ); + this.UI.event_hour.val( this.EVENTS[id][i].hour ); + this.UI.event_minute.val( this.EVENTS[id][i].minute ); + this.UI.event_label.find('.' + this.EVENTS[id][i].label + ' input').attr('checked', 'checked'); + + this.event_i = i; + this.UI.event_delete.data({id: id, i: i}).show(); + this.UI.event_tweet.data({id: id, i: i}).show(); + } else if(hour && minute) { + this.UI.event_hour.val( hour ); + this.UI.event_minute.val( minute ); + } + + $('#event-date').html( this.dateStringID(id) ); + this.dialog( this.UI.add ); + this.UI.event_description.focus(); + + return false; + }, + closeAddPrompt: function() { + this.closeDialog(); + }, + deleteEvent: function(id, i) { + this.EVENTS[id].splice(i,1); + localStorage['events'] = JSON.stringify(this.EVENTS); + }, + createEvent: function(id, hour, minute, description, label, i) { + if(!this.EVENTS[id]) { + this.EVENTS[id] = []; + } + + var entry = { + description: description, + hour: hour, + minute: minute, + label: label + }; + if(!i || i == null) { + this.EVENTS[id].push(entry); + } else { + this.EVENTS[id][i] = entry; + } + + this.EVENTS[id].sort(function(a, b) { + return parseInt(a.hour+''+a.minute) - parseInt(b.hour+''+b.minute); + }); + + localStorage['events'] = JSON.stringify(this.EVENTS); + }, + + exportIcal: function() { + var ical = ''; + + ical = 'BEGIN:VCALENDAR\nMETHOD:PUBLISH\nVERSION:2.0\nCALSCALE:GREGORIAN\n\n'; + for(var id in this.EVENTS) { + var date = Planner.dateFromID(id); + + $.each(this.EVENTS[id], function() { + ical+= 'BEGIN:VEVENT\n'; + ical+= 'DTSTART:'+ [date.getFullYear(), date.getMonth().pad(2), date.getDate().pad(2), 'T', this.hour, this.minute, '00'].join('') +'\n'; + ical+= 'SUMMARY:'+this.description+'\n'; + ical+= 'END:VEVENT\n\n'; + }); + } + ical+='\nEND:VCALENDAR'; + + return ical; + }, + + + today: function() { + this.Date = new Date(); + this.setDate(); + this.renderCalendar(); + }, + nextMonth: function() { + this.Date.setMonth(this.month+1); + this.setDate(); + this.renderCalendar(); + }, + previousMonth: function() { + this.Date.setMonth(this.Month-1 < 0 ? 11 : this.month-1); + this.setDate(); + this.renderCalendar(); + }, + specificMonth: function(m, y) { + this.Date.setMonth(m-1); + this.Date.setYear(y); + this.setDate(); + this.renderCalendar(); + }, + + weekDay: function(d) { + return (d-1).mod(7); + }, + setDate: function() { + this.day = this.Date.getDay(); + this.weekstart = new Date(this.Date.getTime()); + this.weekstart.setDate(1); + this.weekstart = this.weekDay( this.weekstart.getDay() ); + + this.date = this.Date.getDate(); + this.month = this.Date.getMonth(); + this.year = this.Date.getFullYear(); + + this.num_days = 32 - new Date(this.year, this.month, 32).getDate(); + }, + dateStringID: function(id) { + var date = this.dateFromID(id), + d = date.getDate() + + d+=(d>10 && d<20 ? 'th' : {1:'st', 2:'nd', 3:'rd'}[d % 10] || 'th'); + + return this.DAYS[ this.weekDay( date.getDay() ) ] + ', ' + + d + ' ' + this.MONTHS[date.getMonth()] + ', ' + date.getFullYear(); + }, + dateFromID: function(id) { + id = id.split('-'); + return new Date(id[2], id[1], id[0]); + }, + updateTime: function() { + var time = new Date(); + $('#time').html( time.getHours().pad(2) + ':' + time.getMinutes().pad(2) ); + }, + stats: function() { + var stats = {past: 0, future: 0}; + + var today = new Date(); + for(var id in this.EVENTS) { + var date = Planner.dateFromID(id); + + if(date.getTime() > today.getTime()) { + stats.future++; + } else { + stats.past++; + } + } + + return stats; + }, + theme: function(theme) { + $('body').removeClass(Planner.UI.themes.join(' ')).addClass( Planner.UI.themes[theme] ); + } +}; + +Number.prototype.mod = function(n) { + return ((this%n)+n)%n; +}; +Number.prototype.pad = function(n) { + var val = '0' + this; + return val.substr(val.length-n); +}; + +$(document).ready(function() { + Planner.init(); +});
\ No newline at end of file |
