comparison .svn/pristine/8e/8e5c0db7b703cf6a4ad1247955b7ea8792cd025e.svn-base @ 1298:4f746d8966dd redmine_2.3_integration

Merge from redmine-2.3 branch to create new branch redmine-2.3-integration
author Chris Cannam
date Fri, 14 Jun 2013 09:28:30 +0100
parents 622f24f53b42
children
comparison
equal deleted inserted replaced
1297:0a574315af3e 1298:4f746d8966dd
1 /* Redmine - project management software
2 Copyright (C) 2006-2013 Jean-Philippe Lang */
3
4 function checkAll(id, checked) {
5 if (checked) {
6 $('#'+id).find('input[type=checkbox]').attr('checked', true);
7 } else {
8 $('#'+id).find('input[type=checkbox]').removeAttr('checked');
9 }
10 }
11
12 function toggleCheckboxesBySelector(selector) {
13 var all_checked = true;
14 $(selector).each(function(index) {
15 if (!$(this).is(':checked')) { all_checked = false; }
16 });
17 $(selector).attr('checked', !all_checked);
18 }
19
20 function showAndScrollTo(id, focus) {
21 $('#'+id).show();
22 if (focus !== null) {
23 $('#'+focus).focus();
24 }
25 $('html, body').animate({scrollTop: $('#'+id).offset().top}, 100);
26 }
27
28 function toggleRowGroup(el) {
29 var tr = $(el).parents('tr').first();
30 var n = tr.next();
31 tr.toggleClass('open');
32 while (n.length && !n.hasClass('group')) {
33 n.toggle();
34 n = n.next('tr');
35 }
36 }
37
38 function collapseAllRowGroups(el) {
39 var tbody = $(el).parents('tbody').first();
40 tbody.children('tr').each(function(index) {
41 if ($(this).hasClass('group')) {
42 $(this).removeClass('open');
43 } else {
44 $(this).hide();
45 }
46 });
47 }
48
49 function expandAllRowGroups(el) {
50 var tbody = $(el).parents('tbody').first();
51 tbody.children('tr').each(function(index) {
52 if ($(this).hasClass('group')) {
53 $(this).addClass('open');
54 } else {
55 $(this).show();
56 }
57 });
58 }
59
60 function toggleAllRowGroups(el) {
61 var tr = $(el).parents('tr').first();
62 if (tr.hasClass('open')) {
63 collapseAllRowGroups(el);
64 } else {
65 expandAllRowGroups(el);
66 }
67 }
68
69 function toggleFieldset(el) {
70 var fieldset = $(el).parents('fieldset').first();
71 fieldset.toggleClass('collapsed');
72 fieldset.children('div').toggle();
73 }
74
75 function hideFieldset(el) {
76 var fieldset = $(el).parents('fieldset').first();
77 fieldset.toggleClass('collapsed');
78 fieldset.children('div').hide();
79 }
80
81 function initFilters(){
82 $('#add_filter_select').change(function(){
83 addFilter($(this).val(), '', []);
84 });
85 $('#filters-table td.field input[type=checkbox]').each(function(){
86 toggleFilter($(this).val());
87 });
88 $('#filters-table td.field input[type=checkbox]').live('click',function(){
89 toggleFilter($(this).val());
90 });
91 $('#filters-table .toggle-multiselect').live('click',function(){
92 toggleMultiSelect($(this).siblings('select'));
93 });
94 $('#filters-table input[type=text]').live('keypress', function(e){
95 if (e.keyCode == 13) submit_query_form("query_form");
96 });
97 }
98
99 function addFilter(field, operator, values) {
100 var fieldId = field.replace('.', '_');
101 var tr = $('#tr_'+fieldId);
102 if (tr.length > 0) {
103 tr.show();
104 } else {
105 buildFilterRow(field, operator, values);
106 }
107 $('#cb_'+fieldId).attr('checked', true);
108 toggleFilter(field);
109 $('#add_filter_select').val('').children('option').each(function(){
110 if ($(this).attr('value') == field) {
111 $(this).attr('disabled', true);
112 }
113 });
114 }
115
116 function buildFilterRow(field, operator, values) {
117 var fieldId = field.replace('.', '_');
118 var filterTable = $("#filters-table");
119 var filterOptions = availableFilters[field];
120 var operators = operatorByType[filterOptions['type']];
121 var filterValues = filterOptions['values'];
122 var i, select;
123
124 var tr = $('<tr class="filter">').attr('id', 'tr_'+fieldId).html(
125 '<td class="field"><input checked="checked" id="cb_'+fieldId+'" name="f[]" value="'+field+'" type="checkbox"><label for="cb_'+fieldId+'"> '+filterOptions['name']+'</label></td>' +
126 '<td class="operator"><select id="operators_'+fieldId+'" name="op['+field+']"></td>' +
127 '<td class="values"></td>'
128 );
129 filterTable.append(tr);
130
131 select = tr.find('td.operator select');
132 for (i=0;i<operators.length;i++){
133 var option = $('<option>').val(operators[i]).text(operatorLabels[operators[i]]);
134 if (operators[i] == operator) { option.attr('selected', true); }
135 select.append(option);
136 }
137 select.change(function(){ toggleOperator(field); });
138
139 switch (filterOptions['type']){
140 case "list":
141 case "list_optional":
142 case "list_status":
143 case "list_subprojects":
144 tr.find('td.values').append(
145 '<span style="display:none;"><select class="value" id="values_'+fieldId+'_1" name="v['+field+'][]"></select>' +
146 ' <span class="toggle-multiselect">&nbsp;</span></span>'
147 );
148 select = tr.find('td.values select');
149 if (values.length > 1) { select.attr('multiple', true); }
150 for (i=0;i<filterValues.length;i++){
151 var filterValue = filterValues[i];
152 var option = $('<option>');
153 if ($.isArray(filterValue)) {
154 option.val(filterValue[1]).text(filterValue[0]);
155 if ($.inArray(filterValue[1], values) > -1) {option.attr('selected', true);}
156 } else {
157 option.val(filterValue).text(filterValue);
158 if ($.inArray(filterValue, values) > -1) {option.attr('selected', true);}
159 }
160 select.append(option);
161 }
162 break;
163 case "date":
164 case "date_past":
165 tr.find('td.values').append(
166 '<span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_1" size="10" class="value date_value" /></span>' +
167 ' <span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_2" size="10" class="value date_value" /></span>' +
168 ' <span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'" size="3" class="value" /> '+labelDayPlural+'</span>'
169 );
170 $('#values_'+fieldId+'_1').val(values[0]).datepicker(datepickerOptions);
171 $('#values_'+fieldId+'_2').val(values[1]).datepicker(datepickerOptions);
172 $('#values_'+fieldId).val(values[0]);
173 break;
174 case "string":
175 case "text":
176 tr.find('td.values').append(
177 '<span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'" size="30" class="value" /></span>'
178 );
179 $('#values_'+fieldId).val(values[0]);
180 break;
181 case "relation":
182 tr.find('td.values').append(
183 '<span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'" size="6" class="value" /></span>' +
184 '<span style="display:none;"><select class="value" name="v['+field+'][]" id="values_'+fieldId+'_1"></select></span>'
185 );
186 $('#values_'+fieldId).val(values[0]);
187 select = tr.find('td.values select');
188 for (i=0;i<allProjects.length;i++){
189 var filterValue = allProjects[i];
190 var option = $('<option>');
191 option.val(filterValue[1]).text(filterValue[0]);
192 if (values[0] == filterValue[1]) { option.attr('selected', true); }
193 select.append(option);
194 }
195 case "integer":
196 case "float":
197 tr.find('td.values').append(
198 '<span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_1" size="6" class="value" /></span>' +
199 ' <span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_2" size="6" class="value" /></span>'
200 );
201 $('#values_'+fieldId+'_1').val(values[0]);
202 $('#values_'+fieldId+'_2').val(values[1]);
203 break;
204 }
205 }
206
207 function toggleFilter(field) {
208 var fieldId = field.replace('.', '_');
209 if ($('#cb_' + fieldId).is(':checked')) {
210 $("#operators_" + fieldId).show().removeAttr('disabled');
211 toggleOperator(field);
212 } else {
213 $("#operators_" + fieldId).hide().attr('disabled', true);
214 enableValues(field, []);
215 }
216 }
217
218 function enableValues(field, indexes) {
219 var fieldId = field.replace('.', '_');
220 $('#tr_'+fieldId+' td.values .value').each(function(index) {
221 if ($.inArray(index, indexes) >= 0) {
222 $(this).removeAttr('disabled');
223 $(this).parents('span').first().show();
224 } else {
225 $(this).val('');
226 $(this).attr('disabled', true);
227 $(this).parents('span').first().hide();
228 }
229
230 if ($(this).hasClass('group')) {
231 $(this).addClass('open');
232 } else {
233 $(this).show();
234 }
235 });
236 }
237
238 function toggleOperator(field) {
239 var fieldId = field.replace('.', '_');
240 var operator = $("#operators_" + fieldId);
241 switch (operator.val()) {
242 case "!*":
243 case "*":
244 case "t":
245 case "ld":
246 case "w":
247 case "lw":
248 case "l2w":
249 case "m":
250 case "lm":
251 case "y":
252 case "o":
253 case "c":
254 enableValues(field, []);
255 break;
256 case "><":
257 enableValues(field, [0,1]);
258 break;
259 case "<t+":
260 case ">t+":
261 case "><t+":
262 case "t+":
263 case ">t-":
264 case "<t-":
265 case "><t-":
266 case "t-":
267 enableValues(field, [2]);
268 break;
269 case "=p":
270 case "=!p":
271 case "!p":
272 enableValues(field, [1]);
273 break;
274 default:
275 enableValues(field, [0]);
276 break;
277 }
278 }
279
280 function toggleMultiSelect(el) {
281 if (el.attr('multiple')) {
282 el.removeAttr('multiple');
283 } else {
284 el.attr('multiple', true);
285 }
286 }
287
288 function submit_query_form(id) {
289 selectAllOptions("selected_columns");
290 $('#'+id).submit();
291 }
292
293 function showTab(name) {
294 $('div#content .tab-content').hide();
295 $('div.tabs a').removeClass('selected');
296 $('#tab-content-' + name).show();
297 $('#tab-' + name).addClass('selected');
298 return false;
299 }
300
301 function moveTabRight(el) {
302 var lis = $(el).parents('div.tabs').first().find('ul').children();
303 var tabsWidth = 0;
304 var i = 0;
305 lis.each(function(){
306 if ($(this).is(':visible')) {
307 tabsWidth += $(this).width() + 6;
308 }
309 });
310 if (tabsWidth < $(el).parents('div.tabs').first().width() - 60) { return; }
311 while (i<lis.length && !lis.eq(i).is(':visible')) { i++; }
312 lis.eq(i).hide();
313 }
314
315 function moveTabLeft(el) {
316 var lis = $(el).parents('div.tabs').first().find('ul').children();
317 var i = 0;
318 while (i<lis.length && !lis.eq(i).is(':visible')) { i++; }
319 if (i>0) {
320 lis.eq(i-1).show();
321 }
322 }
323
324 function displayTabsButtons() {
325 var lis;
326 var tabsWidth = 0;
327 var el;
328 $('div.tabs').each(function() {
329 el = $(this);
330 lis = el.find('ul').children();
331 lis.each(function(){
332 if ($(this).is(':visible')) {
333 tabsWidth += $(this).width() + 6;
334 }
335 });
336 if ((tabsWidth < el.width() - 60) && (lis.first().is(':visible'))) {
337 el.find('div.tabs-buttons').hide();
338 } else {
339 el.find('div.tabs-buttons').show();
340 }
341 });
342 }
343
344 function setPredecessorFieldsVisibility() {
345 var relationType = $('#relation_relation_type');
346 if (relationType.val() == "precedes" || relationType.val() == "follows") {
347 $('#predecessor_fields').show();
348 } else {
349 $('#predecessor_fields').hide();
350 }
351 }
352
353 function showModal(id, width) {
354 var el = $('#'+id).first();
355 if (el.length === 0 || el.is(':visible')) {return;}
356 var title = el.find('h3.title').text();
357 el.dialog({
358 width: width,
359 modal: true,
360 resizable: false,
361 dialogClass: 'modal',
362 title: title
363 });
364 el.find("input[type=text], input[type=submit]").first().focus();
365 }
366
367 function hideModal(el) {
368 var modal;
369 if (el) {
370 modal = $(el).parents('.ui-dialog-content');
371 } else {
372 modal = $('#ajax-modal');
373 }
374 modal.dialog("close");
375 }
376
377 function submitPreview(url, form, target) {
378 $.ajax({
379 url: url,
380 type: 'post',
381 data: $('#'+form).serialize(),
382 success: function(data){
383 $('#'+target).html(data);
384 }
385 });
386 }
387
388 function collapseScmEntry(id) {
389 $('.'+id).each(function() {
390 if ($(this).hasClass('open')) {
391 collapseScmEntry($(this).attr('id'));
392 }
393 $(this).hide();
394 });
395 $('#'+id).removeClass('open');
396 }
397
398 function expandScmEntry(id) {
399 $('.'+id).each(function() {
400 $(this).show();
401 if ($(this).hasClass('loaded') && !$(this).hasClass('collapsed')) {
402 expandScmEntry($(this).attr('id'));
403 }
404 });
405 $('#'+id).addClass('open');
406 }
407
408 function scmEntryClick(id, url) {
409 el = $('#'+id);
410 if (el.hasClass('open')) {
411 collapseScmEntry(id);
412 el.addClass('collapsed');
413 return false;
414 } else if (el.hasClass('loaded')) {
415 expandScmEntry(id);
416 el.removeClass('collapsed');
417 return false;
418 }
419 if (el.hasClass('loading')) {
420 return false;
421 }
422 el.addClass('loading');
423 $.ajax({
424 url: url,
425 success: function(data){
426 el.after(data);
427 el.addClass('open').addClass('loaded').removeClass('loading');
428 }
429 });
430 return true;
431 }
432
433 function randomKey(size) {
434 var chars = new Array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z');
435 var key = '';
436 for (i = 0; i < size; i++) {
437 key += chars[Math.floor(Math.random() * chars.length)];
438 }
439 return key;
440 }
441
442 // Can't use Rails' remote select because we need the form data
443 function updateIssueFrom(url) {
444 $.ajax({
445 url: url,
446 type: 'post',
447 data: $('#issue-form').serialize()
448 });
449 }
450
451 function updateBulkEditFrom(url) {
452 $.ajax({
453 url: url,
454 type: 'post',
455 data: $('#bulk_edit_form').serialize()
456 });
457 }
458
459 function observeAutocompleteField(fieldId, url, options) {
460 $(document).ready(function() {
461 $('#'+fieldId).autocomplete($.extend({
462 source: url,
463 minLength: 2,
464 search: function(){$('#'+fieldId).addClass('ajax-loading');},
465 response: function(){$('#'+fieldId).removeClass('ajax-loading');}
466 }, options));
467 $('#'+fieldId).addClass('autocomplete');
468 });
469 }
470
471 function observeSearchfield(fieldId, targetId, url) {
472 $('#'+fieldId).each(function() {
473 var $this = $(this);
474 $this.addClass('autocomplete');
475 $this.attr('data-value-was', $this.val());
476 var check = function() {
477 var val = $this.val();
478 if ($this.attr('data-value-was') != val){
479 $this.attr('data-value-was', val);
480 $.ajax({
481 url: url,
482 type: 'get',
483 data: {q: $this.val()},
484 success: function(data){ if(targetId) $('#'+targetId).html(data); },
485 beforeSend: function(){ $this.addClass('ajax-loading'); },
486 complete: function(){ $this.removeClass('ajax-loading'); }
487 });
488 }
489 };
490 var reset = function() {
491 if (timer) {
492 clearInterval(timer);
493 timer = setInterval(check, 300);
494 }
495 };
496 var timer = setInterval(check, 300);
497 $this.bind('keyup click mousemove', reset);
498 });
499 }
500
501 function observeProjectModules() {
502 var f = function() {
503 /* Hides trackers and issues custom fields on the new project form when issue_tracking module is disabled */
504 if ($('#project_enabled_module_names_issue_tracking').attr('checked')) {
505 $('#project_trackers').show();
506 }else{
507 $('#project_trackers').hide();
508 }
509 };
510
511 $(window).load(f);
512 $('#project_enabled_module_names_issue_tracking').change(f);
513 }
514
515 function initMyPageSortable(list, url) {
516 $('#list-'+list).sortable({
517 connectWith: '.block-receiver',
518 tolerance: 'pointer',
519 update: function(){
520 $.ajax({
521 url: url,
522 type: 'post',
523 data: {'blocks': $.map($('#list-'+list).children(), function(el){return $(el).attr('id');})}
524 });
525 }
526 });
527 $("#list-top, #list-left, #list-right").disableSelection();
528 }
529
530 var warnLeavingUnsavedMessage;
531 function warnLeavingUnsaved(message) {
532 warnLeavingUnsavedMessage = message;
533
534 $('form').submit(function(){
535 $('textarea').removeData('changed');
536 });
537 $('textarea').change(function(){
538 $(this).data('changed', 'changed');
539 });
540 window.onbeforeunload = function(){
541 var warn = false;
542 $('textarea').blur().each(function(){
543 if ($(this).data('changed')) {
544 warn = true;
545 }
546 });
547 if (warn) {return warnLeavingUnsavedMessage;}
548 };
549 }
550
551 function setupAjaxIndicator() {
552
553 $('#ajax-indicator').bind('ajaxSend', function(event, xhr, settings) {
554
555 if ($('.ajax-loading').length === 0 && settings.contentType != 'application/octet-stream') {
556 $('#ajax-indicator').show();
557 }
558 });
559
560 $('#ajax-indicator').bind('ajaxStop', function() {
561 $('#ajax-indicator').hide();
562 });
563 }
564
565 function hideOnLoad() {
566 $('.hol').hide();
567 }
568
569 function addFormObserversForDoubleSubmit() {
570 $('form[method=post]').each(function() {
571 if (!$(this).hasClass('multiple-submit')) {
572 $(this).submit(function(form_submission) {
573 if ($(form_submission.target).attr('data-submitted')) {
574 form_submission.preventDefault();
575 } else {
576 $(form_submission.target).attr('data-submitted', true);
577 }
578 });
579 }
580 });
581 }
582
583 function blockEventPropagation(event) {
584 event.stopPropagation();
585 event.preventDefault();
586 }
587
588 $(document).ready(setupAjaxIndicator);
589 $(document).ready(hideOnLoad);
590 $(document).ready(addFormObserversForDoubleSubmit);