mirror of
https://github.com/inverse-inc/sogo.git
synced 2026-10-11 23:07:12 +00:00
Monotone-Parent: c40151185171e3ba8a257569b8ab5ec86930d393
Monotone-Revision: 0efdaccbad84f567e4d9cc3ca0176e506620aefb Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2010-05-05T18:49:29 Monotone-Branch: ca.inverse.sogo
This commit is contained in:
1 parent
2bf4b7cf8b
commit
97df7c4c45
10 files changed
+422
-277
No files matched your search
@@ -78,8 +78,11 @@
|
||||
us = [activeUser userSettings];
|
||||
moduleSettings = [us objectForKey: module];
|
||||
if (!moduleSettings)
|
||||
moduleSettings = [NSMutableDictionary dictionary];
|
||||
[us setObject: moduleSettings forKey: module];
|
||||
{
|
||||
moduleSettings = [NSMutableDictionary new];
|
||||
[us setObject: moduleSettings forKey: module];
|
||||
[moduleSettings release];
|
||||
}
|
||||
contextIsSetup = YES;
|
||||
}
|
||||
}
|
||||
@@ -149,44 +152,6 @@
|
||||
return email;
|
||||
}
|
||||
|
||||
- (NSArray *) _responseForResults: (NSArray *) results
|
||||
{
|
||||
NSEnumerator *contacts;
|
||||
NSString *email, *info;
|
||||
NSDictionary *contact;
|
||||
NSMutableArray *formattedContacts;
|
||||
NSMutableDictionary *formattedContact;
|
||||
|
||||
formattedContacts = [NSMutableArray arrayWithCapacity: [results count]];
|
||||
if ([results count] > 0)
|
||||
{
|
||||
contacts = [results objectEnumerator];
|
||||
contact = [contacts nextObject];
|
||||
while (contact)
|
||||
{
|
||||
email = [contact objectForKey: @"c_email"];
|
||||
if ([email length])
|
||||
{
|
||||
formattedContact = [NSMutableDictionary dictionary];
|
||||
[formattedContact setObject: [contact objectForKey: @"c_uid"]
|
||||
forKey: @"uid"];
|
||||
[formattedContact setObject: [contact objectForKey: @"cn"]
|
||||
forKey: @"name"];
|
||||
[formattedContact setObject: email
|
||||
forKey: @"email"];
|
||||
info = [contact objectForKey: @"c_info"];
|
||||
if (info != nil)
|
||||
[formattedContact setObject: info
|
||||
forKey: @"contactInfo"];
|
||||
[formattedContacts addObject: formattedContact];
|
||||
}
|
||||
contact = [contacts nextObject];
|
||||
}
|
||||
}
|
||||
|
||||
return formattedContacts;
|
||||
}
|
||||
|
||||
- (id <WOActionResults>) allContactSearchAction
|
||||
{
|
||||
id <WOActionResults> result;
|
||||
@@ -196,7 +161,7 @@
|
||||
NSArray *folders, *contacts, *descriptors, *sortedContacts;
|
||||
NSMutableArray *sortedFolders;
|
||||
NSMutableDictionary *contact, *uniqueContacts;
|
||||
unsigned int i, j;
|
||||
unsigned int i, j, max;
|
||||
NSSortDescriptor *commonNameDescriptor;
|
||||
BOOL excludeGroups, excludeLists;
|
||||
|
||||
@@ -217,9 +182,10 @@
|
||||
else
|
||||
[localException raise];
|
||||
NS_ENDHANDLER;
|
||||
sortedFolders = [NSMutableArray arrayWithCapacity: [folders count]];
|
||||
max = [folders count];
|
||||
sortedFolders = [NSMutableArray arrayWithCapacity: max];
|
||||
uniqueContacts = [NSMutableDictionary dictionary];
|
||||
for (i = 0; i < [folders count]; i++)
|
||||
for (i = 0; i < max; i++)
|
||||
{
|
||||
folder = [folders objectAtIndex: i];
|
||||
/* We first search in LDAP folders (in case of duplicated entries in GCS folders) */
|
||||
@@ -228,7 +194,7 @@
|
||||
else
|
||||
[sortedFolders addObject: folder];
|
||||
}
|
||||
for (i = 0; i < [sortedFolders count]; i++)
|
||||
for (i = 0; i < max; i++)
|
||||
{
|
||||
folder = [sortedFolders objectAtIndex: i];
|
||||
//NSLog(@" Address book: %@ (%@)", [folder displayName], [folder class]);
|
||||
@@ -245,8 +211,8 @@
|
||||
&& [uniqueContacts objectForKey: mail] == nil
|
||||
&& !(excludeGroups && [contact objectForKey: @"isGroup"]))
|
||||
[uniqueContacts setObject: contact forKey: mail];
|
||||
else if (!excludeLists
|
||||
&& [[contact objectForKey: @"c_name"] hasSuffix: @".vlf"])
|
||||
else if (!excludeLists && [[contact objectForKey: @"c_component"]
|
||||
isEqualToString: @"vlist"])
|
||||
{
|
||||
[contact setObject: [folder nameInContainer]
|
||||
forKey: @"container"];
|
||||
@@ -254,14 +220,16 @@
|
||||
forKey: [contact objectForKey: @"c_name"]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ([uniqueContacts count] > 0)
|
||||
{
|
||||
// Sort the contacts by display name
|
||||
commonNameDescriptor = [[[NSSortDescriptor alloc] initWithKey: @"c_cn"
|
||||
ascending:YES] autorelease];
|
||||
commonNameDescriptor = [[NSSortDescriptor alloc] initWithKey: @"c_cn"
|
||||
ascending:YES];
|
||||
descriptors = [NSArray arrayWithObjects: commonNameDescriptor, nil];
|
||||
sortedContacts = [[uniqueContacts allValues] sortedArrayUsingDescriptors: descriptors];
|
||||
[commonNameDescriptor release];
|
||||
sortedContacts = [[uniqueContacts allValues]
|
||||
sortedArrayUsingDescriptors: descriptors];
|
||||
}
|
||||
else
|
||||
sortedContacts = [NSArray array];
|
||||
@@ -269,7 +237,7 @@
|
||||
sortedContacts, @"contacts",
|
||||
nil];
|
||||
result = [self responseWithStatus: 200];
|
||||
[(WOResponse*)result appendContentString: [data jsonRepresentation]];
|
||||
[(WOResponse*) result appendContentString: [data jsonRepresentation]];
|
||||
}
|
||||
else
|
||||
result = [NSException exceptionWithHTTPStatus: 400
|
||||
@@ -278,36 +246,6 @@
|
||||
return result;
|
||||
}
|
||||
|
||||
- (id <WOActionResults>) contactSearchAction
|
||||
{
|
||||
NSDictionary *data;
|
||||
NSArray *contacts;
|
||||
NSString *searchText, *domain;
|
||||
id <WOActionResults> result;
|
||||
SOGoUserManager *um;
|
||||
|
||||
searchText = [self queryParameterForKey: @"search"];
|
||||
if ([searchText length] > 0)
|
||||
{
|
||||
um = [SOGoUserManager sharedUserManager];
|
||||
domain = [[context activeUser] domain];
|
||||
contacts
|
||||
= [self _responseForResults: [um fetchContactsMatching: searchText
|
||||
inDomain: domain]];
|
||||
data = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
searchText, @"searchText",
|
||||
contacts, @"contacts",
|
||||
nil];
|
||||
result = [self responseWithStatus: 200];
|
||||
[(WOResponse*)result appendContentString: [data jsonRepresentation]];
|
||||
}
|
||||
else
|
||||
result = [NSException exceptionWithHTTPStatus: 400
|
||||
reason: @"missing 'search' parameter"];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
- (NSArray *) _subFoldersFromFolder: (SOGoParentFolder *) parentFolder
|
||||
{
|
||||
NSMutableArray *folders;
|
||||
@@ -375,8 +313,7 @@
|
||||
|
||||
- (NSString *) currentContactFolderId
|
||||
{
|
||||
return [NSString stringWithFormat: @"/%@",
|
||||
[currentFolder nameInContainer]];
|
||||
return [NSString stringWithFormat: @"/%@", [currentFolder nameInContainer]];
|
||||
}
|
||||
|
||||
- (NSString *) currentContactFolderName
|
||||
@@ -391,7 +328,8 @@
|
||||
|
||||
- (NSString *) currentContactFolderClass
|
||||
{
|
||||
return ([currentFolder isKindOfClass: [SOGoContactSourceFolder class]]? @"remote" : @"local");
|
||||
return ([currentFolder isKindOfClass: [SOGoContactSourceFolder class]]
|
||||
? @"remote" : @"local");
|
||||
}
|
||||
|
||||
- (NSString *) verticalDragHandleStyle
|
||||
@@ -401,7 +339,8 @@
|
||||
[self _setupContext];
|
||||
vertical = [moduleSettings objectForKey: @"DragHandleVertical"];
|
||||
|
||||
return ((vertical && [vertical intValue] > 0) ? (id)[vertical stringByAppendingFormat: @"px"] : nil);
|
||||
return ((vertical && [vertical intValue] > 0)
|
||||
? (id)[vertical stringByAppendingFormat: @"px"] : nil);
|
||||
}
|
||||
|
||||
- (NSString *) horizontalDragHandleStyle
|
||||
@@ -411,7 +350,8 @@
|
||||
[self _setupContext];
|
||||
horizontal = [moduleSettings objectForKey: @"DragHandleHorizontal"];
|
||||
|
||||
return ((horizontal && [horizontal intValue] > 0) ? (id)[horizontal stringByAppendingFormat: @"px"] : nil);
|
||||
return ((horizontal && [horizontal intValue] > 0)
|
||||
? (id)[horizontal stringByAppendingFormat: @"px"] : nil);
|
||||
}
|
||||
|
||||
- (NSString *) contactsListContentStyle
|
||||
@@ -421,7 +361,8 @@
|
||||
[self _setupContext];
|
||||
height = [moduleSettings objectForKey: @"DragHandleVertical"];
|
||||
|
||||
return ((height && [height intValue] > 0) ? [NSString stringWithFormat: @"%ipx", ([height intValue] - 27)] : nil);
|
||||
return ((height && [height intValue] > 0)
|
||||
? [NSString stringWithFormat: @"%ipx", ([height intValue] - 27)] : nil);
|
||||
}
|
||||
|
||||
- (WOResponse *) saveDragHandleStateAction
|
||||
|
||||
+11
-17
@@ -143,29 +143,23 @@
|
||||
|
||||
- (WOResponse *) propertiesAction
|
||||
{
|
||||
NSArray *references;
|
||||
NSMutableArray *data;
|
||||
NGVCardReference *card;
|
||||
WOResponse *rc;
|
||||
int i, count;
|
||||
int count, max;
|
||||
|
||||
data = [NSMutableArray array];
|
||||
co = [self clientObject];
|
||||
list = [co vList];
|
||||
|
||||
count = [[list cardReferences] count];
|
||||
for (i = 0; i < count; i++)
|
||||
list = [[self clientObject] vList];
|
||||
references = [list cardReferences];
|
||||
max = [references count];
|
||||
data = [NSMutableArray arrayWithCapacity: max];
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
card = [[list cardReferences] objectAtIndex: i];
|
||||
[data addObject: [NSArray arrayWithObjects: [card reference], [card fn],
|
||||
[card email], nil]];
|
||||
card = [references objectAtIndex: count];
|
||||
[data addObject: [NSArray arrayWithObjects: [card reference],
|
||||
[card fn], [card email], nil]];
|
||||
}
|
||||
|
||||
rc = [context response];
|
||||
[rc setHeader: @"text/plain; charset=utf-8"
|
||||
forKey: @"content-type"];
|
||||
[rc appendContentString: [data jsonRepresentation]];
|
||||
|
||||
return rc;
|
||||
return [self responseWithStatus: 200 andJSONRepresentation: data];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -23,11 +23,6 @@
|
||||
pageName = "UIxContactFoldersView";
|
||||
actionName = "mailerContacts";
|
||||
};
|
||||
contactSearch = {
|
||||
protectedBy = "<public>";
|
||||
pageName = "UIxContactFoldersView";
|
||||
actionName = "contactSearch";
|
||||
};
|
||||
allContactSearch = {
|
||||
protectedBy = "<public>";
|
||||
pageName = "UIxContactFoldersView";
|
||||
|
||||
@@ -4,7 +4,6 @@ var OwnerLogin = "";
|
||||
|
||||
var resultsDiv;
|
||||
var address;
|
||||
var awaitingFreeBusyRequests = new Array();
|
||||
var additionalDays = 2;
|
||||
|
||||
var isAllDay = parent$("isAllDay").checked + 0;
|
||||
@@ -13,8 +12,6 @@ var displayEndHour = 23;
|
||||
|
||||
var attendeesEditor = {
|
||||
delay: 500,
|
||||
delayedSearch: false,
|
||||
currentField: null,
|
||||
selectedIndex: -1
|
||||
};
|
||||
|
||||
@@ -32,67 +29,135 @@ function handleAllDay () {
|
||||
|
||||
/* address completion */
|
||||
|
||||
function resolveListAttendees(input, append) {
|
||||
var urlstr = (UserFolderURL
|
||||
+ "Contacts/"
|
||||
+ escape(input.container) + "/"
|
||||
+ escape(input.cname) + "/properties");
|
||||
triggerAjaxRequest(urlstr, resolveListAttendeesCallback,
|
||||
{ "input": input, "append": append });
|
||||
}
|
||||
|
||||
function resolveListAttendeesCallback(http) {
|
||||
if (http.readyState == 4 && http.status == 200) {
|
||||
var input = http.callbackData["input"];
|
||||
var append = http.callbackData["append"];
|
||||
var contacts = http.responseText.evalJSON(true);
|
||||
for (var i = 0; i < contacts.length; i++) {
|
||||
var contact = contacts[i];
|
||||
var fullName = contact[1];
|
||||
if (fullName && fullName.length > 0) {
|
||||
fullName += " <" + contact[2] + ">";
|
||||
}
|
||||
else {
|
||||
fullName = contact[2];
|
||||
}
|
||||
input.uid = null;
|
||||
input.cname = null;
|
||||
input.container = null;
|
||||
input.isList = false;
|
||||
input.value = contact[2];
|
||||
input.confirmedValue = null;
|
||||
input.hasfreebusy = false;
|
||||
input.modified = true;
|
||||
// input.focussed = true;
|
||||
// input.activate();
|
||||
input.checkAfterLookup = true;
|
||||
performSearch(input);
|
||||
if (i < (contacts.length - 1)) {
|
||||
var nextRow = newAttendee(input.parentNode.parentNode);
|
||||
input = nextRow.down("input");
|
||||
} else if (append) {
|
||||
var row = input.parentNode.parentNode;
|
||||
var tBody = row.parentNode;
|
||||
if (row.rowIndex == (tBody.rows.length - 3)) {
|
||||
if (input.selectText) {
|
||||
input.selectText(0, 0);
|
||||
} else if (input.createTextRange) {
|
||||
input.createTextRange().moveStart();
|
||||
}
|
||||
newAttendee();
|
||||
} else {
|
||||
var nextRow = tBody.rows[row.rowIndex + 1];
|
||||
var input = nextRow.down("input");
|
||||
input.selectText(0, input.value.length);
|
||||
input.focussed = true;
|
||||
}
|
||||
} else {
|
||||
if (input.selectText) {
|
||||
input.selectText(0, 0);
|
||||
} else if (input.createTextRange) {
|
||||
input.createTextRange().moveStart();
|
||||
}
|
||||
input.blur();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onContactKeydown(event) {
|
||||
if (event.ctrlKey || event.metaKey) {
|
||||
this.focussed = true;
|
||||
return;
|
||||
}
|
||||
if (event.keyCode == 9) { // Tab
|
||||
if (event.keyCode == 9 || event.keyCode == 13) { // Tab
|
||||
preventDefault(event);
|
||||
if (this.confirmedValue)
|
||||
this.value = this.confirmedValue;
|
||||
this.hasfreebusy = false;
|
||||
var row = $(this).up("tr").next();
|
||||
this.blur(); // triggers checkAttendee function call
|
||||
var input = row.down("input");
|
||||
if (input) {
|
||||
input.focussed = true;
|
||||
input.activate();
|
||||
if (this.isList) {
|
||||
resolveListAttendees(this, true);
|
||||
event.stop();
|
||||
} else {
|
||||
checkAttendee(this);
|
||||
// this.blur(); // triggers checkAttendee function call
|
||||
var input = row.down("input");
|
||||
if (input) {
|
||||
input.focussed = true;
|
||||
input.activate();
|
||||
}
|
||||
else
|
||||
newAttendee();
|
||||
}
|
||||
else
|
||||
newAttendee(null);
|
||||
}
|
||||
else if (event.keyCode == 0
|
||||
|| event.keyCode == 8 // Backspace
|
||||
|| event.keyCode == 32 // Space
|
||||
|| event.keyCode > 47) {
|
||||
this.setAttribute("modified", "1");
|
||||
this.modified = true;
|
||||
this.confirmedValue = null;
|
||||
this.cname = null;
|
||||
this.uid = null;
|
||||
this.container = null;
|
||||
this.hasfreebusy = false;
|
||||
attendeesEditor.currentField = this;
|
||||
if (this.value.length > 0 && !attendeesEditor.delayedSearch) {
|
||||
attendeesEditor.delayedSearch = true;
|
||||
setTimeout("performSearch()", attendeesEditor.delay);
|
||||
if (this.searchTimeout) {
|
||||
window.clearTimeout(this.searchTimeout);
|
||||
}
|
||||
if (this.value.length > 0) {
|
||||
var thisInput = this;
|
||||
this.searchTimeout = setTimeout(function()
|
||||
{performSearch(thisInput);
|
||||
thisInput = null;},
|
||||
attendeesEditor.delay);
|
||||
}
|
||||
else if (this.value.length == 0) {
|
||||
if (document.currentPopupMenu)
|
||||
hideMenu(document.currentPopupMenu);
|
||||
}
|
||||
}
|
||||
else if (event.keyCode == 13) {
|
||||
preventDefault(event);
|
||||
if (this.confirmedValue)
|
||||
this.value = this.confirmedValue;
|
||||
$(this).selectText(0, this.value.length);
|
||||
if (document.currentPopupMenu)
|
||||
hideMenu(document.currentPopupMenu);
|
||||
attendeesEditor.selectedIndex = -1;
|
||||
if (this.uid) {
|
||||
this.hasfreebusy = false;
|
||||
this.writeAttribute("modified", "1");
|
||||
this.blur(); // triggers checkAttendee function call
|
||||
}
|
||||
}
|
||||
else if ($('attendeesMenu').getStyle('visibility') == 'visible') {
|
||||
attendeesEditor.currentField = this;
|
||||
if (event.keyCode == Event.KEY_UP) { // 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].readAttribute("address");
|
||||
this.uid = attendees[attendeesEditor.selectedIndex].uid;
|
||||
var attendee = attendees[attendeesEditor.selectedIndex];
|
||||
attendee.addClassName("selected");
|
||||
this.value = this.confirmedValue = attendee.address;
|
||||
this.uid = attendee.uid;
|
||||
this.isList = attendee.isList;
|
||||
this.cname = attendee.cname;
|
||||
this.container = attendee.container;
|
||||
}
|
||||
}
|
||||
else if (event.keyCode == Event.KEY_DOWN) { // Down arrow
|
||||
@@ -101,30 +166,27 @@ function onContactKeydown(event) {
|
||||
if (attendeesEditor.selectedIndex >= 0)
|
||||
attendees[attendeesEditor.selectedIndex].removeClassName("selected");
|
||||
attendeesEditor.selectedIndex++;
|
||||
attendees[attendeesEditor.selectedIndex].addClassName("selected");
|
||||
this.value = this.confirmedValue = attendees[attendeesEditor.selectedIndex].readAttribute("address");
|
||||
this.uid = attendees[attendeesEditor.selectedIndex].uid;
|
||||
var attendee = attendees[attendeesEditor.selectedIndex];
|
||||
attendee.addClassName("selected");
|
||||
this.value = this.confirmedValue = attendee.address;
|
||||
this.isList = attendee.isList;
|
||||
this.uid = attendee.uid;
|
||||
this.cname = attendee.cname;
|
||||
this.container = attendee.container;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function performSearch() {
|
||||
function performSearch(input) {
|
||||
// Perform address completion
|
||||
if (attendeesEditor.currentField) {
|
||||
if (document.contactLookupAjaxRequest) {
|
||||
// Abort any pending request
|
||||
document.contactLookupAjaxRequest.aborted = true;
|
||||
document.contactLookupAjaxRequest.abort();
|
||||
}
|
||||
if (attendeesEditor.currentField.value.trim().length > 0) {
|
||||
var urlstr = ( UserFolderURL + "Contacts/contactSearch?search="
|
||||
+ escape(attendeesEditor.currentField.value) );
|
||||
document.contactLookupAjaxRequest =
|
||||
triggerAjaxRequest(urlstr, performSearchCallback, attendeesEditor.currentField);
|
||||
}
|
||||
if (input.value.trim().length > 0) {
|
||||
var urlstr = (UserFolderURL
|
||||
+ "Contacts/allContactSearch?excludeGroups=1&search="
|
||||
+ escape(input.value));
|
||||
triggerAjaxRequest(urlstr, performSearchCallback, input);
|
||||
}
|
||||
attendeesEditor.delayedSearch = false;
|
||||
input.searchTimeout = null;
|
||||
}
|
||||
|
||||
function performSearchCallback(http) {
|
||||
@@ -139,6 +201,7 @@ function performSearchCallback(http) {
|
||||
var data = http.responseText.evalJSON(true);
|
||||
|
||||
if (data.contacts.length > 1) {
|
||||
list.input = input;
|
||||
$(list.childNodesWithTag("li")).each(function(item) {
|
||||
item.remove();
|
||||
});
|
||||
@@ -146,25 +209,42 @@ function performSearchCallback(http) {
|
||||
// Populate popup menu
|
||||
for (var i = 0; i < data.contacts.length; i++) {
|
||||
var contact = data.contacts[i];
|
||||
var completeEmail = contact["name"] + " <" + contact["email"] + ">";
|
||||
var node = new Element('li', { 'address': completeEmail });
|
||||
var isList = (contact["c_component"] &&
|
||||
contact["c_component"] == "vlist");
|
||||
var completeEmail = contact["c_cn"].trim();
|
||||
if (!isList) {
|
||||
if (completeEmail)
|
||||
completeEmail += " <" + contact["c_mail"] + ">";
|
||||
else
|
||||
completeEmail = contact["c_mail"];
|
||||
}
|
||||
var node = createElement('li');
|
||||
list.appendChild(node);
|
||||
node.address = completeEmail;
|
||||
log("node.address: " + node.address);
|
||||
node.uid = contact["c_uid"];
|
||||
node.isList = isList;
|
||||
if (isList) {
|
||||
node.cname = contact["c_name"];
|
||||
node.container = contact["container"];
|
||||
}
|
||||
var matchPosition = completeEmail.toLowerCase().indexOf(data.searchText.toLowerCase());
|
||||
var matchBefore = completeEmail.substring(0, matchPosition);
|
||||
var matchText = completeEmail.substring(matchPosition, matchPosition + data.searchText.length);
|
||||
var matchAfter = completeEmail.substring(matchPosition + data.searchText.length);
|
||||
list.appendChild(node);
|
||||
node.uid = contact["uid"];
|
||||
node.appendChild(document.createTextNode(matchBefore));
|
||||
node.appendChild(new Element('strong').update(matchText));
|
||||
node.appendChild(document.createTextNode(matchAfter));
|
||||
if (contact["contactInfo"])
|
||||
node.appendChild(document.createTextNode(" (" + contact["contactInfo"] + ")"));
|
||||
$(node).observe("mousedown", onAttendeeResultClick);
|
||||
node.appendChild(document.createTextNode(" (" +
|
||||
contact["contactInfo"] + ")"));
|
||||
node.observe("mousedown",
|
||||
onAttendeeResultClick.bindAsEventListener(node));
|
||||
}
|
||||
|
||||
// Show popup menu
|
||||
var offsetScroll = Element.cumulativeScrollOffset(attendeesEditor.currentField);
|
||||
var offset = Element.cumulativeOffset(attendeesEditor.currentField);
|
||||
var offsetScroll = Element.cumulativeScrollOffset(input);
|
||||
var offset = Element.cumulativeOffset(input);
|
||||
var top = offset[1] - offsetScroll[1] + node.offsetHeight + 3;
|
||||
var height = 'auto';
|
||||
var heightDiff = window.height() - offset[1];
|
||||
@@ -190,52 +270,73 @@ function performSearchCallback(http) {
|
||||
if (data.contacts.length == 1) {
|
||||
// Single result
|
||||
var contact = data.contacts[0];
|
||||
if (contact["uid"].length > 0) {
|
||||
var row = $(input.parentNode.parentNode);
|
||||
input.uid = contact["uid"];
|
||||
if (input.uid == OwnerLogin) {
|
||||
row.removeAttribute("role");
|
||||
row.setAttribute("partstat", "accepted");
|
||||
row.addClassName("organizer-row");
|
||||
row.removeClassName("attendee-row");
|
||||
row.isOrganizer = true;
|
||||
} else {
|
||||
row.removeAttribute("partstat");
|
||||
row.setAttribute("role", "req-participant");
|
||||
row.addClassName("attendee-row");
|
||||
row.removeClassName("organizer-row");
|
||||
row.isOrganizer = false;
|
||||
}
|
||||
input.uid = contact["c_uid"];
|
||||
var row = $(input.parentNode.parentNode);
|
||||
if (input.uid == OwnerLogin) {
|
||||
row.removeAttribute("role");
|
||||
row.setAttribute("partstat", "accepted");
|
||||
row.addClassName("organizer-row");
|
||||
row.removeClassName("attendee-row");
|
||||
row.isOrganizer = true;
|
||||
} else {
|
||||
row.removeAttribute("partstat");
|
||||
row.setAttribute("role", "req-participant");
|
||||
row.addClassName("attendee-row");
|
||||
row.removeClassName("organizer-row");
|
||||
row.isOrganizer = false;
|
||||
}
|
||||
var completeEmail = contact["name"] + " <" + contact["email"] + ">";
|
||||
if (contact["name"].substring(0, input.value.length).toUpperCase()
|
||||
== input.value.toUpperCase())
|
||||
var isList = (contact["c_component"] &&
|
||||
contact["c_component"] == "vlist");
|
||||
if (isList) {
|
||||
input.cname = contact["c_name"];
|
||||
input.container = contact["container"];
|
||||
}
|
||||
var completeEmail = contact["c_cn"].trim();
|
||||
if (!isList) {
|
||||
if (completeEmail)
|
||||
completeEmail += " <" + contact["c_mail"] + ">";
|
||||
else
|
||||
completeEmail = contact["c_mail"];
|
||||
}
|
||||
if ((input.value == contact["c_mail"])
|
||||
|| (contact["c_cn"].substring(0, input.value.length).toUpperCase()
|
||||
== input.value.toUpperCase())) {
|
||||
input.value = completeEmail;
|
||||
}
|
||||
else
|
||||
// The result matches email address, not user name
|
||||
input.value += ' >> ' + completeEmail;
|
||||
input.isList = isList;
|
||||
input.confirmedValue = completeEmail;
|
||||
var end = input.value.length;
|
||||
$(input).selectText(start, end);
|
||||
|
||||
attendeesEditor.selectedIndex = -1;
|
||||
|
||||
if (input.checkAfterLookup) {
|
||||
input.checkAfterLookup = false;
|
||||
input.modified = true;
|
||||
input.hasfreebusy = false;
|
||||
checkAttendee(input);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
if (document.currentPopupMenu)
|
||||
hideMenu(document.currentPopupMenu);
|
||||
document.contactLookupAjaxRequest = null;
|
||||
}
|
||||
}
|
||||
|
||||
function onAttendeeResultClick(event) {
|
||||
if (attendeesEditor.currentField) {
|
||||
attendeesEditor.currentField.uid = this.uid;
|
||||
attendeesEditor.currentField.value = $(this).readAttribute("address");
|
||||
attendeesEditor.currentField.confirmedValue = attendeesEditor.currentField.value;
|
||||
attendeesEditor.currentField.blur(); // triggers checkAttendee function call
|
||||
}
|
||||
var input = this.parentNode.input;
|
||||
input.uid = this.uid;
|
||||
input.cname = this.cname;
|
||||
input.container = this.container;
|
||||
input.isList = this.isList;
|
||||
input.confirmedValue = input.value = this.address;
|
||||
checkAttendee(input);
|
||||
this.parentNode.input = null;
|
||||
}
|
||||
|
||||
function resetFreeBusyZone() {
|
||||
@@ -331,13 +432,23 @@ function rotateAttendeeStatus(row) {
|
||||
}
|
||||
}
|
||||
|
||||
function newAttendee(event) {
|
||||
function onNewAttendeeClick(event) {
|
||||
newAttendee();
|
||||
event.stop();
|
||||
}
|
||||
|
||||
function newAttendee(previousAttendee) {
|
||||
var table = $("freeBusyAttendees");
|
||||
var tbody = table.tBodies[0];
|
||||
var model = tbody.rows[tbody.rows.length - 1];
|
||||
var futureRow = tbody.rows[tbody.rows.length - 2];
|
||||
var nextRowIndex = tbody.rows.length - 2;
|
||||
if (previousAttendee) {
|
||||
nextRowIndex = previousAttendee.rowIndex + 1;
|
||||
}
|
||||
var nextRow = tbody.rows[nextRowIndex];
|
||||
var newRow = $(model.cloneNode(true));
|
||||
tbody.insertBefore(newRow, futureRow);
|
||||
tbody.insertBefore(newRow, nextRow);
|
||||
var result = newRow;
|
||||
|
||||
var statusTD = newRow.down(".attendeeStatus");
|
||||
if (statusTD) {
|
||||
@@ -348,8 +459,8 @@ function newAttendee(event) {
|
||||
$(newRow).removeClassName("attendeeModel");
|
||||
|
||||
var input = newRow.down("input");
|
||||
input.observe("keydown", onContactKeydown);
|
||||
input.observe("blur", checkAttendee);
|
||||
input.observe("keydown", onContactKeydown.bindAsEventListener(input));
|
||||
input.observe("blur", onInputBlur);
|
||||
|
||||
input.focussed = true;
|
||||
input.activate();
|
||||
@@ -357,49 +468,64 @@ function newAttendee(event) {
|
||||
table = $("freeBusyData");
|
||||
tbody = table.tBodies[0];
|
||||
model = tbody.rows[tbody.rows.length - 1];
|
||||
futureRow = tbody.rows[tbody.rows.length - 2];
|
||||
nextRow = tbody.rows[nextRowIndex];
|
||||
newRow = $(model.cloneNode(true));
|
||||
tbody.insertBefore(newRow, futureRow);
|
||||
tbody.insertBefore(newRow, nextRow);
|
||||
newRow.removeClassName("dataModel");
|
||||
|
||||
var attendeesDiv = $$('TABLE#freeBusy TD.freeBusyAttendees DIV').first();
|
||||
var dataDiv = $$('TABLE#freeBusy TD.freeBusyData DIV').first();
|
||||
|
||||
dataDiv.scrollTop = attendeesDiv.scrollTop;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function checkAttendee() { // log ("checkAttendee");
|
||||
if (document.currentPopupMenu)
|
||||
hideMenu(document.currentPopupMenu);
|
||||
|
||||
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 row = this.parentNode.parentNode;
|
||||
function checkAttendee(input) {
|
||||
var row = $(input.parentNode.parentNode);
|
||||
var tbody = row.parentNode;
|
||||
if (tbody && this.value.trim().length == 0) {
|
||||
if (tbody && input.value.trim().length == 0) {
|
||||
var dataTable = $("freeBusyData").tBodies[0];
|
||||
var dataRow = dataTable.rows[row.sectionRowIndex];
|
||||
tbody.removeChild(row);
|
||||
dataTable.removeChild(dataRow);
|
||||
}
|
||||
else if (this.readAttribute("modified") == "1") {
|
||||
if (!this.hasfreebusy) {
|
||||
if (this.uid && this.confirmedValue)
|
||||
this.value = this.confirmedValue;
|
||||
displayFreeBusyForNode(this);
|
||||
this.hasfreebusy = true;
|
||||
else if (input.modified) {
|
||||
if (!row.hasClassName("needs-action")) {
|
||||
row.addClassName("needs-action");
|
||||
row.removeClassName("declined");
|
||||
row.removeClassName("accepted");
|
||||
}
|
||||
this.setAttribute("modified", "0");
|
||||
if (!input.hasfreebusy) {
|
||||
if (input.uid && input.confirmedValue) {
|
||||
input.value = input.confirmedValue;
|
||||
}
|
||||
displayFreeBusyForNode(input);
|
||||
input.hasfreebusy = true;
|
||||
}
|
||||
input.modified = false;
|
||||
}
|
||||
}
|
||||
|
||||
function onInputBlur(event) {
|
||||
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) {
|
||||
log("XXX we return");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (document.currentPopupMenu)
|
||||
hideMenu(document.currentPopupMenu);
|
||||
|
||||
if (this.isList) {
|
||||
resolveListAttendees(this, false);
|
||||
} else {
|
||||
checkAttendee(this);
|
||||
}
|
||||
|
||||
attendeesEditor.currentField = null;
|
||||
}
|
||||
|
||||
function displayFreeBusyForNode(input) {
|
||||
@@ -407,36 +533,33 @@ function displayFreeBusyForNode(input) {
|
||||
var nodes = $("freeBusyData").tBodies[0].rows[rowIndex].cells;
|
||||
log ("displayFreeBusyForNode index " + rowIndex + " (" + nodes.length + " cells)");
|
||||
if (input.uid) {
|
||||
if (document.contactFreeBusyAjaxRequest) { log ("busy -- delay " + rowIndex);
|
||||
awaitingFreeBusyRequests.push(input); }
|
||||
else {
|
||||
for (var i = 0; i < nodes.length; i++) {
|
||||
$(nodes[i]).removeClassName("noFreeBusy");
|
||||
$(nodes[i]).innerHTML = ('<span class="freeBusyZoneElement"></span>'
|
||||
+ '<span class="freeBusyZoneElement"></span>'
|
||||
+ '<span class="freeBusyZoneElement"></span>'
|
||||
+ '<span class="freeBusyZoneElement"></span>');
|
||||
for (var i = 0; i < nodes.length; i++) {
|
||||
var node = $(nodes[i]);
|
||||
node.removeClassName("noFreeBusy");
|
||||
while (node.firstChild) {
|
||||
node.removeChild(node.firstChild);
|
||||
}
|
||||
for (var j = 0; j < 4; j++) {
|
||||
createElement("span", null, "freeBusyZoneElement",
|
||||
null, null, node);
|
||||
}
|
||||
// if (document.contactFreeBusyAjaxRequest) {
|
||||
// // Abort any pending request
|
||||
// document.contactFreeBusyAjaxRequest.aborted = true;
|
||||
// document.contactFreeBusyAjaxRequest.abort();
|
||||
// }
|
||||
var sd = $('startTime_date').valueAsShortDateString();
|
||||
var ed = $('endTime_date').valueAsShortDateString();
|
||||
var urlstr = ( UserFolderURL + "../" + input.uid
|
||||
+ "/freebusy.ifb/ajaxRead?"
|
||||
+ "sday=" + sd + "&eday=" + ed + "&additional=" +
|
||||
additionalDays ); log (urlstr);
|
||||
document.contactFreeBusyAjaxRequest
|
||||
= triggerAjaxRequest(urlstr,
|
||||
updateFreeBusyDataCallback,
|
||||
input);
|
||||
}
|
||||
var sd = $('startTime_date').valueAsShortDateString();
|
||||
var ed = $('endTime_date').valueAsShortDateString();
|
||||
var urlstr = (UserFolderURL + "../" + input.uid
|
||||
+ "/freebusy.ifb/ajaxRead?"
|
||||
+ "sday=" + sd + "&eday=" + ed + "&additional=" +
|
||||
additionalDays);
|
||||
triggerAjaxRequest(urlstr,
|
||||
updateFreeBusyDataCallback,
|
||||
input);
|
||||
} else {
|
||||
for (var i = 0; i < nodes.length; i++) {
|
||||
$(nodes[i]).addClassName("noFreeBusy");
|
||||
$(nodes[i]).update();
|
||||
var node = $(nodes[i]);
|
||||
node.addClassName("noFreeBusy");
|
||||
while (node.firstChild) {
|
||||
node.removeChild(node.firstChild);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -467,15 +590,12 @@ function updateFreeBusyDataCallback(http) {
|
||||
var slots = http.responseText.split(",");
|
||||
var rowIndex = input.parentNode.parentNode.sectionRowIndex;
|
||||
var nodes = $("freeBusyData").tBodies[0].rows[rowIndex].cells;
|
||||
log ("received " + slots.length + " slots for " + rowIndex + " with " + nodes.length + " cells");
|
||||
// log ("received " + slots.length + " slots for " + rowIndex + " with " + nodes.length + " cells");
|
||||
for (var i = 0; i < slots.length; i++) {
|
||||
if (slots[i] != '0')
|
||||
setSlot(nodes, i, slots[i]);
|
||||
}
|
||||
}
|
||||
document.contactFreeBusyAjaxRequest = null;
|
||||
if (awaitingFreeBusyRequests.length > 0) { log ("1");
|
||||
displayFreeBusyForNode(awaitingFreeBusyRequests.shift()); }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -484,8 +604,8 @@ function resetAllFreeBusys() {
|
||||
var inputs = table.getElementsByTagName("input");
|
||||
|
||||
for (var i = 0; i < inputs.length - 1; i++) {
|
||||
var currentInput = inputs[i]; log ("reset fb " + currentInput.uid);
|
||||
currentInput.hasfreebusy = false; log ("2");
|
||||
var currentInput = inputs[i];
|
||||
currentInput.hasfreebusy = false;
|
||||
displayFreeBusyForNode(currentInput);
|
||||
}
|
||||
}
|
||||
@@ -626,8 +746,8 @@ function onEditorOkClick(event) {
|
||||
if (inputs[i].uid)
|
||||
uid = inputs[i].uid;
|
||||
if (!(name && name.length > 0))
|
||||
if (inputs[i].uid)
|
||||
name = inputs[i].uid;
|
||||
if (uid.length > 0)
|
||||
name = uid;
|
||||
else
|
||||
name = email;
|
||||
var attendee = attendees["email"];
|
||||
@@ -791,7 +911,6 @@ function prepareAttendees() {
|
||||
|
||||
attendees.keys().each(function(atKey) {
|
||||
var attendee = attendees.get(atKey);
|
||||
// attendee = $H(attendee);
|
||||
var row = $(modelAttendee.cloneNode(true));
|
||||
tbodyAttendees.insertBefore(row, newAttendeeRow);
|
||||
row.removeClassName("attendeeModel");
|
||||
@@ -822,13 +941,14 @@ function prepareAttendees() {
|
||||
value = "";
|
||||
value += "<" + attendee["email"] + ">";
|
||||
input.value = value;
|
||||
if (uid)
|
||||
input.uid = uid;
|
||||
input.uid = attendee["uid"];
|
||||
input.cname = attendee["cname"];
|
||||
input.setAttribute("name", "");
|
||||
input.setAttribute("modified", "0");
|
||||
input.observe("blur", checkAttendee);
|
||||
input.observe("keydown", onContactKeydown);
|
||||
|
||||
input.modified = false;
|
||||
input.observe("blur", onInputBlur);
|
||||
input.observe("keydown", onContactKeydown.bindAsEventListener(input)
|
||||
);
|
||||
|
||||
row = $(modelData.cloneNode(true));
|
||||
tbodyData.insertBefore(row, newDataRow);
|
||||
row.removeClassName("dataModel");
|
||||
@@ -838,7 +958,7 @@ function prepareAttendees() {
|
||||
|
||||
// Activate "Add attendee" button
|
||||
var links = tableAttendees.select("TR.futureAttendee TD A");
|
||||
links.first().observe("click", newAttendee);
|
||||
links.first().observe("click", onNewAttendeeClick);
|
||||
}
|
||||
|
||||
function onWindowResize(event) {
|
||||
@@ -934,7 +1054,7 @@ function initTimeWidgets(widgets) {
|
||||
function onAdjustTime(event) {
|
||||
var endDate = window.getEndDate();
|
||||
var startDate = window.getStartDate();
|
||||
if ($(this).readAttribute("id").startsWith("start")) {
|
||||
if (this.id.startsWith("start")) {
|
||||
// Start date was changed
|
||||
var delta = window.getShadowStartDate().valueOf() -
|
||||
startDate.valueOf();
|
||||
|
||||
Reference in new issue
Block a user