diff public/javascripts/application.js @ 1337:077b8890835a cannam

Merge from live branch
author Chris Cannam
date Thu, 20 Jun 2013 13:14:02 +0100
parents bb32da3bea34
children 4f746d8966dd 51364c0cd58f
line wrap: on
line diff
--- a/public/javascripts/application.js	Fri Jun 14 11:30:07 2013 +0100
+++ b/public/javascripts/application.js	Thu Jun 20 13:14:02 2013 +0100
@@ -1,70 +1,65 @@
-/* redMine - project management software
-   Copyright (C) 2006-2008  Jean-Philippe Lang */
+/* Redmine - project management software
+   Copyright (C) 2006-2012  Jean-Philippe Lang */
 
-function checkAll (id, checked) {
-	var els = Element.descendants(id);
-	for (var i = 0; i < els.length; i++) {
-    if (els[i].disabled==false) {
-      els[i].checked = checked;
-    }
-	}
+function checkAll(id, checked) {
+  if (checked) {
+    $('#'+id).find('input[type=checkbox]').attr('checked', true);
+  } else {
+    $('#'+id).find('input[type=checkbox]').removeAttr('checked');
+  }
 }
 
 function toggleCheckboxesBySelector(selector) {
-	boxes = $$(selector);
-	var all_checked = true;
-	for (i = 0; i < boxes.length; i++) { if (boxes[i].checked == false) { all_checked = false; } }
-	for (i = 0; i < boxes.length; i++) { boxes[i].checked = !all_checked; }
+  var all_checked = true;
+  $(selector).each(function(index) {
+    if (!$(this).is(':checked')) { all_checked = false; }
+  });
+  $(selector).attr('checked', !all_checked)
 }
 
-function setCheckboxesBySelector(checked, selector) {
-  var boxes = $$(selector);
-  boxes.each(function(ele) {
-    ele.checked = checked;
+function showAndScrollTo(id, focus) {
+  $('#'+id).show();
+  if (focus!=null) {
+    $('#'+focus).focus();
+  }
+  $('html, body').animate({scrollTop: $('#'+id).offset().top}, 100);
+}
+
+function toggleRowGroup(el) {
+  var tr = $(el).parents('tr').first();
+  var n = tr.next();
+  tr.toggleClass('open');
+  while (n.length && !n.hasClass('group')) {
+    n.toggle();
+    n = n.next('tr');
+  }
+}
+
+function collapseAllRowGroups(el) {
+  var tbody = $(el).parents('tbody').first();
+  tbody.children('tr').each(function(index) {
+    if ($(this).hasClass('group')) {
+      $(this).removeClass('open');
+    } else {
+      $(this).hide();
+    }
   });
 }
 
-function showAndScrollTo(id, focus) {
-	Element.show(id);
-	if (focus!=null) { Form.Element.focus(focus); }
-	Element.scrollTo(id);
-}
-
-function toggleRowGroup(el) {
-	var tr = Element.up(el, 'tr');
-	var n = Element.next(tr);
-	tr.toggleClassName('open');
-	while (n != undefined && !n.hasClassName('group')) {
-		Element.toggle(n);
-		n = Element.next(n);
-	}
-}
-
-function collapseAllRowGroups(el) {
-  var tbody = Element.up(el, 'tbody');
-  tbody.childElements('tr').each(function(tr) {
-    if (tr.hasClassName('group')) {
-      tr.removeClassName('open');
+function expandAllRowGroups(el) {
+  var tbody = $(el).parents('tbody').first();
+  tbody.children('tr').each(function(index) {
+    if ($(this).hasClass('group')) {
+      $(this).addClass('open');
     } else {
-      tr.hide();
+      $(this).show();
     }
-  })
-}
-
-function expandAllRowGroups(el) {
-  var tbody = Element.up(el, 'tbody');
-  tbody.childElements('tr').each(function(tr) {
-    if (tr.hasClassName('group')) {
-      tr.addClassName('open');
-    } else {
-      tr.show();
-    }
-  })
+  });
 }
 
 function toggleAllRowGroups(el) {
-	var tr = Element.up(el, 'tr');
-  if (tr.hasClassName('open')) {
+  var tr = $(el).parents('tr').first();
+  if (tr.hasClass('open')) {
     collapseAllRowGroups(el);
   } else {
     expandAllRowGroups(el);
@@ -72,38 +67,243 @@
 }
 
 function toggleFieldset(el) {
-	var fieldset = Element.up(el, 'fieldset');
-	fieldset.toggleClassName('collapsed');
-	Effect.toggle(fieldset.down('div'), 'slide', {duration:0.2});
+  var fieldset = $(el).parents('fieldset').first();
+  fieldset.toggleClass('collapsed');
+  fieldset.children('div').toggle();
 }
 
 function hideFieldset(el) {
-	var fieldset = Element.up(el, 'fieldset');
-	fieldset.toggleClassName('collapsed');
-	fieldset.down('div').hide();
+  var fieldset = $(el).parents('fieldset').first();
+  fieldset.toggleClass('collapsed');
+  fieldset.children('div').hide();
+}
+
+function initFilters(){
+  $('#add_filter_select').change(function(){
+    addFilter($(this).val(), '', []);
+  });
+  $('#filters-table td.field input[type=checkbox]').each(function(){
+    toggleFilter($(this).val());
+  });
+  $('#filters-table td.field input[type=checkbox]').live('click',function(){
+    toggleFilter($(this).val());
+  });
+  $('#filters-table .toggle-multiselect').live('click',function(){
+    toggleMultiSelect($(this).siblings('select'));
+  });
+  $('#filters-table input[type=text]').live('keypress', function(e){
+    if (e.keyCode == 13) submit_query_form("query_form");
+  });
+}
+
+function addFilter(field, operator, values) {
+  var fieldId = field.replace('.', '_');
+  var tr = $('#tr_'+fieldId);
+  if (tr.length > 0) {
+    tr.show();
+  } else {
+    buildFilterRow(field, operator, values);
+  }
+  $('#cb_'+fieldId).attr('checked', true);
+  toggleFilter(field);
+  $('#add_filter_select').val('').children('option').each(function(){
+    if ($(this).attr('value') == field) {
+      $(this).attr('disabled', true);
+    }
+  });
+}
+
+function buildFilterRow(field, operator, values) {
+  var fieldId = field.replace('.', '_');
+  var filterTable = $("#filters-table");
+  var filterOptions = availableFilters[field];
+  var operators = operatorByType[filterOptions['type']];
+  var filterValues = filterOptions['values'];
+  var i, select;
+
+  var tr = $('<tr class="filter">').attr('id', 'tr_'+fieldId).html(
+    '<td class="field"><input checked="checked" id="cb_'+fieldId+'" name="f[]" value="'+field+'" type="checkbox"><label for="cb_'+fieldId+'"> '+filterOptions['name']+'</label></td>' +
+    '<td class="operator"><select id="operators_'+fieldId+'" name="op['+field+']"></td>' +
+    '<td class="values"></td>'
+  );
+  filterTable.append(tr);
+
+  select = tr.find('td.operator select');
+  for (i=0;i<operators.length;i++){
+    var option = $('<option>').val(operators[i]).text(operatorLabels[operators[i]]);
+    if (operators[i] == operator) {option.attr('selected', true)};
+    select.append(option);
+  }
+  select.change(function(){toggleOperator(field)});
+
+  switch (filterOptions['type']){
+  case "list":
+  case "list_optional":
+  case "list_status":
+  case "list_subprojects":
+    tr.find('td.values').append(
+      '<span style="display:none;"><select class="value" id="values_'+fieldId+'_1" name="v['+field+'][]"></select>' +
+      ' <span class="toggle-multiselect">&nbsp;</span></span>'
+    );
+    select = tr.find('td.values select');
+    if (values.length > 1) {select.attr('multiple', true)};
+    for (i=0;i<filterValues.length;i++){
+      var filterValue = filterValues[i];
+      var option = $('<option>');
+      if ($.isArray(filterValue)) {
+        option.val(filterValue[1]).text(filterValue[0]);
+        if ($.inArray(filterValue[1], values) > -1) {option.attr('selected', true);}
+      } else {
+        option.val(filterValue).text(filterValue);
+        if ($.inArray(filterValue, values) > -1) {option.attr('selected', true);}
+      }
+      select.append(option);
+    }
+    break;
+  case "date":
+  case "date_past":
+    tr.find('td.values').append(
+      '<span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_1" size="10" class="value date_value" /></span>' +
+      ' <span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_2" size="10" class="value date_value" /></span>' +
+      ' <span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'" size="3" class="value" /> '+labelDayPlural+'</span>'
+    );
+    $('#values_'+fieldId+'_1').val(values[0]).datepicker(datepickerOptions);
+    $('#values_'+fieldId+'_2').val(values[1]).datepicker(datepickerOptions);
+    $('#values_'+fieldId).val(values[0]);
+    break;
+  case "string":
+  case "text":
+    tr.find('td.values').append(
+      '<span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'" size="30" class="value" /></span>'
+    );
+    $('#values_'+fieldId).val(values[0]);
+    break;
+  case "relation":
+    tr.find('td.values').append(
+      '<span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'" size="6" class="value" /></span>' +
+      '<span style="display:none;"><select class="value" name="v['+field+'][]" id="values_'+fieldId+'_1"></select></span>'
+    );
+    $('#values_'+fieldId).val(values[0]);
+    select = tr.find('td.values select');
+    for (i=0;i<allProjects.length;i++){
+      var filterValue = allProjects[i];
+      var option = $('<option>');
+      option.val(filterValue[1]).text(filterValue[0]);
+      if (values[0] == filterValue[1]) {option.attr('selected', true)};
+      select.append(option);
+    }
+  case "integer":
+  case "float":
+    tr.find('td.values').append(
+      '<span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_1" size="6" class="value" /></span>' +
+      ' <span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_2" size="6" class="value" /></span>'
+    );
+    $('#values_'+fieldId+'_1').val(values[0]);
+    $('#values_'+fieldId+'_2').val(values[1]);
+    break;
+  }
+}
+
+function toggleFilter(field) {
+  var fieldId = field.replace('.', '_');
+  if ($('#cb_' + fieldId).is(':checked')) {
+    $("#operators_" + fieldId).show().removeAttr('disabled');
+    toggleOperator(field);
+  } else {
+    $("#operators_" + fieldId).hide().attr('disabled', true);
+    enableValues(field, []);
+  }
+}
+
+function enableValues(field, indexes) {
+  var fieldId = field.replace('.', '_');
+  $('#tr_'+fieldId+' td.values .value').each(function(index) {
+    if ($.inArray(index, indexes) >= 0) {
+      $(this).removeAttr('disabled');
+      $(this).parents('span').first().show();
+    } else {
+      $(this).val('');
+      $(this).attr('disabled', true);
+      $(this).parents('span').first().hide();
+    }
+
+    if ($(this).hasClass('group')) {
+      $(this).addClass('open');
+    } else {
+      $(this).show();
+    }
+  });
+}
+
+function toggleOperator(field) {
+  var fieldId = field.replace('.', '_');
+  var operator = $("#operators_" + fieldId);
+  switch (operator.val()) {
+    case "!*":
+    case "*":
+    case "t":
+    case "w":
+    case "o":
+    case "c":
+      enableValues(field, []);
+      break;
+    case "><":
+      enableValues(field, [0,1]);
+      break;
+    case "<t+":
+    case ">t+":
+    case "><t+":
+    case "t+":
+    case ">t-":
+    case "<t-":
+    case "><t-":
+    case "t-":
+      enableValues(field, [2]);
+      break;
+    case "=p":
+    case "=!p":
+    case "!p":
+      enableValues(field, [1]);
+      break;
+    default:
+      enableValues(field, [0]);
+      break;
+  }
+}
+
+function toggleMultiSelect(el) {
+  if (el.attr('multiple')) {
+    el.removeAttr('multiple');
+  } else {
+    el.attr('multiple', true);
+  }
+}
+
+function submit_query_form(id) {
+  selectAllOptions("selected_columns");
+  $('#'+id).submit();
 }
 
 var fileFieldCount = 1;
-
 function addFileField() {
-  var fields = $('attachments_fields');
-  if (fields.childElements().length >= 10) return false;
+  var fields = $('#attachments_fields');
+  if (fields.children().length >= 10) return false;
   fileFieldCount++;
-  var s = new Element('span');
-  s.update(fields.down('span').innerHTML);
-  s.down('input.file').name = "attachments[" + fileFieldCount + "][file]";
-  s.down('input.description').name = "attachments[" + fileFieldCount + "][description]";
-  fields.appendChild(s);
+  var s = fields.children('span').first().clone();
+  s.children('input.file').attr('name', "attachments[" + fileFieldCount + "][file]").val('');
+  s.children('input.description').attr('name', "attachments[" + fileFieldCount + "][description]").val('');
+  fields.append(s);
 }
 
 function removeFileField(el) {
-  var fields = $('attachments_fields');
-	var s = Element.up(el, 'span');
-	if (fields.childElements().length > 1) {
-		s.remove();
-	} else {
-		s.update(s.innerHTML);
-	}
+  var fields = $('#attachments_fields');
+  var s = $(el).parents('span').first();
+  if (fields.children().length > 1) {
+    s.remove();
+  } else {
+    s.children('input.file').val('');
+    s.children('input.description').val('');
+  }
 }
 
 function checkFileSize(el, maxSize, message) {
@@ -119,303 +319,288 @@
 }
 
 function showTab(name) {
-    var f = $$('div#content .tab-content');
-	for(var i=0; i<f.length; i++){
-		Element.hide(f[i]);
-	}
-    var f = $$('div.tabs a');
-	for(var i=0; i<f.length; i++){
-		Element.removeClassName(f[i], "selected");
-	}
-	Element.show('tab-content-' + name);
-	Element.addClassName('tab-' + name, "selected");
-	return false;
+  $('div#content .tab-content').hide();
+  $('div.tabs a').removeClass('selected');
+  $('#tab-content-' + name).show();
+  $('#tab-' + name).addClass('selected');
+  return false;
 }
 
 function moveTabRight(el) {
-	var lis = Element.up(el, 'div.tabs').down('ul').childElements();
-	var tabsWidth = 0;
-	var i;
-	for (i=0; i<lis.length; i++) {
-		if (lis[i].visible()) {
-			tabsWidth += lis[i].getWidth() + 6;
-		}
-	}
-	if (tabsWidth < Element.up(el, 'div.tabs').getWidth() - 60) {
-		return;
-	}
-	i=0;
-	while (i<lis.length && !lis[i].visible()) {
-		i++;
-	}
-	lis[i].hide();
+  var lis = $(el).parents('div.tabs').first().find('ul').children();
+  var tabsWidth = 0;
+  var i = 0;
+  lis.each(function(){
+    if ($(this).is(':visible')) {
+      tabsWidth += $(this).width() + 6;
+    }
+  });
+  if (tabsWidth < $(el).parents('div.tabs').first().width() - 60) { return; }
+  while (i<lis.length && !lis.eq(i).is(':visible')) { i++; }
+  lis.eq(i).hide();
 }
 
 function moveTabLeft(el) {
-	var lis = Element.up(el, 'div.tabs').down('ul').childElements();
-	var i = 0;
-	while (i<lis.length && !lis[i].visible()) {
-		i++;
-	}
-	if (i>0) {
-		lis[i-1].show();
-	}
+  var lis = $(el).parents('div.tabs').first().find('ul').children();
+  var i = 0;
+  while (i<lis.length && !lis.eq(i).is(':visible')) { i++; }
+  if (i>0) {
+    lis.eq(i-1).show();
+  }
 }
 
 function displayTabsButtons() {
-	var lis;
-	var tabsWidth = 0;
-	var i;
-	$$('div.tabs').each(function(el) {
-		lis = el.down('ul').childElements();
-		for (i=0; i<lis.length; i++) {
-			if (lis[i].visible()) {
-				tabsWidth += lis[i].getWidth() + 6;
-			}
-		}
-		if ((tabsWidth < el.getWidth() - 60) && (lis[0].visible())) {
-			el.down('div.tabs-buttons').hide();
-		} else {
-			el.down('div.tabs-buttons').show();
-		}
-	});
+  var lis;
+  var tabsWidth = 0;
+  var el;
+  $('div.tabs').each(function() {
+    el = $(this);
+    lis = el.find('ul').children();
+    lis.each(function(){
+      if ($(this).is(':visible')) {
+        tabsWidth += $(this).width() + 6;
+      }
+    });
+    if ((tabsWidth < el.width() - 60) && (lis.first().is(':visible'))) {
+      el.find('div.tabs-buttons').hide();
+    } else {
+      el.find('div.tabs-buttons').show();
+    }
+  });
 }
 
 function setPredecessorFieldsVisibility() {
-    relationType = $('relation_relation_type');
-    if (relationType && (relationType.value == "precedes" || relationType.value == "follows")) {
-        Element.show('predecessor_fields');
-    } else {
-        Element.hide('predecessor_fields');
-    }
-}
-
-function promptToRemote(text, param, url) {
-    value = prompt(text + ':');
-    if (value) {
-        new Ajax.Request(url + '?' + param + '=' + encodeURIComponent(value), {asynchronous:true, evalScripts:true});
-        return false;
-    }
+  var relationType = $('#relation_relation_type');
+  if (relationType.val() == "precedes" || relationType.val() == "follows") {
+    $('#predecessor_fields').show();
+  } else {
+    $('#predecessor_fields').hide();
+  }
 }
 
 function showModal(id, width) {
-  el = $(id);
-	if (el == undefined || el.visible()) {return;}
-  var h = $$('body')[0].getHeight();
-  var d = document.createElement("div");
-  d.id = 'modalbg';
-  $('main').appendChild(d);
-  $('modalbg').setStyle({ width: '100%', height: h + 'px' });
-  $('modalbg').show();
-
-  var pageWidth = document.viewport.getWidth();
-	el.setStyle({'width': width});
-	el.setStyle({'left': (((pageWidth - el.getWidth())/2  *100) / pageWidth) + '%'});
-  el.addClassName('modal');
-	el.show();
-
-  var submit = el.down("input[type=submit]");
-	if (submit) {
-  	submit.focus();
-  }
+  var el = $('#'+id).first();
+  if (el.length == 0 || el.is(':visible')) {return;}
+  var title = el.find('h3.title').text();
+  el.dialog({
+    width: width,
+    modal: true,
+    resizable: false,
+    dialogClass: 'modal',
+    title: title
+  });
+  el.find("input[type=text], input[type=submit]").first().focus();
 }
 
 function hideModal(el) {
-  var modal = Element.up(el, 'div.modal');
-	if (modal) {
-		modal.hide();
-	}
-	var bg = $('modalbg');
-	if (bg) {
-  	bg.remove();
+  var modal;
+  if (el) {
+    modal = $(el).parents('.ui-dialog-content');
+  } else {
+    modal = $('#ajax-modal');
   }
+  modal.dialog("close");
+}
+
+function submitPreview(url, form, target) {
+  $.ajax({
+    url: url,
+    type: 'post',
+    data: $('#'+form).serialize(),
+    success: function(data){
+      $('#'+target).html(data);
+    }
+  });
 }
 
 function collapseScmEntry(id) {
-    var els = document.getElementsByClassName(id, 'browser');
-	for (var i = 0; i < els.length; i++) {
-	   if (els[i].hasClassName('open')) {
-	       collapseScmEntry(els[i].id);
-	   }
-       Element.hide(els[i]);
+  $('.'+id).each(function() {
+    if ($(this).hasClass('open')) {
+      collapseScmEntry($(this).attr('id'));
     }
-    $(id).removeClassName('open');
+    $(this).hide();
+  });
+  $('#'+id).removeClass('open');
 }
 
 function expandScmEntry(id) {
-    var els = document.getElementsByClassName(id, 'browser');
-	for (var i = 0; i < els.length; i++) {
-       Element.show(els[i]);
-       if (els[i].hasClassName('loaded') && !els[i].hasClassName('collapsed')) {
-            expandScmEntry(els[i].id);
-       }
+  $('.'+id).each(function() {
+    $(this).show();
+    if ($(this).hasClass('loaded') && !$(this).hasClass('collapsed')) {
+      expandScmEntry($(this).attr('id'));
     }
-    $(id).addClassName('open');
+  });
+  $('#'+id).addClass('open');
 }
 
-function scmEntryClick(id) {
-    el = $(id);
-    if (el.hasClassName('open')) {
+function scmEntryClick(id, url) {
+    el = $('#'+id);
+    if (el.hasClass('open')) {
         collapseScmEntry(id);
-        el.addClassName('collapsed');
+        el.addClass('collapsed');
         return false;
-    } else if (el.hasClassName('loaded')) {
+    } else if (el.hasClass('loaded')) {
         expandScmEntry(id);
-        el.removeClassName('collapsed');
+        el.removeClass('collapsed');
         return false;
     }
-    if (el.hasClassName('loading')) {
+    if (el.hasClass('loading')) {
         return false;
     }
-    el.addClassName('loading');
+    el.addClass('loading');
+    $.ajax({
+      url: url,
+      success: function(data){
+        el.after(data);
+        el.addClass('open').addClass('loaded').removeClass('loading');
+      }
+    });
     return true;
 }
 
-function scmEntryLoaded(id) {
-    Element.addClassName(id, 'open');
-    Element.addClassName(id, 'loaded');
-    Element.removeClassName(id, 'loading');
+function randomKey(size) {
+  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');
+  var key = '';
+  for (i = 0; i < size; i++) {
+    key += chars[Math.floor(Math.random() * chars.length)];
+  }
+  return key;
 }
 
-function randomKey(size) {
-	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');
-	var key = '';
-	for (i = 0; i < size; i++) {
-  	key += chars[Math.floor(Math.random() * chars.length)];
-	}
-	return key;
+// Can't use Rails' remote select because we need the form data
+function updateIssueFrom(url) {
+  $.ajax({
+    url: url,
+    type: 'post',
+    data: $('#issue-form').serialize()
+  });
 }
 
-function observeParentIssueField(url) {
-  new Ajax.Autocompleter('issue_parent_issue_id',
-                         'parent_issue_candidates',
-                         url,
-                         { minChars: 3,
-                           frequency: 0.5,
-                           paramName: 'q',
-                           method: 'get',
-                           updateElement: function(value) {
-                             document.getElementById('issue_parent_issue_id').value = value.id;
-                           }});
+function updateBulkEditFrom(url) {
+  $.ajax({
+    url: url,
+    type: 'post',
+    data: $('#bulk_edit_form').serialize()
+  });
 }
 
-function observeRelatedIssueField(url) {
-  new Ajax.Autocompleter('relation_issue_to_id',
-                         'related_issue_candidates',
-                         url,
-                         { minChars: 3,
-                           frequency: 0.5,
-                           paramName: 'q',
-                           method: 'get',
-                           updateElement: function(value) {
-                             document.getElementById('relation_issue_to_id').value = value.id;
-                           },
-                           parameters: 'scope=all'
-                           });
+function observeAutocompleteField(fieldId, url) {
+  $(document).ready(function() {
+    $('#'+fieldId).autocomplete({
+      source: url,
+      minLength: 2
+    });
+  });
 }
 
-function setVisible(id, visible) {
-  var el = $(id);
-  if (el) {if (visible) {el.show();} else {el.hide();}}
+function observeSearchfield(fieldId, targetId, url) {
+  $('#'+fieldId).each(function() {
+    var $this = $(this);
+    $this.attr('data-value-was', $this.val());
+    var check = function() {
+      var val = $this.val();
+      if ($this.attr('data-value-was') != val){
+        $this.attr('data-value-was', val);
+        $.ajax({
+          url: url,
+          type: 'get',
+          data: {q: $this.val()},
+          success: function(data){ $('#'+targetId).html(data); },
+          beforeSend: function(){ $this.addClass('ajax-loading'); },
+          complete: function(){ $this.removeClass('ajax-loading'); }
+        });
+      }
+    };
+    var reset = function() {
+      if (timer) {
+        clearInterval(timer);
+        timer = setInterval(check, 300);
+      }
+    };
+    var timer = setInterval(check, 300);
+    $this.bind('keyup click mousemove', reset);
+  });
 }
 
 function observeProjectModules() {
   var f = function() {
     /* Hides trackers and issues custom fields on the new project form when issue_tracking module is disabled */
-    var c = ($('project_enabled_module_names_issue_tracking').checked == true);
-    setVisible('project_trackers', c);
-    setVisible('project_issue_custom_fields', c);
+    if ($('#project_enabled_module_names_issue_tracking').attr('checked')) {
+      $('#project_trackers').show();
+    }else{
+      $('#project_trackers').hide();
+    }
   };
-  
-  Event.observe(window, 'load', f);
-  Event.observe('project_enabled_module_names_issue_tracking', 'change', f);
+
+  $(window).load(f);
+  $('#project_enabled_module_names_issue_tracking').change(f);
 }
 
-/*
- * Class used to warn user when leaving a page with unsaved textarea
- * Author: mathias.fischer@berlinonline.de
-*/
+function initMyPageSortable(list, url) {
+  $('#list-'+list).sortable({
+    connectWith: '.block-receiver',
+    tolerance: 'pointer',
+    update: function(){
+      $.ajax({
+        url: url,
+        type: 'post',
+        data: {'blocks': $.map($('#list-'+list).children(), function(el){return $(el).attr('id');})}
+      });
+    }
+  });
+  $("#list-top, #list-left, #list-right").disableSelection();
+}
 
-var WarnLeavingUnsaved = Class.create({
-	observedForms: false,
-	observedElements: false,
-	changedForms: false,
-	message: null,
-	
-	initialize: function(message){
-		this.observedForms = $$('form');
-		this.observedElements =  $$('textarea');
-		this.message = message;
-		
-		this.observedElements.each(this.observeChange.bind(this));
-		this.observedForms.each(this.submitAction.bind(this));
-		
-		window.onbeforeunload = this.unload.bind(this);
-	},
-	
-	unload: function(){
-		this.observedElements.each(function(el) {el.blur();})
-		if(this.changedForms)
-      return this.message;
-	},
-	
-	setChanged: function(){
-    this.changedForms = true;
-	},
-	
-	setUnchanged: function(){
-    this.changedForms = false;
-	},
-	
-	observeChange: function(element){
-    element.observe('change',this.setChanged.bindAsEventListener(this));
-	},
-	
-	submitAction: function(element){
-    element.observe('submit',this.setUnchanged.bindAsEventListener(this));
-	}
-});
+var warnLeavingUnsavedMessage;
+function warnLeavingUnsaved(message) {
+  warnLeavingUnsavedMessage = message;
 
-/* 
- * 1 - registers a callback which copies the csrf token into the
- * X-CSRF-Token header with each ajax request.  Necessary to 
- * work with rails applications which have fixed
- * CVE-2011-0447
- * 2 - shows and hides ajax indicator
- */
-Ajax.Responders.register({
-    onCreate: function(request){
-        var csrf_meta_tag = $$('meta[name=csrf-token]')[0];
+  $('form').submit(function(){
+    $('textarea').removeData('changed');
+  });
+  $('textarea').change(function(){
+    $(this).data('changed', 'changed');
+  });
+  window.onbeforeunload = function(){
+    var warn = false;
+    $('textarea').blur().each(function(){
+      if ($(this).data('changed')) {
+        warn = true;
+      }
+    });
+    if (warn) {return warnLeavingUnsavedMessage;}
+  };
+};
 
-        if (csrf_meta_tag) {
-            var header = 'X-CSRF-Token',
-                token = csrf_meta_tag.readAttribute('content');
-
-            if (!request.options.requestHeaders) {
-              request.options.requestHeaders = {};
-            }
-            request.options.requestHeaders[header] = token;
-          }
-
-        if ($('ajax-indicator') && Ajax.activeRequestCount > 0) {
-            Element.show('ajax-indicator');
-        }
-    },
-    onComplete: function(){
-        if ($('ajax-indicator') && Ajax.activeRequestCount == 0) {
-            Element.hide('ajax-indicator');
-        }
+$(document).ready(function(){
+  $('#ajax-indicator').bind('ajaxSend', function(){
+    if ($('.ajax-loading').length == 0) {
+      $('#ajax-indicator').show();
     }
+  });
+  $('#ajax-indicator').bind('ajaxStop', function(){
+    $('#ajax-indicator').hide();
+  });
 });
 
 function hideOnLoad() {
-  $$('.hol').each(function(el) {
-  	el.hide();
-	});
+  $('.hol').hide();
 }
 
-Event.observe(window, 'load', hideOnLoad);
+function addFormObserversForDoubleSubmit() {
+  $('form[method=post]').each(function() {
+    if (!$(this).hasClass('multiple-submit')) {
+      $(this).submit(function(form_submission) {
+        if ($(form_submission.target).attr('data-submitted')) {
+          form_submission.preventDefault();
+        } else {
+          $(form_submission.target).attr('data-submitted', true);
+        }
+      });
+    }
+  });
+}
 
+$(document).ready(hideOnLoad);
+$(document).ready(addFormObserversForDoubleSubmit);
 
-
-