/** * Purpose: This JavaScript class drives an admin interface for a calendar. * Most of the calendar is dynamic and operates through JavaScript, * and this file manages those operations. The logic makes use of Prototype and Script.aculo.us. * * Libraries: Prototype and Script.aculo.us * * Copyright: Up and Running * Date: 5/1/2008 * Author: Pete Hanson * */ /** An integer that is equal to the number of the day that is currently open or null if no day is open **/ var curOpen = null; var openedAt = 0; /** * This is triggered when a day is clicked on, it will either * display the form to add items to a day or redirect the click * to the copy handler */ function openDay(date){ if(copyMode != COPY_NONE) return copyClick(date); if(curOpen == date) return; elementTop = $('daydiv'+date).offsetTop; elementLeft = $('daydiv'+date).offsetLeft; $('formdiv').style.position = 'absolute'; $('formdiv').style.display = 'block'; $('formdiv').style.left = (elementLeft-180)+'px'; $('formdiv').style.top = (elementTop-170)+'px'; $('formdiv').style.zIndex = 100; $('datedisplay').innerHTML = date; autoFillers["additem"].lastValue = ''; $('date').value = date; $('additem').value = ''; $('price').value = ''; shadeRows('itemlist'+date); $('editlist').innerHTML = $('itemlist'+date).innerHTML; openedAt = (new Date()).getTime(); curOpen = date; } function shadeRows(toshade){ var curClass; var items = $(toshade).getElementsByTagName('li'); for(index = 0; index < items.length; index++){ curClass = (curClass == 'licolor1') ? 'licolor2' : 'licolor1'; items[index].className = curClass; } } /** * Hide the form to add items to a day */ function closeDay(day){ var now = (new Date()).getTime(); if(now-200 > openedAt){ $('formdiv').style.display = 'none'; curOpen = null; } } var closetimer = null; function delayCloseDay(){ clearTimeout(closetimer); closetimer = setTimeout(function(){ closeDay(curOpen); },150); } /** * This closes the currently open day when the user clicks on the document's body */ Event.observe(document,"click",function(event){ if(!curOpen) return; var element = Event.element(event); if(event.type == "click" && (!element.descendantOf || !element.descendantOf($('formdiv')))) closeDay(curOpen); }); /** * This is called after an item is added, it adds the * item to the display or displays an error */ function itemAdded(request){ eval('var reqdata = '+request.responseText); if(reqdata['status']){ addItemToDisplay(reqdata['date'],reqdata['id'],reqdata['name'],reqdata['price']); }else{ message = ""+reqdata['error']+""; $('status').innerHTML = message; flashNotification(); } } /** * This function adds an item to a date cell */ function addItemToDisplay(date,id,namei,price){ newItem = $(document.createElement("li")); newItem.innerHTML = "
"+price+"
"+namei+""; $('itemlist'+date).appendChild(newItem); if(curOpen){ shadeRows('itemlist'+curOpen); $('editlist').innerHTML = $('itemlist'+curOpen).innerHTML; } } /** * This is called after an item is removed, it removes * the item from the display or displays an error */ function itemRemoved(request){ eval('var reqdata = '+request.responseText); if(reqdata['status']){ var spans = null; var span = null; var items = $('itemlist'+reqdata['date']).getElementsByTagName('li'); for(i = 0; i < items.length; i++){ spans = items[i].getElementsByTagName('span'); span = spans[0]; if(span.innerHTML == reqdata['name']){ items[i].parentNode.removeChild(items[i]); } } if(curOpen){ shadeRows('itemlist'+curOpen); $('editlist').innerHTML = $('itemlist'+curOpen).innerHTML; } }else{ message = ""+reqdata['error']+""; $('status').innerHTML = message; flashNotification(); } } /** * Remove an item from a specific date * * @param day The day number (of the month), used for display purposes * @param date The date in a valid date format (Y-m-d) that the item should be removed from * @param itemid The id number of the item to remove */ function removeItem(date,itemid){ new Ajax.Request('index.php?p=removecafeitem&date='+encodeURIComponent(date)+'&id='+itemid,{onSuccess: itemRemoved}); } /** * Called when a save button is pressed, saves the item to the specified day and clears the input box * * @param date The date in a valid date format (Y-m-d) that the item should be added to */ function triggerSave(){ itemName = encodeURIComponent($('additem').value); price = encodeURIComponent($('price').value); date = encodeURIComponent($('date').value); itype = encodeURIComponent($('type').value); new Ajax.Request('index.php?p=addcafeitem&date='+date+'&_='+itemName+'&data='+price+'&enddate=next&type='+itype,{onSuccess: itemAdded}); $('additem').value = ''; $('price').value = ''; } /** * These vars keep track of the state that the copy system is in */ var COPY_NONE = 0; var SELECT_SRC = 1; var SELECT_DEST = 2; var copyMode = COPY_NONE; var sourceDay; var destDays = []; function changeCopyMode(newMode){ copyMode = newMode; switch(newMode){ case COPY_NONE: $('copy_instructions').innerHTML = "Click on the Copy Day button to copy menu items between days"; $('copyDayButton').style.display = 'inline'; $('copyCancel').style.display = 'none'; $('copySave').style.display = 'none'; break; case SELECT_SRC: $('copy_instructions').innerHTML = "Click on the day from which you would like to copy menu items"; $('copyCancel').style.display = 'inline'; $('copyDayButton').style.display = 'none'; $('copySave').style.display = 'none'; break; case SELECT_DEST: $('copy_instructions').innerHTML = "Click on the day or days to which you would like to copy the menu items"; break; } } /** * This handler is called when the copy system is active and a user clicks on a day */ function copyClick(day){ if(copyMode == SELECT_SRC){ sourceDay = day; changeCopyMode(SELECT_DEST); highlightSrc(day); if(hasDestinations()) $('copySave').style.display = 'inline'; }else if(copyMode == SELECT_DEST){ if(day == sourceDay){ restoreDay(sourceDay); sourceDay = null; return changeCopyMode(SELECT_SRC); } var wasRemoved = false; for(index = 0; index < destDays.length; index++){ if(destDays[index] == day){ restoreDay(destDays[index]); destDays[index] = null; wasRemoved = true; break; } } if(!wasRemoved){ highlightDest(day); destDays[destDays.length] = day; $('copySave').style.display = 'inline'; } if(!hasDestinations()){ $('copySave').style.display = 'none'; destDays = []; } } } /** * This returns true if destinations have been selected, * otherwise it returns false. */ function hasDestinations(){ for(index = 0; index < destDays.length; index++){ if(destDays[index]) return true; } return false; } function endCopy(performCopy){ if(performCopy && sourceDay && hasDestinations()){ initCopy(); } if(sourceDay) restoreDay(sourceDay); for(index = 0; index < destDays.length; index++){ if(destDays[index]) restoreDay(destDays[index]); } changeCopyMode(COPY_NONE); destDays = []; } function restoreDay(date){ $('daydiv'+date).style.background = ''; } function highlightDest(date){ $('daydiv'+date).style.background = '#fff7ae'; } function highlightSrc(date){ $('daydiv'+date).style.background = '#8fe3d8'; } function initCopy(){ destString = ""; for(index = 0; index < destDays.length; index++){ if(destDays[index]){ destString += "&dest[]="+encodeURIComponent(destDays[index]); } } new Ajax.Request('index.php?p=copycafeitems&src='+encodeURIComponent(sourceDay)+destString,{onSuccess: copyComplete}); } function copyComplete(request){ var daysClear = []; eval('var returndata = '+request.responseText); if(returndata['status']){ for(index = 0; index < returndata['data'].length; index++){ reqdata = returndata['data'][index]; if(!daysClear[reqdata['date']]){ $('itemlist'+reqdata['date']).innerHTML = ''; daysClear[reqdata['date']] = true; } if(reqdata['id']) addItemToDisplay(reqdata['date'],reqdata['id'],reqdata['name'],reqdata['price']); } }else{ message = ""+returndata['error']+""; $('status').innerHTML = message; flashNotification(); } }