mirror of
https://github.com/MichMich/MagicMirror.git
synced 2025-06-27 11:50:00 +00:00
Added calendar
This commit is contained in:
parent
1c4a0b4780
commit
024738cb4d
3
calendar.php
Normal file
3
calendar.php
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<?php
|
||||||
|
$url = 'https://p01-calendarws.icloud.com/ca/subscribe/1/n6x7Farxpt7m9S8bHg1TGArSj7J6kanm_2KEoJPL5YIAk3y70FpRo4GyWwO-6QfHSY5mXtHcRGVxYZUf7U3HPDOTG5x0qYnno1Zr_VuKH2M';
|
||||||
|
echo file_get_contents($url);
|
32
css/main.css
32
css/main.css
@ -12,6 +12,10 @@ body, html {
|
|||||||
font-size: 75px;
|
font-size: 75px;
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
}
|
}
|
||||||
|
.wi {
|
||||||
|
line-height: 75px;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
.top
|
.top
|
||||||
{
|
{
|
||||||
@ -64,18 +68,35 @@ body, html {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.xsmall
|
.xsmall
|
||||||
|
{
|
||||||
|
font-size: 20px;
|
||||||
|
letter-spacing: 0px;
|
||||||
|
font-family: "HelveticaNeue-Medium";
|
||||||
|
}
|
||||||
|
.xsmall .wi {
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.small
|
||||||
{
|
{
|
||||||
font-size: 25px;
|
font-size: 25px;
|
||||||
letter-spacing: 0px;
|
letter-spacing: 0px;
|
||||||
font-family: "HelveticaNeue-Medium";
|
font-family: "HelveticaNeue-Medium";
|
||||||
}
|
}
|
||||||
|
.small .wi {
|
||||||
|
line-height: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
.small
|
.medium
|
||||||
{
|
{
|
||||||
font-size: 35px;
|
font-size: 35px;
|
||||||
letter-spacing: -1px;
|
letter-spacing: -1px;
|
||||||
font-family: "HelveticaNeue-Light";
|
font-family: "HelveticaNeue-Light";
|
||||||
}
|
}
|
||||||
|
.medium .wi {
|
||||||
|
line-height: 35px;
|
||||||
|
}
|
||||||
|
|
||||||
.xdimmed
|
.xdimmed
|
||||||
{
|
{
|
||||||
@ -89,7 +110,7 @@ body, html {
|
|||||||
|
|
||||||
.light
|
.light
|
||||||
{
|
{
|
||||||
font-family: "HelveticaNeue-UltraLight";
|
font-family: "HelveticaNeue-Light";
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon
|
.icon
|
||||||
@ -124,6 +145,13 @@ body, html {
|
|||||||
color: #999;
|
color: #999;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.calendar-table {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
.calendar-table .days {
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'HelveticaNeue-UltraLight';
|
font-family: 'HelveticaNeue-UltraLight';
|
||||||
src: url('font/HelveticaNeue-UltraLight.eot'); /* IE9 Compat Modes */
|
src: url('font/HelveticaNeue-UltraLight.eot'); /* IE9 Compat Modes */
|
||||||
|
@ -11,15 +11,17 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<div class="top left"><div class="date xsmall dimmed"></div><div class="time"></div></div>
|
<div class="top left"><div class="date small dimmed"></div><div class="time"></div><div class="calendar xsmall"></div></div>
|
||||||
<div class="top right"><div class="sun xsmall dimmed"></div><div class="temp"></div><div class="forecast xsmall dimmed"></div></div>
|
<div class="top right"><div class="sun small dimmed"></div><div class="temp"></div><div class="forecast small dimmed"></div></div>
|
||||||
<div class="lower-third center-hor"><div class="compliment light"></div></div>
|
<div class="lower-third center-hor"><div class="compliment light"></div></div>
|
||||||
<div class="bottom center-hor"><div class="news small"></div></div>
|
<div class="bottom center-hor"><div class="news medium"></div></div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="js/jquery.js"></script>
|
<script src="js/jquery.js"></script>
|
||||||
<script src="js/jquery.feedToJSON.js"></script>
|
<script src="js/jquery.feedToJSON.js"></script>
|
||||||
|
<script src="js/ical_parser.js"></script>
|
||||||
|
<script src="js/moment-with-langs.min.js"></script>
|
||||||
<script src="js/main.js?nocache=<?php echo md5(microtime()) ?>"></script>
|
<script src="js/main.js?nocache=<?php echo md5(microtime()) ?>"></script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
184
js/ical_parser.js
Executable file
184
js/ical_parser.js
Executable file
@ -0,0 +1,184 @@
|
|||||||
|
/**
|
||||||
|
* Javascript ical Parser
|
||||||
|
* Proof of concept method of reading icalendar (.ics) files with javascript.
|
||||||
|
*
|
||||||
|
* @author: Carl Saggs
|
||||||
|
* @source: https://github.com/thybag/
|
||||||
|
* @version: 0.2
|
||||||
|
*/
|
||||||
|
function ical_parser(feed_url, callback){
|
||||||
|
//store of unproccesed data.
|
||||||
|
this.raw_data = null;
|
||||||
|
//Store of proccessed data.
|
||||||
|
this.events = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* loadFile
|
||||||
|
* Using AJAX to load the requested .ics file, passing it to the callback when completed.
|
||||||
|
* @param url URL of .ics file
|
||||||
|
* @param callback Function to call on completion.
|
||||||
|
*/
|
||||||
|
this.loadFile = function(url, callback){
|
||||||
|
//Create request object
|
||||||
|
try {xmlhttp = window.XMLHttpRequest?new XMLHttpRequest(): new ActiveXObject("Microsoft.XMLHTTP");} catch (e) { }
|
||||||
|
//Grab file
|
||||||
|
xmlhttp.onreadystatechange = function(){
|
||||||
|
if ((xmlhttp.readyState == 4) && (xmlhttp.status == 200)) {
|
||||||
|
//On success, run callback.
|
||||||
|
callback(xmlhttp.responseText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xmlhttp.open("GET", url, true);
|
||||||
|
xmlhttp.send(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* makeDate
|
||||||
|
* Convert the dateformat used by ICalendar in to one more suitable for javascript.
|
||||||
|
* @param String ical_date
|
||||||
|
* @return dt object, includes javascript Date + day name, hour/minutes/day/month/year etc.
|
||||||
|
*/
|
||||||
|
this.makeDate = function(ical_date){
|
||||||
|
//break date apart
|
||||||
|
var dt = {
|
||||||
|
year: ical_date.substr(0,4),
|
||||||
|
month: ical_date.substr(4,2),
|
||||||
|
day: ical_date.substr(6,2),
|
||||||
|
hour: ical_date.substr(9,2),
|
||||||
|
minute: ical_date.substr(11,2)
|
||||||
|
}
|
||||||
|
//Create JS date (months start at 0 in JS - don't ask)
|
||||||
|
dt.date = new Date(dt.year, (dt.month-1), dt.day, dt.hour, dt.minute);
|
||||||
|
//Get the full name of the given day
|
||||||
|
dt.dayname =["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"][dt.date.getDay()];
|
||||||
|
|
||||||
|
return dt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* parseICAL
|
||||||
|
* Convert the ICAL format in to a number of javascript objects (Each representing a date)
|
||||||
|
*
|
||||||
|
* @param data Raw ICAL data
|
||||||
|
*/
|
||||||
|
this.parseICAL = function(data){
|
||||||
|
//Ensure cal is empty
|
||||||
|
this.events = [];
|
||||||
|
|
||||||
|
//Clean string and split the file so we can handle it (line by line)
|
||||||
|
cal_array = data.replace(new RegExp( "\\r", "g" ), "").split("\n");
|
||||||
|
|
||||||
|
//Keep track of when we are activly parsing an event
|
||||||
|
var in_event = false;
|
||||||
|
//Use as a holder for the current event being proccessed.
|
||||||
|
var cur_event = null;
|
||||||
|
for(var i=0;i<cal_array.length;i++){
|
||||||
|
ln = cal_array[i];
|
||||||
|
//If we encounted a new Event, create a blank event object + set in event options.
|
||||||
|
if(!in_event && ln == 'BEGIN:VEVENT'){
|
||||||
|
in_event = true;
|
||||||
|
cur_event = {};
|
||||||
|
}
|
||||||
|
//If we encounter end event, complete the object and add it to our events array then clear it for reuse.
|
||||||
|
if(in_event && ln == 'END:VEVENT'){
|
||||||
|
in_event = false;
|
||||||
|
this.events.push(cur_event);
|
||||||
|
cur_event = null;
|
||||||
|
}
|
||||||
|
//If we are in an event
|
||||||
|
if(in_event){
|
||||||
|
//Split the item based on the first ":"
|
||||||
|
idx = ln.indexOf(':');
|
||||||
|
//Apply trimming to values to reduce risks of badly formatted ical files.
|
||||||
|
type = ln.substr(0,idx).replace(/^\s\s*/, '').replace(/\s\s*$/, '');//Trim
|
||||||
|
val = ln.substr(idx+1,ln.length-(idx+1)).replace(/^\s\s*/, '').replace(/\s\s*$/, '');
|
||||||
|
|
||||||
|
//If the type is a start date, proccess it and store details
|
||||||
|
if(type =='DTSTART'){
|
||||||
|
dt = this.makeDate(val);
|
||||||
|
val = dt.date;
|
||||||
|
//These are helpful for display
|
||||||
|
cur_event.start_time = dt.hour+':'+dt.minute;
|
||||||
|
cur_event.start_date = dt.day+'/'+dt.month+'/'+dt.year;
|
||||||
|
cur_event.day = dt.dayname;
|
||||||
|
}
|
||||||
|
//If the type is an end date, do the same as above
|
||||||
|
if(type =='DTEND'){
|
||||||
|
dt = this.makeDate(val);
|
||||||
|
val = dt.date;
|
||||||
|
//These are helpful for display
|
||||||
|
cur_event.end_time = dt.hour+':'+dt.minute;
|
||||||
|
cur_event.end_date = dt.day+'/'+dt.month+'/'+dt.year;
|
||||||
|
cur_event.day = dt.dayname;
|
||||||
|
}
|
||||||
|
//Convert timestamp
|
||||||
|
if(type =='DTSTAMP') val = this.makeDate(val).date;
|
||||||
|
|
||||||
|
//Add the value to our event object.
|
||||||
|
cur_event[type] = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Run this to finish proccessing our Events.
|
||||||
|
this.complete();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* complete
|
||||||
|
* Sort all events in to a sensible order and run the original callback
|
||||||
|
*/
|
||||||
|
this.complete = function(){
|
||||||
|
//Sort the data so its in date order.
|
||||||
|
this.events.sort(function(a,b){
|
||||||
|
return a.DTSTART-b.DTSTART;
|
||||||
|
});
|
||||||
|
//Run callback method, if was defined. (return self)
|
||||||
|
if(typeof callback == 'function') callback(this);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* getEvents
|
||||||
|
* return all events found in the ical file.
|
||||||
|
*
|
||||||
|
* @return list of events objects
|
||||||
|
*/
|
||||||
|
this.getEvents = function(){
|
||||||
|
return this.events;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getFutureEvents
|
||||||
|
* return all events sheduled to take place after the current date.
|
||||||
|
*
|
||||||
|
* @return list of events objects
|
||||||
|
*/
|
||||||
|
this.getFutureEvents = function(){
|
||||||
|
var future_events = [], current_date = new Date();
|
||||||
|
|
||||||
|
this.events.forEach(function(itm){
|
||||||
|
//If the event starts after the current time, add it to the array to return.
|
||||||
|
if(itm.DTSTART > current_date) future_events.push(itm);
|
||||||
|
});
|
||||||
|
return future_events;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* load
|
||||||
|
* load a new ICAL file.
|
||||||
|
*
|
||||||
|
* @param ical file url
|
||||||
|
*/
|
||||||
|
this.load = function(ical_file){
|
||||||
|
var tmp_this = this;
|
||||||
|
this.raw_data = null;
|
||||||
|
this.loadFile(ical_file, function(data){
|
||||||
|
//if the file loads, store the data and invoke the parser
|
||||||
|
tmp_this.raw_data = data;
|
||||||
|
tmp_this.parseICAL(data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//Store this so we can use it in the callback from the load function.
|
||||||
|
var tmp_this = this;
|
||||||
|
//Store the feed url
|
||||||
|
this.feed_url = feed_url;
|
||||||
|
//Load the file
|
||||||
|
this.load(this.feed_url);
|
||||||
|
}
|
79
js/main.js
79
js/main.js
@ -41,6 +41,8 @@ jQuery(document).ready(function($) {
|
|||||||
var news = [];
|
var news = [];
|
||||||
var newsIndex = 0;
|
var newsIndex = 0;
|
||||||
|
|
||||||
|
var eventList = [];
|
||||||
|
|
||||||
var lastCompliment;
|
var lastCompliment;
|
||||||
var compliment;
|
var compliment;
|
||||||
|
|
||||||
@ -90,6 +92,73 @@ jQuery(document).ready(function($) {
|
|||||||
}, 1000);
|
}, 1000);
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
(function updateCalendarData()
|
||||||
|
{
|
||||||
|
new ical_parser("calendar.php", function(cal){
|
||||||
|
events = cal.getEvents();
|
||||||
|
eventList = [];
|
||||||
|
|
||||||
|
for (var i in events) {
|
||||||
|
var e = events[i];
|
||||||
|
for (var key in e) {
|
||||||
|
var value = e[key];
|
||||||
|
var seperator = key.search(';');
|
||||||
|
if (seperator >= 0) {
|
||||||
|
var mainKey = key.substring(0,seperator);
|
||||||
|
var subKey = key.substring(seperator+1);
|
||||||
|
|
||||||
|
var dt;
|
||||||
|
if (subKey == 'VALUE=DATE') {
|
||||||
|
//date
|
||||||
|
dt = new Date(value.substring(0,4), value.substring(4,6) - 1, value.substring(6,8));
|
||||||
|
} else {
|
||||||
|
//time
|
||||||
|
dt = new Date(value.substring(0,4), value.substring(4,6) - 1, value.substring(6,8), value.substring(9,11), value.substring(11,13), value.substring(13,15));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mainKey == 'DTSTART') e.startDate = dt;
|
||||||
|
if (mainKey == 'DTEND') e.endDate = dt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var days = moment(e.startDate).diff(moment(new Date()), 'days');
|
||||||
|
|
||||||
|
eventList.push({'description':e.SUMMARY,'days':days});
|
||||||
|
};
|
||||||
|
eventList.sort(function(a,b){return a.days-b.days});
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
updateCalendarData();
|
||||||
|
}, 60000);
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
|
||||||
|
(function updateCalendar()
|
||||||
|
{
|
||||||
|
table = $('<table/>').addClass('xsmall').addClass('calendar-table');
|
||||||
|
|
||||||
|
for (var i in eventList) {
|
||||||
|
var e = eventList[i];
|
||||||
|
var days = e.days;
|
||||||
|
|
||||||
|
var daysString = (days == 1) ? 'morgen' : days + ' dagen';
|
||||||
|
if (days == 0) {
|
||||||
|
daysString = 'vandaag';
|
||||||
|
}
|
||||||
|
|
||||||
|
var row = $('<tr/>');
|
||||||
|
row.append($('<td/>').html(e.description).addClass('description light'));
|
||||||
|
row.append($('<td/>').html(daysString).addClass('days dimmed'));
|
||||||
|
table.append(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
$('.calendar').html(table);
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
updateCalendar();
|
||||||
|
}, 5000);
|
||||||
|
})();
|
||||||
|
|
||||||
(function updateCompliment()
|
(function updateCompliment()
|
||||||
{
|
{
|
||||||
var compliments = [
|
var compliments = [
|
||||||
@ -147,10 +216,8 @@ jQuery(document).ready(function($) {
|
|||||||
|
|
||||||
var wind = roundVal(json.wind.speed);
|
var wind = roundVal(json.wind.speed);
|
||||||
|
|
||||||
console.log(wind);
|
|
||||||
|
|
||||||
var iconClass = iconTable[json.weather[0].icon];
|
var iconClass = iconTable[json.weather[0].icon];
|
||||||
var icon = $('<span/>').addClass('icon').addClass('dimmed').addClass(iconClass);
|
var icon = $('<span/>').addClass('icon').addClass('dimmed').addClass('wi').addClass(iconClass);
|
||||||
$('.temp').updateWithText(icon.outerHTML()+temp+'°', 1000);
|
$('.temp').updateWithText(icon.outerHTML()+temp+'°', 1000);
|
||||||
|
|
||||||
// var forecast = 'Min: '+temp_min+'°, Max: '+temp_max+'°';
|
// var forecast = 'Min: '+temp_min+'°, Max: '+temp_max+'°';
|
||||||
@ -160,10 +227,10 @@ jQuery(document).ready(function($) {
|
|||||||
var sunrise = new Date(json.sys.sunrise*1000).toTimeString().substring(0,5);
|
var sunrise = new Date(json.sys.sunrise*1000).toTimeString().substring(0,5);
|
||||||
var sunset = new Date(json.sys.sunset*1000).toTimeString().substring(0,5);
|
var sunset = new Date(json.sys.sunset*1000).toTimeString().substring(0,5);
|
||||||
|
|
||||||
var windString = '<span class="wi-strong-wind xdimmed"></span> ' + kmh2beaufort(wind) ;
|
var windString = '<span class="wi wi-strong-wind xdimmed"></span> ' + kmh2beaufort(wind) ;
|
||||||
var sunString = '<span class="wi-sunrise xdimmed"></span> ' + sunrise;
|
var sunString = '<span class="wi wi-sunrise xdimmed"></span> ' + sunrise;
|
||||||
if (json.sys.sunrise*1000 > now && json.sys.sunset*1000 > now) {
|
if (json.sys.sunrise*1000 > now && json.sys.sunset*1000 > now) {
|
||||||
sunString = '<span class="wi-sunset xdimmed"></span> ' + sunset;
|
sunString = '<span class="wi wi-sunset xdimmed"></span> ' + sunset;
|
||||||
}
|
}
|
||||||
|
|
||||||
$('.sun').updateWithText(windString+' '+sunString, 1000);
|
$('.sun').updateWithText(windString+' '+sunString, 1000);
|
||||||
|
9
js/moment-with-langs.min.js
vendored
Normal file
9
js/moment-with-langs.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user