Monotone-Parent: 10716bba581bb0dd4ad881e814040b2adb37ba10

Monotone-Revision: 305966069ea6e632bec9f09e6fd85e54295efb03

Monotone-Author: flachapelle@inverse.ca
Monotone-Date: 2008-07-04T09:43:28
Monotone-Branch: ca.inverse.sogo
maint-2.0.2
Francis Lachapelle 2008-07-04 09:43:28 +00:00
parent 443265db50
commit 0797fb9a62
9 changed files with 159 additions and 67 deletions

View File

@ -1,3 +1,9 @@
2008-07-07 Francis Lachapelle <flachapelle@inverse.ca>
* UI/Contacts/UIxContactFoldersView.m ([WOActionResults
allContactSearchAction]): new method to search contacts among
all address books.
2008-07-04 Wolfgang Sourdeau <wsourdeau@inverse.ca> 2008-07-04 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* SoObjects/SOGo/SOGoObject.m ([SOGoObject * SoObjects/SOGo/SOGoObject.m ([SOGoObject

View File

@ -24,6 +24,7 @@
#define UIXCONTACTFOLDERSVIEW_H #define UIXCONTACTFOLDERSVIEW_H
#import <SOGoUI/UIxComponent.h> #import <SOGoUI/UIxComponent.h>
#import <Foundation/NSSortDescriptor.h>
@interface UIxContactFoldersView : UIxComponent @interface UIxContactFoldersView : UIxComponent
{ {

View File

@ -179,6 +179,52 @@
return response; return response;
} }
- (id <WOActionResults>) allContactSearchAction
{
id <WOActionResults> result;
id <SOGoContactFolder> folder;
NSString *searchText;
NSArray *folders, *contacts, *descriptors, *sortedContacts;
NSMutableArray *allContacts;
unsigned int i;
NSSortDescriptor *displayNameDescriptor;
searchText = [self queryParameterForKey: @"search"];
if ([searchText length] > 0)
{
folders = [[self clientObject] subFolders];
allContacts = [NSMutableArray new];
for (i = 0; i < [folders count]; i++) {
folder = [folders objectAtIndex: i];
//NSLog(@"Address book: %@ (%@)", [folder displayName], [folder class]);
contacts = [folder lookupContactsWithFilter: searchText
sortBy: @"displayName"
ordering: NSOrderedAscending];
if ([contacts count] > 0) {
[allContacts addObjectsFromArray: contacts];
}
}
result = [context response];
if ([allContacts count] > 0) {
// Sort the contacts by display name
displayNameDescriptor = [[[NSSortDescriptor alloc] initWithKey: @"displayName"
ascending:YES] autorelease];
descriptors = [NSArray arrayWithObjects: displayNameDescriptor, nil];
sortedContacts = [allContacts sortedArrayUsingDescriptors:descriptors];
[(WOResponse*)result appendContentString: [sortedContacts jsonRepresentation]];
}
else
[(WOResponse*)result setStatus: 404];
}
else
result = [NSException exceptionWithHTTPStatus: 400
reason: @"missing 'search' parameter"];
return result;
}
- (id <WOActionResults>) contactSearchAction - (id <WOActionResults>) contactSearchAction
{ {
NSString *contact; NSString *contact;

View File

@ -22,6 +22,11 @@
pageName = "UIxContactFoldersView"; pageName = "UIxContactFoldersView";
actionName = "contactSearch"; actionName = "contactSearch";
}; };
allContactSearch = {
protectedBy = "<public>";
pageName = "UIxContactFoldersView";
actionName = "allContactSearch";
};
updateAdditionalAddressBooks = { updateAdditionalAddressBooks = {
protectedBy = "View"; protectedBy = "View";
pageName = "UIxContactFoldersView"; pageName = "UIxContactFoldersView";

View File

@ -14,7 +14,7 @@
<script type="text/javascript"> <script type="text/javascript">
var mailIsReply = <var:string value="isMailReply"/>; var mailIsReply = <var:string value="isMailReply"/>;
</script> </script>
<div class="menu" id="contactsMenu"> <div class="popupMenu" id="contactsMenu">
<ul></ul> <ul></ul>
</div> </div>
<div class="menu" id="attachmentsMenu"> <div class="menu" id="attachmentsMenu">

View File

@ -11,7 +11,7 @@
const:toolbar="none" const:toolbar="none"
const:popup="YES" const:popup="YES"
const:jsFiles="skycalendar.js"> const:jsFiles="skycalendar.js">
<div class="menu" id="attendeesMenu"> <div class="popupMenu" id="attendeesMenu">
<ul></ul> <ul></ul>
</div> </div>
<div id="attendeesView"> <div id="attendeesView">

View File

@ -17,6 +17,8 @@ var attendeesEditor = {
states: null states: null
}; };
/* address completion */
function onContactKeydown(event) { function onContactKeydown(event) {
if (event.ctrlKey || event.metaKey) { if (event.ctrlKey || event.metaKey) {
this.focussed = true; this.focussed = true;
@ -55,50 +57,58 @@ function onContactKeydown(event) {
hideMenu(document.currentPopupMenu); hideMenu(document.currentPopupMenu);
} }
} }
else if (event.keyCode == 38) { // Up arrow
if (attendeesEditor.selectedIndex > 0) {
var attendees = $('attendeesMenu').select("li");
attendees[attendeesEditor.selectedIndex--].removeClassName("selected");
this.value = attendees[attendeesEditor.selectedIndex].firstChild.nodeValue.trim();
attendees[attendeesEditor.selectedIndex].addClassName("selected");
}
}
else if (event.keyCode == 40) { // Down arrow
var attendees = $('attendeesMenu').select("li");
if (attendees.size() - 1 > attendeesEditor.selectedIndex) {
if (attendeesEditor.selectedIndex >= 0)
attendees[attendeesEditor.selectedIndex].removeClassName("selected");
attendeesEditor.selectedIndex++;
this.value = attendees[attendeesEditor.selectedIndex].firstChild.nodeValue.trim();
attendees[attendeesEditor.selectedIndex].addClassName("selected");
}
}
else if (event.keyCode == 13) { else if (event.keyCode == 13) {
preventDefault(event); preventDefault(event);
if (this.confirmedValue) if (this.confirmedValue)
this.value = this.confirmedValue; this.value = this.confirmedValue;
if (this.uid)
this.blur(); // triggers checkAttendee function call
$(this).selectText(0, this.value.length); $(this).selectText(0, this.value.length);
if (document.currentPopupMenu) if (document.currentPopupMenu)
hideMenu(document.currentPopupMenu); hideMenu(document.currentPopupMenu);
attendeesEditor.selectedIndex = -1; attendeesEditor.selectedIndex = -1;
} }
else if ($('attendeesMenu').getStyle('visibility') == 'visible') {
attendeesEditor.currentField = this;
if (event.keyCode == 38) { // Up arrow
if (attendeesEditor.selectedIndex > 0) {
var attendees = $('attendeesMenu').select("li");
attendees[attendeesEditor.selectedIndex--].removeClassName("selected");
attendees[attendeesEditor.selectedIndex].addClassName("selected");
this.value = this.confirmedValue = attendees[attendeesEditor.selectedIndex].firstChild.nodeValue.trim();
this.uid = attendees[attendeesEditor.selectedIndex].uid;
}
}
else if (event.keyCode == 40) { // Down arrow
var attendees = $('attendeesMenu').select("li");
if (attendees.size() - 1 > attendeesEditor.selectedIndex) {
if (attendeesEditor.selectedIndex >= 0)
attendees[attendeesEditor.selectedIndex].removeClassName("selected");
attendeesEditor.selectedIndex++;
attendees[attendeesEditor.selectedIndex].addClassName("selected");
this.value = this.confirmedValue = attendees[attendeesEditor.selectedIndex].firstChild.nodeValue.trim();
this.uid = attendees[attendeesEditor.selectedIndex].uid;
}
}
}
} }
function performSearch() { function performSearch() {
if (attendeesEditor.currentField) { // Perform address completion
if (document.contactLookupAjaxRequest) { if (attendeesEditor.currentField) {
// Abort any pending request if (document.contactLookupAjaxRequest) {
document.contactLookupAjaxRequest.aborted = true; // Abort any pending request
document.contactLookupAjaxRequest.abort(); document.contactLookupAjaxRequest.aborted = true;
} document.contactLookupAjaxRequest.abort();
if (attendeesEditor.currentField.value.trim().length > 0) { }
var urlstr = ( UserFolderURL + "Contacts/contactSearch?search=" if (attendeesEditor.currentField.value.trim().length > 0) {
+ escape(attendeesEditor.currentField.value) ); var urlstr = ( UserFolderURL + "Contacts/contactSearch?search="
document.contactLookupAjaxRequest = + escape(attendeesEditor.currentField.value) );
triggerAjaxRequest(urlstr, performSearchCallback, attendeesEditor.currentField); document.contactLookupAjaxRequest =
} triggerAjaxRequest(urlstr, performSearchCallback, attendeesEditor.currentField);
} }
attendeesEditor.delayedSearch = false; }
attendeesEditor.delayedSearch = false;
} }
function performSearchCallback(http) { function performSearchCallback(http) {
@ -111,6 +121,7 @@ function performSearchCallback(http) {
if (http.status == 200) { if (http.status == 200) {
var start = input.value.length; var start = input.value.length;
var data = http.responseText.evalJSON(true); var data = http.responseText.evalJSON(true);
if (data.length > 1) { if (data.length > 1) {
$(list.childNodesWithTag("li")).each(function(item) { $(list.childNodesWithTag("li")).each(function(item) {
item.remove(); item.remove();
@ -163,6 +174,8 @@ function performSearchCallback(http) {
input.confirmedValue = completeEmail; input.confirmedValue = completeEmail;
var end = input.value.length; var end = input.value.length;
$(input).selectText(start, end); $(input).selectText(start, end);
attendeesEditor.selectedIndex = -1;
} }
} }
} }

View File

@ -289,6 +289,8 @@ function onTextMouseDown(event) {
} }
} }
/* address completion */
function onContactKeydown(event) { function onContactKeydown(event) {
if (event.ctrlKey || event.metaKey) { if (event.ctrlKey || event.metaKey) {
this.focussed = true; this.focussed = true;
@ -316,24 +318,6 @@ function onContactKeydown(event) {
hideMenu(document.currentPopupMenu); hideMenu(document.currentPopupMenu);
} }
} }
else if (event.keyCode == 38) { // Up arrow
if (MailEditor.selectedIndex > 0) {
var contacts = $('contactsMenu').select("li");
contacts[MailEditor.selectedIndex--].removeClassName("selected");
this.value = contacts[MailEditor.selectedIndex].firstChild.nodeValue.trim();
contacts[MailEditor.selectedIndex].addClassName("selected");
}
}
else if (event.keyCode == 40) { // Down arrow
var contacts = $('contactsMenu').select("li");
if (contacts.size() - 1 > MailEditor.selectedIndex) {
if (MailEditor.selectedIndex >= 0)
contacts[MailEditor.selectedIndex].removeClassName("selected");
MailEditor.selectedIndex++;
this.value = contacts[MailEditor.selectedIndex].firstChild.nodeValue.trim();
contacts[MailEditor.selectedIndex].addClassName("selected");
}
}
else if (event.keyCode == 13) { else if (event.keyCode == 13) {
preventDefault(event); preventDefault(event);
if (this.confirmedValue) if (this.confirmedValue)
@ -343,6 +327,26 @@ function onContactKeydown(event) {
hideMenu(document.currentPopupMenu); hideMenu(document.currentPopupMenu);
MailEditor.selectedIndex = -1; MailEditor.selectedIndex = -1;
} }
else if ($('contactsMenu').getStyle('visibility') == 'visible') {
if (event.keyCode == 38) { // Up arrow
if (MailEditor.selectedIndex > 0) {
var contacts = $('contactsMenu').select("li");
contacts[MailEditor.selectedIndex--].removeClassName("selected");
this.value = contacts[MailEditor.selectedIndex].firstChild.nodeValue.trim();
contacts[MailEditor.selectedIndex].addClassName("selected");
}
}
else if (event.keyCode == 40) { // Down arrow
var contacts = $('contactsMenu').select("li");
if (contacts.size() - 1 > MailEditor.selectedIndex) {
if (MailEditor.selectedIndex >= 0)
contacts[MailEditor.selectedIndex].removeClassName("selected");
MailEditor.selectedIndex++;
this.value = contacts[MailEditor.selectedIndex].firstChild.nodeValue.trim();
contacts[MailEditor.selectedIndex].addClassName("selected");
}
}
}
} }
function performSearch() { function performSearch() {
@ -354,7 +358,7 @@ function performSearch() {
document.contactLookupAjaxRequest.abort(); document.contactLookupAjaxRequest.abort();
} }
if (MailEditor.currentField.value.trim().length > 0) { if (MailEditor.currentField.value.trim().length > 0) {
var urlstr = ( UserFolderURL + "Contacts/contactSearch?search=" var urlstr = ( UserFolderURL + "Contacts/allContactSearch?search="
+ escape(MailEditor.currentField.value) ); + escape(MailEditor.currentField.value) );
document.contactLookupAjaxRequest = document.contactLookupAjaxRequest =
triggerAjaxRequest(urlstr, performSearchCallback, MailEditor.currentField); triggerAjaxRequest(urlstr, performSearchCallback, MailEditor.currentField);
@ -371,20 +375,21 @@ function performSearchCallback(http) {
var input = http.callbackData; var input = http.callbackData;
if (http.status == 200) { if (http.status == 200) {
var start = input.value.length; log(http.responseText); var start = input.value.length;
var data = http.responseText.evalJSON(true); var data = http.responseText.evalJSON(true);
if (data.length > 1) { if (data.length > 1) {
$(list.childNodesWithTag("li")).each(function(item) { list.select("li").each(function(item) {
item.remove(); item.remove();
}); });
// Populate popup menu // Populate popup menu
for (var i = 0; i < data.length; i++) { for (var i = 0; i < data.length; i++) {
var contact = data[i]; var contact = data[i];
var completeEmail = contact["name"] + " <" + contact["email"] + ">"; var completeEmail = contact["displayName"] + " <" + contact["mail"] + ">";
var node = document.createElement("li"); var node = document.createElement("li");
list.appendChild(node); list.appendChild(node);
node.uid = contact["uid"]; node.uid = contact["c_uid"];
node.appendChild(document.createTextNode(completeEmail)); node.appendChild(document.createTextNode(completeEmail));
$(node).observe("mousedown", onAddressResultClick); $(node).observe("mousedown", onAddressResultClick);
} }
@ -413,18 +418,21 @@ function performSearchCallback(http) {
if (data.length == 1) { if (data.length == 1) {
// Single result // Single result
var contact = data[0]; var contact = data[0];
if (contact["uid"].length > 0) if (contact["c_uid"].length > 0)
input.uid = contact["uid"]; input.uid = contact["c_uid"];
var completeEmail = contact["name"] + " <" + contact["email"] + ">"; var completeEmail = contact["displayName"] + " <" + contact["mail"] + ">";
if (contact["name"].substring(0, input.value.length).toUpperCase() if (contact["displayName"].substring(0, input.value.length).toUpperCase()
== input.value.toUpperCase()) == input.value.toUpperCase())
input.value = completeEmail; input.value = completeEmail;
else else
// The result matches email address, not user name // The result matches email address, not user name
input.value += ' >> ' + completeEmail; input.value += ' >> ' + completeEmail;
input.confirmedValue = completeEmail; input.confirmedValue = completeEmail;
var end = input.value.length; var end = input.value.length;
$(input).selectText(start, end); $(input).selectText(start, end);
MailEditor.selectedIndex = -1;
} }
} }
} }

View File

@ -296,7 +296,8 @@ SPAN.toolbarButton:active
/* popups */ /* popups */
.menu .menu,
.popupMenu
{ visibility: hidden; { visibility: hidden;
position: absolute; position: absolute;
z-index: 1000; z-index: 1000;
@ -310,7 +311,11 @@ SPAN.toolbarButton:active
border-right: 1px solid #424142; border-right: 1px solid #424142;
border-bottom: 1px solid #424142; } border-bottom: 1px solid #424142; }
.menu UL .popupMenu
{ background-color: #fff; }
.menu UL,
.popupMenu UL
{ cursor: default; { cursor: default;
list-style-type: none; list-style-type: none;
list-style-image: none; list-style-image: none;
@ -322,7 +327,8 @@ SPAN.toolbarButton:active
border-right: 1px solid #9e9a92; border-right: 1px solid #9e9a92;
border-bottom: 1px solid #9e9a92; } border-bottom: 1px solid #9e9a92; }
.menu LI .menu LI,
.popupMenu LI
{ padding-left: 1em; { padding-left: 1em;
padding-right: 1em; padding-right: 1em;
padding-top: .15em; padding-top: .15em;
@ -332,7 +338,9 @@ SPAN.toolbarButton:active
white-space: nowrap; } white-space: nowrap; }
.menu LI.disabled, .menu LI.disabled,
.menu LI.disabled:hover .popuMenu LI.disabled,
.menu LI.disabled:hover,
.popupMenu LI.disabled:hover
{ color: #999; } { color: #999; }
.menu LI IMG .menu LI IMG
@ -354,11 +362,14 @@ UL.choiceMenu LI._chosen
UL.choiceMenu LI._chosen:hover UL.choiceMenu LI._chosen:hover
{ list-style-image: url("menu-check-hover.gif"); } { list-style-image: url("menu-check-hover.gif"); }
.menu LI:hover, .menu LI.selected, .menu LI.submenu-selected .menu LI:hover,
.menu LI.selected,
.menu LI.submenu-selected
{ background-color: #4b6983; { background-color: #4b6983;
color: #fff; } color: #fff; }
.menu LI.separator, .menu LI.separator:hover .menu LI.separator,
.menu LI.separator:hover
{ padding: 0px; { padding: 0px;
margin: 2px 0px; margin: 2px 0px;
height: 0px; height: 0px;
@ -621,6 +632,8 @@ LI.denied
font-style: italic; font-style: italic;
color: #f33; } color: #f33; }
.popupMenu LI:hover,
.popupMenu LI.selected,
LI._selected, LI._selected,
TR._selected > TD, TR._selected > TD,
TD._selected TD._selected