summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--template/default/query/query.atml215
1 files changed, 130 insertions, 85 deletions
diff --git a/template/default/query/query.atml b/template/default/query/query.atml
index c98d7bdc6..d4f8dbd17 100644
--- a/template/default/query/query.atml
+++ b/template/default/query/query.atml
@@ -27,80 +27,106 @@
[%# Note: use Template comments and not JS ones here, to avoid bloating
what we actually send to the browser %]
+
+[% IF Param('usetargetmilestone') %]
+[% tms = 1 %]
+[% ELSE %]
+[% tms = 0 %]
+[% END %]
<script language="JavaScript" type="text/javascript"> <!--
-var first_load = 1; [%# is this the first time we load the page? %]
-var last_sel = []; [%# caches last selection %]
-var usetms = [% IF Param('usetargetmilestone') %]true[% ELSE %]false[% END %];
- [%# do we have target milestone? %]
+var first_load = true; [%# is this the first time we load the page? %]
+var last_sel = new Array(); [%# caches last selection %]
+var usetms = [% IF tms %]true[% ELSE %]false[% END %];
+ [%# do we have target milestone? %]
+
+var cpts = new Array();
+var vers = new Array();
+var tms = new Array();
-var cpts = new Object();
-var vers = new Object();
-var tms = new Object();
+[%# Create three arrays of components, versions and target milestones, indexed
+ # numerically according to the product they refer to. #%]
+[% n = 0 %]
[% FOREACH p = product %]
- cpts['[% p FILTER js %]'] = [
- [%- FOREACH item = componentsbyproduct.$p %]'[% item FILTER js %]', [%- END -%]]
- vers['[% p FILTER js %]'] = [
- [%- FOREACH item = versionsbyproduct.$p -%]'[% item FILTER js %]', [%- END -%]]
- tms['[% p FILTER js %]'] = [
- [%- FOREACH item = milestonesbyproduct.$p %]'[% item FILTER js %]', [%- END -%]]
+ cpts[[% n %]] = [
+ [%- FOREACH item = componentsbyproduct.$p %]'[% item FILTER js %]', [%- END -%]];
+ vers[[% n %]] = [
+ [%- FOREACH item = versionsbyproduct.$p -%]'[% item FILTER js %]', [%- END -%]];
+ [% IF tms %]
+ tms[[% n %]] = [
+ [%- FOREACH item = milestonesbyproduct.$p %]'[% item FILTER js %]', [%- END -%]];
+ [% END %]
+ [% n = n+1 %]
[% END %]
-[%# Adds to the target select object all elements in array that
+[%# 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 product name. the
- # array should contain the elements that correspont to that
- # product. Example:
- # var array = Array();
- # array['ProductOne'] = [ 'ComponentA', 'ComponentB' ];
- # updateSelect(array, source, target);
+ # - 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 sel_is_diff.
- # - sel_is_diff determines if we are sending in just a diff or the
- # whole selection. a diff is used to optimize adding selections.
+ # depending on merging.
# - target should be the target select object.
- # - single specifies if we selected a single item. if we did, no
- # need to merge. %]
-function updateSelect(array, sel, target, sel_is_diff, single) {
+ # - 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, comp;
+ var i, item;
- [%# if single, even if it's a diff (happens when you have nothing
- selected and select one item alone), skip this. %]
- if (!single) {
- [%# array merging/sorting in the case of multiple selections %]
- if (sel_is_diff) {
- [%# merge in the current options with the first selection %]
- comp = merge_arrays(array[sel[0]], target.options, 1);
+ [%# If we have no versions/components/milestones %]
+ if (array.length < 1) {
+ target.options.length = 0;
+ return false;
+ }
- [%# merge the rest of the selection with the results %]
- for (i = 1 ; i < sel.length ; i++) {
- comp = merge_arrays(array[sel[i]], comp, 0);
- }
- } else {
- [%# here we micro-optimize for two arrays to avoid merging with a
- null array %]
- comp = merge_arrays(array[sel[0]],array[sel[1]], 0);
+ 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 arrays. not very good for multiple selections. %]
- for (i = 2; i < sel.length; i++) {
- comp = merge_arrays(comp, array[sel[i]], 0);
- }
+ [%# 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 {
- [%# single item in selection, just get me the list %]
- comp = array[sel[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 < comp.length; i++) {
- target.options[i] = new Option(comp[i], comp[i]);
+ 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.
@@ -108,19 +134,19 @@ function updateSelect(array, sel, target, sel_is_diff, single) {
# - 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) {
- var found = 0;
for (var ib in b) {
if (a[ia] == b[ib]) {
- found = 1;
+ found = true;
}
}
if (!found) {
newsel[newsel.length] = a[ia];
}
- found = 0;
+ found = false;
}
return newsel;
}
@@ -185,6 +211,34 @@ function merge_arrays(a, b, b_is_select) {
return ret;
}
+[%# Returns an array of indexes.
+ # - control: select control from which to find selections
+ # - findall: boolean, dumping all options if all or just the selected
+ # indexes. %]
+function getSelection(control, findall) {
+ 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] = i;
+ }
+ }
+ return ret;
+}
+
+[%# Selects items in control that have index defined in sel
+ # - control: SELECT control to be restored
+ # - sel: array of indexes in select form control %]
+function restoreSelection(control, sel) {
+ for (var s in sel) {
+ control.options[sel[s]].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
@@ -202,7 +256,7 @@ function merge_arrays(a, b, b_is_select) {
# changed, and optimize for additions. %]
function selectProduct(f) {
[%# this is to avoid handling events that occur before the form
- itself is ready, which happens in buggy browsers. %]
+ itself is ready, which could happen in buggy browsers. %]
if ((!f) || (!f.product)) {
return;
}
@@ -210,7 +264,7 @@ function selectProduct(f) {
[%# 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 = 0;
+ first_load = false;
return;
}
@@ -221,49 +275,40 @@ function selectProduct(f) {
item, selectProduct will be called but the clause will be valid
(since selectedIndex == -1), and we will return - incorrectly -
without merge/sorting. %]
- first_load = 0;
+ first_load = false;
[%# - sel keeps the array of products we are selected.
- - is_diff says if it is a full list or just a list of products that
- were added to the current selection.
- - single indicates if a single item was 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();
- var is_diff = 0;
- var single;
[%# if nothing selected, pick all %]
if (f.product.selectedIndex == -1) {
- for (var i = 0 ; i < f.product.length ; i++) {
- sel[sel.length] = f.product.options[i].value;
- }
- single = 0;
+ sel = getSelection(f.product, true);
} else {
- for (i = 0 ; i < f.product.length ; i++) {
- if (f.product.options[i].selected) {
- sel[sel.length] = f.product.options[i].value;
- }
- }
+ sel = getSelection(f.product, false);
- single = (sel.length == 1);
-
- [%# save last_sel before we kill it %]
- var tmp = last_sel;
- last_sel = sel;
+ [%# save sel for the next invocation of selectProduct() %]
+ var tmp = sel;
- [%# this is an optimization: if we have added components, no need
- to remerge them; just merge the new ones with the existing
- options. %]
- if ((tmp) && (tmp.length < sel.length)) {
- sel = fake_diff_array(sel, tmp);
- is_diff = 1;
+ [%# 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 %]
- updateSelect(cpts, sel, f.component, is_diff, single);
- updateSelect(vers, sel, f.version, is_diff, single);
+ updateSelect(cpts, sel, f.component, merging);
+ updateSelect(vers, sel, f.version, merging);
if (usetms) {
- updateSelect(tms, sel, f.target_milestone, is_diff, single);
+ updateSelect(tms, sel, f.target_milestone, merging);
}
}