From 4235abc956395fb2531719f0e6a564c7ce3ec38f Mon Sep 17 00:00:00 2001 From: Francis Lachapelle Date: Tue, 13 Nov 2007 22:51:32 +0000 Subject: [PATCH] Monotone-Parent: 3239b46c1626108a2b1a3d6cab30ae4c9bd6a731 Monotone-Revision: a3ce416b24dfccdfe9594ae00a7b6d94421077a9 Monotone-Author: flachapelle@inverse.ca Monotone-Date: 2007-11-13T22:51:32 Monotone-Branch: ca.inverse.sogo --- NEWS | 2 + UI/Contacts/UIxContactFoldersView.m | 27 +++-- .../SchedulerUI/UIxAttendeesEditor.wox | 3 + UI/WebServerResources/SchedulerUI.js | 9 +- UI/WebServerResources/UIxAttendeesEditor.css | 4 + UI/WebServerResources/UIxAttendeesEditor.js | 113 ++++++++++++++---- UI/WebServerResources/generic.js | 106 ++++++---------- UI/WebServerResources/iefixes.css | 4 + 8 files changed, 166 insertions(+), 102 deletions(-) diff --git a/NEWS b/NEWS index 48bf59edf..768a45e08 100644 --- a/NEWS +++ b/NEWS @@ -17,6 +17,8 @@ - support for resizable columns in tables; - improved support for multiple selection in tables and lists; - improved IE7 and Safari support: attendees selector, email file attachments; +- updated PrototypeJS to version 1.6.0; +- improved address completion in attendees selector; - changed look of message composition window to Thunderbird 2.0; - countless bugfixes; diff --git a/UI/Contacts/UIxContactFoldersView.m b/UI/Contacts/UIxContactFoldersView.m index 07d47e447..a4f7b1a44 100644 --- a/UI/Contacts/UIxContactFoldersView.m +++ b/UI/Contacts/UIxContactFoldersView.m @@ -35,6 +35,7 @@ #import #import #import +#import #import #import #import @@ -121,8 +122,10 @@ { WOResponse *response; NSEnumerator *contacts; - NSString *responseString, *email; + NSString *email; NSDictionary *contact; + NSMutableArray *formattedContacts; + NSMutableDictionary *formattedContact; response = [context response]; @@ -131,21 +134,25 @@ [response setStatus: 200]; contacts = [results objectEnumerator]; contact = [contacts nextObject]; - if (contact) + formattedContacts = [[NSMutableArray alloc] initWithCapacity: [results count]]; + while (contact) { email = [contact objectForKey: @"c_email"]; if ([email length]) { - responseString = [NSString stringWithFormat: @"%@:%@:%@", - [contact objectForKey: @"c_uid"], - [contact objectForKey: @"cn"], - email]; -// [response setHeader: @"text/plain; charset=iso-8859-1" -// forKey: @"Content-Type"]; - [response appendContentString: responseString]; + formattedContact = [NSMutableDictionary dictionary]; + [formattedContact setObject: [contact objectForKey: @"c_uid"] + forKey: @"uid"]; + [formattedContact setObject: [contact objectForKey: @"cn"] + forKey: @"name"]; + [formattedContact setObject: email + forKey: @"email"]; + [formattedContacts addObject: formattedContact]; } -// contact = [contacts nextObject]; + contact = [contacts nextObject]; } + [response appendContentString: [formattedContacts jsonRepresentation]]; + [formattedContacts release]; } else [response setStatus: 404]; diff --git a/UI/Templates/SchedulerUI/UIxAttendeesEditor.wox b/UI/Templates/SchedulerUI/UIxAttendeesEditor.wox index 80ecdd083..8895bcafc 100644 --- a/UI/Templates/SchedulerUI/UIxAttendeesEditor.wox +++ b/UI/Templates/SchedulerUI/UIxAttendeesEditor.wox @@ -11,6 +11,9 @@ const:toolbar="none" const:popup="YES" const:jsFiles="skycalendar.js"> +
diff --git a/UI/WebServerResources/SchedulerUI.js b/UI/WebServerResources/SchedulerUI.js index 05ded9b27..d68fa0c79 100644 --- a/UI/WebServerResources/SchedulerUI.js +++ b/UI/WebServerResources/SchedulerUI.js @@ -32,10 +32,13 @@ function newEvent(sender, type) { if (!hour) hour = sender.getAttribute("hour"); var folder = getSelectedFolder(); - var roles = folder.getAttribute("roles").split(","); var folderID = folder.getAttribute("id"); - if ($(roles).indexOf("PublicModifier") < 0) - folderID = "/personal"; + var roles = folder.getAttribute("roles"); + if (roles) { + roles = roles.split(",") + if ($(roles).indexOf("PublicModifier") < 0) + folderID = "/personal"; + } var urlstr = ApplicationBaseURL + folderID + "/new" + type; var params = new Array(); if (day) diff --git a/UI/WebServerResources/UIxAttendeesEditor.css b/UI/WebServerResources/UIxAttendeesEditor.css index 67156317a..48873f787 100644 --- a/UI/WebServerResources/UIxAttendeesEditor.css +++ b/UI/WebServerResources/UIxAttendeesEditor.css @@ -1,3 +1,7 @@ +DIV#attendeesMenu +{ overflow: auto; + overflow-x: hidden; } + DIV#attendeesView { position: absolute; left: 1em; diff --git a/UI/WebServerResources/UIxAttendeesEditor.js b/UI/WebServerResources/UIxAttendeesEditor.js index 9cf960237..dff86b27b 100644 --- a/UI/WebServerResources/UIxAttendeesEditor.js +++ b/UI/WebServerResources/UIxAttendeesEditor.js @@ -42,6 +42,10 @@ function onContactKeydown(event) { running = true; requestField = this; requestField.setAttribute("modified", "1"); + if (searchField) { + searchField.confirmedValue = null; + searchField.uid = null; + } setTimeout("triggerRequest()", delay); } else if (this.confirmedValue) { @@ -67,35 +71,95 @@ function triggerRequest() { function updateResults(http) { if (http.readyState == 4) { + var menu = $('attendeesMenu'); + var list = menu.down("ul"); + + searchField = http.callbackData; + searchField.hasfreebusy = false; + if (http.status == 200) { - var searchField = http.callbackData; var start = searchField.value.length; - var text = http.responseText.split(":"); - if (text[0].length > 0) - searchField.uid = text[0]; - else - searchField.uid = null; - searchField.hasfreebusy = false; - var completeEmail = text[1] + " <" + text[2] + ">"; - if (text[1].substring(0, searchField.value.length).toUpperCase() - == searchField.value.toUpperCase()) - searchField.value = completeEmail; + var data = http.responseText.evalJSON(true); + if (data.length > 1) { + $(list.childNodesWithTag("li")).each(function(item) { + item.remove(); + }); + + // Populate popup menu + for (var i = 0; i < data.length; i++) { + var contact = data[i]; + var completeEmail = contact["name"] + " <" + contact["email"] + ">"; + var node = document.createElement("li"); + list.appendChild(node); + node.uid = contact["uid"]; + node.appendChild(document.createTextNode(completeEmail)); + $(node).observe("mousedown", onAttendeeResultClick); + } + + // Show popup menu + var offset; + if (isSafari()) + offset = Position.positionedOffset(searchField); + else + offset = Position.cumulativeOffset(searchField); + var top = offset[1] + node.offsetHeight + 3; + var height = 'auto'; + if (data.length > 5) { + height = 5 * node.getHeight() + 'px'; + } + menu.setStyle({ top: top + "px", + left: offset[0] + "px", + height: height, + visibility: "visible" }); + menu.scrollTop = 0; + + document.currentPopupMenu = menu; + $(document.body).observe("click", onBodyClickMenuHandler); + } else { - searchField.value += ' >> ' + completeEmail; + if (document.currentPopupMenu) + hideMenu(document.currentPopupMenu); + + if (data.length == 1) { + var contact = data[0]; + if (contact["uid"].length > 0) + searchField.uid = contact["uid"]; + else + searchField.uid = null; + var completeEmail = contact["name"] + " <" + contact["email"] + ">"; + if (contact["name"].substring(0, searchField.value.length).toUpperCase() + == searchField.value.toUpperCase()) + searchField.value = completeEmail; + else { + searchField.value += ' >> ' + completeEmail; + } + searchField.confirmedValue = completeEmail; + if (searchField.focussed) { + var end = searchField.value.length; + $(searchField).selectText(start, end); + } + else + searchField.value = contact["name"]; + } } - searchField.confirmedValue = completeEmail; - if (searchField.focussed) { - var end = searchField.value.length; - $(searchField).selectText(start, end); - } - else - searchField.value = text[1]; } + else + if (document.currentPopupMenu) + hideMenu(document.currentPopupMenu); running = false; document.contactLookupAjaxRequest = null; } } +function onAttendeeResultClick(event) { + if (searchField) { + searchField.uid = this.uid; + searchField.value = this.firstChild.nodeValue.trim(); + searchField.confirmedValue = searchField.value; + searchField.blur(); // triggers checkAttendee function call + } +} + function UIDLookupCallback(http) { if (http.readyState == 4) { if (http.status == 200) { @@ -198,14 +262,21 @@ function newAttendee(event) { var input = $(newRow.cells[0]).childNodesWithTag("input")[0]; input.setAttribute("autocomplete", "off"); - Event.observe(input, "blur", checkAttendee.bindAsEventListener(input)); Event.observe(input, "keydown", onContactKeydown.bindAsEventListener(input)); + Event.observe(input, "blur", checkAttendee.bindAsEventListener(input)); input.focussed = true; input.activate(); } function checkAttendee() { + if (document.currentPopupMenu && !this.confirmedValue) { + // Hack for IE7; blur event is triggered on input field when + // selecting a menu item + var visible = $(document.currentPopupMenu).getStyle('visibility') != 'hidden'; + if (visible) + return; + } this.focussed = false; var th = this.parentNode.parentNode; var tbody = th.parentNode; @@ -541,4 +612,4 @@ function onFreeBusyLoadHandler() { initializeFreebusys(); } -addEvent(window, 'load', onFreeBusyLoadHandler); +document.observe("dom:loaded", onFreeBusyLoadHandler); diff --git a/UI/WebServerResources/generic.js b/UI/WebServerResources/generic.js index ea96808e2..96c4b0036 100644 --- a/UI/WebServerResources/generic.js +++ b/UI/WebServerResources/generic.js @@ -576,7 +576,7 @@ function popupMenu(event, menuId, target) { document.currentPopupMenu = popup; - Event.observe(document.body, "click", onBodyClickMenuHandler); + $(document.body).observe("click", onBodyClickMenuHandler); preventDefault(event); } @@ -600,7 +600,7 @@ function getParentMenu(node) { function onBodyClickMenuHandler(event) { hideMenu(document.currentPopupMenu); - Event.stopObserving(document.body, "click", onBodyClickMenuHandler); + document.body.stopObserving("click", onBodyClickMenuHandler); if (event) preventDefault(event); @@ -615,15 +615,12 @@ function hideMenu(menuNode) { } menuNode.setStyle({ visibility: "hidden" }); - // menuNode.hide(); if (menuNode.parentMenuItem) { - Event.stopObserving(menuNode.parentMenuItem, "mouseover", - onMouseEnteredSubmenu); - Event.stopObserving(menuNode, "mouseover", onMouseEnteredSubmenu); - Event.stopObserving(menuNode.parentMenuItem, "mouseout", onMouseLeftSubmenu); - Event.stopObserving(menuNode, "mouseout", onMouseLeftSubmenu); - Event.stopObserving(menuNode.parentMenu, "mouseover", - onMouseEnteredParentMenu); + menuNode.parentMenuItem.stopObserving("mouseover",onMouseEnteredSubmenu); + menuNode.stopObserving("mouseover", onMouseEnteredSubmenu); + menuNode.parentMenuItem.stopObserving("mouseout", onMouseLeftSubmenu); + menuNode.stopObserving("mouseout", onMouseLeftSubmenu); + menuNode.parentMenu.stopObserving("mouseover", onMouseEnteredParentMenu); $(menuNode.parentMenuItem).removeClassName("submenu-selected"); menuNode.parentMenuItem.mouseInside = false; menuNode.parentMenuItem = null; @@ -632,18 +629,7 @@ function hideMenu(menuNode) { menuNode.parentMenu = null; } - if (document.createEvent) { // Safari & Mozilla - var onhideEvent; - if (isSafari()) - onhideEvent = document.createEvent("UIEvents"); - else - onhideEvent = document.createEvent("Events"); - onhideEvent.initEvent("mousedown", false, true); - menuNode.dispatchEvent(onhideEvent); - } - else if (document.createEventObject) { // IE - menuNode.fireEvent("onmousedown"); - } + $(menuNode).fire("mousedown"); } function onMenuEntryClick(event) { @@ -673,8 +659,8 @@ function initLogConsole() { var logConsole = $("logConsole"); if (logConsole) { logConsole.highlighted = false; - Event.observe(logConsole, "dblclick", onLogDblClick, false); - logConsole.innerHTML = ""; + logConsole.observe("dblclick", onLogDblClick, false); + logConsole.update(); Event.observe(window, "keydown", onBodyKeyDown); } } @@ -776,15 +762,11 @@ function popupSubmenu(event) { menuLeft = parentNode.offsetLeft - submenuNode.offsetWidth + 3; this.mouseInside = true; - Event.observe(this, "mouseover", - onMouseEnteredSubmenu.bindAsEventListener(this)); - Event.observe(submenuNode, "mouseover", - onMouseEnteredSubmenu.bindAsEventListener(submenuNode)); - Event.observe(this, "mouseout", onMouseLeftSubmenu.bindAsEventListener(this)); - Event.observe(submenuNode, "mouseout", - onMouseLeftSubmenu.bindAsEventListener(submenuNode)); - Event.observe(parentNode, "mouseover", - onMouseEnteredParentMenu.bindAsEventListener(parentNode)); + this.observe("mouseover", onMouseEnteredSubmenu); + submenuNode.observe("mouseover", onMouseEnteredSubmenu); + this.observe("mouseout", onMouseLeftSubmenu); + submenuNode.observe("mouseout", onMouseLeftSubmenu); + parentNode.observe("mouseover", onMouseEnteredParentMenu); $(this).addClassName("submenu-selected"); submenuNode.setStyle({ top: menuTop + "px", left: menuLeft + "px", @@ -829,7 +811,7 @@ function popupSearchMenu(event) { visibility: "visible" }); document.currentPopupMenu = popup; - Event.observe(document.body, "click", onBodyClickMenuHandler); + $(document.body).observe("click", onBodyClickMenuHandler); } } @@ -865,17 +847,12 @@ function configureSearchField() { if (!searchValue) return; - Event.observe(searchValue, "mousedown", - onSearchMouseDown.bindAsEventListener(searchValue)); - Event.observe(searchValue, "click", - popupSearchMenu.bindAsEventListener(searchValue)); - Event.observe(searchValue, "blur", - onSearchBlur.bindAsEventListener(searchValue)); - Event.observe(searchValue, "focus", - onSearchFocus.bindAsEventListener(searchValue)); - Event.observe(searchValue, "keydown", - onSearchKeyDown.bindAsEventListener(searchValue)); - + searchValue.observe("click", popupSearchMenu); + searchValue.observe("blur", onSearchBlur); + searchValue.observe("focus", onSearchFocus); + searchValue.observe("keydown", onSearchKeyDown); + searchValue.observe("mousedown", onSearchMouseDown); + if (!searchOptions) return; // Set the checkmark to the first option @@ -975,7 +952,7 @@ function popupToolbarMenu(node, menuId) { visibility: "visible" }); document.currentPopupMenu = popup; - Event.observe(document.body, "click", onBodyClickMenuHandler); + $(document.body).observe("click", onBodyClickMenuHandler); } /* contact selector */ @@ -1099,10 +1076,8 @@ function initTabs() { if (currentNode.tagName == 'LI') { if (!firstTab) firstTab = i; - Event.observe(currentNode, "mousedown", - onTabMouseDown.bindAsEventListener(currentNode)); - Event.observe(currentNode, "click", - onTabClick.bindAsEventListener(currentNode)); + $(currentNode).observe("mousedown", onTabMouseDown); + $(currentNode).observe("click", onTabClick); //$(currentNode.getAttribute("target")).hide(); } } @@ -1132,9 +1107,7 @@ function initMenu(menuDIV, callbacks) { var lis = $(menuDIV.childNodesWithTag("ul")[0]).childNodesWithTag("li"); for (var j = 0; j < lis.length; j++) { var node = $(lis[j]); - Event.observe(node, "mousedown", - listRowMouseDownHandler.bindAsEventListener(node), - false); + node.observe("mousedown", listRowMouseDownHandler, false); var callback = callbacks[j]; if (callback) { if (typeof(callback) == "string") { @@ -1143,15 +1116,12 @@ function initMenu(menuDIV, callbacks) { else { node.submenu = callback; node.addClassName("submenu"); - Event.observe(node, "mouseover", - popupSubmenu.bindAsEventListener(node)); + node.observe("mouseover", popupSubmenu); } } else { - Event.observe(node, "mouseup", - onBodyClickMenuHandler); - Event.observe(node, "click", - $(callback).bindAsEventListener(node)); + node.observe("mouseup", onBodyClickMenuHandler); + node.observe("click", callback); } } else @@ -1349,7 +1319,7 @@ function onLoadHandler(event) { var progressImage = $("progressIndicator"); if (progressImage) progressImage.parentNode.removeChild(progressImage); - Event.observe(document.body, "contextmenu", onBodyClickContextMenu); + $(document.body).observe("contextmenu", onBodyClickContextMenu); } function onBodyClickContextMenu(event) { @@ -1360,8 +1330,8 @@ function configureSortableTableHeaders(table) { var headers = $(table).getElementsByClassName("sortableTableHeader"); for (var i = 0; i < headers.length; i++) { var header = headers[i]; - Event.observe(header, "click", onHeaderClick.bindAsEventListener(header)) - } + $(header).observe("click", onHeaderClick); + } } function onLinkBannerClick() { @@ -1384,13 +1354,13 @@ function configureLinkBanner() { if (linkBanner) { var anchors = linkBanner.childNodesWithTag("a"); for (var i = 1; i < 3; i++) { - Event.observe(anchors[i], "mousedown", listRowMouseDownHandler); - Event.observe(anchors[i], "click", onLinkBannerClick); + $(anchors[i]).observe("mousedown", listRowMouseDownHandler); + $(anchors[i]).observe("click", onLinkBannerClick); } - Event.observe(anchors[4], "mousedown", listRowMouseDownHandler); - Event.observe(anchors[4], "click", onPreferencesClick); + $(anchors[4]).observe("mousedown", listRowMouseDownHandler); + $(anchors[4]).observe("click", onPreferencesClick); if (anchors.length > 5) - Event.observe(anchors[5], "click", toggleLogConsole); + $(anchors[5]).observe("click", toggleLogConsole); } } @@ -1432,7 +1402,7 @@ function onFinalLoadHandler(event) { safetyNet.parentNode.removeChild(safetyNet); } -addEvent(window, 'load', onLoadHandler); +document.observe("dom:loaded", onLoadHandler); function parent$(element) { return this.opener.document.getElementById(element); diff --git a/UI/WebServerResources/iefixes.css b/UI/WebServerResources/iefixes.css index 412621b26..3ee824937 100644 --- a/UI/WebServerResources/iefixes.css +++ b/UI/WebServerResources/iefixes.css @@ -50,6 +50,10 @@ SPAN.content > INPUT.textField /* UIxAttendeesEditor */ +DIV#attendeesMenu +{ overflow: scroll; + overflow-x: hidden; } + DIV#freeBusyView { border-bottom: 1px solid #fff; border-right: 1px solid #fff;