Improve quicksearch in dimp.
authorMichael M Slusarz <slusarz@curecanti.org>
Tue, 14 Apr 2009 19:09:23 +0000 (13:09 -0600)
committerMichael M Slusarz <slusarz@curecanti.org>
Tue, 14 Apr 2009 19:20:15 +0000 (13:20 -0600)
An example of improvement by subtraction - quicksearch in dimp view
should only search entire text of all messages only in the current mailbox.
More advanced search queries need to be implemented in a different UI -
a UI that will be incorporated in the regular imp view also.

Additionally, remove filter interface from ViewPort.  A filter interface
to viewport doesn't make much sense, especially considering the entire
data for the view may not be loaded in the browser.  It is best to deal
with these search views entirely on the server.

imp/ajax.php
imp/config/conf.xml
imp/docs/CHANGES
imp/js/src/DimpBase.js
imp/js/src/ViewPort.js
imp/lib/DIMP.php
imp/lib/Views/ListMessages.php
imp/templates/index/index-dimp.inc
imp/templates/javascript/mailbox-dimp.js
imp/themes/screen-dimp.css

index d7ab9ac..ac4716c 100644 (file)
@@ -69,11 +69,10 @@ function _getListMessages($mbox, $change)
     $args = array(
         'cached' => Util::getPost('cached'),
         'cacheid' => Util::getPost('cacheid'),
-        'filter' => Util::getPost('filter'),
         'mbox' => $mbox,
         'rangeslice' => Util::getPost('rangeslice'),
-        'searchfolder' => Util::getPost('searchfolder'),
-        'searchmsg' => Util::getPost('searchmsg'),
+        'qsearch' => Util::getPost('qsearch'),
+        'qsearchmbox' => Util::getPost('qsearchmbox'),
     );
 
     $search = Util::getPost('search');
index 95cb2e0..f2f90e3 100644 (file)
     background?">true</configboolean>
    </configsection>
 
-   <configheader>Search Settings</configheader>
-   <configsection name="search">
-    <configboolean name="search_all" desc="Allow user to search all mailboxes
-    at a single time? Unless your mail server is optimized to perform searches,
-    enabling this can cause massive server load if a user has a large
-    mailbox.">false</configboolean>
-   </configsection>
-
    <configsection name="menu" desc="Menu Settings">
     <configheader>Menu Settings</configheader>
     <configmultienum name="apps" desc="Select any applications that should be
index 5b5584c..048eccf 100644 (file)
@@ -2,6 +2,7 @@
 v5.0-git
 --------
 
