2015-02-17 01:58:04 -06:00
|
|
|
function toggleVisibility(node, nodeType){
|
|
|
|
// Toggle visibility of all elements having p_nodeType within p_node
|
|
|
|
var elements = node.getElementsByTagName(nodeType);
|
|
|
|
for (var i=0; i<elements.length; i++){
|
|
|
|
var sNode = elements[i];
|
|
|
|
if (sNode.style.visibility == 'hidden') sNode.style.visibility = 'visible';
|
|
|
|
else sNode.style.visibility = 'hidden';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-04 07:35:02 -06:00
|
|
|
// Sends an Ajax request for getting the calendar, at p_month
|
|
|
|
function askMonth(hookId, month) {askAjax(hookId, null, {'month': month})}
|
2012-10-03 07:44:34 -05:00
|
|
|
|
2015-03-02 05:19:19 -06:00
|
|
|
function enableOptions(select, enabled, selectFirst, message){
|
|
|
|
/* This function disables, in p_select, all options that are not in p_enabled.
|
|
|
|
p_enabled is a string containing a comma-separated list of option names.
|
|
|
|
If p_selectFirst is True, the first option from p_enabled will be selected
|
|
|
|
by default. p_message will be shown (as "title") for disabled options. */
|
|
|
|
// Get p_enabled as a dict
|
|
|
|
var l = enabled.split(',');
|
|
|
|
var d = {};
|
|
|
|
for (var i=0; i < l.length; i++) d[l[i]] = true;
|
|
|
|
// Remember if we have already selected the first enabled option
|
|
|
|
var isSelected = false;
|
|
|
|
var options = select.options;
|
|
|
|
// Disable options not being p_enabled
|
|
|
|
for (var i=0; i<options.length; i++) {
|
|
|
|
options[i].selected = false;
|
|
|
|
if (!options[i].value) continue;
|
|
|
|
if (options[i].value in d) {
|
|
|
|
options[i].disabled = false;
|
|
|
|
options[i].title = '';
|
|
|
|
// Select it?
|
|
|
|
if (selectFirst && !isSelected) {
|
|
|
|
options[i].selected = true;
|
|
|
|
isSelected = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
options[i].disabled = true;
|
|
|
|
options[i].title = message;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-04 07:35:02 -06:00
|
|
|
function openEventPopup(hookId, action, day, timeslot, spansDays,
|
2015-03-02 05:19:19 -06:00
|
|
|
applicableEventTypes, message, freeSlots) {
|
2012-10-03 07:44:34 -05:00
|
|
|
/* Opens the popup for creating (or deleting, depending on p_action) a
|
2015-02-27 08:57:42 -06:00
|
|
|
calendar event at some p_day. When action is "del", we need to know the
|
|
|
|
p_timeslot where the event is assigned and if the event spans more days
|
|
|
|
(from p_spansDays), in order to propose a checkbox allowing to delete
|
|
|
|
events for those successive days. When action is "new", a possibly
|
|
|
|
restricted list of applicable event types for this day is given in
|
|
|
|
p_applicableEventTypes; p_message contains an optional message explaining
|
2015-03-02 05:19:19 -06:00
|
|
|
why not applicable types are not applicable. When "new", p_freeSlots may
|
|
|
|
list the available timeslots at p_day. */
|
2015-03-04 07:35:02 -06:00
|
|
|
var popupId = hookId + '_' + action;
|
|
|
|
var f = document.getElementById(popupId + 'Form');
|
2012-10-03 07:44:34 -05:00
|
|
|
f.day.value = day;
|
|
|
|
if (action == 'del') {
|
2015-03-02 05:19:19 -06:00
|
|
|
if (f.timeslot) f.timeslot.value = timeslot;
|
2015-02-27 08:57:42 -06:00
|
|
|
// Show or hide the checkbox for deleting the event for successive days
|
2015-03-04 07:35:02 -06:00
|
|
|
var elem = document.getElementById(hookId + '_DelNextEvent');
|
2012-10-03 07:44:34 -05:00
|
|
|
var cb = elem.getElementsByTagName('input');
|
|
|
|
cb[0].checked = false;
|
|
|
|
cb[1].value = 'False';
|
2015-02-27 08:57:42 -06:00
|
|
|
if (spansDays == 'True') elem.style.display = 'block';
|
|
|
|
else elem.style.display = 'none';
|
2012-10-03 07:44:34 -05:00
|
|
|
}
|
2012-10-29 23:53:45 -05:00
|
|
|
else if (action == 'new') {
|
2015-03-02 05:19:19 -06:00
|
|
|
// Reinitialise field backgrounds
|
2012-10-29 23:53:45 -05:00
|
|
|
f.eventType.style.background = '';
|
2015-02-27 08:57:42 -06:00
|
|
|
if (f.eventSpan) f.eventSpan.style.background = '';
|
2015-03-02 05:19:19 -06:00
|
|
|
// Disable unapplicable events and non-free timeslots
|
|
|
|
enableOptions(f.eventType, applicableEventTypes, false, message);
|
|
|
|
if (f.timeslot) enableOptions(f.timeslot, freeSlots, true, 'Not free');
|
2012-10-29 23:53:45 -05:00
|
|
|
}
|
2015-03-04 07:35:02 -06:00
|
|
|
openPopup(popupId);
|
2012-10-03 07:44:34 -05:00
|
|
|
}
|
|
|
|
|
2015-03-04 07:35:02 -06:00
|
|
|
function triggerCalendarEvent(hookId, action, maxEventLength) {
|
2012-10-03 07:44:34 -05:00
|
|
|
/* Sends an Ajax request for triggering a calendar event (create or delete an
|
|
|
|
event) and refreshing the view month. */
|
2015-03-04 07:35:02 -06:00
|
|
|
var popupId = hookId + '_' + action;
|
|
|
|
var formId = popupId + 'Form';
|
|
|
|
var f = document.getElementById(formId);
|
2012-10-03 07:44:34 -05:00
|
|
|
if (action == 'new') {
|
2012-10-29 23:53:45 -05:00
|
|
|
// Check that an event span has been specified
|
|
|
|
if (f.eventType.selectedIndex == 0) {
|
|
|
|
f.eventType.style.background = wrongTextInput;
|
|
|
|
return;
|
|
|
|
}
|
2015-02-27 08:57:42 -06:00
|
|
|
if (f.eventSpan) {
|
|
|
|
// Check that eventSpan is empty or contains a valid number
|
|
|
|
var spanNumber = f.eventSpan.value.replace(' ', '');
|
|
|
|
if (spanNumber) {
|
|
|
|
spanNumber = parseInt(spanNumber);
|
|
|
|
if (isNaN(spanNumber) || (spanNumber > maxEventLength)) {
|
|
|
|
f.eventSpan.style.background = wrongTextInput;
|
|
|
|
return;
|
|
|
|
}
|
2012-10-03 07:44:34 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-03-04 07:35:02 -06:00
|
|
|
closePopup(popupId);
|
|
|
|
askAjax(hookId, formId);
|
|
|
|
}
|
|
|
|
|
2015-03-11 07:44:32 -05:00
|
|
|
// Function that collects the status of all validation checkboxes
|
|
|
|
function getValidationStatus(hookId) {
|
|
|
|
var res = {'validated': [], 'discarded': []};
|
2015-03-04 07:35:02 -06:00
|
|
|
var node = document.getElementById(hookId + '_cal');
|
|
|
|
var cbs = node.getElementsByTagName('input');
|
2015-03-11 07:44:32 -05:00
|
|
|
var key = null;
|
2015-03-04 07:35:02 -06:00
|
|
|
for (var i=0; i<cbs.length; i++) {
|
|
|
|
if (cbs[i].type != 'checkbox') continue;
|
2015-03-11 07:44:32 -05:00
|
|
|
key = (cbs[i].checked)? 'validated': 'discarded';
|
|
|
|
res[key].push(cbs[i].id);
|
2012-10-03 07:44:34 -05:00
|
|
|
}
|
2015-03-11 07:44:32 -05:00
|
|
|
// Convert lists to comma-separated strings
|
|
|
|
for (key in res) res[key] = res[key].join();
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function for validating and discarding calendar events
|
|
|
|
function validateEvents(hookId, month) {
|
|
|
|
// Collect checkboxes from hookId and identify checked and unchecked ones
|
|
|
|
var params = {'action': 'validateEvents', 'mode': 'POST', 'month': month};
|
|
|
|
var status = getValidationStatus(hookId);
|
|
|
|
for (var key in status) params[key] = status[key];
|
2015-03-04 07:35:02 -06:00
|
|
|
askAjax(hookId, null, params);
|
2012-10-03 07:44:34 -05:00
|
|
|
}
|
2015-03-05 09:35:04 -06:00
|
|
|
|
|
|
|
// Function for (un)-checking checkboxes automatically
|
2015-03-11 07:44:32 -05:00
|
|
|
function onCheckCbCell(cb, hook, totalRows) {
|
2015-03-05 09:35:04 -06:00
|
|
|
// Is automatic selection on/off?
|
|
|
|
var auto = document.getElementById(hook + '_auto');
|
2015-03-11 07:44:32 -05:00
|
|
|
if (auto.checked) {
|
|
|
|
// Get the current render mode
|
|
|
|
var render = document.getElementById(hook)['ajax'].params['render'];
|
|
|
|
// Change the state of every successive checkbox
|
|
|
|
var timeline = render == 'timeline'; // Else, render is "month"
|
|
|
|
// From the checkbox id, extract the date and the remaining part
|
|
|
|
var elems = cb.id.split('_');
|
|
|
|
if (timeline) {
|
|
|
|
var date = elems[2], part = elems[0] + '_' + elems[1] + '_'; }
|
|
|
|
else { var date = elems[0], part = '_' + elems[1] + '_' + elems[2]; }
|
|
|
|
// Create a Date instance
|
|
|
|
var year = parseInt(date.slice(0,4)), month = parseInt(date.slice(4,6))-1,
|
|
|
|
day = parseInt(date.slice(6,8));
|
|
|
|
var next = new Date(year, month, day);
|
|
|
|
// Change the status of successive checkboxes if found
|
|
|
|
var checked = cb.checked;
|
|
|
|
var nextId = nextCb = null;
|
|
|
|
while (true) {
|
2015-03-05 09:35:04 -06:00
|
|
|
// Compute the date at the next day
|
|
|
|
next.setDate(next.getDate() + 1);
|
|
|
|
month = (next.getMonth() + 1).toString();
|
|
|
|
if (month.length == 1) month = '0' + month;
|
|
|
|
day = next.getDate().toString();
|
|
|
|
if (day.length == 1) day = '0' + day;
|
|
|
|
date = next.getFullYear().toString() + month + day;
|
|
|
|
// Find the next checkbox
|
|
|
|
if (timeline) nextId = part + date;
|
|
|
|
else nextId = date + part;
|
|
|
|
nextCb = document.getElementById(nextId);
|
|
|
|
if (!nextCb) break;
|
|
|
|
nextCb.checked = checked;
|
2015-03-11 07:44:32 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// Refresh the total rows if requested
|
|
|
|
if (totalRows) {
|
|
|
|
var params = getValidationStatus(hook);
|
|
|
|
params['mode'] = 'POST';
|
|
|
|
askAjax(hook + '_trs', null, params);
|
2015-03-05 09:35:04 -06:00
|
|
|
}
|
|
|
|
}
|