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 @ 1298:4f746d8966dd

History | View | Annotate | Download (16.3 KB)

1 1115:433d4f72a19b Chris
/* Redmine - project management software
2 1295:622f24f53b42 Chris
   Copyright (C) 2006-2013  Jean-Philippe Lang */
3 0:513646585e45 Chris
4 1115:433d4f72a19b Chris
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 0:513646585e45 Chris
}
11
12
function toggleCheckboxesBySelector(selector) {
13 1115:433d4f72a19b Chris
  var all_checked = true;
14
  $(selector).each(function(index) {
15
    if (!$(this).is(':checked')) { all_checked = false; }
16
  });
17 1295:622f24f53b42 Chris
  $(selector).attr('checked', !all_checked);
18 0:513646585e45 Chris
}
19
20 1115:433d4f72a19b Chris
function showAndScrollTo(id, focus) {
21
  $('#'+id).show();
22 1295:622f24f53b42 Chris
  if (focus !== null) {
23 1115:433d4f72a19b Chris
    $('#'+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 37:94944d00e43c chris
  });
47
}
48
49 1115:433d4f72a19b Chris
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 441:cbce1fd3b1b7 Chris
    } else {
55 1115:433d4f72a19b Chris
      $(this).show();
56 441:cbce1fd3b1b7 Chris
    }
57 1115:433d4f72a19b Chris
  });
58 441:cbce1fd3b1b7 Chris
}
59
60
function toggleAllRowGroups(el) {
61 1115:433d4f72a19b Chris
  var tr = $(el).parents('tr').first();
62
  if (tr.hasClass('open')) {
63 441:cbce1fd3b1b7 Chris
    collapseAllRowGroups(el);
64
  } else {
65
    expandAllRowGroups(el);
66
  }
67
}
68
69 0:513646585e45 Chris
function toggleFieldset(el) {
70 1115:433d4f72a19b Chris
  var fieldset = $(el).parents('fieldset').first();
71
  fieldset.toggleClass('collapsed');
72
  fieldset.children('div').toggle();
73 0:513646585e45 Chris
}
74
75 245:051f544170fe Chris
function hideFieldset(el) {
76 1115:433d4f72a19b Chris
  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 1295:622f24f53b42 Chris
    if (operators[i] == operator) { option.attr('selected', true); }
135 1115:433d4f72a19b Chris
    select.append(option);
136
  }
137 1295:622f24f53b42 Chris
  select.change(function(){ toggleOperator(field); });
138 1115:433d4f72a19b Chris
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 1295:622f24f53b42 Chris
    if (values.length > 1) { select.attr('multiple', true); }
150 1115:433d4f72a19b Chris
    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 1295:622f24f53b42 Chris
      if (values[0] == filterValue[1]) { option.attr('selected', true); }
193 1115:433d4f72a19b Chris
      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 1295:622f24f53b42 Chris
    case "ld":
246 1115:433d4f72a19b Chris
    case "w":
247 1295:622f24f53b42 Chris
    case "lw":
248
    case "l2w":
249
    case "m":
250
    case "lm":
251
    case "y":