+[mms] Simplify quicksearch UI in DIMP.
 [mms] Improve notification display (DIMP).
 [mms] Use mailbox names in folder confirmation actions (DIMP) (Request #8162).
 [mms] Optimize viewport row insertion/updating (DIMP).
index fbefc27..0e105db 100644 (file)
@@ -9,29 +9,17 @@
 
 var DimpBase = {
     // Vars used and defaulting to null/false:
-    //   cfolderaction, filter_on, filtertoggle, fl_visible, folder,
-    //   folderswitch, fspecial, isvisible, message_list_template, offset,
-    //   pollPE, pp, uid, viewport
+    //   cfolderaction, fl_visible, folder, folderswitch, isvisible,
+    //   message_list_template, offset, pollPE, pp, sfolder, uid, viewport
     bcache: $H(),
     cacheids: {},
     lastrow: -1,
     pivotrow: -1,
     ppcache: {},
     ppfifo: [],
+    searchid: 'dimp\x00qsearch',
     tcache: {},
 
-    sfiltersfolder: $H({
-        sf_all: 'all',
-        sf_current: 'current'
-    }),
-
-    sfilters: $H({
-        sf_msgall: 'msgall',
-        sf_from: 'from',
-        sf_to: 'to',
-        sf_subject: 'subject'
-    }),
-
     // Message selection functions
 
     // vs = (ViewPort_Selection) A ViewPort_Selection object.
@@ -94,7 +82,7 @@ var DimpBase = {
         // from the search input, because the user may immediately start
         // keyboard navigation after that. Thus, we need to ensure that a
         // message click loses focus on the search input.
-        $('msgList_filter').blur();
+        $('quicksearch').blur();
 
         if (opts.shift) {
             if (selcount) {
@@ -224,7 +212,7 @@ var DimpBase = {
                     this._addHistory(loc);
                 }
             }
-            this.loadFolder(f);
+            this.loadMailbox(f);
             return;
         }
 
@@ -351,35 +339,35 @@ var DimpBase = {
         });
     },
 
-    loadFolder: function(f, background)
+    loadMailbox: function(f, opts)
     {
+        opts = opts || {};
+
         if (!this.viewport) {
             this._createViewPort();
         }
 
-        if (!background) {
+        if (!opts.background) {
             this.resetSelected();
+            this.quicksearchClear(true);
 
             if (this.folder == f) {
-                this.searchfilterClear(false);
                 return;
             }
 
-            this.searchfilterClear(true);
             $('folderName').update(DIMP.text.loading);
             $('msgHeader').update();
             this.folderswitch = true;
             this.folder = f;
         }
 
-        this.viewport.loadView(f, this.uid ? { imapuid: this.uid, view: f } : null, background);
+        this.viewport.loadView(f, this.uid ? { imapuid: this.uid, view: f } : null, opts.background);
     },
 
     _createViewPort: function()
     {
-        var mf = $('msgList_filter'),
-            // No need to cache - this function only called once.
-            settitle = this.setMessageListTitle.bind(this);
+        // No need to cache - this function only called once.
+        var settitle = this.setMessageListTitle.bind(this);
 
         this.viewport = new ViewPort({
             content_container: 'msgList',
@@ -402,14 +390,11 @@ var DimpBase = {
             onScrollIdle: settitle,
             onSlide: settitle,
             onContent: function(row) {
-                var bg, search, u,
+                var bg, re, search, u,
                     thread = ((this.viewport.getMetaData('sortby') == DIMP.conf.sortthread) && this.viewport.getMetaData('thread'));
 
-                if (this.viewport.isFiltering()) {
-                    search = this.sfilters.get(this._getSearchfilterField());
-                }
-
                 row.subjectdata = row.status = '';
+                row.subjecttitle = row.subject;
 
                 // Add thread graphics
                 if (thread && thread.get(row.imapuid)) {
@@ -453,17 +438,21 @@ var DimpBase = {
                     row.style = 'background:' + bg;
                 }
 
-                // Highlight search terms
-                if (search == 'from' || search == 'subject') {
-                    row[search] = row[search].gsub(new RegExp("(" + $F('msgList_filter') + ")", "i"), '<span class="searchMatch">#{1}</span>');
+                // Check for search strings
+                if (this.isSearch()) {
+                    re = new RegExp("(" + $F('quicksearch') + ")", "i");
+                    [ 'from', 'subject' ].each(function(h) {
+                        row[h] = row[h].gsub(re, '<span class="quicksearchMatch">#{1}</span>');
+                    });
                 }
 
-                // If null, invalid string was scrubbed by JSON encode.
+                // If these fields are null, invalid string was scrubbed by
+                // JSON encode.
                 if (row.from === null) {
                     row.from = '[' + DIMP.text.badaddr + ']';
                 }
                 if (row.subject === null) {
-                    row.subject = '[' + DIMP.text.badsubject + ']';
+                    row.subject = row.subjecttitle = '[' + DIMP.text.badsubject + ']';
                 }
             }.bind(this),
             onContentComplete: function(rows) {
@@ -493,6 +482,9 @@ var DimpBase = {
                 // retrieving data from the server.
                 l = this.viewport.getMetaData('label');
                 if (l) {
+                    if (this.isSearch()) {
+                        l += ' (' + this.sfolder + ')';
+                    }
                     $('folderName').update(l);
                 }
 
@@ -533,17 +525,14 @@ var DimpBase = {
                         tmp.compact().invoke('show');
                         $('folderName').next().hide();
                     }
-                } else if (this.filtertoggle) {
-                    if (this.filtertoggle == 1 &&
-                        this.viewport.getMetaData('sortby') == DIMP.conf.sortthread) {
-                        ssc = DIMP.conf.sortdate;
-                    }
-                    this.filtertoggle = 0;
+                } else if (this.filtertoggle &&
+                           this.viewport.getMetaData('sortby') == DIMP.conf.sortthread) {
+                    ssc = DIMP.conf.sortdate;
                 }
 
                 this.setSortColumns(ssc);
 
-                if (this.viewport.isFiltering()) {
+                if (this.isSearch()) {
                     this.resetSelected();
                 } else {
                     this.setFolderLabel(this.folder, this.viewport.getMetaData('unseen') || 0);
@@ -603,6 +592,14 @@ var DimpBase = {
                 }
                 return this.cacheids[id];
             }.bind(this),
+            requestParams: function(id) {
+                return this.isSearch(id)
+                    ? $H({
+                        qsearch: $F('quicksearch'),
+                        qsearchmbox: this.sfolder
+                    })
+                    : $H();
+            }.bind(this),
             onSplitBarChange: function() {
                 this._updatePrefs('dimp_splitbar', this.viewport.getPageSize());
             }.bind(this),
@@ -614,12 +611,6 @@ var DimpBase = {
         if (!DIMP.conf.preview_pref) {
             $('msgList').addClassName('msglistNoPreview');
         }
-
-        // Set up viewport filter events.
-        this.viewport.addFilter('ListMessages', this._addSearchfilterParams.bind(this));
-        mf.observe('focus', this._searchfilterOnFocus.bind(this));
-        mf.observe('blur', this._searchfilterOnBlur.bind(this));
-        mf.addClassName('msgFilterDefault');
     },
 
     _addMouseEvents: function(p, popdown)
@@ -805,12 +796,12 @@ var DimpBase = {
 
     updateTitle: function()
     {
-        var elt, label, unseen;
+        var elt, unseen,
+            label = this.viewport.getMetaData('label');
 
-        if (this.viewport.isFiltering()) {
-            label = DIMP.text.search + ' :: ' + (this.viewport.getMetaData('total_rows') || 0) + ' ' + DIMP.text.resfound;
+        if (this.isSearch()) {
+            label += ' (' + this.sfolder + ')';
         } else {
-            label = this.viewport.getMetaData('label');
             elt = $(this.getFolderId(this.folder));
             if (elt) {
                 unseen = elt.readAttribute('u');
@@ -866,15 +857,14 @@ var DimpBase = {
         }
 
         tmp = m.down('div.msgFrom a');
-        if ((this.viewport.isFiltering() && this.fspecial) ||
-            this.viewport.getMetaData('special')) {
+        if (this.viewport.getMetaData('special')) {
             tmp.hide().next().show();
         } else {
             tmp.show().next().hide();
         }
 
         tmp = m.down('div.msgSubject a');
-        if (this.viewport.isFiltering() ||
+        if (this.isSearch() ||
             this.viewport.getMetaData('nothread') ||
             this.viewport.getMetaData('sortlimit')) {
             tmp.show().next().hide();
@@ -1211,99 +1201,57 @@ var DimpBase = {
         $('dimpmain_portal').update(r.response.portal);
     },
 
-    /* Search filter functions. */
-    searchfilterRun: function()
+    /* Search functions. */
+    isSearch: function(id)
     {
-        if (!this.viewport.isFiltering()) {
-            this.filtertoggle = 1;
-            this.fspecial = this.viewport.getMetaData('special');
-        }
-        this.viewport.runFilter($F('msgList_filter'));
+        return (id ? id : this.folder) == this.searchid;
     },
 
-    _searchfilterOnFocus: function()
+    _quicksearchOnFocus: function()
     {
-        var q = $('qoptions').up();
-
-        if ($('msgList_filter').hasClassName('msgFilterDefault')) {
+        if ($('quicksearch').hasClassName('quicksearchDefault')) {
             this._setFilterText(false);
         }
-
-        if (!this.filter_on) {
-            this.filter_on = true;
-            $('sf_current').update(this.viewport.getMetaData('label'));
-            this._setSearchfilterParams(this.viewport.getMetaData('special') ? 'to' : 'from', 'msg');
-            this._setSearchfilterParams('current', 'folder');
-            $(document.documentElement).setStyle({ overflowY: 'hidden' });
-            Effect.SlideDown(q, { duration: 0.5, afterFinish: function() { this.onResize(false, true); $(document.documentElement).setStyle({ overflowY: 'auto' }); }.bind(this) });
-        }
     },
 
-    _searchfilterOnBlur: function()
+    _quicksearchOnBlur: function()
     {
-        if (!$F('msgList_filter')) {
+        if (!$F('quicksearch')) {
             this._setFilterText(true);
         }
     },
 
-    // reset = (boolean) TODO
-    searchfilterClear: function(reset)
-    {
-        if (!this.filter_on) {
-            return;
-        }
-
-        this.filter_on = false;
-        this._setFilterText(true);
-        Effect.SlideUp($('qoptions').up(), { duration: 0.5, afterFinish: this.onResize.bind(this, reset) });
-        this.filtertoggle = 2;
-        this.resetSelected();
-        this.viewport.stopFilter(reset);
-    },
-
-    // d = (boolean) Deactivate filter input?
-    _setFilterText: function(d)
+    quicksearchRun: function()
     {
-        var mf = $('msgList_filter');
-        if (d) {
-            mf.setValue(DIMP.text.search);
-            mf.addClassName('msgFilterDefault');
+        if (this.isSearch()) {
+            this.viewport.reload();
         } else {
-            mf.setValue('');
-            mf.removeClassName('msgFilterDefault');
+            this.sfolder = this.folder;
+            $('quicksearch_close').show();
+            this.loadMailbox(this.searchid);
         }
     },
 
-    // type = 'folder' or 'msg'
-    _setSearchfilterParams: function(id, type)
-    {
-        var c = (type == 'folder') ? this.sfiltersfolder : this.sfilters;
-        c.keys().each(function(i) {
-            $(i).writeAttribute('className', (id == c.get(i)) ? 'qselected' : '');
-        });
-    },
-
-    updateSearchfilter: function(id, type)
+    // 'noload' = (boolean) If true, don't load the mailbox
+    quicksearchClear: function(noload)
     {
-        this._setSearchfilterParams(id, type);
-        if ($F('msgList_filter')) {
-            this.viewport.runFilter();
+        if (this.isSearch()) {
+            this._setFilterText(true);
+            $('quicksearch_close').hide();
+            this.resetSelected();
+            if (!noload) {
+                this.loadMailbox(this.sfolder);
+            }
+            this.viewport.deleteView(this.searchid);
         }
     },
 
-    _addSearchfilterParams: function()
-    {
-        var sf = this.sfiltersfolder.keys().find(function(s) {
-            return $(s).hasClassName('qselected');
-        });
-        return $H({ searchfolder: this.sfiltersfolder.get(sf), searchmsg: this.sfilters.get(this._getSearchfilterField()) });
-    },
-
-    _getSearchfilterField: function()
+    // d = (boolean) Deactivate filter input?
+    _setFilterText: function(d)
     {
-        return this.sfilters.keys().find(function(s) {
-            return $(s).hasClassName('qselected');
-        });
+        var qs = $('quicksearch');
+        qs.setValue(d ? DIMP.text.search : '');
+        [ qs ].invoke(d ? 'addClassName' : 'removeClassName', 'quicksearchDefault');
     },
 
     /* Enable/Disable DIMP action buttons as needed. */
@@ -1376,9 +1324,9 @@ var DimpBase = {
             case Event.KEY_ESC:
             case Event.KEY_TAB:
                 // Catch escapes in search box
-                if (elt.readAttribute('id') == 'msgList_filter') {
+                if (elt.readAttribute('id') == 'quicksearch') {
                     if (kc == Event.KEY_ESC || !elt.getValue()) {
-                        this.searchfilterClear(false);
+                        this.quicksearchClear();
                     }
                     elt.blur();
                     e.stop();
@@ -1390,8 +1338,12 @@ var DimpBase = {
                 if (form.readAttribute('id') == 'RB_folder') {
                     this.cfolderaction(e);
                     e.stop();
-                } else if (elt.readAttribute('id') == 'msgList_filter') {
-                    this.searchfilterRun();
+                } else if (elt.readAttribute('id') == 'quicksearch') {
+                    if ($F('quicksearch')) {
+                        this.quicksearchRun();
+                    } else {
+                        this.quicksearchClear();
+                    }
                     e.stop();
                 }
                 break;
@@ -1601,20 +1553,6 @@ var DimpBase = {
                 e.stop();
                 return;
 
-            case 'sf_all':
-            case 'sf_current':
-                this.updateSearchfilter(id.substring(3), 'folder');
-                e.stop();
-                return;
-
-            case 'sf_msgall':
-            case 'sf_from':
-            case 'sf_to':
-            case 'sf_subject':
-                this.updateSearchfilter(id.substring(3), 'msg');
-                e.stop();
-                return;
-
             case 'msglistHeader':
                 this.sort(e);
                 e.stop();
@@ -1631,11 +1569,6 @@ var DimpBase = {
                 e.stop();
                 return;
 
-            case 'qclose':
-                this.searchfilterClear(false);
-                e.stop();
-                return;
-
             case 'applicationfolders':
                 tmp = e.element();
                 if (!tmp.hasClassName('custom')) {
@@ -1663,6 +1596,10 @@ var DimpBase = {
                     return;
                 }
                 break;
+
+            case 'quicksearch_close':
+                this.quicksearchClear();
+                break;
             }
 
             elt = elt.up();
@@ -2293,7 +2230,8 @@ var DimpBase = {
     {
         DimpCore.init();
 
-        var DM = DimpCore.DMenu;
+        var DM = DimpCore.DMenu,
+            qs = $('quicksearch');
 
         /* Register global handlers now. */
         document.observe('keydown', this.keydownHandler.bindAsEventListener(this));
@@ -2322,7 +2260,7 @@ var DimpBase = {
             } else {
                 this.go('portal');
                 if (DIMP.conf.background_inbox) {
-                    this.loadFolder('INBOX', true);
+                    this.loadMailbox('INBOX', { background: true });
                 }
             }
         }
@@ -2354,11 +2292,6 @@ var DimpBase = {
 
         this._resizeIE6();
 
-        /* Remove unneeded search folders. */
-        if (!DIMP.conf.search_all) {
-            this.sfiltersfolder.unset('sf_all');
-        }
-
         /* Remove unavailable menu items. */
         if (!$('GrowlerLog')) {
             $('alertsloglink').remove();
@@ -2367,6 +2300,10 @@ var DimpBase = {
         /* Check for new mail. */
         this.setPollFolders();
 
+        /* Init quicksearch. */
+        qs.observe('focus', this._quicksearchOnFocus.bind(this));
+        qs.observe('blur', this._quicksearchOnBlur.bind(this));
+
         if (DIMP.conf.is_ie6) {
             /* Disable text selection in preview pane for IE 6. */
             document.observe('selectstart', Event.stop);
index 2af3ccd..33946f0 100644 (file)
@@ -18,7 +18,7 @@ var ViewPort = Class.create({
     // Required: content_container, fetch_action, template,
     //           cachecheck_action, ajaxRequest, buffer_pages,
     //           limit_factor, content_class, row_class, selected_class
-    // Optional: show_split_pane, page_size
+    // Optional: requestParams, show_split_pane, page_size
     initialize: function(opts)
     {
         opts.content = $(opts.content_container);
@@ -41,7 +41,7 @@ var ViewPort = Class.create({
         this.request_num = 1;
     },
 
-    // view = ID of view. Can not contain a '%' character.
+    // view = ID of view.
     // search = (object) Search parameters
     // background = Load view in background?
     loadView: function(view, search, background)
@@ -155,11 +155,7 @@ var ViewPort = Class.create({
     // params = TODO
     reload: function(params)
     {
-        if (this.isFiltering()) {
-            this.filter.filter(null, params);
-        } else {
-            this._fetchBuffer({ offset: this.currentOffset(), purge: true, params: params });
-        }
+        this._fetchBuffer({ offset: this.currentOffset(), purge: true, params: params });
     },
 
     // vs = (Viewport_Selection) A Viewport_Selection object.
@@ -230,36 +226,6 @@ var ViewPort = Class.create({
         this.isbusy = false;
     },
 
-    // action = TODO
-    // callback = TODO
-    addFilter: function(action, callback)
-    {
-        this.filter = new ViewPort_Filter(this, action, callback);
-    },
-
-    // val = TODO
-    // params = TODO
-    runFilter: function(val, params)
-    {
-        if (this.filter) {
-            this.filter.filter(Object.isUndefined(val) ? null : val, params);
-        }
-    },
-
-    // Return: (boolean) Is filtering currently active?
-    isFiltering: function()
-    {
-        return this.filter ? this.filter.isFiltering() : false;
-    },
-
-    // reset = (boolean) If true, don't update the viewport
-    stopFilter: function(reset)
-    {
-        if (this.filter) {
-            this.filter.clear(reset);
-        }
-    },
-
     // noupdate = (boolean) TODO
     // nowait = (boolean) TODO
     onResize: function(noupdate, nowait)
@@ -387,11 +353,6 @@ var ViewPort = Class.create({
         }
         params.set(type, Object.toJSON(value));
 
-        // Are we currently filtering results?
-        if (this.isFiltering()) {
-            action = this.filter.getAction();
-        }
-
         // Generate a unique request ID value based on the search params.
         // Since javascript does not have a native hashing function, use a
         // local lookup table instead.
@@ -504,12 +465,11 @@ var ViewPort = Class.create({
         var cid = this.getMetaData('cacheid', opts.view),
             cached, params, rowlist;
 
-        if (this.isFiltering()) {
-            params = this.filter.addFilterParams().merge({ view: this.isFiltering() });
-        } else {
-            params = this.opts.additionalParams ? this.opts.additionalParams(opts.view || this.view) : $H();
-            params.update({ view: opts.view || this.view });
-        }
+        params = this.opts.requestParams
+            ? this.opts.requestParams(opts.view || this.view)
+            : $H();
+
+        params.update({ view: opts.view || this.view });
 
         if (cid) {
             params.update({ cacheid: cid });
@@ -528,6 +488,7 @@ var ViewPort = Class.create({
                 ? cached.toJSON()
                 : '';
         }
+
         if (cached.length) {
             params.update({ cached: cached });
         }
@@ -1362,107 +1323,6 @@ ViewPort_Buffer = Class.create({
 }),
 
 /**
- * ViewPort_Filter
- */
-ViewPort_Filter = Class.create({
-
-    initialize: function(vp, action, callback)
-    {
-        this.vp = vp;
-        this.action = action;
-        this.callback = callback;
-
-        this.filtering = this.last_filter = this.last_folder = null;
-    },
-
-    // val = (string) The string to filter on. if null, will use the last
-    //                filter string.
-    filter: function(val, params)
-    {
-        params = params || {};
-
-        if (val === null) {
-            val = this.last_filter;
-        } else {
-            val = val.toLowerCase();
-            if (val == this.last_filter) {
-                return;
-            }
-        }
-
-        if (!val) {
-            this.clear();
-            return;
-        }
-
-        this.last_filter = val;
-
-        if (this.filtering) {
-            this.vp._fetchBuffer({ offset: 0, params: params });
-            return;
-        }
-
-        this.filtering = true;
-        this.last_folder = this.vp.view;
-
-        // Filter visible rows immediately.
-        var c = this.vp.opts.content, delrows;
-        delrows = c.childElements().findAll(function(n) {
-            return n.collectTextNodes().toLowerCase().indexOf(val) == -1;
-        });
-        if (this.vp.opts.onClearRows) {
-            this.vp.opts.onClearRows(delrows);
-        }
-        delrows.invoke('remove');
-        this.vp.scroller.clear();
-        if (this.vp.opts.empty && !c.childElements().size()) {
-            c.update(this.vp.opts.empty.innerHTML);
-        }
-
-        this.vp.loadView('%%filter%%');
-    },
-
-    isFiltering: function()
-    {
-        return this.filtering ? this.last_folder : false;
-    },
-
-    getAction: function()
-    {
-        return this.action;
-    },
-
-    addFilterParams: function()
-    {
-        if (!this.filtering) {
-            return $H();
-        }
-
-        var params = $H({ filter: this.last_filter });
-
-        // Get parameters from a callback function, if defined.
-        if (this.callback) {
-            params.update(this.callback());
-        }
-
-        return params;
-    },
-
-    clear: function(reset)
-    {
-        if (this.filtering) {
-            this.filtering = null;
-            if (!reset) {
-                this.vp.loadView(this.last_folder);
-            }
-            this.vp.deleteView('%%filter%%');
-            this.last_filter = this.last_folder = null;
-        }
-    }
-
-}),
-
-/**
  * ViewPort_Selection
  */
 ViewPort_Selection = Class.create({
index 02ee310..894926b 100644 (file)
@@ -200,7 +200,6 @@ class DIMP
             'ham_reporting' => intval(!empty($conf['notspam']['reporting'])),
             'ham_spamfolder' => intval(!empty($conf['notspam']['spamfolder'])),
             'refresh_time' => intval($prefs->getValue('refresh_time')),
-            'search_all' => intval(!empty($conf['dimp']['search']['search_all'])),
 
             'fixed_folders' => empty($conf['server']['fixed_folders'])
                 ? array()
@@ -231,7 +230,6 @@ class DIMP
             'portal' => ("Portal"),
             'prefs' => _("User Options"),
             'search' => _("Search"),
-            'resfound' => _("messages found"),
             'message' => _("Message"),
             'messages' => _("Messages"),
             'of' => _("of"),
index 9dc9ade..1914440 100644 (file)
@@ -22,54 +22,20 @@ class IMP_Views_ListMessages
     public function ListMessages($args)
     {
         $mbox = $args['mbox'];
-        $search_id = null;
+        $is_search = false;
 
         $sortpref = IMP::getSort($mbox);
 
-        /* If we're searching, do search. */
-        if (!empty($args['filter']) &&
-            !empty($args['searchfolder']) &&
-            !empty($args['searchmsg'])) {
+        /* Check for quicksearch request. */
+        if (strlen($args['qsearch']) &&
+            strlen($args['qsearchmbox'])) {
             /* Create the search query. */
             $query = new Horde_Imap_Client_Search_Query();
-
-            /* Create message search list. */
-            switch ($args['searchmsg']) {
-            case 'msgall':
-                $query->text($args['filter'], false);
-                break;
-
-            case 'from':
-                $query->headerText('From', $args['filter']);
-                break;
-
-            case 'to':
-                $query->headerText('To', $args['filter']);
-                break;
-
-            case 'subject':
-                $query->headerText('Subject', $args['filter']);
-                break;
-            }
-
-            /* Create folder search list. */
-            switch ($args['searchfolder']) {
-            case 'all':
-                $imptree = &IMP_Imap_Tree::singleton();
-                $folder_list = $imptree->folderList();
-                break;
-
-            case 'current':
-                $folder_list = array($mbox);
-                break;
-            }
+            $query->text($args['qsearch'], false);
 
             /* Set the search in the IMP session. */
-            $c_ptr = &$_SESSION['imp']['cache'];
-            $search_id = $GLOBALS['imp_search']->createSearchQuery($query, $folder_list, array(), _("Search Results"), isset($c_ptr['dimp_searchquery']) ? $c_ptr['dimp_searchquery'] : null);
-
-            /* Folder is now the search folder. */
-            $mbox = $c_ptr['dimp_searchquery'] = $GLOBALS['imp_search']->createSearchID($search_id);
+            $GLOBALS['imp_search']->createSearchQuery($query, array($args['qsearchmbox']), array(), _("Search Results"), $mbox);
+            $is_search = true;
         }
 
         $label = IMP::getLabel($mbox);
@@ -138,7 +104,7 @@ class IMP_Views_ListMessages
         if (IMP::isSpecialFolder($mbox)) {
             $md->special = 1;
         }
-        if ($GLOBALS['imp_search']->isSearchMbox($mbox)) {
+        if ($is_search || $GLOBALS['imp_search']->isSearchMbox($mbox)) {
             $md->search = 1;
         }
         if ($GLOBALS['imp_imap']->isReadOnly($mbox)) {
@@ -148,7 +114,7 @@ class IMP_Views_ListMessages
         /* Check for mailbox existence now. If there are no messages, there
          * is a chance that the mailbox doesn't exist. If there is at least
          * 1 message, we don't need this check. */
-        if (empty($msgcount) && is_null($search_id)) {
+        if (empty($msgcount) && !$is_search) {
             $imp_folder = &IMP_Folder::singleton();
             if (!$imp_folder->exists($mbox)) {
                 $GLOBALS['notification']->push(sprintf(_("Mailbox %s does not exist."), $label), 'horde.error');
@@ -234,7 +200,7 @@ class IMP_Views_ListMessages
         $result->data = $this->_getOverviewData($imp_mailbox, $mbox, $data, isset($md->search));
 
         /* Get unseen/thread information. */
-        if (is_null($search_id)) {
+        if (!$is_search) {
             $imptree = &IMP_Imap_Tree::singleton();
             $info = $imptree->getElementInfo($mbox);
             if (!empty($info)) {
index 15ad8e1..cea4ae1 100644 (file)
@@ -173,8 +173,9 @@ function _simpleButton($id, $text, $image, $imagedir = null)
 
      <div class="dimpActions">
       <form action="#" method="post">
-       <input id="msgList_filter" type="text" size="30" />
+       <input autocomplete="off" class="quicksearchDefault" id="quicksearch" type="text" size="30" />
       </form>
+      <?php echo IMP::img('close.png', '', array('id' => 'quicksearch_close', 'style' => 'display:none', 'title' => _("Clear Search")), $hordeimg) ?>
       <span>
        <?php _createDA(_("Reply"), 'Reply', 'button_reply', '', $show_text) ?>
       </span>
@@ -205,23 +206,6 @@ function _simpleButton($id, $text, $image, $imagedir = null)
       </span>
      </div>
 
-     <div style="display:none">
-      <div id="qoptions">
-       <span id="qclose"><a>x</a></span>
-       <span class="qlabel"><?php echo _("Folders: ") ?></span>
-<?php if (!empty($conf['dimp']['search']['search_all'])): ?>
-       <a id="sf_all"><?php echo _("All") ?></a>
-<?php endif; ?>
-       <a id="sf_current"></a>
-       <span class="qlabel">|&nbsp;</span>
-       <span class="qlabel"><?php echo _("Message: ") ?></span>
-       <a id="sf_msgall"><?php echo _("All") ?></a>
-       <a id="sf_from"><?php echo _("From") ?></a>
-       <a id="sf_to"><?php echo _("To") ?></a>
-       <a id="sf_subject"><?php echo _("Subject") ?></a>
-      </div>
-     </div>
-
      <div id="msglistHeader" class="item">
       <div class="msgStatus">&nbsp;</div>
       <div class="msgFrom">
index 615bdc8..660a66c 100644 (file)
@@ -21,7 +21,7 @@ DimpBase.message_list_template =
   '#{status}' +
  '</div>' +
  '<div class="msgFrom">#{from}</div>' +
- '<div class="msgSubject" title="#{subject}">#{subjectdata}#{subject}</div>' +
+ '<div class="msgSubject" title="#{subjecttitle}">#{subjectdata}#{subject}</div>' +
  '<div class="msgDate">#{date}</div>' +
  '<div class="msgSize">#{size}</div>' +
 '</div>';
index e25a42b..8bd6970 100644 (file)
@@ -817,66 +817,19 @@ a.address:hover img {
     color: red;
 }
 
-/* Message Search Filter bar */
-#qoptions {
-    background: gray;
-    color: #fff;
-    font-size: 90%;
-    padding: 5px 5px 5px 10px;
-}
-#qoptions a, #qoptions a:visited {
-    text-decoration: none;
-    font-weight: bold;
-    color: #fff;
-    margin: 0 5px;
-    padding: 2px 5px;
-}
-#qoptions a.qselected, #qoptions a.qselected:visited, #qoptions a:hover {
-    background: #fafafa;
-    color: #000;
-    font-weight: bold;
-    border-top: 1px silver solid;
-    border-left: 1px silver solid;
-    border-bottom: 1px #e0e0e0 solid;
-    border-right: 1px #e0e0e0 solid;
-    -moz-border-radius: 5px;
-    -webkit-border-radius: 5px;
-    padding: 1px 4px;
-}
-#qclose a, #qclose a:visited {
-    float: right;
-    margin-top: -2px;
-    width: 10px;
-    background: #efefef;
-    color: #000;
-    font-weight: bold;
-    border-top: 1px silver solid;
-    border-left: 1px silver solid;
-    border-bottom: 1px #e0e0e0 solid;
-    border-right: 1px #e0e0e0 solid;
-    text-align: center;
-    vertical-align: middle;
-    -moz-border-radius: 5px;
-    -webkit-border-radius: 5px;
-    padding: 0 2px 2px 4px;
-    text-decoration: none;
-}
-#qclose a:hover {
-    background: #fff;
-    padding: 0 2px 2px 4px;
-}
-#qoptions .qlabel {
-    font-weight: bold;
-}
-
-.msgFilterDefault {
+/* Search-related styles */
+.quicksearchDefault {
     color: #a0a0a0;
 }
-
-.searchMatch {
+.quicksearchMatch {
     font-weight: bold;
     text-decoration: underline;
 }
+#quicksearch_close {
+    cursor: pointer;
+    float: right;
+    padding: 2px 5px 0 0;
+}
 
 /* Redbox styles. */
 #RB_folder {