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 @ 1255:90d92ad3fc59

History | View | Annotate | Download (16.6 KB)

1
/* Redmine - project management software
2
   Copyright (C) 2006-2012  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 "w":
246
    case "o":
247
    case "c":
248
      enableValues(field, []);
249
      break;
250
    case "><":
251
      enableValues(field, [0,1]);
252
      break;
253
    case "<t+":
254
    case ">t+":
255
    case "><t+":
256
    case "t+":
257
    case ">t-":
258
    case "<t-":
259
    case "><t-":
260
    case "t-":
261
      enableValues(field, [2]);
262
      break;
263
    case "=p":
264
    case "=!p":
265
    case "!p":
266
      enableValues(field, [1]);
267
      break;
268
    default:
269
      enableValues(field, [0]);
270
      break;
271
  }
272
}
273

    
274
function toggleMultiSelect(el) {
275
  if (el.attr('multiple')) {
276
    el.removeAttr('multiple');
277
  } else {
278
    el.attr('multiple', true);
279
  }
280
}
281

    
282
function submit_query_form(id) {
283
  selectAllOptions("selected_columns");
284
  $('#'+id).submit();
285
}
286

    
287
var fileFieldCount = 1;
288
function addFileField() {
289
  var fields = $('#attachments_fields');
290
  if (fields.children().length >= 10) return false;
291
  fileFieldCount++;
292
  var s = fields.children('span').first().clone();
293
  s.children('input.file').attr('name', "attachments[" + fileFieldCount + "][file]").val('');
294
  s.children('input.description').attr('name', "attachments[" + fileFieldCount + "][description]").val('');
295
  fields.append(s);
296
}
297

    
298
function removeFileField(el) {
299
  var fields = $('#attachments_fields');
300
  var s = $(el).parents('span').first();
301
  if (fields.children().length > 1) {
302
    s.remove();
303
  } else {
304
    s.children('input.file').val('');
305
    s.children('input.description').val('');
306
  }
307
}
308

    
309
function checkFileSize(el, maxSize, message) {
310
  var files = el.files;
311
  if (files) {
312
    for (var i=0; i<files.length; i++) {
313
      if (files[i].size > maxSize) {
314
        alert(message);
315
        el.value = "";
316
      }
317
    }
318
  }
319
}
320

    
321
function showTab(name) {
322
  $('div#content .tab-content').hide();
323
  $('div.tabs a').removeClass('selected');
324
  $('#tab-content-' + name).show();
325
  $('#tab-' + name).addClass('selected');
326
  return false;
327
}
328

    
329
function moveTabRight(el) {
330
  var lis = $(el).parents('div.tabs').first().find('ul').children();
331
  var tabsWidth = 0;
332
  var i = 0;
333
  lis.each(function(){
334
    if ($(this).is(':visible')) {
335
      tabsWidth += $(this).width() + 6;
336
    }
337
  });
338
  if (tabsWidth < $(el).parents('div.tabs').first().width() - 60) { return; }
339
  while (i<lis.length && !lis.eq(i).is(':visible')) { i++; }
340
  lis.eq(i).hide();
341
}
342

    
343
function moveTabLeft(el) {
344
  var lis = $(el).parents('div.tabs').first().find('ul').children();
345
  var i = 0;
346
  while (i<lis.length && !lis.eq(i).is(':visible')) { i++; }
347
  if (i>0) {
348
    lis.eq(i-1).show();
349
  }
350
}
351

    
352
function displayTabsButtons() {
353
  var lis;
354
  var tabsWidth = 0;
355
  var el;
356
  $('div.tabs').each(function() {
357
    el = $(this);
358
    lis = el.find('ul').children();
359
    lis.each(function(){
360
      if ($(this).is(':visible')) {
361
        tabsWidth += $(this).width() + 6;
362
      }
363
    });
364
    if ((tabsWidth < el.width() - 60) && (lis.first().is(':visible'))) {
365
      el.find('div.tabs-buttons').hide();
366
    } else {
367
      el.find('div.tabs-buttons').show();
368
    }
369
  });
370
}
371

    
372
function setPredecessorFieldsVisibility() {
373
  var relationType = $('#relation_relation_type');
374
  if (relationType.val() == "precedes" || relationType.val() == "follows") {
375
    $('#predecessor_fields').show();
376
  } else {
377
    $('#predecessor_fields').hide();
378
  }
379
}
380

    
381
function showModal(id, width) {
382
  var el = $('#'+id).first();
383
  if (el.length == 0 || el.is(':visible')) {return;}
384
  var title = el.find('h3.title').text();
385
  el.dialog({
386
    width: width,
387
    modal: true,
388
    resizable: false,
389
    dialogClass: 'modal',
390
    title: title
391
  });
392
  el.find("input[type=text], input[type=submit]").first().focus();
393
}
394

    
395
function hideModal(el) {
396
  var modal;
397
  if (el) {
398
    modal = $(el).parents('.ui-dialog-content');
399
  } else {
400
    modal = $('#ajax-modal');
401
  }
402
  modal.dialog("close");
403
}
404

    
405
function submitPreview(url, form, target) {
406
  $.ajax({
407
    url: url,
408
    type: 'post',
409
    data: $('#'+form).serialize(),
410
    success: function(data){
411
      $('#'+target).html(data);
412
    }
413
  });
414
}
415

    
416
function collapseScmEntry(id) {
417
  $('.'+id).each(function() {
418
    if ($(this).hasClass('open')) {
419
      collapseScmEntry($(this).attr('id'));
420
    }
421
    $(this).hide();
422
  });
423
  $('#'+id).removeClass('open');
424
}
425

    
426
function expandScmEntry(id) {
427
  $('.'+id).each(function() {
428
    $(this).show();
429
    if ($(this).hasClass('loaded') && !$(this).hasClass('collapsed')) {
430
      expandScmEntry($(this).attr('id'));
431
    }
432
  });
433
  $('#'+id).addClass('open');
434
}
435

    
436
function scmEntryClick(id, url) {
437
    el = $('#'+id);
438
    if (el.hasClass('open')) {
439
        collapseScmEntry(id);
440
        el.addClass('collapsed');
441
        return false;
442
    } else if (el.hasClass('loaded')) {
443
        expandScmEntry(id);
444
        el.removeClass('collapsed');
445
        return false;
446
    }
447
    if (el.hasClass('loading')) {
448
        return false;
449
    }
450
    el.addClass('loading');
451
    $.ajax({
452
      url: url,
453
      success: function(data){
454
        el.after(data);
455
        el.addClass('open').addClass('loaded').removeClass('loading');
456
      }
457
    });
458
    return true;
459
}
460

    
461
function randomKey(size) {
462
  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');
463
  var key = '';
464
  for (i = 0; i < size; i++) {
465
    key += chars[Math.floor(Math.random() * chars.length)];
466
  }
467
  return key;
468
}
469

    
470
// Can't use Rails' remote select because we need the form data
471
function updateIssueFrom(url) {
472
  $.ajax({
473
    url: url,
474
    type: 'post',
475
    data: $('#issue-form').serialize()
476
  });
477
}
478

    
479
function updateBulkEditFrom(url) {
480
  $.ajax({
481
    url: url,
482
    type: 'post',
483
    data: $('#bulk_edit_form').serialize()
484
  });
485
}
486

    
487
function observeAutocompleteField(fieldId, url) {
488
  $(document).ready(function() {
489
    $('#'+fieldId).autocomplete({
490
      source: url,
491
      minLength: 2
492
    });
493
  });
494
}
495

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

    
525
function observeProjectModules() {
526
  var f = function() {
527
    /* Hides trackers and issues custom fields on the new project form when issue_tracking module is disabled */
