~ubuntu-branches/ubuntu/intrepid/bugzilla/intrepid

« back to all changes in this revision

Viewing changes to productmenu.js

  • Committer: Bazaar Package Importer
  • Author(s): Raphael Bossek
  • Date: 2008-06-27 22:34:34 UTC
  • mfrom: (1.1.7 upstream)
  • Revision ID: james.westby@ubuntu.com-20080627223434-0ib57vstn43bb4a3
Tags: 3.0.4.1-1
* Update of French, Russian and German translations. (closes: #488251)
* Added Bulgarian and Belarusian translations.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// Adds to the target select object all elements in array that
2
 
// correspond to the elements selected in source.
3
 
//     - array should be a array of arrays, indexed by product name. the
4
 
//       array should contain the elements that correspont to that
5
 
//       product. Example:
6
 
//         var array = Array();
7
 
//         array['ProductOne'] = [ 'ComponentA', 'ComponentB' ];
8
 
//         updateSelect(array, source, target);
9
 
//     - sel is a list of selected items, either whole or a diff
10
 
//       depending on sel_is_diff.
11
 
//     - sel_is_diff determines if we are sending in just a diff or the
12
 
//       whole selection. a diff is used to optimize adding selections.
13
 
//     - target should be the target select object.
14
 
//     - single specifies if we selected a single item. if we did, no
15
 
//       need to merge.
16
 
 
17
 
function updateSelect( array, sel, target, sel_is_diff, single, blank ) {
18
 
 
19
 
    var i, j, comp;
20
 
 
21
 
    // if single, even if it's a diff (happens when you have nothing
22
 
    // selected and select one item alone), skip this.
23
 
    if ( ! single ) {
24
 
 
25
 
        // array merging/sorting in the case of multiple selections
26
 
        if ( sel_is_diff ) {
27
 
 
28
 
            // merge in the current options with the first selection
29
 
            comp = merge_arrays( array[sel[0]], target.options, 1 );
30
 
 
31
 
            // merge the rest of the selection with the results
32
 
            for ( i = 1 ; i < sel.length ; i++ ) {
33
 
                comp = merge_arrays( array[sel[i]], comp, 0 );
34
 
            }
35
 
        } else {
36
 
            // here we micro-optimize for two arrays to avoid merging with a
37
 
            // null array
38
 
            comp = merge_arrays( array[sel[0]],array[sel[1]], 0 );
39
 
 
40
 
            // merge the arrays. not very good for multiple selections.
41
 
            for ( i = 2; i < sel.length; i++ ) {
42
 
                comp = merge_arrays( comp, array[sel[i]], 0 );
43
 
            }
44
 
        }
45
 
    } else {
46
 
        // single item in selection, just get me the list
47
 
        comp = array[sel[0]];
48
 
    }
49
 
 
50
 
    // save the selection in the target select so we can restore it later
51
 
    var selections = new Array();
52
 
    for ( i = 0; i < target.options.length; i++ )
53
 
      if (target.options[i].selected) selections.push(target.options[i].value);
54
 
 
55
 
    // clear select
56
 
    target.options.length = 0;
57
 
 
58
 
    // add empty "Any" value back to the list
59
 
    if (blank) target.options[0] = new Option( blank, "" );
60
 
 
61
 
    // load elements of list into select
62
 
    for ( i = 0; i < comp.length; i++ ) {
63
 
        target.options[target.options.length] = new Option( comp[i], comp[i] );
64
 
    }
65
 
 
66
 
    // restore the selection
67
 
    for ( i=0 ; i<selections.length ; i++ )
68
 
      for ( j=0 ; j<target.options.length ; j++ )
69
 
        if (target.options[j].value == selections[i]) target.options[j].selected = true;
70
 
 
71
 
}
72
 
 
73
 
// Returns elements in a that are not in b.
74
 
// NOT A REAL DIFF: does not check the reverse.
75
 
//     - a,b: arrays of values to be compare.
76
 
 
77
 
function fake_diff_array( a, b ) {
78
 
    var newsel = new Array();
79
 
 
80
 
    // do a boring array diff to see who's new
81
 
        for ( var ia in a ) {
82
 
            var found = 0;
83
 
            for ( var ib in b ) {
84
 
                if ( a[ia] == b[ib] ) {
85
 
                    found = 1;
86
 
                }
87
 
            }
88
 
            if ( ! found ) {
89
 
                newsel[newsel.length] = a[ia];
90
 
            }
91
 
            found = 0;
92
 
        }
93
 
        return newsel;
94
 
    }
95
 
 
96
 
// takes two arrays and sorts them by string, returning a new, sorted
97
 
// array. the merge removes dupes, too.
98
 
//     - a, b: arrays to be merge.
99
 
//     - b_is_select: if true, then b is actually an optionitem and as
100
 
//       such we need to use item.value on it.
101
 
 
102
 
    function merge_arrays( a, b, b_is_select ) {
103
 
        var pos_a = 0;
104
 
        var pos_b = 0;
105
 
        var ret = new Array();
106
 
        var bitem, aitem;
107
 
 
108
 
    // iterate through both arrays and add the larger item to the return
109
 
    // list. remove dupes, too. Use toLowerCase to provide
110
 
    // case-insensitivity.
111
 
 
112
 
        while ( ( pos_a < a.length ) && ( pos_b < b.length ) ) {
113
 
 
114
 
            if ( b_is_select ) {
115
 
                bitem = b[pos_b].value;
116
 
            } else {
117
 
                bitem = b[pos_b];
118
 
            }
119
 
            aitem = a[pos_a];
120
 
 
121
 
        // smaller item in list a
122
 
            if ( aitem.toLowerCase() < bitem.toLowerCase() ) {
123
 
                ret[ret.length] = aitem;
124
 
                pos_a++;
125
 
            } else {
126
 
            // smaller item in list b
127
 
                if ( aitem.toLowerCase() > bitem.toLowerCase() ) {
128
 
                    ret[ret.length] = bitem;
129
 
                    pos_b++;
130
 
                } else {
131
 
                // list contents are equal, inc both counters.
132
 
                    ret[ret.length] = aitem;
133
 
                pos_a++;
134
 
                pos_b++;
135
 
            }
136
 
        }
137
 
        }
138
 
 
139
 
    // catch leftovers here. these sections are ugly code-copying.
140
 
        if ( pos_a < a.length ) {
141
 
            for ( ; pos_a < a.length ; pos_a++ ) {
142
 
                ret[ret.length] = a[pos_a];
143
 
            }
144
 
        }
145
 
 
146
 
        if ( pos_b < b.length ) {
147
 
            for ( ; pos_b < b.length; pos_b++ ) {
148
 
                if ( b_is_select ) {
149
 
                    bitem = b[pos_b].value;
150
 
                } else {
151
 
                    bitem = b[pos_b];
152
 
                }
153
 
                ret[ret.length] = bitem;
154
 
            }
155
 
        }
156
 
        return ret;
157
 
    }
158
 
 
159
 
// selectProduct reads the selection from f[productfield] and updates
160
 
// f.version, component and target_milestone accordingly.
161
 
//     - f: a form containing product, component, varsion and
162
 
//       target_milestone select boxes.
163
 
// globals (3vil!):
164
 
//     - cpts, vers, tms: array of arrays, indexed by product name. the
165
 
//       subarrays contain a list of names to be fed to the respective
166
 
//       selectboxes. For bugzilla, these are generated with perl code
167
 
//       at page start.
168
 
//     - usetms: this is a global boolean that is defined if the
169
 
//       bugzilla installation has it turned on. generated in perl too.
170
 
//     - first_load: boolean, specifying if it's the first time we load
171
 
//       the query page.
172
 
//     - last_sel: saves our last selection list so we know what has
173
 
//       changed, and optimize for additions.
174
 
 
175
 
function selectProduct( f , productfield, componentfield, blank ) {
176
 
 
177
 
    // this is to avoid handling events that occur before the form
178
 
    // itself is ready, which happens in buggy browsers.
179
 
 
180
 
    if ( ( !f ) || ( ! f[productfield] ) ) {
181
 
        return;
182
 
    }
183
 
 
184
 
    // Do nothing if no products are defined (this avoids the
185
 
    // "a has no properties" error from merge_arrays function)
186
 
    if (f[productfield].length == blank ? 1 : 0) {
187
 
        return;
188
 
    }
189
 
 
190
 
    // if this is the first load and nothing is selected, no need to
191
 
    // merge and sort all components; perl gives it to us sorted.
192
 
 
193
 
    if ( ( first_load ) && ( f[productfield].selectedIndex == -1 ) ) {
194
 
            first_load = 0;
195
 
            return;
196
 
    }
197
 
 
198
 
    // turn first_load off. this is tricky, since it seems to be
199
 
    // redundant with the above clause. It's not: if when we first load
200
 
    // the page there is _one_ element selected, it won't fall into that
201
 
    // clause, and first_load will remain 1. Then, if we unselect that
202
 
    // item, selectProduct will be called but the clause will be valid
203
 
    // (since selectedIndex == -1), and we will return - incorrectly -
204
 
    // without merge/sorting.
205
 
 
206
 
    first_load = 0;
207
 
 
208
 
    // - sel keeps the array of products we are selected.
209
 
    // - is_diff says if it's a full list or just a list of products that
210
 
    //   were added to the current selection.
211
 
    // - single indicates if a single item was selected
212
 
    // - selectedIndex is the index of the first selected item
213
 
    // - selectedValue is the value of the first selected item
214
 
    var sel = Array();
215
 
    var is_diff = 0;
216
 
    var single;
217
 
    var selectedIndex = f[productfield].selectedIndex;
218
 
    var selectedValue = f[productfield].options[selectedIndex].value;
219
 
 
220
 
    // If nothing is selected, or the selected item is the "blank" value
221
 
    // at the top of the list which represents all products on drop-down menus,
222
 
    // then pick all products so we show all components.
223
 
    if ( selectedIndex == -1 || !cpts[selectedValue])
224
 
    {
225
 
        for ( var i = blank ? 1 : 0 ; i < f[productfield].length ; i++ ) {
226
 
            sel[sel.length] = f[productfield].options[i].value;
227
 
        }
228
 
        // If there is only one product, then only one product can be selected
229
 
        single = ( sel.length == 1 );
230
 
    } else {
231
 
 
232
 
        for ( i = blank ? 1 : 0 ; i < f[productfield].length ; i++ ) {
233
 
            if ( f[productfield].options[i].selected ) {
234
 
                sel[sel.length] = f[productfield].options[i].value;
235
 
            }
236
 
        }
237
 
 
238
 
        single = ( sel.length == 1 );
239
 
 
240
 
        // save last_sel before we kill it
241
 
            var tmp = last_sel;
242
 
        last_sel = sel;
243
 
 
244
 
        // this is an optimization: if we've added components, no need
245
 
        // to remerge them; just merge the new ones with the existing
246
 
        // options.
247
 
 
248
 
        if ( ( tmp ) && ( tmp.length < sel.length ) ) {
249
 
            sel = fake_diff_array(sel, tmp);
250
 
            is_diff = 1;
251
 
        }
252
 
    }
253
 
 
254
 
    // do the actual fill/update
255
 
    updateSelect( cpts, sel, f[componentfield], is_diff, single, blank );
256
 
}