Bug 122154 - change arrays to numeric, and clean up query.atml js

patch by kiko@async.com.br, r=caillon,bbaetz
parent 7703b328
...@@ -27,80 +27,106 @@ ...@@ -27,80 +27,106 @@
[%# Note: use Template comments and not JS ones here, to avoid bloating [%# Note: use Template comments and not JS ones here, to avoid bloating
what we actually send to the browser %] what we actually send to the browser %]
[% IF Param('usetargetmilestone') %]
[% tms = 1 %]
[% ELSE %]
[% tms = 0 %]
[% END %]
<script language="JavaScript" type="text/javascript"> <!-- <script language="JavaScript" type="text/javascript"> <!--
var first_load = 1; [%# is this the first time we load the page? %] var first_load = true; [%# is this the first time we load the page? %]
var last_sel = []; [%# caches last selection %] var last_sel = new Array(); [%# caches last selection %]
var usetms = [% IF Param('usetargetmilestone') %]true[% ELSE %]false[% END %]; var usetms = [% IF tms %]true[% ELSE %]false[% END %];
[%# do we have target milestone? %] [%# do we have target milestone? %]
var cpts = new Array();
var vers = new Array();
var tms = new Array();
var cpts = new Object(); [%# Create three arrays of components, versions and target milestones, indexed
var vers = new Object(); # numerically according to the product they refer to. #%]
var tms = new Object();
[% n = 0 %]
[% FOREACH p = product %] [% FOREACH p = product %]
cpts['[% p FILTER js %]'] = [ cpts[[% n %]] = [
[%- FOREACH item = componentsbyproduct.$p %]'[% item FILTER js %]', [%- END -%]] [%- FOREACH item = componentsbyproduct.$p %]'[% item FILTER js %]', [%- END -%]];
vers['[% p FILTER js %]'] = [ vers[[% n %]] = [
[%- FOREACH item = versionsbyproduct.$p -%]'[% item FILTER js %]', [%- END -%]] [%- FOREACH item = versionsbyproduct.$p -%]'[% item FILTER js %]', [%- END -%]];
tms['[% p FILTER js %]'] = [ [% IF tms %]
[%- FOREACH item = milestonesbyproduct.$p %]'[% item FILTER js %]', [%- END -%]] tms[[% n %]] = [
[%- FOREACH item = milestonesbyproduct.$p %]'[% item FILTER js %]', [%- END -%]];
[% END %]
[% n = n+1 %]
[% END %] [% 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. # correspond to the elements selected in source.
# - array should be a array of arrays, indexed by product name. the # - array should be a array of arrays, indexed by number. the
# array should contain the elements that correspont to that # array should contain the elements that correspond to that
# product. Example: # product.
# var array = Array();
# array['ProductOne'] = [ 'ComponentA', 'ComponentB' ];
# updateSelect(array, source, target);
# - sel is a list of selected items, either whole or a diff # - sel is a list of selected items, either whole or a diff
# depending on sel_is_diff. # depending on merging.
# - sel_is_diff determines if we are sending in just a diff or the
# whole selection. a diff is used to optimize adding selections.
# - target should be the target select object. # - target should be the target select object.
# - single specifies if we selected a single item. if we did, no # - merging (boolean) determines if we are mergine in a diff or
# need to merge. %] # substituting the whole selection. a diff is used to optimize adding
function updateSelect(array, sel, target, sel_is_diff, single) { # 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 [%# If we have no versions/components/milestones %]
selected and select one item alone), skip this. %] if (array.length < 1) {
if (!single) { target.options.length = 0;
[%# array merging/sorting in the case of multiple selections %] return false;
if (sel_is_diff) { }
[%# merge in the current options with the first selection %]
comp = merge_arrays(array[sel[0]], target.options, 1);
[%# merge the rest of the selection with the results %] if (merging) {
for (i = 1 ; i < sel.length ; i++) { [%# array merging/sorting in the case of multiple selections %]
comp = merge_arrays(array[sel[i]], comp, 0); [%# merge in the current options with the first selection %]
} item = merge_arrays(array[sel[0]], target.options, 1);
} 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);
[%# merge the arrays. not very good for multiple selections. %] [%# merge the rest of the selection with the results %]
for (i = 2; i < sel.length; i++) { for (i = 1 ; i < sel.length ; i++) {
comp = merge_arrays(comp, array[sel[i]], 0); item = merge_arrays(array[sel[i]], item, 0);
}
} }
} else { } else if ( sel.length > 1 ) {
[%# single item in selection, just get me the list %] [%# here we micro-optimize for two arrays to avoid merging with a
comp = array[sel[0]]; 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 %] [%# clear select %]
target.options.length = 0; target.options.length = 0;
[%# load elements of list into select %] [%# load elements of list into select %]
for (i = 0; i < comp.length; i++) { for (i = 0; i < item.length; i++) {
target.options[i] = new Option(comp[i], comp[i]); target.options[i] = new Option(item[i], item[i]);
} }
return true;
} }
[%# Returns elements in a that are not in b. [%# Returns elements in a that are not in b.
...@@ -108,19 +134,19 @@ function updateSelect(array, sel, target, sel_is_diff, single) { ...@@ -108,19 +134,19 @@ function updateSelect(array, sel, target, sel_is_diff, single) {
# - a,b: arrays of values to be compare. %] # - a,b: arrays of values to be compare. %]
function fake_diff_array(a, b) { function fake_diff_array(a, b) {
var newsel = new Array(); var newsel = new Array();
var found = false;
[%# do a boring array diff to see who's new %] [%# do a boring array diff to see who's new %]
for (var ia in a) { for (var ia in a) {
var found = 0;
for (var ib in b) { for (var ib in b) {
if (a[ia] == b[ib]) { if (a[ia] == b[ib]) {
found = 1; found = true;
} }
} }
if (!found) { if (!found) {
newsel[newsel.length] = a[ia]; newsel[newsel.length] = a[ia];
} }
found = 0; found = false;
} }
return newsel; return newsel;
} }
...@@ -185,6 +211,34 @@ function merge_arrays(a, b, b_is_select) { ...@@ -185,6 +211,34 @@ function merge_arrays(a, b, b_is_select) {
return ret; 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 [%# selectProduct reads the selection from f.product and updates
# f.version, component and target_milestone accordingly. # f.version, component and target_milestone accordingly.
# - f: a form containing product, component, varsion and # - f: a form containing product, component, varsion and
...@@ -202,7 +256,7 @@ function merge_arrays(a, b, b_is_select) { ...@@ -202,7 +256,7 @@ function merge_arrays(a, b, b_is_select) {
# changed, and optimize for additions. %] # changed, and optimize for additions. %]
function selectProduct(f) { function selectProduct(f) {
[%# this is to avoid handling events that occur before the form [%# 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)) { if ((!f) || (!f.product)) {
return; return;
} }
...@@ -210,7 +264,7 @@ function selectProduct(f) { ...@@ -210,7 +264,7 @@ function selectProduct(f) {
[%# if this is the first load and nothing is selected, no need to [%# if this is the first load and nothing is selected, no need to
merge and sort all components; perl gives it to us sorted. %] merge and sort all components; perl gives it to us sorted. %]
if ((first_load) && (f.product.selectedIndex == -1)) { if ((first_load) && (f.product.selectedIndex == -1)) {
first_load = 0; first_load = false;
return; return;
} }
...@@ -221,49 +275,40 @@ function selectProduct(f) { ...@@ -221,49 +275,40 @@ function selectProduct(f) {
item, selectProduct will be called but the clause will be valid item, selectProduct will be called but the clause will be valid
(since selectedIndex == -1), and we will return - incorrectly - (since selectedIndex == -1), and we will return - incorrectly -
without merge/sorting. %] without merge/sorting. %]
first_load = 0; first_load = false;
[%# - sel keeps the array of products we are selected. [%# - 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 - merging says if it is a full list or just a list of products that
were added to the current selection. were added to the current selection. %]
- single indicates if a single item was selected %] var merging = false;
var sel = Array(); var sel = Array();
var is_diff = 0;
var single;
[%# if nothing selected, pick all %] [%# if nothing selected, pick all %]
if (f.product.selectedIndex == -1) { if (f.product.selectedIndex == -1) {
for (var i = 0 ; i < f.product.length ; i++) { sel = getSelection(f.product, true);
sel[sel.length] = f.product.options[i].value;
}
single = 0;
} else { } else {
for (i = 0 ; i < f.product.length ; i++) { sel = getSelection(f.product, false);
if (f.product.options[i].selected) {
sel[sel.length] = f.product.options[i].value;
}
}
single = (sel.length == 1); [%# save sel for the next invocation of selectProduct() %]
var tmp = sel;
[%# save last_sel before we kill it %]
var tmp = last_sel;
last_sel = sel;
[%# this is an optimization: if we have added components, no need [%# this is an optimization: if we have just added products to an
to remerge them; just merge the new ones with the existing existing selection, no need to clear the form controls and add
options. %] everybody again; just merge the new ones with the existing
if ((tmp) && (tmp.length < sel.length)) { options. %]
sel = fake_diff_array(sel, tmp); if ((last_sel.length > 0) && (last_sel.length < sel.length)) {
is_diff = 1; sel = fake_diff_array(sel, last_sel);
merging = true;
} }
last_sel = tmp;
} }
[%# do the actual fill/update %] [%# do the actual fill/update %]
updateSelect(cpts, sel, f.component, is_diff, single); updateSelect(cpts, sel, f.component, merging);
updateSelect(vers, sel, f.version, is_diff, single); updateSelect(vers, sel, f.version, merging);
if (usetms) { if (usetms) {
updateSelect(tms, sel, f.target_milestone, is_diff, single); updateSelect(tms, sel, f.target_milestone, merging);
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment