ea33e520fb493fbd1d929459d6e5360ee0aeba5c
[WebKit-https.git] / BugsSite / js / field.js
1 /* The contents of this file are subject to the Mozilla Public
2  * License Version 1.1 (the "License"); you may not use this file
3  * except in compliance with the License. You may obtain a copy of
4  * the License at http://www.mozilla.org/MPL/
5  *
6  * Software distributed under the License is distributed on an "AS
7  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
8  * implied. See the License for the specific language governing
9  * rights and limitations under the License.
10  *
11  * The Original Code is the Bugzilla Bug Tracking System.
12  *
13  * The Initial Developer of the Original Code is Everything Solved, Inc.
14  * Portions created by Everything Solved are Copyright (C) 2007 Everything
15  * Solved, Inc. All Rights Reserved.
16  *
17  * Contributor(s): Max Kanat-Alexander <mkanat@bugzilla.org>
18  *                 Guy Pyrzak <guy.pyrzak@gmail.com>
19  */
20
21 /* This library assumes that the needed YUI libraries have been loaded 
22    already. */
23
24 function createCalendar(name) {
25     var cal = new YAHOO.widget.Calendar('calendar_' + name, 
26                                         'con_calendar_' + name);
27     YAHOO.bugzilla['calendar_' + name] = cal;
28     var field = document.getElementById(name);
29     cal.selectEvent.subscribe(setFieldFromCalendar, field, false);
30     updateCalendarFromField(field);
31     cal.render();
32 }
33
34 /* The onclick handlers for the button that shows the calendar. */
35 function showCalendar(field_name) {
36     var calendar  = YAHOO.bugzilla["calendar_" + field_name];
37     var field     = document.getElementById(field_name);
38     var button    = document.getElementById('button_calendar_' + field_name);
39
40     bz_overlayBelow(calendar.oDomContainer, field);
41     calendar.show();
42     button.onclick = function() { hideCalendar(field_name); };
43
44     // Because of the way removeListener works, this has to be a function
45     // attached directly to this calendar.
46     calendar.bz_myBodyCloser = function(event) {
47         var container = this.oDomContainer;
48         var target    = YAHOO.util.Event.getTarget(event);
49         if (target != container && target != button
50             && !YAHOO.util.Dom.isAncestor(container, target))
51         {
52             hideCalendar(field_name);
53         }
54     };
55
56     // If somebody clicks outside the calendar, hide it.
57     YAHOO.util.Event.addListener(document.body, 'click', 
58                                  calendar.bz_myBodyCloser, calendar, true);
59
60     // Make Esc close the calendar.
61     calendar.bz_escCal = function (event) {
62         var key = YAHOO.util.Event.getCharCode(event);
63         if (key == 27) {
64             hideCalendar(field_name);
65         }
66     };
67     YAHOO.util.Event.addListener(document.body, 'keydown', calendar.bz_escCal);
68 }
69
70 function hideCalendar(field_name) {
71     var cal = YAHOO.bugzilla["calendar_" + field_name];
72     cal.hide();
73     var button = document.getElementById('button_calendar_' + field_name);
74     button.onclick = function() { showCalendar(field_name); };
75     YAHOO.util.Event.removeListener(document.body, 'click',
76                                     cal.bz_myBodyCloser);
77     YAHOO.util.Event.removeListener(document.body, 'keydown', cal.bz_escCal);
78 }
79
80 /* This is the selectEvent for our Calendar objects on our custom 
81  * DateTime fields.
82  */
83 function setFieldFromCalendar(type, args, date_field) {
84     var dates = args[0];
85     var setDate = dates[0];
86
87     // We can't just write the date straight into the field, because there 
88     // might already be a time there.
89     var timeRe = /\b(\d{1,2}):(\d\d)(?::(\d\d))?/;
90     var currentTime = timeRe.exec(date_field.value);
91     var d = new Date(setDate[0], setDate[1] - 1, setDate[2]);
92     if (currentTime) {
93         d.setHours(currentTime[1], currentTime[2]);
94         if (currentTime[3]) {
95             d.setSeconds(currentTime[3]);
96         }
97     }
98
99     var year = d.getFullYear();
100     // JavaScript's "Date" represents January as 0 and December as 11.
101     var month = d.getMonth() + 1;
102     if (month < 10) month = '0' + String(month);
103     var day = d.getDate();
104     if (day < 10) day = '0' + String(day);
105     var dateStr = year + '-' + month  + '-' + day;
106
107     if (currentTime) {
108         var minutes = d.getMinutes();
109         if (minutes < 10) minutes = '0' + String(minutes);
110         var seconds = d.getSeconds();
111         if (seconds > 0 && seconds < 10) {
112             seconds = '0' + String(seconds);
113         }
114
115         dateStr = dateStr + ' ' + d.getHours() + ':' + minutes;
116         if (seconds) dateStr = dateStr + ':' + seconds;
117     }
118
119     date_field.value = dateStr;
120     hideCalendar(date_field.id);
121 }
122
123 /* Sets the calendar based on the current field value. 
124  */ 
125 function updateCalendarFromField(date_field) {
126     var dateRe = /(\d\d\d\d)-(\d\d?)-(\d\d?)/;
127     var pieces = dateRe.exec(date_field.value);
128     if (pieces) {
129         var cal = YAHOO.bugzilla["calendar_" + date_field.id];
130         cal.select(new Date(pieces[1], pieces[2] - 1, pieces[3]));
131         var selectedArray = cal.getSelectedDates();
132         var selected = selectedArray[0];
133         cal.cfg.setProperty("pagedate", (selected.getMonth() + 1) + '/' 
134                                         + selected.getFullYear());
135         cal.render();
136     }
137 }
138
139
140 /* Hide input fields and show the text with (edit) next to it */  
141 function hideEditableField( container, input, action, field1_id, field2_id, original_value ) {
142     YAHOO.util.Dom.setStyle(container, 'display', 'inline');
143     YAHOO.util.Dom.setStyle(input, 'display', 'none');
144     YAHOO.util.Event.addListener(action, 'click', showEditableField,
145                                  new Array(container, input, field2_id));
146     YAHOO.util.Event.addListener(field1_id + '_nonedit_display', 'click', showEditableField,
147                                  new Array(container, input, field1_id));
148     YAHOO.util.Event.addListener(field2_id + '_nonedit_display', 'click', showEditableField,
149                                  new Array(container, input, field2_id));
150     if(field2_id != ""){
151         YAHOO.util.Event.addListener(window, 'load', checkForChangedFieldValues,
152                         new Array(container, input, field2_id, original_value));
153     }
154 }
155
156 /* showEditableField (e, ContainerInputArray)
157  * Function hides the (edit) link and the text and displays the input
158  *
159  * var e: the event
160  * var ContainerInputArray: An array containing the (edit) and text area and the input being displayed
161  * var ContainerInputArray[0]: the conainer that will be hidden usually shows the (edit) text
162  * var ContainerInputArray[1]: the input area and label that will be displayed
163  * var ContainerInputArray[2]: [optional] the id of the input element to focus
164  *
165  */
166 function showEditableField (e, ContainerInputArray) {
167     var inputs = new Array();
168     var inputArea = YAHOO.util.Dom.get(ContainerInputArray[1]);    
169     if ( ! inputArea ){
170         YAHOO.util.Event.preventDefault(e);
171         return;
172     }
173     YAHOO.util.Dom.setStyle(ContainerInputArray[0], 'display', 'none');
174     YAHOO.util.Dom.setStyle(inputArea, 'display', 'inline');
175     if ( inputArea.tagName.toLowerCase() == "input" ) {
176         inputs.push(inputArea);
177     } else {
178         inputs = inputArea.getElementsByTagName('input');
179     }
180     if ( inputs.length > 0 ) {
181         var elementToFocus = YAHOO.util.Dom.get(ContainerInputArray[2]);
182         if (elementToFocus) {
183             // focus on the requested field
184             elementToFocus.focus();
185             elementToFocus.select();
186         } else {
187             // focus on the first field, this makes it easier to edit
188             inputs[0].focus();
189             inputs[0].select();
190         }
191     }
192     YAHOO.util.Event.preventDefault(e);
193 }
194
195
196 /* checkForChangedFieldValues(e, array )
197  * Function checks if after the autocomplete by the browser if the values match the originals.
198  *   If they don't match then hide the text and show the input so users don't get confused.
199  *
200  * var e: the event
201  * var ContainerInputArray: An array containing the (edit) and text area and the input being displayed
202  * var ContainerInputArray[0]: the conainer that will be hidden usually shows the (edit) text
203  * var ContainerInputArray[1]: the input area and label that will be displayed
204  * var ContainerInputArray[2]: the field that is on the page, might get changed by browser autocomplete 
205  * var ContainerInputArray[3]: the original value from the page loading.
206  *
207  */  
208 function checkForChangedFieldValues(e, ContainerInputArray ) {
209     var el = document.getElementById(ContainerInputArray[2]);
210     var unhide = false;
211     if ( el ) {
212         if ( el.value != ContainerInputArray[3] ||
213             ( el.value == "" && el.id != "alias") ) {
214             unhide = true;
215         }
216         else {
217             var set_default = document.getElementById("set_default_" +
218                                                       ContainerInputArray[2]);
219             if ( set_default ) {
220                 if(set_default.checked){
221                     unhide = true;
222                 }              
223             }
224         }
225     }
226     if(unhide){
227         YAHOO.util.Dom.setStyle(ContainerInputArray[0], 'display', 'none');
228         YAHOO.util.Dom.setStyle(ContainerInputArray[1], 'display', 'inline');
229     }
230
231 }
232
233 function hideAliasAndSummary(short_desc_value, alias_value) {
234     // check the short desc field
235     hideEditableField( 'summary_alias_container','summary_alias_input',
236                        'editme_action', 'alias', 'short_desc', short_desc_value);
237     // check that the alias hasn't changed
238     var bz_alias_check_array = new Array('summary_alias_container',
239                                      'summary_alias_input', 'alias', alias_value);
240     YAHOO.util.Event.addListener( window, 'load', checkForChangedFieldValues,
241                                  bz_alias_check_array);
242 }
243
244 function showPeopleOnChange( field_id_list ) {
245     for(var i = 0; i < field_id_list.length; i++) {
246         YAHOO.util.Event.addListener( field_id_list[i],'change', showEditableField,
247                                       new Array('bz_qa_contact_edit_container',
248                                                 'bz_qa_contact_input'));
249         YAHOO.util.Event.addListener( field_id_list[i],'change',showEditableField,
250                                       new Array('bz_assignee_edit_container',
251                                                 'bz_assignee_input'));
252     }
253 }
254
255 function assignToDefaultOnChange(field_id_list) {
256     showPeopleOnChange( field_id_list );
257     for(var i = 0; i < field_id_list.length; i++) {
258         YAHOO.util.Event.addListener( field_id_list[i],'change', setDefaultCheckbox,
259                                       'set_default_assignee');
260         YAHOO.util.Event.addListener( field_id_list[i],'change',setDefaultCheckbox,
261                                       'set_default_qa_contact');    
262     }
263 }
264
265 function initDefaultCheckbox(field_id){
266     YAHOO.util.Event.addListener( 'set_default_' + field_id,'change', boldOnChange,
267                                   'set_default_' + field_id);
268     YAHOO.util.Event.addListener( window,'load', checkForChangedFieldValues,
269                                   new Array( 'bz_' + field_id + '_edit_container',
270                                              'bz_' + field_id + '_input',
271                                              'set_default_' + field_id ,'1'));
272     
273     YAHOO.util.Event.addListener( window, 'load', boldOnChange,
274                                  'set_default_' + field_id ); 
275 }
276
277 function showHideStatusItems(e, dupArrayInfo) {
278     var el = document.getElementById('bug_status');
279     // finish doing stuff based on the selection.
280     if ( el ) {
281         showDuplicateItem(el);
282         YAHOO.util.Dom.setStyle('resolution_settings', 'display', 'none');
283         if (document.getElementById('resolution_settings_warning')) {
284             YAHOO.util.Dom.setStyle('resolution_settings_warning', 'display', 'none');
285         }
286         YAHOO.util.Dom.setStyle('duplicate_display', 'display', 'none');
287
288         if ( el.value == dupArrayInfo[1] && dupArrayInfo[0] == "is_duplicate" ) {
289             YAHOO.util.Dom.setStyle('resolution_settings', 'display', 'inline');
290             YAHOO.util.Dom.setStyle('resolution_settings_warning', 'display', 'block');  
291         }
292         else if ( bz_isValueInArray(close_status_array, el.value) ) {
293             // hide duplicate and show resolution
294             YAHOO.util.Dom.setStyle('resolution_settings', 'display', 'inline');
295             YAHOO.util.Dom.setStyle('resolution_settings_warning', 'display', 'block');
296         }
297     }
298 }
299
300 function showDuplicateItem(e) {
301     var resolution = document.getElementById('resolution');
302     var bug_status = document.getElementById('bug_status');
303     var dup_id = document.getElementById('dup_id');
304     if (resolution) {
305         if (resolution.value == 'DUPLICATE' && bz_isValueInArray( close_status_array, bug_status.value) ) {
306             // hide resolution show duplicate
307             YAHOO.util.Dom.setStyle('duplicate_settings', 'display', 'inline');
308             YAHOO.util.Dom.setStyle('dup_id_discoverable', 'display', 'none');
309             dup_id.focus();
310             dup_id.select();
311         }
312         else {
313             YAHOO.util.Dom.setStyle('duplicate_settings', 'display', 'none');
314             YAHOO.util.Dom.setStyle('dup_id_discoverable', 'display', 'block');
315             dup_id.blur();
316         }
317     }
318     YAHOO.util.Event.preventDefault(e); //prevents the hyperlink from going to the url in the href.
319 }
320
321 function setResolutionToDuplicate(e, duplicate_or_move_bug_status) {
322     var status = document.getElementById('bug_status');
323     var resolution = document.getElementById('resolution');
324     YAHOO.util.Dom.setStyle('dup_id_discoverable', 'display', 'none');
325     status.value = duplicate_or_move_bug_status;
326     resolution.value = "DUPLICATE";
327     showHideStatusItems("", ["",""]);
328     YAHOO.util.Event.preventDefault(e);
329 }
330
331 function setDefaultCheckbox(e, field_id ) { 
332     var el = document.getElementById(field_id);
333     var elLabel = document.getElementById(field_id + "_label");
334     if( el && elLabel ) {
335         el.checked = "true";
336         YAHOO.util.Dom.setStyle(elLabel, 'font-weight', 'bold');
337     }
338 }
339
340 function boldOnChange(e, field_id){
341     var el = document.getElementById(field_id);
342     var elLabel = document.getElementById(field_id + "_label");
343     if( el && elLabel ) {
344         if( el.checked ){
345             YAHOO.util.Dom.setStyle(elLabel, 'font-weight', 'bold');
346         }
347         else{
348             YAHOO.util.Dom.setStyle(elLabel, 'font-weight', 'normal');
349         }
350     }
351 }