v5.0-git
--------
+[mms] Improved advanced search query interface (Request #6875).
[mms] More intelligent ordering of autocomplete search results.
[mms] Add a mini search query interface (Request #6875).
[mms] Make DIMP quicksearch field selection persist across sessions.
$morembox = $rows = array();
foreach ($raw_rows as $val) {
$val['nocheckbox'] = !empty($val['vfolder']);
- if (!empty($val['vfolder']) && ($val['value'] != IMP_Imap_Tree::VFOLDER_KEY)) {
- $val['delvfolder'] = Horde::link($imp_search->deleteURL($val['value']), _("Delete Virtual Folder")) . _("Delete") . '</a>';
- $val['editvfolder'] = Horde::link($imp_search->editURL($val['value']), _("Edit Virtual Folder")) . _("Edit") . '</a>';
+ if (!empty($val['vfolder']) && $val['editvfolder']) {
+ $val['delvfolder'] = Horde::link($imp_search->deleteUrl($val['value']), _("Delete Virtual Folder")) . _("Delete") . '</a>';
+ $val['editvfolder'] = Horde::link($imp_search->editUrl($val['value']), _("Edit Virtual Folder")) . _("Edit") . '</a>';
}
$val['cname'] = (++$rowct % 2) ? 'item0' : 'item1';
/**
- * Provides the javascript for the search.php script (standard view).
+ * Provides the javascript for the search.php script (advanced view).
*
* See the enclosed file COPYING for license information (GPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
var ImpSearch = {
// The following variables are defined in search.php:
- // inverse_sub, not_search, search_date
+ // loading, months, need_criteria, need_folder, types
+ criteria: {},
+ saved_searches: {},
+ show_unsub: false,
- _toggleAll: function(checked)
+ _getAll: function()
{
- $('search').getInputs(null, 'search_folders[]').each(function(e) {
+ return $('search_form').getInputs(null, 'search_folders_form[]');
+ },
+
+ selectFolders: function(checked)
+ {
+ this._getAll().each(function(e) {
e.checked = checked;
});
},
- _dateCheck: function(field)
+ updateFolderList: function(folders)
{
- var m = $('search_' + field + '_month'),
- d = $('search_' + field + '_day'),
- y = $('search_' + field + '_year');
+ var fragment = document.createDocumentFragment(),
+ node = $($('folder_row').cloneNode(true)).writeAttribute('id', false).show();
- if (m.selectedIndex == 0) {
- m.selectedIndex = this.search_date.m;
- }
+ folders.each(function(f) {
+ var n = $(node.cloneNode(true));
+ n.down().writeAttribute({ disabled: !Boolean(f.v), value: (f.v ? f.v.escapeHTML() : null) }).insert({ after: f.l });
+ fragment.appendChild(n);
+ });
- if (d.selectedIndex == 0) {
- d.selectedIndex = this.search_date.d;
- }
+ $('search_folders_hdr').next('DIV').update('').appendChild(fragment);
+ },
- if (y.value == "") {
- y.value = this.search_date.y;
- }
+ updateSavedSearches: function(searches)
+ {
+ var fragment = document.createDocumentFragment(),
+ node = new Element('OPTION');
+
+ $('recent_searches_div').show();
+
+ $H(searches).each(function(s) {
+ fragment.appendChild($(node.cloneNode(false)).writeAttribute({ value: s.value.v.escapeHTML() }).update(s.value.l.escapeHTML()));
+ this.saved_searches[s.key] = s.value.c;
+ }, this);
+
+ $('recent_searches').appendChild(fragment);
},
- _formCheck: function()
+ updateSearchCriteria: function(criteria)
{
- if (this.not_search &&
- (!$('preselected_folders') || !$F('preselected_folders'))) {
- if (!Form.getInputs('search', null, 'search_folders[]').detect(function(e) { return e.checked; })) {
- alert(IMP.text.search_select);
- return;
+ this.resetCriteria();
+
+ criteria.each(function(c) {
+ switch (this.types[c.t]) {
+ case 'header':
+ case 'body':
+ case 'text':
+ this.insertText(c.t, c.v, c.n);
+ break;
+
+ case 'size':
+ this.insertSize(c.t, c.v);
+ break;
+
+ case 'date':
+ this.insertDate(c.t, c.v);
+ break;
+
+ case 'flag':
+ this.insertFlag(c.t);
+ break;
+ }
+ }, this);
+ },
+
+ updateSelectedFolders: function(folders)
+ {
+ var tmp = $('search_folders_hdr').next();
+ this.selectFolders(false);
+ folders.each(function(f) {
+ var i = tmp.down('INPUT[value=' + f + ']');
+ if (i) {
+ i.checked = true;
+ }
+ });
+ },
+
+ resetCriteria: function()
+ {
+ $('search_criteria').siblings().invoke('remove');
+ },
+
+ changeHandler: function(e)
+ {
+ var elt = e.element(), val = $F(elt);
+
+ switch (elt.readAttribute('id')) {
+ case 'recent_searches':
+ this.updateSearchCriteria(this.saved_searches[$F(elt)]);
+ elt.setValue('');
+ break;
+
+ case 'search_criteria':
+ switch (this.types[val]) {
+ case 'header':
+ case 'body':
+ case 'text':
+ this.insertText(val);
+ break;
+
+ case 'size':
+ this.insertSize(val);
+ break;
+
+ case 'date':
+ this.insertDate(val);
+ break;
+
+ case 'flag':
+ this.insertFlag(val);
+ break;
}
+ break;
}
- $('actionID').setValue('do_search');
+ e.stop();
},
- _reset: function()
+ getLabel: function(id)
{
- $('actionID').setValue('reset_search');
- $('search').submit();
+ return $('search_criteria').down('[value=' + id + ']').getText() + ': ';
},
- _saveCache: function()
+ insertCriteria: function(elt)
{
- $('edit_query').setValue($F('save_cache'));
- $('search').submit();
+ 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();
},
- _deleteField: function(i)
+ insertText: function(id, text, not)
{
- $('delete_field_id').setValue(i);
- $('actionID').setValue('delete_field');
- $('search').submit();
+ 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);
+ }
+ this.criteria[this.insertCriteria(tmp)] = { t: id };
},
- _showSubscribed: function(i)
+ insertSize: function(id, size)
{
- $('show_subscribed_only').setValue(i);
- $('search').submit();
+ 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();
+ this.criteria[this.insertCriteria(tmp)] = { t: id };
},
- changeHandler: function(e)
+ insertDate: function(id, data)
{
- var id = e.element().readAttribute('id');
+ 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));
+ this.replaceDate(this.insertCriteria(tmp), id, { y: d.getFullYear(), m: d.getMonth(), d: d.getDate() });
+ },
- switch (id) {
- case 'save_cache':
- this._saveCache();
- break;
+ replaceDate: function(id, type, data)
+ {
+ $(id).down('SPAN', 1).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).
+ this.criteria[id] = { t: type, v: data };
+ },
+
+ insertFlag: function(id)
+ {
+ var tmp = $($('flag_criteria').cloneNode(true)).insert({ bottom: this.getLabel(id) } );
+ this.criteria[this.insertCriteria(tmp)] = { t: id };
+ },
+
+ _submit: function()
+ {
+ var data = [], tmp;
+
+ if (!this._getAll().findAll(function(i) { return i.checked; }).size()) {
+ alert(this.need_folder);
+ } else {
+ tmp = $('search_criteria').siblings().pluck('id');
+ if (tmp.size()) {
+ tmp.each(function(c) {
+ var tmp2;
+
+ switch (this.types[this.criteria[c].t]) {
+ case 'header':
+ case 'body':
+ case 'text':
+ this.criteria[c].n = Number(Boolean($F($(c).down('INPUT[type=checkbox]'))));
+ this.criteria[c].v = $F($(c).down('INPUT[type=text]'));
+ data.push(this.criteria[c]);
+ break;
+
+ case 'size':
+ tmp2 = Number($F($(c).down('INPUT')));
+ if (!isNaN(tmp2)) {
+ // Convert KB to bytes
+ this.criteria[c].v = tmp2 * 1024;
+ data.push(this.criteria[c]);
+ }
+ break;
- default:
- if (id.startsWith('field_')) {
- $('search').submit();
- } else if (id.startsWith('search_date_')) {
- this._dateCheck('on');
+ case 'date':
+ data.push(this.criteria[c]);
+ break;
+
+ case 'flag':
+ data.push({ t: 'flag', v: this.criteria[c].t });
+ break;
+ }
+ }, this);
+ $('criteria_form').setValue(data.toJSON());
+ $('search_form').submit();
+ } else {
+ alert(this.need_criteria);
}
- break;
}
},
return;
}
- var elt = e.element();
+ var id, tmp,
+ elt = e.element();
while (Object.isElement(elt)) {
- if (elt.hasClassName('searchSubmit')) {
- this._formCheck();
- } else if (elt.hasClassName('searchReset')) {
- this._reset();
- } else if (elt.hasClassName('searchDelete')) {
- this._deleteField(elt.readAttribute('fid'));
- } else {
- switch (elt.readAttribute('id')) {
- case 'link_sel_all':
- this._toggleAll(true);
- break;
-
- case 'link_sel_none':
- this._toggleAll(false);
- break;
-
- case 'link_sub':
- this._showSubscribed(this.inverse_sub);
- break;
-
- case 'search_match_and':
- case 'search_match_or':
- if ($('field_1')) {
- $('search').submit();
+ id = elt.readAttribute('id');
+
+ switch (id) {
+ case 'search_submit':
+ this._submit();
+ e.stop();
+ return;
+
+ case 'search_reset':
+ this.resetCriteria();
+ this.selectFolders(false);
+ return;
+
+ case 'link_sel_all':
+ case 'link_sel_none':
+ this.selectFolders(id == 'link_sel_all');
+ e.stop();
+ return;
+
+ case 'link_sub':
+ tmp = this._getAll();
+ this.show_unsub = !this.show_unsub;
+ $('search_folders_hdr').next('DIV').update(this.loading);
+ new Ajax.Request($('search_form').readAttribute('action'), {
+ parameters: { show_unsub: Number(this.show_unsub) },
+ onComplete: this._showFoldersCallback.bind(this, tmp)
+ });
+ elt.childElements().invoke('toggle');
+ e.stop();
+ return;
+
+ default:
+ if (elt.hasClassName('arrowExpanded') ||
+ elt.hasClassName('arrowCollapsed')) {
+ elt.up().down().toggle().next().toggle().up().next().toggle();
+ if (elt.descendantOf('search_folders_hdr')) {
+ elt.next('SPAN.item').toggle();
}
- break;
+ } else if (elt.hasClassName('searchuiDelete')) {
+ tmp = elt.up('DIV');
+ 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));
+ e.stop();
+ return;
}
+ break;
}
elt = elt.up();
}
+ },
+
+ _showFoldersCallback: function(flist, r)
+ {
+ this.updateFolderList(r.responseJSON);
+ this.updateSelectedFolders(flist);
}
};
*
* $_SESSION['imp']['search'] = array(
* 'id_1' => array(
- * 'query' => Horde_Imap_Client_Search_Query object (serialized),
- * 'folders' => array (List of folders to search),
- * 'uiinfo' => array (Info used by search.php to render page.
- * For virtual folders, this data is stored
- * in the preferences),
- * 'label' => string (Description of search),
- * 'vfolder' => boolean (True if this is a Virtual Folder)
- * ),
- * 'id_2' => array(
- * ....
+ * 'c' => (array) List of search criteria. For virtual folders, this
+ * data is stored in the preferences,
+ * 'f' => (array) List of folders to search,
+ * 'l' => (string) Description of search,
+ * 'q' => (Horde_Imap_Client_Search_Query) [serialized],
+ * 'v' => (boolean) True if this is a Virtual Folder
* ),
* ....
* );
/* The mailbox search prefix. */
const MBOX_PREFIX = 'impsearch\0';
+ /* The basic search mailbox name. */
+ const BASIC_SEARCH = 'impbsearch';
+
/* Bitmask constants for listQueries(). */
const LIST_SEARCH = 1;
const LIST_VFOLDER = 2;
+ const NO_BASIC_SEARCH = 4;
/**
* The ID of the current search query in use.
}
/**
- * Initialize the class.
+ * Initialize search data for a session.
*
* @param boolean $no_vf Don't readd the Virtual Folders.
*/
if (!$no_vf) {
$imaptree = IMP_Imap_Tree::singleton();
foreach ($this->_getVFolderList() as $key => $val) {
- if (!empty($val['vfolder']) &&
+ if (!empty($val['v']) &&
!$this->isEditableVFolder($key)) {
- $imaptree->insertVFolders(array($key => $val['label']));
- unset($val['uiinfo']);
+ $imaptree->insertVFolders(array($key => $val['l']));
+ unset($val['c']);
$_SESSION['imp']['search'][$key] = $val;
}
}
}
/**
+ * Return the base search fields.
+ *
+ * @return array The base search fields.
+ */
+ public function searchFields()
+ {
+ return array(
+ 'from' => array(
+ 'label' => _("From"),
+ 'type' => 'header',
+ 'not' => true
+ ),
+ 'to' => array(
+ 'label' => _("To"),
+ 'type' => 'header',
+ 'not' => true
+ ),
+ 'cc' => array(
+ 'label' => _("Cc"),
+ 'type' => 'header',
+ 'not' => true
+ ),
+ 'bcc' => array(
+ 'label' => _("Bcc"),
+ 'type' => 'header',
+ 'not' => true
+ ),
+ 'subject' => array(
+ 'label' => _("Subject"),
+ 'type' => 'header',
+ 'not' => true
+ ),
+ 'body' => array(
+ 'label' => _("Body"),
+ 'type' => 'body',
+ 'not' => true
+ ),
+ 'text' => array(
+ 'label' => _("Entire Message"),
+ 'type' => 'text',
+ 'not' => true
+ ),
+ 'date_on' => array(
+ 'label' => _("Date ="),
+ 'type' => 'date',
+ 'not' => true
+ ),
+ 'date_until' => array(
+ 'label' => _("Date <"),
+ 'type' => 'date',
+ 'not' => true
+ ),
+ 'date_since' => array(
+ 'label' => _("Date >="),
+ 'type' => 'date',
+ 'not' => true
+ ),
+ // Displayed in KB, but stored internally in bytes
+ 'size_smaller' => array(
+ 'label' => _("Size (KB) <"),
+ 'type' => 'size',
+ 'not' => false
+ ),
+ // Displayed in KB, but stored internally in bytes
+ 'size_larger' => array(
+ 'label' => _("Size (KB) >"),
+ 'type' => 'size',
+ 'not' => false
+ ),
+ );
+ }
+
+ /**
+ * Return the base flag fields.
+ *
+ * @return array The base flag fields.
+ */
+ public function flagFields()
+ {
+ $imp_flags = IMP_Imap_Flags::singleton();
+ $flist = $imp_flags->getFlagList(null);
+
+ $flags = array();
+
+ for ($i = 0, $cnt = count($flist['set']); $i < $cnt; ++$i) {
+ $flags[$flist['set'][$i]['f']] = $flist['set'][$i]['l'];
+ $flags[$flist['unset'][$i]['f']] = sprintf(_("Not %s"), $flist['unset'][$i]['l']);
+ }
+
+ return $flags;
+ }
+
+ /**
* Run a search.
*
* @param object $ob An optional search query to add (via 'AND') to the
$search = &$_SESSION['imp']['search'][$id];
/* Prepare the search query. */
- $query = unserialize($search['query']);
+ $query = unserialize($search['q']);
if (!empty($ob)) {
$query->andSearch(array($ob));
}
$sortpref['by'] = Horde_Imap_Client::SORT_DATE;
}
- foreach ($search['folders'] as $val) {
+ foreach ($search['f'] as $val) {
$results = $GLOBALS['imp_imap']->ob()->search($val, $query, array('reverse' => $sortpref['dir'], 'sort' => array($sortpref['by'])));
foreach ($results['sort'] as $val2) {
$sorted[] = $val2 . IMP::IDX_SEP . $val;
* queries with custom sorts to be used without affecting cached
* mailboxes.
*
- * @param object $query The search query.
- * @param string $mailbox The mailbox to search.
- * @param integer $sortby The sort criteria.
- * @param integer $sortdir The sort directory.
+ * @param object $query The search query object
+ * (Horde_Imap_Client_Search_Query).
+ * @param string $mailbox The mailbox to search.
+ * @param integer $sortby The sort criteria.
+ * @param integer $sortdir The sort directory.
*
* @return array The sorted list.
*/
/**
* Creates the IMAP search query in the IMP session.
*
- * @param object $query The search query object
- * (Horde_Imap_Client_Search_Query).
- * @param array $folders The list of folders to search.
- * @param array $search The search array used to build the search UI
- * screen.
- * @param string $label The label to use for the search results.
- * @param string $id The query id to use (or else one is
- * automatically generated).
+ * @param object $query The search query object
+ * (Horde_Imap_Client_Search_Query).
+ * @param array $folders The list of folders to search.
+ * @param array $criteria The search criteria array.
+ * @param string $label The label to use for the search results.
+ * @param string $id The query id to use (or else one is
+ * automatically generated).
*
* @return string Returns the search query id.
*/
- public function createSearchQuery($query, $folders, $search, $label,
+ public function createSearchQuery($query, $folders, $criteria, $label,
$id = null)
{
$id = is_null($id) ? uniqid(mt_rand()) : $this->_strip($id);
+
$_SESSION['imp']['search'][$id] = array(
- 'query' => serialize($query),
- 'folders' => $folders,
- 'uiinfo' => $search,
- 'label' => $label,
- 'vfolder' => false
+ 'c' => $criteria,
+ 'f' => $folders,
+ 'l' => $label,
+ 'q' => serialize($query),
+ 'v' => false
);
+
return $id;
}
public function deleteSearchQuery($id = null, $no_delete = false)
{
$id = $this->_strip($id);
- $is_vfolder = !empty($_SESSION['imp']['search'][$id]['vfolder']);
+ $is_vfolder = $this->isVFolder($id);
unset($_SESSION['imp']['search'][$id]);
if ($is_vfolder) {
$vfolders = $this->_getVFolderList();
unset($vfolders[$id]);
$this->_saveVFolderList($vfolders);
+
if (!$no_delete) {
$imaptree = IMP_Imap_Tree::singleton();
$imaptree->delete($id);
}
/**
- * Retrieves the previously stored search UI information.
+ * Retrieves the previously stored search criteria information.
*
* @param string $id The search query id to use (by default, will use
* the current ID set in the object).
*
* @return array The array necessary to rebuild the search UI page.
*/
- public function retrieveUIQuery($id = null)
+ public function getCriteria($id = null)
{
$id = $this->_strip($id);
- if (isset($_SESSION['imp']['search'][$id]['uiinfo'])) {
- return $_SESSION['imp']['search'][$id]['uiinfo'];
+ if (isset($_SESSION['imp']['search'][$id]['c'])) {
+ return $_SESSION['imp']['search'][$id]['c'];
}
if ($this->isVFolder($id)) {
$vlist = $this->_getVFolderList();
- return $vlist[$id]['uiinfo'];
+ return $vlist[$id]['c'];
}
return array();
public function getLabel($id = null)
{
$id = $this->_strip($id);
- return isset($_SESSION['imp']['search'][$id]['label'])
- ? $_SESSION['imp']['search'][$id]['label']
+ return isset($_SESSION['imp']['search'][$id]['l'])
+ ? $_SESSION['imp']['search'][$id]['l']
: '';
}
*/
protected function _getVFolderList()
{
- if (!is_null(self::$_vfolder)) {
- return self::$_vfolder;
- }
-
- $vfolder = $GLOBALS['prefs']->getValue('vfolder');
- if (!empty($vfolder)) {
- $vfolder = @unserialize($vfolder);
- }
+ if (is_null(self::$_vfolder)) {
+ self::$_vfolder = $GLOBALS['prefs']->getValue('vfolder');
+ if (!empty(self::$_vfolder)) {
+ self::$_vfolder = @unserialize(self::$_vfolder);
+ }
- if (empty($vfolder) || !is_array($vfolder)) {
- $vfolder = array();
+ if (empty(self::$_vfolder) || !is_array(self::$_vfolder)) {
+ self::$_vfolder = array();
+ }
}
- self::$_vfolder = $vfolder;
-
- return $vfolder;
+ return self::$_vfolder;
}
/**
protected function _saveVFolderList($vfolder)
{
$GLOBALS['prefs']->setValue('vfolder', serialize($vfolder));
- self::$_vfolder = null;
+ self::$_vfolder = $vfolder;
}
/**
* Add a virtual folder for the current user.
*
- * @param object $query The search query object
- * (Horde_Imap_Client_Search_Query).
- * @param array $folders The list of folders to search.
- * @param array $search The search array used to build the search UI
- * screen.
- * @param string $label The label to use for the search results.
- * @param string $id The virtual folder id.
+ * @param object $query The search query object
+ * (Horde_Imap_Client_Search_Query).
+ * @param array $folders The list of folders to search.
+ * @param array $search The search array used to build the search UI
+ * screen.
+ * @param string $label The label to use for the search results.
+ * @param string $id The virtual folder id.
*
* @return string The virtual folder ID.
*/
public function addVFolder($query, $folders, $search, $label, $id = null)
{
$id = $this->createSearchQuery($query, $folders, $search, $label, $id);
- $_SESSION['imp']['search'][$id]['vfolder'] = true;
+ $_SESSION['imp']['search'][$id]['v'] = true;
+
if ($this->_saveVFolder) {
$vfolders = $this->_getVFolderList();
$vfolders[$id] = $_SESSION['imp']['search'][$id];
public function isEditableVFolder($id = null)
{
$id = $this->_strip($id);
- return ($this->isVFolder($id) && !$this->isVTrashFolder($id) && !$this->isVINBOXFolder($id));
+ return ($this->isVFolder($id) &&
+ !$this->isVTrashFolder($id) &&
+ !$this->isVINBOXFolder($id));
}
/**
* Return a list of queryies.
*
* @param integer $mask A bitmask of the query types to return.
- * IMP_Search::LIST_SEARCH and/or
- * IMP_Search::LIST_VFOLDER.
+ * IMP_Search::LIST_SEARCH,
+ * IMP_Search::LIST_VFOLDER, and/or
+ * IMP_Search::NO_BASIC_SEARCH.
* @param boolean $label If true, returns the label. Otherwise, returns
* a textual representation.
*
}
foreach ($_SESSION['imp']['search'] as $key => $val) {
- if ((($mask & self::LIST_VFOLDER) && !empty($val['vfolder'])) ||
- (($mask & self::LIST_SEARCH) && empty($val['vfolder']))) {
- $vfolders[$key] = $label
+ if ((($mask & self::LIST_VFOLDER) && !empty($val['v'])) ||
+ (($mask & self::LIST_SEARCH) && empty($val['v'])) &&
+ (!($mask & self::NO_BASIC_SEARCH) ||
+ ($key != self::BASIC_SEARCH))) {
+ $folders[$key] = $label
? $this->getLabel($key)
: $this->searchQueryText($key);
}
public function getSearchFolders($id = null)
{
$id = $this->_strip($id);
- return isset($_SESSION['imp']['search'][$id]['folders'])
- ? $_SESSION['imp']['search'][$id]['folders']
+ return isset($_SESSION['imp']['search'][$id]['f'])
+ ? $_SESSION['imp']['search'][$id]['f']
: array();
}
if (empty($_SESSION['imp']['search'][$id])) {
return '';
} elseif ($this->isVINBOXFolder($id) || $this->isVTrashFolder($id)) {
- return $_SESSION['imp']['search'][$id]['label'];
+ return $_SESSION['imp']['search'][$id]['l'];
}
- $imp_ui_search = new IMP_UI_Search();
-
- $flagfields = $imp_ui_search->flagFields();
- $searchfields = $imp_ui_search->searchFields();
+ $flagfields = $this->flagFields();
+ $searchfields = $this->searchFields();
$text = '';
- $uiinfo = $this->retrieveUIQuery($id);
-
- if (empty($uiinfo['field'])) {
- return '';
- }
+ $criteria = $this->getCriteria($id);
$text = _("Search") . ' ';
$text_array = array();
- foreach ($uiinfo['field'] as $key2 => $val2) {
- if (isset($flagfields[$val2])) {
- $text_array[] = $flagfields[$val2]['label'];
+ foreach ($criteria as $rule) {
+ $field = $rule->t;
+
+ if (isset($flagfields[$field])) {
+ $text_array[] = sprintf(_("flagged \"%s\""), $flagfields[$field]);
} else {
- switch ($searchfields[$val2]['type']) {
- case IMP_UI_Search::DATE:
- $text_array[] = sprintf("%s '%s'", $searchfields[$val2]['label'], strftime("%x", mktime(0, 0, 0, $uiinfo['date'][$key2]['month'], $uiinfo['date'][$key2]['day'], $uiinfo['date'][$key2]['year'])));
+ switch ($searchfields[$field]['type']) {
+ case 'date':
+ $text_array[] = sprintf("%s '%s'", $searchfields[$field]['label'], strftime("%x", mktime(0, 0, 0, $rule->v->m + 1, $rule->v->d, $rule->v->y)));
break;
- case IMP_UI_Search::SIZE:
- $text_array[] = $searchfields[$val2]['label'] . ' ' . ($uiinfo['text'][$key2] / 1024);
+ case 'size':
+ $text_array[] = $searchfields[$field]['label'] . ' ' . ($rule->v / 1024);
break;
default:
- $text_array[] = sprintf("%s for '%s'", $searchfields[$val2]['label'], ((!empty($uiinfo['text_not'][$key2])) ? _("not") . ' ' : '') . $uiinfo['text'][$key2]);
+ $text_array[] = sprintf("%s for '%s'", $searchfields[$field]['label'], ((!empty($rule->n)) ? _("not") . ' ' : '') . $rule->v);
break;
}
}
}
- $text .= implode(' ' . (($uiinfo['match'] == 'and') ? _("and") : _("or")) . ' ', $text_array) . ' ' . _("in") . ' ' . implode(', ', $uiinfo['folders']);
+ return $text . implode(' ' . _("and") . ' ', $text_array) . ' ' . _("in") . ' ' . implode(', ', $this->getSearchFolders($id));
}
/**
*
* @return string The URL to the search page.
*/
- public function editURL($id = null)
+ public function editUrl($id = null)
{
- $id = $this->_strip($id);
- return Horde_Util::addParameter(Horde::applicationUrl('search.php'), array('edit_query' => $id));
+ return Horde_Util::addParameter(Horde::applicationUrl('search.php'), array('edit_query' => $this->createSearchID($this->_strip($id))));
}
/**
*
* @return string The URL to allow deletion of the search query.
*/
- public function deleteURL($id = null)
+ public function deleteUrl($id = null)
{
- $id = $this->_strip($id);
- return Horde_Util::addParameter(Horde::applicationUrl('folders.php'),
- array('actionID' => 'delete_search_query',
- 'folders_token' => Horde::getRequestToken('imp.folders'),
- 'queryid' => $id,
- ));
+ return Horde_Util::addParameter(Horde::applicationUrl('folders.php'), array(
+ 'actionID' => 'delete_search_query',
+ 'folders_token' => Horde::getRequestToken('imp.folders'),
+ 'queryid' => $this->createSearchID($this->_strip($id))
+ ));
}
/**
public function isVFolder($id = null)
{
$id = $this->_strip($id);
- return !empty($_SESSION['imp']['search'][$id]['vfolder']);
+ return !empty($_SESSION['imp']['search'][$id]['v']);
}
/**
*
* @param string $id The mailbox query ID.
*
- * @return string The virtual folder ID, with any IMP specific identifying
- * information stripped off.
+ * @return string The virtual folder ID, with any IMP specific
+ * identifying information stripped off.
*/
protected function _strip($id)
{
*/
class IMP_UI_Search
{
- /* Defines used to determine what kind of field query we are dealing
- * with. */
- const HEADER = 1;
- const BODY = 2;
- const DATE = 3;
- const TEXT = 4;
- const SIZE = 5;
-
- /**
- * Return the base search fields.
- *
- * @return array The base search fields.
- */
- public function searchFields()
- {
- return array(
- 'from' => array(
- 'label' => _("From"),
- 'type' => self::HEADER,
- 'not' => true
- ),
- 'to' => array(
- 'label' => _("To"),
- 'type' => self::HEADER,
- 'not' => true
- ),
- 'cc' => array(
- 'label' => _("Cc"),
- 'type' => self::HEADER,
- 'not' => true
- ),
- 'bcc' => array(
- 'label' => _("Bcc"),
- 'type' => self::HEADER,
- 'not' => true
- ),
- 'subject' => array(
- 'label' => _("Subject"),
- 'type' => self::HEADER,
- 'not' => true
- ),
- 'body' => array(
- 'label' => _("Body"),
- 'type' => self::BODY,
- 'not' => true
- ),
- 'text' => array(
- 'label' => _("Entire Message"),
- 'type' => self::TEXT,
- 'not' => true
- ),
- 'date_on' => array(
- 'label' => _("Date ="),
- 'type' => self::DATE,
- 'not' => true
- ),
- 'date_until' => array(
- 'label' => _("Date <"),
- 'type' => self::DATE,
- 'not' => true
- ),
- 'date_since' => array(
- 'label' => _("Date >="),
- 'type' => self::DATE,
- 'not' => true
- ),
- // Displayed in KB, but stored internally in bytes
- 'size_smaller' => array(
- 'label' => _("Size (KB) <"),
- 'type' => self::SIZE,
- 'not' => false
- ),
- // Displayed in KB, but stored internally in bytes
- 'size_larger' => array(
- 'label' => _("Size (KB) >"),
- 'type' => self::SIZE,
- 'not' => false
- ),
- );
- }
-
- /**
- * Return the base flag fields.
- *
- * @return array The base flag fields.
- */
- public function flagFields()
- {
- $imp_flags = IMP_Imap_Flags::singleton();
- $flist = $imp_flags->getFlagList(null);
-
- $flags = array();
-
- for ($i = 0, $cnt = count($flist['set']); $i < $cnt; ++$i) {
- $flags[$flist['set'][$i]['f']] = $flist['set'][$i]['l'];
- $flags[$flist['unset'][$i]['f']] = sprintf(_("Not %s"), $flist['unset'][$i]['l']);
- }
-
- return $flags;
- }
-
/**
* Creates a search query.
*
- * @param array $uiinfo A UI info array (see imp/search.php).
+ * @param array $search The list of search criteria.
*
* @return object A search object (Horde_Imap_Client_Search_Query).
*/
$query = new Horde_Imap_Client_Search_Query();
$search_array = array();
- $search_fields = $this->searchFields();
- $flag_fields = $this->flagFields();
+ $search_fields = $GLOBALS['imp_search']->searchFields();
+ $flag_fields = $GLOBALS['imp_search']->flagFields();
$imp_flags = IMP_Imap_Flags::singleton();
- foreach ($search['field'] as $key => $val) {
+ foreach ($search as $rule) {
$ob = new Horde_Imap_Client_Search_Query();
- if (isset($flag_fields[$val])) {
- $val = $imp_flags->parseFormId($val);
+ if (isset($flag_fields[$rule->t])) {
+ $val = $imp_flags->parseFormId($rule->t);
$ob->flag($val['flag'], $val['set']);
$search_array[] = $ob;
} else {
- switch ($search_fields[$val]['type']) {
- case self::HEADER:
- if (!empty($search['text'][$key])) {
- $ob->headerText($val, $search['text'][$key], $search['text_not'][$key]);
+ /* Ignore unknown types. */
+ switch ($search_fields[$rule->t]['type']) {
+ case 'header':
+ if (!empty($rule->v)) {
+ $ob->headerText($rule->t, $rule->v, !empty($rule->n));
$search_array[] = $ob;
}
break;
- case self::BODY:
- case self::TEXT:
- if (!empty($search['text'][$key])) {
- $ob->text($search['text'][$key], $search_fields[$val]['type'] == self::BODY, $search['text_not'][$key]);
+ case 'body':
+ case 'text':
+ if (!empty($rule->v)) {
+ $ob->text($rule->c, $search_fields[$rule->t]['type'] == 'body', !empty($rule->n));
$search_array[] = $ob;
}
break;
- case self::DATE:
- if (!empty($search['date'][$key]['day']) &&
- !empty($search['date'][$key]['month']) &&
- !empty($search['date'][$key]['year'])) {
- $date = new Horde_Date($search['date']);
- $ob->dateSearch($date, ($val == 'date_on') ? Horde_Imap_Client_Search_Query::DATE_ON : (($val == 'date_until') ? Horde_Imap_Client_Search_Query::DATE_BEFORE : Horde_Imap_Client_Search_Query::DATE_SINCE));
+ case 'date':
+ if (!empty($rule->v)) {
+ $date = new Horde_Date(array('year' => $rule->v->y, 'month' => $rule->v->m + 1, 'mday' => $rule->v->d));
+ $ob->dateSearch($date, ($rule->t == 'date_on') ? Horde_Imap_Client_Search_Query::DATE_ON : (($rule->t == 'date_until') ? Horde_Imap_Client_Search_Query::DATE_BEFORE : Horde_Imap_Client_Search_Query::DATE_SINCE));
$search_array[] = $ob;
}
break;
- case self::SIZE:
- if (!empty($search['text'][$key])) {
- $ob->size(intval($search['text'][$key]), $val == 'size_larger');
+ case 'size':
+ if (!empty($rule->v)) {
+ $ob->size(intval($rule->v), $rule->t == 'size_larger');
$search_array[] = $ob;
}
break;
}
}
- /* Search match. */
- if ($search['match'] == 'and') {
- $query->andSearch($search_array);
- } elseif ($search['match'] == 'or') {
- $query->orSearch($search_array);
- }
+ $query->andSearch($search_array);
return $query;
}
/**
+ * Create a search query from input gathered from the basic search script
+ * (imp/search-basic.php).
+ *
+ * @param string $mbox The mailbox to search.
+ * @param string $criteria The criteria to search.
+ * @param string $text The criteria text.
+ * @param boolean $not Should the criteria search be a not search?
+ * @param string $flag A flag to search for.
*
+ * @return string The search query ID.
*/
public function processBasicSearch($mbox, $criteria, $text, $not, $flag)
{
- $search_query = array(
- 'field' => array(),
- 'match' => 'and',
- 'text' => array(),
- 'text_not' => array()
- );
+ $c_list = array();
if ($criteria) {
- $search_query['field'][] = $criteria;
- $search_query['text'][] = $text;
- $search_query['text_not'][] = $not;
+ $tmp = new stdClass;
+ $tmp->t = $criteria;
+ $tmp->v = $text;
+ $tmp->n = $not;
+ $c_list[] = $tmp;
}
if ($flag) {
- $search_query['field'][] = $flag;
- $search_query['text'][] = $search_query['text_not'][] = null;
+ $tmp = new stdClass;
+ $tmp->t = $flag;
+ $c_list[] = $tmp;
}
/* Set the search in the IMP session. */
- return $GLOBALS['imp_search']->createSearchQuery($this->createQuery($search_query), array($mbox), array(), _("Search Results"));
+ return $GLOBALS['imp_search']->createSearchQuery($this->createQuery($c_list), array($mbox), $c_list, _("Search Results"), IMP_Search::MBOX_PREFIX . IMP_Search::BASIC_SEARCH);
}
}
</para>
</entry>
-<entry id="search">
- <title>Message Search</title>
- <heading>Search Criteria</heading>
- <para>
- You may search for messages from your folders using different search criteria.
- </para>
- <para>
- Step 1: Select whether you want to match <b>all</b> queries (an AND search) or match <b>any</b> query (an OR search).
- </para>
- <para>
- Step 2: Choose the fields(s) to add to your search criteria and, if necessary, identify the search parameters for these fields.
- </para>
- <para>
- Step 3: Choose the folder(s) from which to search for the messages.
- </para>
- <para>
- Step 4: Click "Search".
- </para>
- <para>
- If any messages matched your search criteria, then the subjects of these messages will be shown in the "Search Results" view.
- </para>
-</entry>
-
<entry id="folder-options">
<title>Folders: Folder Actions</title>
<para>
$pagetitle = $title .= ' (' . $unread . ')';
}
-if ($vfolder || $search_mbox) {
- $query_text = $imp_search->searchQueryText($imp_search->searchMboxID());
- if ($query_text) {
- $query_text = htmlspecialchars(wordwrap($query_text));
- if ($vfolder) {
- $pagetitle .= ' [' . Horde::linkTooltip('#', $query_text, '', '', '', $query_text) . _("Virtual Folder") . '</a>]';
- $title .= ' [' . _("Virtual Folder") . ']';
- } else {
- $pagetitle = Horde::linkTooltip('#', $query_text, '', '', '', $query_text) . $pagetitle . '</a>';
- }
+if ($vfolder ||
+ ($search_mbox && ($imp_search->searchMboxID() != IMP_Search::BASIC_SEARCH))) {
+ $query_text = wordwrap($imp_search->searchQueryText($imp_search->searchMboxID()));
+ if ($vfolder) {
+ $pagetitle .= ' [' . Horde::linkTooltip('#', $query_text, '', '', '', $query_text) . _("Virtual Folder") . '</a>]';
+ $title .= ' [' . _("Virtual Folder") . ']';
} else {
- $pagetitle = htmlspecialchars($title);
+ $pagetitle = Horde::linkTooltip('#', $query_text, '', '', '', $query_text) . $pagetitle . '</a>';
}
} else {
$pagetitle = $title = htmlspecialchars($title);
} else {
if ($imp_search->isEditableVFolder()) {
$edit_search = sprintf(_("Edit Virtual Folder Definition for %s"), htmlspecialchars($rawtitle));
- $hdr_template->set('delete_vfolder', Horde::link($imp_search->deleteURL(), sprintf(_("Delete Virtual Folder Definition for %s"), htmlspecialchars($rawtitle)), null, null, "if (confirm('" . addslashes(_("Are you sure you want to delete this Virtual Folder Definition?")) . "')) { return true; } else { return false; }") . Horde::img('delete.png', sprintf(_("Delete Virtual Folder Definition for %s"), $rawtitle), '', $graphicsdir) . '</a>');
- } elseif (!$query_text) {
+ $hdr_template->set('delete_vfolder', Horde::link($imp_search->deleteUrl(), sprintf(_("Delete Virtual Folder Definition for %s"), htmlspecialchars($rawtitle)), null, null, "if (confirm('" . addslashes(_("Are you sure you want to delete this Virtual Folder Definition?")) . "')) { return true; } else { return false; }") . Horde::img('delete.png', sprintf(_("Delete Virtual Folder Definition for %s"), $rawtitle), '', $graphicsdir) . '</a>');
+ } elseif ($search_mbox && !isset($query_text)) {
/* Mini search results. */
$search_mailbox = reset($imp_search->getSearchFolders());
$hdr_template->set('search', Horde::link(Horde_Util::addParameter(Horde::applicationUrl('search-basic.php'), array('search_mailbox' => $search_mailbox)), sprintf(_("Search %s"), IMP::getLabel($search_mailbox))) . Horde::img('search.png', _("Search")) . '</a>');
}
if (isset($edit_search)) {
- $hdr_template->set('search', Horde::link($imp_search->editURL(), $edit_search) . Horde::img('edit.png', $edit_search, '', $graphicsdir) . '</a>');
+ $hdr_template->set('search', Horde::link($imp_search->editUrl(), $edit_search) . Horde::img('edit.png', $edit_search, '', $graphicsdir) . '</a>');
}
}
}
exit;
}
-$imp_ui_search = new IMP_UI_Search();
-
/* If search_basic_mbox is set, we are processing the search query. */
$search_mailbox = Horde_Util::getFormData('search_basic_mbox');
if ($search_mailbox) {
+ $imp_ui_search = new IMP_UI_Search();
$id = $imp_ui_search->processBasicSearch($search_mailbox, Horde_Util::getFormData('search_criteria'), Horde_Util::getFormData('search_criteria_text'), Horde_Util::getFormData('search_criteria_not'), Horde_Util::getFormData('search_flags'));
/* Redirect to the mailbox screen. */
$f_fields = $s_fields = array();
$search_mailbox = Horde_Util::getFormData('search_mailbox');
-foreach ($imp_ui_search->searchFields() as $key => $val) {
- if ($val['type'] != IMP_UI_Search::DATE) {
+foreach ($imp_search->searchFields() as $key => $val) {
+ if ($val['type'] != 'date') {
$s_fields[] = array(
'val' => $key,
'label' => $val['label']
}
}
-foreach ($imp_ui_search->flagFields() as $key => $val) {
+foreach ($imp_search->flagFields() as $key => $val) {
$f_fields[] = array(
'val' => $key,
'label' => $val
<?php
/**
- * IMP search script.
+ * IMP advanced search script. This search script only works with javascript
+ * enabled browsers. All other browsers are limited to the basic search
+ * script only.
*
* URL Parameters:
* ---------------
- * 'search_mailbox' -- If exists, don't show the folder selection list; use
- * the passed in mailbox value instead.
- * 'edit_query' -- If exists, the search query to edit.
+ * 'criteria_form' - (string) JSON representation of the search query.
+ * 'edit_query' - (string) The search query to edit.
+ * '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'
*
* Copyright 1999-2009 The Horde Project (http://www.horde.org/)
*
require_once dirname(__FILE__) . '/lib/Application.php';
new IMP_Application(array('init' => true));
-/* Load mailbox page if searching is not allowed. */
-if ($_SESSION['imp']['protocol'] == 'pop') {
- $notification->push(_("Searching is not available with a POP3 server."), 'horde.error');
- $from_message_page = true;
- $actionID = $start = null;
- require_once IMP_BASE . '/mailbox.php';
- exit;
-}
-
-/* Load basic search if javascript is not enabled. */
-if (!$browser->hasFeature('javascript')) {
+/* Load basic search if javascript is not enabled or searching is not
+ * allowed (basic page will do the required redirection in the latter case). */
+if (!$browser->hasFeature('javascript') ||
+ ($_SESSION['imp']['protocol'] == 'pop')) {
require_once IMP_BASE . '/search-basic.php';
exit;
}
-$imp_ui_search = new IMP_UI_Search();
-
-$actionID = Horde_Util::getFormData('actionID');
-$edit_query = Horde_Util::getFormData('edit_query');
-$edit_query_vfolder = Horde_Util::getFormData('edit_query_vfolder');
-$search_mailbox = Horde_Util::getFormData('search_mailbox');
-
-$imp_search_fields = $imp_ui_search->searchFields();
-
$charset = Horde_Nls::getCharset();
+$criteria = Horde_Util::getFormData('criteria_form');
+$edit_query = Horde_Util::getFormData('edit_query');
+$imp_search_fields = $imp_search->searchFields();
-/* Get URL parameter data. */
-$retrieve_search = false;
-$search = array();
-if (!is_null($edit_query) && $imp_search->isSearchMbox($edit_query)) {
- if ($imp_search->isVFolder($edit_query)) {
- if (!$imp_search->isEditableVFolder($edit_query)) {
- $notification->push(_("Special Virtual Folders cannot be edited."), 'horde.error');
- header('Location: ' . Horde::applicationUrl('mailbox.php', true));
- exit;
- }
- $edit_query_vfolder = $edit_query;
- }
- $search = $imp_search->retrieveUIQuery($edit_query);
- $retrieve_search = true;
-}
-
-if (empty($search)) {
- $search['field'] = Horde_Util::getFormData('field', array('from', 'to', 'subject', 'body'));
- if (!empty($search['field']) && !end($search['field'])) {
- array_pop($search['field']);
- }
- $search['field_end'] = count($search['field']);
- $search['match'] = Horde_Util::getFormData('search_match');
- $search['text'] = Horde_Util::getFormData('search_text');
- $search['text_not'] = Horde_Util::getFormData('search_text_not');
- $search['date'] = Horde_Util::getFormData('search_date');
- $search['folders'] = Horde_Util::getFormData('search_folders', array());
- $search['save_vfolder'] = Horde_Util::getFormData('save_vfolder');
- $search['vfolder_label'] = Horde_Util::getFormData('vfolder_label');
- $search['mbox'] = Horde_Util::getFormData('mbox', $search_mailbox);
-}
-
-/* Run through the action handlers. */
-switch ($actionID) {
-case 'do_search':
- /* Need to convert size from KB to bytes. */
- for ($i = 0; $i <= $search['field_end']; $i++) {
- if (isset($search['field'][$i]) &&
- isset($imp_search_fields[$search['field'][$i]]) &&
- ($imp_search_fields[$search['field'][$i]]['type'] == IMP_UI_Search::SIZE)) {
- $search['text'][$i] *= 1024;
- }
- }
+/* Generate the search query if 'criteria_form' is present in the form
+ * data. */
+if (!empty($criteria)) {
+ $criteria = Horde_Serialize::unserialize($criteria, Horde_Serialize::JSON);
+ $folders = Horde_Util::getFormData('search_folders_form');
/* Create the search query. */
- $query = $imp_ui_search->createQuery($search);
+ $imp_ui_search = new IMP_UI_Search();
+ $query = $imp_ui_search->createQuery($criteria);
/* Save the search as a virtual folder if requested. */
- if (!empty($search['save_vfolder'])) {
- if (empty($search['vfolder_label'])) {
- $notification->push(_("Virtual Folders require a label."), 'horde.error');
- break;
- }
-
- $id = $imp_search->addVFolder($query, $search['folders'], $search, $search['vfolder_label'], (empty($edit_query_vfolder) ? null : $edit_query_vfolder));
- $notification->push(sprintf(_("Virtual Folder \"%s\" created succesfully."), $search['vfolder_label']), 'horde.success');
+ if (Horde_Util::getFormData('vfolder_save')) {
+ $edit_query_vfolder = Horde_Util::getFormData('edit_query_vfolder');
+ $vfolder_label = Horde_Util::getFormData('vfolder_label');
+ $id = $imp_search->addVFolder($query, $folders, $criteria, $vfolder_label, empty($edit_query_vfolder) ? null : $edit_query_vfolder);
+ $notification->push(sprintf(_("Virtual Folder \"%s\" created succesfully."), $vfolder_label), 'horde.success');
} else {
- /* Set the search in the IMP session. */
- $id = $imp_search->createSearchQuery($query, $search['folders'], $search, _("Search Results"));
+ /* Set the search in the session. */
+ $id = $imp_search->createSearchQuery($query, $folders, $criteria, _("Search Results"));
}
- /* Redirect to the Mailbox Screen. */
- header('Location: ' . Horde_Util::addParameter(Horde::applicationUrl('mailbox.php', true), 'mailbox', $GLOBALS['imp_search']->createSearchID($id), false));
+ /* Redirect to the mailbox page. */
+ header('Location: ' . Horde_Util::addParameter(Horde::applicationUrl('mailbox.php', true), array('mailbox' => $GLOBALS['imp_search']->createSearchID($id)), null, false));
exit;
+}
-case 'reset_search':
- if ($def_search = $prefs->getValue('default_search')) {
- $search['field'] = array($def_search);
- $search['field_end'] = 1;
- } else {
- $search['field'] = array();
- $search['field_end'] = 0;
- }
- $search['match'] = null;
- $search['date'] = $search['text'] = $search['text_not'] = $search['flag'] = array();
- $search['folders'] = array();
- break;
+/* Generate master folder list. */
+$show_unsub = ($subscribe = $prefs->getValue('subscribe'))
+ ? Horde_Util::getFormData('show_unsub', false)
+ : false;
+
+$imp_folder = IMP_Folder::singleton();
+$folders = array();
+foreach ($imp_folder->flist(array(), $subscribe && !$show_unsub) as $val) {
+ $folders[] = array_filter(array(
+ 'l' => Horde_Text_Filter::filter($val['label'], 'space2html', array('charset' => $charset, 'encode' => true)),
+ 'v' => $val['val']
+ ));
+}
-case 'delete_field':
- $key = Horde_Util::getFormData('delete_field_id');
+if (Horde_Util::getFormData('show_unsub') !== null) {
+ Horde::sendHTTPResponse($folders, 'json');
+}
- /* Unset all entries in array input and readjust ids. */
- $vars = array('field', 'text', 'text_not', 'date');
- foreach ($vars as $val) {
- unset($search[$val][$key]);
- if (!empty($search[$val])) {
- $search[$val] = array_values($search[$val]);
- }
+$on_domload = array(
+ 'ImpSearch.updateFolderList(' . Horde_Serialize::serialize($folders, Horde_Serialize::JSON, $charset) . ')'
+);
+
+/* Process list of saved searches. */
+$saved_searches = $imp_search->listQueries(IMP_Search::LIST_SEARCH | IMP_Search::NO_BASIC_SEARCH, false);
+if (!empty($saved_searches)) {
+ $ss = array();
+ foreach ($saved_searches as $key => $val) {
+ $ss[$key] = array(
+ 'c' => $imp_search->getCriteria($key),
+ 'l' => Horde_String::truncate($val),
+ 'v' => $key
+ );
}
- $search['field_end'] = count($search['field']);
- break;
+ $on_domload[] = 'ImpSearch.updateSavedSearches(' . Horde_Serialize::serialize($ss, Horde_Serialize::JSON, $charset) . ')';
}
-$shown = null;
-if (!$conf['user']['allow_folders']) {
- $search['mbox'] = 'INBOX';
- $search['folders'][] = 'INBOX';
- $subscribe = false;
-} elseif ($subscribe = $prefs->getValue('subscribe')) {
- $shown = Horde_Util::getFormData('show_subscribed_only', $subscribe);
-}
+/* Preselect mailboxes. */
+$on_domload[] = 'ImpSearch.updateSelectedFolders(' . Horde_Serialize::serialize(array(Horde_Util::getFormData('search_mailbox', 'INBOX')), Horde_Serialize::JSON, $charset) . ')';
/* Prepare the search template. */
$t = new Horde_Template();
$t->setOption('gettext', true);
-
$t->set('action', Horde::applicationUrl('search.php'));
$t->set('subscribe', $subscribe);
-$t->set('shown', htmlspecialchars($shown));
-$t->set('edit_query_vfolder', htmlspecialchars($edit_query_vfolder));
-if (!$edit_query_vfolder) {
- if (empty($search['mbox'])) {
- $t->set('search_title', _("Search"));
- } else {
- $t->set('search_title',
- sprintf(
- _("Search %s"),
- Horde::link(
- Horde::url(Horde_Util::addParameter('mailbox.php',
- 'mailbox',
- $search['mbox'])))
- . htmlspecialchars(IMP::displayFolder($search['mbox']))
- . '</a>'));
- }
-}
-$t->set('search_help', Horde_Help::link('imp', 'search'));
-$t->set('match_or', $search['match'] == 'or');
-$t->set('label_or', Horde::label('search_match_or', _("Match Any Query")));
-$t->set('match_and', ($search['match'] == null) || ($search['match'] == 'and'));
-$t->set('label_and', Horde::label('search_match_and', _("Match All Queries")));
-$saved_searches = $imp_search->listQueries(IMP_Search::LIST_SEARCH, false);
-if (!empty($saved_searches)) {
- $ss = array();
- foreach ($saved_searches as $key => $val) {
- $ss[] = array('val' => htmlspecialchars($key), 'text' => htmlspecialchars(Horde_String::truncate($val)));
+/* Determine if we are editing a current search folder. */
+if (!is_null($edit_query) && $imp_search->isSearchMbox($edit_query)) {
+ if ($imp_search->isVFolder($edit_query)) {
+ if (!$imp_search->isEditableVFolder($edit_query)) {
+ $notification->push(_("Special Virtual Folders cannot be edited."), 'horde.error');
+ header('Location: ' . Horde::applicationUrl('mailbox.php', true));
+ exit;
+ }
+ $t->set('edit_query_vfolder', htmlspecialchars($edit_query));
}
- $t->set('saved_searches', $ss);
+ $on_domload[] = 'ImpSearch.updateSearchCriteria(' . Horde_Serialize::serialize($imp_search->getCriteria($edit_query), Horde_Serialize::JSON, $charset) . ')';
}
-$fields = $f_fields = $s_fields = array();
-$js_first = 0;
+$f_fields = $s_fields = $types = array();
/* Process the list of fields. */
foreach ($imp_search_fields as $key => $val) {
- $s_fields[$key] = array(
+ $s_fields[] = array(
'val' => $key,
- 'label' => $val['label'],
- 'sel' => null
+ 'label' => $val['label']
);
+ $types[$key] = $val['type'];
}
-foreach ($imp_ui_search->flagFields() as $key => $val) {
- $f_fields[$key] = array(
+$t->set('s_fields', $s_fields);
+
+foreach ($imp_search->flagFields() as $key => $val) {
+ $f_fields[] = array(
'val' => $key,
- 'label' => $val,
- 'sel' => null
+ 'label' => $val
);
+ $types[$key] = 'flag';
}
+$t->set('f_fields', $f_fields);
-for ($i = 0; $i <= $search['field_end']; $i++) {
- $curr = (isset($search['field'][$i])) ? $search['field'][$i] : null;
- $fields[$i] = array(
- 'i' => $i,
- 'last' => ($i == $search['field_end']),
- 'curr' => $curr,
- 'f_fields' => $f_fields,
- 'first' => (($i == 0) && ($i != $search['field_end'])),
- 'notfirst' => ($i > 0),
- 's_fields' => $s_fields,
- 'search_text' => false,
- 'search_date' => false,
- 'js_calendar' => null
- );
- if ($curr !== null) {
- if (isset($f_fields[$curr])) {
- $fields[$i]['f_fields'][$curr]['sel'] = true;
- } else {
- $fields[$i]['s_fields'][$curr]['sel'] = true;
- if (in_array($imp_search_fields[$curr]['type'], array(IMP_UI_Search::HEADER, IMP_UI_Search::BODY, IMP_UI_Search::TEXT, IMP_UI_Search::SIZE))) {
- $fields[$i]['search_text'] = true;
- $fields[$i]['search_text_val'] = (!empty($search['text'][$i])) ? @htmlspecialchars($search['text'][$i], ENT_COMPAT, $charset) : null;
- if ($retrieve_search &&
- ($imp_search_fields[$curr]['type'] == IMP_UI_Search::SIZE)) {
- $fields[$i]['search_text_val'] /= 1024;
- }
- if ($imp_search_fields[$curr]['not']) {
- $fields[$i]['show_not'] = true;
- $fields[$i]['search_text_not'] = (!empty($search['text_not'][$i]));
- }
- } elseif ($imp_search_fields[$curr]['type'] == IMP_UI_Search::DATE) {
- if (!isset($curr_date)) {
- $curr_date = getdate();
- }
- $fields[$i]['search_date'] = true;
-
- $fields[$i]['month'] = array();
- $month_default = isset($search['date'][$i]['month']) ? $search['date'][$i]['month'] : $curr_date['mon'];
- for ($month = 1; $month <= 12; $month++) {
- $fields[$i]['month'][] = array(
- 'val' => $month,
- 'sel' => ($month == $month_default),
- 'label' => strftime('%B', mktime(0, 0, 0, $month, 1))
- );
- }
-
- $fields[$i]['day'] = array();
- $day_default = isset($search['date'][$i]['day']) ? $search['date'][$i]['day'] : $curr_date['mday'];
- for ($day = 1; $day <= 31; $day++) {
- $fields[$i]['day'][] = array(
- 'val' => $day,
- 'sel' => ($day == $day_default)
- );
- }
-
- $fields[$i]['year'] = array();
- $year_default = isset($search['date'][$i]['year']) ? $search['date'][$i]['year'] : $curr_date['year'];
- if (!isset($curr_year)) {
- $curr_year = date('Y');
- $yearlist = array();
- $years = -20;
- $startyear = (($year_default < $curr_year) && ($years > 0)) ? $year_default : $curr_year;
- $startyear = min($startyear, $startyear + $years);
- for ($j = 0; $j <= abs($years); $j++) {
- $yearlist[] = $startyear++;
- }
- if ($years < 0) {
- $yearlist = array_reverse($yearlist);
- }
- }
- foreach ($yearlist as $year) {
- $fields[$i]['year'][] = array(
- 'val' => $year,
- 'sel' => ($year == $year_default)
- );
- }
-
- if ($browser->hasFeature('javascript')) {
- Horde::addScriptFile('open_calendar.js', 'horde');
- $fields[$i]['js_calendar_first'] = !$js_first++;
- $fields[$i]['js_calendar'] = Horde::link('#', _("Select a date"), '', '', 'openCalendar(\'dateimg' . $i . '\', \'search_date_' . $i . '\'); return false;');
- $fields[$i]['js_calendar_img'] = Horde::img('calendar.png', _("Calendar"), 'align="top" id="dateimg' . $i . '"', $GLOBALS['registry']->getImageDir('horde'));
- }
- }
- }
- }
-}
-$t->set('fields', array_values($fields));
-$t->set('delete_img', $registry->getImageDir('horde') . '/delete.png');
-$t->set('remove', _("Remove Field From Search"));
-
-if ($subscribe) {
- $t->set('inverse_subscribe', !$shown);
-}
-
-$t->set('mbox', htmlspecialchars($search['mbox']));
$t->set('virtualfolder', $_SESSION['imp']['protocol'] != 'pop');
-if ($t->get('virtualfolder')) {
- $t->set('save_vfolder', !empty($search['save_vfolder']));
- $t->set('vfolder_label', !empty($search['vfolder_label']) ? htmlspecialchars($search['vfolder_label'], ENT_COMPAT, $charset) : null);
-}
-if (empty($search['mbox'])) {
- $count = -1;
- $mboxes = array();
- $newcol = $numcolumns = 1;
-
- $imp_folder = IMP_Folder::singleton();
- $mailboxes = $imp_folder->flist(array(), !is_null($shown) ? $shown : null);
- $total = ceil(count($mailboxes) / 3);
-
- if (empty($search['folders']) && ($actionID != 'update_search')) {
- /* Default to Inbox search. */
- $search['folders'][] = 'INBOX';
- }
-
- foreach ($mailboxes as $key => $mbox) {
- $mboxes[$key] = array(
- 'count' => ++$count,
- 'val' => (!empty($mbox['val']) ? htmlspecialchars($mbox['val']) : null),
- 'sel' => false,
- 'label' => str_replace(' ', ' ', $mbox['label']),
- 'newcol' => false
- );
+Horde_UI_JsCalendar::init();
- if (!empty($mbox['val']) &&
- in_array($mbox['val'], $search['folders'])) {
- $mboxes[$key]['sel'] = true;
- }
-
- if ((++$newcol > $total) && ($numcolumns != 3)) {
- $newcol = 1;
- ++$numcolumns;
- $mboxes[$key]['newcol'] = true;
- }
- }
- $t->set('mboxes', array_values($mboxes));
-}
+Horde::addInlineScript(array(
+ '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.types = ' . Horde_Serialize::serialize($types, Horde_Serialize::JSON, $charset)
+));
+Horde::addInlineScript($on_domload, 'dom');
-$title = _("Message Search");
-Horde::addScriptFile('stripe.js', 'horde', true);
+$title = _("Search");
+Horde::addScriptFile('horde.js', 'horde', true);
Horde::addScriptFile('search.js', 'imp', true);
IMP::prepareMenu();
require IMP_TEMPLATES . '/common-header.inc';
IMP::menu();
IMP::status();
-Horde::addInlineScript(array(
- 'ImpSearch.search_date = ' . Horde_Serialize::serialize(array('m' => date('m'), 'd' => date('d'), 'y' => date('Y')), Horde_Serialize::JSON, $charset),
- 'ImpSearch.not_search = ' . intval(empty($search['mbox'])),
- 'ImpSearch.inverse_sub = ' . intval($t->get('inverse_subscribe')),
-));
echo $t->fetch(IMP_TEMPLATES . '/search/search.html');
require $registry->get('templates', 'horde') . '/common-footer.inc';
'folders_rename2' => _("Please enter the new name:"),
'folders_no_rename' => _("This folder may not be renamed:"),
- /* Strings used in search.js */
- 'search_select' => _("Please select at least one folder to search."),
-
/* Strings used in imp.js */
'popup_block' => _("A popup window could not be opened. Perhaps you have set your browser to block popup windows?"),
-<form method="post" id="search" action="<tag:action />">
-<input type="hidden" id="actionID" name="actionID" value="update_search" />
-<input type="hidden" id="delete_field_id" name="delete_field_id" value="" />
-<input type="hidden" id="edit_query" name="edit_query" value="" />
-<input type="hidden" name="edit_query_vfolder" value="<tag:edit_query_vfolder />" />
-<if:mbox>
-<input type="hidden" name="mbox" value="<tag:mbox />" />
-<input id="preselected_folders" type="hidden" name="search_folders[]" value="<tag:mbox />" />
-<else:mbox>
-<if:subscribe>
-<input type="hidden" id="show_subscribed_only" name="show_subscribed_only" value="<tag:shown />" />
-</if:subscribe>
-</else:mbox></if:mbox>
+<form id="search_form" action="<tag:action />" method="post">
+ <input class="hidden" name="criteria_form" id="criteria_form" value="" />
-<h1 class="header">
-<if:edit_query_vfolder>
- <strong><gettext>Edit Virtual Folder</gettext></strong>
-<else:edit_query_vfolder>
- <strong><tag:search_title /></strong>
-</else:edit_query_vfolder></if:edit_query_vfolder>
- <tag:search_help />
-</h1>
+ <h1 class="header">
+ <strong><if:edit_query_vfolder><gettext>Edit Virtual Folder</gettext><else:edit_query_vfolder><gettext>Search</gettext></else:edit_query_vfolder></if:edit_query_vfolder></strong>
+ </h1>
-<div>
- <input type="submit" class="button searchSubmit" value="<if:edit_query_vfolder><gettext>Save</gettext><else:edit_query_vfolder><gettext>Submit</gettext></else:edit_query_vfolder></if:edit_query_vfolder>" />
- <input type="button" class="button searchReset" value="<gettext>Reset</gettext>" />
-</div>
+ <div id="recent_searches_div" class="smallheader leftAlign" style="display:none">
+ <span class="searchuiImg arrowExpanded" style="display:none"></span>
+ <span class="searchuiImg arrowCollapsed"></span>
+ <gettext>Recent Searches</gettext>
+ </div>
-<if:saved_searches>
-<div class="smallheader leftAlign">
- <gettext>Recent Searches</gettext>
-</div>
+ <div class="item" style="display:none">
+ <label for="recent_searches" class="hidden"><gettext>Recent Searches:</gettext></label>
+ <select id="recent_searches">
+ <option value=""><gettext>Recent Searches:</gettext></option>
+ </select>
+ </div>
-<div class="item">
- <label for="save_cache" class="hidden"><gettext>Recent Searches:</gettext></label>
- <select id="save_cache" name="save_cache">
- <option value=""><gettext>Recent Searches:</gettext></option>
-<loop:saved_searches>
- <option value="<tag:saved_searches.val />"><tag:saved_searches.text /></option>
-</loop:saved_searches>
- </select>
-</div>
-</if:saved_searches>
-
-<div class="smallheader leftAlign">
+ <div class="smallheader leftAlign">
+ <span class="searchuiImg arrowExpanded"></span>
+ <span class="searchuiImg arrowCollapsed" style="display:none"></span>
<gettext>Search Criteria</gettext>
-</div>
+ </div>
-<div class="item">
- <input type="radio" class="checkbox" name="search_match" id="search_match_or" value="or"<if:match_or> checked="checked"</if:match_or> />
- <em><tag:label_or /></em>
- <input type="radio" class="checkbox" name="search_match" id="search_match_and" value="and"<if:match_and> checked="checked"</if:match_and> />
- <em><tag:label_and /></em>
-
-<table class="item" cellspacing="0">
-<loop:fields>
- <tr>
-<if:fields.first>
- <td> </td>
-<else:fields.first><if:fields.i>
- <td><strong><if:match_and><gettext>AND</gettext><else:match_and><gettext>OR</gettext></else:match_and></if:match_and></strong></td>
-</if:fields.i>
-</else:fields.first></if:fields.first>
- <td>
- <label for="field_<tag:fields.i />" class="hidden"><gettext>Select a field</gettext></label>
- <select name="field[<tag:fields.i />]" id="field_<tag:fields.i />">
-<if:fields.last>
- <option value=""><gettext>Select a field</gettext></option>
+ <div class="item">
+ <div>
+ <select id="search_criteria">
+ <option value=""><gettext>Add search criteria:</gettext></option>
<option value="" disabled="disabled">- - - - - - - - -</option>
-</if:fields.last>
-<loop:fields.s_fields>
- <option value="<tag:fields.s_fields.val />"<if:fields.s_fields.sel> selected="selected"</if:fields.s_fields.sel>><tag:fields.s_fields.label /></option>
-</loop:fields.s_fields>
+<loop:s_fields>
+ <option value="<tag:s_fields.val />"><tag:s_fields.label /></option>
+</loop:s_fields>
<option value="" disabled="disabled">- - - - - - - - -</option>
-<loop:fields.f_fields>
- <option value="<tag:fields.f_fields.val />"<if:fields.f_fields.sel> selected="selected"</if:fields.f_fields.sel>><tag:fields.f_fields.label /></option>
-</loop:fields.f_fields>
- </select>
- </td>
-<if:fields.curr>
-<if:fields.search_text>
- <td class="leftAlign">
- <input type="text" id="search_text_<tag:fields.i />" name="search_text[<tag:fields.i />]" size="40" <if:fields.search_text_val>value="<tag:fields.search_text_val />" </if:fields.search_text_val>/>
- <label for="search_text_<tag:fields.i />" class="hidden"><gettext>Search Text</gettext></label>
-<if:fields.show_not>
- <input type="checkbox" class="checkbox" id="search_text_not_<tag:fields.i />" name="search_text_not[<tag:fields.i />]" <if:fields.search_text_not>checked="checked" </if:fields.search_text_not>/>
- <label for="search_text_not_<tag:fields.i />"><em><gettext>Do NOT match</gettext></em></label>
-</if:fields.show_not>
- </td>
-</if:fields.search_text>
-<if:fields.search_date>
- <td class="leftAlign">
- <label for="search_date_<tag:fields.i />_month" class="hidden"><gettext>Month</gettext></label>
- <select id="search_date_<tag:fields.i />_month" name="search_date[<tag:fields.i />][month]">
-<loop:fields.month>
- <option value="<tag:fields.month.val />" <if:fields.month.sel>selected="selected" </if:fields.month.sel>><tag:fields.month.label /></option>
-</loop:fields.month>
+<loop:f_fields>
+ <option value="<tag:f_fields.val />"><tag:f_fields.label /></option>
+</loop:f_fields>
</select>
- <label for="search_date_<tag:fields.i />_day" class="hidden"><gettext>Day</gettext></label>
- <select id="search_date_<tag:fields.i />_day" name="search_date[<tag:fields.i />][day]">
-<loop:fields.day>
- <option value="<tag:fields.day.val />" <if:fields.day.sel>selected="selected" </if:fields.day.sel>><tag:fields.day.val /></option>
-</loop:fields.day>
- </select>
- <label for="search_date_<tag:fields.i />_year" class="hidden"><gettext>Year</gettext></label>
- <select id="search_date_<tag:fields.i />_year" name="search_date[<tag:fields.i />][year]">
-<loop:fields.year>
- <option value="<tag:fields.year.val />" <if:fields.year.sel>selected="selected"</if:fields.year.sel>><tag:fields.year.val /></option>
-</loop:fields.year>
- </select>
-<if:fields.js_calendar>
-<if:fields.js_calendar_first>
- <div id="goto" style="position:absolute;visibility:hidden;padding:1px"></div>
-</if:fields.js_calendar_first>
- <tag:fields.js_calendar /><tag:fields.js_calendar_img /></a>
-</if:fields.js_calendar>
- </td>
-</if:fields.search_date>
-<else:fields.curr>
- <td> </td>
-</else:fields.curr></if:fields.curr>
+ </div>
+ </div>
-<if:fields.last>
-<if:fields.i>
- <td> </td>
-</if:fields.i>
-<else:fields.last>
- <td><input type="image" class="image searchDelete" fid="<tag:fields.i />" src="<tag:delete_img />" value="<tag:remove />" /></td>
-</else:fields.last></if:fields.last>
- </tr>
-</loop:fields>
-</table>
-</div>
-
-<if:mbox><else:mbox>
-<div class="smallheader leftAlign">
- <gettext>Search Folders</gettext>
-</div>
-
-<div class="item">
- <a id="link_sel_all" href="#"><gettext>Select all</gettext></a> |
- <a id="link_sel_none" href="#"><gettext>Select none</gettext></a>
+ <div class="smallheader leftAlign" id="search_folders_hdr">
+ <span class="searchuiImg arrowExpanded" style="display:none"></span>
+ <span class="searchuiImg arrowCollapsed"></span>
+ <gettext>Search Folders</gettext>
+ <span class="item" 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>
- | <a id="link_sub" href="#"><if:inverse_subscribe><gettext>Show Only Subscribed Folders</gettext><else:inverse_subscribe><gettext>Show All Folders</gettext></else:inverse_subscribe></if:inverse_subscribe></a>
+| <a id="link_sub" href="#"><span><gettext>Show All</gettext></span><span style="display:none"><gettext>Show Subscribed Only</gettext></span></a>
</if:subscribe>
-</div>
+ </span>
+ </div>
-<table width="100%" cellspacing="0">
- <tr>
- <td class="item leftAlign" valign="top">
-<loop:mboxes>
- <input id="folder<tag:mboxes.count />" type="checkbox" class="checkbox"<if:mboxes.val>name="search_folders[]" value="<tag:mboxes.val />"<if:mboxes.sel> checked="checked"</if:mboxes.sel><else:mboxes.val>disabled="disabled"</else:mboxes.val></if:mboxes.val> />
- <tag:mboxes.label /><br />
-<if:mboxes.newcol>
- </td>
- <td class="item" valign="top">
-</if:mboxes.newcol>
-</loop:mboxes>
- </td>
- </tr>
-</table>
-</else:mbox></if:mbox>
+ <div class="item" style="display:none">
+ </div>
<if:virtualfolder>
-<div class="smallheader leftAlign">
- <gettext>Virtual Folders</gettext>
-</div>
+ <div class="smallheader leftAlign">
+ <span class="searchuiImg arrowExpanded" style="display:none"></span>
+ <span class="searchuiImg arrowCollapsed"></span>
+ <gettext>Virtual Folders</gettext>
+ </div>
+ <div style="display:none">
<if:edit_query_vfolder>
-<input type="hidden" name="save_vfolder" value="1" />
+ <input type="hidden" name="edit_query_vfolder" value="" />
<else:edit_query_vfolder>
-<div class="item">
- <label for="save_vfolder"><em><gettext>Save search as a virtual folder?</gettext></em></label> <input type="checkbox" class="checkbox" id="save_vfolder" name="save_vfolder" <if:save_vfolder>checked="checked" </if:save_vfolder>/>
-</div>
+ <div class="item">
+ <label for="vfolder_save"><gettext>Save search as a virtual folder?</gettext></label> <input type="checkbox" class="checkbox" id="vfolder_save" name="vfolder_save" />
+ </div>
</else:edit_query_vfolder></if:edit_query_vfolder>
-<div class="item">
- <label for="vfolder_label"><em><gettext>Virtual folder label:</gettext></em></label> <input type="text" id="vfolder_label" name="vfolder_label" <if:vfolder_label>value="<tag:vfolder_label />" </if:vfolder_label>/>
-</div>
+ <div class="item">
+ <label for="vfolder_label"><gettext>Label:</gettext></label> <input type="text" name="vfolder_label" id="vfolder_label" />
+ </div>
+ </div>
</if:virtualfolder>
-<div>
- <input type="submit" class="button searchSubmit" value="<if:edit_query_vfolder><gettext>Save</gettext><else:edit_query_vfolder><gettext>Submit</gettext></else:edit_query_vfolder></if:edit_query_vfolder>" />
- <input type="button" class="button searchReset" value="<gettext>Reset</gettext>" />
-</div>
+ <div>
+ <input type="button" id="search_submit" class="button" value="<if:edit_query_vfolder><gettext>Save</gettext><else:edit_query_vfolder><gettext>Submit</gettext></else:edit_query_vfolder></if:edit_query_vfolder>" />
+ <input type="button" id="search_reset" class="button" value="<gettext>Reset</gettext>" />
+ </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>
}
/* Search page styling. */
-form#search div {
- padding: 1px;
+.searchuiCalendar {
+ background-image: url("graphics/calendar.png");
}
/* Folder view. */
background-image: url("graphics/tree/rev-plusbottom.png");
}
+/* Expand/Collapse graphic. */
+span.arrowCollapsed {
+ background-image: url("graphics/arrow_collapsed.png");
+}
+span.arrowExpanded {
+ background-image: url("graphics/arrow_expanded.png");
+}
+
/* Loading graphic */
span.loadingImg {
z-index: 1000;
white-space: nowrap;
}
-.downloadAtc, .downloadZipAtc, .saveImgAtc, .closeImg, .stripAtc, .foldersImg {
+.downloadAtc, .downloadZipAtc, .saveImgAtc, .closeImg, .stripAtc, .foldersImg, .searchuiImg {
display: -moz-inline-stack;
display: inline-block;
height: 16px;
.saveImgAtc {
background-image: url("graphics/gallery.png");
}
-.stripAtc {
+.stripAtc, .searchuiDelete {
background-image: url("graphics/delete.png");
}
.closeImg {
.closeImg {
background-image: url("graphics/close.png");
}
+.searchuiCalendar {
+ background-image: url("graphics/calendar.png");
+}
.closeImg {
background-image: url("graphics/close.png");
}
+.searchuiCalendar {
+ background-image: url("graphics/calendar.png");
+}