/* ***** 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 * * 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"; var gCalendarEventTreeClicked = false; //set this to true when the calendar event tree is clicked //to allow for multiple selection var gEventArray = new Array(); 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.treeBoxObject.selection.selectEventsSuppressed = false; SearchTree.addEventListener( "select", unifinderOnSelect, true ); } var doingSelection = false; function selectSelectedEventsInTree( EventsToSelect ) { if( doingSelection === true ) return; doingSelection = true; if( EventsToSelect === false ) EventsToSelect = gCalendarWindow.EventSelection.selectedEvents; dump( "\nCALENDAR unifinder.js->on selection changed" ); 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.treeBoxObject.selection.selectEventsSuppressed = true; if( EventsToSelect.length == 1 ) { var RowToScrollTo = SearchTree.eventView.getRowOfCalendarEvent( EventsToSelect[0] ); if( RowToScrollTo != "null" ) { SearchTree.treeBoxObject.selection.clearSelection( ); SearchTree.treeBoxObject.ensureRowIsVisible( RowToScrollTo ); SearchTree.treeBoxObject.selection.timedSelect( RowToScrollTo, 1 ); } else { SearchTree.treeBoxObject.selection.clearSelection( ); } } else if( EventsToSelect.length > 1 ) { /* selecting all events is taken care of in the selectAllEvents in calendar.js ** Other than that, there's no other way to get in here. */ if( gSelectAll === true ) { SearchTree.treeBoxObject.selection.selectAll( ); gSelectAll = false; } } else { dump( "\n--->>>>unifinder.js selection callback :: Clear selection" ); SearchTree.treeBoxObject.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 unifinderEventDataSourceObserver = { onLoad : function() { if( !gICalLib.batchMode ) { refreshEventTree( getAndSetEventTable() ); } }, onStartBatch : function() { }, onEndBatch : function() { refreshEventTree( getAndSetEventTable() ); }, onAddItem : function( calendarEvent ) { if( !gICalLib.batchMode ) { if( calendarEvent ) { refreshEventTree( getAndSetEventTable() ); } } }, onModifyItem : function( calendarEvent, originalEvent ) { if( !gICalLib.batchMode ) { refreshEventTree( getAndSetEventTable() ); } }, onDeleteItem : function( calendarEvent ) { if( !gICalLib.batchMode ) { refreshEventTree( getAndSetEventTable() ); } }, onAlarm : function( calendarEvent ) { }, onError : function() { } }; /** * Called when the calendar is loaded */ function prepareCalendarUnifinder( ) { // tell the unifinder to get ready var unifinderEventSelectionObserver = { onSelectionChanged : function( EventSelectionArray ) { selectSelectedEventsInTree( EventSelectionArray ); } } gCalendarWindow.EventSelection.addObserver( unifinderEventSelectionObserver ); // set up our calendar event observer gICalLib.addObserver( unifinderEventDataSourceObserver ); } /** * Called when the calendar is unloaded */ function finishCalendarUnifinder( ) { gICalLib.removeObserver( unifinderEventDataSourceObserver ); } /** * Helper function to display event dates in the unifinder */ function formatUnifinderEventDate( date ) { return( gCalendarWindow.dateFormater.getFormatedDate( date ) ); } /** * Helper function to display event times in the unifinder */ function formatUnifinderEventTime( time ) { return( gCalendarWindow.dateFormater.getFormatedTime( time ) ); } /** * 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 ) { // go to day view, of the day of the event, select the event editEvent( calendarEvent ); } } function getCalendarEventFromEvent( event ) { var tree = document.getElementById( UnifinderTreeName ); var row = new Object(); tree.treeBoxObject.getCellAt( event.clientX, event.clientY, row, {}, {} ); if( row.value != -1 && row.value < tree.view.rowCount ) { var event = tree.eventView.getCalendarEventAtRow( row.value ); return event; } return( false ); } /** * This is attached to the onclik attribute of the events shown in the unifinder */ function unifinderOnSelect( event ) { dump( "\n\nin unifinder onselect" ); 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 EventB.title) ? 1 : -1) * modifier ); case "unifinder-search-results-tree-col-startdate": return( ((EventA.start.getTime() > EventB.start.getTime()) ? 1 : -1) * modifier ); case "unifinder-search-results-tree-col-enddate": return( ((EventA.end.getTime() > EventB.end.getTime()) ? 1 : -1) * modifier ); case "unifinder-search-results-tree-col-categories": return( ((EventA.categories > EventB.categories) ? 1 : -1) * modifier ); case "unifinder-search-results-tree-col-location": return( ((EventA.location > EventB.location) ? 1 : -1) * modifier ); case "unifinder-search-results-tree-col-status": return( ((EventA.status > EventB.status) ? 1 : -1) * modifier ); default: return true; } } function calendarEventView( eventArray ) { this.eventArray = eventArray; } calendarEventView.prototype.getCalendarEventAtRow = function( i ) { return( this.eventArray[ i ] ); } calendarEventView.prototype.getRowOfCalendarEvent = function( Event ) { for( var i = 0; i < this.eventArray.length; i++ ) { if( this.eventArray[i].id == Event.id ) return( i ); } return( "null" ); } function refreshEventTree( eventArray ) { gEventArray = eventArray; treeView.rowCount = gEventArray.length; 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"); gEventArray.sort(sortEvents); break; } } document.getElementById( UnifinderTreeName ).view = treeView; document.getElementById( UnifinderTreeName ).eventView = new calendarEventView( eventArray ); //select selected events in the tree. selectSelectedEventsInTree( false ); } function focusFirstItemIfNoSelection() { if( gCalendarWindow.EventSelection.selectedEvents.length == 0 ) { //select the first event in the list. var ListBox = document.getElementById( UnifinderTreeName ); if( ListBox.childNodes.length > 0 ) { var SelectedEvent = ListBox.childNodes[0].event; var ArrayOfEvents = new Array(); ArrayOfEvents[ ArrayOfEvents.length ] = SelectedEvent; gCalendarWindow.EventSelection.setArrayToSelection( ArrayOfEvents ); /*start date is either the next or last occurence, or the start date of the event */ var eventStartDate = getNextOrPreviousRecurrence( SelectedEvent ); /* you need this in case the current day is not visible. */ gCalendarWindow.currentView.goToDay( eventStartDate, true); } } } function getNextOrPreviousRecurrence( calendarEvent ) { var isValid; if( calendarEvent.recur ) { var now = new Date(); var result = new Object(); isValid = calendarEvent.getNextRecurrence( now.getTime(), result ); if( isValid ) { return( new Date( result.value ) ); } else { isValid = calendarEvent.getPreviousOccurrence( now.getTime(), result ); return( new Date( result.value ) ); } } if( !isValid || !calendarEvent.recur ) { return( new Date( calendarEvent.start.getTime() ) ); } return( false ); } function changeToolTipTextForEvent( event ) { var thisEvent = getCalendarEventFromEvent( event ); var Html = document.getElementById( "eventTreeListTooltip" ); while( Html.hasChildNodes() ) { Html.removeChild( Html.firstChild ); } if( !thisEvent ) { showTooltip = false; return; } showTooltip = true; var HolderBox = getPreviewText( thisEvent ); Html.appendChild( HolderBox ); } function getPreviewText( calendarEvent ) { var HolderBox = document.createElement( "vbox" ); var textString ; if (calendarEvent.title) { var TitleHtml = document.createElement( "description" ); textString = gCalendarBundle.getFormattedString("tooltipTitleElement", [calendarEvent.title]); var TitleText = document.createTextNode( textString ); TitleHtml.appendChild( TitleText ); HolderBox.appendChild( TitleHtml ); } var startDate = new Date( calendarEvent.start.getTime() ); var endDate = new Date( calendarEvent.end.getTime() ); var diff = DateUtils.getDifferenceInDays(startDate, endDate) ; var DateHtml = document.createElement( "description" ); if (calendarEvent.allDay) { if ( diff > 1 ) { textString = gCalendarBundle.getFormattedString("tooltipEventStart", [gCalendarWindow.dateFormater.getFormatedDate( startDate ), ""]); var DateText = document.createTextNode( textString ); DateHtml.appendChild( DateText ); HolderBox.appendChild( DateHtml ); DateHtml = document.createElement( "description" ); textString = gCalendarBundle.getFormattedString("tooltipEventEnd", [gCalendarWindow.dateFormater.getFormatedDate( endDate ), ""]); } else { textString = gCalendarBundle.getFormattedString("tooltipAlldayEventDate", [gCalendarWindow.dateFormater.getFormatedDate( startDate ), ""]); } } else { textString = gCalendarBundle.getFormattedString("tooltipEventStart", [gCalendarWindow.dateFormater.getFormatedDate( startDate ), gCalendarWindow.dateFormater.getFormatedTime( startDate )]); var DateText = document.createTextNode( textString ); DateHtml.appendChild( DateText ); HolderBox.appendChild( DateHtml ); DateHtml = document.createElement( "description" ); textString = gCalendarBundle.getFormattedString("tooltipEventEnd", [gCalendarWindow.dateFormater.getFormatedDate( endDate ), gCalendarWindow.dateFormater.getFormatedTime( endDate )]); } DateText = document.createTextNode( textString ); DateHtml.appendChild( DateText ); HolderBox.appendChild( DateHtml ); if (calendarEvent.location) { var LocationHtml = document.createElement( "description" ); textString = gCalendarBundle.getFormattedString("tooltipEventLocation", [calendarEvent.location]); var LocationText = document.createTextNode( textString ); LocationHtml.appendChild( LocationText ); HolderBox.appendChild( LocationHtml ); } if (calendarEvent.description) { textString = gCalendarBundle.getFormattedString("tooltipEventDescription", [calendarEvent.description]); var lines = textString.split("\n"); var nbmaxlines = 5 ; var nblines = lines.length ; if( nblines > nbmaxlines ) { var nblines = nbmaxlines ; lines[ nblines - 1 ] = "..." ; } for (var i = 0; i < nblines; i++) { var DescriptionHtml = document.createElement( "description" ); var DescriptionText = document.createTextNode(lines[i]); DescriptionHtml.appendChild(DescriptionText); HolderBox.appendChild(DescriptionHtml); } } return ( HolderBox ); }