From 7794d716b983992251492f26bcf3ff07edbd3b5a Mon Sep 17 00:00:00 2001 From: Alexandre Cloutier Date: Wed, 6 Aug 2014 14:49:36 -0400 Subject: [PATCH 01/12] version 1 of the inbox search --- UI/MailerUI/GNUmakefile | 1 + UI/MailerUI/Toolbars/SOGoMailFolder.toolbar | 7 + UI/MailerUI/UIxMailListActions.m | 117 ++++--- UI/MailerUI/UIxMailMainFrame.m | 11 + UI/MailerUI/UIxMailSearch.h | 29 ++ UI/MailerUI/UIxMailSearch.m | 118 +++++++ UI/MailerUI/product.plist | 4 + UI/Templates/MailerUI/UIxMailMainFrame.wox | 4 +- UI/Templates/MailerUI/UIxMailSearch.wox | 112 ++++++ UI/WebServerResources/MailerUI.js | 74 +++- UI/WebServerResources/SOGoDataTable.js | 3 +- UI/WebServerResources/SOGoMailDataSource.js | 15 +- UI/WebServerResources/UIxMailSearch.css | 95 +++++ UI/WebServerResources/UIxMailSearch.js | 368 ++++++++++++++++++++ UI/WebServerResources/generic.css | 13 + UI/WebServerResources/generic.js | 2 +- 16 files changed, 891 insertions(+), 82 deletions(-) create mode 100644 UI/MailerUI/UIxMailSearch.h create mode 100644 UI/MailerUI/UIxMailSearch.m create mode 100644 UI/Templates/MailerUI/UIxMailSearch.wox create mode 100644 UI/WebServerResources/UIxMailSearch.css create mode 100644 UI/WebServerResources/UIxMailSearch.js diff --git a/UI/MailerUI/GNUmakefile b/UI/MailerUI/GNUmakefile index e354d983f..851eb9abf 100644 --- a/UI/MailerUI/GNUmakefile +++ b/UI/MailerUI/GNUmakefile @@ -23,6 +23,7 @@ MailerUI_OBJC_FILES += \ UIxMailPopupView.m \ UIxMailMoveToPopUp.m \ UIxMailFilterPanel.m \ + UIxMailSearch.m \ \ UIxMailAccountActions.m \ UIxMailFolderActions.m \ diff --git a/UI/MailerUI/Toolbars/SOGoMailFolder.toolbar b/UI/MailerUI/Toolbars/SOGoMailFolder.toolbar index 1c9d1968d..c536a49fc 100644 --- a/UI/MailerUI/Toolbars/SOGoMailFolder.toolbar +++ b/UI/MailerUI/Toolbars/SOGoMailFolder.toolbar @@ -63,5 +63,12 @@ image = "tb-mail-print-flat-24x24.png"; label = "Print"; tooltip = "Print this message"; }, + + { link = "#"; + onclick = "return onSearchMail(event);"; + cssClass = ""; + image = "search-messages.png"; + label = "Search"; + tooltip = "Search inbox"; } ) ) diff --git a/UI/MailerUI/UIxMailListActions.m b/UI/MailerUI/UIxMailListActions.m index 33585e932..5ae707e6c 100644 --- a/UI/MailerUI/UIxMailListActions.m +++ b/UI/MailerUI/UIxMailListActions.m @@ -325,24 +325,33 @@ - (NSString *) imap4SortKey { NSString *sort; + NSDictionary *urlParams, *sortingAttributes; + WORequest *request; - sort = [[context request] formValueForKey: @"sort"]; + request = [context request]; + urlParams = [request contentAsString] objectFromJSONString]; + sortingAttributes = [urlParams objectForKey:@"sortingAttributes"]; + sort = [sortingAttributes objectForKey:@"sort"]; return [sort uppercaseString]; } - (NSString *) imap4SortOrdering { - NSString *sort, *ascending; + NSString *sort; NSString *module; NSMutableDictionary *moduleSettings; + NSDictionary *urlParams, *sortingAttributes; + WORequest *request; BOOL asc; SOGoUser *activeUser; SOGoUserSettings *us; sort = [self imap4SortKey]; - ascending = [[context request] formValueForKey: @"asc"]; - asc = [ascending boolValue]; + request = [context request]; + urlParams = [[request contentAsString] objectFromJSONString]; + sortingAttributes = [urlParams objectForKey:@"sortingAttributes"]; + asc = [[sortingAttributes objectForKey:@"asc"] boolValue]; activeUser = [context activeUser]; module = @"Mail"; @@ -393,68 +402,71 @@ - (EOQualifier *) searchQualifier { - NSString *criteria, *value; - EOQualifier *qualifier; - WORequest *request; - - request = [context request]; - criteria = [request formValueForKey: @"search"]; - value = [request formValueForKey: @"value"]; - qualifier = nil; - if ([value length]) - { - if ([criteria isEqualToString: @"subject"]) - qualifier = [EOQualifier qualifierWithQualifierFormat: - @"(subject doesContain: %@)", value]; - else if ([criteria isEqualToString: @"sender"]) - qualifier = [EOQualifier qualifierWithQualifierFormat: - @"(from doesContain: %@)", value]; - else if ([criteria isEqualToString: @"subject_or_sender"]) - qualifier = [EOQualifier qualifierWithQualifierFormat: - @"((subject doesContain: %@)" - @" OR (from doesContain: %@))", - value, value]; - else if ([criteria isEqualToString: @"to_or_cc"]) - qualifier = [EOQualifier qualifierWithQualifierFormat: - @"((to doesContain: %@)" - @" OR (cc doesContain: %@))", - value, value]; - else if ([criteria isEqualToString: @"entire_message"]) - qualifier = [EOQualifier qualifierWithQualifierFormat: - @"(body doesContain: %@)", value]; - } + EOQualifier *qualifier, *searchQualifier; + WORequest *request; + NSDictionary *filters, *sortingAttributes, *content; + NSString *searchBy, *searchArgument, *searchInput, *searchString, *match; + NSMutableArray *searchArray; + int nbFilters, i; + request = [context request]; + content = [[request contentAsString] objectFromJSONString]; + qualifier = nil; + searchString = nil; + nbFilters = 0; + searchArray = [[NSMutableArray alloc] init]; + + if ([content objectForKey:@"filters"]) + { + filters = [content objectForKey:@"filters"]; + sortingAttributes = [content objectForKey:@"sortingAttributes"]; + nbFilters = [filters count]; + match = [NSString stringWithString:[sortingAttributes objectForKey:@"match"]]; // AND, OR + + for (i = 0; i < nbFilters; i++) + { + searchBy = [NSString stringWithString:[[filters objectAtIndex:i] objectForKey:@"searchBy"]]; + searchArgument = [NSString stringWithString:[[filters objectAtIndex:i] objectForKey:@"searchArgument"]]; + searchInput = [NSString stringWithString:[[filters objectAtIndex:i] objectForKey:@"searchInput"]]; + + searchString = [NSString stringWithFormat:@"(%@ %@: '%@')", searchBy, searchArgument, searchInput]; + searchQualifier = [EOQualifier qualifierWithQualifierFormat:searchString]; + [searchArray addObject:searchQualifier]; + } + if ([match isEqualToString:@"OR"]) + qualifier = [[EOOrQualifier alloc] initWithQualifierArray: searchArray]; + else + qualifier = [[EOAndQualifier alloc] initWithQualifierArray: searchArray]; + + [searchArray release]; + [qualifier autorelease]; + } return qualifier; } - (NSArray *) getSortedUIDsInFolder: (SOGoMailFolder *) mailFolder { EOQualifier *qualifier, *fetchQualifier, *notDeleted; - + if (!sortedUIDs) { - notDeleted = [EOQualifier qualifierWithQualifierFormat: - @"(not (flags = %@))", - @"deleted"]; + notDeleted = [EOQualifier qualifierWithQualifierFormat: @"(not (flags = %@))", @"deleted"]; qualifier = [self searchQualifier]; if (qualifier) - { - fetchQualifier = [[EOAndQualifier alloc] initWithQualifiers: - notDeleted, qualifier, - nil]; - [fetchQualifier autorelease]; - } + { + fetchQualifier = [[EOAndQualifier alloc] initWithQualifiers: notDeleted, qualifier, nil]; + [fetchQualifier autorelease]; + } else - fetchQualifier = notDeleted; - - sortedUIDs - = [mailFolder fetchUIDsMatchingQualifier: fetchQualifier - sortOrdering: [self imap4SortOrdering] - threaded: sortByThread]; - + fetchQualifier = notDeleted; + + sortedUIDs = [mailFolder fetchUIDsMatchingQualifier: fetchQualifier + sortOrdering: [self imap4SortOrdering] + threaded: sortByThread]; + [sortedUIDs retain]; } - + return sortedUIDs; } @@ -681,6 +693,7 @@ response = [context response]; [response setHeader: @"text/plain; charset=utf-8" forKey: @"content-type"]; + folder = [self clientObject]; noHeaders = [request formValueForKey: @"no_headers"]; diff --git a/UI/MailerUI/UIxMailMainFrame.m b/UI/MailerUI/UIxMailMainFrame.m index d87fa20af..d94f90aae 100644 --- a/UI/MailerUI/UIxMailMainFrame.m +++ b/UI/MailerUI/UIxMailMainFrame.m @@ -119,6 +119,17 @@ return [names jsonRepresentation]; } +- (NSString *) userNames +{ + NSArray *accounts, *userNames; + + accounts = [[self clientObject] mailAccounts]; + userNames = [accounts objectsForKey: @"userName" notFoundMarker: nil]; + + return [userNames jsonRepresentation]; + +} + - (NSString *) pageFormURL { NSString *u; diff --git a/UI/MailerUI/UIxMailSearch.h b/UI/MailerUI/UIxMailSearch.h new file mode 100644 index 000000000..8eb7b03ba --- /dev/null +++ b/UI/MailerUI/UIxMailSearch.h @@ -0,0 +1,29 @@ +/* UIxMailSearch.h - this file is part of SOGo + * + * Copyright (C) 2006-2014 Inverse inc. + * + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +@interface UIxMailSearch : UIxComponent +{ + id item; + +} +@end \ No newline at end of file diff --git a/UI/MailerUI/UIxMailSearch.m b/UI/MailerUI/UIxMailSearch.m new file mode 100644 index 000000000..3de88e00d --- /dev/null +++ b/UI/MailerUI/UIxMailSearch.m @@ -0,0 +1,118 @@ +/* UIxMailSearch.m - this file is part of SOGo + * + * Copyright (C) 2006-2014 Inverse inc. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#import +#import +#import + +#import +#import +#import + +#import + +@implementation UIxMailSearch + +- (id) init +{ + item = nil; + + return self; +} + +- (void) dealloc +{ + [item release]; +} + +- (void) setItem: (NSString *) newItem +{ + ASSIGN(item, newItem); +} + +- (NSString *) item +{ + return item; +} + +- (NSArray *) mailAccountsList +{ + SOGoMailAccount *co, *accountFolder; + SOGoMailAccounts *accountsFolder; + SOGoUserFolder *userFolder; + NSString *userName, *option, *lookup; + NSArray *folders; + NSMutableArray *mailboxes; + NSDictionary *mailAccount; + int nbMailboxes, nbMailAccounts, i, j; + + + userFolder = [[context activeUser] homeFolderInContext: context]; + accountsFolder = [userFolder lookupName: @"Mail" inContext: context acquire: NO]; + nbMailAccounts = [[accountsFolder mailAccounts] count]; + + mailboxes = [[NSMutableArray alloc] init]; + for (i = 0; i < nbMailAccounts; i++) + { + mailAccount = [[[accountsFolder mailAccounts] objectAtIndex:i] objectForKey:@"name"]; // Keys on this account = (name, port, encryption, mailboxes, serverName, identities, userName) + userName = [[[accountsFolder mailAccounts] objectAtIndex:i] objectForKey:@"userName"]; + lookup = [NSString stringWithFormat:@"%i", i]; + accountFolder = [accountsFolder lookupName:lookup inContext: context acquire: NO]; + folders = [accountFolder allFoldersMetadata]; + nbMailboxes = [folders count]; + [mailboxes addObject:mailAccount]; + for (j = 0; j < nbMailboxes; j++) + { + option = [NSString stringWithFormat:@"%@%@", userName, [[folders objectAtIndex:j] objectForKey:@"displayName"]]; + [mailboxes addObject:option]; + } + } + return mailboxes; + [mailboxes release]; +} + +// +// The objective here is to return the parent view layout and select the print +// layout corresponding. Default print view: list view +/* +- (NSString *) mailAccountSelected +{ + SOGoUser *activeUser; + NSString *parentView; + + activeUser = [context activeUser]; + us = [activeUser userSettings]; + parentView = [[us objectForKey:@"Calendar"] objectForKey:@"View" ]; + + if ([parentView isEqualToString:@"dayview"]) + return @"Daily"; + + else if ([parentView isEqualToString:@"weekview"]) + return @"Weekly"; + + else if ([parentView isEqualToString:@"multicolumndayview"]) + return @"Multi-Columns"; + + else + return @"LIST"; +} +*/ + +@end \ No newline at end of file diff --git a/UI/MailerUI/product.plist b/UI/MailerUI/product.plist index 8b9ed30cb..4956cf286 100644 --- a/UI/MailerUI/product.plist +++ b/UI/MailerUI/product.plist @@ -327,6 +327,10 @@ pageName = "UIxMailMainFrame"; actionName = "saveColumnsState"; }; + search = { + protectedBy = "View"; + pageName = "UIxMailSearch"; + }; }; }; diff --git a/UI/Templates/MailerUI/UIxMailMainFrame.wox b/UI/Templates/MailerUI/UIxMailMainFrame.wox index 6e83548a6..b796d8ad3 100644 --- a/UI/Templates/MailerUI/UIxMailMainFrame.wox +++ b/UI/Templates/MailerUI/UIxMailMainFrame.wox @@ -9,9 +9,11 @@ title="title" const:userDefaultsKeys="SOGoMailMessageCheck,SOGoMailSortByThreads,SOGoMailListViewColumnsOrder,SOGoMailDisplayRemoteInlineImages" const:userSettingsKeys="Mail" - const:jsFiles="dtree.js,MailerUIdTree.js,SOGoAutoCompletion.js,SOGoResizableTable.js,SOGoMailDataSource.js,SOGoDataTable.js,jquery-ui.js"> + const:jsFiles="dtree.js,MailerUIdTree.js,SOGoAutoCompletion.js,SOGoResizableTable.js,SOGoMailDataSource.js,SOGoDataTable.js,jquery-ui.js, UIxMailSearch.js" + const:cssFiles="UIxMailSearch.css"> diff --git a/UI/Templates/MailerUI/UIxMailSearch.wox b/UI/Templates/MailerUI/UIxMailSearch.wox new file mode 100644 index 000000000..2e77b13e3 --- /dev/null +++ b/UI/Templates/MailerUI/UIxMailSearch.wox @@ -0,0 +1,112 @@ + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + +
+
+ +
+
+
+ + + + +
+
+ + + +
+
+ + + +
+ + + + + + + + + + + + + + + +
+ + + + + +
+
+ + + + +
+
diff --git a/UI/WebServerResources/MailerUI.js b/UI/WebServerResources/MailerUI.js index 2df20dd8b..e08440f38 100644 --- a/UI/WebServerResources/MailerUI.js +++ b/UI/WebServerResources/MailerUI.js @@ -432,6 +432,38 @@ function onDocumentKeydown(event) { } } +/* Search mail, call the template and open inside a dialog windoƒw */ +function onSearchMail(event) { + if ($("searchMailView")) { + $("searchMailView").style.display = "block"; + $("bgDialogDiv").style.display = "block"; + initSearchMailView(); + } + else { + var urlstr = ApplicationBaseURL + "/search"; + + // Return the template for the searchMail feature + triggerAjaxRequest(urlstr, displaySearchMailCallback); + } +} + +function displaySearchMailCallback(http) { + if (http.readyState == 4 && http.status == 200) { + var fields = createElement("div", null); // (tagName, id, classes, attributes, htmlAttributes, parentNode) + var title = _("Search mail"); + var id = _("searchMailView"); + fields.innerHTML = http.responseText; + + dialog = createDialog(id, title, null, fields, "searchMail"); // (id, title, legend, content, positionClass) + document.body.appendChild(dialog); + + if (Prototype.Browser.IE) + jQuery('#bgDialogDiv').css('opacity', 0.4); + jQuery(dialog).fadeIn('fast'); + initSearchMailView(); + } +} + /* bulk delete of messages */ function deleteSelectedMessages(sender) { @@ -780,7 +812,7 @@ function composeNewMessage() { function openMailbox(mailbox, reload) { if (mailbox != Mailer.currentMailbox || reload) { var url = ApplicationBaseURL + encodeURI(mailbox.unescapeHTML()); - var urlParams = new Hash(); + var urlParams = {}; if (!reload) { var messageContent = $("messageContent"); @@ -791,13 +823,28 @@ function openMailbox(mailbox, reload) { var searchValue = search["mail"]["value"]; if (searchValue && searchValue.length > 0) { - urlParams.set("search", search["mail"]["criteria"]); - urlParams.set("value", escape(searchValue.utf8encode())); + var searchCriteria = []; + if (search["mail"]["criteria"] == "subject") + searchCriteria.push("subject"); + else if (search["mail"]["criteria"] == "sender") + searchCriteria.push("from"); + else if (search["mail"]["criteria"] == "subject_or_sender") + searchCriteria.push("subject", "from"); + else if (search["mail"]["criteria"] == "to_or_cc") + searchCriteria.push("to", "cc"); + else if (search["mail"]["criteria"] == "entire_message") + searchCriteria.push("body"); + + var filters = []; + for (i = 0; i < searchCriteria.length; i++) + filters.push({"searchBy": searchCriteria[i], "searchArgument": "doesContain", "searchInput": searchValue}); + + urlParams.filters = filters; } var sortAttribute = sorting["attribute"]; if (sortAttribute && sortAttribute.length > 0) { - urlParams.set("sort", sorting["attribute"]); - urlParams.set("asc", sorting["ascending"]); + var sortingAttributes = {"sort":sorting["attribute"], "asc":sorting["ascending"], "match":"OR"}; + urlParams.sortingAttributes = sortingAttributes; var sortHeader = $(sorting["attribute"] + "Header"); if (sortHeader) { @@ -816,18 +863,15 @@ function openMailbox(mailbox, reload) { var messageList = $("messageListBody").down('TBODY'); var key = mailbox; - if (urlParams.keys().length > 0) { - var p = urlParams.keys().collect(function(key) { return key + "=" + urlParams.get(key); }).join("&"); - key += "?" + p; - } if (reload) { // Don't change data source, only query UIDs from server and refresh // the view. Cases that end up here: // - performed a search // - clicked on Get Mail button - urlParams.set("no_headers", "1"); - Mailer.dataTable.load(urlParams); + urlParams.sortingAttributes.no_headers= "1"; + var content = Object.toJSON(urlParams); + Mailer.dataTable.load(content); Mailer.dataTable.refresh(); } else { @@ -843,7 +887,8 @@ function openMailbox(mailbox, reload) { } else // Fetch UIDs and headers from server - dataSource.load(urlParams); + var content = Object.toJSON(urlParams); + dataSource.load(content); // Cache data source Mailer.dataSources.set(key, dataSource); // Update unseen count @@ -851,8 +896,9 @@ function openMailbox(mailbox, reload) { } else { // Data source is cached, query only UIDs from server - urlParams.set("no_headers", "1"); - dataSource.load(urlParams); + urlParams.sortingAttributes.no_headers= "1"; + var content = Object.toJSON(urlParams); + dataSource.load(content); } // Associate data source with data table and render the view Mailer.dataTable.setSource(dataSource); diff --git a/UI/WebServerResources/SOGoDataTable.js b/UI/WebServerResources/SOGoDataTable.js index fed13db47..ee04b19f7 100644 --- a/UI/WebServerResources/SOGoDataTable.js +++ b/UI/WebServerResources/SOGoDataTable.js @@ -118,8 +118,7 @@ var SOGoDataTableInterface = { load: function(urlParams) { if (!this.dataSource) return; // log ("DataTable.load() with parameters [" + urlParams.keys().join(' ') + "]"); - if (Object.isHash(urlParams) && urlParams.keys().length > 0) this.dataSource.load(urlParams); - else this.dataSource.load(new Hash()); + this.dataSource.load(urlParams); }, visibleRowCount: function() { diff --git a/UI/WebServerResources/SOGoMailDataSource.js b/UI/WebServerResources/SOGoMailDataSource.js index c587b2982..7826ffe32 100644 --- a/UI/WebServerResources/SOGoMailDataSource.js +++ b/UI/WebServerResources/SOGoMailDataSource.js @@ -72,22 +72,13 @@ SOGoMailDataSource = Class.create({ // log ("MailDataSource.init() " + this.uids.length + " UIDs, " + this.cache.keys().length + " headers"); }, - load: function(urlParams) { - var params; + load: function(content) { this.loaded = false; - if (urlParams.keys().length > 0) { - params = urlParams.keys().collect(function(key) { return key + "=" + urlParams.get(key); }).join("&"); - } - else - params = ""; - this.id = this.url + "?" + params; - -// log ("MailDataSource.load() " + params); triggerAjaxRequest(this.url + "/uids", this._loadCallback.bind(this), null, - params, - { "Content-type": "application/x-www-form-urlencoded" }); + content, + { "content-type": "application/json" }); }, _loadCallback: function(http) { diff --git a/UI/WebServerResources/UIxMailSearch.css b/UI/WebServerResources/UIxMailSearch.css new file mode 100644 index 000000000..80969374d --- /dev/null +++ b/UI/WebServerResources/UIxMailSearch.css @@ -0,0 +1,95 @@ + +/*************** Table adjustment *****************/ + +TABLE#searchMailHeader, TABLE#searchFiltersList, TABLE#searchMailFooter +{ width: 100%; } + +TABLE#searchFiltersList, TABLE#searchMailFooter +{ + border: 1px solid #909090; + margin-top: 1em; + padding:2px; + border-radius: 3px; +} + +TABLE#searchFiltersList +{ + display:block; + max-height:100px; + overflow:auto; + width:672px; +} + +TABLE#searchMailFooter +{ + height:141px; + min-height: 110px; +} + +.buttonsCell +{ + width:1%; +} + +.inputsCell +{ + width:45%; +} + +.filterRow +{ + cellspacing=0; +} + +.scrollbar +{ + overflow-y:auto; + height:106px; + width:676px; + position:absolute; +} + +/*************** Table adjustment : search results *****************/ +.resultsRow { + cursor:pointer; +} + +/*************** Button adjustment *****************/ + +#headerButtons +{ + width:27%; +} + +#searchButton, #cancelButton +{ + margin-top:0; +} + +.searchByList, .searchArgumentsList, .searchInput +{ + width:100%; +} + +DIV#optionsButtons +{ float:left; } + +.button +{ + font-style:normal; +} + +#changeHeader +{ width:15px} + +DIV.bottomToolbar { + margin:0; + position:relative; + border-radius:5px; + width:40px; +} + +/*************** Lists *****************/ +.hidden +{ display:none; } + diff --git a/UI/WebServerResources/UIxMailSearch.js b/UI/WebServerResources/UIxMailSearch.js new file mode 100644 index 000000000..e9c3245e0 --- /dev/null +++ b/UI/WebServerResources/UIxMailSearch.js @@ -0,0 +1,368 @@ +/* -*- Mode: js2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +var searchParams = { + searchLocation: "", + subfolder: true, + filterMatching: "AND", + filters: [] +}; + +// This variable allowed the user to stop the ongoing search +var stopOngoingSearch = false; + +/************ Search mail header ************/ + +function onSearchClick() { +// This function updates the searchParams + var filterRows = $$(".filterRow"); + var searchButton = $("searchButton").down().innerText; + var mailAccountsList = $("mailAccountsList").options; + + if (searchButton == _("Search")) { + searchParams.filters = []; + stopOngoingSearch = false; + + // Get the mailboxe(s) + for (i = 0; i < mailAccountsList.length ; i++) { + if (mailAccountsList[i].selected) { + searchParams.searchLocation = mailAccountsList[i].innerText; + break; + } + } + + for (i = 0; i < filterRows.length; i++){ + // Get the information from every filter row before triggering the AJAX call + var filter = {}; + var searchByOptions = filterRows[i].down(".searchByList").options; + var searchArgumentsOptions = filterRows[i].down(".searchArgumentsList").options; + var searchInput = filterRows[i].down(".searchInput"); + + // Get the searchBy + for (j = 0; j < searchByOptions.length ; j++) { + if (searchByOptions[j].selected) { + filter.searchBy = searchByOptions[j].innerText; + break; + } + } + + // Get the searchArgument + for (j = 0; j < searchArgumentsOptions.length ; j++) { + if (searchArgumentsOptions[j].selected) { + filter.searchArgument = searchArgumentsOptions[j].innerText; + if (filter.searchArgument == "contains") + filter.searchArgument = "doesContain"; + else + filter.searchArgument = "NOT doesContain"; + break; + } + } + + // Get the input text + filter.searchInput = searchInput.getValue(); + + // Add the filter inside the searchParams.filters if the input is not empty + if (!filter.searchInput.empty()) + searchParams.filters.push(filter); + } + // Send the request only if there is at least one filter + if (searchParams.filters.length > 0) { + $("searchButton").down().innerText = _("Stop"); + searchMails(); + } + // TODO - give the user a warning or a notice that it needs at least one filter + } + else { + stopOngoingSearch = true; + $("searchButton").down().innerText = _("Search"); + } +} + +function searchMails() { + // Variables for the subfolders search + var optionsList = $("mailAccountsList").options; + var nbOptions = optionsList.length; + var selectedIndex = optionsList.selectedIndex; + + var mailAccountIndex = mailAccounts.indexOf(searchParams.searchLocation); + if (mailAccountIndex != -1) { + var accountNumber = "/" + mailAccountIndex; + var folderName = accountNumber + "/folderINBOX"; + var accountUser = userNames[mailAccountIndex]; + var folderPath = accountUser; + } + else { + var searchLocation = searchParams.searchLocation.split("/"); + var accountUser = searchLocation[0]; + var accountNumber = "/" + userNames.indexOf(accountUser); + + var position = searchLocation.length; + var folderName = accountNumber + "/folder" + searchLocation[1]; + for (i = 2; i < position; i++) + folderName += accountNumber + "/folder" + searchLocation[i]; + + var folderPath = optionsList[selectedIndex].innerText; + + } + + var subfolders = []; + if (searchParams.subfolder == true) { + for (i = 0; i < nbOptions; i++) { + if ((optionsList[i].innerText.search(folderPath) != -1) && (i != selectedIndex)) { + var splitArray = optionsList[i].innerText.split("/"); + // Remove the user information since it is not required + splitArray.splice(0, 1); + var subfolder = []; + var level = splitArray.length; + for(j = 0; j < level; j++) { + subfolder += "/folder" + splitArray[j]; + } + subfolders.push(accountNumber + subfolder); + } + } + } + + var urlstr = (ApplicationBaseURL + folderName + "/uids"); + + var callbackData = {"folderName" : folderName, "subfolders" : subfolders, "newSearch" : true}; + var object = {"filters":searchParams.filters, "sortingAttributes":{"match":searchParams.filterMatching}}; + var content = Object.toJSON(object); + document.searchMailsAjaxRequest = triggerAjaxRequest(urlstr, searchMailsCallback, callbackData, content, {"content-type": "application/json"}); + +} + +function searchMailsCallback(http) { + if (http.readyState == 4 && http.status == 200 && !stopOngoingSearch) { + var response = http.responseText.evalJSON(); + var table = $("searchMailFooter").down("tbody"); + + // Erase all previous entries before proceeding with the current request + if (http.callbackData.newSearch) { + var oldEntries = table.rows; + var count = oldEntries.length - 1; + for (x = count; x >= 0; x--) + oldEntries[x].remove(); + } + + // ["To", "Attachment", "Flagged", "Subject", "From", "Unread", "Priority", "Date", "Size", "rowClasses", "labels", "rowID", "uid"] + if (response.headers.length > 1) { + if ($("noSearchResults")) + $("noSearchResults").remove(); + + for (i = 1; i < response.headers.length; i++) { // Starts at 1 because the position 0 in the array are the headers of the table + var row = table.insertRow(i - 1); // This is the reason why row inserting starts at i - 1 + Element.addClassName(row, "resultsRow"); + row.writeAttribute("uid", response.headers[i][12]); + row.writeAttribute("folderName", http.callbackData.folderName); + + var cell1 = row.insertCell(0); + cell1.innerHTML = response.headers[i][3]; + + var cell2 = row.insertCell(1); + cell2.innerHTML = response.headers[i][4]; + + var cell3 = row.insertCell(2); + cell3.innerHTML = response.headers[i][7]; + + var cell4 = row.insertCell(3); + cell4.innerHTML = response.headers[i][12]; + } + + } + else if (http.callbackData.newSearch) { + if (!table.down("tr")) { + var row = table.insertRow(0); + var cell = row.insertCell(0); + var element = document.createElement("span"); + + cell.writeAttribute("id", "noSearchResults"); + cell.writeAttribute("colspan", "4"); + element.innerText = _("No matches found"); + cell.appendChild(element); + } + } + + if (http.callbackData.subfolders.length > 0) { + var folderName = http.callbackData.subfolders[0]; + var subfolders = http.callbackData.subfolders; + subfolders.splice(0, 1); + + var urlstr = (ApplicationBaseURL + folderName + "/uids"); + var callbackData = {"folderName" : folderName, "subfolders" : subfolders, "newSearch" : false}; + + // TODO - need to add these following contents ; asc, no-headers, sort + var object = {"filters":searchParams.filters, "sortingAttributes":{"match":searchParams.filterMatching}}; + var content = Object.toJSON(object); + document.searchMailsAjaxRequest = triggerAjaxRequest(urlstr, searchMailsCallback, callbackData, content, {"content-type": "application/json"}); + } + else { + $("searchButton").down().innerText = _("Search"); + } + + } +} + +function onCancelClick() { + disposeDialog(); + $("searchMailView").remove(); +} + +function onSearchSubfoldersCheck(event) { + searchParams.subfolder = (event.checked ? true : false); +} + +function onMatchFilters(event) { + searchParams.filterMatching = ((event.getAttribute("id") == "matchAllFilters") ? "AND" : "OR"); +} + +/**** Search mail body ****/ + +function onAddFilter() { + var table = $("searchFiltersList").down("tbody"); + var searchByList = $("searchByList").getElementsByTagName("li"); + var stringArgumentsList = $("stringArgumentsList").getElementsByTagName("li"); + + var rowCount = table.rows.length; + var row = table.insertRow(rowCount); + Element.addClassName(row, "filterRow"); + + var cell1 = row.insertCell(0); + var element1 = document.createElement("select"); + Element.addClassName(element1, "searchByList"); + element1.writeAttribute("id", "searchByListRow" + rowCount); + for (i = 0; i < searchByList.length; i++) { + var option = document.createElement("option"); + option.writeAttribute("value", i); + option.innerHTML = searchByList[i].innerText; + element1.appendChild(option); + } + cell1.appendChild(element1); + + var cell2 = row.insertCell(1); + var element2 = document.createElement("select"); + Element.addClassName(element2, "searchArgumentsList"); + element2.writeAttribute("id", "searchArgumentsListRow" + rowCount); + for (i = 0; i < stringArgumentsList.length; i++) { + var option = document.createElement("option"); + option.writeAttribute("value", i); + option.innerHTML = stringArgumentsList[i].innerText; + element2.appendChild(option); + } + cell2.appendChild(element2); + + var cell3 = row.insertCell(2); + Element.addClassName(cell3, "inputsCell"); + var element3 = document.createElement("input"); + Element.addClassName(element3, "searchInput"); + element3.writeAttribute("type", "text"); + element3.writeAttribute("name", "searchInput"); + element3.writeAttribute("value", ""); + element3.writeAttribute("id", "searchInputRow" + rowCount); + cell3.appendChild(element3); + + var cell4 = row.insertCell(3); + Element.addClassName(cell4, "buttonsCell"); + var element4 = document.createElement("a"); + var element5 = document.createElement("a"); + var buttonsDiv = document.createElement("div"); + var spanAddFilter = document.createElement("span"); + var imageAddFilter = document.createElement("img"); + var spanRemoveFilter = document.createElement("span"); + var imageRemoveFilter = document.createElement("img"); + Element.addClassName(element4, "addFilterButton"); + Element.addClassName(buttonsDiv, "bottomToolbar"); + element4.writeAttribute("name", "addFilter"); + element4.writeAttribute("id", "addFilterButtonRow" + rowCount); + element4.writeAttribute("onclick", "onAddFilter(this)"); + imageAddFilter.writeAttribute("src", "/SOGo.woa/WebServerResources/add-icon.png"); + spanAddFilter.appendChild(imageAddFilter); + element4.appendChild(spanAddFilter); + buttonsDiv.appendChild(element4); + + Element.addClassName(element5, "removeFilterButton"); + element5.writeAttribute("name", "removeFilter"); + element5.writeAttribute("id", "removeFilterButtonRow" + rowCount); + element5.writeAttribute("onclick", "onRemoveFilter(this)"); + imageRemoveFilter.writeAttribute("src", "/SOGo.woa/WebServerResources/remove-icon.png"); + spanRemoveFilter.appendChild(imageRemoveFilter); + element5.appendChild(spanRemoveFilter); + buttonsDiv.appendChild(element5); + cell4.appendChild(buttonsDiv); + +} + +function onRemoveFilter(event) { + var rows = $("searchFiltersList").down("tbody").getElementsByTagName("tr"); + var currentRow = event.up(".filterRow"); + + if(rows.length > 1) + currentRow.remove(); +} + +/**** Search mail Footer ****/ + +function onResultSelectionChange(event) { + var table = $("searchMailFooter").down("tbody"); + + if (event && (event.target.innerText != _("No matches found"))) { + var node = getTarget(event); + + if (node.tagName == "SPAN") + node = node.parentNode; + + // Update rows selection + onRowClick(event, node); + } +} + +/**** Search mail optionsButtons ****/ + +function onOpenClick(event) { +// This function is linked with the openButton and the doubleClick on a message + var selectedRow = $("searchMailFooter").down("._selected"); + var msguid = selectedRow.getAttribute("uid"); + var folderName = selectedRow.getAttribute("folderName"); + + var url = "/SOGo/so/sogo1/Mail" + folderName + "/" + msguid + "/popupview"; + if (selectedRow) { + openMessageWindow(msguid, url); + } +} + +function onDeleteClick(event) { + console.debug("deleteButton"); +} + +function onResizeClick() { + var resizeAttrribute = $("resizeButton").getAttribute("name"); + if (resizeAttrribute == "resizeUp") { + $("searchFiltersList").style.display = "none"; + $("searchMailFooter").style.height = "300px"; + $("resultsTable").style.height = "265px"; + $("resizeUp").style.display = "none"; + $("resizeDown").style.display = "block"; + $("resizeButton").writeAttribute("name", "resizeDown"); + } + else { + $("searchFiltersList").style.display = "block"; + $("searchMailFooter").style.height = "141px"; + $("resultsTable").style.height = "106px"; + $("resizeUp").style.display = "block"; + $("resizeDown").style.display = "none"; + $("resizeButton").writeAttribute("name", "resizeUp"); + } + +} + +/*************** Init ********************/ + +function initSearchMailView () { + + // Add one filterRow + onAddFilter(); + + // Observers : Event.on(element, eventName[, selector], callback) + $("searchMailFooter").down("tbody").on("mousedown", "tr", onResultSelectionChange); + $("searchMailFooter").down("tbody").on("dblclick", "tr", onOpenClick); + + +} \ No newline at end of file diff --git a/UI/WebServerResources/generic.css b/UI/WebServerResources/generic.css index 64dd2dd35..736d556d4 100644 --- a/UI/WebServerResources/generic.css +++ b/UI/WebServerResources/generic.css @@ -658,6 +658,19 @@ DIV.dialog > DIV top: 7px; } +DIV.dialog.searchMail { + position: relative; + margin: 0px; + padding: 0px; + opacity: 1; + width: 700px; + margin: 100px auto; +} + +DIV.dialog.searchMail > DIV { + padding: 10px; +} + DIV.dialog.none { position: relative; margin: 0px; diff --git a/UI/WebServerResources/generic.js b/UI/WebServerResources/generic.js index 1c45ddd15..f51d0b0a4 100644 --- a/UI/WebServerResources/generic.js +++ b/UI/WebServerResources/generic.js @@ -1998,7 +1998,7 @@ function createDialog(id, title, legend, content, positionClass) { var newDialog = createElement("div", id, ["dialog", positionClass]); newDialog.setStyle({"display": "none"}); - if (positionClass == "none") { + if (positionClass == "none" || positionClass == "searchMail") { var bgDiv = $("bgDialogDiv"); if (bgDiv) { bgDiv.show(); From c3e46e4bafd6e26ec417927f10cf0c88180b7786 Mon Sep 17 00:00:00 2001 From: Alexandre Cloutier Date: Mon, 11 Aug 2014 09:25:09 -0400 Subject: [PATCH 02/12] code refactoring and GUI improvement --- UI/MailerUI/UIxMailListActions.m | 14 ++- UI/Templates/MailerUI/UIxMailSearch.wox | 56 +++------ UI/WebServerResources/UIxMailSearch.css | 147 +++++++++++++++++++++--- UI/WebServerResources/UIxMailSearch.js | 120 +++++++++++-------- UI/WebServerResources/generic.css | 7 +- 5 files changed, 231 insertions(+), 113 deletions(-) diff --git a/UI/MailerUI/UIxMailListActions.m b/UI/MailerUI/UIxMailListActions.m index 5ae707e6c..4dd20ad95 100644 --- a/UI/MailerUI/UIxMailListActions.m +++ b/UI/MailerUI/UIxMailListActions.m @@ -54,6 +54,7 @@ #import #import #import +#import #import #import #import @@ -329,7 +330,7 @@ WORequest *request; request = [context request]; - urlParams = [request contentAsString] objectFromJSONString]; + urlParams = [[request contentAsString] objectFromJSONString]; sortingAttributes = [urlParams objectForKey:@"sortingAttributes"]; sort = [sortingAttributes objectForKey:@"sort"]; @@ -404,7 +405,8 @@ { EOQualifier *qualifier, *searchQualifier; WORequest *request; - NSDictionary *filters, *sortingAttributes, *content; + NSDictionary *sortingAttributes, *content; + NSArray *filters; NSString *searchBy, *searchArgument, *searchInput, *searchString, *match; NSMutableArray *searchArray; int nbFilters, i; @@ -428,8 +430,12 @@ searchBy = [NSString stringWithString:[[filters objectAtIndex:i] objectForKey:@"searchBy"]]; searchArgument = [NSString stringWithString:[[filters objectAtIndex:i] objectForKey:@"searchArgument"]]; searchInput = [NSString stringWithString:[[filters objectAtIndex:i] objectForKey:@"searchInput"]]; - - searchString = [NSString stringWithFormat:@"(%@ %@: '%@')", searchBy, searchArgument, searchInput]; + + if ([[[filters objectAtIndex:i] objectForKey:@"negative"] boolValue]) + searchString = [NSString stringWithFormat:@"(not (%@ %@: '%@'))", searchBy, searchArgument, searchInput]; + else + searchString = [NSString stringWithFormat:@"(%@ %@: '%@')", searchBy, searchArgument, searchInput]; + searchQualifier = [EOQualifier qualifierWithQualifierFormat:searchString]; [searchArray addObject:searchQualifier]; } diff --git a/UI/Templates/MailerUI/UIxMailSearch.wox b/UI/Templates/MailerUI/UIxMailSearch.wox index 2e77b13e3..388648a13 100644 --- a/UI/Templates/MailerUI/UIxMailSearch.wox +++ b/UI/Templates/MailerUI/UIxMailSearch.wox @@ -14,31 +14,10 @@
  • - - + @@ -63,9 +42,9 @@ @@ -76,25 +55,22 @@
    - + - +
    -
    - - - + - - + - - + - - @@ -109,4 +85,6 @@ +
    +
    diff --git a/UI/WebServerResources/UIxMailSearch.css b/UI/WebServerResources/UIxMailSearch.css index 80969374d..9430167dd 100644 --- a/UI/WebServerResources/UIxMailSearch.css +++ b/UI/WebServerResources/UIxMailSearch.css @@ -1,29 +1,33 @@ /*************** Table adjustment *****************/ -TABLE#searchMailHeader, TABLE#searchFiltersList, TABLE#searchMailFooter +TABLE#searchMailHeader { width: 100%; } TABLE#searchFiltersList, TABLE#searchMailFooter { border: 1px solid #909090; - margin-top: 1em; padding:2px; border-radius: 3px; } TABLE#searchFiltersList { - display:block; - max-height:100px; + display:inline-block; + max-height:105px; + height:105px; overflow:auto; - width:672px; + width:674px; + margin-top: 1em; } TABLE#searchMailFooter { - height:141px; - min-height: 110px; + position:absolute; + left:10px; + width:680px; + top:240px; + height:194px; } .buttonsCell @@ -36,17 +40,18 @@ TABLE#searchMailFooter width:45%; } -.filterRow -{ - cellspacing=0; -} - .scrollbar { overflow-y:auto; - height:106px; - width:676px; + height:171px; position:absolute; + top:21px; + left:0; + right:0; +} + +#td_table_1, #td_table_2, #td_table_3, #td_table_4 { + width:25%; } /*************** Table adjustment : search results *****************/ @@ -54,6 +59,37 @@ TABLE#searchMailFooter cursor:pointer; } +.td_header { + border: solid #909090 1px; + position:absolute; + top:-1px; + width:157px; + cursor:pointer; + background: -webkit-linear-gradient(left top, #f0f1f0 , #e6e7e6); /* For Safari 5.1 to 6.0 */ + background: -o-linear-gradient(bottom right, #f0f1f0, #e6e7e6); /* For Opera 11.1 to 12.0 */ + background: -moz-linear-gradient(bottom right, #f0f1f0, #e6e7e6); /* For Firefox 3.6 to 15 */ + background: linear-gradient(to bottom right, #f0f1f0 , #e6e7e6); /* Standard syntax */ +} + +.td_header:hover +{text-decoration: underline; } + +#subjectHeader { + left:-1px; + border-top-left-radius: 3px; +} +#fromHeader { + left:166px; +} +#toHeader { + left:333px; +} +#dateHeader { + left:500px; + width:168px; + border-top-right-radius: 3px; +} + /*************** Button adjustment *****************/ #headerButtons @@ -72,7 +108,10 @@ TABLE#searchMailFooter } DIV#optionsButtons -{ float:left; } +{ + position:absolute; + bottom:10px; +} .button { @@ -82,14 +121,84 @@ DIV#optionsButtons #changeHeader { width:15px} -DIV.bottomToolbar { - margin:0; - position:relative; - border-radius:5px; +#resizeFrame +{ + text-align: -webkit-right; + margin-top:1em; +} + +#resizeButton +{ + display:inline-block; + text-align: -webkit-center; +} + + +#resultsFound { + position:absolute; + bottom:25px; + right:10px; +} + + +#imgPosition +{ position: absolute; + right: 17px; + top: 233px; + z-index: 1; +} + +#listCollapse +{ position: absolute; + top: .2em; + right: 0; + margin: 0.5em 1em; } + +#listCollapse img +{ position: absolute; } + +#listCollapse img.collapse +{ clip: rect(0 18px 18px 0); + left: 0; + top: 0; } + +#listCollapse img.collapse:hover +{ clip: rect(0 36px 18px 18px); + left: -18px; } + +#listCollapse img.rise +{ clip: rect(18px 18px 36px 0); + left: 0; + top: -18px; } + +#listCollapse img.rise:hover +{ clip: rect(18px 36px 36px 18px); + left: -18px; } + +#filterButtons +{ width:40px; + cursor:pointer; +} + +/* Glow */ +.glow { + display: inline-block; + -webkit-transition-duration: 0.3s; + transition-duration: 0.3s; + -webkit-transition-property: box-shadow; + transition-property: box-shadow; + -webkit-transform: translateZ(0); + transform: translateZ(0); + box-shadow: 0 0 1px rgba(0, 0, 0, 0); +} +.glow:hover, .glow:focus, .glow:active { + box-shadow: 0 0 8px rgba(0, 0, 0, 0.6); } /*************** Lists *****************/ .hidden { display:none; } + + diff --git a/UI/WebServerResources/UIxMailSearch.js b/UI/WebServerResources/UIxMailSearch.js index e9c3245e0..aecbc9400 100644 --- a/UI/WebServerResources/UIxMailSearch.js +++ b/UI/WebServerResources/UIxMailSearch.js @@ -49,10 +49,14 @@ function onSearchClick() { for (j = 0; j < searchArgumentsOptions.length ; j++) { if (searchArgumentsOptions[j].selected) { filter.searchArgument = searchArgumentsOptions[j].innerText; - if (filter.searchArgument == "contains") + filter.negative = false; + if (filter.searchArgument == "contains") { filter.searchArgument = "doesContain"; - else - filter.searchArgument = "NOT doesContain"; + } + else if (filter.searchArgument == "does not contain") { + filter.searchArgument = "doesContain"; + filter.negative = true; + } break; } } @@ -73,7 +77,7 @@ function onSearchClick() { } else { stopOngoingSearch = true; - $("searchButton").down().innerText = _("Search"); + onSearchEnd(); } } @@ -155,16 +159,20 @@ function searchMailsCallback(http) { row.writeAttribute("folderName", http.callbackData.folderName); var cell1 = row.insertCell(0); + cell1.writeAttribute("id", "td_table_1"); cell1.innerHTML = response.headers[i][3]; var cell2 = row.insertCell(1); + cell2.writeAttribute("id", "td_table_2"); cell2.innerHTML = response.headers[i][4]; var cell3 = row.insertCell(2); - cell3.innerHTML = response.headers[i][7]; + cell3.writeAttribute("id", "td_table_3"); + cell3.innerHTML = response.headers[i][0]; var cell4 = row.insertCell(3); - cell4.innerHTML = response.headers[i][12]; + cell4.writeAttribute("id", "td_table_4"); + cell4.innerHTML = response.headers[i][7]; } } @@ -195,12 +203,23 @@ function searchMailsCallback(http) { document.searchMailsAjaxRequest = triggerAjaxRequest(urlstr, searchMailsCallback, callbackData, content, {"content-type": "application/json"}); } else { - $("searchButton").down().innerText = _("Search"); + onSearchEnd(); } } } +function onSearchEnd() { + $("searchButton").down().innerText = _("Search"); + var nbResults = $$(".resultsRow").length; + if (nbResults == 1) + $("resultsFound").innerHTML = nbResults + " " + _("result found"); + else if (nbResults > 0) + $("resultsFound").innerHTML = nbResults + " " + _("results found"); + else + $("resultsFound").innerHTML = ""; +} + function onCancelClick() { disposeDialog(); $("searchMailView").remove(); @@ -261,31 +280,27 @@ function onAddFilter() { var cell4 = row.insertCell(3); Element.addClassName(cell4, "buttonsCell"); - var element4 = document.createElement("a"); - var element5 = document.createElement("a"); - var buttonsDiv = document.createElement("div"); - var spanAddFilter = document.createElement("span"); - var imageAddFilter = document.createElement("img"); - var spanRemoveFilter = document.createElement("span"); - var imageRemoveFilter = document.createElement("img"); - Element.addClassName(element4, "addFilterButton"); - Element.addClassName(buttonsDiv, "bottomToolbar"); - element4.writeAttribute("name", "addFilter"); - element4.writeAttribute("id", "addFilterButtonRow" + rowCount); - element4.writeAttribute("onclick", "onAddFilter(this)"); - imageAddFilter.writeAttribute("src", "/SOGo.woa/WebServerResources/add-icon.png"); - spanAddFilter.appendChild(imageAddFilter); - element4.appendChild(spanAddFilter); - buttonsDiv.appendChild(element4); - Element.addClassName(element5, "removeFilterButton"); - element5.writeAttribute("name", "removeFilter"); - element5.writeAttribute("id", "removeFilterButtonRow" + rowCount); - element5.writeAttribute("onclick", "onRemoveFilter(this)"); + var buttonsDiv = document.createElement("div"); + var imageAddFilter = document.createElement("img"); + var imageRemoveFilter = document.createElement("img"); + imageAddFilter.writeAttribute("src", "/SOGo.woa/WebServerResources/add-icon.png"); imageRemoveFilter.writeAttribute("src", "/SOGo.woa/WebServerResources/remove-icon.png"); - spanRemoveFilter.appendChild(imageRemoveFilter); - element5.appendChild(spanRemoveFilter); - buttonsDiv.appendChild(element5); + Element.addClassName(imageAddFilter, "addFilterButton"); + Element.addClassName(imageAddFilter, "glow"); + Element.addClassName(imageRemoveFilter, "removeFilterButton"); + Element.addClassName(imageRemoveFilter, "glow"); + imageAddFilter.writeAttribute("name", "addFilter"); + imageAddFilter.writeAttribute("id", "addFilterButtonRow" + rowCount); + imageAddFilter.writeAttribute("onclick", "onAddFilter(this)"); + imageRemoveFilter.writeAttribute("name", "removeFilter"); + imageRemoveFilter.writeAttribute("id", "removeFilterButtonRow" + rowCount); + imageRemoveFilter.writeAttribute("onclick", "onRemoveFilter(this)"); + buttonsDiv.writeAttribute("id", "filterButtons"); + + buttonsDiv.appendChild(imageAddFilter); + buttonsDiv.appendChild(imageRemoveFilter); + cell4.appendChild(buttonsDiv); } @@ -333,24 +348,37 @@ function onDeleteClick(event) { } function onResizeClick() { - var resizeAttrribute = $("resizeButton").getAttribute("name"); - if (resizeAttrribute == "resizeUp") { - $("searchFiltersList").style.display = "none"; - $("searchMailFooter").style.height = "300px"; - $("resultsTable").style.height = "265px"; - $("resizeUp").style.display = "none"; - $("resizeDown").style.display = "block"; - $("resizeButton").writeAttribute("name", "resizeDown"); + var searchFiltersList = jQuery("#searchFiltersList"); + var searchMailFooter = jQuery("#searchMailFooter"); + var resultsTable = jQuery("#resultsTable"); + var imgPosition = jQuery("#imgPosition"); + var state = 'collapse'; + var img = $("listCollapse").select('img').first(); + + + if (searchFiltersList[0].visible()) { + searchFiltersList.fadeOut(300, function() { + searchMailFooter.animate({ top:"120px" }, {queue: false, duration: 100}); + resultsTable.animate({height:"288px"}, 100); + searchMailFooter.animate({height:"312px" }, {queue: false, duration: 100, complete: function() { + img.removeClassName('collapse').addClassName('rise'); + $("resultsFound").style.bottom = "40px;"; + }}); + imgPosition.animate({ top:"113px" }, {duration: 100}); + }); } else { - $("searchFiltersList").style.display = "block"; - $("searchMailFooter").style.height = "141px"; - $("resultsTable").style.height = "106px"; - $("resizeUp").style.display = "block"; - $("resizeDown").style.display = "none"; - $("resizeButton").writeAttribute("name", "resizeUp"); + state = 'rise'; + searchMailFooter.animate({height:"194px"}, {queue: false, duration: 100}); + searchMailFooter.animate({top:"240px" }, {queue: false, duration: 100, complete:function() { + searchFiltersList.fadeIn(); + img.removeClassName('rise').addClassName('collapse'); + $("resultsFound").style.bottom = "25px;"; + }}); + imgPosition.animate({ top:"233px" }, {duration: 100}); + resultsTable.animate({height:"171px"}, 100); + } - } /*************** Init ********************/ @@ -363,6 +391,4 @@ function initSearchMailView () { // Observers : Event.on(element, eventName[, selector], callback) $("searchMailFooter").down("tbody").on("mousedown", "tr", onResultSelectionChange); $("searchMailFooter").down("tbody").on("dblclick", "tr", onOpenClick); - - } \ No newline at end of file diff --git a/UI/WebServerResources/generic.css b/UI/WebServerResources/generic.css index 736d556d4..b32901017 100644 --- a/UI/WebServerResources/generic.css +++ b/UI/WebServerResources/generic.css @@ -660,15 +660,14 @@ DIV.dialog > DIV DIV.dialog.searchMail { position: relative; - margin: 0px; padding: 0px; opacity: 1; width: 700px; - margin: 100px auto; + margin: 2em auto; } -DIV.dialog.searchMail > DIV { - padding: 10px; +DIV.dialog.searchMail > DIV { + min-height:467px; } DIV.dialog.none From f6c7ca33797bfd0e00a6b1f4e85f6b7de1ae9889 Mon Sep 17 00:00:00 2001 From: Alexandre Cloutier Date: Wed, 13 Aug 2014 17:41:58 -0400 Subject: [PATCH 03/12] applied comments --- UI/MailerUI/English.lproj/Localizable.strings | 16 ++- UI/MailerUI/UIxMailListActions.m | 44 +++----- UI/MailerUI/UIxMailSearch.m | 100 +++++++----------- UI/WebServerResources/UIxMailSearch.js | 4 +- 4 files changed, 68 insertions(+), 96 deletions(-) diff --git a/UI/MailerUI/English.lproj/Localizable.strings b/UI/MailerUI/English.lproj/Localizable.strings index 345d4c09b..3175b293b 100644 --- a/UI/MailerUI/English.lproj/Localizable.strings +++ b/UI/MailerUI/English.lproj/Localizable.strings @@ -13,6 +13,7 @@ "Print" = "Print"; "Stop" = "Stop"; "Write" = "Write"; +"Search" = "Search"; "Send" = "Send"; "Contacts" = "Contacts"; @@ -41,6 +42,7 @@ "Attachment" = "Attachment"; "Unread" = "Unread"; "Flagged" = "Flagged"; +"Search inbox" = "Search inbox"; /* Main Frame */ @@ -94,8 +96,9 @@ "To" = "To"; "Cc" = "Cc"; "Bcc" = "Bcc"; -"Reply-To" = "Reply-To"; +"Reply-To" = "Reply-To"; "Add address" = "Add address"; +"Body" = "Body"; "Open" = "Open"; "Select All" = "Select All"; @@ -237,6 +240,17 @@ "As Not Junk" = "As Not Junk"; "Run Junk Mail Controls" = "Run Junk Mail Controls"; +"Search messages in" = "Search messages in"; +"Search" = "Search"; +"Search subfolders" = "Search subfolders"; +"Match any of the following" = "Match any of the following"; +"Match all of the following" = "Match all of the following"; +"contains" = "contains"; +"does not contain" = "does not contain"; +"No matches found" = "No matches found"; +"results found" = "results found"; +"result found" = "result found"; + /* Folder operations */ "Name :" = "Name :"; "Enter the new name of your folder :" diff --git a/UI/MailerUI/UIxMailListActions.m b/UI/MailerUI/UIxMailListActions.m index 4dd20ad95..ac7e59171 100644 --- a/UI/MailerUI/UIxMailListActions.m +++ b/UI/MailerUI/UIxMailListActions.m @@ -323,35 +323,20 @@ return @"ARRIVAL"; } -- (NSString *) imap4SortKey -{ - NSString *sort; - NSDictionary *urlParams, *sortingAttributes; - WORequest *request; - - request = [context request]; - urlParams = [[request contentAsString] objectFromJSONString]; - sortingAttributes = [urlParams objectForKey:@"sortingAttributes"]; - sort = [sortingAttributes objectForKey:@"sort"]; - - return [sort uppercaseString]; -} - - (NSString *) imap4SortOrdering { - NSString *sort; - NSString *module; + WORequest *request; + NSString *sort, *module; NSMutableDictionary *moduleSettings; NSDictionary *urlParams, *sortingAttributes; - WORequest *request; - BOOL asc; SOGoUser *activeUser; SOGoUserSettings *us; + BOOL asc; - sort = [self imap4SortKey]; request = [context request]; urlParams = [[request contentAsString] objectFromJSONString]; sortingAttributes = [urlParams objectForKey:@"sortingAttributes"]; + sort = [[sortingAttributes objectForKey:@"sort"] uppercaseString]; asc = [[sortingAttributes objectForKey:@"asc"] boolValue]; activeUser = [context activeUser]; @@ -409,14 +394,12 @@ NSArray *filters; NSString *searchBy, *searchArgument, *searchInput, *searchString, *match; NSMutableArray *searchArray; - int nbFilters, i; + int nbFilters = 0, i; request = [context request]; content = [[request contentAsString] objectFromJSONString]; qualifier = nil; searchString = nil; - nbFilters = 0; - searchArray = [[NSMutableArray alloc] init]; if ([content objectForKey:@"filters"]) { @@ -425,6 +408,7 @@ nbFilters = [filters count]; match = [NSString stringWithString:[sortingAttributes objectForKey:@"match"]]; // AND, OR + searchArray = [NSMutableArray arrayWithCapacity:nbFilters]; for (i = 0; i < nbFilters; i++) { searchBy = [NSString stringWithString:[[filters objectAtIndex:i] objectForKey:@"searchBy"]]; @@ -443,17 +427,15 @@ qualifier = [[EOOrQualifier alloc] initWithQualifierArray: searchArray]; else qualifier = [[EOAndQualifier alloc] initWithQualifierArray: searchArray]; - - [searchArray release]; - [qualifier autorelease]; } + return qualifier; } - (NSArray *) getSortedUIDsInFolder: (SOGoMailFolder *) mailFolder { EOQualifier *qualifier, *fetchQualifier, *notDeleted; - + if (!sortedUIDs) { notDeleted = [EOQualifier qualifierWithQualifierFormat: @"(not (flags = %@))", @"deleted"]; @@ -472,7 +454,7 @@ [sortedUIDs retain]; } - + return sortedUIDs; } @@ -689,7 +671,7 @@ - (id ) getUIDsAction { - NSDictionary *data; + NSDictionary *data, *requestContent; NSString *noHeaders; SOGoMailFolder *folder; WORequest *request; @@ -697,12 +679,14 @@ request = [context request]; response = [context response]; + requestContent = [[request contentAsString] objectFromJSONString]; + [response setHeader: @"text/plain; charset=utf-8" - forKey: @"content-type"]; + forKey: @"content-type"]; folder = [self clientObject]; - noHeaders = [request formValueForKey: @"no_headers"]; + noHeaders = [[requestContent objectForKey: @"sortingAttributes"] objectForKey:@"no_headers"]; data = [self getUIDsInFolder: folder withHeaders: ([noHeaders length] == 0)]; diff --git a/UI/MailerUI/UIxMailSearch.m b/UI/MailerUI/UIxMailSearch.m index 3de88e00d..9a468248c 100644 --- a/UI/MailerUI/UIxMailSearch.m +++ b/UI/MailerUI/UIxMailSearch.m @@ -32,87 +32,61 @@ - (id) init { - item = nil; - - return self; + item = nil; + + return self; } - (void) dealloc { - [item release]; + [item release]; } - (void) setItem: (NSString *) newItem { - ASSIGN(item, newItem); + ASSIGN(item, newItem); } - (NSString *) item { - return item; + return item; } - (NSArray *) mailAccountsList { - SOGoMailAccount *co, *accountFolder; - SOGoMailAccounts *accountsFolder; - SOGoUserFolder *userFolder; - NSString *userName, *option, *lookup; - NSArray *folders; - NSMutableArray *mailboxes; - NSDictionary *mailAccount; - int nbMailboxes, nbMailAccounts, i, j; - - - userFolder = [[context activeUser] homeFolderInContext: context]; - accountsFolder = [userFolder lookupName: @"Mail" inContext: context acquire: NO]; - nbMailAccounts = [[accountsFolder mailAccounts] count]; + SOGoMailAccount *mAccount; + SOGoMailAccounts *mAccounts; + NSString *userName, *option, *aString; + NSArray *accountFolders; + NSMutableArray *mailboxes; + NSDictionary *accountName; + int nbMailboxes, nbMailAccounts, i, j; - mailboxes = [[NSMutableArray alloc] init]; - for (i = 0; i < nbMailAccounts; i++) - { - mailAccount = [[[accountsFolder mailAccounts] objectAtIndex:i] objectForKey:@"name"]; // Keys on this account = (name, port, encryption, mailboxes, serverName, identities, userName) - userName = [[[accountsFolder mailAccounts] objectAtIndex:i] objectForKey:@"userName"]; - lookup = [NSString stringWithFormat:@"%i", i]; - accountFolder = [accountsFolder lookupName:lookup inContext: context acquire: NO]; - folders = [accountFolder allFoldersMetadata]; - nbMailboxes = [folders count]; - [mailboxes addObject:mailAccount]; - for (j = 0; j < nbMailboxes; j++) - { - option = [NSString stringWithFormat:@"%@%@", userName, [[folders objectAtIndex:j] objectForKey:@"displayName"]]; - [mailboxes addObject:option]; - } - } - return mailboxes; - [mailboxes release]; -} + // Number of accounts linked with the current user + mAccounts = [self clientObject]; + nbMailAccounts = [[mAccounts mailAccounts] count]; -// -// The objective here is to return the parent view layout and select the print -// layout corresponding. Default print view: list view -/* -- (NSString *) mailAccountSelected -{ - SOGoUser *activeUser; - NSString *parentView; - - activeUser = [context activeUser]; - us = [activeUser userSettings]; - parentView = [[us objectForKey:@"Calendar"] objectForKey:@"View" ]; - - if ([parentView isEqualToString:@"dayview"]) - return @"Daily"; - - else if ([parentView isEqualToString:@"weekview"]) - return @"Weekly"; - - else if ([parentView isEqualToString:@"multicolumndayview"]) - return @"Multi-Columns"; - - else - return @"LIST"; + mailboxes = [[NSMutableArray alloc] init]; + for (i = 0; i < nbMailAccounts; i++) + { + accountName = [[[mAccounts mailAccounts] objectAtIndex:i] objectForKey:@"name"]; // Keys on this account = (name, port, encryption, mailboxes, serverName, identities, userName) + userName = [[[mAccounts mailAccounts] objectAtIndex:i] objectForKey:@"userName"]; + + aString = [NSString stringWithFormat:@"%i", i]; + mAccount = [mAccounts lookupName:aString inContext: context acquire: NO]; + accountFolders = [mAccount allFoldersMetadata]; + + // Number of mailboxes inside the current account + nbMailboxes = [accountFolders count]; + [mailboxes addObject:accountName]; + for (j = 0; j < nbMailboxes; j++) + { + option = [NSString stringWithFormat:@"%@%@", userName, [[accountFolders objectAtIndex:j] objectForKey:@"displayName"]]; + [mailboxes addObject:option]; + } + } + return mailboxes; + [mailboxes release]; } -*/ @end \ No newline at end of file diff --git a/UI/WebServerResources/UIxMailSearch.js b/UI/WebServerResources/UIxMailSearch.js index aecbc9400..0c52be72a 100644 --- a/UI/WebServerResources/UIxMailSearch.js +++ b/UI/WebServerResources/UIxMailSearch.js @@ -100,9 +100,9 @@ function searchMails() { var accountNumber = "/" + userNames.indexOf(accountUser); var position = searchLocation.length; - var folderName = accountNumber + "/folder" + searchLocation[1]; + var folderName = accountNumber + "/folder" + searchLocation[1].replace(" ", "_SP_"); for (i = 2; i < position; i++) - folderName += accountNumber + "/folder" + searchLocation[i]; + folderName += "/folder" + searchLocation[i]; var folderPath = optionsList[selectedIndex].innerText; From 52476251b82ed0c172bc143a0642ae223d306b6e Mon Sep 17 00:00:00 2001 From: Alexandre Cloutier Date: Thu, 14 Aug 2014 14:49:44 -0400 Subject: [PATCH 04/12] applied comments, fix bug and add sortable results --- UI/MailerUI/UIxMailListActions.m | 8 ++- UI/Templates/MailerUI/UIxMailSearch.wox | 5 +- UI/WebServerResources/UIxMailSearch.css | 2 +- UI/WebServerResources/UIxMailSearch.js | 91 +++++++++++++++++++++++-- 4 files changed, 96 insertions(+), 10 deletions(-) diff --git a/UI/MailerUI/UIxMailListActions.m b/UI/MailerUI/UIxMailListActions.m index ac7e59171..163ead021 100644 --- a/UI/MailerUI/UIxMailListActions.m +++ b/UI/MailerUI/UIxMailListActions.m @@ -459,7 +459,8 @@ } /** - * Returns a flatten representation of the messages threads as triples of + * Returns a + of the messages threads as triples of * metadata, including the message UID, thread level and root position. * @param _sortedUIDs the interleaved arrays representation of the messages UIDs * @return an flatten array representation of the messages UIDs @@ -632,11 +633,14 @@ // Retrieve messages UIDs using form parameters "sort" and "asc" uids = [self getSortedUIDsInFolder: folder]; + + // Get rid of the extra parenthesis + // uids = [[[[uids stringValue] stringByReplacingOccurrencesOfString:@"(" withString:@""] stringByReplacingOccurrencesOfString:@")" withString:@""] componentsSeparatedByString:@","]; if (includeHeaders) { // Also retrieve the first headers, up to 'headersPrefetchMaxSize' - count = [uids count]; + count = [[uids flattenedArray] count]; if (count > headersPrefetchMaxSize) count = headersPrefetchMaxSize; r = NSMakeRange(0, count); headers = [self getHeadersForUIDs: [[uids flattenedArray] subarrayWithRange: r] diff --git a/UI/Templates/MailerUI/UIxMailSearch.wox b/UI/Templates/MailerUI/UIxMailSearch.wox index 388648a13..1f8c3cb2d 100644 --- a/UI/Templates/MailerUI/UIxMailSearch.wox +++ b/UI/Templates/MailerUI/UIxMailSearch.wox @@ -4,7 +4,8 @@ xmlns:const="http://www.skyrix.com/od/constant" xmlns:uix="OGo:uix" xmlns:rsrc="OGo:url" - xmlns:label="OGo:label"> + xmlns:label="OGo:label" + const:jsFiles="tablekit.js, tablekit-sogo.js, tablekit-trueresize.js">
    - +
    + + + - -
    +
    diff --git a/UI/WebServerResources/UIxMailSearch.css b/UI/WebServerResources/UIxMailSearch.css index 9430167dd..cd3e37a21 100644 --- a/UI/WebServerResources/UIxMailSearch.css +++ b/UI/WebServerResources/UIxMailSearch.css @@ -50,7 +50,7 @@ TABLE#searchMailFooter right:0; } -#td_table_1, #td_table_2, #td_table_3, #td_table_4 { +.td_table_1, .td_table_2, .td_table_3, .td_table_4 { width:25%; } diff --git a/UI/WebServerResources/UIxMailSearch.js b/UI/WebServerResources/UIxMailSearch.js index 0c52be72a..393000e1f 100644 --- a/UI/WebServerResources/UIxMailSearch.js +++ b/UI/WebServerResources/UIxMailSearch.js @@ -159,19 +159,19 @@ function searchMailsCallback(http) { row.writeAttribute("folderName", http.callbackData.folderName); var cell1 = row.insertCell(0); - cell1.writeAttribute("id", "td_table_1"); + Element.addClassName(cell1, "td_table_1"); cell1.innerHTML = response.headers[i][3]; var cell2 = row.insertCell(1); - cell2.writeAttribute("id", "td_table_2"); + Element.addClassName(cell2, "td_table_2"); cell2.innerHTML = response.headers[i][4]; var cell3 = row.insertCell(2); - cell3.writeAttribute("id", "td_table_3"); + Element.addClassName(cell3, "td_table_3"); cell3.innerHTML = response.headers[i][0]; var cell4 = row.insertCell(3); - cell4.writeAttribute("id", "td_table_4"); + Element.addClassName(cell4, "td_table_4"); cell4.innerHTML = response.headers[i][7]; } @@ -218,6 +218,8 @@ function onSearchEnd() { $("resultsFound").innerHTML = nbResults + " " + _("results found"); else $("resultsFound").innerHTML = ""; + + TableKit.reloadTable($("searchMailFooter")); } function onCancelClick() { @@ -344,7 +346,85 @@ function onOpenClick(event) { } function onDeleteClick(event) { - console.debug("deleteButton"); + var messageList = $("resultsTable"); + var row = messageList.getSelectedRows()[0]; + if (row) { + var rowIds = messageList.getSelectedRows()[0].getAttribute("uid"); + var uids = new Array(); // message IDs + var paths = new Array(); // row IDs + var unseenCount = 0; + var refreshFolder = false; + + if (rowIds && rowIds.length > 0) { + messageList.deselectAll(); + if (unseenCount < 1) { + row.remove(); + if (row.hasClassName("mailer_unreadmail")) + unseenCount--; + else + unseenCount = 1; + } + var uid = rowIds; + var path = Mailer.currentMailbox + "/" + uid; + uids.push(uid); + paths.push(path); + deleteMessageRequestCount++; + + deleteCachedMessage(path); + if (Mailer.currentMessages[Mailer.currentMailbox] == uid) { + if (messageContent) messageContent.innerHTML = ''; + Mailer.currentMessages[Mailer.currentMailbox] = null; + } + + Mailer.dataTable.remove(uid); + updateMessageListCounter(0 - rowIds.length, true); + if (unseenCount < 0) { + var node = mailboxTree.getMailboxNode(Mailer.currentMailbox); + if (node) { + updateUnseenCount(node, unseenCount, true); + } + } + var url = ApplicationBaseURL + encodeURI(Mailer.currentMailbox) + "/batchDelete"; + var parameters = "uid=" + uids.join(","); + var data = { "id": uids, "mailbox": Mailer.currentMailbox, "path": paths, "refreshUnseenCount": (unseenCount > 0), "refreshFolder": refreshFolder }; + triggerAjaxRequest(url, deleteMessageCallback, data, parameters, + { "Content-type": "application/x-www-form-urlencoded" }); + } + } + return false; + +} + +function deleteMessageCallback (http){ + if (isHttpStatus204(http.status) || http.status == 200) { + var data = http.callbackData; + if (http.status == 200) { + // The answer contains quota information + var rdata = http.responseText.evalJSON(true); + if (rdata.quotas && data["mailbox"].startsWith('/0/')) + updateQuotas(rdata.quotas); + } + if (data["refreshUnseenCount"]) + // TODO : the unseen count should be returned when calling the batchDelete remote action, + // in order to avoid this extra AJAX call. + getUnseenCountForFolder(data["mailbox"]); + if (data["refreshFolder"]) + Mailer.dataTable.refresh(); + } + else if (!http.callbackData["withoutTrash"]) { + showConfirmDialog(_("Warning"), + _("The messages could not be moved to the trash folder. Would you like to delete them immediately?"), + deleteMessagesWithoutTrash.bind(document, http.callbackData), + function() { refreshCurrentFolder(); disposeDialog(); }); + } + else { + var html = new Element('div').update(http.responseText); + log ("Messages deletion failed (" + http.status + ") : "); + log (html.down('p').innerHTML); + showAlertDialog(_("Operation failed")); + refreshCurrentFolder(); + } + onSearchEnd(); } function onResizeClick() { @@ -391,4 +471,5 @@ function initSearchMailView () { // Observers : Event.on(element, eventName[, selector], callback) $("searchMailFooter").down("tbody").on("mousedown", "tr", onResultSelectionChange); $("searchMailFooter").down("tbody").on("dblclick", "tr", onOpenClick); + TableKit.Sortable.init($("searchMailFooter"), {sortable : true}); } \ No newline at end of file From 8783f09a4acca298fc3a9f533feb2dda5590db36 Mon Sep 17 00:00:00 2001 From: Alexandre Cloutier Date: Thu, 14 Aug 2014 15:01:40 -0400 Subject: [PATCH 05/12] fix leak --- UI/MailerUI/UIxMailSearch.m | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/UI/MailerUI/UIxMailSearch.m b/UI/MailerUI/UIxMailSearch.m index 9a468248c..a89467df2 100644 --- a/UI/MailerUI/UIxMailSearch.m +++ b/UI/MailerUI/UIxMailSearch.m @@ -66,7 +66,7 @@ mAccounts = [self clientObject]; nbMailAccounts = [[mAccounts mailAccounts] count]; - mailboxes = [[NSMutableArray alloc] init]; + mailboxes = [NSMutableArray array]; for (i = 0; i < nbMailAccounts; i++) { accountName = [[[mAccounts mailAccounts] objectAtIndex:i] objectForKey:@"name"]; // Keys on this account = (name, port, encryption, mailboxes, serverName, identities, userName) @@ -86,7 +86,6 @@ } } return mailboxes; - [mailboxes release]; } @end \ No newline at end of file From 73fcdc230615da8ac22281397f4ba692a4a7cdc8 Mon Sep 17 00:00:00 2001 From: Alexandre Cloutier Date: Fri, 15 Aug 2014 11:41:37 -0400 Subject: [PATCH 06/12] adjust css for other browser, fix display bug --- UI/Templates/MailerUI/UIxMailSearch.wox | 18 ++-- UI/WebServerResources/UIxMailSearch.css | 118 ++++++++++++++---------- UI/WebServerResources/UIxMailSearch.js | 33 +++---- UI/WebServerResources/tablekit.js | 6 ++ 4 files changed, 98 insertions(+), 77 deletions(-) diff --git a/UI/Templates/MailerUI/UIxMailSearch.wox b/UI/Templates/MailerUI/UIxMailSearch.wox index 1f8c3cb2d..957031927 100644 --- a/UI/Templates/MailerUI/UIxMailSearch.wox +++ b/UI/Templates/MailerUI/UIxMailSearch.wox @@ -56,22 +56,22 @@
    -
    - - - -
    - - - - + diff --git a/UI/WebServerResources/UIxMailSearch.css b/UI/WebServerResources/UIxMailSearch.css index cd3e37a21..0ba74e62e 100644 --- a/UI/WebServerResources/UIxMailSearch.css +++ b/UI/WebServerResources/UIxMailSearch.css @@ -4,26 +4,24 @@ TABLE#searchMailHeader { width: 100%; } -TABLE#searchFiltersList, TABLE#searchMailFooter -{ - border: 1px solid #909090; - padding:2px; - border-radius: 3px; -} - TABLE#searchFiltersList { + border: 1px solid #909090; + padding-top:2px; + border-radius: 3px; display:inline-block; max-height:105px; height:105px; overflow:auto; - width:674px; + width:100%; margin-top: 1em; } TABLE#searchMailFooter { position:absolute; + border: 1px solid #909090; + border-radius: 3px; left:10px; width:680px; top:240px; @@ -54,16 +52,25 @@ TABLE#searchMailFooter width:25%; } -/*************** Table adjustment : search results *****************/ -.resultsRow { - cursor:pointer; +TD.sortasc { + background:#bfc2bf; + background-image: url(/SOGo.woa/WebServerResources/arrow-up.png); + background-repeat: no-repeat; + background-position:right center; +} + +TD.sortdesc { + background:#bfc2bf; + background-image: url(/SOGo.woa/WebServerResources/arrow-down.png); + background-repeat: no-repeat; + background-position:right center; } .td_header { - border: solid #909090 1px; - position:absolute; - top:-1px; - width:157px; + border-bottom: solid #909090 1px; + border-right: solid #909090 1px; + height:18px; + width:20%; cursor:pointer; background: -webkit-linear-gradient(left top, #f0f1f0 , #e6e7e6); /* For Safari 5.1 to 6.0 */ background: -o-linear-gradient(bottom right, #f0f1f0, #e6e7e6); /* For Opera 11.1 to 12.0 */ @@ -74,20 +81,17 @@ TABLE#searchMailFooter .td_header:hover {text-decoration: underline; } -#subjectHeader { - left:-1px; - border-top-left-radius: 3px; +#buttonExpandHeader { + width:3%; + border-right:0; } -#fromHeader { - left:166px; -} -#toHeader { - left:333px; -} -#dateHeader { - left:500px; - width:168px; - border-top-right-radius: 3px; + +@-moz-document url-prefix() { + #buttonExpandHeader { + width:1.5%; + border-right:0; + } + } /*************** Button adjustment *****************/ @@ -118,9 +122,6 @@ DIV#optionsButtons font-style:normal; } -#changeHeader -{ width:15px} - #resizeFrame { text-align: -webkit-right; @@ -133,47 +134,64 @@ DIV#optionsButtons text-align: -webkit-center; } - #resultsFound { position:absolute; bottom:25px; right:10px; } - #imgPosition -{ position: absolute; - right: 17px; - top: 233px; - z-index: 1; -} - -#listCollapse -{ position: absolute; - top: .2em; - right: 0; - margin: 0.5em 1em; } +{ z-index: 1; } #listCollapse img { position: absolute; } #listCollapse img.collapse { clip: rect(0 18px 18px 0); - left: 0; - top: 0; } + top: 1px; + right: -16px; } #listCollapse img.collapse:hover { clip: rect(0 36px 18px 18px); - left: -18px; } + top: 1px; + right: 2px; } #listCollapse img.rise { clip: rect(18px 18px 36px 0); - left: 0; - top: -18px; } + top: -17px; + right:-16px; + } #listCollapse img.rise:hover { clip: rect(18px 36px 36px 18px); - left: -18px; } + top: -17px; + right:2px; } + +@-moz-document url-prefix() { + #listCollapse img + { position: absolute; } + + #listCollapse img.collapse + { clip: rect(0 18px 18px 0); + top: 2px; + right: -16px; } + + #listCollapse img.collapse:hover + { clip: rect(0 36px 18px 18px); + top: 2px; + right: 2px; } + + #listCollapse img.rise + { clip: rect(18px 18px 36px 0); + top: -16px; + right:-16px; + } + + #listCollapse img.rise:hover + { clip: rect(18px 36px 36px 18px); + top: -16px; + right:2px; } +} #filterButtons { diff --git a/UI/WebServerResources/UIxMailSearch.js b/UI/WebServerResources/UIxMailSearch.js index 393000e1f..df649c2f9 100644 --- a/UI/WebServerResources/UIxMailSearch.js +++ b/UI/WebServerResources/UIxMailSearch.js @@ -15,7 +15,7 @@ var stopOngoingSearch = false; function onSearchClick() { // This function updates the searchParams var filterRows = $$(".filterRow"); - var searchButton = $("searchButton").down().innerText; + var searchButton = $("searchButton").down().innerHTML; var mailAccountsList = $("mailAccountsList").options; if (searchButton == _("Search")) { @@ -25,7 +25,7 @@ function onSearchClick() { // Get the mailboxe(s) for (i = 0; i < mailAccountsList.length ; i++) { if (mailAccountsList[i].selected) { - searchParams.searchLocation = mailAccountsList[i].innerText; + searchParams.searchLocation = mailAccountsList[i].innerHTML; break; } } @@ -40,7 +40,7 @@ function onSearchClick() { // Get the searchBy for (j = 0; j < searchByOptions.length ; j++) { if (searchByOptions[j].selected) { - filter.searchBy = searchByOptions[j].innerText; + filter.searchBy = searchByOptions[j].innerHTML; break; } } @@ -48,7 +48,7 @@ function onSearchClick() { // Get the searchArgument for (j = 0; j < searchArgumentsOptions.length ; j++) { if (searchArgumentsOptions[j].selected) { - filter.searchArgument = searchArgumentsOptions[j].innerText; + filter.searchArgument = searchArgumentsOptions[j].innerHTML; filter.negative = false; if (filter.searchArgument == "contains") { filter.searchArgument = "doesContain"; @@ -70,7 +70,7 @@ function onSearchClick() { } // Send the request only if there is at least one filter if (searchParams.filters.length > 0) { - $("searchButton").down().innerText = _("Stop"); + $("searchButton").down().innerHTML = _("Stop"); searchMails(); } // TODO - give the user a warning or a notice that it needs at least one filter @@ -104,15 +104,15 @@ function searchMails() { for (i = 2; i < position; i++) folderName += "/folder" + searchLocation[i]; - var folderPath = optionsList[selectedIndex].innerText; + var folderPath = optionsList[selectedIndex].innerHTML; } var subfolders = []; if (searchParams.subfolder == true) { for (i = 0; i < nbOptions; i++) { - if ((optionsList[i].innerText.search(folderPath) != -1) && (i != selectedIndex)) { - var splitArray = optionsList[i].innerText.split("/"); + if ((optionsList[i].innerHTML.search(folderPath) != -1) && (i != selectedIndex)) { + var splitArray = optionsList[i].innerHTML.split("/"); // Remove the user information since it is not required splitArray.splice(0, 1); var subfolder = []; @@ -184,7 +184,7 @@ function searchMailsCallback(http) { cell.writeAttribute("id", "noSearchResults"); cell.writeAttribute("colspan", "4"); - element.innerText = _("No matches found"); + element.innerHTML = _("No matches found"); cell.appendChild(element); } } @@ -210,7 +210,7 @@ function searchMailsCallback(http) { } function onSearchEnd() { - $("searchButton").down().innerText = _("Search"); + $("searchButton").down().innerHTML = _("Search"); var nbResults = $$(".resultsRow").length; if (nbResults == 1) $("resultsFound").innerHTML = nbResults + " " + _("result found"); @@ -219,7 +219,8 @@ function onSearchEnd() { else $("resultsFound").innerHTML = ""; - TableKit.reloadTable($("searchMailFooter")); + TableKit.reloadSortableTable($("searchMailFooter")); + $("buttonExpandHeader").addClassName("nosort"); } function onCancelClick() { @@ -253,7 +254,7 @@ function onAddFilter() { for (i = 0; i < searchByList.length; i++) { var option = document.createElement("option"); option.writeAttribute("value", i); - option.innerHTML = searchByList[i].innerText; + option.innerHTML = searchByList[i].innerHTML; element1.appendChild(option); } cell1.appendChild(element1); @@ -265,7 +266,7 @@ function onAddFilter() { for (i = 0; i < stringArgumentsList.length; i++) { var option = document.createElement("option"); option.writeAttribute("value", i); - option.innerHTML = stringArgumentsList[i].innerText; + option.innerHTML = stringArgumentsList[i].innerHTML; element2.appendChild(option); } cell2.appendChild(element2); @@ -320,7 +321,7 @@ function onRemoveFilter(event) { function onResultSelectionChange(event) { var table = $("searchMailFooter").down("tbody"); - if (event && (event.target.innerText != _("No matches found"))) { + if (event && (event.target.innerHTML != _("No matches found"))) { var node = getTarget(event); if (node.tagName == "SPAN") @@ -431,7 +432,6 @@ function onResizeClick() { var searchFiltersList = jQuery("#searchFiltersList"); var searchMailFooter = jQuery("#searchMailFooter"); var resultsTable = jQuery("#resultsTable"); - var imgPosition = jQuery("#imgPosition"); var state = 'collapse'; var img = $("listCollapse").select('img').first(); @@ -444,7 +444,6 @@ function onResizeClick() { img.removeClassName('collapse').addClassName('rise'); $("resultsFound").style.bottom = "40px;"; }}); - imgPosition.animate({ top:"113px" }, {duration: 100}); }); } else { @@ -455,7 +454,6 @@ function onResizeClick() { img.removeClassName('rise').addClassName('collapse'); $("resultsFound").style.bottom = "25px;"; }}); - imgPosition.animate({ top:"233px" }, {duration: 100}); resultsTable.animate({height:"171px"}, 100); } @@ -471,5 +469,4 @@ function initSearchMailView () { // Observers : Event.on(element, eventName[, selector], callback) $("searchMailFooter").down("tbody").on("mousedown", "tr", onResultSelectionChange); $("searchMailFooter").down("tbody").on("dblclick", "tr", onOpenClick); - TableKit.Sortable.init($("searchMailFooter"), {sortable : true}); } \ No newline at end of file diff --git a/UI/WebServerResources/tablekit.js b/UI/WebServerResources/tablekit.js index 370879520..4287e17fc 100644 --- a/UI/WebServerResources/tablekit.js +++ b/UI/WebServerResources/tablekit.js @@ -242,6 +242,12 @@ Object.extend(TableKit, { if(op.resizable) {TableKit.Resizable.init(table);} if(op.editable) {TableKit.Editable.init(table);} }, + reloadSortableTable : function(table){ + table = $(table); + TableKit.unloadTable(table); + var op = TableKit.option('sortable', table.id); + if(op.sortable) {TableKit.Sortable.init(table);} + }, reload : function() { for(var k in TableKit.tables) { TableKit.reloadTable(k); From c76cb3646122e43e6b1cb2dfa6e64a88da85d605 Mon Sep 17 00:00:00 2001 From: Alexandre Cloutier Date: Fri, 15 Aug 2014 13:06:46 -0400 Subject: [PATCH 07/12] Disable the search button on toolbar once it is opened --- UI/WebServerResources/MailerUI.js | 24 ++++++++++++++---------- UI/WebServerResources/UIxMailSearch.js | 2 ++ 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/UI/WebServerResources/MailerUI.js b/UI/WebServerResources/MailerUI.js index e08440f38..777453570 100644 --- a/UI/WebServerResources/MailerUI.js +++ b/UI/WebServerResources/MailerUI.js @@ -434,16 +434,20 @@ function onDocumentKeydown(event) { /* Search mail, call the template and open inside a dialog windoƒw */ function onSearchMail(event) { - if ($("searchMailView")) { - $("searchMailView").style.display = "block"; - $("bgDialogDiv").style.display = "block"; - initSearchMailView(); - } - else { - var urlstr = ApplicationBaseURL + "/search"; - - // Return the template for the searchMail feature - triggerAjaxRequest(urlstr, displaySearchMailCallback); + if (event.element().disabled == false || event.element().disabled == undefined) { + event.element().disabled = true; + event.element().writeAttribute("id", "toolbarSearchButton"); + if ($("searchMailView")) { + $("searchMailView").style.display = "block"; + $("bgDialogDiv").style.display = "block"; + initSearchMailView(); + } + else { + var urlstr = ApplicationBaseURL + "/search"; + + // Return the template for the searchMail feature + triggerAjaxRequest(urlstr, displaySearchMailCallback); + } } } diff --git a/UI/WebServerResources/UIxMailSearch.js b/UI/WebServerResources/UIxMailSearch.js index df649c2f9..4ec62b8df 100644 --- a/UI/WebServerResources/UIxMailSearch.js +++ b/UI/WebServerResources/UIxMailSearch.js @@ -226,6 +226,8 @@ function onSearchEnd() { function onCancelClick() { disposeDialog(); $("searchMailView").remove(); + $("toolbarSearchButton").disabled = false; + } function onSearchSubfoldersCheck(event) { From 07a138e0d62ebaaea722dc91ae0be162385d74ed Mon Sep 17 00:00:00 2001 From: Alexandre Cloutier Date: Wed, 27 Aug 2014 12:30:33 -0400 Subject: [PATCH 08/12] applied comments and add the possibility to resize the search inbox window --- UI/Templates/MailerUI/UIxMailSearch.wox | 50 +++++++++-------- UI/WebServerResources/MailerUI.js | 2 +- UI/WebServerResources/UIxMailSearch.css | 56 ++++++++---------- UI/WebServerResources/UIxMailSearch.js | 75 ++++++++++++++----------- UI/WebServerResources/generic.css | 3 +- 5 files changed, 95 insertions(+), 91 deletions(-) diff --git a/UI/Templates/MailerUI/UIxMailSearch.wox b/UI/Templates/MailerUI/UIxMailSearch.wox index 957031927..96511446d 100644 --- a/UI/Templates/MailerUI/UIxMailSearch.wox +++ b/UI/Templates/MailerUI/UIxMailSearch.wox @@ -56,30 +56,32 @@
    + + + + +
    - - - - - - - - - - - - - - - -
    - - - - -
    +
    + + + + + + + + + + + + + + + +
    + + + + +
    +
    diff --git a/UI/WebServerResources/MailerUI.js b/UI/WebServerResources/MailerUI.js index 777453570..77a83a59f 100644 --- a/UI/WebServerResources/MailerUI.js +++ b/UI/WebServerResources/MailerUI.js @@ -458,7 +458,7 @@ function displaySearchMailCallback(http) { var id = _("searchMailView"); fields.innerHTML = http.responseText; - dialog = createDialog(id, title, null, fields, "searchMail"); // (id, title, legend, content, positionClass) + var dialog = createDialog(id, title, null, fields, "searchMail"); // (id, title, legend, content, positionClass) document.body.appendChild(dialog); if (Prototype.Browser.IE) diff --git a/UI/WebServerResources/UIxMailSearch.css b/UI/WebServerResources/UIxMailSearch.css index 0ba74e62e..831f9669e 100644 --- a/UI/WebServerResources/UIxMailSearch.css +++ b/UI/WebServerResources/UIxMailSearch.css @@ -2,7 +2,8 @@ /*************** Table adjustment *****************/ TABLE#searchMailHeader -{ width: 100%; } +{ width: 100%; + margin-bottom: 1em; } TABLE#searchFiltersList { @@ -14,18 +15,18 @@ TABLE#searchFiltersList height:105px; overflow:auto; width:100%; - margin-top: 1em; } -TABLE#searchMailFooter +DIV#resultsTable { - position:absolute; border: 1px solid #909090; border-radius: 3px; - left:10px; - width:680px; - top:240px; - height:194px; + overflow-y: auto; +} + +TD#mailAccountsCell { + overflow:hidden; + white-space: nowrap; } .buttonsCell @@ -38,18 +39,8 @@ TABLE#searchMailFooter width:45%; } -.scrollbar -{ - overflow-y:auto; - height:171px; - position:absolute; - top:21px; - left:0; - right:0; -} - .td_table_1, .td_table_2, .td_table_3, .td_table_4 { - width:25%; + cursor:default; } TD.sortasc { @@ -82,8 +73,7 @@ TD.sortdesc { {text-decoration: underline; } #buttonExpandHeader { - width:3%; - border-right:0; + width:10px; } @-moz-document url-prefix() { @@ -98,7 +88,8 @@ TD.sortdesc { #headerButtons { - width:27%; + width:171px; + white-space: nowrap; } #searchButton, #cancelButton @@ -136,36 +127,37 @@ DIV#optionsButtons #resultsFound { position:absolute; - bottom:25px; + bottom:20px; right:10px; } #imgPosition -{ z-index: 1; } +{ z-index: 1; + position:relative; } #listCollapse img { position: absolute; } #listCollapse img.collapse { clip: rect(0 18px 18px 0); - top: 1px; - right: -16px; } + top: -9px; + right: -22px; } #listCollapse img.collapse:hover { clip: rect(0 36px 18px 18px); - top: 1px; - right: 2px; } + top: -9px; + right: -4px; } #listCollapse img.rise { clip: rect(18px 18px 36px 0); - top: -17px; - right:-16px; + top: -27px; + right:-22px; } #listCollapse img.rise:hover { clip: rect(18px 36px 36px 18px); - top: -17px; - right:2px; } + top: -27px; + right:-4px; } @-moz-document url-prefix() { #listCollapse img diff --git a/UI/WebServerResources/UIxMailSearch.js b/UI/WebServerResources/UIxMailSearch.js index 4ec62b8df..68ae26ee7 100644 --- a/UI/WebServerResources/UIxMailSearch.js +++ b/UI/WebServerResources/UIxMailSearch.js @@ -86,30 +86,30 @@ function searchMails() { var optionsList = $("mailAccountsList").options; var nbOptions = optionsList.length; var selectedIndex = optionsList.selectedIndex; + var accountNumber, accountUser, folderPath, folderName; var mailAccountIndex = mailAccounts.indexOf(searchParams.searchLocation); if (mailAccountIndex != -1) { - var accountNumber = "/" + mailAccountIndex; - var folderName = accountNumber + "/folderINBOX"; - var accountUser = userNames[mailAccountIndex]; - var folderPath = accountUser; + accountNumber = "/" + mailAccountIndex; + folderName = accountNumber + "/folderINBOX"; + accountUser = userNames[mailAccountIndex]; + folderPath = accountUser; } else { var searchLocation = searchParams.searchLocation.split("/"); - var accountUser = searchLocation[0]; - var accountNumber = "/" + userNames.indexOf(accountUser); + accountUser = searchLocation[0]; + accountNumber = "/" + userNames.indexOf(accountUser); var position = searchLocation.length; - var folderName = accountNumber + "/folder" + searchLocation[1].replace(" ", "_SP_"); + folderName = accountNumber + "/folder" + searchLocation[1].replace(" ", "_SP_"); for (i = 2; i < position; i++) folderName += "/folder" + searchLocation[i]; - var folderPath = optionsList[selectedIndex].innerHTML; - + folderPath = optionsList[selectedIndex].innerHTML; } - + var subfolders = []; - if (searchParams.subfolder == true) { + if (searchParams.subfolder === true) { for (i = 0; i < nbOptions; i++) { if ((optionsList[i].innerHTML.search(folderPath) != -1) && (i != selectedIndex)) { var splitArray = optionsList[i].innerHTML.split("/"); @@ -124,7 +124,7 @@ function searchMails() { } } } - + var urlstr = (ApplicationBaseURL + folderName + "/uids"); var callbackData = {"folderName" : folderName, "subfolders" : subfolders, "newSearch" : true}; @@ -172,6 +172,7 @@ function searchMailsCallback(http) { var cell4 = row.insertCell(3); Element.addClassName(cell4, "td_table_4"); + cell4.writeAttribute("colspan", "2"); cell4.innerHTML = response.headers[i][7]; } @@ -341,8 +342,9 @@ function onOpenClick(event) { var selectedRow = $("searchMailFooter").down("._selected"); var msguid = selectedRow.getAttribute("uid"); var folderName = selectedRow.getAttribute("folderName"); + var accountUser = userNames[0]; - var url = "/SOGo/so/sogo1/Mail" + folderName + "/" + msguid + "/popupview"; + var url = "/SOGo/so/" + accountUser + "/Mail" + folderName + "/" + msguid + "/popupview"; if (selectedRow) { openMessageWindow(msguid, url); } @@ -432,43 +434,50 @@ function deleteMessageCallback (http){ function onResizeClick() { var searchFiltersList = jQuery("#searchFiltersList"); - var searchMailFooter = jQuery("#searchMailFooter"); - var resultsTable = jQuery("#resultsTable"); - var state = 'collapse'; var img = $("listCollapse").select('img').first(); - - + var dialogWindowHeight = $("searchMailView").getHeight(); + var state = "collapse"; + if (searchFiltersList[0].visible()) { + var state = "rise"; searchFiltersList.fadeOut(300, function() { - searchMailFooter.animate({ top:"120px" }, {queue: false, duration: 100}); - resultsTable.animate({height:"288px"}, 100); - searchMailFooter.animate({height:"312px" }, {queue: false, duration: 100, complete: function() { - img.removeClassName('collapse').addClassName('rise'); - $("resultsFound").style.bottom = "40px;"; - }}); + adjustResultsTable(state); + img.removeClassName('collapse').addClassName('rise'); }); } else { - state = 'rise'; - searchMailFooter.animate({height:"194px"}, {queue: false, duration: 100}); - searchMailFooter.animate({top:"240px" }, {queue: false, duration: 100, complete:function() { - searchFiltersList.fadeIn(); - img.removeClassName('rise').addClassName('collapse'); - $("resultsFound").style.bottom = "25px;"; - }}); - resultsTable.animate({height:"171px"}, 100); - + state = "collapse" + adjustResultsTable(state); + searchFiltersList.fadeIn(); + img.removeClassName('rise').addClassName('collapse'); } } +function adjustResultsTable(state) { + var resultsTable = $("resultsTable"); + var width = $("searchMailView").getWidth() - 22; + var height = $("searchMailView").getHeight(); + if (state == "collapse") + height -= 260; + else + height -= 146; + resultsTable.style.width = width + "px"; + resultsTable.style.height = height + "px"; +} + /*************** Init ********************/ function initSearchMailView () { // Add one filterRow onAddFilter(); + adjustResultsTable("collapse"); // Observers : Event.on(element, eventName[, selector], callback) $("searchMailFooter").down("tbody").on("mousedown", "tr", onResultSelectionChange); $("searchMailFooter").down("tbody").on("dblclick", "tr", onOpenClick); + Event.observe(window, "resize", function() { + var state = ($("searchFiltersList").visible() ? "collapse": "rise"); + adjustResultsTable(state); + }); } \ No newline at end of file diff --git a/UI/WebServerResources/generic.css b/UI/WebServerResources/generic.css index b32901017..87b96ca47 100644 --- a/UI/WebServerResources/generic.css +++ b/UI/WebServerResources/generic.css @@ -662,7 +662,8 @@ DIV.dialog.searchMail { position: relative; padding: 0px; opacity: 1; - width: 700px; + width: 60%; + height: 75%; margin: 2em auto; } From 9bd09cc55d08ed34745f4fa51413dc760c7114d1 Mon Sep 17 00:00:00 2001 From: Alexandre Cloutier Date: Thu, 28 Aug 2014 13:20:43 -0400 Subject: [PATCH 09/12] add the location column --- UI/Templates/MailerUI/UIxMailSearch.wox | 2 ++ UI/WebServerResources/UIxMailSearch.js | 9 ++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/UI/Templates/MailerUI/UIxMailSearch.wox b/UI/Templates/MailerUI/UIxMailSearch.wox index 96511446d..3efd2e543 100644 --- a/UI/Templates/MailerUI/UIxMailSearch.wox +++ b/UI/Templates/MailerUI/UIxMailSearch.wox @@ -68,6 +68,8 @@ + +
    diff --git a/UI/WebServerResources/UIxMailSearch.js b/UI/WebServerResources/UIxMailSearch.js index 68ae26ee7..490182854 100644 --- a/UI/WebServerResources/UIxMailSearch.js +++ b/UI/WebServerResources/UIxMailSearch.js @@ -172,8 +172,15 @@ function searchMailsCallback(http) { var cell4 = row.insertCell(3); Element.addClassName(cell4, "td_table_4"); - cell4.writeAttribute("colspan", "2"); cell4.innerHTML = response.headers[i][7]; + + var cell5 = row.insertCell(4); + Element.addClassName(cell5, "td_table_5"); + cell5.writeAttribute("colspan", "2"); + var folderPath = http.callbackData.folderName.split("/"); + var folderLocation = folderPath[folderPath.length - 1]; // get the last element of the array (location) + folderLocation = folderLocation.substr(6); // strip down the prefix folder + cell5.innerHTML = folderLocation; } } From ca8351d1f9097793ed816c099683c3b97e87a13d Mon Sep 17 00:00:00 2001 From: Alexandre Cloutier Date: Thu, 4 Sep 2014 10:50:03 -0400 Subject: [PATCH 10/12] fix IE7, IE8, IE9, IE10, IE11 GUI --- UI/MailerUI/English.lproj/Localizable.strings | 1 + UI/Templates/MailerUI/UIxMailSearch.wox | 12 +- UI/WebServerResources/MailerUI.js | 7 +- UI/WebServerResources/UIxMailSearch.css | 57 +++++--- UI/WebServerResources/UIxMailSearch.js | 123 +++++++++--------- UI/WebServerResources/generic.css | 2 +- UI/WebServerResources/iefixes.css | 3 - 7 files changed, 115 insertions(+), 90 deletions(-) diff --git a/UI/MailerUI/English.lproj/Localizable.strings b/UI/MailerUI/English.lproj/Localizable.strings index 3175b293b..0c16e118b 100644 --- a/UI/MailerUI/English.lproj/Localizable.strings +++ b/UI/MailerUI/English.lproj/Localizable.strings @@ -250,6 +250,7 @@ "No matches found" = "No matches found"; "results found" = "results found"; "result found" = "result found"; +"Please specify at least one filter" = "Please specify at least one filter"; /* Folder operations */ "Name :" = "Name :"; diff --git a/UI/Templates/MailerUI/UIxMailSearch.wox b/UI/Templates/MailerUI/UIxMailSearch.wox index 3efd2e543..cb728c681 100644 --- a/UI/Templates/MailerUI/UIxMailSearch.wox +++ b/UI/Templates/MailerUI/UIxMailSearch.wox @@ -52,10 +52,10 @@ - - - -
    +
    + +
    +
    @@ -85,10 +85,10 @@
    diff --git a/UI/WebServerResources/MailerUI.js b/UI/WebServerResources/MailerUI.js index 77a83a59f..6c94ccbd8 100644 --- a/UI/WebServerResources/MailerUI.js +++ b/UI/WebServerResources/MailerUI.js @@ -434,9 +434,10 @@ function onDocumentKeydown(event) { /* Search mail, call the template and open inside a dialog windoƒw */ function onSearchMail(event) { - if (event.element().disabled == false || event.element().disabled == undefined) { - event.element().disabled = true; - event.element().writeAttribute("id", "toolbarSearchButton"); + var element = Event.findElement(event); + if (element.disabled == false || element.disabled == undefined) { + element.disabled = true; + element.writeAttribute("id", "toolbarSearchButton"); if ($("searchMailView")) { $("searchMailView").style.display = "block"; $("bgDialogDiv").style.display = "block"; diff --git a/UI/WebServerResources/UIxMailSearch.css b/UI/WebServerResources/UIxMailSearch.css index 831f9669e..0bf6e49b7 100644 --- a/UI/WebServerResources/UIxMailSearch.css +++ b/UI/WebServerResources/UIxMailSearch.css @@ -5,23 +5,25 @@ TABLE#searchMailHeader { width: 100%; margin-bottom: 1em; } -TABLE#searchFiltersList +DIV#searchFiltersList { border: 1px solid #909090; padding-top:2px; border-radius: 3px; - display:inline-block; max-height:105px; height:105px; - overflow:auto; + overflow-y:auto; + overflow-x:hidden; width:100%; } DIV#resultsTable { border: 1px solid #909090; + margin-top:5px; border-radius: 3px; overflow-y: auto; + width:100%; } TD#mailAccountsCell { @@ -29,14 +31,25 @@ TD#mailAccountsCell { white-space: nowrap; } -.buttonsCell +TR.filterRow { - width:1%; + width:100%; } -.inputsCell +TR.filterRow > TD { - width:45%; + width: 20%; + vertical-align:middle; +} + +TR.filterRow > TD.buttonsCell +{ + width:7%; +} + +TR.filterRow > TD.inputsCell +{ + width:70%; } .td_table_1, .td_table_2, .td_table_3, .td_table_4 { @@ -58,6 +71,7 @@ TD.sortdesc { } .td_header { + white-space:initial !important; border-bottom: solid #909090 1px; border-right: solid #909090 1px; height:18px; @@ -88,7 +102,7 @@ TD.sortdesc { #headerButtons { - width:171px; + width:175px; white-space: nowrap; } @@ -104,8 +118,14 @@ TD.sortdesc { DIV#optionsButtons { - position:absolute; - bottom:10px; + position:relative; + height:22px; +} + +A#deleteButton, A#openButton +{ + float:left; + margin-top:5px; } .button @@ -131,30 +151,30 @@ DIV#optionsButtons right:10px; } -#imgPosition +DIV#imgPosition { z-index: 1; position:relative; } -#listCollapse img +A#listCollapse > img { position: absolute; } -#listCollapse img.collapse +A#listCollapse > img.collapse { clip: rect(0 18px 18px 0); top: -9px; right: -22px; } -#listCollapse img.collapse:hover +A#listCollapse > img.collapse:hover { clip: rect(0 36px 18px 18px); top: -9px; right: -4px; } -#listCollapse img.rise +A#listCollapse > img.rise { clip: rect(18px 18px 36px 0); top: -27px; right:-22px; } -#listCollapse img.rise:hover +A#listCollapse > img.rise:hover { clip: rect(18px 36px 36px 18px); top: -27px; right:-4px; } @@ -188,6 +208,11 @@ DIV#optionsButtons #filterButtons { width:40px; +} + +IMG.addFilterButton, IMG.removeFilterButton +{ + z-index: 1; cursor:pointer; } diff --git a/UI/WebServerResources/UIxMailSearch.js b/UI/WebServerResources/UIxMailSearch.js index 490182854..fbd3ffa86 100644 --- a/UI/WebServerResources/UIxMailSearch.js +++ b/UI/WebServerResources/UIxMailSearch.js @@ -73,7 +73,8 @@ function onSearchClick() { $("searchButton").down().innerHTML = _("Stop"); searchMails(); } - // TODO - give the user a warning or a notice that it needs at least one filter + else + alert(_("Please specify at least one filter")); } else { stopOngoingSearch = true; @@ -87,8 +88,8 @@ function searchMails() { var nbOptions = optionsList.length; var selectedIndex = optionsList.selectedIndex; var accountNumber, accountUser, folderPath, folderName; - var mailAccountIndex = mailAccounts.indexOf(searchParams.searchLocation); + if (mailAccountIndex != -1) { accountNumber = "/" + mailAccountIndex; folderName = accountNumber + "/folderINBOX"; @@ -101,7 +102,7 @@ function searchMails() { accountNumber = "/" + userNames.indexOf(accountUser); var position = searchLocation.length; - folderName = accountNumber + "/folder" + searchLocation[1].replace(" ", "_SP_"); + folderName = accountNumber + "/folder" + searchLocation[1].asCSSIdentifier(); for (i = 2; i < position; i++) folderName += "/folder" + searchLocation[i]; @@ -126,12 +127,10 @@ function searchMails() { } var urlstr = (ApplicationBaseURL + folderName + "/uids"); - var callbackData = {"folderName" : folderName, "subfolders" : subfolders, "newSearch" : true}; var object = {"filters":searchParams.filters, "sortingAttributes":{"match":searchParams.filterMatching}}; var content = Object.toJSON(object); document.searchMailsAjaxRequest = triggerAjaxRequest(urlstr, searchMailsCallback, callbackData, content, {"content-type": "application/json"}); - } function searchMailsCallback(http) { @@ -143,44 +142,54 @@ function searchMailsCallback(http) { if (http.callbackData.newSearch) { var oldEntries = table.rows; var count = oldEntries.length - 1; - for (x = count; x >= 0; x--) - oldEntries[x].remove(); + for (var x = count; x >= 0; x--){ + $(oldEntries[x]).remove(); + } + + } - + // ["To", "Attachment", "Flagged", "Subject", "From", "Unread", "Priority", "Date", "Size", "rowClasses", "labels", "rowID", "uid"] if (response.headers.length > 1) { if ($("noSearchResults")) $("noSearchResults").remove(); - - for (i = 1; i < response.headers.length; i++) { // Starts at 1 because the position 0 in the array are the headers of the table - var row = table.insertRow(i - 1); // This is the reason why row inserting starts at i - 1 + + for (var i = 1; i < response.headers.length; i++) { // Starts at 1 because the position 0 in the array are the headers of the table + var row = document.createElement("tr"); Element.addClassName(row, "resultsRow"); - row.writeAttribute("uid", response.headers[i][12]); - row.writeAttribute("folderName", http.callbackData.folderName); + row.setAttribute("uid", response.headers[i][12]); + row.setAttribute("folderName", http.callbackData.folderName); - var cell1 = row.insertCell(0); + var cell1 = document.createElement("td"); Element.addClassName(cell1, "td_table_1"); cell1.innerHTML = response.headers[i][3]; + row.appendChild(cell1); - var cell2 = row.insertCell(1); + var cell2 = document.createElement("td"); Element.addClassName(cell2, "td_table_2"); cell2.innerHTML = response.headers[i][4]; + row.appendChild(cell2); - var cell3 = row.insertCell(2); + var cell3 = document.createElement("td"); Element.addClassName(cell3, "td_table_3"); cell3.innerHTML = response.headers[i][0]; + row.appendChild(cell3); - var cell4 = row.insertCell(3); + var cell4 = document.createElement("td"); Element.addClassName(cell4, "td_table_4"); cell4.innerHTML = response.headers[i][7]; + row.appendChild(cell4); - var cell5 = row.insertCell(4); + var cell5 = document.createElement("td"); Element.addClassName(cell5, "td_table_5"); - cell5.writeAttribute("colspan", "2"); + cell5.setAttribute("colspan", "2"); var folderPath = http.callbackData.folderName.split("/"); var folderLocation = folderPath[folderPath.length - 1]; // get the last element of the array (location) folderLocation = folderLocation.substr(6); // strip down the prefix folder cell5.innerHTML = folderLocation; + row.appendChild(cell5); + + table.appendChild(row); } } @@ -190,8 +199,8 @@ function searchMailsCallback(http) { var cell = row.insertCell(0); var element = document.createElement("span"); - cell.writeAttribute("id", "noSearchResults"); - cell.writeAttribute("colspan", "4"); + cell.setAttribute("id", "noSearchResults"); + cell.setAttribute("colspan", "4"); element.innerHTML = _("No matches found"); cell.appendChild(element); } @@ -213,7 +222,6 @@ function searchMailsCallback(http) { else { onSearchEnd(); } - } } @@ -249,33 +257,31 @@ function onMatchFilters(event) { /**** Search mail body ****/ function onAddFilter() { - var table = $("searchFiltersList").down("tbody"); + var table = $("searchFiltersList").down("TABLE"); var searchByList = $("searchByList").getElementsByTagName("li"); var stringArgumentsList = $("stringArgumentsList").getElementsByTagName("li"); - + var rowCount = table.rows.length; var row = table.insertRow(rowCount); Element.addClassName(row, "filterRow"); - + var cell1 = row.insertCell(0); var element1 = document.createElement("select"); Element.addClassName(element1, "searchByList"); - element1.writeAttribute("id", "searchByListRow" + rowCount); - for (i = 0; i < searchByList.length; i++) { + element1.setAttribute("id", "searchByListRow" + rowCount); + for (var i = 0; i < searchByList.length; i++) { var option = document.createElement("option"); - option.writeAttribute("value", i); option.innerHTML = searchByList[i].innerHTML; element1.appendChild(option); } cell1.appendChild(element1); - + var cell2 = row.insertCell(1); var element2 = document.createElement("select"); Element.addClassName(element2, "searchArgumentsList"); - element2.writeAttribute("id", "searchArgumentsListRow" + rowCount); - for (i = 0; i < stringArgumentsList.length; i++) { + element2.setAttribute("id", "searchArgumentsListRow" + rowCount); + for (var i = 0; i < stringArgumentsList.length; i++) { var option = document.createElement("option"); - option.writeAttribute("value", i); option.innerHTML = stringArgumentsList[i].innerHTML; element2.appendChild(option); } @@ -285,10 +291,9 @@ function onAddFilter() { Element.addClassName(cell3, "inputsCell"); var element3 = document.createElement("input"); Element.addClassName(element3, "searchInput"); - element3.writeAttribute("type", "text"); - element3.writeAttribute("name", "searchInput"); - element3.writeAttribute("value", ""); - element3.writeAttribute("id", "searchInputRow" + rowCount); + element3.setAttribute("type", "text"); + element3.setAttribute("name", "searchInput"); + element3.setAttribute("id", "searchInputRow" + rowCount); cell3.appendChild(element3); var cell4 = row.insertCell(3); @@ -297,33 +302,32 @@ function onAddFilter() { var buttonsDiv = document.createElement("div"); var imageAddFilter = document.createElement("img"); var imageRemoveFilter = document.createElement("img"); - imageAddFilter.writeAttribute("src", "/SOGo.woa/WebServerResources/add-icon.png"); - imageRemoveFilter.writeAttribute("src", "/SOGo.woa/WebServerResources/remove-icon.png"); + imageAddFilter.setAttribute("src", "/SOGo.woa/WebServerResources/add-icon.png"); + imageRemoveFilter.setAttribute("src", "/SOGo.woa/WebServerResources/remove-icon.png"); Element.addClassName(imageAddFilter, "addFilterButton"); Element.addClassName(imageAddFilter, "glow"); Element.addClassName(imageRemoveFilter, "removeFilterButton"); Element.addClassName(imageRemoveFilter, "glow"); - imageAddFilter.writeAttribute("name", "addFilter"); - imageAddFilter.writeAttribute("id", "addFilterButtonRow" + rowCount); - imageAddFilter.writeAttribute("onclick", "onAddFilter(this)"); - imageRemoveFilter.writeAttribute("name", "removeFilter"); - imageRemoveFilter.writeAttribute("id", "removeFilterButtonRow" + rowCount); - imageRemoveFilter.writeAttribute("onclick", "onRemoveFilter(this)"); - buttonsDiv.writeAttribute("id", "filterButtons"); + imageAddFilter.setAttribute("name", "addFilter"); + imageAddFilter.setAttribute("id", "addFilterButtonRow" + rowCount); + $(imageAddFilter).on("click", onAddFilter); + imageRemoveFilter.setAttribute("name", "removeFilter"); + imageRemoveFilter.setAttribute("id", "removeFilterButtonRow" + rowCount); + $(imageRemoveFilter).on("click", onRemoveFilter); + buttonsDiv.setAttribute("id", "filterButtons"); buttonsDiv.appendChild(imageAddFilter); buttonsDiv.appendChild(imageRemoveFilter); cell4.appendChild(buttonsDiv); - } -function onRemoveFilter(event) { - var rows = $("searchFiltersList").down("tbody").getElementsByTagName("tr"); - var currentRow = event.up(".filterRow"); +function onRemoveFilter() { + var rows = $("searchFiltersList").getElementsByTagName("tr"); + var currentRow = this.up(".filterRow"); if(rows.length > 1) - currentRow.remove(); + $(currentRow).remove(); } /**** Search mail Footer ****/ @@ -358,23 +362,23 @@ function onOpenClick(event) { } function onDeleteClick(event) { - var messageList = $("resultsTable"); - var row = messageList.getSelectedRows()[0]; + var messageList = $("resultsTable").down("TABLE"); + var row = $(messageList).getSelectedRows()[0]; if (row) { - var rowIds = messageList.getSelectedRows()[0].getAttribute("uid"); + var rowIds = row.getAttribute("uid"); var uids = new Array(); // message IDs var paths = new Array(); // row IDs var unseenCount = 0; var refreshFolder = false; - - if (rowIds && rowIds.length > 0) { + if (rowIds) { messageList.deselectAll(); if (unseenCount < 1) { - row.remove(); if (row.hasClassName("mailer_unreadmail")) unseenCount--; else unseenCount = 1; + + $(row).remove(); } var uid = rowIds; var path = Mailer.currentMailbox + "/" + uid; @@ -387,7 +391,6 @@ function onDeleteClick(event) { if (messageContent) messageContent.innerHTML = ''; Mailer.currentMessages[Mailer.currentMailbox] = null; } - Mailer.dataTable.remove(uid); updateMessageListCounter(0 - rowIds.length, true); if (unseenCount < 0) { @@ -462,13 +465,11 @@ function onResizeClick() { function adjustResultsTable(state) { var resultsTable = $("resultsTable"); - var width = $("searchMailView").getWidth() - 22; var height = $("searchMailView").getHeight(); if (state == "collapse") - height -= 260; + height = height - 266; else - height -= 146; - resultsTable.style.width = width + "px"; + height = height - 152; resultsTable.style.height = height + "px"; } diff --git a/UI/WebServerResources/generic.css b/UI/WebServerResources/generic.css index 87b96ca47..dfd2aecfb 100644 --- a/UI/WebServerResources/generic.css +++ b/UI/WebServerResources/generic.css @@ -662,7 +662,7 @@ DIV.dialog.searchMail { position: relative; padding: 0px; opacity: 1; - width: 60%; + width: 75%; height: 75%; margin: 2em auto; } diff --git a/UI/WebServerResources/iefixes.css b/UI/WebServerResources/iefixes.css index aaf871494..be993817a 100644 --- a/UI/WebServerResources/iefixes.css +++ b/UI/WebServerResources/iefixes.css @@ -54,9 +54,6 @@ DIV.colorBox IMG.dragMessage { filter: alpha(opacity=70); } -TABLE.messageList TD -{ white-space: pre; } - TABLE.messageList TR._selected TD { border-right: 1px solid #9ABCD8 !important; } From 984e208dd938911cdb091514e8da2a3f328bedce Mon Sep 17 00:00:00 2001 From: Alexandre Cloutier Date: Fri, 5 Sep 2014 11:01:57 -0400 Subject: [PATCH 11/12] IE bugfixes --- UI/Templates/MailerUI/UIxMailSearch.wox | 4 ++-- UI/WebServerResources/UIxMailSearch.css | 13 +++++++++---- UI/WebServerResources/UIxMailSearch.js | 12 +++++++----- UI/WebServerResources/generic.css | 2 +- UI/WebServerResources/iefixes.css | 3 +++ 5 files changed, 22 insertions(+), 12 deletions(-) diff --git a/UI/Templates/MailerUI/UIxMailSearch.wox b/UI/Templates/MailerUI/UIxMailSearch.wox index cb728c681..2691ec54a 100644 --- a/UI/Templates/MailerUI/UIxMailSearch.wox +++ b/UI/Templates/MailerUI/UIxMailSearch.wox @@ -57,7 +57,7 @@
    - +
    - +
    @@ -79,7 +79,7 @@
    diff --git a/UI/WebServerResources/UIxMailSearch.css b/UI/WebServerResources/UIxMailSearch.css index 0bf6e49b7..c513b760f 100644 --- a/UI/WebServerResources/UIxMailSearch.css +++ b/UI/WebServerResources/UIxMailSearch.css @@ -26,12 +26,15 @@ DIV#resultsTable width:100%; } +TABLE.messageList TD +{ white-space: normal !important; } + TD#mailAccountsCell { overflow:hidden; white-space: nowrap; } -TR.filterRow +TR.filterRow, DIV#searchFiltersList > TABLE { width:100%; } @@ -44,12 +47,12 @@ TR.filterRow > TD TR.filterRow > TD.buttonsCell { - width:7%; + width:5%; } TR.filterRow > TD.inputsCell { - width:70%; + width:55%; } .td_table_1, .td_table_2, .td_table_3, .td_table_4 { @@ -113,7 +116,9 @@ TD.sortdesc { .searchByList, .searchArgumentsList, .searchInput { - width:100%; + width:98%; + paddin:0; + margin:0; } DIV#optionsButtons diff --git a/UI/WebServerResources/UIxMailSearch.js b/UI/WebServerResources/UIxMailSearch.js index fbd3ffa86..4aa9a8790 100644 --- a/UI/WebServerResources/UIxMailSearch.js +++ b/UI/WebServerResources/UIxMailSearch.js @@ -298,6 +298,7 @@ function onAddFilter() { var cell4 = row.insertCell(3); Element.addClassName(cell4, "buttonsCell"); + cell4.setAttribute("align", "center"); var buttonsDiv = document.createElement("div"); var imageAddFilter = document.createElement("img"); @@ -465,12 +466,13 @@ function onResizeClick() { function adjustResultsTable(state) { var resultsTable = $("resultsTable"); - var height = $("searchMailView").getHeight(); - if (state == "collapse") - height = height - 266; + var height = "innerHeight" in $("searchMailView") ? $("searchMailView").innerHeight : $("searchMailView").offsetHeight; + if (state == "collapse") { + height -= 266; + } else - height = height - 152; - resultsTable.style.height = height + "px"; + height -= 152; + $(resultsTable).style.height = height + "px"; } /*************** Init ********************/ diff --git a/UI/WebServerResources/generic.css b/UI/WebServerResources/generic.css index dfd2aecfb..4b7a87351 100644 --- a/UI/WebServerResources/generic.css +++ b/UI/WebServerResources/generic.css @@ -668,7 +668,7 @@ DIV.dialog.searchMail { } DIV.dialog.searchMail > DIV { - min-height:467px; + min-height:500px; } DIV.dialog.none diff --git a/UI/WebServerResources/iefixes.css b/UI/WebServerResources/iefixes.css index be993817a..aaf871494 100644 --- a/UI/WebServerResources/iefixes.css +++ b/UI/WebServerResources/iefixes.css @@ -54,6 +54,9 @@ DIV.colorBox IMG.dragMessage { filter: alpha(opacity=70); } +TABLE.messageList TD +{ white-space: pre; } + TABLE.messageList TR._selected TD { border-right: 1px solid #9ABCD8 !important; } From b639c2d251c48a5ab6498a81e8a40fb3f153ef84 Mon Sep 17 00:00:00 2001 From: Francis Lachapelle Date: Fri, 5 Sep 2014 16:04:29 -0400 Subject: [PATCH 12/12] Fixes for IE --- UI/Templates/MailerUI/UIxMailSearch.wox | 30 +++++------ UI/WebServerResources/UIxMailSearch.css | 72 ++++++------------------- UI/WebServerResources/UIxMailSearch.js | 5 +- 3 files changed, 31 insertions(+), 76 deletions(-) diff --git a/UI/Templates/MailerUI/UIxMailSearch.wox b/UI/Templates/MailerUI/UIxMailSearch.wox index 2691ec54a..9e5707420 100644 --- a/UI/Templates/MailerUI/UIxMailSearch.wox +++ b/UI/Templates/MailerUI/UIxMailSearch.wox @@ -53,28 +53,22 @@
    - -
    +
    - - - - - - - + + + + + + + diff --git a/UI/WebServerResources/UIxMailSearch.css b/UI/WebServerResources/UIxMailSearch.css index c513b760f..37302c61e 100644 --- a/UI/WebServerResources/UIxMailSearch.css +++ b/UI/WebServerResources/UIxMailSearch.css @@ -26,9 +26,6 @@ DIV#resultsTable width:100%; } -TABLE.messageList TD -{ white-space: normal !important; } - TD#mailAccountsCell { overflow:hidden; white-space: nowrap; @@ -90,15 +87,7 @@ TD.sortdesc { {text-decoration: underline; } #buttonExpandHeader { - width:10px; -} - -@-moz-document url-prefix() { - #buttonExpandHeader { - width:1.5%; - border-right:0; - } - + width: 20px; } /*************** Button adjustment *****************/ @@ -156,60 +145,33 @@ A#deleteButton, A#openButton right:10px; } -DIV#imgPosition -{ z-index: 1; - position:relative; } +#listCollapse +{ position: relative; + border: 1px solid transparent; } -A#listCollapse > img +#listCollapse img { position: absolute; } -A#listCollapse > img.collapse +#listCollapse img.collapse { clip: rect(0 18px 18px 0); - top: -9px; - right: -22px; } + top: 0; + left: 0; } -A#listCollapse > img.collapse:hover +#listCollapse img.collapse:hover { clip: rect(0 36px 18px 18px); - top: -9px; - right: -4px; } + top: 0; + left: -18px; } -A#listCollapse > img.rise +#listCollapse img.rise { clip: rect(18px 18px 36px 0); - top: -27px; - right:-22px; - } + top: -18px; + left: 0; } -A#listCollapse > img.rise:hover +#listCollapse img.rise:hover { clip: rect(18px 36px 36px 18px); - top: -27px; - right:-4px; } + top: -18px; + left: -18px; } -@-moz-document url-prefix() { - #listCollapse img - { position: absolute; } - - #listCollapse img.collapse - { clip: rect(0 18px 18px 0); - top: 2px; - right: -16px; } - - #listCollapse img.collapse:hover - { clip: rect(0 36px 18px 18px); - top: 2px; - right: 2px; } - - #listCollapse img.rise - { clip: rect(18px 18px 36px 0); - top: -16px; - right:-16px; - } - - #listCollapse img.rise:hover - { clip: rect(18px 36px 36px 18px); - top: -16px; - right:2px; } -} - #filterButtons { width:40px; diff --git a/UI/WebServerResources/UIxMailSearch.js b/UI/WebServerResources/UIxMailSearch.js index 4aa9a8790..c0196a6ad 100644 --- a/UI/WebServerResources/UIxMailSearch.js +++ b/UI/WebServerResources/UIxMailSearch.js @@ -450,14 +450,13 @@ function onResizeClick() { var state = "collapse"; if (searchFiltersList[0].visible()) { - var state = "rise"; + state = "rise"; searchFiltersList.fadeOut(300, function() { adjustResultsTable(state); img.removeClassName('collapse').addClassName('rise'); }); } else { - state = "collapse" adjustResultsTable(state); searchFiltersList.fadeIn(); img.removeClassName('rise').addClassName('collapse'); @@ -490,4 +489,4 @@ function initSearchMailView () { var state = ($("searchFiltersList").visible() ? "collapse": "rise"); adjustResultsTable(state); }); -} \ No newline at end of file +}
    - - - - - -