795 lines
26 KiB
JavaScript
795 lines
26 KiB
JavaScript
/**
|
|
* mobile.js - Base mobile application logic.
|
|
*
|
|
* Copyright 2010-2014 Horde LLC (http://www.horde.org/)
|
|
*
|
|
* See the enclosed file COPYING for license information (GPL). If you
|
|
* did not receive this file, see http://www.horde.org/licenses/gpl.
|
|
*
|
|
* @author Michael J. Rubinsky <mrubinsk@horde.org>
|
|
* @author Jan Schneider <jan@horde.org>
|
|
* @category Horde
|
|
* @license http://www.horde.org/licenses/gpl GPL
|
|
* @package Kronolith
|
|
*/
|
|
var KronolithMobile = {
|
|
|
|
/**
|
|
* List of calendars we are displaying
|
|
*/
|
|
calendars: [],
|
|
|
|
/**
|
|
* List of calendars that are currently loaded for the current view
|
|
*/
|
|
loadedCalendars: [],
|
|
|
|
/**
|
|
* Event cache
|
|
*/
|
|
ecache: {},
|
|
cacheStart: null,
|
|
cacheEnd: null,
|
|
|
|
deferHash: {},
|
|
viewRan: false,
|
|
|
|
/**
|
|
* The currently displayed view
|
|
*/
|
|
view: 'day',
|
|
|
|
/**
|
|
* The currently selected date
|
|
*/
|
|
date: null,
|
|
|
|
/**
|
|
* Temporary fix for pages not firing pagebeforecreate events properly
|
|
*/
|
|
haveOverview: false,
|
|
|
|
/**
|
|
* Load all events between start and end time.
|
|
*
|
|
* @param Date firstDay
|
|
* @param Date lastDay
|
|
* @param string view The view we are loading for (month, day)
|
|
*/
|
|
loadEvents: function(firstDay, lastDay, view)
|
|
{
|
|
var dates = [firstDay, lastDay], loading = false;
|
|
|
|
// Clear out the loaded cal cache
|
|
KronolithMobile.loadedCalendars = [];
|
|
KronolithMobile.clearView(view);
|
|
KronolithMobile.viewRan = false;
|
|
$.each(KronolithMobile.calendars, function(key, cal) {
|
|
var startDay = dates[0].clone(), endDay = dates[1].clone(),
|
|
cals = KronolithMobile.ecache[cal[0]], c;
|
|
if (typeof cals != 'undefined' &&
|
|
typeof cals[cal[1]] != 'undefined') {
|
|
|
|
cals = cals[cal[1]];
|
|
c = cals[startDay.dateString()];
|
|
while (typeof c != 'undefined' && startDay.isBefore(endDay)) {
|
|
if (view == 'day') {
|
|
KronolithMobile.insertEvents([startDay, startDay], view, cal.join('|'));
|
|
}
|
|
startDay.addDays(1);
|
|
c = cals[startDay.dateString()];
|
|
}
|
|
|
|
c = cals[endDay.dateString()];
|
|
while (typeof c != 'undefined' && !startDay.isAfter(endDay)) {
|
|
if (view == 'day') {
|
|
KronolithMobile.insertEvents([endDay, endDay], view, cal.join('|'));
|
|
}
|
|
endDay.addDays(-1);
|
|
c = cals[endDay.dateString()];
|
|
}
|
|
if (startDay.compareTo(endDay) > 0) {
|
|
KronolithMobile.loadedCalendars.push(cal.join('|'));
|
|
return;
|
|
}
|
|
}
|
|
|
|
var start = startDay.dateString(), end = endDay.dateString();
|
|
loading = true;
|
|
HordeMobile.doAction('listEvents',
|
|
{
|
|
'start': start,
|
|
'end': end,
|
|
'cal': cal.join('|'),
|
|
'view': view,
|
|
'sig': start + end + (Math.random() + '').slice(2)
|
|
},
|
|
KronolithMobile.loadEventsCallback
|
|
);
|
|
});
|
|
|
|
if (!loading && view == 'overview') {
|
|
KronolithMobile.insertEvents([firstDay, lastDay], view);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Sort a collection of events as returned from the ecache
|
|
*/
|
|
sortEvents: function(events)
|
|
{
|
|
var e = [];
|
|
|
|
// Need a native array to sort.
|
|
$.each(events, function(id, event) {
|
|
e.push(event);
|
|
});
|
|
return e.sort(function(a, b) {
|
|
sortA = a.sort;
|
|
sortB = b.sort;
|
|
return (sortA < sortB) ? -1 : (sortA > sortB) ? 1 : 0;
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Callback for the loadEvents AJAX request.
|
|
*
|
|
* @param object data The ajax response.
|
|
*/
|
|
loadEventsCallback: function(data)
|
|
{
|
|
var start = KronolithMobile.parseDate(data.sig.substr(0, 8)),
|
|
end = KronolithMobile.parseDate(data.sig.substr(8, 8)),
|
|
dates = [start, end], view = data.view;
|
|
|
|
KronolithMobile.storeCache(data.events, data.cal, dates, true);
|
|
KronolithMobile.loadedCalendars.push(data.cal);
|
|
KronolithMobile.insertEvents(dates, view, data.cal);
|
|
},
|
|
|
|
/**
|
|
* Inserts events into current view.
|
|
* For Day view, builds a new listview and attaches to the DOM.
|
|
* For Month view, hightlights dates with events.
|
|
*/
|
|
insertEvents: function(dates, view, cal)
|
|
{
|
|
var key = dates[0].dateString() + dates[1].dateString() + view + cal,
|
|
d = [dates[0].clone(), dates[1].clone()], date, events, list, key, day;
|
|
|
|
// Make sure all calendars are loaded before rendering the view.
|
|
// @TODO: Implement LIFO queue as in kronolith.js
|
|
if (KronolithMobile.loadedCalendars.length != KronolithMobile.calendars.length) {
|
|
if (KronolithMobile.deferHash[key]) {
|
|
return;
|
|
} else {
|
|
KronolithMobile.deferHash[key] = window.setTimeout(function() { KronolithMobile.insertEvents(d, view, cal); }, 0);
|
|
return;
|
|
}
|
|
}
|
|
if (KronolithMobile.deferHash[key]) {
|
|
window.clearTimeout(KronolithMobile.deferHash[key]);
|
|
KronolithMobile.deferHash[key] = false;
|
|
}
|
|
|
|
KronolithMobile.running = true;
|
|
switch (view) {
|
|
case 'day':
|
|
if (!KronolithMobile.viewRan) {
|
|
KronolithMobile.viewRan = true;
|
|
date = d[0].dateString();
|
|
events = KronolithMobile.getCacheForDate(date);
|
|
events = KronolithMobile.sortEvents(events);
|
|
list = $('<ul>').attr({'data-role': 'listview'});
|
|
$.each(events, function(index, event) {
|
|
list.append(KronolithMobile.buildDayEvent(event));
|
|
});
|
|
if (!list.children().length) {
|
|
list.append($('<li>').text(Kronolith.text.noevents));
|
|
}
|
|
$("#dayview :jqmData(role='content')").append(list).trigger('create');
|
|
}
|
|
break;
|
|
|
|
case 'month':
|
|
day = d[0].clone();
|
|
while (!day.isAfter(d[1])) {
|
|
date = day.dateString();
|
|
events = KronolithMobile.getCacheForDate(date);
|
|
$.each(events, function(key, event) {
|
|
$('#kronolithMonth' + date).addClass('kronolithContainsEvents');
|
|
});
|
|
day.next().day();
|
|
}
|
|
// Select current date.
|
|
$('#kronolithMonth'+ KronolithMobile.date.dateString()).addClass('kronolith-selected');
|
|
KronolithMobile.selectMonthDay(KronolithMobile.date.dateString());
|
|
break;
|
|
|
|
case 'overview':
|
|
day = d[0].clone(), haveEvent = false;
|
|
list = $('<ul>').attr({'data-role': 'listview'});
|
|
while (!day.isAfter(d[1])) {
|
|
list.append($('<li>').attr({ 'data-role': 'list-divider' }).text(day.toString('ddd') + ' ' + day.toString('d')));
|
|
events = KronolithMobile.sortEvents(KronolithMobile.getCacheForDate(day.dateString())) ;
|
|
$.each(events, function(index, event) {
|
|
list.append(KronolithMobile.buildDayEvent(event));
|
|
haveEvent = true;
|
|
});
|
|
if (!haveEvent) {
|
|
list.append($('<li>').text(Kronolith.text.noevents));
|
|
}
|
|
haveEvent = false;
|
|
day.next().day();
|
|
}
|
|
$("#overview :jqmData(role='content')").append(list).trigger('create');
|
|
break;
|
|
}
|
|
KronolithMobile.running = false;
|
|
},
|
|
|
|
/**
|
|
* Build the dom element for an event to insert into the day view.
|
|
*
|
|
* @param object event The event object returned from the ajax request.
|
|
*/
|
|
buildDayEvent: function(event)
|
|
{
|
|
var id;
|
|
if ($.isEmptyObject(event)) {
|
|
return;
|
|
}
|
|
|
|
var cal = event.calendar, type = cal.split('|')[0], c = cal.split('|')[1],
|
|
d = $('<div>'), item = $('<li>'), a;
|
|
|
|
// Time
|
|
var timeWrapper = $('<div>').addClass('kronolithTimeWrapper');
|
|
if (event.al) {
|
|
timeWrapper.append(Kronolith.text.allday).html();
|
|
} else {
|
|
var startTime = Date.parse(event.s).toString(Kronolith.conf.time_format);
|
|
var endTime = '- ' + Date.parse(event.e).toString(Kronolith.conf.time_format);
|
|
timeWrapper
|
|
.append($('<div>').addClass('kronolithStartTime').append(startTime))
|
|
.append($('<div>').addClass('kronolithEndTime').append(endTime));
|
|
}
|
|
|
|
e = $('<h2>').text(event.t);
|
|
l = $('<p>').addClass('kronolithDayLocation' + Kronolith.conf.calendars[type][c].fg.substring(1)).text(event.l);
|
|
d.append(timeWrapper).append(e).append(l);
|
|
|
|
// Add the link to view the event detail.
|
|
a = $('<a>')
|
|
.css({ backgroundColor: Kronolith.conf.calendars[type][c].bg })
|
|
.attr({ href: '#eventview',
|
|
'class': 'kronolith-event kronolith-event-' + Kronolith.conf.calendars[type][c].fg.substring(1) })
|
|
.click(function(ev) {
|
|
$("#eventview :jqmData(role='content') ul").detach();
|
|
KronolithMobile.loadEvent(cal, event.id, Date.parse(event.e));
|
|
})
|
|
.append(d);
|
|
|
|
return item.append(a);
|
|
},
|
|
|
|
/**
|
|
* Retrieve a single event from the server and show it.
|
|
*
|
|
* @param string cal The calendar identifier.
|
|
* @param string id The event identifier.
|
|
* @param Date d The date the event occurs.
|
|
*/
|
|
loadEvent: function(cal, id, d)
|
|
{
|
|
HordeMobile.doAction('getEvent',
|
|
{'cal': cal, 'id': id, 'date': d.toString('yyyyMMdd')},
|
|
KronolithMobile.loadEventCallback);
|
|
},
|
|
|
|
/**
|
|
* Callback for loadEvent call. Assume we are in Event view for now, build
|
|
* the event view structure and attach to DOM.
|
|
*
|
|
* @param object data The ajax response.
|
|
*/
|
|
loadEventCallback: function(data)
|
|
{
|
|
if (!data.event) {
|
|
// @TODO: Error handling.
|
|
return;
|
|
}
|
|
|
|
var event = data.event;
|
|
var ul = KronolithMobile.buildEventView(event);
|
|
$("#eventview :jqmData(role='content')").append(ul).trigger('create');
|
|
},
|
|
|
|
/**
|
|
* Build event view DOM structure and return the top event element.
|
|
*
|
|
* @param object e The event structure returned from the ajax call.
|
|
*/
|
|
buildEventView: function(e)
|
|
{
|
|
var list = $('<ul>')
|
|
.addClass('kronolithEventDetail')
|
|
.attr({'data-role': 'listview', 'data-inset': true});
|
|
|
|
var loc = false;
|
|
|
|
// Title and calendar
|
|
var title = $('<div>').addClass('kronolithEventDetailTitle').append($('<h2>').text(e.t));
|
|
var calendar = $('<p>').addClass('kronolithEventDetailCalendar').text(Kronolith.conf.calendars[e.ty][e.c]['name']);
|
|
list.append($('<li>').append(title).append(calendar));
|
|
|
|
// Time
|
|
var item = $('<div>');
|
|
if (e.r) {
|
|
var recurText = Kronolith.text.recur.desc[e.r.t][(e.r.i > 1) ? 1 : 0],
|
|
date = Date.parse(e.s);
|
|
recurText = recurText.replace('#{interval}', e.r.i);
|
|
switch (e.r.t) {
|
|
case 2:
|
|
// WEEKLY
|
|
recurText = recurText.replace('#{weekday}', Kronolith.text.weekday[e.r.d]);
|
|
break;
|
|
case 3:
|
|
// MONTHLY_DATE
|
|
recurText = recurText.replace('#{date}', date.toString('d') + '.');
|
|
break;
|
|
case 5:
|
|
// YEARLY_DATE
|
|
recurText = recurText.replace('#{date}', date.toString('m'));
|
|
break;
|
|
}
|
|
item.append($('<div>').addClass('kronolithEventDetailRecurring').append(recurText));
|
|
item.append($('<div>').addClass('kronolithEventDetailRecurring').text(Kronolith.text.recur[e.r.t]));
|
|
}
|
|
if (e.al) {
|
|
item.append($('<div>').addClass('kronolithEventDetailAllDay').text(Kronolith.text.allday))
|
|
.append($('<div>').addClass('kronolithEventDetailDate').text(Date.parse(e.s).toString('D')));
|
|
} else {
|
|
item.append($('<div>')
|
|
.append($('<div>').addClass('kronolithEventDetailDate').text(Date.parse(e.s).toString('D'))
|
|
.append($('<div>').addClass('kronolithEventDetailTime').text(Date.parse(e.s).toString(Kronolith.conf.time_format) + ' - ' + Date.parse(e.e).toString(Kronolith.conf.time_format))))
|
|
);
|
|
}
|
|
list.append($('<li>').append(item));
|
|
|
|
// Location
|
|
if (e.gl) {
|
|
loc = $('<div>').addClass('kronolithEventDetailLocation')
|
|
.append($('<a>').attr({'data-style': 'b', 'href': 'http://maps.google.com?q=' + encodeURIComponent(e.gl.lat + ',' + e.gl.lon)}).text(e.l));
|
|
} else if (e.l) {
|
|
loc = $('<div>').addClass('kronolithEventDetailLocation')
|
|
.append($('<a>').attr({'href': 'http://maps.google.com?q=' + encodeURIComponent(e.l)}).text(e.l));
|
|
}
|
|
if (loc) {
|
|
list.append($('<li>').append(loc));
|
|
}
|
|
|
|
// Description
|
|
if (e.d) {
|
|
list.append($('<li>').append($('<div>').addClass('kronolithEventDetailDesc').text(e.d)));
|
|
}
|
|
|
|
// url
|
|
if (e.u) {
|
|
list.append($('<li>').append($('<a>').attr({'rel': 'external', 'href': e.u}).text(e.u)));
|
|
}
|
|
|
|
return list;
|
|
},
|
|
|
|
clearView: function(view)
|
|
{
|
|
switch (view) {
|
|
case 'month':
|
|
$('#kronolithDayDetail ul').detach();
|
|
break;
|
|
case 'day':
|
|
$("#dayview :jqmData(role='content') ul").detach();
|
|
break;
|
|
case 'overview':
|
|
$("#overview :jqmData(role='content') ul").detach();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Advance the day view by one day
|
|
*/
|
|
showNextDay: function()
|
|
{
|
|
KronolithMobile.moveToDay(KronolithMobile.date.clone().addDays(1));
|
|
},
|
|
|
|
/**
|
|
* Move the day view back by one day
|
|
*/
|
|
showPrevDay: function()
|
|
{
|
|
KronolithMobile.moveToDay(KronolithMobile.date.clone().addDays(-1));
|
|
},
|
|
|
|
/**
|
|
* Move the day view to a specific day
|
|
*
|
|
* @param Date date The date to set the day view to.
|
|
*/
|
|
moveToDay: function(date)
|
|
{
|
|
$('#kronolithDayDate').text(date.toString('ddd') + ' ' + date.toString('d'));
|
|
KronolithMobile.date = date.clone();
|
|
KronolithMobile.loadEvents(KronolithMobile.date, KronolithMobile.date, 'day');
|
|
},
|
|
|
|
/**
|
|
* Advance the month view ahead one month.
|
|
*/
|
|
showPrevMonth: function()
|
|
{
|
|
KronolithMobile.moveToMonth(KronolithMobile.date.clone().addMonths(-1));
|
|
},
|
|
|
|
/**
|
|
* Move the month view back one month
|
|
*/
|
|
showNextMonth: function()
|
|
{
|
|
KronolithMobile.moveToMonth(KronolithMobile.date.clone().addMonths(1));
|
|
},
|
|
|
|
/**
|
|
* Move the month view to the month containing the specified date.
|
|
*
|
|
* @params Date date The date to move to.
|
|
*/
|
|
moveToMonth: function(date)
|
|
{
|
|
var dates = KronolithMobile.viewDates(date, 'month');
|
|
KronolithMobile.date = date;
|
|
KronolithMobile.loadEvents(dates[0], dates[1], 'month');
|
|
KronolithMobile.buildCal(date);
|
|
KronolithMobile.insertEvents(dates, 'month');
|
|
},
|
|
|
|
/**
|
|
* Selects a day in the month view, and displays any events it may contain.
|
|
* Also sets the dayview to the same date, so navigating back to it is
|
|
* smooth.
|
|
*
|
|
* @param string date A date string in the form of yyyyMMdd.
|
|
*/
|
|
selectMonthDay: function(date)
|
|
{
|
|
var ul = $('<ul>').attr({ 'data-role': 'listview' }),
|
|
d = KronolithMobile.parseDate(date), today = new Date(), text;
|
|
$('#kronolithDayDetail ul').detach();
|
|
if (today.dateString() == d.dateString()) {
|
|
text = Kronolith.text.today;
|
|
} else if (today.clone().addDays(-1).dateString() == d.dateString()) {
|
|
text = Kronolith.text.yesterday;
|
|
} else if (today.clone().addDays(1).dateString() == d.dateString()) {
|
|
text = Kronolith.text.tomorrow;
|
|
} else {
|
|
text = d.toString('ddd') + ' ' + d.toString('d')
|
|
}
|
|
$('#kronolithDayDetailHeader h3').text(text);
|
|
$('.kronolith-selected').removeClass('kronolith-selected');
|
|
$('#kronolithMonth' + date).addClass('kronolith-selected');
|
|
if ($('#kronolithMonth' + date).hasClass('kronolithContainsEvents')) {
|
|
var events = KronolithMobile.getCacheForDate(date);
|
|
events = KronolithMobile.sortEvents(events);
|
|
$.each(events, function(k, e) {
|
|
ul.append(KronolithMobile.buildDayEvent(e));
|
|
});
|
|
}
|
|
$('#kronolithDayDetail').append(ul).trigger('create');
|
|
KronolithMobile.moveToDay(d);
|
|
},
|
|
|
|
/**
|
|
* Calculates first and last days being displayed.
|
|
*
|
|
* @var Date date The date of the view.
|
|
* @var string view A view name.
|
|
*
|
|
* @return array Array with first and last day of the view.
|
|
*/
|
|
viewDates: function(date, view)
|
|
{
|
|
var start = date.clone(), end = date.clone();
|
|
|
|
switch (view) {
|
|
case 'month':
|
|
start.setDate(1);
|
|
start.moveToBeginOfWeek(Kronolith.conf.week_start);
|
|
end.moveToLastDayOfMonth();
|
|
end.moveToEndOfWeek(Kronolith.conf.week_start);
|
|
break;
|
|
case 'summary':
|
|
end.add(6).days();
|
|
break;
|
|
}
|
|
|
|
return [start, end];
|
|
},
|
|
|
|
/**
|
|
* Creates the month view calendar.
|
|
*
|
|
* @param Date date The date to show in the calendar.
|
|
*/
|
|
buildCal: function(date)
|
|
{
|
|
var tbody = $('.kronolith-minical table tbody');
|
|
var dates = KronolithMobile.viewDates(date, 'month'), day = dates[0].clone(),
|
|
today = Date.today(), dateString, td, tr, i;
|
|
|
|
// Remove old calendar rows.
|
|
tbody.children().remove();
|
|
|
|
// Update title
|
|
$('#kronolithMinicalDate').html(date.toString('MMMM yyyy'));
|
|
|
|
for (i = 0; i < 42; i++) {
|
|
dateString = day.dateString();
|
|
|
|
// Create calendar row .
|
|
if (day.getDay() == Kronolith.conf.week_start) {
|
|
tr = $('<tr>');
|
|
tbody.append(tr);
|
|
}
|
|
|
|
// Insert day cell.
|
|
td = $('<td>').attr({ id: 'kronolithMonth' + dateString })
|
|
.addClass('kronolithMonthDay')
|
|
.jqmData('date', dateString);
|
|
if (day.getMonth() != date.getMonth()) {
|
|
td.addClass('kronolithMinicalEmpty');
|
|
}
|
|
|
|
// Highlight today.
|
|
if (day.dateString() == today.dateString()) {
|
|
td.addClass('kronolithToday');
|
|
}
|
|
td.html(day.getDate());
|
|
tr.append(td);
|
|
day.next().day();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Parses a date attribute string into a Date object.
|
|
*
|
|
* For other strings use Date.parse().
|
|
*
|
|
* @param string date A yyyyMMdd date string.
|
|
*
|
|
* @return Date A date object.
|
|
*/
|
|
parseDate: function(date)
|
|
{
|
|
var d = new Date(date.substr(0, 4), date.substr(4, 2) - 1, date.substr(6, 2));
|
|
if (date.length == 12) {
|
|
d.setHours(date.substr(8, 2));
|
|
d.setMinutes(date.substr(10, 2));
|
|
}
|
|
return d;
|
|
},
|
|
|
|
storeCache: function(events, calendar, dates, createCache)
|
|
{
|
|
events = events || {};
|
|
|
|
//calendar[0] == type, calendar[1] == calendar name
|
|
calendar = calendar.split('|');
|
|
if (!KronolithMobile.ecache[calendar[0]]) {
|
|
if (!createCache) {
|
|
return;
|
|
}
|
|
KronolithMobile.ecache[calendar[0]] = {};
|
|
}
|
|
if (!KronolithMobile.ecache[calendar[0]][calendar[1]]) {
|
|
if (!createCache) {
|
|
return;
|
|
}
|
|
KronolithMobile.ecache[calendar[0]][calendar[1]] = {};
|
|
}
|
|
var calHash = KronolithMobile.ecache[calendar[0]][calendar[1]];
|
|
|
|
// Create empty cache entries for all dates.
|
|
if (!!dates) {
|
|
var day = dates[0].clone(), date;
|
|
while (!day.isAfter(dates[1])) {
|
|
date = day.dateString();
|
|
if (!calHash[date]) {
|
|
if (!createCache) {
|
|
return;
|
|
}
|
|
if (!KronolithMobile.cacheStart || KronolithMobile.cacheStart.isAfter(day)) {
|
|
KronolithMobile.cacheStart = day.clone();
|
|
}
|
|
if (!KronolithMobile.cacheEnd || KronolithMobile.cacheEnd.isBefore(day)) {
|
|
KronolithMobile.cacheEnd = day.clone();
|
|
}
|
|
calHash[date] = {};
|
|
}
|
|
day.add(1).day();
|
|
}
|
|
}
|
|
|
|
var cal = calendar.join('|');
|
|
$.each(events, function(key, date) {
|
|
// We might not have a cache for this date if the event lasts
|
|
// longer than the current view
|
|
if (typeof calHash[key] == 'undefined') {
|
|
return;
|
|
}
|
|
|
|
// Store useful information in event objects.
|
|
$.each(date, function(k, event) {
|
|
event.calendar = cal;
|
|
event.start = Date.parse(event.s);
|
|
event.end = Date.parse(event.e);
|
|
event.sort = event.start.toString('HHmmss')
|
|
+ (240000 - parseInt(event.end.toString('HHmmss'), 10)).toPaddedString(6);
|
|
event.id = k;
|
|
});
|
|
|
|
// Store events in cache.
|
|
$.extend(calHash[key], date);
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Return all events for a single day from all displayed calendars merged
|
|
* into a single hash.
|
|
*
|
|
* @param string date A yyyymmdd date string.
|
|
*
|
|
* @return Hash An event hash which event ids as keys and event objects as
|
|
* values.
|
|
*/
|
|
getCacheForDate: function(date, calendar)
|
|
{
|
|
if (calendar) {
|
|
var cals = calendar.split('|');
|
|
return KronolithMobile.ecache[cals[0]][cals[1]][date];
|
|
}
|
|
|
|
var events = {};
|
|
$.each(KronolithMobile.ecache, function(key, type) {
|
|
$.each(type, function(id, cal) {
|
|
if (!Kronolith.conf.calendars[key][id].show) {
|
|
return;
|
|
}
|
|
if (typeof cal[date] != 'undefined') {
|
|
$.extend(events, cal[date]);
|
|
}
|
|
});
|
|
});
|
|
|
|
return events;
|
|
},
|
|
|
|
/**
|
|
* Handle swipe events for the current view.
|
|
*/
|
|
handleSwipe: function(map)
|
|
{
|
|
switch (KronolithMobile.view) {
|
|
case 'day':
|
|
if (map.type == 'swipeleft') {
|
|
KronolithMobile.showNextDay();
|
|
} else {
|
|
KronolithMobile.showPrevDay();
|
|
}
|
|
break;
|
|
|
|
case 'month':
|
|
if (map.type == 'swipeleft') {
|
|
KronolithMobile.showNextMonth();
|
|
} else {
|
|
KronolithMobile.showPrevMonth();
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Event handler for the pagebeforechange event that implements loading of
|
|
* deep-linked pages.
|
|
*
|
|
* @param object e Event object.
|
|
* @param object data Event data.
|
|
*/
|
|
toPage: function(e, data)
|
|
{
|
|
switch (data.options.parsedUrl.view) {
|
|
case 'minical-next':
|
|
KronolithMobile.showNextMonth();
|
|
e.preventDefault();
|
|
break;
|
|
|
|
case 'minical-prev':
|
|
KronolithMobile.showPrevMonth();
|
|
e.preventDefault();
|
|
break;
|
|
|
|
case 'nextday':
|
|
KronolithMobile.showNextDay();
|
|
e.preventDefault();
|
|
break;
|
|
|
|
case 'prevday':
|
|
KronolithMobile.showPrevDay();
|
|
e.preventDefault();
|
|
break;
|
|
}
|
|
},
|
|
|
|
/**
|
|
*/
|
|
loadPage: function()
|
|
{
|
|
switch (HordeMobile.currentPage()) {
|
|
case 'monthview':
|
|
KronolithMobile.view = "month";
|
|
// (re)build the minical only if we need to
|
|
if (!$("#kronolithMinicalDate").jqmData("date") ||
|
|
($("#kronolithMinicalDate").jqmData("date").toString("M") != KronolithMobile.date.toString("M"))) {
|
|
KronolithMobile.moveToMonth(KronolithMobile.date);
|
|
}
|
|
break;
|
|
|
|
case 'overview':
|
|
KronolithMobile.view = "overview";
|
|
if (!KronolithMobile.haveOverview) {
|
|
KronolithMobile.loadEvents(KronolithMobile.date, KronolithMobile.date.clone().addDays(7), "overview");
|
|
KronolithMobile.haveOverview = true;
|
|
}
|
|
break;
|
|
|
|
case null:
|
|
break;
|
|
|
|
case 'dayview':
|
|
default:
|
|
KronolithMobile.view = "day";
|
|
$("#kronolithDayDate").html(KronolithMobile.date.toString("ddd") + " " + KronolithMobile.date.toString("d"));
|
|
KronolithMobile.loadEvents(KronolithMobile.date, KronolithMobile.date, "day");
|
|
break;
|
|
}
|
|
},
|
|
|
|
onDocumentReady: function()
|
|
{
|
|
KronolithMobile.date = new Date();
|
|
|
|
// Build list of calendars we want.
|
|
$.each(Kronolith.conf.calendars, function(key, value) {
|
|
$.each(value, function(cal, info) {
|
|
if (info.show) {
|
|
KronolithMobile.calendars.push([key, cal]);
|
|
}
|
|
});
|
|
});
|
|
|
|
// Bind click and swipe events
|
|
$('body').bind('swipeleft', KronolithMobile.handleSwipe)
|
|
.bind('swiperight', KronolithMobile.handleSwipe);
|
|
$(document).bind('pageshow', KronolithMobile.loadPage)
|
|
.bind('pagebeforechange', KronolithMobile.toPage)
|
|
.on("pageshow", "#eventview", function(event, ui) {
|
|
KronolithMobile.view = "event";
|
|
});
|
|
|
|
$('#kronolith-minical').on('click', 'td', function(e) {
|
|
KronolithMobile.selectMonthDay($(e.target).jqmData('date'));
|
|
});
|
|
}
|
|
};
|
|
|
|
$(KronolithMobile.onDocumentReady);
|