/* * Calendar Report * * Copyright (c) 2003 Mackley F. Pexton. All rights reserved. */ /** These functions enhance the calendar functions for calendar reports where there are pop-up menus of daily events filled in from the database. The hiliteDate() routine highlights dates after the calendar has been rendered. The appendDate() routine fills in date cells with HTML elements. It is used to display the pop-up menus in the date cells on full screen calendars. It only works if the calendar is rendered in the main window (not a lookup window). The showMenu() and hideMenu() routines assist displayCalendar() to implement pop-up menus over the calendar. They only work if the calendar is rendered in the main window (not a lookup window). The DayMenu object encompases the TearOffMenu and move_me objects located in .../acmebase/tear_off_menus.js to provide pop-up menus of daily events that can be moved and resized on the screen by the user. **/ // // Highlight dates on the calendar. // function hiliteDate() { // Convenience wrapper to Calendar.hiliteDate(). // usage: hiliteDate(cal_name, hilite_code, date ...); // The calendar name cal_name is an optional argument, // the last calendar made is used as a default value. // The hilite_code can be a background color like '#33AA99' // or it can be a CSS class name like 'holiday'. var n = 0; var cal_name = arguments[n]; if (cal_name == null || Calendar.calendars[cal_name]) n++; var hilite_code = arguments[n++]; var c = (cal_name && Calendar.calendars[cal_name]) ? Calendar.calendars[cal_name] : Calendar.last_calendar; if (!c) return; for (; n < arguments.length; n++) { c.hiliteDate(hilite_code, arguments[n]); } } // // Fill in dates on the calendar. // function appendDate() { // Convenience wrapper to Calendar.appendDate(). // This fills in dates on fullscreen calendars. // usage: appendDate(cal_name, element, date ...); // The calendar name cal_name is an optional argument, // the last calendar made is used as a default value. var n = 0; var cal_name = arguments[n]; if (cal_name == null || Calendar.calendars[cal_name]) n++; var e = arguments[n++]; var c = (cal_name && Calendar.calendars[cal_name]) ? Calendar.calendars[cal_name] : Calendar.last_calendar; if (!c) return; for (; n < arguments.length; n++) { c.appendDate(e, arguments[n]); } } // // Show pop-up menu on a calendar. // function showMenu(calendar, date, active) { // Display a menu when hovering over a date. var w = calendar.win; if (!w) w = self; var m; var menu_id = calendar.daymenu.getDayMenuIdPrefix(); if (menu_id) menu_id += date; if (!menu_id && active) menu_id = calendar.daymenu.getDayMenuId(); if (menu_id) m = w.document.getElementById(menu_id); if (!m) m = w.document.getElementById(calendar.daymenu.DayMenuIdPrefix + date); if (!m) return; if (calendar.daymenu.FixedMenu) return DayMenu.show(m); if (!m.tear_off_made) DayMenu.setup_tear_off_menu(m,calendar.Type); if (DayMenu.tear_off && DayMenu.tear_off.is_torn) return DayMenu.show_tear_off(m); return DayMenu.show_floating_menu(m); } // // Hide pop-up menu on a calendar. // function hideMenu(calendar, date) { // Hide the menu after hovering over a date. var w = calendar.win; if (!w) w = self; var m; var menu_id = calendar.daymenu.getDayMenuIdPrefix(); if (menu_id) menu_id += date; if (!menu_id) menu_id = calendar.daymenu.getDayMenuId(); if (menu_id) m = w.document.getElementById(menu_id); if (!m) m = w.document.getElementById(calendar.daymenu.DayMenuIdPrefix + date); if (!m) return; if (DayMenu.tear_off && DayMenu.tear_off.is_torn) return DayMenu.hide_tear_off(m); return DayMenu.hide(m); } // // Find enclosing document element having "contents" in its class name. // function contents_of(id){ // Contents of a day menu now have an id of "menu_01-01-2004". var e = getElementRef(id); if (!e) return; return getElementRef(e.id.replace(/.*_/,'menu_')); } /* ------------------------------------------------------------------------ */ /* * DayMenu control object */ DayMenu.tear_off = new TearOffMenu; // object tracking torn-off pop-up menu function DayMenu(fixed, day_menu_id, day_menu_id_prefix) { this.FixedMenu = fixed ? true : false; this.DayMenuId = day_menu_id ? day_menu_id : 'day_menu'; this.DayMenuIdPrefix = day_menu_id_prefix ? day_menu_id_prefix : 'day_'; } // // Tear-Off and Resizable Menu handlers. // DayMenu.start = function(evt,e) { // Start moving tear off menu DayMenu.tear_off.start(evt,e); } DayMenu.stop = function(evt,e) { // Stop moving tear off menu DayMenu.tear_off.stop(evt,e); if (DayMenu.tear_off.is_torn) { var button_id = DayMenu.tear_off.e.id.replace(/day_/,'cal_'); var b = document.getElementById(button_id); do_callback(b); } } DayMenu.close = function() { // Close an opened menu. do_unselect(); DayMenu.tear_off.close(); // reset tear-off menus with (DayMenu.tear_off) { left = top = width = height = contents_width = contents_height = null; } } DayMenu.resize_stop = function(evt,e) { // Resize menu event handler // Record widths and heights after menu resized. if (!e) return; if (e.style.width) DayMenu.tear_off.width=e.style.width; if (e.style.height) DayMenu.tear_off.height=e.style.height; var c = contents_of(e); if (!c) return; if (c.style.width) DayMenu.tear_off.contents_width=c.style.width; if (c.style.height) DayMenu.tear_off.contents_height=c.style.height; // Act as if menu was torn off. var tom = DayMenu.tear_off; if (! tom.is_torn) { if (!e.tear_off_made) DayMenu.setup_tear_off_menu(e); tom.e = e; tom.left = e.style.left; tom.top = e.style.top; tom.is_torn = true; var button_id = DayMenu.tear_off.e.id.replace(/day_/,'cal_'); var b = document.getElementById(button_id); do_callback(b); } } /////// Configuration Variables ////////////////////////////////////////////// make_tear_off_menu.Default_Class='day-menu-banner'; // CSS class name make_tear_off_menu.Default_Object_Name='DayMenu'; // object with event handlers resize_me.onstop=DayMenu.resize_stop; // function name /////// End of Configuration Variables /////////////////////////////////////// // // Support methods for showing pop-up day menus // DayMenu.show = function(m) { m.style.display = "block"; m.style.visibility = "visible"; } DayMenu.show_tear_off = function(m) { var dto = DayMenu.tear_off; dto.save_width = m.style.width; dto.save_height = m.style.height; var c = contents_of(m); dto.save_contents_width = c.style.width; dto.save_contents_height = c.style.height; m.style.left = dto.left; m.style.top = dto.top; if (dto.width != null) m.style.width = dto.width; if (dto.height != null) m.style.height = dto.height; if (dto.contents_width != null) c.style.width = dto.contents_width; if (dto.contents_height != null) c.style.height = dto.contents_height; DayMenu.show(m); resize_me.reposition_control(m); } DayMenu.show_floating_menu = function(m) { if (window.event) { // Compute coordinates if (event.pageX || event.pageY) { m.style.left = event.pageX + 'px'; m.style.top = event.pageY + 'px'; } else { m.style.left = (document.body.scrollLeft + event.clientX) + 'px'; m.style.top = (document.body.scrollTop + event.clientY) + 'px'; } } // Display menu DayMenu.show(m); // Recompute coordinates if display off the page if (window.event) { var rightedge = document.body.clientWidth - event.clientX; var bottomedge = document.body.clientHeight - event.clientY; var leftedge = document.body.scrollLeft + event.clientX - m.offsetWidth; var topedge = document.body.scrollTop + event.clientY - m.offsetHeight; // Uncomment the next to float menus left from the right. if (rightedge < m.offsetWidth) m.style.left = ((leftedge < document.body.scrollLeft) ? document.body.scrollLeft + 3 : leftedge) + 'px'; // Uncomment the next to float menus up from the bottom. //if (bottomedge < m.offsetHeight) // m.style.top = ((topedge < document.body.scrollTop) ? document.body.scrollTop + 3 : topedge) + 'px'; event.cancelBubble = true; if (event.evt && event.evt.stopPropagation) event.evt.stopPropagation(); } } DayMenu.hide = function(m) { m.style.display = "none"; m.style.visibility = "hidden"; } DayMenu.hide_tear_off = function(m) { var dto = DayMenu.tear_off; if (dto.save_width != null) m.style.width = dto.save_width; if (dto.save_height != null) m.style.height = dto.save_height; var c = contents_of(m); if (dto.save_contents_width != null) c.style.width = dto.save_contents_width; if (dto.save_contents_height != null) c.style.height = dto.save_contents_height; resize_me.reposition_control(m); dto.save_width = dto.save_height = null; dto.save_contents_width = dto.save_contents_height = null; DayMenu.hide(m); } // // Setup menu to be a tear-off menu. // DayMenu.setup_tear_off_menu = function(m,type) { // Setup a document element m to be a tear off menu. // The type argument is needed only for "day" type calendars. var date = m.id.replace(/.*_/,""); // get date from menu id var d = new Date(date.replace(/\W/g,"/")); if (isNaN(d)) return; var longdate = Calendar.longdate(d); var title = "" + longdate + ""; var resize = (type && type == "day") ? "" : "menu_"+date; make_tear_off_menu(("day_"+date),{ "title":title,"resize":resize}); m.tear_off_made = true; // set custom element property as a flag } // // Open tear off menu that was positioned on the previous screen. // DayMenu.reinitialize_tear_off = function(menu_date,left,top,width,height,contents_width,contents_height) { DayMenu.tear_off.is_torn = true; DayMenu.tear_off.left = left; DayMenu.tear_off.top = top; if(width != null) DayMenu.tear_off.width = width; if(height != null) DayMenu.tear_off.height = height; if(contents_width != null) DayMenu.tear_off.contents_width = contents_width; if(contents_height != null) DayMenu.tear_off.contents_height = contents_height; var m = getElementRef('cal_'+menu_date); if (!m) return; do_select(m); } // // DayMenu methods to change settings. // DayMenu.prototype.setDayMenuIdPrefix = function(s) { // Set menu id prefix to use as a pop-up menu for each day. // The prefix has the date (mm-dd-yyyy) appended to make the DayMenuId. var p = this.DayMenuIdPrefix; this.DayMenuIdPrefix = s; return p; } DayMenu.prototype.getDayMenuIdPrefix = function() { // Get menu id prefix to use as a pop-up menu for each day. return this.DayMenuIdPrefix; } DayMenu.prototype.setDayMenuId = function(s) { // Set menu id to use as a pop-up menu for each day. var p = this.DayMenuId; this.DayMenuId = s; return p; } DayMenu.prototype.getDayMenuId = function() { // Get menu id to use as a pop-up menu for each day. return this.DayMenuId; } // // Show pop-up window of a day's menu items. // DayMenu.list = function(menu_id) { var menu_e = document.getElementById(menu_id); var e, header_e, content_e, content_id = menu_id.replace(/^day_/,'menu_'); if (menu_e) { // Try getting content element by its own id (full screen calendars). content_e = document.getElementById(content_id); for (var i = 0; i < menu_e.childNodes.length; i++) { e = menu_e.childNodes[i]; if (e.className == 'day-menu-header') header_e = e; if (e.className == 'day-menu-contents') content_e = e; if (header_e && content_e) break; } } // Extract date from menu_id. var d = menu_id.match(/\d+\W\d+\W\d+$/) + ''; d = d.replace(/\W/g,'/'); var window_name = menu_id.replace(/\W/g,'_'); // make valid window name (for IE) var w = new_day('',window_name); // open a new window (common.js function) // Construct day window title out of this calendar window title. var title = document.title.replace(/^cal /,''); var day_title = Calendar.longdate((new Date(d))); w.document.open(); w.document.write('' + '\n' + '\n' + 'day ' + title + '\n' + '\n' + '\n' + '\n' + '\n' + '\n' + '\n' + '\n' + '
\n' + '\n' + '
\n' + '
\n' + ((header_e) ? header_e.innerHTML : '') + ((header_e) ? '
\n' : '') + '
\n' + ((content_e) ? content_e.innerHTML : '') + '
\n' + '
\n' + '\n' + '
\n' + '\n' + '\n'); w.document.close(); } /* ------------------------------------------------------------------------ */ /* * Additional Calendar application methods */ /** These calendar methods add functionality to the Calendar methods in acmebase/calendar.js. They support a calendar application and are not needed for simple calendar lookups. **/ Calendar.longdate = function(d) { // Return formatted date like "Thursday, January 1, 2004" return '' + Calendar.WeekNames[d.getDay()] + ", " + Calendar.MonthNames[d.getMonth()] + " " + d.getDate() + ", " + d.getFullYear(); } Calendar.prototype.redisplay = function(cmd) { if (this.win != self) { if (cmd != null && cmd != this.Type) this.resize(cmd); this.display(cmd); } else { this.reload(cmd); } } Calendar.prototype.reload = function(cmd) { if (cmd == null) cmd = this.Type; // Compose url with calendar command // Like: 'calendar=n_months,start_date,end_date' var newurl = self.location.href; // // Remove commands from url // // Remove possible calendar command from url. newurl = newurl.replace(/([?&;])calendar=[^&;]*[&;]?/,'$1'); // Remove possible menu coordinates from url. newurl = newurl.replace(/([?&;])menu=[^&;]*[&;]?/,'$1'); // Remove possible resize command from url. newurl = newurl.replace(/([?&;])resize=[^&;]*[&;]?/,'$1'); // Remove possible select_date command from url. newurl = newurl.replace(/([?&;])select(_date)?=[^&;]*[&;]?/,'$1'); // Remove possible start_day command from url. newurl = newurl.replace(/([?&;])start_day=[^&;]*[&;]?/,'$1'); // // Add commands back to url // var sep = '?'; if (newurl.match(/[?]/)) sep = ';'; if (newurl.match(/[?&;]$/)) sep = ''; // Add calendar command to url newurl += sep+'calendar='+cmd+','+this.getStartDate()+','+this.getEndDate(); // Add resize flag to url if (this.Type == cmd) { newurl += ';resize=no'; } // Add selected date if (this.getSelectedDate()) newurl += ';select='+this.getSelectedDate(); // Add start_day (0-6) to url newurl += ';start_day='+this.getStartDay(); // Add menu coordinates to url if (DayMenu.tear_off.is_torn && this.Type == cmd) { var dto = DayMenu.tear_off; newurl += ';menu=' + dto.left + ',' + dto.top; if (dto.width != null) newurl += ',' + dto.width; if (dto.height != null) newurl += ',' + dto.height; if (dto.contents_width != null) newurl += ',' + dto.contents_width; if (dto.contents_height != null)newurl += ',' + dto.contents_height; } // // Redisplay page // self.location.href = newurl; } Calendar.prototype.print = function() { // Note: this method overloads the basic Calendar print() method // used for popup calendars. if (this.win != self) { // Hide navigation button bar var e = this.win.document.getElementById("navigation_toolbar"); e.style.display = 'none'; e.style.visibility = 'hidden'; // Print calendar window if (this.win.print) { this.win.print(); } else { alert("Your browser does not support this shortcut.\n" + "Please select Print from the File menu."); } // Show navigation button bar e.style.display = 'block'; e.style.visibility = 'visible'; } else { var cmd = this.Type; // Compose url with calendar command // Like: 'calendar=n_months,start_date,end_date' var newurl = self.location.href; // Remove possible calendar command at end of url. newurl = newurl.replace(/\Wcalendar=.*$/,''); var sep = newurl.match(/\?/) ? ';' : '?'; // Add print cgi parameter newurl += sep+'print=yes'; sep = ';'; // Add calendar command newurl += sep+'calendar='+cmd+','+this.getStartDate()+','+this.getEndDate(); // Add selected date if (this.selected_date) newurl += sep+'select='+this.selected_date; // Set window to small size var settings = 'width=80,height=80,top=100,left=100,resizable'; // Display new window for print job var w = window.open('','',settings); var title, message; title = message = "Printing..."; w.document.open(); w.document.write('' + '\n' + '\n' + '\n' + '' + title + '\n' + '\n' + '\n' + '\n' + '\n' + '
\n' + '

' + message + '

\n' + '
\n' + '\n' + '\n'); w.document.close(); // Display calendar formatted for printer w.location.href = newurl; } } // appendDate() can be used after the calendar is displayed to add // content to date cells. This should only be used for full screen calendars. Calendar.prototype.appendDate = function(e, date) { if (typeof e == 'string') e = document.getElementById(e); if (typeof e != 'object') return; var w = this.win; if (!w) w = self; // Note: intolerant Netscape 6.2 needs dates in mm/dd/yyyy format (not mm-dd-yyyy) !! var d = new Date(date.replace(/\W/g,"/")); if (isNaN(d)) return; var id =this.DayButtonPrefix + Calendar.dateToString(d); var button = w.document.getElementById(id) if (button) { // Append after date button var newe = button.parentNode.appendChild(e); newe.style.display = "block"; newe.style.visibility = "visible"; } else { // No cell to attach to, hide entry e.style.display = "none"; e.style.visibility = "hidden"; } }