528
    if ($('#project_enabled_module_names_issue_tracking').attr('checked')) {
529
      $('#project_trackers').show();
530
    }else{
531
      $('#project_trackers').hide();
532
    }
533
  };
534

    
535
  $(window).load(f);
536
  $('#project_enabled_module_names_issue_tracking').change(f);
537
}
538

    
539
function initMyPageSortable(list, url) {
540
  $('#list-'+list).sortable({
541
    connectWith: '.block-receiver',
542
    tolerance: 'pointer',
543
    update: function(){
544
      $.ajax({
545
        url: url,
546
        type: 'post',
547
        data: {'blocks': $.map($('#list-'+list).children(), function(el){return $(el).attr('id');})}
548
      });
549
    }
550
  });
551
  $("#list-top, #list-left, #list-right").disableSelection();
552
}
553

    
554
var warnLeavingUnsavedMessage;
555
function warnLeavingUnsaved(message) {
556
  warnLeavingUnsavedMessage = message;
557

    
558
  $('form').submit(function(){
559
    $('textarea').removeData('changed');
560
  });
561
  $('textarea').change(function(){
562
    $(this).data('changed', 'changed');
563
  });
564
  window.onbeforeunload = function(){
565
    var warn = false;
566
    $('textarea').blur().each(function(){
567
      if ($(this).data('changed')) {
568
        warn = true;
569
      }
570
    });
571
    if (warn) {return warnLeavingUnsavedMessage;}
572
  };
573
};
574

    
575
$(document).ready(function(){
576
  $('#ajax-indicator').bind('ajaxSend', function(){
577
    if ($('.ajax-loading').length == 0) {
578
      $('#ajax-indicator').show();
579
    }
580
  });
581
  $('#ajax-indicator').bind('ajaxStop', function(){
582
    $('#ajax-indicator').hide();
583
  });
584
});
585

    
586
function hideOnLoad() {
587
  $('.hol').hide();
588
}
589

    
590
function addFormObserversForDoubleSubmit() {
591
  $('form[method=post]').each(function() {
592
    if (!$(this).hasClass('multiple-submit')) {
593
      $(this).submit(function(form_submission) {
594
        if ($(form_submission.target).attr('data-submitted')) {
595
          form_submission.preventDefault();
596
        } else {
597
          $(form_submission.target).attr('data-submitted', true);
598
        }
599
      });
600
    }
601
  });
602
}
603

    
604
$(document).ready(hideOnLoad);
605
$(document).ready(addFormObserversForDoubleSubmit);
606