mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-08 20:43:50 +00:00
Fix for bug 123030: Move query.cgi javascript to separate file. Create
productform.js that contains functions to handle the various select boxes in the advanced search page, and update the callsites to use it. r,a=myk.
This commit is contained in:
parent
57260fe853
commit
b345891dda
295
webtools/bugzilla/js/productform.js
Normal file
295
webtools/bugzilla/js/productform.js
Normal file
@ -0,0 +1,295 @@
|
||||
/* 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): Christian Reis <kiko@async.com.br>
|
||||
*/
|
||||
|
||||
/* this file contains functions to update form controls based on a
|
||||
* collection of javascript arrays containing strings */
|
||||
|
||||
/* selectProduct reads the selection from the product control and
|
||||
* updates version, component and milestone controls accordingly.
|
||||
*
|
||||
* - product, component, version and milestone: form controls
|
||||
*
|
||||
* 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(product, component, version, milestone) {
|
||||
|
||||
if (!product) {
|
||||
/* this is to avoid handling events that occur before the form
|
||||
* itself is ready, which could happen in buggy browsers. */
|
||||
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) && (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 = product.selectedIndex == -1;
|
||||
sel = get_selection(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;
|
||||
}
|
||||
|
||||
/* do the actual fill/update */
|
||||
if (component) {
|
||||
var saved_cpts = get_selection(component, false, true);
|
||||
updateSelect(cpts, sel, component, merging);
|
||||
restoreSelection(component, saved_cpts);
|
||||
}
|
||||
|
||||
if (version) {
|
||||
var saved_vers = get_selection(version, false, true);
|
||||
updateSelect(vers, sel, version, merging);
|
||||
restoreSelection(version, saved_vers);
|
||||
}
|
||||
|
||||
if (milestone) {
|
||||
var saved_tms = get_selection(milestone, false, true);
|
||||
updateSelect(tms, sel, milestone, merging);
|
||||
restoreSelection(milestone, saved_tms);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* 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 get_selection(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;
|
||||
}
|
||||
|
@ -23,302 +23,6 @@
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
|
||||
[%# 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 = p.components %]'[% item FILTER js %]'[% ", " UNLESS loop.last %] [%- END -%] ];
|
||||
vers[[% n %]] = [
|
||||
[%- FOREACH item = p.versions -%]'[% item FILTER js %]'[% ", " UNLESS loop.last %] [%- END -%] ];
|
||||
[% IF Param('usetargetmilestone') %]
|
||||
tms[[% n %]] = [
|
||||
[%- FOREACH item = p.milestones %]'[% item FILTER js %]'[% ", " UNLESS loop.last %] [%- 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 get_selection(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 = get_selection(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 = get_selection(f.component, false, true);
|
||||
var saved_vers = get_selection(f.version, false, true);
|
||||
[% IF Param('usetargetmilestone') %]
|
||||
var saved_tms = get_selection(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" },
|
||||
@ -379,7 +83,7 @@ function selectProduct(f) {
|
||||
<td align="left">
|
||||
<label for="product" accesskey="p">
|
||||
<select name="product" multiple="multiple" size="5" id="product"
|
||||
onchange="selectProduct(this.form);">
|
||||
onchange="doOnSelectProduct();">
|
||||
[% FOREACH p = product %]
|
||||
<option value="[% p.name FILTER html %]"
|
||||
[% " selected" IF lsearch(default.product, p.name) != -1 %]>
|
||||
|
@ -30,10 +30,48 @@
|
||||
[% USE Bugzilla %]
|
||||
[% cgi = Bugzilla.cgi %]
|
||||
|
||||
|
||||
[% js_data = BLOCK %]
|
||||
function doOnSelectProduct() {
|
||||
var f = document.forms['queryform'];
|
||||
milestone = (typeof(f.target_milestone) == "undefined" ?
|
||||
null : f.target_milestone);
|
||||
selectProduct(f.product, f.component, f.version, milestone);
|
||||
}
|
||||
|
||||
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 = p.components %]'[% item FILTER js %]'[% ", " UNLESS loop.last %] [%- END -%] ];
|
||||
vers[[% n %]] = [
|
||||
[%- FOREACH item = p.versions -%]'[% item FILTER js %]'[% ", " UNLESS loop.last %] [%- END -%] ];
|
||||
[% IF Param('usetargetmilestone') %]
|
||||
tms[[% n %]] = [
|
||||
[%- FOREACH item = p.milestones %]'[% item FILTER js %]'[% ", " UNLESS loop.last %] [%- END -%] ];
|
||||
[% END %]
|
||||
[% n = n+1 %]
|
||||
[% END %]
|
||||
|
||||
[% END %]
|
||||
|
||||
[% PROCESS global/header.html.tmpl
|
||||
title = "Search for $terms.bugs"
|
||||
h1 = ""
|
||||
onload = "selectProduct(document.forms['queryform']);initHelp();"
|
||||
onload = "doOnSelectProduct(); initHelp();"
|
||||
javascript = js_data
|
||||
javascript_urls = [ "js/productform.js" ]
|
||||
style = "td.selected_tab {
|
||||
border-width: 2px 2px 0px;
|
||||
border-style: solid;
|
||||
|
Loading…
Reference in New Issue
Block a user