Various search improvements
authorMichael M Slusarz <slusarz@curecanti.org>
Tue, 15 Sep 2009 09:57:26 +0000 (03:57 -0600)
committerMichael M Slusarz <slusarz@curecanti.org>
Tue, 15 Sep 2009 10:09:20 +0000 (04:09 -0600)
imp/js/search.js
imp/lib/LoginTasks/SystemTask/UpgradeFromImp4.php
imp/lib/Search.php
imp/lib/UI/Search.php
imp/search-basic.php
imp/search.php
imp/templates/search/search.html
imp/themes/screen.css

index 1c91527..8a49427 100644 (file)
@@ -7,7 +7,8 @@
 
 var ImpSearch = {
     // The following variables are defined in search.php:
-    //   loading, months, need_criteria, need_folder, types
+    //   loading, months, need_criteria, need_folder, need_vfolder_label,
+    //   types
     criteria: {},
     saved_searches: {},
     show_unsub: false,
@@ -20,7 +21,9 @@ var ImpSearch = {
     selectFolders: function(checked)
     {
         this._getAll().each(function(e) {
-            e.checked = checked;
+            if (!e.disabled) {
+                e.checked = Boolean(checked);
+            }
         });
     },
 
@@ -94,7 +97,7 @@ var ImpSearch = {
 
     resetCriteria: function()
     {
-        $('search_criteria').siblings().invoke('remove');
+        $('search_criteria_table').childElements().invoke('remove');
     },
 
     changeHandler: function(e)
@@ -138,45 +141,51 @@ var ImpSearch = {
         return $('search_criteria').down('[value=' + id + ']').getText() + ': ';
     },
 
-    insertCriteria: function(elt)
+    insertCriteria: function(tds)
     {
-        var div = new Element('DIV').insert(elt.writeAttribute('id', null).show()).insert($($('delete_criteria').cloneNode(true)).writeAttribute('id', null).show());
-        $('search_criteria').insert({ before: div }).setValue('');
-        return div.identify();
+        var tr = new Element('TR');
+        tds.each(function(td) {
+            tr.insert(new Element('TD').insert(td));
+        });
+        tr.childElements().last().insert(new Element('A', { href: '#', className: 'searchuiImg searchuiDelete' }));
+        $('search_criteria').setValue('');
+        $('search_criteria_table').insert(tr);
+        return tr.identify();
     },
 
     insertText: function(id, text, not)
     {
-        var tmp = $($('text_criteria').cloneNode(true));
-        tmp.down('EM').insert(this.getLabel(id));
-        tmp.down('INPUT').setValue(text);
-        if (not) {
-            tmp.down('INPUT', 1).writeAttribute('checked', true);
-        }
+        var tmp = [
+            new Element('EM').insert(this.getLabel(id)),
+            new Element('INPUT', { type: 'text', size: 25 }),
+            new Element('SPAN').insert(new Element('INPUT', { checked: Boolean(not), className: 'checkbox', type: 'checkbox' })).insert(this.not_match)
+        ];
         this.criteria[this.insertCriteria(tmp)] = { t: id };
     },
 
     insertSize: function(id, size)
     {
-        var tmp = $($('text_criteria').cloneNode(true));
-        tmp.down('EM').insert(this.getLabel(id));
-        // Convert from bytes to KB
-        tmp.down('INPUT').writeAttribute('size', 10).setValue(Object.isNumber(size) ? Math.round(size / 1024) : '');
-        tmp.down('SPAN').hide();
+        var tmp = [
+            new Element('EM').insert(this.getLabel(id)),
+            // Convert from bytes to KB
+            new Element('INPUT', { type: 'text', size: 10 }).setValue(Object.isNumber(size) ? Math.round(size / 1024) : '')
+        ];
         this.criteria[this.insertCriteria(tmp)] = { t: id };
     },
 
     insertDate: function(id, data)
     {
         var d = (data ? new Date(data.y, data.m, data.d) : new Date()),
-            tmp = $($('date_criteria').cloneNode(true));
-        tmp.down('EM').insert(this.getLabel(id));
+            tmp = [
+                new Element('EM').insert(this.getLabel(id)),
+                new Element('SPAN').insert(new Element('SPAN')).insert(new Element('A', { href: '#', className: 'calendarPopup', title: this.dateselection }).insert(new Element('SPAN', { className: 'searchuiImg searchuiCalendar' })))
+            ];
         this.replaceDate(this.insertCriteria(tmp), id, { y: d.getFullYear(), m: d.getMonth(), d: d.getDate() });
     },
 
     replaceDate: function(id, type, data)
     {
-        $(id).down('SPAN', 1).update(this.months[data.m] + ' ' + data.d + ', ' + data.y);
+        $(id).down('TD SPAN SPAN').update(this.months[data.m] + ' ' + data.d + ', ' + data.y);
         // Need to store date information at all times in criteria, since we
         // have no other way to track this information (there is not form
         // field for this type).
@@ -185,7 +194,10 @@ var ImpSearch = {
 
     insertFlag: function(id)
     {
-        var tmp = $($('flag_criteria').cloneNode(true)).insert({ bottom: this.getLabel(id) } );
+        var tmp = [
+            new Element('EM').insert(this.flag),
+            this.getLabel(id).slice(0, -2)
+        ];
         this.criteria[this.insertCriteria(tmp)] = { t: id };
     },
 
@@ -196,7 +208,7 @@ var ImpSearch = {
         if (!this._getAll().findAll(function(i) { return i.checked; }).size()) {
             alert(this.need_folder);
         } else {
-            tmp = $('search_criteria').siblings().pluck('id');
+            tmp = $('search_criteria_table').childElements().pluck('id');
             if (tmp.size()) {
                 tmp.each(function(c) {
                     var tmp2;
@@ -282,17 +294,17 @@ var ImpSearch = {
                     elt.hasClassName('arrowCollapsed')) {
                     elt.up().down().toggle().next().toggle().up().next().toggle();
                     if (elt.descendantOf('search_folders_hdr')) {
-                        elt.next('SPAN.item').toggle();
+                        elt.next('SPAN.searchFoldersActions').toggle();
                     }
                 } else if (elt.hasClassName('searchuiDelete')) {
-                    tmp = elt.up('DIV');
+                    tmp = elt.up('TR');
                     delete this.criteria[tmp.identify()];
                     tmp.remove();
                     e.stop();
                     return;
                 } else if (elt.hasClassName('searchuiCalendar')) {
-                    tmp = this.criteria[elt.up('DIV').identify()];
-                    Horde_Calendar.open(elt.identify(), { y: tmp.v.y, m: tmp.v.m + 1, d: tmp.v.d }, this.replaceDate.bind(this, elt.up('DIV').identify(), tmp.t));
+                    tmp = this.criteria[elt.up('TR').identify()];
+                    Horde_Calendar.open(elt.identify(), { y: tmp.v.y, m: tmp.v.m + 1, d: tmp.v.d }, this.replaceDate.bind(this, elt.up('TR').identify(), tmp.t));
                     e.stop();
                     return;
                 }
index dfee404..2ef3fc5 100644 (file)
@@ -26,8 +26,7 @@ class IMP_LoginTasks_SystemTask_UpgradeFromImp4 extends Horde_LoginTasks_SystemT
     {
         IMP::initialize();
 
-        /* IMP 4 upgrade: check for old, non-existent sort values.
-         * See Bug #7296. */
+        /* Check for old, non-existent sort values. See Bug #7296. */
         $sortby = $GLOBALS['prefs']->getValue('sortby');
         if ($sortby > 10) {
             $GLOBALS['prefs']->setValue('sortby', Horde_Imap_Client::SORT_ARRIVAL);
@@ -44,6 +43,8 @@ class IMP_LoginTasks_SystemTask_UpgradeFromImp4 extends Horde_LoginTasks_SystemT
         if ($update) {
             $GLOBALS['prefs']->setValue('sortpref', serialize($sortpref));
         }
+
+        /* Upgrade old virtual folders. */
     }
 
 }
index da1db54..33e35f1 100644 (file)
@@ -130,15 +130,20 @@ class IMP_Search
                 'type' => 'header',
                 'not' => true
             ),
+            'custom' => array(
+                'label' => _("Custom Header"),
+                'type' => 'customhdr',
+                'not' => true
+            ),
             'body' => array(
                'label' => _("Body"),
                'type' => 'body',
-                'not' => true
+               'not' => true
             ),
             'text' => array(
                'label' => _("Entire Message"),
                'type' => 'text',
-                'not' => true
+               'not' => true
             ),
             'date_on' => array(
                 'label' => _("Date ="),
index 9cc82e2..34feb3a 100644 (file)
@@ -94,10 +94,15 @@ class IMP_UI_Search
         $c_list = array();
 
         if ($criteria) {
+            $search_fields = $GLOBALS['imp_search']->searchFields();
             $tmp = new stdClass;
             $tmp->t = $criteria;
-            $tmp->v = $text;
-            $tmp->n = $not;
+            $tmp->v = ($search_fields[$criteria]['type'] == 'size')
+                ? floatval($text) * 1024
+                : $text;
+            if ($search_fields[$criteria]['not']) {
+                $tmp->n = (bool)$not;
+            }
             $c_list[] = $tmp;
         }
 
index ae05418..ac1fedd 100644 (file)
@@ -39,7 +39,7 @@ $f_fields = $s_fields = array();
 $search_mailbox = Horde_Util::getFormData('search_mailbox');
 
 foreach ($imp_search->searchFields() as $key => $val) {
-    if ($val['type'] != 'date') {
+    if (!in_array($val['type'], array('customhdr', 'date'))) {
         $s_fields[] = array(
             'val' => $key,
             'label' => $val['label']
index 043eca6..54f45e0 100644 (file)
@@ -8,15 +8,14 @@
  * ---------------
  * 'criteria_form' - (string) JSON representation of the search query.
  * 'edit_query' - (string) The search query to edit.
+ * 'edit_query_vfolder' - (string) The name of the vfolder being edited.
+ * 'search_folders_form' - (array) The list of folders to add to the query.
  * 'search_mailbox' - (string) Use this mailbox as the default value.
  *                    DEFAULT: INBOX
- *
- * TODO:
- * 'edit_query_vfolder'
- * 'search_folders_form[]'
- * 'show_unsub'
- * 'vfolder_label'
- * 'vfolder_save'
+ * 'show_unsub' - (integer) If set, return a JSON object with folder
+ *                information used to create the folder list.
+ * 'vfolder_label' - (string) The label to use when saving as a virtual folder.
+ * 'vfolder_save' - (boolean) If set, save search as a virtual folder.
  *
  * Copyright 1999-2009 The Horde Project (http://www.horde.org/)
  *
@@ -41,8 +40,7 @@ if (!$browser->hasFeature('javascript') ||
 
 $charset = Horde_Nls::getCharset();
 $criteria = Horde_Util::getFormData('criteria_form');
-$edit_query = Horde_Util::getFormData('edit_query');
-$imp_search_fields = $imp_search->searchFields();
+$search_fields = $imp_search->searchFields();
 
 /* Generate the search query if 'criteria_form' is present in the form
  * data. */
@@ -114,8 +112,10 @@ $t = new Horde_Template();
 $t->setOption('gettext', true);
 $t->set('action', Horde::applicationUrl('search.php'));
 $t->set('subscribe', $subscribe);
+$t->set('virtualfolder', $_SESSION['imp']['protocol'] != 'pop');
 
 /* Determine if we are editing a current search folder. */
+$edit_query = Horde_Util::getFormData('edit_query');
 if (!is_null($edit_query) && $imp_search->isSearchMbox($edit_query)) {
     if ($imp_search->isVFolder($edit_query)) {
         if (!$imp_search->isEditableVFolder($edit_query)) {
@@ -131,7 +131,7 @@ if (!is_null($edit_query) && $imp_search->isSearchMbox($edit_query)) {
 $f_fields = $s_fields = $types = array();
 
 /* Process the list of fields. */
-foreach ($imp_search_fields as $key => $val) {
+foreach ($search_fields as $key => $val) {
     $s_fields[] = array(
         'val' => $key,
         'label' => $val['label']
@@ -149,16 +149,17 @@ foreach ($imp_search->flagFields() as $key => $val) {
 }
 $t->set('f_fields', $f_fields);
 
-$t->set('virtualfolder', $_SESSION['imp']['protocol'] != 'pop');
-
 Horde_UI_JsCalendar::init();
 
 Horde::addInlineScript(array(
+    'ImpSearch.dateselection = ' . Horde_Serialize::serialize(_("Date Selection"), Horde_Serialize::JSON, $charset),
+    'ImpSearch.flag = ' . Horde_Serialize::serialize(_("Flag:"), Horde_Serialize::JSON, $charset),
     'ImpSearch.loading = ' . Horde_Serialize::serialize(_("Loading..."), Horde_Serialize::JSON, $charset),
     'ImpSearch.months = ' . Horde_Serialize::serialize(Horde_UI_JsCalendar::months(), Horde_Serialize::JSON, $charset),
     'ImpSearch.need_criteria = ' . Horde_Serialize::serialize(_("Please select at least one search criteria."), Horde_Serialize::JSON, $charset),
     'ImpSearch.need_folder = ' . Horde_Serialize::serialize(_("Please select at least one folder to search."), Horde_Serialize::JSON, $charset),
     'ImpSearch.need_vfolder_label = ' . Horde_Serialize::serialize(_("Virtual Folders require a label."), Horde_Serialize::JSON, $charset),
+    'ImpSearch.not_match = ' . Horde_Serialize::serialize(_("Do NOT Match"), Horde_Serialize::JSON, $charset),
     'ImpSearch.types = ' . Horde_Serialize::serialize($types, Horde_Serialize::JSON, $charset)
 ));
 Horde::addInlineScript($on_domload, 'dom');
index e451579..b81ffe4 100644 (file)
@@ -25,6 +25,7 @@
  </div>
 
  <div class="item">
+  <table id="search_criteria_table"></table>
   <div>
    <select id="search_criteria">
     <option value=""><gettext>Add search criteria:</gettext></option>
@@ -44,7 +45,7 @@
   <span class="searchuiImg arrowExpanded" style="display:none"></span>
   <span class="searchuiImg arrowCollapsed"></span>
   <gettext>Search Folders</gettext>
-  <span class="item" style="display:none">
+  <span class="searchFoldersActions" style="display:none">
    <a id="link_sel_all" href="#"><gettext>Select all</gettext></a> |
    <a id="link_sel_none" href="#"><gettext>Select none</gettext></a>
 <if:subscribe>
  </div>
 </form>
 
-<span id="text_criteria" style="display:none">
- <em></em>
- <input type="text" size="25" />
- <span><input type="checkbox" /><gettext>Do NOT Match</gettext></input></span>
-</span>
-
-<span id="flag_criteria" style="display:none">
- <em><gettext>Flag</gettext>: </em>
-</span>
-
-<span id="date_criteria" style="display:none">
- <em></em>
- <span></span>
- <a href="#" class="calendarPopup" title="<gettext>Date Selection</gettext>"><span class="searchuiImg searchuiCalendar"></span></a>
-</span>
-
-<span id="delete_criteria" style="display:none">
- <a href="#" class="searchuiImg searchuiDelete"></a>
-</span>
-
 <div id="folder_row" style="display:none">
  <input type="checkbox" class="checkbox" name="search_folders_form[]" />
 </div>
index 47fc99d..b9c8be5 100644 (file)
@@ -164,6 +164,10 @@ div.msgActions, #fmanager div.folderActions {
 .searchuiCalendar {
     background-image: url("graphics/calendar.png");
 }
+.searchFoldersActions {
+    margin-left: 20px;
+    font-size: 90%;
+}
 
 /* Folder view. */
 #fmanager div, #fmanager div input {