From 91b171e7584920d03abb9c45e779c84f3dee975c Mon Sep 17 00:00:00 2001 From: "myk%mozilla.org" <> Date: Sun, 29 Sep 2002 01:42:23 +0000 Subject: Fix for bug 98801: Implementation of the request tracker, a set of enhancements to attachment statuses. r=gerv,bbaetz --- productmenu.js | 242 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 242 insertions(+) create mode 100644 productmenu.js (limited to 'productmenu.js') diff --git a/productmenu.js b/productmenu.js new file mode 100644 index 000000000..d917d325c --- /dev/null +++ b/productmenu.js @@ -0,0 +1,242 @@ +// 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); +// - 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. +// - 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, blank ) { + + var i, j, comp; + + // 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 ); + + // 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 ); + + // merge the arrays. not very good for multiple selections. + for ( i = 2; i < sel.length; i++ ) { + comp = merge_arrays( comp, array[sel[i]], 0 ); + } + } + } else { + // single item in selection, just get me the list + comp = array[sel[0]]; + } + + // save the selection in the target select so we can restore it later + var selections = new Array(); + for ( i = 0; i < target.options.length; i++ ) + if (target.options[i].selected) selections.push(target.options[i].value); + + // clear select + target.options.length = 0; + + // add empty "Any" value back to the list + if (blank) target.options[0] = new Option( blank, "" ); + + // load elements of list into select + for ( i = 0; i < comp.length; i++ ) { + target.options[target.options.length] = new Option( comp[i], comp[i] ); + } + + // restore the selection + for ( i=0 ; i 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; + } + +// selectProduct reads the selection from f[productfield] 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. +// - usetms: this is a global boolean that is defined if the +// bugzilla installation has it turned on. generated in perl too. +// - first_load: boolean, specifying if it's 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 , productfield, componentfield, blank ) { + + // this is to avoid handling events that occur before the form + // itself is ready, which happens in buggy browsers. + + if ( ( !f ) || ( ! f[productfield] ) ) { + 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[productfield].selectedIndex == -1 ) ) { + first_load = 0; + 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 = 0; + + // - sel keeps the array of products we are selected. + // - is_diff says if it's a full list or just a list of products that + // were added to the current selection. + // - single indicates if a single item was selected + var sel = Array(); + var is_diff = 0; + var single; + + // if nothing selected, pick all + if ( f[productfield].selectedIndex == -1 ) { + for ( var i = 0 ; i < f[productfield].length ; i++ ) { + sel[sel.length] = f[productfield].options[i].value; + } + single = 0; + } else { + + for ( i = 0 ; i < f[productfield].length ; i++ ) { + if ( f[productfield].options[i].selected ) { + sel[sel.length] = f[productfield].options[i].value; + } + } + + single = ( sel.length == 1 ); + + // save last_sel before we kill it + var tmp = last_sel; + last_sel = sel; + + // this is an optimization: if we've 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; + } + } + + // do the actual fill/update + updateSelect( cpts, sel, f[componentfield], is_diff, single, blank ); +} -- cgit v1.2.3-24-g4f1b