PK eY2׷="="content/calendar/attachFile.js/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Mozilla Communicator client code, released * March 31, 1998. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ /** * In order to distinguish clearly globals that are initialized once when js load (static globals) and those that need to be * initialize every time a compose window open (globals), I (ducarroz) have decided to prefix by s... the static one and * by g... the other one. Please try to continue and repect this rule in the future. Thanks. */ /** * static globals, need to be initialized only once */ var sPrefs = null; var sPrefBranchInternal = null; const kComposeAttachDirPrefName = "mail.compose.attach.dir"; // First get the preferences service try { var prefService = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefService); sPrefs = prefService.getBranch(null); sPrefBranchInternal = sPrefs.QueryInterface(Components.interfaces.nsIPrefBranch2); } catch (ex) { dump("failed to preferences services\n"); } function GetLastAttachDirectory() { var lastDirectory; try { lastDirectory = sPrefs.getComplexValue(kComposeAttachDirPrefName, Components.interfaces.nsILocalFile); } catch (ex) { // this will fail the first time we attach a file // as we won't have a pref value. lastDirectory = null; } return lastDirectory; } // attachedLocalFile must be a nsILocalFile function SetLastAttachDirectory(attachedLocalFile) { try { var file = attachedLocalFile.QueryInterface(Components.interfaces.nsIFile); var parent = file.parent.QueryInterface(Components.interfaces.nsILocalFile); sPrefs.setComplexValue(kComposeAttachDirPrefName, Components.interfaces.nsILocalFile, parent); } catch (ex) { dump("error: SetLastAttachDirectory failed: " + ex + "\n"); } } function AttachFile() { var currentAttachment = ""; //Get file using nsIFilePicker and convert to URL try { var nsIFilePicker = Components.interfaces.nsIFilePicker; var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker); fp.init(window, "Attach File", nsIFilePicker.modeOpen); var lastDirectory = GetLastAttachDirectory(); if (lastDirectory) fp.displayDirectory = lastDirectory; fp.appendFilters(nsIFilePicker.filterAll); if (fp.show() == nsIFilePicker.returnOK) { currentAttachment = fp.fileURL.spec; SetLastAttachDirectory(fp.file) } } catch (ex) { dump("failed to get the local file to attach\n"); } if (currentAttachment == "") return; if (DuplicateFileCheck(currentAttachment)) { dump("Error, attaching the same item twice\n"); } else { var attachment = Components.classes["@mozilla.org/messengercompose/attachment;1"] .createInstance(Components.interfaces.nsIMsgAttachment); attachment.url = currentAttachment; AddAttachment(attachment); } } function AddAttachment(attachment) { if (attachment && attachment.url) { var bucket = document.getElementById("attachmentBucket"); var item = document.createElement("listitem"); if (!attachment.name) attachment.name = attachment.url; item.setAttribute("label", attachment.name); //use for display only item.attachment = attachment; //full attachment object stored here try { item.setAttribute("tooltiptext", decodeURI(attachment.url)); } catch(e) { item.setAttribute("tooltiptext", attachment.url); } item.setAttribute("class", "listitem-iconic"); item.setAttribute("image", "moz-icon:" + attachment.url); bucket.appendChild(item); } } function DuplicateFileCheck(FileUrl) { var bucket = document.getElementById('attachmentBucket'); for (var index = 0; index < bucket.childNodes.length; index++) { var item = bucket.childNodes[index]; var attachment = item.attachment; if (attachment) { if (FileUrl == attachment.url) return true; } } return false; } function RemoveSelectedAttachment() { var child; var bucket = document.getElementById("attachmentBucket"); if (bucket.selectedItems.length > 0) { for (var item = bucket.selectedItems.length - 1; item >= 0; item-- ) { child = bucket.removeChild(bucket.selectedItems[item]) = null; // Let's release the attachment object hold by the node else it won't go away until the window is destroyed child.attachment = null; } } } function AttachmentBucketClicked(event) { if (event.button != 0) return; if (event.originalTarget.localName == "listboxbody") { AttachFile(); } } var attachmentBucketObserver = { canHandleMultipleItems: true, onDrop: function (aEvent, aData, aDragSession) { var dataList = aData.dataList; var dataListLength = dataList.length; var errorTitle; var attachment; var errorMsg; for (var i = 0; i < dataListLength; i++) { var item = dataList[i].first; var prettyName; var rawData = item.data; if (item.flavour.contentType == "text/x-moz-url" || item.flavour.contentType == "text/x-moz-message-or-folder" || item.flavour.contentType == "application/x-moz-file") { if (item.flavour.contentType == "application/x-moz-file") { var ioService = Components.classes["@mozilla.org/network/io-service;1"] .getService(Components.interfaces.nsIIOService); rawData = ioService.getURLSpecFromFile(rawData); } else { var separator = rawData.indexOf("\n"); if (separator != -1) { prettyName = rawData.substr(separator+1); rawData = rawData.substr(0,separator); } } if (DuplicateFileCheck(rawData)) { dump("Error, attaching the same item twice\n"); } else { attachment = Components.classes["@mozilla.org/messengercompose/attachment;1"] .createInstance(Components.interfaces.nsIMsgAttachment); attachment.url = rawData; attachment.name = prettyName; AddAttachment(attachment); } } } }, onDragOver: function (aEvent, aFlavour, aDragSession) { var attachmentBucket = document.getElementById("attachmentBucket"); attachmentBucket.setAttribute("dragover", "true"); }, onDragExit: function (aEvent, aDragSession) { var attachmentBucket = document.getElementById("attachmentBucket"); attachmentBucket.removeAttribute("dragover"); }, getSupportedFlavours: function () { var flavourSet = new FlavourSet(); flavourSet.appendFlavour("text/x-moz-url"); flavourSet.appendFlavour("text/x-moz-message-or-folder"); flavourSet.appendFlavour("application/x-moz-file", "nsIFile"); return flavourSet; } }; PK Z677"")content/calendar/calendar-dnd-listener.js/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Calendar Drag-n-drop code. * * The Initial Developer of the Original Code is * Joey Minta * Portions created by the Initial Developer are Copyright (C) 2006 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Michael Buettner * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ var calendarDNDObserver = { getSupportedFlavours: function calDNDGetFlavors() { var flavourSet = new FlavourSet(); flavourSet.appendFlavour("application/x-moz-file"); flavourSet.appendFlavour("text/x-moz-url"); flavourSet.appendFlavour("text/calendar"); flavourSet.appendFlavour("text/unicode"); return flavourSet; }, onDrop: function calDNDDrop(aEvent, aTransferData, aDragSession) { var transferable = Components.classes["@mozilla.org/widget/transferable;1"] .createInstance(Components.interfaces.nsITransferable); transferable.addDataFlavor("text/x-moz-url"); transferable.addDataFlavor("application/x-moz-file"); transferable.addDataFlavor("text/calendar"); transferable.addDataFlavor("text/unicode"); aDragSession.getData(transferable, 0); var data = new Object(); var bestFlavor = new Object(); var length = new Object(); transferable.getAnyTransferData(bestFlavor, data, length); data = data.value.QueryInterface(Components.interfaces.nsISupportsString); // Treat unicode data with VEVENT in it as text/calendar if (bestFlavor.value == "text/unicode" && data.toString().indexOf("VEVENT") != -1) { bestFlavor.value = "text/calendar"; } var destCal = getSelectedCalendar(); switch (bestFlavor.value) { case "text/calendar": var parser = Components.classes["@mozilla.org/calendar/ics-parser;1"] .createInstance(Components.interfaces.calIIcsParser); parser.parseString(data); startBatchTransaction(); try { for each (var item in parser.getItems({})) { doTransaction('add', item, destCal, null, null); } } finally { endBatchTransaction(); } break; case "text/unicode": var droppedUrl = this.retrieveURLFromData(data, bestFlavor.value); if (!droppedUrl) return; var url = makeURL(droppedUrl); var localFileInstance = Components.classes["@mozilla.org/file/local;1"] .createInstance(Components.interfaces.nsILocalFile); localFileInstance.initWithPath(url.path); var inputStream = Components.classes["@mozilla.org/network/file-input-stream;1"] .createInstance(Components.interfaces.nsIFileInputStream); inputStream.init(localFileInstance, MODE_RDONLY, 0444, {}); try { //XXX support csv var importer = Components.classes["@mozilla.org/calendar/import;1?type=ics"] .getService(Components.interfaces.calIImporter); var items = importer.importFromStream(inputStream, {}); startBatchTransaction(); try { for each (item in items) { doTransaction('add', item, destCal, null, null); } } finally { endBatchTransaction(); } } finally { inputStream.close(); } break; case "application/x-moz-file-promise": case "text/x-moz-url": var ioService = Components.classes["@mozilla.org/network/io-service;1"] .getService(Components.interfaces.nsIIOService); var uri = ioService.newURI(data.toString(), null, null); var loader = Components.classes["@mozilla.org/network/unichar-stream-loader;1"] .createInstance(Components.interfaces.nsIUnicharStreamLoader); channel = ioService.newChannelFromURI(uri); channel.loadFlags |= Components.interfaces.nsIRequest.LOAD_BYPASS_CACHE; var listener = { // nsIUnicharStreamLoaderObserver: onDetermineCharset: function(loader, context, firstSegment, length) { var charset = null; if (loader && loader.channel) { charset = channel.contentCharset; } if (!charset || charset.length == 0) { charset = "UTF-8"; } return charset; }, onStreamComplete: function(loader, context, status, unicharData) { if (unicharData) { var str = ""; var str_ = {}; while (unicharData.readString(-1, str_)) { str += str_.value; } var parser = Components.classes["@mozilla.org/calendar/ics-parser;1"] .createInstance(Components.interfaces.calIIcsParser); parser.parseString(str); startBatchTransaction(); try { for each (var item in parser.getItems({})) { doTransaction('add', item, destCal, null, null); } } finally { endBatchTransaction(); } } } }; try { loader.init(channel, listener, null, 0); } catch(e) { Component.utils.reportError(e) } break; default: dump("unknown data flavour:" + bestFlavor.value+'\n'); break; } }, onDragStart: function calDNDStart(aEvent, aTransferData, aDragAction) {}, onDragOver: function calDNDOver(aEvent, aFlavor, aDragSession) {}, onDragExit: function calDNDExit(aEvent, aDragSession) {}, retrieveURLFromData: function calDNDRetrieveURL(aData, aFlavor) { var data; switch (aFlavor) { case "text/unicode": data = aData.toString(); var separator = data.indexOf("\n"); if (separator != -1) data = data.substr(0, separator); return data; case "application/x-moz-file": return aData.URL; default: return null; } } }; PK -M62"content/calendar/calendarWindow.js/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is OEone Calendar Code, released October 31st, 2001. * * The Initial Developer of the Original Code is * OEone Corporation. * Portions created by the Initial Developer are Copyright (C) 2001 * the Initial Developer. All Rights Reserved. * * Contributor(s): Garth Smedley * Mike Potter * Eric Belhaire * Robin Edrenius * Joey Minta * Philipp Kewisch * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ /*----------------------------------------------------------------- * C A L E N D A R C L A S S E S */ /*----------------------------------------------------------------- * CalendarWindow Class * * Maintains the three calendar views and the selection. * * PROPERTIES * selectedDate - selected date, instance of Date * */ /** * CalendarWindow Constructor. * * NOTES * There is one instance of CalendarWindow * WARNING: As much as we all love CalendarWindow, it's going to die soon. */ function CalendarWindow( ) { // Extension authors can tweak this array to make gCalendarWindow.switchToView // play nicely with any additional views this.availableViews = ["day", "week", "multiweek", "month"]; /** This object only exists to keep too many things from breaking during the * switch to the new views **/ this.currentView = { changeNumberOfWeeks: function(menuitem) { var mwView = document.getElementById("view-deck").selectedPanel; mwView.weeksInView = menuitem.value; } }; // Get the last view that was shown before shutdown, and switch to it var SelectedIndex = document.getElementById("view-deck").selectedIndex; switch( SelectedIndex ) { case "1": this.switchToView('week'); break; case "2": this.switchToView('multiweek'); break; case "3": this.switchToView('month'); break; case "0": default: this.switchToView('day'); break; } } /** PUBLIC * * Display today in the current view */ CalendarWindow.prototype.goToToday = function calWin_goToToday( ) { document.getElementById("lefthandcalendar").value = new Date(); document.getElementById("view-deck").selectedPanel.goToDay(now()); } /** PUBLIC * * Choose a date, then go to that date in the current view. */ CalendarWindow.prototype.pickAndGoToDate = function calWin_pickAndGoToDate( ) { var args = new Object(); args.initialDate = currentView().selectedDay.getInTimezone("floating").jsDate; args.onOk = function receiveAndGoToDate( pickedDate ) { currentView().goToDay( jsDateToDateTime(pickedDate) ); document.getElementById( "lefthandcalendar" ).value = pickedDate; }; openDialog("chrome://calendar/content/goToDateDialog.xul", "GoToDateDialog", // target= window name "chrome,modal", args); } /** PUBLIC * * Go to today in the current view */ CalendarWindow.prototype.goToDay = function calWin_goToDay( newDate ) { var view = document.getElementById("view-deck").selectedPanel; var cdt = Components.classes["@mozilla.org/calendar/datetime;1"] .createInstance(Components.interfaces.calIDateTime); cdt.year = newDate.getFullYear(); cdt.month = newDate.getMonth(); cdt.day = newDate.getDate(); cdt.isDate = true; cdt.timezone = view.timezone; view.goToDay(cdt); } /** PRIVATE * * Helper function to switch to a view * * PARAMETERS * newView - MUST be one of the three CalendarView instances created in the constructor */ CalendarWindow.prototype.switchToView = function calWin_switchToView( newView ) { // Set up the commands for each (var view in this.availableViews) { var command = document.getElementById(view+"_view_command"); if (view == newView) { command.setAttribute("checked", true); } else { command.removeAttribute("checked"); } } var mwWeeksCommand = document.getElementById("menu-numberofweeks-inview") if (newView == "multiweek") { mwWeeksCommand.removeAttribute("disabled"); } else { mwWeeksCommand.setAttribute("disabled", true); } // Disable the orientation menuitem on non multiday views var mwOrientCommand = document.getElementById("menu-multiday-rotated"); if (newView == "day" || newView == "week") { mwOrientCommand.removeAttribute("disabled"); } else { mwOrientCommand.setAttribute("disabled", true); } // Call the common view switching code in calendar-views.js switchToView(newView); var labelAttribute = "label-"+newView+"-view"; var prevCommand = document.getElementById("calendar-go-menu-previous"); prevCommand.setAttribute("label", prevCommand.getAttribute(labelAttribute)); var nextCommand = document.getElementById("calendar-go-menu-next"); nextCommand.setAttribute("label", nextCommand.getAttribute(labelAttribute)); } PK 87%content/calendar/calendarCreation.xul %dtd1; %dtd2; ]> &calendar.publish.example.url.description; PK 87Thhcontent/calendar/unifinder.js/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is OEone Calendar Code, released October 31st, 2001. * * The Initial Developer of the Original Code is * OEone Corporation. * Portions created by the Initial Developer are Copyright (C) 2001 * the Initial Developer. All Rights Reserved. * * Contributor(s): Garth Smedley * Mike Potter * Chris Charabaruk * Colin Phillips * ArentJan Banck * Eric Belhaire * Matthew Willis * Michiel van Leeuwen * Joey Minta * Dan Mosedale * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ /*----------------------------------------------------------------- * U N I F I N D E R * * This is a hacked in interface to the unifinder. We will need to * improve this to make it usable in general. */ const UnifinderTreeName = "unifinder-search-results-listbox"; const kEventStatusOrder = ["TENTATIVE", "CONFIRMED", "CANCELLED"]; var gCalendarEventTreeClicked = false; //set this to true when the calendar event tree is clicked //to allow for multiple selection var gEventArray = new Array(); // Store the start and enddate, because the providers can't be trusted when // dealing with all-day events. So we need to filter later. See bug 306157 var gStartDate; var gEndDate; var kDefaultTimezone; function resetAllowSelection() { /* Do not change anything in the following lines, they are needed as described in the selection observer above */ doingSelection = false; var SearchTree = document.getElementById( UnifinderTreeName ); SearchTree.view.selection.selectEventsSuppressed = false; SearchTree.addEventListener( "select", unifinderOnSelect, true ); } var doingSelection = false; function selectSelectedEventsInTree( EventsToSelect ) { if( doingSelection === true ) return; doingSelection = true; if( EventsToSelect === false ) EventsToSelect = currentView().getSelectedItems({}); var SearchTree = document.getElementById( UnifinderTreeName ); /* The following is a brutal hack, caused by http://lxr.mozilla.org/mozilla1.0/source/layout/xul/base/src/tree/src/nsTreeSelection.cpp#555 and described in bug 168211 http://bugzilla.mozilla.org/show_bug.cgi?id=168211 Do NOT remove anything in the next 3 lines, or the selection in the tree will not work. */ SearchTree.onselect = null; SearchTree.removeEventListener( "select", unifinderOnSelect, true ); SearchTree.view.selection.selectEventsSuppressed = true; if( EventsToSelect && EventsToSelect.length == 1 ) { var RowToScrollTo = SearchTree.eventView.getRowOfCalendarEvent( EventsToSelect[0] ); if( RowToScrollTo != "null" ) { SearchTree.view.selection.clearSelection( ); SearchTree.treeBoxObject.ensureRowIsVisible( RowToScrollTo ); SearchTree.view.selection.timedSelect( RowToScrollTo, 1 ); } else { SearchTree.view.selection.clearSelection( ); } } else if( EventsToSelect && EventsToSelect.length > 1 ) { SearchTree.view.selection.clearSelection( ); for (var i in EventsToSelect) { var row = SearchTree.eventView.getRowOfCalendarEvent(EventsToSelect[i]); SearchTree.view.selection.rangedSelect(row,row,true); } } else { SearchTree.view.selection.clearSelection( ); } /* This needs to be in a setTimeout */ setTimeout( "resetAllowSelection()", 1 ); } /** * Observer for the calendar event data source. This keeps the unifinder * display up to date when the calendar event data is changed */ var unifinderObserver = { mInBatch: false, QueryInterface: function (aIID) { if (!aIID.equals(Components.interfaces.nsISupports) && !aIID.equals(Components.interfaces.calICompositeObserver) && !aIID.equals(Components.interfaces.calIObserver)) { throw Components.results.NS_ERROR_NO_INTERFACE; } return this; }, // calIObserver: onStartBatch: function() { this.mInBatch = true; }, onEndBatch: function() { this.mInBatch = false; refreshEventTree(); }, onLoad: function() { if (!this.mInBatch) refreshEventTree(); }, onAddItem: function(aItem) { if (!(aItem instanceof Components.interfaces.calIEvent) || this.mInBatch) { return; } this.addItemToTree(aItem); }, onModifyItem: function(aNewItem, aOldItem) { if (this.mInBatch) { return; } if (aOldItem instanceof Components.interfaces.calIEvent) { this.removeItemFromTree(aOldItem); } if (aNewItem instanceof Components.interfaces.calIEvent) { this.addItemToTree(aNewItem); } }, onDeleteItem: function(aDeletedItem) { if (!(aDeletedItem instanceof Components.interfaces.calIEvent) || this.mInBatch) { return; } this.removeItemFromTree(aDeletedItem); }, dateFilter: function(event) { return ((!gEndDate || gEndDate.compare(event.startDate) >= 0) && (!gStartDate || gStartDate.compare(event.endDate) < 0)); }, // It is safe to call these for any event. The functions will determine // whether or not anything actually needs to be done to the tree addItemToTree: function(aItem) { var items; if (gStartDate && gEndDate) { items = aItem.getOccurrencesBetween(gStartDate, gEndDate, {}); } else { items = [aItem]; } items = items.filter(this.dateFilter); gEventArray = gEventArray.concat(items); gEventArray.sort(compareEvents); var tree = document.getElementById("unifinder-search-results-listbox"); for each (var item in items) { var row = tree.eventView.getRowOfCalendarEvent(item); tree.treeBoxObject.rowCountChanged(row, 1); } }, removeItemFromTree: function(aItem) { var items; if (gStartDate && gEndDate && (aItem.parentItem == aItem)) { items = aItem.getOccurrencesBetween(gStartDate, gEndDate, {}); } else { items = [aItem]; } items = items.filter(this.dateFilter); var tree = document.getElementById("unifinder-search-results-listbox"); for each (var item in items) { var row = tree.eventView.getRowOfCalendarEvent(item); gEventArray.splice(row, 1); tree.treeBoxObject.rowCountChanged(row, -1); } }, onError: function(aErrNo, aMessage) {}, // calICompositeObserver: onCalendarAdded: function(aDeletedItem) { if (!this.mInBatch) refreshEventTree(); }, onCalendarRemoved: function(aDeletedItem) { if (!this.mInBatch) refreshEventTree(); }, onDefaultCalendarChanged: function(aNewDefaultCalendar) {} }; /** * Called when the calendar is loaded */ function prepareCalendarUnifinder( ) { function onGridSelect(aEvent) { selectSelectedEventsInTree(aEvent.detail); } // set up our calendar event observer var ccalendar = getCompositeCalendar(); ccalendar.addObserver(unifinderObserver); kDefaultTimezone = calendarDefaultTimezone(); // Listen for changes in the selected day, so we can update if need be var viewDeck = document.getElementById("view-deck") viewDeck.addEventListener("dayselect", unifinderOnDaySelect, false); viewDeck.addEventListener("itemselect", onGridSelect, true); refreshEventTree(); //Display something upon first load. onLoad doesn't work properly for observers } /** * Called when the calendar is unloaded */ function finishCalendarUnifinder( ) { var ccalendar = getCompositeCalendar(); ccalendar.removeObserver(unifinderObserver); } function unifinderOnDaySelect() { var filterList = document.getElementById("event-filter-menulist"); if (filterList.selectedItem.value == "current") { refreshEventTree(); } } /** * Helper function to display event datetimes in the unifinder */ function formatUnifinderEventDateTime(datetime) { var dateFormatter = Components.classes["@mozilla.org/calendar/datetime-formatter;1"] .getService(Components.interfaces.calIDateTimeFormatter); return dateFormatter.formatDateTime(datetime.getInTimezone(kDefaultTimezone)); } /** * This is attached to the ondblclik attribute of the events shown in the unifinder */ function unifinderDoubleClickEvent( event ) { // we only care about button 0 (left click) events if (event.button != 0) return; // find event by id var calendarEvent = getCalendarEventFromEvent( event ); if( calendarEvent != null ) modifyEventWithDialog(calendarEvent); else createEventWithDialog(); } function getCalendarEventFromEvent( event ) { var tree = document.getElementById( UnifinderTreeName ); var row = tree.treeBoxObject.getRowAt( event.clientX, event.clientY ); if( row != -1 && row < tree.view.rowCount ) { return ( tree.eventView.getCalendarEventAtRow( row ) ); } else { return ( null ); } } /** * This is attached to the onclik attribute of the events shown in the unifinder */ function unifinderOnSelect( event ) { if( event.target.view.selection.getRangeCount() == 0 ) return; var ArrayOfEvents = new Array( ); gCalendarEventTreeClicked = true; var calendarEvent; //get the selected events from the tree var tree = document.getElementById( UnifinderTreeName ); var start = new Object(); var end = new Object(); var numRanges = tree.view.selection.getRangeCount(); for (var t=0; t b) ? 1 : 0); } function nullToEmpty(value) { return value == null? "" : value; } function compareMSTime(a, b) { return ((a < b) ? -1 : (a > b) ? 1 : 0); } function msNextOrPreviousRecurrenceStart( calendarEvent ) { return calendarEvent.startDate.nativeTime; // XXX reimplement the following if (calendarEvent.recur && calendarEvent.start) { treeView.outParameter.value = null; // avoid creating objects during sort if (calendarEvent.getNextRecurrence(treeView.sortStartedTime, treeView.outParameter) || calendarEvent.getPreviousOccurrence(treeView.sortStartedTime, treeView.outParameter)) return treeView.outParameter.value; } return dateToMilliseconds(calendarEvent.start); } function msNextOrPreviousRecurrenceEnd(event) { return event.endDate.nativeTime; //XXX reimplement the following var msNextStart = msNextOrPreviousRecurrenceStart(event); var msDuration=dateToMilliseconds(event.endDate)-dateToMilliseconds(event.startDate); return msNextStart + msDuration; } function dateToMilliseconds(date) { // Treat null/0 as 'now' when sort started, so incomplete tasks stay current. // Time is computed once per sort (just before sort) so sort is stable. if (date == null) return treeView.sortStartedTime; var ms = date.getTime(); // note: date is not a javascript date. if (ms == -62171262000000) // ms value for (0000/00/00 00:00:00) return treeView.sortStartedTime; return ms; } function calendarEventView( eventArray ) { this.eventArray = eventArray; } calendarEventView.prototype.getCalendarEventAtRow = function( i ) { return( gEventArray[ i ] ); } calendarEventView.prototype.getRowOfCalendarEvent = function( Event ) { if (!Event) { return null; } for (var i in gEventArray) { if (gEventArray[i].hashId == Event.hashId) return i; } return null; } function refreshEventTree( eventArray ) { var savedThis = this; var refreshListener = { mEventArray: new Array(), onOperationComplete: function (aCalendar, aStatus, aOperationType, aId, aDateTime) { setTimeout(function () { refreshEventTreeInternal(refreshListener.mEventArray); }, 0); }, onGetResult: function (aCalendar, aStatus, aItemType, aDetail, aCount, aItems) { for (var i = 0; i < aCount; i++) { refreshListener.mEventArray.push(aItems[i]); } } }; var Today = new Date(); //do this to allow all day events to show up all day long var StartDate = new Date( Today.getFullYear(), Today.getMonth(), Today.getDate(), 0, 0, 0 ); var EndDate; var ccalendar = getCompositeCalendar(); var filter = 0; filter |= ccalendar.ITEM_FILTER_TYPE_EVENT; switch( document.getElementById( "event-filter-menulist" ).selectedItem.value ) { case "all": StartDate = null; EndDate = null; break; case "today": EndDate = new Date( StartDate.getTime() + ( 1000 * 60 * 60 * 24 ) - 1 ); break; case "next7Days": EndDate = new Date( StartDate.getTime() + ( 1000 * 60 * 60 * 24 * 8 ) ); break; case "next14Days": EndDate = new Date( StartDate.getTime() + ( 1000 * 60 * 60 * 24 * 15 ) ); break; case "next31Days": EndDate = new Date( StartDate.getTime() + ( 1000 * 60 * 60 * 24 * 32 ) ); break; case "thisCalendarMonth": // midnight on first day of this month var startOfMonth = new Date( Today.getFullYear(), Today.getMonth(), 1, 0, 0, 0 ); // midnight on first day of next month var startOfNextMonth = new Date( Today.getFullYear(), (Today.getMonth() + 1), 1, 0, 0, 0 ); // 23:59:59 on last day of this month EndDate = new Date( startOfNextMonth.getTime() - 1000 ); StartDate = startOfMonth; break; case "future": EndDate = null; break; case "current": var SelectedDate = currentView().selectedDay.jsDate; StartDate = new Date( SelectedDate.getFullYear(), SelectedDate.getMonth(), SelectedDate.getDate(), 0, 0, 0 ); EndDate = new Date( StartDate.getTime() + ( 1000 * 60 * 60 * 24 ) - 1000 ); break; default: dump( "there's no case for "+document.getElementById( "event-filter-menulist" ).selectedItem.value+"\n" ); EndDate = StartDate; break; } gStartDate = StartDate ? jsDateToDateTime(StartDate).getInTimezone(calendarDefaultTimezone()) : null; gEndDate = EndDate ? jsDateToDateTime(EndDate).getInTimezone(calendarDefaultTimezone()) : null; if (StartDate && EndDate) { filter |= ccalendar.ITEM_FILTER_CLASS_OCCURRENCES; } ccalendar.getItems (filter, 0, gStartDate, gEndDate, refreshListener); } function refreshEventTreeInternal(eventArray) { var searchText = document.getElementById( "unifinder-search-field" ).value; searchText = searchText.toLowerCase(); // XXX match for strings with only whitespace. Skip those too if (searchText.length) { gEventArray = new Array(); var fieldsToSearch = ["DESCRIPTION", "LOCATION", "CATEGORIES", "URL"]; for (var j in eventArray) { var event = eventArray[j]; if (event.title && event.title.toLowerCase().indexOf(searchText) != -1 ) { gEventArray.push(event); } else { for (var k in fieldsToSearch) { var val = event.getProperty(fieldsToSearch[k]); if (val && val.toLowerCase().indexOf(searchText) != -1 ) { gEventArray.push(event); break; } } } } } else { gEventArray = eventArray; } // Extra check to see if the events are in the daterange. Some providers // are broken when looking at all-day events. function dateFilter(event) { // Using .compare on the views start and end, not on the events dates, // because .compare uses the timezone of the datetime it is called on. // The view's timezone is what is important here. return ((!gEndDate || gEndDate.compare(event.startDate) >= 0) && (!gStartDate || gStartDate.compare(event.endDate) < 0)); } gEventArray = gEventArray.filter(dateFilter); var ArrayOfTreeCols = document.getElementById( UnifinderTreeName ).getElementsByTagName( "treecol" ); for( var i = 0; i < ArrayOfTreeCols.length; i++ ) { if( ArrayOfTreeCols[i].getAttribute( "sortActive" ) == "true" ) { treeView.selectedColumn = ArrayOfTreeCols[i].getAttribute( "id" ); treeView.sortDirection = ArrayOfTreeCols[i].getAttribute("sortDirection"); treeView.sortStartedTime = new Date().getTime(); //for null/0 dates gEventArray.sort(compareEvents); break; } } document.getElementById( UnifinderTreeName ).view = treeView; document.getElementById( UnifinderTreeName ).eventView = new calendarEventView( gEventArray ); //select selected events in the tree. selectSelectedEventsInTree( false ); } function unifinderKeyPress(aEvent) { const kKE = Components.interfaces.nsIDOMKeyEvent; switch (aEvent.keyCode) { case 13: // Enter, edit the event modifyEventWithDialog(getSelectedItems()[0]); break; case kKE.DOM_VK_BACK_SPACE: case kKE.DOM_VK_DELETE: deleteEventCommand(true); break; } } function focusSearch() { document.getElementById("unifinder-search-field").focus(); } PK P6??%content/calendar/mouseoverPreviews.js/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is OEone Calendar Code, released October 31st, 2001. * * The Initial Developer of the Original Code is * OEone Corporation. * Portions created by the Initial Developer are Copyright (C) 2001 * the Initial Developer. All Rights Reserved. * * Contributor(s): Garth Smedley * Mike Potter * Chris Charabaruk * Colin Phillips * Karl Guertin * Mike Norton * ArentJan Banck * Eric Belhaire * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ /** * Code which generates event and task (todo) preview tooltips/titletips * when the mouse hovers over either the event list, the task list, or * an event or task box in one of the grid views. * * (Portions of this code were previously in calendar.js and unifinder.js, * some of it duplicated.) */ /** PUBLIC * * This changes the mouseover preview based on the start and end dates * of an occurrence of a (one-time or recurring) calEvent or calToDo. * Used by all grid views. */ function onMouseOverItem( occurrenceBoxMouseEvent ) { if ("occurrence" in occurrenceBoxMouseEvent.currentTarget) { // occurrence of repeating event or todo var occurrence = occurrenceBoxMouseEvent.currentTarget.occurrence; const toolTip = document.getElementById("itemTooltip"); var holderBox; if (isEvent(occurrence)) { holderBox = getPreviewForEvent(occurrence, occurrence.startDate, occurrence.endDate); } else if (isToDo(occurrence)) { holderBox = getPreviewForTask(occurrence); } if (holderBox) { setToolTipContent(toolTip, holderBox); return true; } } return false; } /** For all instances of an event, as displayed by unifinder. **/ function onMouseOverEventTree( toolTip, mouseEvent ) { var item = getCalendarEventFromEvent( mouseEvent ); if (isEvent(item)) { var holderBox = getPreviewForEvent(item); if (holderBox) { setToolTipContent(toolTip, holderBox); return true; } } return false; } /** For all instances of a task, as displayed by unifinderToDo. **/ function onMouseOverTaskTree( toolTip, mouseEvent ) { var item = getToDoFromEvent( mouseEvent ); if (isToDo(item)) { var holderBox = getPreviewForTask(item); if (holderBox) { setToolTipContent(toolTip, holderBox); return true; } } return false; } /** * Removes old content from tooltip, adds new content box to tooltip, * then resizes the tooltip to the size of the new content box. * * @param tooltip The tooltip to modify. * @param holderBox The box element containing the new content. */ function setToolTipContent(toolTip, holderBox) { while (toolTip.hasChildNodes()) { toolTip.removeChild( toolTip.firstChild ); } toolTip.appendChild( holderBox ); var width = holderBox.boxObject.width; var height = holderBox.boxObject.height; // workaround bug 369225 (aspect: tooltip may not shrink height) toolTip.sizeTo(0,0); // workaround bug 369225 (aspect: tooltip height too short) // Add top and bottom border and padding to workaround bug where bottom // tooltip border disappears if wrapped description below header grid. height += 1 + 2 + 2 + 1; toolTip.sizeTo(width, height); } /** * Called when a user hovers over a todo element and the text for the mouse over is changed. */ function getPreviewForTask( toDoItem ) { if( toDoItem ) { const vbox = document.createElement( "vbox" ); vbox.setAttribute("class", "tooltipBox"); // tooltip appears above or below pointer, so may have as little as // one half the screen height available (avoid top going off screen). vbox.maxHeight = Math.floor(screen.height / 2); boxInitializeHeaderGrid(vbox); var hasHeader = false; if (toDoItem.title) { boxAppendLabeledText(vbox, "tooltipTitle", toDoItem.title); hasHeader = true; } var location = toDoItem.getProperty("LOCATION"); if (location) { boxAppendLabeledText(vbox, "tooltipLocation", location); hasHeader = true; } if (toDoItem.entryDate && toDoItem.entryDate.isValid) { boxAppendLabeledDateTime(vbox, "tooltipStart", toDoItem.entryDate); hasHeader = true; } if (toDoItem.dueDate && toDoItem.dueDate.isValid) { boxAppendLabeledDateTime(vbox, "tooltipDue", toDoItem.dueDate); hasHeader = true; } if (toDoItem.priority && toDoItem.priority != 0) { var priorityInteger = parseInt(toDoItem.priority); var priorityString; // These cut-offs should match calendar-event-dialog.js if (priorityInteger >= 1 && priorityInteger <= 4) { priorityString = calGetString('calendar', 'highPriority'); // high priority } else if (priorityInteger == 5) { priorityString = calGetString('calendar', 'mediumPriority'); // medium priority } else { priorityString = calGetString('calendar', 'lowPriority'); // low priority } boxAppendLabeledText(vbox, "tooltipPriority", priorityString); hasHeader = true; } if (toDoItem.status && toDoItem.status != "NONE") { var status = getToDoStatusString(toDoItem); boxAppendLabeledText(vbox, "tooltipStatus", status); hasHeader = true; } if (toDoItem.percentComplete != 0 && toDoItem.percentComplete != 100) { boxAppendLabeledText(vbox, "tooltipPercent", String(toDoItem.percentComplete)+"%"); hasHeader = true; } else if (toDoItem.percentComplete == 100) { if (toDoItem.completedDate == null) { boxAppendLabeledText(vbox, "tooltipPercent", "100%"); } else { boxAppendLabeledDateTime(vbox, "tooltipCompleted", toDoItem.completedDate); } hasHeader = true; } var description = toDoItem.getProperty("DESCRIPTION"); if (description) { // display wrapped description lines like body of message below headers if (hasHeader) { boxAppendBodySeparator(vbox); } boxAppendBody(vbox, description); } return ( vbox ); } else { return null; } } /** * Called when mouse moves over a different, or * when mouse moves over event in event list. * The instStartDate is date of instance displayed at event box * (recurring or multiday events may be displayed by more than one event box * for different days), or null if should compute next instance from now. */ function getPreviewForEvent( event, instStartDate, instEndDate ) { const vbox = document.createElement( "vbox" ); vbox.setAttribute("class", "tooltipBox"); // tooltip appears above or below pointer, so may have as little as // one half the screen height available (avoid top going off screen). vbox.maxHeight = Math.floor(screen.height / 2); boxInitializeHeaderGrid(vbox); if (event) { if (event.title) { boxAppendLabeledText(vbox, "tooltipTitle", event.title); } var location = event.getProperty("LOCATION"); if (location) { boxAppendLabeledText(vbox, "tooltipLocation", location); } if (event.startDate || instStartDate) { var startDate, endDate; if (instStartDate && instEndDate) { startDate = instStartDate; endDate = instEndDate; } else { // Event may be recurrent event. If no displayed instance specified, // use next instance, or previous instance if no next instance. var occ = getCurrentNextOrPreviousRecurrence(event); startDate = instStartDate || occ.startDate; endDate = occ.endDate; } boxAppendLabeledDateTimeInterval(vbox, "tooltipDate", startDate, endDate); } if (event.status && event.status != "NONE") { var statusString = getEventStatusString(event); boxAppendLabeledText(vbox, "tooltipStatus", statusString); } var description = event.getProperty("DESCRIPTION"); if (description) { boxAppendBodySeparator(vbox); // display wrapped description lines, like body of message below headers boxAppendBody(vbox, description); } return ( vbox ); } else { return null; } } /** String for event status: (none), Tentative, Confirmed, or Cancelled **/ function getEventStatusString(calendarEvent) { switch( calendarEvent.status ) { // Event status value keywords are specified in RFC2445sec4.8.1.11 case "TENTATIVE": return calGetString('calendar', "statusTentative"); case "CONFIRMED": return calGetString('calendar', "statusConfirmed"); case "CANCELLED": return calGetString('calendar', "statusCancelled"); default: return ""; } } /** String for todo status: (none), NeedsAction, InProcess, Cancelled, or Completed **/ function getToDoStatusString(iCalToDo) { switch( iCalToDo.status ) { // Todo status keywords are specified in RFC2445sec4.8.1.11 case "NEEDS-ACTION": return calGetString('calendar', "statusNeedsAction"); case "IN-PROCESS": return calGetString('calendar', "statusInProcess"); case "CANCELLED": return calGetString('calendar', "statusCancelled"); case "COMPLETED": return calGetString('calendar', "statusCompleted"); default: return ""; } } /** * PRIVATE: Append a separator, a thin space between header and body. * * @param vbox box to which to append separator. */ function boxAppendBodySeparator(vbox) { const separator = document.createElement("separator"); separator.setAttribute("class", "tooltipBodySeparator"); vbox.appendChild(separator); } /** * PRIVATE: Append description to box for body text. Text may contain * paragraphs; line indent and line breaks will be preserved by CSS. * @param box box to which to append body * @param textString text of body */ function boxAppendBody(box, textString) { var textNode = document.createTextNode(textString); var xulDescription = document.createElement("description"); xulDescription.setAttribute("class", "tooltipBody"); xulDescription.appendChild(textNode); box.appendChild(xulDescription); } /** * PRIVATE: Use dateFormatter to format date and time, * and to header grid append a row containing localized Label: date. */ function boxAppendLabeledDateTime(box, labelProperty, date) { var dateFormatter = Components.classes["@mozilla.org/calendar/datetime-formatter;1"] .getService(Components.interfaces.calIDateTimeFormatter); date = date.getInTimezone(calendarDefaultTimezone()); var formattedDateTime = dateFormatter.formatDateTime(date); boxAppendLabeledText(box, labelProperty, formattedDateTime); } /** * PRIVATE: Use dateFormatter to format date and time interval, * and to header grid append a row containing localized Label: interval. * @param box contains header grid. * @param labelProperty name of property for localized field label. * @param start calDateTime of start of time interval. * @param end calDateTime of end of time interval. */ function boxAppendLabeledDateTimeInterval(box, labelProperty, start, end) { var dateFormatter = Components.classes["@mozilla.org/calendar/datetime-formatter;1"] .getService(Components.interfaces.calIDateTimeFormatter); var startString = new Object(); var endString = new Object(); start = start.getInTimezone(calendarDefaultTimezone()); end = end.getInTimezone(calendarDefaultTimezone()); dateFormatter.formatInterval(start, end, startString, endString); if (endString.value != "") { boxAppendLabeledText(box, labelProperty, startString.value + ' - ' + endString.value); } else { boxAppendLabeledText(box, labelProperty, startString.value); } } /** * PRIVATE: create empty 2-column grid for header fields, * and append it to box. */ function boxInitializeHeaderGrid(box) { var grid = document.createElement("grid"); grid.setAttribute("class", "tooltipHeaderGrid"); var rows; { var columns = document.createElement("columns"); { var labelColumn = document.createElement("column"); labelColumn.setAttribute("class", "tooltipLabelColumn"); columns.appendChild(labelColumn); var valueColumn = document.createElement("column"); valueColumn.setAttribute("class", "tooltipValueColumn"); columns.appendChild(valueColumn); } grid.appendChild(columns); rows = document.createElement("rows"); grid.appendChild(rows); } box.appendChild(grid); } /** * PRIVATE: To headers grid, append a row containing Label: value, * where label is localized text for labelProperty. * @param box box containing headers grid * @param labelProperty name of property for localized name of header * @param textString value of header field. */ function boxAppendLabeledText(box, labelProperty, textString) { var labelText = calGetString('calendar', labelProperty); var rows = box.getElementsByTagName("rows")[0]; { var row = document.createElement("row"); { row.appendChild(createTooltipHeaderLabel(labelText)); row.appendChild(createTooltipHeaderDescription(textString)); } rows.appendChild(row); } } /** PRIVATE: create element for field label (for header grid). **/ function createTooltipHeaderLabel(text) { var label = document.createElement("label"); label.setAttribute("class", "tooltipHeaderLabel"); label.appendChild(document.createTextNode(text)); return label; } /** PRIVATE: create element for field value (for header grid). **/ function createTooltipHeaderDescription(text) { var label = document.createElement("description"); label.setAttribute("class", "tooltipHeaderDescription"); label.appendChild(document.createTextNode(text)); return label; } /** * If now is during an occurrence, return the ocurrence. * Else if now is before an ocurrence, return the next ocurrence. * Otherwise return the previous ocurrence. */ function getCurrentNextOrPreviousRecurrence(calendarEvent) { if (!calendarEvent.recurrenceInfo) { return calendarEvent; } var dur = calendarEvent.duration.clone(); dur.isNegative = true; // To find current event when now is during event, look for occurrence // starting duration ago. var probeTime = now(); probeTime.addDuration(dur); var occ = calendarEvent.recurrenceInfo.getNextOccurrence(probeTime); if (!occ) { var occs = calendarEvent.recurrenceInfo.getOccurrences(calendarEvent.startDate, probeTime, 0, {}); occ = occs[occs.length -1]; } return occ; } PK 4-ihh)content/calendar/converters/date-time.xsl $Id: date-time.xsl,v 1.1 2002/08/19 13:32:34 mikep%oeone.com Exp $ Diamond Jason 2001 Jason Diamond Date/Time Processing
Introduction This module provides templates for formatting and parsing date/time strings. See http://www.tondering.dk/claus/calendar.html for more information on calendars and the calculations this library performs.
Returns a string with a formatted date/time. The formatted date/time is determined by the format parameter. The default format is %Y-%m-%dT%H:%M:%S%z, the W3C format. year Year month Month (1 - 12; January = 1) day Day of month (1 - 31) hour Hours since midnight (0 - 23) minute Minutes after hour (0 - 59) second Seconds after minute (0 - 59) time-zone Time zone string (e.g., 'Z' or '-08:00') format The format specification. %a Abbreviated weekday name %A Full weekday name %b Abbreviated month name %B Full month name %c Date and time representation appropriate for locale %d Day of month as decimal number (01 - 31) %H Hour in 24-hour format (00 - 23) %I Hour in 12-hour format (01 - 12) %j Day of year as decimal number (001 - 366) %m Month as decimal number (01 - 12) %M Minute as decimal number (00 - 59) %p Current locale's A.M./P.M. indicator for 12-hour clock %S Second as decimal number (00 - 59) %U Week of year as decimal number, with Sunday as first day of week (00 - 53) %w Weekday as decimal number (0 - 6; Sunday is 0) %W Week of year as decimal number, with Monday as first day of week (00 - 53) %x Date representation for current locale %X Time representation for current locale %y Year without century, as decimal number (00 - 99) %Y Year with century, as decimal number %z Time-zone name or abbreviation; no characters if time zone is unknown %% Percent sign Returns a formatted date/time string. [not implemented] 0 0 12 0 0 [not implemented] 0 0 AM PM 0 [not implemented] [not implemented] [not implemented] % Calculates the day of the week. Given any Gregorian date, this calculates the day of the week. year Year month Month (1 - 12; January = 1) day Day of month (1 - 31) Returns the day of the week (0 - 6; Sunday = 0). Gets the day of the week's full name. Converts a numeric day of the week value into a string representing the day's full name. day-of-the-week Day of the week (0 - 6; Sunday = 0) Returns a string. Sunday Monday Tuesday Wednesday Thursday Friday Saturday error: Gets the day of the week's abbreviation. Converts a numeric day of the week value into a string representing the day's abbreviation. day-of-the-week Day of the week (0 - 6; Sunday = 0) Returns a string. Sun Mon Tue Wed Thu Fri Sat error: Gets the month's full name. Converts a numeric month value into a string representing the month's full name. month Month (1 - 12; Januaray = 1) Returns a string. January February March April May June July August September October November December error: Gets the month's abbreviation. Converts a numeric month value into a string representing the month's abbreviation. month Month (1 - 12; Januaray = 1) Returns a string. Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec error: Calculates the Julian Day for a specified date. Given any Gregorian date, this calculates the Julian Day. year Year month Month (1 - 12; January = 1) day Day of month (1 - 31) Returns the Julian Day as a decimal number. Returns a string with a formatted date for a specified Julian Day. Given any Julian Day, this returns a string according to the format specification. julian-day A Julian Day format The format specification. See dt:format-date-time for more details. A string. Calculates the week number for a specified date. Assumes Monday is the first day of the week. year Year month Month (1 - 12; January = 1) day Day of month (1 - 31) Returns the week number as a decimal number.
PK R3- րS!S!'content/calendar/converters/ecsJune.xsl example Calendar

June 2002

Sun Mon Tue Wed Thu Fri Sat
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3



PK 4-Cw*content/calendar/converters/sortEvents.xsl

Event:
Date:
Location:

10 30 0
mailto: http://
PK R3-   'content/calendar/converters/xcs2csv.xsl "UID","DTSTAMP","SEQUENCE","DTSTART","DTEND","SUMMARY","DESCRIPTION","LOCATION","CATEGORIES","CLASS" "","","","","","","","","","" , PK R3-IA'content/calendar/converters/xcs2ics.xsl BEGIN:VCALENDAR PRODID: VERSION: END:VCALENDAR BEGIN:VEVENT END:VEVENT BEGIN:VJOURNAL END:VJOURNAL UID: SUMMARY: DESCRIPTION: CATEGORIES:, PRIORITY: CLASS: DTSTAMP: SEQUENCE: DTSTART;VALUE= : DTEND: LOCATION: PK Tg-`P'content/calendar/converters/xcs2rdf.xsl PK Tg--HQ'content/calendar/converters/xml2xcs.xsl PK 5K/3C C 4content/calendar/datetimepickers/datetimepickers.css/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is OEone Calendar Code, released October 31st, 2001. * * The Initial Developer of the Original Code is OEone Corporation. * Portions created by the Initial Developer are Copyright (C) 2001 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ @import url("chrome://calendar/content/datetimepickers/minimonth.css"); datepicker { -moz-binding: url("chrome://calendar/content/datetimepickers/datetimepickers.xml#datepicker"); } datetimepicker { -moz-binding: url("chrome://calendar/content/datetimepickers/datetimepickers.xml#datetimepicker"); } datetextpicker { -moz-binding: url("chrome://calendar/content/datetimepickers/datetimepickers.xml#datetextpicker"); } timepicker { -moz-binding: url("chrome://calendar/content/datetimepickers/datetimepickers.xml#timepicker"); } timepicker-grids { -moz-binding: url("chrome://calendar/content/datetimepickers/datetimepickers.xml#timepicker-grids"); } timepicker-minute { -moz-binding: url("chrome://calendar/content/datetimepickers/datetimepickers.xml#timepicker-minute"); } timepicker-hour { -moz-binding: url("chrome://calendar/content/datetimepickers/datetimepickers.xml#timepicker-hour"); } PK s2d5.content/calendar/datetimepickers/minimonth.css@import url("chrome://calendar/skin/datetimepickers/minimonth.css"); minimonth { -moz-binding: url("chrome://calendar/content/datetimepickers/minimonth.xml#minimonth"); } .minimonth-navbtn { -moz-binding: url("chrome://calendar/content/datetimepickers/minimonth.xml#minimonth-navbtn"); } .minimonth-day { -moz-binding: url("chrome://calendar/content/datetimepickers/minimonth.xml#minimonth-day"); } PK %7.׍rr.content/calendar/datetimepickers/minimonth.xml null 2; })) { for (var endPrefix = 0; endPrefix < minLength; endPrefix++) { var c = dayList[0][endPrefix]; if (dayList.some(function(dayAbbr) { return dayAbbr[endPrefix] != c; })) { if (endPrefix > 0) { for (i = 0; i < dayList.length; i++) // trim prefix chars. dayList[i] = dayList[i].substring(endPrefix); } break; } } } // 3. trim each day abbreviation to 1 char if unique, else 2 chars. for (i = 0; i < dayList.length; i++) { var foundMatch = 1; for (j = 0; j < dayList.length; j++) { if (i != j) { if (dayList[i].substring(0,1) == dayList[j].substring(0,1)) { foundMatch = 2; break; } } } dayList[i] = dayList[i].substring(0,foundMatch) } } for (var column = 0; column < header.childNodes.length; column++) { header.childNodes[column].setAttribute( "value", dayList[column]); } ]]> allowedAttributes) { switch (aBox.attributes[allowedAttributes].nodeName) { case "selected": case "othermonth": case "today": case "interactive": case "value": case "class": case "flex": allowedAttributes++; break; default: aBox.removeAttribute(aBox.attributes[allowedAttributes].nodeName); break; } } } if (aDate) { var box = this.getBoxForDate(aDate); if (box) { removeForBox(box); } } else { for (var k = 1; k < this.kDaysOfMonthBox.childNodes.length; k++) { for (var i = 0; i < 7; i++) { removeForBox(this.kDaysOfMonthBox.childNodes[k].childNodes[i]); } } } ]]> this._getEndDate(aMainDate))) { aMainDate = new Date(aDate); aMainDate.setDate(1); } // note, that aMainDate and this.mEditorDate refer to the first day // of the corresponding month var sameMonth = this._sameDay(aMainDate, this.mEditorDate); var sameDate = this._sameDay(aDate,this.mValue); if (!sameMonth && !sameDate) { // change month and select day this.mValue = aDate; this.showMonth(aMainDate); } else if (!sameMonth) { // change month only this.showMonth(aMainDate); } else if (!sameDate) { // select day only var day = this.getBoxForDate(aDate); if (this.mSelected) { this.mSelected.removeAttribute("selected"); } this.mSelected = day; day.setAttribute("selected", "true"); this.mValue = aDate; } ]]> 0) ? 1 : -1; } this.advanceMonth(rows); ]]> PK b6ٜ77(content/calendar/preferences/advanced.js/** * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Thunderbird preferences * * The Initial Developer of the Original Code is * Scott MacGregor * Portions created by the Initial Developer are Copyright (C) 2005 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Matthew Willis * Jeff Walden * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ var gAdvancedPane = { _inited: false, init: function advPaneInit() { this._inited = true; this._initMasterPasswordUI(); var advancedPrefs = document.getElementById("advancedPrefs"); var preference = document.getElementById("calendar.preferences.advanced.selectedTabIndex"); if (preference.value === null) { return; } advancedPrefs.selectedIndex = preference.value; this.updateAppUpdateItems(); this.updateAutoItems(); this.updateModeItems(); }, tabSelectionChanged: function advPaneTabSelectionChanged() { if (!this._inited) { return; } var advancedPrefs = document.getElementById("advancedPrefs"); var preference = document.getElementById("calendar.preferences.advanced.selectedTabIndex"); preference.valueFromPreferences = advancedPrefs.selectedIndex; }, // GENERAL TAB showConnections: function advPaneShowConnections() { var url = "chrome://calendar/content/preferences/connection.xul"; document.documentElement.openSubDialog(url, "", "chrome,dialog"); }, showConfigEdit: function advPaneShowConfigEdit() { document.documentElement.openWindow("Preferences:ConfigManager", "chrome://global/content/config.xul", "", null); }, // PASSWORDS TAB /** * Caches the security module service for multiple use. */ __secModDb: null, get _secModDb() { if (!this.__secModDb) { this.__secModDb = Components.classes["@mozilla.org/security/pkcs11moduledb;1"] .getService(Components.interfaces.nsIPKCS11ModuleDB); } return this.__secModDb; }, /** * Initializes Master Password UI: the "Use Master Password" checkbox, * selects the Master Password button to show, and enables/disables it as * necessary. The Master Password is controlled by various bits of NSS * functionality, so the UI for it can't be controlled by the normal * preference bindings. */ _initMasterPasswordUI: function advPaneInitMasterPassword() { var noMP = !this._masterPasswordSet(); var button = document.getElementById("changeMasterPassword"); button.disabled = noMP; var checkbox = document.getElementById("useMasterPassword"); checkbox.checked = !noMP; }, /** * Returns true if the user has a Master Password set and false otherwise. */ _masterPasswordSet: function advPaneMasterPasswordSet() { var slot = this._secModDb.findSlotByName(""); if (slot) { const nsIPKCS11Slot = Components.interfaces.nsIPKCS11Slot; var status = slot.status; // Does the user have a Master Password set? return ((status != nsIPKCS11Slot.SLOT_UNINITIALIZED) && (status != nsIPKCS11Slot.SLOT_READY)); } else { return false; } }, /** * Enables/disables the Master Password button depending on the state of * the "Use Master Password" checkbox, and prompts for Master Password * removal if one is set. This function is called when the "Use Master * Password" checkbox is changed. */ updateMasterPasswordButton: function advPaneUpdateMasterPasswordButton() { var checkbox = document.getElementById("useMasterPassword"); var button = document.getElementById("changeMasterPassword"); button.disabled = !checkbox.checked; // Unchecking the checkbox should try to immediately remove the Master // Password, because it's impossible to non-destructively remove the // Master Password used to encrypt all the passwords without providing // it (by design), and it would be extremely odd to pop up that dialog // when the user closes the prefwindow and saves his settings. if (!checkbox.checked) { this._removeMasterPassword(); } else { this.changeMasterPassword(); } }, /** * Displays the "Remove Master Password" dialog to allow the user to * remove the current Master Password. When the dialog is dismissed, * the Master Password UI is automatically updated. */ _removeMasterPassword: function advRemoveMasterPassword() { if (this._secModDb.isFIPSEnabled) { var bundle = document.getElementById("bundleCalendarPreferences"); var promptSvc = Components.classes["@mozilla.org/embedcomp/prompt-service;1"] .getService(Components.interfaces.nsIPromptService); promptSvc.alert(window, bundle.getString("pw_change_failed_title"), bundle.getString("pw_change2empty_in_fips_mode")); } else { var url = "chrome://mozapps/content/preferences/removemp.xul"; document.documentElement.openSubDialog(url, "", null); } this._initMasterPasswordUI(); }, /** * Displays a dialog in which the Master Password may be changed. */ changeMasterPassword: function advPaneChangeMasterPassword() { var url = "chrome://mozapps/content/preferences/changemp.xul"; document.documentElement.openSubDialog(url, "", null); this._initMasterPasswordUI(); }, /** * Shows the sites where the user has saved passwords and the associated * login information. */ viewPasswords: function advPaneViewPasswords() { var url = "chrome://passwordmgr/content/passwordManager.xul"; document.documentElement.openWindow("Toolkit:PasswordManager", url, "", null); }, // UPDATE TAB /** * Preferences: * * app.update.enabled * - true if updates to the application are enabled, false otherwise * extensions.update.enabled * - true if updates to extensions and themes are enabled, false otherwise * app.update.auto * - true if updates should be automatically downloaded and installed, * possibly with a warning if incompatible extensions are installed (see * app.update.mode); false if the user should be asked what he wants to * do when an update is available * app.update.mode * - an integer: * 0 do not warn if an update will disable extensions or themes * 1 warn if an update will disable extensions or themes * 2 warn if an update will disable extensions or themes *or* if * the update is a major update */ /** * Enables and disables various UI preferences as necessary to reflect * locked, disabled, and checked/unchecked states. * * UI state matrix for update preference conditions * * UI Elements: Preferences * 1 = Sunbird checkbox i = app.update.enabled * 2 = When updates for Sunbird are found label ii = app.update.auto * 3 = Automatic Radiogroup (Ask vs. Auto) iii = app.update.mode * 4 = Warn before disabling add-ons checkbox * * States: * Element Disabled Pref Value Locked * 1 false i t/f f * true i t/f t * false ii t/f t/f * false iii 0/1/2 t/f * 2,3 false i t t/f * true i f t/f * false ii t/f f * true ii t/f t * false iii 0/1/2 t/f * 4 false i t t/f * true i f t/f * false ii t t/f * true ii f t/f * false iii 0/1/2 f * true iii 0/1/2 t * */ updateAppUpdateItems: function advPaneUpdateAppUpdateItems() { var aus = Components.classes["@mozilla.org/updates/update-service;1"] .getService(Components.interfaces.nsIApplicationUpdateService); var enabledPref = document.getElementById("app.update.enabled"); var enableAppUpdate = document.getElementById("enableAppUpdate"); enableAppUpdate.disabled = !aus.canUpdate || enabledPref.locked; }, /** * Enables/disables UI for "when updates are found" based on the values, * and "locked" states of associated preferences. */ updateAutoItems: function advPaneUpdateAutoItems() { var enabledPref = document.getElementById("app.update.enabled"); var autoPref = document.getElementById("app.update.auto"); var updateModeLabel = document.getElementById("updateModeLabel"); var updateMode = document.getElementById("updateMode"); var disable = enabledPref.locked || !enabledPref.value || autoPref.locked; updateMode.disabled = disable; updateModeLabel.disabled = updateMode.disabled; }, /** * Enables/disables the "warn if incompatible add-ons exist" UI based on * the values and "locked" states of various preferences. */ updateModeItems: function advPaneUpdateModeItems() { var enabledPref = document.getElementById("app.update.enabled"); var autoPref = document.getElementById("app.update.auto"); var modePref = document.getElementById("app.update.mode"); var warnIncompatible = document.getElementById("warnIncompatible"); var disable = enabledPref.locked || !enabledPref.value || autoPref.locked || !autoPref.value || modePref.locked; warnIncompatible.disabled = disable; }, /** * The Add-ons checkbox and button are disabled only if the enable * add-on update preference is locked. */ updateAddonUpdateUI: function advPaneUpdateAddonUpdateUI() { var enabledPref = document.getElementById("extensions.update.enabled"); var enableAddonUpdate = document.getElementById("enableAddonUpdate"); enableAddonUpdate.disabled = enabledPref.locked; }, /** * Stores the value of the app.update.mode preference, which is a tristate * integer preference. We store the value here so that we can properly * restore the preference value if the UI reflecting the preference value * is in a state which can represent either of two integer values (as * opposed to only one possible value in the other UI state). */ _modePreference: -1, /** * Reads the app.update.mode preference and converts its value into a * true/false value for use in determining whether the "Warn me if this * will disable any of my add-ons" checkbox is checked. We also save the * value of the preference so that the preference value can be properly * restored if the user's preferences cannot adequately be expressed by a * single checkbox. * * app.update.mode Checkbox State Meaning * 0 Unchecked Do not warn * 1 Checked Warn if there are incompatibilities * 2 Checked Warn if there are incompatibilities, * or the update is major. */ readAddonWarn: function advPaneReadAddonWarn() { var preference = document.getElementById("app.update.mode"); var warnMe = preference.value != 0; this._modePreference = warnMe ? preference.value : 1; return warnMe; }, /** * Converts the state of the "Warn me if this will disable any of my * add-ons" checkbox into the integer preference which represents it, * returning that value. */ writeAddonWarn: function advPaneWriteAddonWarn() { var warnIncompatible = document.getElementById("warnIncompatible"); return warnIncompatible.checked ? this._modePreference : 0; }, /** * Displays the history of installed updates. */ showUpdates: function advPaneShowUpdates() { var prompter = Components.classes["@mozilla.org/updates/update-prompt;1"] .createInstance(Components.interfaces.nsIUpdatePrompt); prompter.showUpdateHistory(window); } }; PK P6)))content/calendar/preferences/advanced.xul %brandDTD; %advancedDTD; ]>