diff options
Diffstat (limited to 'apps/calendar')
| -rw-r--r-- | apps/calendar/css/charms.css | 195 | ||||
| -rw-r--r-- | apps/calendar/img/close-light.png | bin | 0 -> 3786 bytes | |||
| -rw-r--r-- | apps/calendar/img/close.png | bin | 0 -> 3516 bytes | |||
| -rw-r--r-- | apps/calendar/img/left-light.png | bin | 0 -> 3572 bytes | |||
| -rw-r--r-- | apps/calendar/img/left.png | bin | 0 -> 3644 bytes | |||
| -rw-r--r-- | apps/calendar/img/plus-light.png | bin | 0 -> 3525 bytes | |||
| -rw-r--r-- | apps/calendar/img/plus.png | bin | 0 -> 3597 bytes | |||
| -rw-r--r-- | apps/calendar/img/right-light.png | bin | 0 -> 3667 bytes | |||
| -rw-r--r-- | apps/calendar/img/right.png | bin | 0 -> 3711 bytes | |||
| -rw-r--r-- | apps/calendar/index.html | 170 | ||||
| -rw-r--r-- | apps/calendar/lib.js | 585 | ||||
| -rw-r--r-- | apps/calendar/splashscreen.png | bin | 0 -> 3038 bytes | |||
| -rw-r--r-- | apps/calendar/style.css | 498 |
13 files changed, 1448 insertions, 0 deletions
diff --git a/apps/calendar/css/charms.css b/apps/calendar/css/charms.css new file mode 100644 index 0000000..54337b7 --- /dev/null +++ b/apps/calendar/css/charms.css @@ -0,0 +1,195 @@ +body { + font-family:Segoe UI; + margin:0px; + padding:0px; +} +img, a { + outline:none; + border:none; +} +#splashscreen { + position:fixed; + width:100%; + height:100%; + color:#FFFFFF; + background-image:url('../splashscreen.png'); + background-position:center; + background-color:#5133AB; + background-repeat:no-repeat; + animation:splash 4s; + -ms-animation:splash 4s; + -webkit-animation:splash 4s; + -o-animation:splash 4s; + opacity:0; + z-index:-1; +} +@keyframes splash { + from { + z-index:2; + opacity: 1; + } + 66% { + opacity: 1; + } + to { + opacity:0; + z-index:1; + display:none; + } +} +@-webkit-keyframes splash { + from { + z-index:2; + opacity: 1; + } + 66% { + opacity: 1; + } + to { + opacity:0; + z-index:1; + display:none; + } +} +@-ms-keyframes splash { + from { + z-index:2; + opacity: 1; + } + 66% { + opacity: 1; + } + to { + opacity:0; + z-index:1; + display:none; + } +} +@-o-keyframes splash { + from { + z-index:2; + opacity: 1; + } + 66% { + opacity: 1; + } + to { + opacity:0; + z-index:1; + display:none; + } +} +#hoverarea { + position:fixed; + top:0px; + right:0px; + width:15px; + height:15px; +} +#bottomhoverarea { + position:fixed; + bottom:0px; + right:0px; + width:15px; + height:15px; +} +#starthoverarea { + position:fixed; + bottom:0px; + left:0px; + width:15px; + height:15px; +} +#charmsbar { + display:none; + background-color:#111111; + position:fixed; + padding:5% 0; + top:0px; + right:0px; + height:100%; + width: 86px; + +} +#settingscharms { + padding : 40px; + display:none; + background-color:#5133AB; + position:fixed; + top:0px; + right:0px; + height:100%; + width: 345px; + font-size:9pt; + color:#FFFFFF !important; +} +#settingscharms a { + color:#FFFFFF !important; +} +#startbutton { + display:none; + position:fixed; + left:0px; + bottom:0px; +} +#iconnetwork { + position:absolute; + top:35px; + left:25px; +} +#iconbattery { + position:absolute; + bottom:35px; + left:32px; +} +#datetime { + display:none; + position:fixed; + left:50px; + bottom:50px; + width:490px; + height:139px; + background-color: rgba(17,17,17,1); +} +#ctime { + position:absolute; + left:70px; + bottom:19px; + font-family: Segoe UI Light; + font-size: 64pt; + color:#FFFFFF; +} +#date { + margin-top:20px; + margin-right:20px; + float:right; + font-size:24pt; + font-family: Segoe UI; + color:#FFFFFF; +} +.cheading1 { + font-family:Segoe UI Semilight; + font-size:28px; + margin-bottom:25px; + display:block; +} +.cheading2 { + font-size:11pt; + margin-bottom:25px; + display:block; +} +.cheading2d { + font-size:11pt; + color:#A8A8A8; + margin-bottom:25px; + display:block; +} +#settingscharms a { + display:block; + margin-bottom:25px; +} +.closecharms { + width:32px; + height:32px; + float:right; +}
\ No newline at end of file diff --git a/apps/calendar/img/close-light.png b/apps/calendar/img/close-light.png Binary files differnew file mode 100644 index 0000000..3ede172 --- /dev/null +++ b/apps/calendar/img/close-light.png diff --git a/apps/calendar/img/close.png b/apps/calendar/img/close.png Binary files differnew file mode 100644 index 0000000..7173f58 --- /dev/null +++ b/apps/calendar/img/close.png diff --git a/apps/calendar/img/left-light.png b/apps/calendar/img/left-light.png Binary files differnew file mode 100644 index 0000000..b581ca9 --- /dev/null +++ b/apps/calendar/img/left-light.png diff --git a/apps/calendar/img/left.png b/apps/calendar/img/left.png Binary files differnew file mode 100644 index 0000000..02d77e1 --- /dev/null +++ b/apps/calendar/img/left.png diff --git a/apps/calendar/img/plus-light.png b/apps/calendar/img/plus-light.png Binary files differnew file mode 100644 index 0000000..40039c0 --- /dev/null +++ b/apps/calendar/img/plus-light.png diff --git a/apps/calendar/img/plus.png b/apps/calendar/img/plus.png Binary files differnew file mode 100644 index 0000000..19d9cf6 --- /dev/null +++ b/apps/calendar/img/plus.png diff --git a/apps/calendar/img/right-light.png b/apps/calendar/img/right-light.png Binary files differnew file mode 100644 index 0000000..0bb359b --- /dev/null +++ b/apps/calendar/img/right-light.png diff --git a/apps/calendar/img/right.png b/apps/calendar/img/right.png Binary files differnew file mode 100644 index 0000000..e915318 --- /dev/null +++ b/apps/calendar/img/right.png diff --git a/apps/calendar/index.html b/apps/calendar/index.html new file mode 100644 index 0000000..fbe49c8 --- /dev/null +++ b/apps/calendar/index.html @@ -0,0 +1,170 @@ +<!DOCTYPE html> +<html lang="en-US"> +<head> + <title>Calendar</title> + <meta charset="utf-8" /> + <meta http-equiv="x-ua-compatible" content="IE=edge"> + <link href="style.css" rel="stylesheet" type="text/css" /> + <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.6.2.min.js"></script> + <script src="lib.js"></script> + <!--Stylesheet that styles the charms bar and the startbutton --> + <link rel="stylesheet" href="css/charms.css"/> + <!--Script that powers the charms bar--> + <script> +function charms(){ + document.getElementById('charmsbar').style.display='block'; + document.getElementById('datetime').style.display='block'; + document.getElementById('ctime').style.display='inline'; +} +function destroycharms() { + document.getElementById('charmsbar').style.display='none'; + document.getElementById('datetime').style.display='none'; + document.getElementById('ctime').style.display='none'; +} +function start(){ + document.getElementById('startbutton').style.display='block'; +} +function destroystart() { + document.getElementById('startbutton').style.display='none'; +} + </script> +<script> +var settingscharms = 'document.getElementById('settingscharms')' +</script> +</head> +<body class="dark"> +<div id="splashscreen"></div> +<div id="calendar-wrap" class="box"> + <div id="calendar"> + <h1 id="calendar-title"> </h1> + <ul id="controls"> + <li><a href="#" id="btn-previous"></a></li> + <li><a href="#" id="btn-today">Today</a></li> + <li><a href="#" id="btn-next"></a></li> + </ul> + <div class="clear"> </div> + <h3 id="time"> </h3> + <table id="table"> + <thead> + </thead> + <tbody> + </tbody> + </table> + <div class="clear"> </div> + <span id="stats"></span> + <!--<p class="info"> + Click on a date to view events. Use arrow keys to browser the calendar. + </p> + <div class="clear"> </div--> + </div> + <div class="clear"> </div> +</div> + +<div id="diary-wrap" class="box"> + <div class="content"> + <a href="#" id="diary-close"></a> + <h2 id="diary-title"> </h2> + <div class="clear"> </div> + + <ul id="diary"></ul> + <p class="info">Click on a time to add an event</p> + </div> +</div> + +<div id="dialog"> + <a href="" id="dialog-close"/></a> + <form id="add" class="target"> + <h2 id="event-date"></h2> + <p class="time"> + <label>Event time</label> + Hour <select id="event-hour"></select> + Minute <select id="event-minute"></select> + </p> + <p> + <label>Event description</label> + <input type="text" id="event-description" maxlength="100" /> + </p> + <div id="event-label"> + </div> + <p class="buttons"> + <input type="submit" id="event-create" value="ok" class="button" /> + <input type="button" id="event-close" value="cancel" class="button" /> + <input type="button" id="event-delete" value="delete" class="button" /> + <input type="button" id="event-tweet" value="tweet" class="button" /> + </p> + </form> + + <div id="ical2" class="target"> + Copy the text and save it as calendar.ics file.<br /> + <small>You can then import the file to Google Calendar, iCal etc.</small> + <textarea id="ical-data2"> </textarea> + </div> +</div> +<div class="clear"> </div> + <!-- CHARMS BAR CODE --> +<div id="hoverarea" onmouseover="charms()" class="hotcorner"> +</div> +<div id="charmsbar" onmouseover="charms()" onmouseout="destroycharms()"> +<img src="../../common/img/charmsbar/search.png" onmouseover="this.src='../../common/img/charmsbar/search-hover.png'" onmouseout="this.src='../../common/img/charmsbar/search.png'"/><br/> +<img src="../../common/img/charmsbar/share.png" onmouseover="this.src='../../common/img/charmsbar/share-hover.png'" onmouseout="this.src='../../common/img/charmsbar/share.png'"/><br/> +<a href="../../start/index.html"><img src="../../common/img/charmsbar/start.png" onmouseover="this.src='../../common/img/charmsbar/start-hover.png'" onmouseout="this.src='../../common/img/charmsbar/start.png'"/></a><br/> +<img src="../../common/img/charmsbar/devices.png" onmouseover="this.src='../../common/img/charmsbar/devices-hover.png'" onmouseout="this.src='../../common/img/charmsbar/devices.png'"/><br/> +<img src="../../common/img/charmsbar/settings.png" onmouseover="this.src='../../common/img/charmsbar/settings-hover.png'" onmouseout="this.src='../../common/img/charmsbar/settings.png'" onclick="settingscharms.style.display='block'"/><br/> +</div> +<div id="datetime"> +<img src="../../common/img/network.png" id="iconnetwork" height="24px" width="24px"/> +<img src="../../common/img/battery.png" id="iconbattery"/> +<span id="ctime"></span> +<script language="javascript" type="text/javascript"> +<!-- Begin +function clock() { +var digital = new Date(); +var hours = digital.getHours(); +var minutes = digital.getMinutes(); +var seconds = digital.getSeconds(); +var amOrPm = "AM"; +if (hours > 11) amOrPm = "PM"; +if (hours > 12) hours = hours - 12; +if (hours == 0) hours = 12; +if (minutes <= 9) minutes = "0" + minutes; +if (seconds <= 9) seconds = "0" + seconds; +dispTime = hours + ":" + minutes ; +document.getElementById('ctime').innerHTML = dispTime; +setTimeout("clock()", 1000); +} +window.onload=clock; +// End --> +</script> +<div id="date"><script language="Javascript"> + + var dayName = new Array ("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday") + + var monName = new Array ("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December") + + var now = new Date + + document.write("" + dayName[now.getDay()] + "<br/>" +"<span id=month>" + monName[now.getMonth()] + " "+now.getDate() +"") + </script> +</div> +</div> +<div id="bottomhoverarea" onmouseover="charms()" class="hotcorner"> +</div> +<div id="starthoverarea" onmouseover="start()" class="hotcorner"> +</div> +<div id="startbutton" onmouseout="destroystart()"> +<a href="../../start/index.html"><img src="../../common/img/start.png"/></a> +</div> +<div id="settingscharms"> +<img src="img/close.png" class="closecharms" onclick="settingscharms.style.display='none'"/> +<span class="cheading1">Settings</span> +<span class="cheading2d">Calendar</span> +<span class="cheading2">Theme</span> +<a href="#" id="btn-theme">light</a> +<span class="cheading2">Get as iCal</span> +<a href="#" id="btn-ical">Click here to show code</a> +<div id="ical"> +<textarea id="ical-data"></textarea> +</div> +</div> +</body> +</html>
\ No newline at end of file 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 diff --git a/apps/calendar/splashscreen.png b/apps/calendar/splashscreen.png Binary files differnew file mode 100644 index 0000000..4e5c822 --- /dev/null +++ b/apps/calendar/splashscreen.png diff --git a/apps/calendar/style.css b/apps/calendar/style.css new file mode 100644 index 0000000..4e1112a --- /dev/null +++ b/apps/calendar/style.css @@ -0,0 +1,498 @@ +html { + height: 100%; +} +body { + background: #eee; + font-family: Segoe UI; + font-size: 1em; + color: #000; + height: 100%; + margin: 0; + padding: 0; + transition:all 1s ease 0s; + -moz-transition:all 1s ease 0s; + -webkit-transition:all 1s ease 0s; +} +a { +outline:none; +} + +.box { + background: #fff; + box-shadow: 0 0 30px #ddd; +} + +#calendar-wrap { + padding-right: 35px; + float: left; + z-index: 1; + overflow: hidden; + transition:all 1s ease 0s; + -moz-transition:all 1s ease 0s; + -webkit-transition:all 1s ease 0s; +} + #calendar { + position: relative; + margin: 15px; + } + #stats { + color: #aaa; + line-height: 40px; + font-size:14pt; + } + #calendar-title { + + margin-bottom: 10px; + float: left; + width: 40%; + font-family:Segoe UI Light; + color: rgb(0, 114, 198); + transition:all 1s ease 0s; + -moz-transition:all 1s ease 0s; + -webkit-transition:all 1s ease 0s; + } + #time { + color: #999; + } + +table { + width: 100%; + height: 80%; + margin-top: -20px; + border-spacing: 0; +} +thead td { + font-size: 11px; + text-transform:uppercase; + color: rgb(102, 102, 102); + + height: 40px; +} +tbody td { + border-width: 0 1px 1px 0; + border-style: solid; + border-color: #ddd; + padding: 10px; + overflow: hidden; +} +thead td { + border-bottom: 1px solid #ddd; +} +tbody tr td:nth-child(1) { + border-left: 1px solid #ddd; +} + +.day { + background: #fff url('w.png') repeat-x bottom left; + overflow: hidden; + cursor: pointer; +} +.day div { + position: relative; +} +.day:hover { + background: #fff; +} +.day .d { + position: absolute; + top: 0; + right: 0; +} +.selected .d { + text-decoration: underline; +} +.today { + background: #DFEDFA; + border-top:3px solid #0072C6; +} + .marked .d { + font-weight: bold; + } +#btn-previous { + width:32px; + height:32px; + padding:0px !important; + background-image:url(img/left-light.png) !important; + background-color:transparent !important; + vertical-align:middle; + opacity:0.8; + +} +#btn-next { + width:32px; + height:32px; + padding:0px !important; + background-image:url(img/right-light.png) !important; + background-color:transparent !important; + vertical-align:middle; + opacity:0.8; +} +#btn-previous:hover , #btn-next:hover { + opacity:1; +} +#btn-today { + padding:0px !important; + background-color:transparent !important; + font-size:14pt !important; + vertical-align:middle; + margin-left:50px; + margin-right:50px; + color:#000; + transition:all 2s ease 0s; + -moz-transition:all 2s ease 0s; + -webkit-transition:all 2s ease 0s; + +} +.day .add { + position: absolute; + top: 0px; + left: 0px; + line-height: 16px; + width: 16px; + height: 16px; + opacity: 0; + background-image:url(img/plus-light.png); + background-size:16px 16px; +} + .day ul { + position: absolute; + font-size: 11px; + top: 25px; + width: 100%; + } + .day li { + padding: 2px; + width: 100%; + margin-bottom: 1px; + overflow: hidden; + height: 14px; + } + .day ul .time { + margin-right: 5px; + } + + +#diary-wrap { + border-left: 1px solid #ddd; + float: left; + width: 30%; + display: none; + transition:all 1s ease 0s; + -moz-transition:all 1s ease 0s; + -webkit-transition:all 1s ease 0s; +} + #diary-title { + float: left; + color: rgb(0, 114, 198); + font-family:Segoe UI Light; + } + #diary-close { + float: left; + margin: 1px 15px 10px 0; + background-image:url(img/close-light.png); + width:32px; + height:32px; + } + + #diary-wrap .content { + margin: 15px; + } + .compact #diary-wrap { + position: absolute; + top: 0; + right: 0; + z-index: 5; + margin-left: 40px; + } + .compact #calendar-title { + float: none; + } + .compact #controls { + float: none; + } +#diary { + font-size: 12px; + margin: 15px; + transition:all 1s ease 0s; + -moz-transition:all 1s ease 0s; + -webkit-transition:all 1s ease 0s; +} + #diary li { + margin-bottom: 3px; + } + #diary .time { + background: #bbb; + color: #fff; + padding: 2px; + display: block; + width: 100px; + float: left; + margin-right: 15px; + } + #diary .time:hover { + background: #000; + } + #diary .desc { + display: inline-block; + padding: 0 0 3px 0; + overflow: hidden; + border-bottom: 1px solid #ddd; + } + +#dialog { + background: #fff url('w.png') repeat-x bottom left; + display: none; + padding: 15px 25px; + position: absolute; + z-index: 10; + + box-shadow: 0 0 30px #aaa; +} + #dialog-close { + float: right; + margin: -5px -15px 10px 10px; + background-image:url(img/close-light.png); + width:32px; + height:32px; + } + #dialog .target { + display: none; + } + + + #add #event-description { + width: 90%; + } + #add label { + display: block; + font-weight: bold; + margin-bottom: 5px; + } + #add p.time { + margin-bottom: 10px; + } + #add .label { + font-size: 11px; + font-weight: normal; + display: inline-block; + margin-right: 10px; + } + #add #event-label input { + padding: 0; + } + #add .buttons { + margin-top: 30px; + } + #event-tweet, + #event-delete { + float: right; + display: none; + margin-left: 5px; + } + #event-tweet { + background-image: url('t.png'); + background-repeat: no-repeat; + background-position: 3px 9px; + padding-left: 22px; + } + + #ical-data { + margin-top: 15px; + width: 100%; + font-size: 11px; + height: 250px; + border:1px solid #EBEBEB; + transition:all 1s ease 0s; + -moz-transition:all 1s ease 0s; + -webkit-transition:all 1s ease 0s; + } + +#controls { + float: right; + margin-top: 8px; +} + #controls li { + display: inline-block; + margin-left: 5px; + } + #controls a { + display: inline-block; + padding: 5px 12px; + } + #controls .sep { + margin-right: 35px; + } + .button { + border: 0; + margin: 0; + font-weight: bold; + font-size: 15px; + cursor: pointer; + } + + +#credit { + background: #eee; + border-radius: 3px; + padding: 3px 5px; + margin-top: 15px; + display: inline-block; +} + +/* ____________ */ +.label { + padding: 3px; + color: #fff !important; +} +.important { + background: #ff0000 !important; +} +.todo { + background: #3366cc !important; +} +.personal { + background: #35A200 !important; +} +.work { + background: #D89700 !important; +} +.misc { + background: #48BFF2 !important; +} + +.clear { + clear: both; +} + +.info { + font-size: 12px; + color: #666; +} + +.round { + display: block; + width: 20px; + height: 20px; + + border: 3px solid #000; + border-radius: 20px; + font-weight: bold; + text-align: center; + overflow: hidden; +} + .round:hover { + border-color: #3366cc; + color: #3366cc; + } + +h1, h2, h3, h4 { + margin: 0 0 25px 0; + font-weight: normal; +} +a { + color: #000; + text-decoration: none; +} +input, select { + padding: 10px; + font-family:Segoe UI Light; + font-size:14pt; +} +ul { + list-style-type: none; + margin: 0; + padding: 0; +} + + + +/* ___________ colour schemes */ +.dark { + background: #414141; + color: #FFF; + transition:all 2s ease 0s; +} +.dark #time { + color: #FFF; +} +.dark #stats { + color: #666; +} +.dark .box { + background: #212121; + box-shadow: 0 0 30px #111; +} +.dark #calendar-title , .dark #diary-title { + color: #FFF; +} +.dark #dialog { + background: #212121; + border: 1px solid #444; + box-shadow: 0 0 30px #000; +} +.dark #diary-wrap { + border: 0; + border-right: 1px solid #1e1e1e; +} + + +.dark .round { + border-color: #ff4800; + color: #ff4800; +} + .dark .round:hover { + border-color: #aaa; + color: #aaa; + } +.dark .day { + background: #191919; +} +.dark .day .add { + background-image:url(img/plus.png); + background-size:16px 16px; +} +.dark tbody td, +.dark thead td, +.dark tbody tr td:nth-child(1) { + border-color: #2e2e2e; +} +.dark #diary .time { + background: #444; + color: #ccc; +} +.dark #diary .desc { + border-color: #444; +} + +.dark #credit { + background: #111; +} +.dark #credit a { + color: #ddd; +} +.dark .today { + background: #333; +} +.dark .info { + color: #999; +} +.dark #ical-data { + background: #222; + color: #aaa; + border: 1px solid #333; +} +.dark .button { + background: #666; +} +.dark #dialog-close , .dark #diary-close { + background-image:url(img/close.png); +} +.dark #btn-today { + color:#FFF; +} +.dark #btn-previous { + background-image:url(img/left.png) !important; +} +.dark #btn-next { + background-image:url(img/right.png) !important; +}
\ No newline at end of file |
