diff options
Diffstat (limited to 'template/en/default')
-rw-r--r-- | template/en/default/search/boolean-charts.html.tmpl | 118 | ||||
-rw-r--r-- | template/en/default/search/form.html.tmpl | 670 | ||||
-rw-r--r-- | template/en/default/search/knob.html.tmpl | 95 | ||||
-rw-r--r-- | template/en/default/search/search-advanced.html.tmpl | 831 | ||||
-rw-r--r-- | template/en/default/search/search.html.tmpl | 831 |
5 files changed, 899 insertions, 1646 deletions
diff --git a/template/en/default/search/boolean-charts.html.tmpl b/template/en/default/search/boolean-charts.html.tmpl new file mode 100644 index 000000000..2d25f91f0 --- /dev/null +++ b/template/en/default/search/boolean-charts.html.tmpl @@ -0,0 +1,118 @@ +<!-- 1.0@bugzilla.org --> +[%# The contents of this file are subject to the Mozilla Public + # License Version 1.1 (the "License"); you may not use this file + # except in compliance with the License. You may obtain a copy of + # the License at http://www.mozilla.org/MPL/ + # + # Software distributed under the License is distributed on an "AS + # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + # implied. See the License for the specific language governing + # rights and limitations under the License. + # + # The Original Code is the Bugzilla Bug Tracking System. + # + # The Initial Developer of the Original Code is Netscape Communications + # Corporation. Portions created by Netscape are + # Copyright (C) 1998 Netscape Communications Corporation. All + # Rights Reserved. + # + # Contributor(s): Gervase Markham <gerv@gerv.net> + #%] + +[% types = [ + { name => "noop", description => "---" }, + { name => "equals", description => "is equal to" }, + { name => "notequals", description => "is not equal to" }, + { name => "substring", description => "contains the string" }, + { name => "casesubstring", description => "contains the string (exact case)" }, + { name => "notsubstring", description => "does not contain the string" }, + { name => "allwordssubstr", description => "contains all of the strings" }, + { name => "anywordssubstr", description => "contains any of the strings" }, + { name => "regexp", description => "contains regexp" }, + { name => "notregexp", description => "does not contain regexp" }, + { name => "lessthan", description => "is less than" }, + { name => "greaterthan", description => "is greater than" }, + { name => "anywords", description => "contains any of the words" }, + { name => "allwords", description => "contains all of the words" }, + { name => "nowords", description => "contains none of the words" }, + { name => "changedbefore", description => "changed before" }, + { name => "changedafter", description => "changed after" }, + { name => "changedfrom", description => "changed from" }, + { name => "changedto", description => "changed to" }, + { name => "changedby", description => "changed by" } ] %] + + <p> + <strong> + <a name="chart" href="queryhelp.cgi#advancedquerying"> + Advanced Querying Using Boolean Charts</a>: + </strong> + </p> + +[%# Whoever wrote the original version of boolean charts had a seriously twisted mind %] + +[% jsmagic = "onclick=\"document.forms[0].action='query.cgi#chart'; document.forms[0].method='POST'; return 1;\"" %] + +[% FOREACH chart = default.charts %] + [% chartnum = loop.count - 1 %] + <table> + [% FOREACH row = chart %] + [% rownum = loop.count - 1 %] + <tr> + [% FOREACH col = row %] + [% colnum = loop.count - 1 %] + <td> + <select name="[% "field${chartnum}-${rownum}-${colnum}" %]"> + [% FOREACH field = fields %] + <option value="[% field.name %]" + [%- " selected" IF field.name == col.field %]>[% field.description %]</option> + [% END %] + </select> + + <select name="[% "type${chartnum}-${rownum}-${colnum}" %]"> + [% FOREACH type = types %] + <option value="[% type.name %]" + [%- " selected" IF type.name == col.type %]>[% type.description %]</option> + [% END %] + </select> + + <input name="[% "value${chartnum}-${rownum}-${colnum}" %]" + value="[% col.value FILTER html %]"> + </td> + + [% IF NOT col == row.last %] + <td align="center"> + Or + </td> + [% ELSE %] + <td> + [% newor = colnum + 1 %] + <input type="submit" value="Or" + name="cmd-add[% "${chartnum}-${rownum}-${newor}" %]" [% $jsmagic %]> + </td> + [% END %] + + [% END %] + </tr> + + [% IF NOT row == chart.last %] + <tr> + <td>And</td> + </tr> + [% ELSE %] + <tr> + <td> + [% newand = rownum + 1; newchart = chartnum + 1 %] + <input type="submit" value="And" + name="cmd-add[% "${chartnum}-${newand}-0" %]"[% $jsmagic %]> + + <input type="submit" value="Add another boolean chart" + name="cmd-add[% newchart %]-0-0" [% $jsmagic %]> + + </td> + </tr> + [% END %] + + [% END %] + </table> + <hr> +[% END %] diff --git a/template/en/default/search/form.html.tmpl b/template/en/default/search/form.html.tmpl new file mode 100644 index 000000000..916039743 --- /dev/null +++ b/template/en/default/search/form.html.tmpl @@ -0,0 +1,670 @@ +<!-- 1.0@bugzilla.org --> +[%# The contents of this file are subject to the Mozilla Public + # License Version 1.1 (the "License"); you may not use this file + # except in compliance with the License. You may obtain a copy of + # the License at http://www.mozilla.org/MPL/ + # + # Software distributed under the License is distributed on an "AS + # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + # implied. See the License for the specific language governing + # rights and limitations under the License. + # + # The Original Code is the Bugzilla Bug Tracking System. + # + # The Initial Developer of the Original Code is Netscape Communications + # Corporation. Portions created by Netscape are + # Copyright (C) 1998 Netscape Communications Corporation. All + # Rights Reserved. + # + # Contributor(s): Chris Lahey <clahey@ximian.com> [javascript fixes] + # Christian Reis <kiko@async.com.br> [javascript rewrite] + # Gervase Markham <gerv@gerv.net> + #%] + + [%# Note: use Template comments and not JS ones here, to avoid bloating + what we actually send to the browser %] + +<script language="JavaScript" type="text/javascript"> <!-- + +var first_load = true; [%# is this the first time we load the page? %] +var last_sel = new Array(); [%# caches last selection %] + +var cpts = new Array(); +var vers = new Array(); +[% IF Param('usetargetmilestone') %] +var tms = new Array(); +[% END %] + +[%# Create three arrays of components, versions and target milestones, indexed + # numerically according to the product they refer to. #%] + +[% n = 0 %] +[% FOREACH p = product %] + cpts[[% n %]] = [ + [%- FOREACH item = componentsbyproduct.$p %]'[% item FILTER js %]', [%- END -%]]; + vers[[% n %]] = [ + [%- FOREACH item = versionsbyproduct.$p -%]'[% item FILTER js %]', [%- END -%]]; + [% IF Param('usetargetmilestone') %] + tms[[% n %]] = [ + [%- FOREACH item = milestonesbyproduct.$p %]'[% item FILTER js %]', [%- END -%]]; + [% END %] + [% n = n+1 %] +[% END %] + +[%# updateSelect(array, sel, target, merging) + # + # Adds to the target select object all elements in array that + # correspond to the elements selected in source. + # - array should be a array of arrays, indexed by number. the + # array should contain the elements that correspond to that + # product. + # - sel is a list of selected items, either whole or a diff + # depending on merging. + # - target should be the target select object. + # - merging (boolean) determines if we are mergine in a diff or + # substituting the whole selection. a diff is used to optimize adding + # selections. + # + # Example (compsel is a select form control) + # + # var components = Array(); + # components[1] = [ 'ComponentA', 'ComponentB' ]; + # components[2] = [ 'ComponentC', 'ComponentD' ]; + # source = [ 2 ]; + # updateSelect(components, source, compsel, 0, 0); + # + # would clear compsel and add 'ComponentC' and 'ComponentD' to it. + # + %] + +function updateSelect(array, sel, target, merging) { + + var i, item; + + [%# If we have no versions/components/milestones %] + if (array.length < 1) { + target.options.length = 0; + return false; + } + + if (merging) { + [%# array merging/sorting in the case of multiple selections %] + [%# merge in the current options with the first selection %] + item = merge_arrays(array[sel[0]], target.options, 1); + + [%# merge the rest of the selection with the results %] + for (i = 1 ; i < sel.length ; i++) { + item = merge_arrays(array[sel[i]], item, 0); + } + } else if ( sel.length > 1 ) { + [%# here we micro-optimize for two arrays to avoid merging with a + null array %] + item = merge_arrays(array[sel[0]],array[sel[1]], 0); + + [%# merge the arrays. not very good for multiple selections. %] + for (i = 2; i < sel.length; i++) { + item = merge_arrays(item, array[sel[i]], 0); + } + } else { [%# single item in selection, just get me the list %] + item = array[sel[0]]; + } + + [%# clear select %] + target.options.length = 0; + + [%# load elements of list into select %] + for (i = 0; i < item.length; i++) { + target.options[i] = new Option(item[i], item[i]); + } + return true; +} + +[%# Returns elements in a that are not in b. + # NOT A REAL DIFF: does not check the reverse. + # - a,b: arrays of values to be compare. %] +function fake_diff_array(a, b) { + var newsel = new Array(); + var found = false; + + [%# do a boring array diff to see who's new %] + for (var ia in a) { + for (var ib in b) { + if (a[ia] == b[ib]) { + found = true; + } + } + if (!found) { + newsel[newsel.length] = a[ia]; + } + found = false; + } + return newsel; +} + +[%# takes two arrays and sorts them by string, returning a new, sorted + # array. the merge removes dupes, too. + # - a, b: arrays to be merge. + # - b_is_select: if true, then b is actually an optionitem and as + # such we need to use item.value on it. %] +function merge_arrays(a, b, b_is_select) { + var pos_a = 0; + var pos_b = 0; + var ret = new Array(); + var bitem, aitem; + + [%# iterate through both arrays and add the larger item to the return + list. remove dupes, too. Use toLowerCase to provide + case-insensitivity. %] + while ((pos_a < a.length) && (pos_b < b.length)) { + if (b_is_select) { + bitem = b[pos_b].value; + } else { + bitem = b[pos_b]; + } + aitem = a[pos_a]; + + [%# smaller item in list a %] + if (aitem.toLowerCase() < bitem.toLowerCase()) { + ret[ret.length] = aitem; + pos_a++; + } else { + [%# smaller item in list b %] + if (aitem.toLowerCase() > bitem.toLowerCase()) { + ret[ret.length] = bitem; + pos_b++; + } else { + [%# list contents are equal, inc both counters. %] + ret[ret.length] = aitem; + pos_a++; + pos_b++; + } + } + } + + [%# catch leftovers here. these sections are ugly code-copying. %] + if (pos_a < a.length) { + for (; pos_a < a.length ; pos_a++) { + ret[ret.length] = a[pos_a]; + } + } + + if (pos_b < b.length) { + for (; pos_b < b.length; pos_b++) { + if (b_is_select) { + bitem = b[pos_b].value; + } else { + bitem = b[pos_b]; + } + ret[ret.length] = bitem; + } + } + return ret; +} + +[%# Returns an array of indexes or values from a select form control. + # - control: select control from which to find selections + # - findall: boolean, store all options when true or just the selected + # indexes + # - want_values: boolean; we store values when true and indexes when + # false %] +function getSelection(control, findall, want_values) { + var ret = new Array(); + + if ((!findall) && (control.selectedIndex == -1)) { + return ret; + } + + for (var i=0; i<control.length; i++) { + if (findall || control.options[i].selected) { + ret[ret.length] = want_values ? control.options[i].value : i; + } + } + return ret; +} + +[%# Selects items in control that have index defined in sel + # - control: SELECT control to be restored + # - selnames: array of indexes in select form control %] +function restoreSelection(control, selnames) { + [%# right. this sucks. but I see no way to avoid going through the + # list and comparing to the contents of the control. %] + for (var j=0; j < selnames.length; j++) { + for (var i=0; i < control.options.length; i++) { + if (control.options[i].value == selnames[j]) { + control.options[i].selected = true; + } + } + } +} + +[%# selectProduct reads the selection from f.product and updates + # f.version, component and target_milestone accordingly. + # - f: a form containing product, component, varsion and + # target_milestone select boxes. + # globals (3vil!): + # - cpts, vers, tms: array of arrays, indexed by product name. the + # subarrays contain a list of names to be fed to the respective + # selectboxes. For bugzilla, these are generated with perl code + # at page start. + # - first_load: boolean, specifying if it is the first time we load + # the query page. + # - last_sel: saves our last selection list so we know what has + # changed, and optimize for additions. %] +function selectProduct(f) { + [%# this is to avoid handling events that occur before the form + itself is ready, which could happen in buggy browsers. %] + if ((!f) || (!f.product)) { + return; + } + + [%# if this is the first load and nothing is selected, no need to + merge and sort all components; perl gives it to us sorted. %] + if ((first_load) && (f.product.selectedIndex == -1)) { + first_load = false; + return; + } + + [%# turn first_load off. this is tricky, since it seems to be + redundant with the above clause. It's not: if when we first load + the page there is _one_ element selected, it won't fall into that + clause, and first_load will remain 1. Then, if we unselect that + item, selectProduct will be called but the clause will be valid + (since selectedIndex == -1), and we will return - incorrectly - + without merge/sorting. %] + first_load = false; + + [%# - sel keeps the array of products we are selected. + - merging says if it is a full list or just a list of products that + were added to the current selection. %] + var merging = false; + var sel = Array(); + + [%# if nothing selected, pick all %] + var findall = f.product.selectedIndex == -1; + sel = getSelection(f.product, findall, false); + if (!findall) { + [%# save sel for the next invocation of selectProduct() %] + var tmp = sel; + + [%# this is an optimization: if we have just added products to an + existing selection, no need to clear the form controls and add + everybody again; just merge the new ones with the existing + options. %] + if ((last_sel.length > 0) && (last_sel.length < sel.length)) { + sel = fake_diff_array(sel, last_sel); + merging = true; + } + last_sel = tmp; + } + [%# save original options selected %] + var saved_cpts = getSelection(f.component, false, true); + var saved_vers = getSelection(f.version, false, true); + [% IF Param('usetargetmilestone') %] + var saved_tms = getSelection(f.target_milestone, false, true); + [% END %] + + [%# do the actual fill/update, reselect originally selected options %] + updateSelect(cpts, sel, f.component, merging); + restoreSelection(f.component, saved_cpts); + updateSelect(vers, sel, f.version, merging); + restoreSelection(f.version, saved_vers); + [% IF Param('usetargetmilestone') %] + updateSelect(tms, sel, f.target_milestone, merging); + restoreSelection(f.target_milestone, saved_tms); + [% END %] +} + +// --> +</script> + +[% query_variants = [ + { value => "allwordssubstr", description => "contains all of the words/strings" }, + { value => "anywordssubstr", description => "contains any of the words/strings" }, + { value => "substring", description => "contains the string" }, + { value => "casesubstring", description => "contains the string (exact case)" }, + { value => "allwords", description => "contains all of the words" }, + { value => "anywords", description => "contains any of the words" }, + { value => "regexp", description => "matches the regexp" }, + { value => "notregexp", description => "doesn’t match the regexp" } ] %] + +[%# *** Summary *** %] + +<table> + <tr> + <th align="right">Summary:</th> + <td> + <select name="short_desc_type"> + [% FOREACH qv = query_variants %] + <option value="[% qv.value %]" + [% " selected" IF default.short_desc_type.0 == qv.value %]>[% qv.description %]</option> + [% END %] + </select> + </td> + <td> + <input name="short_desc" size="40" value="[% default.short_desc.0 FILTER html %]"> + </td> + <td> + <input type="submit" value="[% button_name %]"> + </td> + </tr> + +[%# *** Product Component Version Target *** %] + + <tr> + <td colspan="4"> + <table> + <tr valign="bottom"> + <th align="left">Product:</th> + <th align="left"><a href="describecomponents.cgi">Component</a>:</th> + <th align="left">Version:</th> + + [% IF (Param("usetargetmilestone")) %] + <th align="left">Target:</th> + [% END %] + </tr> + + <tr valign="top"> + + [%# Can't use the select block here because of onChange and the fact that + 'component' is a toolkit reserved word - we use 'component_' instead. %] + <td align="left"> + <select name="product" multiple size="5" onChange="selectProduct(this.form);"> + [% FOREACH p = product %] + <option value="[% p FILTER html %]" + [% " selected" IF lsearch(default.product, p) != -1 %]> + [% p FILTER html %]</option> + [% END %] + </select> + </td> + + <td align="left"> + <select name="component" multiple size="5"> + [% FOREACH c = component_ %] + <option value="[% c FILTER html %]" + [% " selected" IF lsearch(default.component, c) != -1 %]> + [% c FILTER html %]</option> + [% END %] + </select> + </td> + + [% PROCESS select sel = { name => 'version', size => 5 } %] + + [% IF Param('usetargetmilestone') && target_milestone.size > 0 %] + [% PROCESS select sel = { name => 'target_milestone', size => 5 } %] + [% END %] + </tr> + </table> + </td> + </tr> + +[%# *** Comment URL Whiteboard Keywords *** %] + + [% FOREACH field = [ + { name => "long_desc", description => "A comment" }, + { name => "bug_file_loc", description => "The URL" }, + { name => "status_whiteboard", description => "Whiteboard" } ] %] + + [% UNLESS field.name == 'status_whiteboard' AND NOT Param('usestatuswhiteboard') %] + <tr> + <th align="right">[% field.description %]:</th> + <td> + <select name="[% field.name %]_type"> + [% FOREACH qv = query_variants %] + [% type = "${field.name}_type" %] + <option value="[% qv.value %]" + [% " selected" IF default.$type.0 == qv.value %]>[% qv.description %]</option> + [% END %] + </select> + </td> + <td><input name="[% field.name %]" size="40" value=" + [% default.${field.name}.0 FILTER html %]"> + </td> + <td></td> + </tr> + [% END %] + [% END %] + + [% IF have_keywords %] + <tr> + <th align="right"><a href="describekeywords.cgi">Keywords</a>:</th> + <td> + <select name="keywords_type"> + [% FOREACH qv = [ + { name => "anywords", description => "contains any of the keywords" }, + { name => "allwords", description => "contains all of the keywords" }, + { name => "nowords", description => "contains none of the keywords" } ] %] + + <option value="[% qv.name %]" + [% " selected" IF default.keywords_type.0 == qv.name %]> + [% qv.description %]</option> + [% END %] + </select> + </td> + <td> + <input name="keywords" size="40" value="[% default.keywords.0 FILTER html %]"> + </td> + </tr> + [% END %] +</table> + +<hr> + +[%# *** Status Resolution Severity Priority Hardware OS *** %] + +<table> + <tr> + <th align="left"><a href="queryhelp.cgi#status">Status</a>:</th> + <th align="left"><a href="queryhelp.cgi#resolution">Resolution</a>:</th> + <th align="left"><a href="queryhelp.cgi#severity">Severity</a>:</th> + <th align="left"><a href="queryhelp.cgi#priority">Priority</a>:</th> + <th align="left"><a href="queryhelp.cgi#platform">Hardware</a>:</th> + <th align="left"><a href="queryhelp.cgi#opsys">OS</a>:</th> + </tr> + + <tr valign="top"> + [% PROCESS select sel = { name => 'bug_status', size => 7 } %] + [% PROCESS select sel = { name => 'resolution', size => 7 } %] + [% PROCESS select sel = { name => 'bug_severity', size => 7 } %] + [% PROCESS select sel = { name => 'priority', size => 7 } %] + [% PROCESS select sel = { name => 'rep_platform', size => 7 } %] + [% PROCESS select sel = { name => 'op_sys', size => 7 } %] + </tr> +</table> + +<p> + +[%# *** Email Numbering Votes *** %] + +<table> + <tr> + <td> + <fieldset> + <legend> + <strong> + <a href="queryhelp.cgi#peopleinvolved">Email</a> and Numbering + </strong> + </legend> + + +<table> + <tr> + [% FOREACH n = [1, 2] %] + <td> + + +<table cellspacing="0" cellpadding="0"> + <tr> + <td> + Any of: + </td> + </tr> + <tr> + <td> + <input type="checkbox" name="emailassigned_to[% n %]" + id="emailassigned_to[% n %]" value="1" + [% " checked" IF default.emailassigned_to.$n %]> + <label for="emailassigned_to[% n %]"> + bug owner + </label> + </td> + </tr> + <tr> + <td> + <input type="checkbox" name="emailreporter[% n %]" + id="emailreporter[% n %]" value="1" + [% " checked" IF default.emailreporter.$n %]> + <label for="emailreporter[% n %]"> + reporter + </label> + </td> + </tr> + [% IF Param('useqacontact') %] + <tr> + <td> + <input type="checkbox" name="emailqa_contact[% n %]" + id="emailqa_contact[% n %]" value="1" + [% " checked" IF default.emailqa_contact.$n %]> + <label for="emailqa_contact[% n %]"> + QA contact + </label> + </td> + </tr> + [% END %] + <tr> + <td> + <input type="checkbox" name="emailcc[% n %]" + id="emailcc[% n %]" value="1" + [% " checked" IF default.emailcc.$n %]> + <label for="emailcc[% n %]"> + CC list member + </label> + </td> + </tr> + <tr> + <td> + <input type="checkbox" name="emaillongdesc[% n %]" + id="emaillongdesc[% n %]" value="1" + [% " checked" IF default.emaillongdesc.$n %]> + <label for="emaillongdesc[% n %]"> + commenter + </label> + </td> + </tr> + <tr> + <td> + <select name="emailtype[% n %]"> + [% FOREACH qv = [ + { name => "substring", description => "contains" }, + { name => "exact", description => "is" }, + { name => "regexp", description => "matches regexp" }, + { name => "notregexp", description => "doesn’t match regexp" } ] %] + + <option value="[% qv.name %]" + [% " selected" IF default.emailtype.$n == qv.name %]>[% qv.description %]</option> + [% END %] + </select> + </td> + </tr> + <tr> + <td> + <input name="email[% n %]" size="25" value="[% default.email.$n FILTER html %]"> + </td> + </tr> +</table> + + + </td> + [% END %] + </tr> +</table> +<hr> +<table> + <tr> + <td> + <select name="bugidtype"> + <option value="include"[% " selected" IF default.bugidtype.0 == "include" %]>Only include</option> + <option value="exclude"[% " selected" IF default.bugidtype.0 == "exclude" %]>Exclude</option> + </select> + bugs numbered: + </td> + <td> + <input type="text" name="bug_id" value="[% default.bug_id.0 FILTER html %]" size="20"> + </td> + </tr> + <tr> + <td></td> + <td>(comma-separated list)</td> + </tr> + <tr> + <td align="right"> + Only bugs with at least: + </td> + <td> + <input name="votes" size="3" value="[% default.votes.0 FILTER html %]"> votes + </td> + </tr> +</table> + + + </fieldset> + </td> + +[%# *** Bug Changes *** %] + + <td valign="top"> + <fieldset> + <legend><strong>Bug Changes</strong></legend> + + +<dl> + <dt>Only bugs changed in the last </dt> + <dd><input name=changedin size=3 value="[% default.changedin.0 FILTER html %]"> days</dd> +</dl> + +<dl> + <dt>Only bugs where any of the fields</dt> + <dd> + <select name="chfield" multiple size="4"> + [% FOREACH field = chfield %] + <option value="[% field FILTER html %]" + [% " selected" IF lsearch(default.chfield, field) != -1 %]> + [% field FILTER html %]</option> + [% END %] + </select> + </dd> + + <dt>were changed between</dt> + <dd> + <input name="chfieldfrom" size="10" value="[% default.chfieldfrom.0 FILTER html %]"> + and <input name="chfieldto" size="10" value="[% default.chfieldto.0 FILTER html %]"> + <br>(YYYY-MM-DD) + </dd> + <dt>to this value: (optional)</dt> + <dd> + <input name="chfieldvalue" size="20" value="[% default.chfieldvalue.0 FILTER html %]"> + </dd> +</dl> + + + </fieldset> + </td> + </tr> +</table> + +[%# Note: the <form> tag is unclosed at the end of this template %] + +[%############################################################################%] +[%# Block for SELECT fields #%] +[%############################################################################%] + +[% BLOCK select %] + <td align="left"> + <select name="[% sel.name %]" multiple size="[% sel.size %]"> + [% FOREACH name = ${sel.name} %] + <option value="[% name FILTER html %]" + [% " selected" IF lsearch(default.${sel.name}, name) != -1 %]> + [% name FILTER html %]</option> + [% END %] + </select> + </td> +[% END %] diff --git a/template/en/default/search/knob.html.tmpl b/template/en/default/search/knob.html.tmpl new file mode 100644 index 000000000..beda930b3 --- /dev/null +++ b/template/en/default/search/knob.html.tmpl @@ -0,0 +1,95 @@ +<!-- 1.0@bugzilla.org --> +[%# The contents of this file are subject to the Mozilla Public + # License Version 1.1 (the "License"); you may not use this file + # except in compliance with the License. You may obtain a copy of + # the License at http://www.mozilla.org/MPL/ + # + # Software distributed under the License is distributed on an "AS + # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + # implied. See the License for the specific language governing + # rights and limitations under the License. + # + # The Original Code is the Bugzilla Bug Tracking System. + # + # The Initial Developer of the Original Code is Netscape Communications + # Corporation. Portions created by Netscape are + # Copyright (C) 1998 Netscape Communications Corporation. All + # Rights Reserved. + # + # Contributor(s): Gervase Markham <gerv@gerv.net> + #%] + +<table> + <tr> + <td colspan="2"> + + [% IF NOT userid %] + <input type="hidden" name="cmdtype" value="doit"> + [% ELSE %] + <br> + <input type="radio" name="cmdtype" value="doit" checked> Run this query + <br> + + [% IF namedqueries.size > 0 %] + <p> + <table cellspacing="0" cellpadding="0"> + <tr> + <td> + <input type="radio" name="cmdtype" value="editnamed"> + Load my remembered query: + </td> + <td rowspan="3"> + <select name="namedcmd"> + [% FOREACH query = namedqueries %] + <option value="[% query FILTER html %]">[% query FILTER html %]</option> + [% END %] + </select> + </td> + </tr> + <tr> + <td> + <input type="radio" name="cmdtype" value="runnamed"> + Run my remembered query: + </td> + </tr> + <tr> + <td> + <input type="radio" name="cmdtype" value="forgetnamed"> + Forget my remembered query: + </td> + </tr> + </table> + </p> + [% END %] + + <input type="radio" name="cmdtype" value="asdefault"> + Remember this as my default query + <br> + <input type="radio" name="cmdtype" value="asnamed"> + Remember this query, and name it: + <input type="text" name="newqueryname"> + <br> <input type="checkbox" name="tofooter" value="1"> + and put it in my page footer + <br> + [% END %] + <br> + <div> + Sort results by: + <select name="order"> + [% FOREACH order = orders %] + <option value="[% order FILTER html %]" + [% " selected" IF default.order.0 == order %]>[% order FILTER html %]</option> + [% END %] + </select> + + <input type="submit" value="[% button_name %]"> + [% IF userdefaultquery %] + <p> + <a href="query.cgi?nukedefaultquery=1"> + Set my default query back to the system default</a> + </p> + [% END %] + </div> + </td> + </tr> +</table> diff --git a/template/en/default/search/search-advanced.html.tmpl b/template/en/default/search/search-advanced.html.tmpl index ec93e8592..b64470937 100644 --- a/template/en/default/search/search-advanced.html.tmpl +++ b/template/en/default/search/search-advanced.html.tmpl @@ -16,9 +16,7 @@ # Copyright (C) 1998 Netscape Communications Corporation. All # Rights Reserved. # - # Contributor(s): Chris Lahey <clahey@ximian.com> [javascript fixes] - # Christian Reis <kiko@async.com.br> [javascript rewrite] - # Gervase Markham <gerv@gerv.net> + # Contributor(s): Gervase Markham <gerv@gerv.net> #%] [% PROCESS global/header.html.tmpl @@ -26,833 +24,20 @@ extra = " onLoad=\"selectProduct(document.forms['queryform']);\"" %] -[%# Note: use Template comments and not JS ones here, to avoid bloating - what we actually send to the browser %] +[% button_name = "Search" %] -<script language="JavaScript" type="text/javascript"> <!-- +[% PROCESS search/form.html.tmpl %] -var first_load = true; [%# is this the first time we load the page? %] -var last_sel = new Array(); [%# caches last selection %] - -var cpts = new Array(); -var vers = new Array(); -[% IF Param('usetargetmilestone') %] -var tms = new Array(); -[% END %] - -[%# Create three arrays of components, versions and target milestones, indexed - # numerically according to the product they refer to. #%] - -[% n = 0 %] -[% FOREACH p = product %] - cpts[[% n %]] = [ - [%- FOREACH item = componentsbyproduct.$p %]'[% item FILTER js %]', [%- END -%]]; - vers[[% n %]] = [ - [%- FOREACH item = versionsbyproduct.$p -%]'[% item FILTER js %]', [%- END -%]]; - [% IF Param('usetargetmilestone') %] - tms[[% n %]] = [ - [%- FOREACH item = milestonesbyproduct.$p %]'[% item FILTER js %]', [%- END -%]]; - [% END %] - [% n = n+1 %] -[% END %] - -[%# updateSelect(array, sel, target, merging) - # - # Adds to the target select object all elements in array that - # correspond to the elements selected in source. - # - array should be a array of arrays, indexed by number. the - # array should contain the elements that correspond to that - # product. - # - sel is a list of selected items, either whole or a diff - # depending on merging. - # - target should be the target select object. - # - merging (boolean) determines if we are mergine in a diff or - # substituting the whole selection. a diff is used to optimize adding - # selections. - # - # Example (compsel is a select form control) - # - # var components = Array(); - # components[1] = [ 'ComponentA', 'ComponentB' ]; - # components[2] = [ 'ComponentC', 'ComponentD' ]; - # source = [ 2 ]; - # updateSelect(components, source, compsel, 0, 0); - # - # would clear compsel and add 'ComponentC' and 'ComponentD' to it. - # - %] - -function updateSelect(array, sel, target, merging) { - - var i, item; - - [%# If we have no versions/components/milestones %] - if (array.length < 1) { - target.options.length = 0; - return false; - } - - if (merging) { - [%# array merging/sorting in the case of multiple selections %] - [%# merge in the current options with the first selection %] - item = merge_arrays(array[sel[0]], target.options, 1); - - [%# merge the rest of the selection with the results %] - for (i = 1 ; i < sel.length ; i++) { - item = merge_arrays(array[sel[i]], item, 0); - } - } else if ( sel.length > 1 ) { - [%# here we micro-optimize for two arrays to avoid merging with a - null array %] - item = merge_arrays(array[sel[0]],array[sel[1]], 0); - - [%# merge the arrays. not very good for multiple selections. %] - for (i = 2; i < sel.length; i++) { - item = merge_arrays(item, array[sel[i]], 0); - } - } else { [%# single item in selection, just get me the list %] - item = array[sel[0]]; - } - - [%# clear select %] - target.options.length = 0; - - [%# load elements of list into select %] - for (i = 0; i < item.length; i++) { - target.options[i] = new Option(item[i], item[i]); - } - return true; -} - -[%# Returns elements in a that are not in b. - # NOT A REAL DIFF: does not check the reverse. - # - a,b: arrays of values to be compare. %] -function fake_diff_array(a, b) { - var newsel = new Array(); - var found = false; - - [%# do a boring array diff to see who's new %] - for (var ia in a) { - for (var ib in b) { - if (a[ia] == b[ib]) { - found = true; - } - } - if (!found) { - newsel[newsel.length] = a[ia]; - } - found = false; - } - return newsel; -} - -[%# takes two arrays and sorts them by string, returning a new, sorted - # array. the merge removes dupes, too. - # - a, b: arrays to be merge. - # - b_is_select: if true, then b is actually an optionitem and as - # such we need to use item.value on it. %] -function merge_arrays(a, b, b_is_select) { - var pos_a = 0; - var pos_b = 0; - var ret = new Array(); - var bitem, aitem; - - [%# iterate through both arrays and add the larger item to the return - list. remove dupes, too. Use toLowerCase to provide - case-insensitivity. %] - while ((pos_a < a.length) && (pos_b < b.length)) { - if (b_is_select) { - bitem = b[pos_b].value; - } else { - bitem = b[pos_b]; - } - aitem = a[pos_a]; - - [%# smaller item in list a %] - if (aitem.toLowerCase() < bitem.toLowerCase()) { - ret[ret.length] = aitem; - pos_a++; - } else { - [%# smaller item in list b %] - if (aitem.toLowerCase() > bitem.toLowerCase()) { - ret[ret.length] = bitem; - pos_b++; - } else { - [%# list contents are equal, inc both counters. %] - ret[ret.length] = aitem; - pos_a++; - pos_b++; - } - } - } - - [%# catch leftovers here. these sections are ugly code-copying. %] - if (pos_a < a.length) { - for (; pos_a < a.length ; pos_a++) { - ret[ret.length] = a[pos_a]; - } - } - - if (pos_b < b.length) { - for (; pos_b < b.length; pos_b++) { - if (b_is_select) { - bitem = b[pos_b].value; - } else { - bitem = b[pos_b]; - } - ret[ret.length] = bitem; - } - } - return ret; -} - -[%# Returns an array of indexes or values from a select form control. - # - control: select control from which to find selections - # - findall: boolean, store all options when true or just the selected - # indexes - # - want_values: boolean; we store values when true and indexes when - # false %] -function getSelection(control, findall, want_values) { - var ret = new Array(); - - if ((!findall) && (control.selectedIndex == -1)) { - return ret; - } - - for (var i=0; i<control.length; i++) { - if (findall || control.options[i].selected) { - ret[ret.length] = want_values ? control.options[i].value : i; - } - } - return ret; -} - -[%# Selects items in control that have index defined in sel - # - control: SELECT control to be restored - # - selnames: array of indexes in select form control %] -function restoreSelection(control, selnames) { - [%# right. this sucks. but I see no way to avoid going through the - # list and comparing to the contents of the control. %] - for (var j=0; j < selnames.length; j++) { - for (var i=0; i < control.options.length; i++) { - if (control.options[i].value == selnames[j]) { - control.options[i].selected = true; - } - } - } -} - -[%# selectProduct reads the selection from f.product and updates - # f.version, component and target_milestone accordingly. - # - f: a form containing product, component, varsion and - # target_milestone select boxes. - # globals (3vil!): - # - cpts, vers, tms: array of arrays, indexed by product name. the - # subarrays contain a list of names to be fed to the respective - # selectboxes. For bugzilla, these are generated with perl code - # at page start. - # - first_load: boolean, specifying if it is the first time we load - # the query page. - # - last_sel: saves our last selection list so we know what has - # changed, and optimize for additions. %] -function selectProduct(f) { - [%# this is to avoid handling events that occur before the form - itself is ready, which could happen in buggy browsers. %] - if ((!f) || (!f.product)) { - return; - } - - [%# if this is the first load and nothing is selected, no need to - merge and sort all components; perl gives it to us sorted. %] - if ((first_load) && (f.product.selectedIndex == -1)) { - first_load = false; - return; - } - - [%# turn first_load off. this is tricky, since it seems to be - redundant with the above clause. It's not: if when we first load - the page there is _one_ element selected, it won't fall into that - clause, and first_load will remain 1. Then, if we unselect that - item, selectProduct will be called but the clause will be valid - (since selectedIndex == -1), and we will return - incorrectly - - without merge/sorting. %] - first_load = false; - - [%# - sel keeps the array of products we are selected. - - merging says if it is a full list or just a list of products that - were added to the current selection. %] - var merging = false; - var sel = Array(); - - [%# if nothing selected, pick all %] - var findall = f.product.selectedIndex == -1; - sel = getSelection(f.product, findall, false); - if (!findall) { - [%# save sel for the next invocation of selectProduct() %] - var tmp = sel; - - [%# this is an optimization: if we have just added products to an - existing selection, no need to clear the form controls and add - everybody again; just merge the new ones with the existing - options. %] - if ((last_sel.length > 0) && (last_sel.length < sel.length)) { - sel = fake_diff_array(sel, last_sel); - merging = true; - } - last_sel = tmp; - } - [%# save original options selected %] - var saved_cpts = getSelection(f.component, false, true); - var saved_vers = getSelection(f.version, false, true); - [% IF Param('usetargetmilestone') %] - var saved_tms = getSelection(f.target_milestone, false, true); - [% END %] - - [%# do the actual fill/update, reselect originally selected options %] - updateSelect(cpts, sel, f.component, merging); - restoreSelection(f.component, saved_cpts); - updateSelect(vers, sel, f.version, merging); - restoreSelection(f.version, saved_vers); - [% IF Param('usetargetmilestone') %] - updateSelect(tms, sel, f.target_milestone, merging); - restoreSelection(f.target_milestone, saved_tms); - [% END %] -} - -// --> -</script> - -[% query_variants = [ - { value => "allwordssubstr", description => "contains all of the words/strings" }, - { value => "anywordssubstr", description => "contains any of the words/strings" }, - { value => "substring", description => "contains the string" }, - { value => "casesubstring", description => "contains the string (exact case)" }, - { value => "allwords", description => "contains all of the words" }, - { value => "anywords", description => "contains any of the words" }, - { value => "regexp", description => "matches the regexp" }, - { value => "notregexp", description => "doesn’t match the regexp" } ] %] - -<form method="get" action="buglist.cgi" name="queryform"> - -[%# *** Summary *** %] - -<table> - <tr> - <th align="right">Summary:</th> - <td> - <select name="short_desc_type"> - [% FOREACH qv = query_variants %] - <option value="[% qv.value %]" - [% " selected" IF default.short_desc_type.0 == qv.value %]>[% qv.description %]</option> - [% END %] - </select> - </td> - <td> - <input name="short_desc" size="40" value="[% default.short_desc.0 FILTER html %]"> - </td> - <td> - <input type="submit" value="Search"> - </td> - </tr> - -[%# *** Product Component Version Target *** %] - - <tr> - <td colspan="4"> - <table> - <tr valign="bottom"> - <th align="left">Product:</th> - <th align="left"><a href="describecomponents.cgi">Component</a>:</th> - <th align="left">Version:</th> - - [% IF (Param("usetargetmilestone")) %] - <th align="left">Target:</th> - [% END %] - </tr> - - <tr valign="top"> - - [%# Can't use the select block here because of onChange and the fact that - 'component' is a toolkit reserved word - we use 'component_' instead. %] - <td align="left"> - <select name="product" multiple size="5" onChange="selectProduct(this.form);"> - [% FOREACH p = product %] - <option value="[% p FILTER html %]" - [% " selected" IF lsearch(default.product, p) != -1 %]> - [% p FILTER html %]</option> - [% END %] - </select> - </td> - - <td align="left"> - <select name="component" multiple size="5"> - [% FOREACH c = component_ %] - <option value="[% c FILTER html %]" - [% " selected" IF lsearch(default.component, c) != -1 %]> - [% c FILTER html %]</option> - [% END %] - </select> - </td> - - [% PROCESS select sel = { name => 'version', size => 5 } %] - - [% IF Param('usetargetmilestone') && target_milestone.size > 0 %] - [% PROCESS select sel = { name => 'target_milestone', size => 5 } %] - [% END %] - </tr> - </table> - </td> - </tr> - -[%# *** Comment URL Whiteboard Keywords *** %] - - [% FOREACH field = [ - { name => "long_desc", description => "A comment" }, - { name => "bug_file_loc", description => "The URL" }, - { name => "status_whiteboard", description => "Whiteboard" } ] %] - - [% UNLESS field.name == 'status_whiteboard' AND NOT Param('usestatuswhiteboard') %] - <tr> - <th align="right">[% field.description %]:</th> - <td> - <select name="[% field.name %]_type"> - [% FOREACH qv = query_variants %] - [% type = "${field.name}_type" %] - <option value="[% qv.value %]" - [% " selected" IF default.$type.0 == qv.value %]>[% qv.description %]</option> - [% END %] - </select> - </td> - <td><input name="[% field.name %]" size="40" value=" - [% default.${field.name}.0 FILTER html %]"> - </td> - <td></td> - </tr> - [% END %] - [% END %] - - [% IF have_keywords %] - <tr> - <th align="right"><a href="describekeywords.cgi">Keywords</a>:</th> - <td> - <select name="keywords_type"> - [% FOREACH qv = [ - { name => "anywords", description => "contains any of the keywords" }, - { name => "allwords", description => "contains all of the keywords" }, - { name => "nowords", description => "contains none of the keywords" } ] %] - - <option value="[% qv.name %]" - [% " selected" IF default.keywords_type.0 == qv.name %]> - [% qv.description %]</option> - [% END %] - </select> - </td> - <td> - <input name="keywords" size="40" value="[% default.keywords.0 FILTER html %]"> - </td> - </tr> - [% END %] -</table> +[% PROCESS search/knob.html.tmpl %] <hr> -[%# *** Status Resolution Severity Priority Hardware OS *** %] - -<table> - <tr> - <th align="left"><a href="queryhelp.cgi#status">Status</a>:</th> - <th align="left"><a href="queryhelp.cgi#resolution">Resolution</a>:</th> - <th align="left"><a href="queryhelp.cgi#severity">Severity</a>:</th> - <th align="left"><a href="queryhelp.cgi#priority">Priority</a>:</th> - <th align="left"><a href="queryhelp.cgi#platform">Hardware</a>:</th> - <th align="left"><a href="queryhelp.cgi#opsys">OS</a>:</th> - </tr> - - <tr valign="top"> - [% PROCESS select sel = { name => 'bug_status', size => 7 } %] - [% PROCESS select sel = { name => 'resolution', size => 7 } %] - [% PROCESS select sel = { name => 'bug_severity', size => 7 } %] - [% PROCESS select sel = { name => 'priority', size => 7 } %] - [% PROCESS select sel = { name => 'rep_platform', size => 7 } %] - [% PROCESS select sel = { name => 'op_sys', size => 7 } %] - </tr> -</table> +[% PROCESS "search/boolean-charts.html.tmpl" %] <p> + Give me a <a href="queryhelp.cgi">clue</a> about how to use this form. +</p> -[%# *** Email Numbering Votes *** %] - -<table> - <tr> - <td> - <fieldset> - <legend> - <strong> - <a href="queryhelp.cgi#peopleinvolved">Email</a> and Numbering - </strong> - </legend> - - -<table> - <tr> - [% FOREACH n = [1, 2] %] - <td> - - -<table cellspacing="0" cellpadding="0"> - <tr> - <td> - Any of: - </td> - </tr> - <tr> - <td> - <input type="checkbox" name="emailassigned_to[% n %]" - id="emailassigned_to[% n %]" value="1" - [% " checked" IF default.emailassigned_to.$n %]> - <label for="emailassigned_to[% n %]"> - bug owner - </label> - </td> - </tr> - <tr> - <td> - <input type="checkbox" name="emailreporter[% n %]" - id="emailreporter[% n %]" value="1" - [% " checked" IF default.emailreporter.$n %]> - <label for="emailreporter[% n %]"> - reporter - </label> - </td> - </tr> - [% IF Param('useqacontact') %] - <tr> - <td> - <input type="checkbox" name="emailqa_contact[% n %]" - id="emailqa_contact[% n %]" value="1" - [% " checked" IF default.emailqa_contact.$n %]> - <label for="emailqa_contact[% n %]"> - QA contact - </label> - </td> - </tr> - [% END %] - <tr> - <td> - <input type="checkbox" name="emailcc[% n %]" - id="emailcc[% n %]" value="1" - [% " checked" IF default.emailcc.$n %]> - <label for="emailcc[% n %]"> - CC list member - </label> - </td> - </tr> - <tr> - <td> - <input type="checkbox" name="emaillongdesc[% n %]" - id="emaillongdesc[% n %]" value="1" - [% " checked" IF default.emaillongdesc.$n %]> - <label for="emaillongdesc[% n %]"> - commenter - </label> - </td> - </tr> - <tr> - <td> - <select name="emailtype[% n %]"> - [% FOREACH qv = [ - { name => "substring", description => "contains" }, - { name => "exact", description => "is" }, - { name => "regexp", description => "matches regexp" }, - { name => "notregexp", description => "doesn’t match regexp" } ] %] - - <option value="[% qv.name %]" - [% " selected" IF default.emailtype.$n == qv.name %]>[% qv.description %]</option> - [% END %] - </select> - </td> - </tr> - <tr> - <td> - <input name="email[% n %]" size="20" value="[% default.email.$n FILTER html %]"> - </td> - </tr> -</table> - - - </td> - [% END %] - </tr> -</table> -<hr> -<table> - <tr> - <td> - <select name="bugidtype"> - <option value="include"[% " selected" IF default.bugidtype.0 == "include" %]>Only include</option> - <option value="exclude"[% " selected" IF default.bugidtype.0 == "exclude" %]>Exclude</option> - </select> - bugs numbered: - </td> - <td> - <input type="text" name="bug_id" value="[% default.bug_id.0 FILTER html %]" size="20"> - </td> - </tr> - <tr> - <td></td> - <td>(comma-separated list)</td> - </tr> - <tr> - <td align="right"> - Only bugs with at least: - </td> - <td> - <input name="votes" size="3" value="[% default.votes.0 FILTER html %]"> votes - </td> - </tr> -</table> - - - </fieldset> - </td> - -[%# *** Bug Changes *** %] - - <td valign="top"> - <fieldset> - <legend><strong>Bug Changes</strong></legend> - - -<dl> - <dt>Only bugs changed in the last </dt> - <dd><input name=changedin size=3 value="[% default.changedin.0 FILTER html %]"> days</dd> -</dl> - -<dl> - <dt>Only bugs where any of the fields</dt> - <dd> - <select name="chfield" multiple size="4"> - [% FOREACH field = chfield %] - <option value="[% field FILTER html %]" - [% " selected" IF lsearch(default.chfield, field) != -1 %]> - [% field FILTER html %]</option> - [% END %] - </select> - </dd> - - <dt>were changed between</dt> - <dd> - <input name="chfieldfrom" size="10" value="[% default.chfieldfrom.0 FILTER html %]"> - and <input name="chfieldto" size="10" value="[% default.chfieldto.0 FILTER html %]"> - <br>(YYYY-MM-DD) - </dd> - <dt>to this value: (optional)</dt> - <dd> - <input name="chfieldvalue" size="20" value="[% default.chfieldvalue.0 FILTER html %]"> - </dd> -</dl> - - - </fieldset> - </td> - </tr> - -[%# *** Action Selection *** %] - - <tr> - <td colspan="2"> - - [% IF NOT userid %] - <input type="hidden" name="cmdtype" value="doit"> - [% ELSE %] - <br> - <input type="radio" name="cmdtype" value="doit" checked> Run this query - <br> - - [% IF namedqueries.size > 0 %] - <p> - <table cellspacing="0" cellpadding="0"> - <tr> - <td> - <input type="radio" name="cmdtype" value="editnamed"> - Load my remembered query: - </td> - <td rowspan="3"> - <select name="namedcmd"> - [% FOREACH query = namedqueries %] - <option value="[% query FILTER html %]">[% query FILTER html %]</option> - [% END %] - </select> - </td> - </tr> - <tr> - <td> - <input type="radio" name="cmdtype" value="runnamed"> - Run my remembered query: - </td> - </tr> - <tr> - <td> - <input type="radio" name="cmdtype" value="forgetnamed"> - Forget my remembered query: - </td> - </tr> - </table> - </p> - [% END %] - - <input type="radio" name="cmdtype" value="asdefault"> - Remember this as my default query - <br> - <input type="radio" name="cmdtype" value="asnamed"> - Remember this query, and name it: - <input type="text" name="newqueryname"> - <br> <input type="checkbox" name="tofooter" value="1"> - and put it in my page footer - <br> - [% END %] - <br> - <div> - Sort results by: - <select name="order"> - [% FOREACH order = orders %] - <option value="[% order FILTER html %]" - [% " selected" IF default.order.0 == order %]>[% order FILTER html %]</option> - [% END %] - </select> - - <input type="submit" value="Search"> - [% IF userdefaultquery %] - <p> - <a href="query.cgi?nukedefaultquery=1"> - Set my default query back to the system default</a> - </p> - [% END %] - </div> - </td> - </tr> -</table> - -[%# *** Boolean Charts *** %] - -<hr> - -[% types = [ - { name => "noop", description => "---" }, - { name => "equals", description => "is equal to" }, - { name => "notequals", description => "is not equal to" }, - { name => "substring", description => "contains the string" }, - { name => "casesubstring", description => "contains the string (exact case)" }, - { name => "notsubstring", description => "does not contain the string" }, - { name => "allwordssubstr", description => "contains all of the strings" }, - { name => "anywordssubstr", description => "contains any of the strings" }, - { name => "regexp", description => "contains regexp" }, - { name => "notregexp", description => "does not contain regexp" }, - { name => "lessthan", description => "is less than" }, - { name => "greaterthan", description => "is greater than" }, - { name => "anywords", description => "contains any of the words" }, - { name => "allwords", description => "contains all of the words" }, - { name => "nowords", description => "contains none of the words" }, - { name => "changedbefore", description => "changed before" }, - { name => "changedafter", description => "changed after" }, - { name => "changedfrom", description => "changed from" }, - { name => "changedto", description => "changed to" }, - { name => "changedby", description => "changed by" } ] %] - - <p> - <strong> - <a name="chart" href="queryhelp.cgi#advancedquerying"> - Advanced Querying Using Boolean Charts</a>: - </strong> - </p> - -[%# Whoever wrote the original version of boolean charts had a seriously twisted mind %] - -[% jsmagic = "onclick=\"document.forms[0].action='query.cgi#chart'; document.forms[0].method='POST'; return 1;\"" %] - -[% FOREACH chart = default.charts %] - [% chartnum = loop.count - 1 %] - <table> - [% FOREACH row = chart %] - [% rownum = loop.count - 1 %] - <tr> - [% FOREACH col = row %] - [% colnum = loop.count - 1 %] - <td> - <select name="[% "field${chartnum}-${rownum}-${colnum}" %]"> - [% FOREACH field = fields %] - <option value="[% field.name %]" - [%- " selected" IF field.name == col.field %]>[% field.description %]</option> - [% END %] - </select> - - <select name="[% "type${chartnum}-${rownum}-${colnum}" %]"> - [% FOREACH type = types %] - <option value="[% type.name %]" - [%- " selected" IF type.name == col.type %]>[% type.description %]</option> - [% END %] - </select> - - <input name="[% "value${chartnum}-${rownum}-${colnum}" %]" - value="[% col.value FILTER html %]"> - </td> - - [% IF NOT col == row.last %] - <td align="center"> - Or - </td> - [% ELSE %] - <td> - [% newor = colnum + 1 %] - <input type="submit" value="Or" - name="cmd-add[% "${chartnum}-${rownum}-${newor}" %]" [% $jsmagic %]> - </td> - [% END %] - - [% END %] - </tr> - - [% IF NOT row == chart.last %] - <tr> - <td>And</td> - </tr> - [% ELSE %] - <tr> - <td> - [% newand = rownum + 1; newchart = chartnum + 1 %] - <input type="submit" value="And" - name="cmd-add[% "${chartnum}-${newand}-0" %]"[% $jsmagic %]> - - <input type="submit" value="Add another boolean chart" - name="cmd-add[% newchart %]-0-0" [% $jsmagic %]> - - </td> - </tr> - [% END %] - - [% END %] - </table> - <hr> -[% END %] - -<p>Give me a <a href="queryhelp.cgi">clue</a> about how to use this form.</p> - -</FORM> +</form> [% PROCESS global/footer.html.tmpl %] - -[%############################################################################%] -[%# Block for SELECT fields #%] -[%############################################################################%] - -[% BLOCK select %] - <td align="left"> - <select name="[% sel.name %]" multiple size="[% sel.size %]"> - [% FOREACH name = ${sel.name} %] - <option value="[% name FILTER html %]" - [% " selected" IF lsearch(default.${sel.name}, name) != -1 %]> - [% name FILTER html %]</option> - [% END %] - </select> - </td> -[% END %] diff --git a/template/en/default/search/search.html.tmpl b/template/en/default/search/search.html.tmpl index ec93e8592..b64470937 100644 --- a/template/en/default/search/search.html.tmpl +++ b/template/en/default/search/search.html.tmpl @@ -16,9 +16,7 @@ # Copyright (C) 1998 Netscape Communications Corporation. All # Rights Reserved. # - # Contributor(s): Chris Lahey <clahey@ximian.com> [javascript fixes] - # Christian Reis <kiko@async.com.br> [javascript rewrite] - # Gervase Markham <gerv@gerv.net> + # Contributor(s): Gervase Markham <gerv@gerv.net> #%] [% PROCESS global/header.html.tmpl @@ -26,833 +24,20 @@ extra = " onLoad=\"selectProduct(document.forms['queryform']);\"" %] -[%# Note: use Template comments and not JS ones here, to avoid bloating - what we actually send to the browser %] +[% button_name = "Search" %] -<script language="JavaScript" type="text/javascript"> <!-- +[% PROCESS search/form.html.tmpl %] -var first_load = true; [%# is this the first time we load the page? %] -var last_sel = new Array(); [%# caches last selection %] - -var cpts = new Array(); -var vers = new Array(); -[% IF Param('usetargetmilestone') %] -var tms = new Array(); -[% END %] - -[%# Create three arrays of components, versions and target milestones, indexed - # numerically according to the product they refer to. #%] - -[% n = 0 %] -[% FOREACH p = product %] - cpts[[% n %]] = [ - [%- FOREACH item = componentsbyproduct.$p %]'[% item FILTER js %]', [%- END -%]]; - vers[[% n %]] = [ - [%- FOREACH item = versionsbyproduct.$p -%]'[% item FILTER js %]', [%- END -%]]; - [% IF Param('usetargetmilestone') %] - tms[[% n %]] = [ - [%- FOREACH item = milestonesbyproduct.$p %]'[% item FILTER js %]', [%- END -%]]; - [% END %] - [% n = n+1 %] -[% END %] - -[%# updateSelect(array, sel, target, merging) - # - # Adds to the target select object all elements in array that - # correspond to the elements selected in source. - # - array should be a array of arrays, indexed by number. the - # array should contain the elements that correspond to that - # product. - # - sel is a list of selected items, either whole or a diff - # depending on merging. - # - target should be the target select object. - # - merging (boolean) determines if we are mergine in a diff or - # substituting the whole selection. a diff is used to optimize adding - # selections. - # - # Example (compsel is a select form control) - # - # var components = Array(); - # components[1] = [ 'ComponentA', 'ComponentB' ]; - # components[2] = [ 'ComponentC', 'ComponentD' ]; - # source = [ 2 ]; - # updateSelect(components, source, compsel, 0, 0); - # - # would clear compsel and add 'ComponentC' and 'ComponentD' to it. - # - %] - -function updateSelect(array, sel, target, merging) { - - var i, item; - - [%# If we have no versions/components/milestones %] - if (array.length < 1) { - target.options.length = 0; - return false; - } - - if (merging) { - [%# array merging/sorting in the case of multiple selections %] - [%# merge in the current options with the first selection %] - item = merge_arrays(array[sel[0]], target.options, 1); - - [%# merge the rest of the selection with the results %] - for (i = 1 ; i < sel.length ; i++) { - item = merge_arrays(array[sel[i]], item, 0); - } - } else if ( sel.length > 1 ) { - [%# here we micro-optimize for two arrays to avoid merging with a - null array %] - item = merge_arrays(array[sel[0]],array[sel[1]], 0); - - [%# merge the arrays. not very good for multiple selections. %] - for (i = 2; i < sel.length; i++) { - item = merge_arrays(item, array[sel[i]], 0); - } - } else { [%# single item in selection, just get me the list %] - item = array[sel[0]]; - } - - [%# clear select %] - target.options.length = 0; - - [%# load elements of list into select %] - for (i = 0; i < item.length; i++) { - target.options[i] = new Option(item[i], item[i]); - } - return true; -} - -[%# Returns elements in a that are not in b. - # NOT A REAL DIFF: does not check the reverse. - # - a,b: arrays of values to be compare. %] -function fake_diff_array(a, b) { - var newsel = new Array(); - var found = false; - - [%# do a boring array diff to see who's new %] - for (var ia in a) { - for (var ib in b) { - if (a[ia] == b[ib]) { - found = true; - } - } - if (!found) { - newsel[newsel.length] = a[ia]; - } - found = false; - } - return newsel; -} - -[%# takes two arrays and sorts them by string, returning a new, sorted - # array. the merge removes dupes, too. - # - a, b: arrays to be merge. - # - b_is_select: if true, then b is actually an optionitem and as - # such we need to use item.value on it. %] -function merge_arrays(a, b, b_is_select) { - var pos_a = 0; - var pos_b = 0; - var ret = new Array(); - var bitem, aitem; - - [%# iterate through both arrays and add the larger item to the return - list. remove dupes, too. Use toLowerCase to provide - case-insensitivity. %] - while ((pos_a < a.length) && (pos_b < b.length)) { - if (b_is_select) { - bitem = b[pos_b].value; - } else { - bitem = b[pos_b]; - } - aitem = a[pos_a]; - - [%# smaller item in list a %] - if (aitem.toLowerCase() < bitem.toLowerCase()) { - ret[ret.length] = aitem; - pos_a++; - } else { - [%# smaller item in list b %] - if (aitem.toLowerCase() > bitem.toLowerCase()) { - ret[ret.length] = bitem; - pos_b++; - } else { - [%# list contents are equal, inc both counters. %] - ret[ret.length] = aitem; - pos_a++; - pos_b++; - } - } - } - - [%# catch leftovers here. these sections are ugly code-copying. %] - if (pos_a < a.length) { - for (; pos_a < a.length ; pos_a++) { - ret[ret.length] = a[pos_a]; - } - } - - if (pos_b < b.length) { - for (; pos_b < b.length; pos_b++) { - if (b_is_select) { - bitem = b[pos_b].value; - } else { - bitem = b[pos_b]; - } - ret[ret.length] = bitem; - } - } - return ret; -} - -[%# Returns an array of indexes or values from a select form control. - # - control: select control from which to find selections - # - findall: boolean, store all options when true or just the selected - # indexes - # - want_values: boolean; we store values when true and indexes when - # false %] -function getSelection(control, findall, want_values) { - var ret = new Array(); - - if ((!findall) && (control.selectedIndex == -1)) { - return ret; - } - - for (var i=0; i<control.length; i++) { - if (findall || control.options[i].selected) { - ret[ret.length] = want_values ? control.options[i].value : i; - } - } - return ret; -} - -[%# Selects items in control that have index defined in sel - # - control: SELECT control to be restored - # - selnames: array of indexes in select form control %] -function restoreSelection(control, selnames) { - [%# right. this sucks. but I see no way to avoid going through the - # list and comparing to the contents of the control. %] - for (var j=0; j < selnames.length; j++) { - for (var i=0; i < control.options.length; i++) { - if (control.options[i].value == selnames[j]) { - control.options[i].selected = true; - } - } - } -} - -[%# selectProduct reads the selection from f.product and updates - # f.version, component and target_milestone accordingly. - # - f: a form containing product, component, varsion and - # target_milestone select boxes. - # globals (3vil!): - # - cpts, vers, tms: array of arrays, indexed by product name. the - # subarrays contain a list of names to be fed to the respective - # selectboxes. For bugzilla, these are generated with perl code - # at page start. - # - first_load: boolean, specifying if it is the first time we load - # the query page. - # - last_sel: saves our last selection list so we know what has - # changed, and optimize for additions. %] -function selectProduct(f) { - [%# this is to avoid handling events that occur before the form - itself is ready, which could happen in buggy browsers. %] - if ((!f) || (!f.product)) { - return; - } - - [%# if this is the first load and nothing is selected, no need to - merge and sort all components; perl gives it to us sorted. %] - if ((first_load) && (f.product.selectedIndex == -1)) { - first_load = false; - return; - } - - [%# turn first_load off. this is tricky, since it seems to be - redundant with the above clause. It's not: if when we first load - the page there is _one_ element selected, it won't fall into that - clause, and first_load will remain 1. Then, if we unselect that - item, selectProduct will be called but the clause will be valid - (since selectedIndex == -1), and we will return - incorrectly - - without merge/sorting. %] - first_load = false; - - [%# - sel keeps the array of products we are selected. - - merging says if it is a full list or just a list of products that - were added to the current selection. %] - var merging = false; - var sel = Array(); - - [%# if nothing selected, pick all %] - var findall = f.product.selectedIndex == -1; - sel = getSelection(f.product, findall, false); - if (!findall) { - [%# save sel for the next invocation of selectProduct() %] - var tmp = sel; - - [%# this is an optimization: if we have just added products to an - existing selection, no need to clear the form controls and add - everybody again; just merge the new ones with the existing - options. %] - if ((last_sel.length > 0) && (last_sel.length < sel.length)) { - sel = fake_diff_array(sel, last_sel); - merging = true; - } - last_sel = tmp; - } - [%# save original options selected %] - var saved_cpts = getSelection(f.component, false, true); - var saved_vers = getSelection(f.version, false, true); - [% IF Param('usetargetmilestone') %] - var saved_tms = getSelection(f.target_milestone, false, true); - [% END %] - - [%# do the actual fill/update, reselect originally selected options %] - updateSelect(cpts, sel, f.component, merging); - restoreSelection(f.component, saved_cpts); - updateSelect(vers, sel, f.version, merging); - restoreSelection(f.version, saved_vers); - [% IF Param('usetargetmilestone') %] - updateSelect(tms, sel, f.target_milestone, merging); - restoreSelection(f.target_milestone, saved_tms); - [% END %] -} - -// --> -</script> - -[% query_variants = [ - { value => "allwordssubstr", description => "contains all of the words/strings" }, - { value => "anywordssubstr", description => "contains any of the words/strings" }, - { value => "substring", description => "contains the string" }, - { value => "casesubstring", description => "contains the string (exact case)" }, - { value => "allwords", description => "contains all of the words" }, - { value => "anywords", description => "contains any of the words" }, - { value => "regexp", description => "matches the regexp" }, - { value => "notregexp", description => "doesn’t match the regexp" } ] %] - -<form method="get" action="buglist.cgi" name="queryform"> - -[%# *** Summary *** %] - -<table> - <tr> - <th align="right">Summary:</th> - <td> - <select name="short_desc_type"> - [% FOREACH qv = query_variants %] - <option value="[% qv.value %]" - [% " selected" IF default.short_desc_type.0 == qv.value %]>[% qv.description %]</option> - [% END %] - </select> - </td> - <td> - <input name="short_desc" size="40" value="[% default.short_desc.0 FILTER html %]"> - </td> - <td> - <input type="submit" value="Search"> - </td> - </tr> - -[%# *** Product Component Version Target *** %] - - <tr> - <td colspan="4"> - <table> - <tr valign="bottom"> - <th align="left">Product:</th> - <th align="left"><a href="describecomponents.cgi">Component</a>:</th> - <th align="left">Version:</th> - - [% IF (Param("usetargetmilestone")) %] - <th align="left">Target:</th> - [% END %] - </tr> - - <tr valign="top"> - - [%# Can't use the select block here because of onChange and the fact that - 'component' is a toolkit reserved word - we use 'component_' instead. %] - <td align="left"> - <select name="product" multiple size="5" onChange="selectProduct(this.form);"> - [% FOREACH p = product %] - <option value="[% p FILTER html %]" - [% " selected" IF lsearch(default.product, p) != -1 %]> - [% p FILTER html %]</option> - [% END %] - </select> - </td> - - <td align="left"> - <select name="component" multiple size="5"> - [% FOREACH c = component_ %] - <option value="[% c FILTER html %]" - [% " selected" IF lsearch(default.component, c) != -1 %]> - [% c FILTER html %]</option> - [% END %] - </select> - </td> - - [% PROCESS select sel = { name => 'version', size => 5 } %] - - [% IF Param('usetargetmilestone') && target_milestone.size > 0 %] - [% PROCESS select sel = { name => 'target_milestone', size => 5 } %] - [% END %] - </tr> - </table> - </td> - </tr> - -[%# *** Comment URL Whiteboard Keywords *** %] - - [% FOREACH field = [ - { name => "long_desc", description => "A comment" }, - { name => "bug_file_loc", description => "The URL" }, - { name => "status_whiteboard", description => "Whiteboard" } ] %] - - [% UNLESS field.name == 'status_whiteboard' AND NOT Param('usestatuswhiteboard') %] - <tr> - <th align="right">[% field.description %]:</th> - <td> - <select name="[% field.name %]_type"> - [% FOREACH qv = query_variants %] - [% type = "${field.name}_type" %] - <option value="[% qv.value %]" - [% " selected" IF default.$type.0 == qv.value %]>[% qv.description %]</option> - [% END %] - </select> - </td> - <td><input name="[% field.name %]" size="40" value=" - [% default.${field.name}.0 FILTER html %]"> - </td> - <td></td> - </tr> - [% END %] - [% END %] - - [% IF have_keywords %] - <tr> - <th align="right"><a href="describekeywords.cgi">Keywords</a>:</th> - <td> - <select name="keywords_type"> - [% FOREACH qv = [ - { name => "anywords", description => "contains any of the keywords" }, - { name => "allwords", description => "contains all of the keywords" }, - { name => "nowords", description => "contains none of the keywords" } ] %] - - <option value="[% qv.name %]" - [% " selected" IF default.keywords_type.0 == qv.name %]> - [% qv.description %]</option> - [% END %] - </select> - </td> - <td> - <input name="keywords" size="40" value="[% default.keywords.0 FILTER html %]"> - </td> - </tr> - [% END %] -</table> +[% PROCESS search/knob.html.tmpl %] <hr> -[%# *** Status Resolution Severity Priority Hardware OS *** %] - -<table> - <tr> - <th align="left"><a href="queryhelp.cgi#status">Status</a>:</th> - <th align="left"><a href="queryhelp.cgi#resolution">Resolution</a>:</th> - <th align="left"><a href="queryhelp.cgi#severity">Severity</a>:</th> - <th align="left"><a href="queryhelp.cgi#priority">Priority</a>:</th> - <th align="left"><a href="queryhelp.cgi#platform">Hardware</a>:</th> - <th align="left"><a href="queryhelp.cgi#opsys">OS</a>:</th> - </tr> - - <tr valign="top"> - [% PROCESS select sel = { name => 'bug_status', size => 7 } %] - [% PROCESS select sel = { name => 'resolution', size => 7 } %] - [% PROCESS select sel = { name => 'bug_severity', size => 7 } %] - [% PROCESS select sel = { name => 'priority', size => 7 } %] - [% PROCESS select sel = { name => 'rep_platform', size => 7 } %] - [% PROCESS select sel = { name => 'op_sys', size => 7 } %] - </tr> -</table> +[% PROCESS "search/boolean-charts.html.tmpl" %] <p> + Give me a <a href="queryhelp.cgi">clue</a> about how to use this form. +</p> -[%# *** Email Numbering Votes *** %] - -<table> - <tr> - <td> - <fieldset> - <legend> - <strong> - <a href="queryhelp.cgi#peopleinvolved">Email</a> and Numbering - </strong> - </legend> - - -<table> - <tr> - [% FOREACH n = [1, 2] %] - <td> - - -<table cellspacing="0" cellpadding="0"> - <tr> - <td> - Any of: - </td> - </tr> - <tr> - <td> - <input type="checkbox" name="emailassigned_to[% n %]" - id="emailassigned_to[% n %]" value="1" - [% " checked" IF default.emailassigned_to.$n %]> - <label for="emailassigned_to[% n %]"> - bug owner - </label> - </td> - </tr> - <tr> - <td> - <input type="checkbox" name="emailreporter[% n %]" - id="emailreporter[% n %]" value="1" - [% " checked" IF default.emailreporter.$n %]> - <label for="emailreporter[% n %]"> - reporter - </label> - </td> - </tr> - [% IF Param('useqacontact') %] - <tr> - <td> - <input type="checkbox" name="emailqa_contact[% n %]" - id="emailqa_contact[% n %]" value="1" - [% " checked" IF default.emailqa_contact.$n %]> - <label for="emailqa_contact[% n %]"> - QA contact - </label> - </td> - </tr> - [% END %] - <tr> - <td> - <input type="checkbox" name="emailcc[% n %]" - id="emailcc[% n %]" value="1" - [% " checked" IF default.emailcc.$n %]> - <label for="emailcc[% n %]"> - CC list member - </label> - </td> - </tr> - <tr> - <td> - <input type="checkbox" name="emaillongdesc[% n %]" - id="emaillongdesc[% n %]" value="1" - [% " checked" IF default.emaillongdesc.$n %]> - <label for="emaillongdesc[% n %]"> - commenter - </label> - </td> - </tr> - <tr> - <td> - <select name="emailtype[% n %]"> - [% FOREACH qv = [ - { name => "substring", description => "contains" }, - { name => "exact", description => "is" }, - { name => "regexp", description => "matches regexp" }, - { name => "notregexp", description => "doesn’t match regexp" } ] %] - - <option value="[% qv.name %]" - [% " selected" IF default.emailtype.$n == qv.name %]>[% qv.description %]</option> - [% END %] - </select> - </td> - </tr> - <tr> - <td> - <input name="email[% n %]" size="20" value="[% default.email.$n FILTER html %]"> - </td> - </tr> -</table> - - - </td> - [% END %] - </tr> -</table> -<hr> -<table> - <tr> - <td> - <select name="bugidtype"> - <option value="include"[% " selected" IF default.bugidtype.0 == "include" %]>Only include</option> - <option value="exclude"[% " selected" IF default.bugidtype.0 == "exclude" %]>Exclude</option> - </select> - bugs numbered: - </td> - <td> - <input type="text" name="bug_id" value="[% default.bug_id.0 FILTER html %]" size="20"> - </td> - </tr> - <tr> - <td></td> - <td>(comma-separated list)</td> - </tr> - <tr> - <td align="right"> - Only bugs with at least: - </td> - <td> - <input name="votes" size="3" value="[% default.votes.0 FILTER html %]"> votes - </td> - </tr> -</table> - - - </fieldset> - </td> - -[%# *** Bug Changes *** %] - - <td valign="top"> - <fieldset> - <legend><strong>Bug Changes</strong></legend> - - -<dl> - <dt>Only bugs changed in the last </dt> - <dd><input name=changedin size=3 value="[% default.changedin.0 FILTER html %]"> days</dd> -</dl> - -<dl> - <dt>Only bugs where any of the fields</dt> - <dd> - <select name="chfield" multiple size="4"> - [% FOREACH field = chfield %] - <option value="[% field FILTER html %]" - [% " selected" IF lsearch(default.chfield, field) != -1 %]> - [% field FILTER html %]</option> - [% END %] - </select> - </dd> - - <dt>were changed between</dt> - <dd> - <input name="chfieldfrom" size="10" value="[% default.chfieldfrom.0 FILTER html %]"> - and <input name="chfieldto" size="10" value="[% default.chfieldto.0 FILTER html %]"> - <br>(YYYY-MM-DD) - </dd> - <dt>to this value: (optional)</dt> - <dd> - <input name="chfieldvalue" size="20" value="[% default.chfieldvalue.0 FILTER html %]"> - </dd> -</dl> - - - </fieldset> - </td> - </tr> - -[%# *** Action Selection *** %] - - <tr> - <td colspan="2"> - - [% IF NOT userid %] - <input type="hidden" name="cmdtype" value="doit"> - [% ELSE %] - <br> - <input type="radio" name="cmdtype" value="doit" checked> Run this query - <br> - - [% IF namedqueries.size > 0 %] - <p> - <table cellspacing="0" cellpadding="0"> - <tr> - <td> - <input type="radio" name="cmdtype" value="editnamed"> - Load my remembered query: - </td> - <td rowspan="3"> - <select name="namedcmd"> - [% FOREACH query = namedqueries %] - <option value="[% query FILTER html %]">[% query FILTER html %]</option> - [% END %] - </select> - </td> - </tr> - <tr> - <td> - <input type="radio" name="cmdtype" value="runnamed"> - Run my remembered query: - </td> - </tr> - <tr> - <td> - <input type="radio" name="cmdtype" value="forgetnamed"> - Forget my remembered query: - </td> - </tr> - </table> - </p> - [% END %] - - <input type="radio" name="cmdtype" value="asdefault"> - Remember this as my default query - <br> - <input type="radio" name="cmdtype" value="asnamed"> - Remember this query, and name it: - <input type="text" name="newqueryname"> - <br> <input type="checkbox" name="tofooter" value="1"> - and put it in my page footer - <br> - [% END %] - <br> - <div> - Sort results by: - <select name="order"> - [% FOREACH order = orders %] - <option value="[% order FILTER html %]" - [% " selected" IF default.order.0 == order %]>[% order FILTER html %]</option> - [% END %] - </select> - - <input type="submit" value="Search"> - [% IF userdefaultquery %] - <p> - <a href="query.cgi?nukedefaultquery=1"> - Set my default query back to the system default</a> - </p> - [% END %] - </div> - </td> - </tr> -</table> - -[%# *** Boolean Charts *** %] - -<hr> - -[% types = [ - { name => "noop", description => "---" }, - { name => "equals", description => "is equal to" }, - { name => "notequals", description => "is not equal to" }, - { name => "substring", description => "contains the string" }, - { name => "casesubstring", description => "contains the string (exact case)" }, - { name => "notsubstring", description => "does not contain the string" }, - { name => "allwordssubstr", description => "contains all of the strings" }, - { name => "anywordssubstr", description => "contains any of the strings" }, - { name => "regexp", description => "contains regexp" }, - { name => "notregexp", description => "does not contain regexp" }, - { name => "lessthan", description => "is less than" }, - { name => "greaterthan", description => "is greater than" }, - { name => "anywords", description => "contains any of the words" }, - { name => "allwords", description => "contains all of the words" }, - { name => "nowords", description => "contains none of the words" }, - { name => "changedbefore", description => "changed before" }, - { name => "changedafter", description => "changed after" }, - { name => "changedfrom", description => "changed from" }, - { name => "changedto", description => "changed to" }, - { name => "changedby", description => "changed by" } ] %] - - <p> - <strong> - <a name="chart" href="queryhelp.cgi#advancedquerying"> - Advanced Querying Using Boolean Charts</a>: - </strong> - </p> - -[%# Whoever wrote the original version of boolean charts had a seriously twisted mind %] - -[% jsmagic = "onclick=\"document.forms[0].action='query.cgi#chart'; document.forms[0].method='POST'; return 1;\"" %] - -[% FOREACH chart = default.charts %] - [% chartnum = loop.count - 1 %] - <table> - [% FOREACH row = chart %] - [% rownum = loop.count - 1 %] - <tr> - [% FOREACH col = row %] - [% colnum = loop.count - 1 %] - <td> - <select name="[% "field${chartnum}-${rownum}-${colnum}" %]"> - [% FOREACH field = fields %] - <option value="[% field.name %]" - [%- " selected" IF field.name == col.field %]>[% field.description %]</option> - [% END %] - </select> - - <select name="[% "type${chartnum}-${rownum}-${colnum}" %]"> - [% FOREACH type = types %] - <option value="[% type.name %]" - [%- " selected" IF type.name == col.type %]>[% type.description %]</option> - [% END %] - </select> - - <input name="[% "value${chartnum}-${rownum}-${colnum}" %]" - value="[% col.value FILTER html %]"> - </td> - - [% IF NOT col == row.last %] - <td align="center"> - Or - </td> - [% ELSE %] - <td> - [% newor = colnum + 1 %] - <input type="submit" value="Or" - name="cmd-add[% "${chartnum}-${rownum}-${newor}" %]" [% $jsmagic %]> - </td> - [% END %] - - [% END %] - </tr> - - [% IF NOT row == chart.last %] - <tr> - <td>And</td> - </tr> - [% ELSE %] - <tr> - <td> - [% newand = rownum + 1; newchart = chartnum + 1 %] - <input type="submit" value="And" - name="cmd-add[% "${chartnum}-${newand}-0" %]"[% $jsmagic %]> - - <input type="submit" value="Add another boolean chart" - name="cmd-add[% newchart %]-0-0" [% $jsmagic %]> - - </td> - </tr> - [% END %] - - [% END %] - </table> - <hr> -[% END %] - -<p>Give me a <a href="queryhelp.cgi">clue</a> about how to use this form.</p> - -</FORM> +</form> [% PROCESS global/footer.html.tmpl %] - -[%############################################################################%] -[%# Block for SELECT fields #%] -[%############################################################################%] - -[% BLOCK select %] - <td align="left"> - <select name="[% sel.name %]" multiple size="[% sel.size %]"> - [% FOREACH name = ${sel.name} %] - <option value="[% name FILTER html %]" - [% " selected" IF lsearch(default.${sel.name}, name) != -1 %]> - [% name FILTER html %]</option> - [% END %] - </select> - </td> -[% END %] |