To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

Statistics Download as Zip
| Branch: | Tag: | Revision:

root / public / javascripts / application.js @ 1586:d0d59d12db94

History | View | Annotate | Download (17.1 KB)

1
/* Redmine - project management software
2
   Copyright (C) 2006-2014  Jean-Philippe Lang */
3

    
4
function checkAll(id, checked) {
5
  $('#'+id).find('input[type=checkbox]:enabled').attr('checked', checked);
6
}
7

    
8
function toggleCheckboxesBySelector(selector) {
9
  var all_checked = true;
10
  $(selector).each(function(index) {
11
    if (!$(this).is(':checked')) { all_checked = false; }
12
  });
13
  $(selector).attr('checked', !all_checked);
14
}
15

    
16
function showAndScrollTo(id, focus) {
17
  $('#'+id).show();
18
  if (focus !== null) {
19
    $('#'+focus).focus();
20
  }
21
  $('html, body').animate({scrollTop: $('#'+id).offset().top}, 100);
22
}
23

    
24
function toggleRowGroup(el) {
25
  var tr = $(el).parents('tr').first();
26
  var n = tr.next();
27
  tr.toggleClass('open');
28
  while (n.length && !n.hasClass('group')) {
29
    n.toggle();
30
    n = n.next('tr');
31
  }
32
}
33

    
34
function collapseAllRowGroups(el) {
35
  var tbody = $(el).parents('tbody').first();
36
  tbody.children('tr').each(function(index) {
37
    if ($(this).hasClass('group')) {
38
      $(this).removeClass('open');
39
    } else {
40
      $(this).hide();
41
    }
42
  });
43
}
44

    
45
function expandAllRowGroups(el) {
46
  var tbody = $(el).parents('tbody').first();
47
  tbody.children('tr').each(function(index) {
48
    if ($(this).hasClass('group')) {
49
      $(this).addClass('open');
50
    } else {
51
      $(this).show();
52
    }
53
  });
54
}
55

    
56
function toggleAllRowGroups(el) {
57
  var tr = $(el).parents('tr').first();
58
  if (tr.hasClass('open')) {
59
    collapseAllRowGroups(el);
60
  } else {
61
    expandAllRowGroups(el);
62
  }
63
}
64

    
65
function toggleFieldset(el) {
66
  var fieldset = $(el).parents('fieldset').first();
67
  fieldset.toggleClass('collapsed');
68
  fieldset.children('div').toggle();
69
}
70

    
71
function hideFieldset(el) {
72
  var fieldset = $(el).parents('fieldset').first();
73
  fieldset.toggleClass('collapsed');
74
  fieldset.children('div').hide();
75
}
76

    
77
function initFilters() {
78
  $('#add_filter_select').change(function() {
79
    addFilter($(this).val(), '', []);
80
  });
81
  $('#filters-table td.field input[type=checkbox]').each(function() {
82
    toggleFilter($(this).val());
83
  });
84
  $('#filters-table td.field input[type=checkbox]').live('click', function() {
85
    toggleFilter($(this).val());
86
  });
87
  $('#filters-table .toggle-multiselect').live('click', function() {
88
    toggleMultiSelect($(this).siblings('select'));
89
  });
90
  $('#filters-table input[type=text]').live('keypress', function(e) {
91
    if (e.keyCode == 13) submit_query_form("query_form");
92
  });
93
}
94

    
95
function addFilter(field, operator, values) {
96
  var fieldId = field.replace('.', '_');
97
  var tr = $('#tr_'+fieldId);
98
  if (tr.length > 0) {
99
    tr.show();
100
  } else {
101
    buildFilterRow(field, operator, values);
102
  }
103
  $('#cb_'+fieldId).attr('checked', true);
104
  toggleFilter(field);
105
  $('#add_filter_select').val('').children('option').each(function() {
106
    if ($(this).attr('value') == field) {
107
      $(this).attr('disabled', true);
108
    }
109
  });
110
}
111

    
112
function buildFilterRow(field, operator, values) {
113
  var fieldId = field.replace('.', '_');
114
  var filterTable = $("#filters-table");
115
  var filterOptions = availableFilters[field];
116
  if (!filterOptions) return;
117
  var operators = operatorByType[filterOptions['type']];
118
  var filterValues = filterOptions['values'];
119
  var i, select;
120

    
121
  var tr = $('<tr class="filter">').attr('id', 'tr_'+fieldId).html(
122
    '<td class="field"><input checked="checked" id="cb_'+fieldId+'" name="f[]" value="'+field+'" type="checkbox"><label for="cb_'+fieldId+'"> '+filterOptions['name']+'</label></td>' +
123
    '<td class="operator"><select id="operators_'+fieldId+'" name="op['+field+']"></td>' +
124
    '<td class="values"></td>'
125
  );
126
  filterTable.append(tr);
127

    
128
  select = tr.find('td.operator select');
129
  for (i = 0; i < operators.length; i++) {
130
    var option = $('<option>').val(operators[i]).text(operatorLabels[operators[i]]);
131
    if (operators[i] == operator) { option.attr('selected', true); }
132
    select.append(option);
133
  }
134
  select.change(function(){ toggleOperator(field); });
135

    
136
  switch (filterOptions['type']) {
137
  case "list":
138
  case "list_optional":
139
  case "list_status":
140
  case "list_subprojects":
141
    tr.find('td.values').append(
142
      '<span style="display:none;"><select class="value" id="values_'+fieldId+'_1" name="v['+field+'][]"></select>' +
143
      ' <span class="toggle-multiselect">&nbsp;</span></span>'
144
    );
145
    select = tr.find('td.values select');
146
    if (values.length > 1) { select.attr('multiple', true); }
147
    for (i = 0; i < filterValues.length; i++) {
148
      var filterValue = filterValues[i];
149
      var option = $('<option>');
150
      if ($.isArray(filterValue)) {
151
        option.val(filterValue[1]).text(filterValue[0]);
152
        if ($.inArray(filterValue[1], values) > -1) {option.attr('selected', true);}
153
      } else {
154
        option.val(filterValue).text(filterValue);
155
        if ($.inArray(filterValue, values) > -1) {option.attr('selected', true);}
156
      }
157
      select.append(option);
158
    }
159
    break;
160
  case "date":
161
  case "date_past":
162
    tr.find('td.values').append(
163
      '<span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_1" size="10" class="value date_value" /></span>' +
164
      ' <span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_2" size="10" class="value date_value" /></span>' +
165
      ' <span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'" size="3" class="value" /> '+labelDayPlural+'</span>'
166
    );
167
    $('#values_'+fieldId+'_1').val(values[0]).datepicker(datepickerOptions);
168
    $('#values_'+fieldId+'_2').val(values[1]).datepicker(datepickerOptions);
169
    $('#values_'+fieldId).val(values[0]);
170
    break;
171
  case "string":
172
  case "text":
173
    tr.find('td.values').append(
174
      '<span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'" size="30" class="value" /></span>'
175
    );
176
    $('#values_'+fieldId).val(values[0]);
177
    break;
178
  case "relation":
179
    tr.find('td.values').append(
180
      '<span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'" size="6" class="value" /></span>' +
181
      '<span style="display:none;"><select class="value" name="v['+field+'][]" id="values_'+fieldId+'_1"></select></span>'
182
    );
183
    $('#values_'+fieldId).val(values[0]);
184
    select = tr.find('td.values select');
185
    for (i = 0; i < allProjects.length; i++) {
186
      var filterValue = allProjects[i];
187
      var option = $('<option>');
188
      option.val(filterValue[1]).text(filterValue[0]);
189
      if (values[0] == filterValue[1]) { option.attr('selected', true); }
190
      select.append(option);
191
    }
192
  case "integer":
193
  case "float":
194
    tr.find('td.values').append(
195
      '<span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_1" size="6" class="value" /></span>' +
196
      ' <span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_2" size="6" class="value" /></span>'
197
    );
198
    $('#values_'+fieldId+'_1').val(values[0]);
199
    $('#values_'+fieldId+'_2').val(values[1]);
200
    break;
201
  }
202
}
203

    
204
function toggleFilter(field) {
205
  var fieldId = field.replace('.', '_');
206
  if ($('#cb_' + fieldId).is(':checked')) {
207
    $("#operators_" + fieldId).show().removeAttr('disabled');
208
    toggleOperator(field);
209
  } else {
210
    $("#operators_" + fieldId).hide().attr('disabled', true);
211
    enableValues(field, []);
212
  }
213
}
214

    
215
function enableValues(field, indexes) {
216
  var fieldId = field.replace('.', '_');
217
  $('#tr_'+fieldId+' td.values .value').each(function(index) {
218
    if ($.inArray(index, indexes) >= 0) {
219
      $(this).removeAttr('disabled');
220
      $(this).parents('span').first().show();
221
    } else {
222
      $(this).val('');
223
      $(this).attr('disabled', true);
224
      $(this).parents('span').first().hide();
225
    }
226

    
227
    if ($(this).hasClass('group')) {
228
      $(this).addClass('open');
229
    } else {
230
      $(this).show();
231
    }
232
  });
233
}
234

    
235
function toggleOperator(field) {
236
  var fieldId = field.replace('.', '_');
237
  var operator = $("#operators_" + fieldId);
238
  switch (operator.val()) {
239
    case "!*":
240
    case "*":
241
    case "t":
242
    case "ld":
243
    case "w":
244
    case "lw":
245
    case "l2w":
246
    case "m":
247
    case "lm":
248
    case "y":
249
    case "o":
250
    case "c":
251
      enableValues(field, []);
252
      break;
253
    case "><":
254
      enableValues(field, [0,1]);
255
      break;
256
    case "<t+":
257
    case ">t+":
258
    case "><t+":
259
    case "t+":
260
    case ">t-":
261
    case "<t-":
262
    case "><t-":
263
    case "t-":
264
      enableValues(field, [2]);
265
      break;
266
    case "=p":
267
    case "=!p":
268
    case "!p":
269
      enableValues(field, [1]);
270
      break;
271
    default:
272
      enableValues(field, [0]);
273
      break;
274
  }
275
}
276

    
277
function toggleMultiSelect(el) {
278
  if (el.attr('multiple')) {
279
    el.removeAttr('multiple');
280
    el.attr('size', 1);
281
  } else {
282
    el.attr('multiple', true);
283
    if (el.children().length > 10)
284
      el.attr('size', 10);
285
    else
286
      el.attr('size', 4);
287
  }
288
}
289

    
290
function submit_query_form(id) {
291
  selectAllOptions("selected_columns");
292
  $('#'+id).submit();
293
}
294

    
295
function showTab(name, url) {
296
  $('div#content .tab-content').hide();
297
  $('div.tabs a').removeClass('selected');
298
  $('#tab-content-' + name).show();
299
  $('#tab-' + name).addClass('selected');
300
  //replaces current URL with the "href" attribute of the current link
301
  //(only triggered if supported by browser)
302
  if ("replaceState" in window.history) {
303
    window.history.replaceState(null, document.title, url);
304
  }
305
  return false;
306
}
307

    
308
function moveTabRight(el) {
309
  var lis = $(el).parents('div.tabs').first().find('ul').children();
310
  var tabsWidth = 0;
311
  var i = 0;
312
  lis.each(function() {
313
    if ($(this).is(':visible')) {
314
      tabsWidth += $(this).width() + 6;
315
    }
316
  });
317
  if (tabsWidth < $(el).parents('div.tabs').first().width() - 60) { return; }
318
  while (i<lis.length && !lis.eq(i).is(':visible')) { i++; }
319
  lis.eq(i).hide();
320
}
321

    
322
function moveTabLeft(el) {
323
  var lis = $(el).parents('div.tabs').first().find('ul').children();
324
  var i = 0;
325
  while (i < lis.length && !lis.eq(i).is(':visible')) { i++; }
326
  if (i > 0) {
327
    lis.eq(i-1).show();
328
  }
329
}
330

    
331
function displayTabsButtons() {
332
  var lis;
333
  var tabsWidth = 0;
334
  var el;
335
  $('div.tabs').each(function() {
336
    el = $(this);
337
    lis = el.find('ul').children();
338
    lis.each(function(){
339
      if ($(this).is(':visible')) {
340
        tabsWidth += $(this).width() + 6;
341
      }
342
    });
343
    if ((tabsWidth < el.width() - 60) && (lis.first().is(':visible'))) {
344
      el.find('div.tabs-buttons').hide();
345
    } else {
346
      el.find('div.tabs-buttons').show();
347
    }
348
  });
349
}
350

    
351
function setPredecessorFieldsVisibility() {
352
  var relationType = $('#relation_relation_type');
353
  if (relationType.val() == "precedes" || relationType.val() == "follows") {
354
    $('#predecessor_fields').show();
355
  } else {
356
    $('#predecessor_fields').hide();
357
  }
358
}
359

    
360
function showModal(id, width) {
361
  var el = $('#'+id).first();
362
  if (el.length === 0 || el.is(':visible')) {return;}
363
  var title = el.find('h3.title').text();
364
  el.dialog({
365
    width: width,
366
    modal: true,
367
    resizable: false,
368
    dialogClass: 'modal',
369
    title: title
370
  });
371
  el.find("input[type=text], input[type=submit]").first().focus();
372
}
373

    
374
function hideModal(el) {
375
  var modal;
376
  if (el) {
377
    modal = $(el).parents('.ui-dialog-content');
378
  } else {
379
    modal = $('#ajax-modal');
380
  }
381
  modal.dialog("close");
382
}
383

    
384
function submitPreview(url, form, target) {
385
  $.ajax({
386
    url: url,
387
    type: 'post',
388
    data: $('#'+form).serialize(),
389
    success: function(data){
390
      $('#'+target).html(data);
391
    }
392
  });
393
}
394

    
395
function collapseScmEntry(id) {
396
  $('.'+id).each(function() {
397
    if ($(this).hasClass('open')) {
398
      collapseScmEntry($(this).attr('id'));
399
    }
400
    $(this).hide();
401
  });
402
  $('#'+id).removeClass('open');
403
}
404

    
405
function expandScmEntry(id) {
406
  $('.'+id).each(function() {
407
    $(this).show();
408
    if ($(this).hasClass('loaded') && !$(this).hasClass('collapsed')) {
409
      expandScmEntry($(this).attr('id'));
410
    }
411
  });
412
  $('#'+id).addClass('open');
413
}
414

    
415
function scmEntryClick(id, url) {
416
    var el = $('#'+id);
417
    if (el.hasClass('open')) {
418
        collapseScmEntry(id);
419
        el.addClass('collapsed');
420
        return false;
421
    } else if (el.hasClass('loaded')) {
422
        expandScmEntry(id);
423
        el.removeClass('collapsed');
424
        return false;
425
    }
426
    if (el.hasClass('loading')) {
427
        return false;
428
    }
429
    el.addClass('loading');
430
    $.ajax({
431
      url: url,
432
      success: function(data) {
433
        el.after(data);
434
        el.addClass('open').addClass('loaded').removeClass('loading');
435
      }
436
    });
437
    return true;
438
}
439

    
440
function randomKey(size) {
441
  var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
442
  var key = '';
443
  for (var i = 0; i < size; i++) {
444
    key += chars.charAt(Math.floor(Math.random() * chars.length));
445
  }
446
  return key;
447
}
448

    
449
function updateIssueFrom(url) {
450
  $('#all_attributes input, #all_attributes textarea, #all_attributes select').each(function(){
451
    $(this).data('valuebeforeupdate', $(this).val());
452
  });
453
  $.ajax({
454
    url: url,
455
    type: 'post',
456
    data: $('#issue-form').serialize()
457
  });
458
}
459

    
460
function replaceIssueFormWith(html){
461
  var replacement = $(html);
462
  $('#all_attributes input, #all_attributes textarea, #all_attributes select').each(function(){
463
    var object_id = $(this).attr('id');
464
    if (object_id && $(this).data('valuebeforeupdate')!=$(this).val()) {
465
      replacement.find('#'+object_id).val($(this).val());
466
    }
467
  });
468
  $('#all_attributes').empty();
469
  $('#all_attributes').prepend(replacement);
470
}
471

    
472
function updateBulkEditFrom(url) {
473
  $.ajax({
474
    url: url,
475
    type: 'post',
476
    data: $('#bulk_edit_form').serialize()
477
  });
478
}
479

    
480
function observeAutocompleteField(fieldId, url, options) {
481
  $(document).ready(function() {
482
    $('#'+fieldId).autocomplete($.extend({
483
      source: url,
484
      minLength: 2,
485
      search: function(){$('#'+fieldId).addClass('ajax-loading');},
486
      response: function(){$('#'+fieldId).removeClass('ajax-loading');}
487
    }, options));
488
    $('#'+fieldId).addClass('autocomplete');
489
  });
490
}
491

    
492
function observeSearchfield(fieldId, targetId, url) {
493
  $('#'+fieldId).each(function() {
494
    var $this = $(this);
495
    $this.addClass('autocomplete');
496
    $this.attr('data-value-was', $this.val());
497
    var check = function() {
498
      var val = $this.val();
499
      if ($this.attr('data-value-was') != val){
500
        $this.attr('data-value-was', val);
501
        $.ajax({
502
          url: url,
503
          type: 'get',
504
          data: {q: $this.val()},
505
          success: function(data){ if(targetId) $('#'+targetId).html(data); },
506
          beforeSend: function(){ $this.addClass('ajax-loading'); },
507
          complete: function(){ $this.removeClass('ajax-loading'); }
508
        });
509
      }
510
    };
511
    var reset = function() {
512
      if (timer) {
513
        clearInterval(timer);
514
        timer = setInterval(check, 300);
515
      }
516
    };
517
    var timer = setInterval(check, 300);
518
    $this.bind('keyup click mousemove', reset);
519
  });
520
}
521

    
522
function initMyPageSortable(list, url) {
523
  $('#list-'+list).sortable({
524
    connectWith: '.block-receiver',
525
    tolerance: 'pointer',
526
    update: function(){
527
      $.ajax({
528
        url: url,
529
        type: 'post',
530
        data: {'blocks': $.map($('#list-'+list).children(), function(el){return $(el).attr('id');})}
531
      });
532
    }
533
  });
534
  $("#list-top, #list-left, #list-right").disableSelection();
535
}
536

    
537
var warnLeavingUnsavedMessage;
538
function warnLeavingUnsaved(message) {
539
  warnLeavingUnsavedMessage = message;
540
  $('form').live('submit', function(){
541
    $('textarea').removeData('changed');
542
  });
543
  $('textarea').live('change', function(){
544
    $(this).data('changed', 'changed');
545
  });
546
  window.onbeforeunload = function(){
547
    var warn = false;
548
    $('textarea').blur().each(function(){
549
      if ($(this).data('changed')) {
550
        warn = true;
551
      }
552
    });
553
    if (warn) {return warnLeavingUnsavedMessage;}
554
  };
555
}
556

    
557
function setupAjaxIndicator() {
558
  $('#ajax-indicator').bind('ajaxSend', function(event, xhr, settings) {
559
    if ($('.ajax-loading').length === 0 && settings.contentType != 'application/octet-stream') {
560
      $('#ajax-indicator').show();
561
    }
562
  });
563
  $('#ajax-indicator').bind('ajaxStop', function() {
564
    $('#ajax-indicator').hide();
565
  });
566
}
567

    
568
function hideOnLoad() {
569
  $('.hol').hide();
570
}
571

    
572
function addFormObserversForDoubleSubmit() {
573
  $('form[method=post]').each(function() {
574
    if (!$(this).hasClass('multiple-submit')) {
575
      $(this).submit(function(form_submission) {
576
        if ($(form_submission.target).attr('data-submitted')) {
577
          form_submission.preventDefault();
578
        } else {
579
          $(form_submission.target).attr('data-submitted', true);
580
        }
581
      });
582
    }
583
  });
584
}
585

    
586
function defaultFocus(){
587
  if ($('#content :focus').length == 0) {
588
    $('#content input[type=text], #content textarea').first().focus();
589
  }
590
}
591

    
592
function blockEventPropagation(event) {
593
  event.stopPropagation();
594
  event.preventDefault();
595
}
596

    
597
function toggleDisabledOnChange() {
598
  var checked = $(this).is(':checked');
599
  $($(this).data('disables')).attr('disabled', checked);
600
  $($(this).data('enables')).attr('disabled', !checked);
601
}
602
function toggleDisabledInit() {
603
  $('input[data-disables], input[data-enables]').each(toggleDisabledOnChange);
604
}
605
$(document).ready(function(){
606
  $('#content').on('change', 'input[data-disables], input[data-enables]', toggleDisabledOnChange);
607
  toggleDisabledInit();
608
});
609

    
610
$(document).ready(setupAjaxIndicator);
611
$(document).ready(hideOnLoad);
612
$(document).ready(addFormObserversForDoubleSubmit);
613
$(document).ready(defaultFocus);
614