Changeset View
Changeset View
Standalone View
Standalone View
plugins/calendar/calendar_ui.js
Show First 20 Lines • Show All 1,703 Lines • ▼ Show 20 Lines | var freebusy_find_slot = function(dir) | ||||
// exit if free-busy data isn't available yet | // exit if free-busy data isn't available yet | ||||
if (!freebusy_data || !freebusy_data.start) | if (!freebusy_data || !freebusy_data.start) | ||||
return false; | return false; | ||||
var event = me.selected_event, | var event = me.selected_event, | ||||
eventstart = clone_date(event.start, event.allDay ? 1 : 0).getTime(), // calculate with integers | eventstart = clone_date(event.start, event.allDay ? 1 : 0).getTime(), // calculate with integers | ||||
eventend = clone_date(event.end, event.allDay ? 2 : 0).getTime(), | eventend = clone_date(event.end, event.allDay ? 2 : 0).getTime(), | ||||
duration = eventend - eventstart - (event.allDay ? HOUR_MS : 0), /* make sure we don't cross day borders on DST change */ | duration = eventend - eventstart - (event.allDay ? HOUR_MS : 0), /* make sure we don't cross day borders on DST change */ | ||||
sinterval = freebusy_data.interval * 60000, | sinterval = freebusy_data.interval * 60000 / (settings.timeslots || 1), | ||||
intvlslots = 1, | intvlslots = 1, | ||||
numslots = Math.ceil(duration / sinterval), | numslots = Math.ceil(duration / sinterval), | ||||
checkdate, slotend, email, ts, slot, slotdate = new Date(); | checkdate, slotend, email, ts, slot, slotdate = new Date(); | ||||
// shift event times to next possible slot | // shift event times to next possible slot | ||||
eventstart += sinterval * intvlslots * dir; | eventstart += sinterval * intvlslots * dir; | ||||
eventend += sinterval * intvlslots * dir; | eventend += sinterval * intvlslots * dir; | ||||
// iterate through free-busy slots and find candidates | // iterate through free-busy slots and find candidates | ||||
var candidatecount = 0, candidatestart = candidateend = success = false; | var candidatecount = 0, candidatestart = false, success = false; | ||||
for (slot = dir > 0 ? freebusy_data.start.getTime() : freebusy_data.end.getTime() - sinterval; | for (slot = dir > 0 ? freebusy_data.start.getTime() : freebusy_data.end.getTime() - sinterval; | ||||
(dir > 0 && slot < freebusy_data.end.getTime()) || (dir < 0 && slot >= freebusy_data.start.getTime()); | (dir > 0 && slot < freebusy_data.end.getTime()) || (dir < 0 && slot >= freebusy_data.start.getTime()); | ||||
slot += sinterval * dir) { | slot += sinterval * dir) { | ||||
slotdate.setTime(slot); | slotdate.setTime(slot); | ||||
// fix slot if just crossed a DST change | // fix slot if just crossed a DST change | ||||
if (event.allDay) { | if (event.allDay) { | ||||
fix_date(slotdate); | fix_date(slotdate); | ||||
slot = slotdate.getTime(); | slot = slotdate.getTime(); | ||||
} | } | ||||
slotend = slot + sinterval; | slotend = slot + sinterval; | ||||
if ((dir > 0 && slotend <= eventstart) || (dir < 0 && slot >= eventend)) // skip | if ((dir > 0 && slotend <= eventstart) || (dir < 0 && slot >= eventend)) // skip | ||||
continue; | continue; | ||||
// respect workingours setting | // respect workingours setting | ||||
if (freebusy_ui.workinhoursonly) { | if (freebusy_ui.workinhoursonly) { | ||||
if (is_weekend(slotdate) || (freebusy_data.interval <= 60 && !is_workinghour(slotdate))) { // skip off-hours | if (is_weekend(slotdate) || (freebusy_data.interval <= 60 && !is_workinghour(slotdate))) { // skip off-hours | ||||
candidatestart = candidateend = false; | candidatestart = false; | ||||
candidatecount = 0; | candidatecount = 0; | ||||
continue; | continue; | ||||
} | } | ||||
} | } | ||||
if (!candidatestart) | if (!candidatestart) | ||||
candidatestart = slot; | candidatestart = slot; | ||||
// check freebusy data for all attendees | // check freebusy data for all attendees | ||||
ts = date2timestring(slotdate, freebusy_data.interval > 60); | ts = date2timestring(slotdate, freebusy_data.interval > 60); | ||||
// @TODO: freebusy_data slots should use sinterval not full hour | |||||
ts = ts.replace(/[0-9]{4}$/, '0000'); | |||||
for (var i=0; i < event_attendees.length; i++) { | for (var i=0; i < event_attendees.length; i++) { | ||||
if (freebusy_ui.attendees[i].role != 'OPT-PARTICIPANT' && (email = freebusy_ui.attendees[i].email) && freebusy_data[email] && freebusy_data[email][ts] > 1) { | if (freebusy_ui.attendees[i].role != 'OPT-PARTICIPANT' && (email = freebusy_ui.attendees[i].email) && freebusy_data[email] && freebusy_data[email][ts] > 1) { | ||||
candidatestart = candidateend = false; | candidatestart = false; | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
// occupied slot | // occupied slot | ||||
if (!candidatestart) { | if (!candidatestart) { | ||||
slot += Math.max(0, intvlslots - candidatecount - 1) * sinterval * dir; | slot += Math.max(0, intvlslots - candidatecount - 1) * sinterval * dir; | ||||
candidatecount = 0; | candidatecount = 0; | ||||
continue; | continue; | ||||
} | } | ||||
else if (dir < 0) | |||||
candidatestart = slot; | |||||
// set candidate end to slot end time | |||||
candidatecount++; | candidatecount++; | ||||
if (dir < 0 && !candidateend) | |||||
candidateend = slotend; | |||||
// if candidate is big enough, this is it! | // if candidate is big enough, this is it! | ||||
if (candidatecount == numslots) { | if (candidatecount == numslots) { | ||||
if (dir > 0) { | |||||
event.start.setTime(candidatestart); | event.start.setTime(candidatestart); | ||||
event.end.setTime(candidatestart + duration); | event.end.setTime(candidatestart + duration); | ||||
} | |||||
else { | |||||
event.end.setTime(candidateend); | |||||
event.start.setTime(candidateend - duration); | |||||
} | |||||
success = true; | success = true; | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
// update event date/time display | // update event date/time display | ||||
if (success) { | if (success) { | ||||
update_freebusy_dates(event.start, event.end); | update_freebusy_dates(event.start, event.end); | ||||
▲ Show 20 Lines • Show All 2,422 Lines • Show Last 20 Lines |