From 86f3e5ef0bad2c97d8a55c2dc53c2d808577f12c Mon Sep 17 00:00:00 2001 From: Michael M Slusarz Date: Tue, 14 Apr 2009 13:09:23 -0600 Subject: [PATCH] Improve quicksearch in dimp. 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 | 5 +- imp/config/conf.xml | 8 - imp/docs/CHANGES | 1 + imp/js/src/DimpBase.js | 247 ++++++++++++------------------- imp/js/src/ViewPort.js | 158 ++------------------ imp/lib/DIMP.php | 2 - imp/lib/Views/ListMessages.php | 54 ++----- imp/templates/index/index-dimp.inc | 20 +-- imp/templates/javascript/mailbox-dimp.js | 2 +- imp/themes/screen-dimp.css | 63 +------- 10 files changed, 125 insertions(+), 435 deletions(-) diff --git a/imp/ajax.php b/imp/ajax.php index d7ab9ac8c..ac4716cdb 100644 --- a/imp/ajax.php +++ b/imp/ajax.php @@ -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'); diff --git a/imp/config/conf.xml b/imp/config/conf.xml index 95cb2e0f9..f2f90e3d0 100644 --- a/imp/config/conf.xml +++ b/imp/config/conf.xml @@ -520,14 +520,6 @@ background?">true - Search Settings - - false - - Menu Settings #{1}'); + // Check for search strings + if (this.isSearch()) { + re = new RegExp("(" + $F('quicksearch') + ")", "i"); + [ 'from', 'subject' ].each(function(h) { + row[h] = row[h].gsub(re, '#{1}'); + }); } - // 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); diff --git a/imp/js/src/ViewPort.js b/imp/js/src/ViewPort.js index 2af3ccdcc..33946f0e6 100644 --- a/imp/js/src/ViewPort.js +++ b/imp/js/src/ViewPort.js @@ -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({ diff --git a/imp/lib/DIMP.php b/imp/lib/DIMP.php index 02ee31024..894926b76 100644 --- a/imp/lib/DIMP.php +++ b/imp/lib/DIMP.php @@ -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"), diff --git a/imp/lib/Views/ListMessages.php b/imp/lib/Views/ListMessages.php index 9dc9ade89..1914440ba 100644 --- a/imp/lib/Views/ListMessages.php +++ b/imp/lib/Views/ListMessages.php @@ -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)) { diff --git a/imp/templates/index/index-dimp.inc b/imp/templates/index/index-dimp.inc index 15ad8e12a..cea4ae1de 100644 --- a/imp/templates/index/index-dimp.inc +++ b/imp/templates/index/index-dimp.inc @@ -173,8 +173,9 @@ function _simpleButton($id, $text, $image, $imagedir = null)
- +
+ 'quicksearch_close', 'style' => 'display:none', 'title' => _("Clear Search")), $hordeimg) ?> @@ -205,23 +206,6 @@ function _simpleButton($id, $text, $image, $imagedir = null)
-
-
- x - - - - - - - - - - - -
-
-
 
diff --git a/imp/templates/javascript/mailbox-dimp.js b/imp/templates/javascript/mailbox-dimp.js index 615bdc8b6..660a66cb7 100644 --- a/imp/templates/javascript/mailbox-dimp.js +++ b/imp/templates/javascript/mailbox-dimp.js @@ -21,7 +21,7 @@ DimpBase.message_list_template = '#{status}' + '
' + '
#{from}
' + - '
#{subjectdata}#{subject}
' + + '
#{subjectdata}#{subject}
' + '
#{date}
' + '
#{size}
' + '
'; diff --git a/imp/themes/screen-dimp.css b/imp/themes/screen-dimp.css index e25a42bc3..8bd697016 100644 --- a/imp/themes/screen-dimp.css +++ b/imp/themes/screen-dimp.css @@ -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 { -- 2.11.0