252 1115:433d4f72a19b Chris
    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 245:051f544170fe Chris
}
292
293 0:513646585e45 Chris
function showTab(name) {
294 1115:433d4f72a19b Chris
  $('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 0:513646585e45 Chris
}
300
301
function moveTabRight(el) {
302 1115:433d4f72a19b Chris
  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 0:513646585e45 Chris
}
314
315
function moveTabLeft(el) {
316 1115:433d4f72a19b Chris
  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 0:513646585e45 Chris
}
323
324
function displayTabsButtons() {
325 1115:433d4f72a19b Chris
  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 0:513646585e45 Chris
}
343
344
function setPredecessorFieldsVisibility() {
345 1115:433d4f72a19b Chris
  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 0:513646585e45 Chris
}
352
353 909:cbb26bc654de Chris
function showModal(id, width) {
354 1115:433d4f72a19b Chris
  var el = $('#'+id).first();
355 1295:622f24f53b42 Chris
  if (el.length === 0 || el.is(':visible')) {return;}
356 1115:433d4f72a19b Chris
  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 909:cbb26bc654de Chris
}
366
367
function hideModal(el) {
368 1115:433d4f72a19b Chris
  var modal;
369
  if (el) {
370
    modal = $(el).parents('.ui-dialog-content');
371
  } else {
372
    modal = $('#ajax-modal');
373 909:cbb26bc654de Chris
  }
374 1115:433d4f72a19b Chris
  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 909:cbb26bc654de Chris
}
387
388 0:513646585e45 Chris
function collapseScmEntry(id) {
389 1115:433d4f72a19b Chris
  $('.'+id).each(function() {
390
    if ($(this).hasClass('open')) {
391
      collapseScmEntry($(this).attr('id'));
392 0:513646585e45 Chris
    }
393 1115:433d4f72a19b Chris
    $(this).hide();
394
  });
395
  $('#'+id).removeClass('open');
396 0:513646585e45 Chris
}
397
398
function expandScmEntry(id) {
399 1115:433d4f72a19b Chris
  $('.'+id).each(function() {
400
    $(this).show();
401
    if ($(this).hasClass('loaded') && !$(this).hasClass('collapsed')) {
402
      expandScmEntry($(this).attr('id'));
403 0:513646585e45 Chris
    }
404 1115:433d4f72a19b Chris
  });
405
  $('#'+id).addClass('open');
406 0:513646585e45 Chris
}
407
408 1115:433d4f72a19b Chris
function scmEntryClick(id, url) {
409
    el = $('#'+id);
410
    if (el.hasClass('open')) {
411 0:513646585e45 Chris
        collapseScmEntry(id);
412 1115:433d4f72a19b Chris
        el.addClass('collapsed');
413 0:513646585e45 Chris
        return false;
414 1115:433d4f72a19b Chris
    } else if (el.hasClass('loaded')) {
415 0:513646585e45 Chris
        expandScmEntry(id);
416 1115:433d4f72a19b Chris
        el.removeClass('collapsed');
417 0:513646585e45 Chris
        return false;
418
    }
419 1115:433d4f72a19b Chris
    if (el.hasClass('loading')) {
420 0:513646585e45 Chris
        return false;
421
    }
422 1115:433d4f72a19b Chris
    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 0:513646585e45 Chris
    return true;
431
}
432
433 1115:433d4f72a19b Chris
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 0:513646585e45 Chris
}
441
442 1115:433d4f72a19b Chris
// 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 0:513646585e45 Chris
}
450
451 1115:433d4f72a19b Chris
function updateBulkEditFrom(url) {
452
  $.ajax({
453
    url: url,
454
    type: 'post',
455
    data: $('#bulk_edit_form').serialize()
456
  });
457 0:513646585e45 Chris
}
458
459 1295:622f24f53b42 Chris
function observeAutocompleteField(fieldId, url, options) {
460 1115:433d4f72a19b Chris
  $(document).ready(function() {
461 1295:622f24f53b42 Chris
    $('#'+fieldId).autocomplete($.extend({
462 1115:433d4f72a19b Chris
      source: url,
463 1295:622f24f53b42 Chris
      minLength: 2,
464
      search: function(){$('#'+fieldId).addClass('ajax-loading');},
465
      response: function(){$('#'+fieldId).removeClass('ajax-loading');}
466
    }, options));
467
    $('#'+fieldId).addClass('autocomplete');
468 1115:433d4f72a19b Chris
  });
469 117:af80e5618e9b Chris
}
470
471 1115:433d4f72a19b Chris
function observeSearchfield(fieldId, targetId, url) {
472
  $('#'+fieldId).each(function() {
473
    var $this = $(this);
474 1295:622f24f53b42 Chris
    $this.addClass('autocomplete');
475 1115:433d4f72a19b Chris
    $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 1295:622f24f53b42 Chris
          success: function(data){ if(targetId) $('#'+targetId).html(data); },
485 1115:433d4f72a19b Chris
          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 117:af80e5618e9b Chris
}
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 1115:433d4f72a19b Chris
    if ($('#project_enabled_module_names_issue_tracking').attr('checked')) {
505
      $('#project_trackers').show();
506
    }else{
507
      $('#project_trackers').hide();
508
    }
509 117:af80e5618e9b Chris
  };
510 1115:433d4f72a19b Chris
511
  $(window).load(f);
512
  $('#project_enabled_module_names_issue_tracking').change(f);
513 117:af80e5618e9b Chris
}
514
515 1115:433d4f72a19b Chris
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 245:051f544170fe Chris
530 1115:433d4f72a19b Chris
var warnLeavingUnsavedMessage;
531
function warnLeavingUnsaved(message) {
532
  warnLeavingUnsavedMessage = message;
533 117:af80e5618e9b Chris
534 1115:433d4f72a19b Chris
  $('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 1295:622f24f53b42 Chris
}
550 441:cbce1fd3b1b7 Chris
551 1295:622f24f53b42 Chris
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 1115:433d4f72a19b Chris
      $('#ajax-indicator').show();
557 0:513646585e45 Chris
    }
558 1115:433d4f72a19b Chris
  });
559 1295:622f24f53b42 Chris
560
  $('#ajax-indicator').bind('ajaxStop', function() {
561 1115:433d4f72a19b Chris
    $('#ajax-indicator').hide();
562
  });
563 1295:622f24f53b42 Chris
}
564 0:513646585e45 Chris
565
function hideOnLoad() {
566 1115:433d4f72a19b Chris
  $('.hol').hide();
567 0:513646585e45 Chris
}
568
569 1115:433d4f72a19b Chris
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 1295:622f24f53b42 Chris
function blockEventPropagation(event) {
584
  event.stopPropagation();
585
  event.preventDefault();
586
}
587
588
$(document).ready(setupAjaxIndicator);
589 1115:433d4f72a19b Chris
$(document).ready(hideOnLoad);
590
$(document).ready(addFormObserversForDoubleSubmit);