diff --git a/app/assets/javascripts/issues.js b/app/assets/javascripts/issues.js
index 148dc7b96e90690d3f7e5d9908305d8cece6877a..3ddc6926ecdad9b569487c17fc667ebf25e4237a 100644
--- a/app/assets/javascripts/issues.js
+++ b/app/assets/javascripts/issues.js
@@ -5,7 +5,7 @@ function switchToNewIssue(form){
     $('select#issue_milestone_id').chosen();
     $("#new_issue_dialog").show("fade", { direction: "right" }, 150);
     $('.top-tabs .add_new').hide();
-    disableButtonIfEmtpyField("#issue_title", ".save-btn");
+    disableButtonIfEmptyField("#issue_title", ".save-btn");
   });
 }
 
@@ -16,7 +16,7 @@ function switchToEditIssue(form){
     $('select#issue_milestone_id').chosen();
     $("#edit_issue_dialog").show("fade", { direction: "right" }, 150);
     $('.add_new').hide();
-    disableButtonIfEmtpyField("#issue_title", ".save-btn");
+    disableButtonIfEmptyField("#issue_title", ".save-btn");
   });
 }
 
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js
deleted file mode 100644
index 61af1dc3d1989ac52dbb66a13d08a8afa2cb8789..0000000000000000000000000000000000000000
--- a/app/assets/javascripts/main.js
+++ /dev/null
@@ -1,130 +0,0 @@
-$(document).ready(function(){
-
-  $(".one_click_select").live("click", function(){
-    $(this).select();
-  });
-
-  $('body').on('ajax:complete, ajax:beforeSend, submit', 'form', function(e){
-    var buttons = $('[type="submit"]', this);
-    switch( e.type ){
-      case 'ajax:beforeSend':
-      case 'submit':
-        buttons.attr('disabled', 'disabled');
-      break;
-      case ' ajax:complete':
-      default:
-        buttons.removeAttr('disabled');
-      break;
-    }
-  })
-
-  $(".account-box").mouseenter(showMenu);
-  $(".account-box").mouseleave(resetMenu);
-
-  $("#projects-list .project").live('click', function(e){
-    if(e.target.nodeName != "A" && e.target.nodeName != "INPUT") {
-      location.href = $(this).attr("url");
-      e.stopPropagation();
-      return false;
-    }
-  });
-
-  /**
-   * Focus search field by pressing 's' key
-   */
-  $(document).keypress(function(e) {
-    if( $(e.target).is(":input") ) return;
-    switch(e.which)  {
-      case 115:  focusSearch();
-        e.preventDefault();
-    }
-  });
-
-  /**
-   * Commit show suppressed diff
-   *
-   */
-  $(".supp_diff_link").bind("click", function() {
-    showDiff(this);
-  });
-
-  /**
-   * Note markdown preview
-   *
-   */
-  $(document).on('click', '#preview-link', function(e) {
-    $('#preview-note').text('Loading...');
-
-    var previewLinkText = ($(this).text() == 'Preview' ? 'Edit' : 'Preview');
-    $(this).text(previewLinkText);
-
-    var note = $('#note_note').val();
-    if (note.trim().length === 0) { note = 'Nothing to preview'; }
-    $.post($(this).attr('href'), {note: note}, function(data) {
-      $('#preview-note').html(data);
-    });
-
-    $('#preview-note, #note_note').toggle();
-    e.preventDefault();
-  });
-});
-
-function focusSearch() {
-  $("#search").focus();
-}
-
-function updatePage(data){
-  $.ajax({type: "GET", url: location.href, data: data, dataType: "script"});
-}
-
-function showMenu() {
-  $(this).toggleClass('hover');
-}
-
-function resetMenu() {
-  $(this).removeClass("hover");
-}
-
-function slugify(text) {
-  return text.replace(/[^-a-zA-Z0-9]+/g, '_').toLowerCase();
-}
-
-function showDiff(link) {
-  $(link).next('table').show();
-  $(link).remove();
-}
-
-(function($){
-    var _chosen = $.fn.chosen;
-    $.fn.extend({
-        chosen: function(options) {
-            var default_options = {'search_contains' : 'true'};
-            $.extend(default_options, options);
-            return _chosen.apply(this, [default_options]);
-    }})
-})(jQuery);
-
-
-function ajaxGet(url) {
-  $.ajax({type: "GET", url: url, dataType: "script"});
-}
-
-/**
- * Disable button if text field is empty
- */
-function disableButtonIfEmtpyField(field_selector, button_selector) {
-  field = $(field_selector);
-  if(field.val() == "") {
-    field.closest("form").find(button_selector).attr("disabled", "disabled").addClass("disabled");
-  }
-
-  field.on('keyup', function(){
-    var field = $(this);
-    var closest_submit = field.closest("form").find(button_selector);
-    if(field.val() == "") {
-      closest_submit.attr("disabled", "disabled").addClass("disabled");
-    } else {
-      closest_submit.removeAttr("disabled").removeClass("disabled");
-    }
-  })
-}
diff --git a/app/assets/javascripts/main.js.coffee b/app/assets/javascripts/main.js.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..a01b3932323ab8381e8cd7a043fad4cc46346f32
--- /dev/null
+++ b/app/assets/javascripts/main.js.coffee
@@ -0,0 +1,89 @@
+window.updatePage = (data) ->
+  $.ajax({type: "GET", url: location.href, data: data, dataType: "script"})
+
+window.slugify = (text) ->
+  text.replace(/[^-a-zA-Z0-9]+/g, '_').toLowerCase()
+
+window.ajaxGet = (url) ->
+  $.ajax({type: "GET", url: url, dataType: "script"})
+
+ # Disable button if text field is empty
+window.disableButtonIfEmptyField = (field_selector, button_selector) ->
+  field = $(field_selector)
+  closest_submit = field.closest("form").find(button_selector)
+
+  closest_submit.disable() if field.val() is ""
+
+  field.on "keyup", ->
+    if $(this).val() is ""
+      closest_submit.disable()
+    else
+      closest_submit.enable()
+
+$ ->
+  # Click a .one_click_select field, select the contents
+  $(".one_click_select").live 'click', -> $(this).select()
+
+  # Disable form buttons while a form is submitting
+  $('body').on 'ajax:complete, ajax:beforeSend, submit', 'form', (e) ->
+    buttons = $('[type="submit"]', this)
+
+    switch e.type
+      when 'ajax:beforeSend', 'submit'
+        buttons.disable()
+      else
+        buttons.enable()
+
+  # Show/Hide the profile menu when hovering the account box
+  $('.account-box').hover -> $(this).toggleClass('hover')
+
+  # Focus search field by pressing 's' key
+  $(document).keypress (e) ->
+    # Don't do anything if typing in an input
+    return if $(e.target).is(":input")
+
+    switch e.which
+      when 115
+        $("#search").focus()
+        e.preventDefault()
+
+  # Commit show suppressed diff
+  $(".supp_diff_link").bind "click", ->
+    $(this).next('table').show()
+    $(this).remove()
+
+  # Note markdown preview
+  $(document).on 'click', '#preview-link', (e) ->
+    $('#preview-note').text('Loading...')
+
+    previewLinkText = if $(this).text() == 'Preview' then 'Edit' else 'Preview'
+    $(this).text(previewLinkText)
+
+    note = $('#note_note').val()
+
+    if note.trim().length == 0
+      $('#preview-note').text("Nothing to preview.")
+    else
+      $.post $(this).attr('href'), {note: note}, (data) ->
+        $('#preview-note').html(data)
+
+    $('#preview-note, #note_note').toggle()
+    e.preventDefault()
+    false
+
+(($) ->
+  _chosen = $.fn.chosen
+  $.fn.extend chosen: (options) ->
+    default_options = search_contains: "true"
+    $.extend default_options, options
+    _chosen.apply this, [default_options]
+
+  # Disable an element and add the 'disabled' Bootstrap class
+  $.fn.extend disable: ->
+    $(this).attr('disabled', 'disabled').addClass('disabled')
+
+  # Enable an element and remove the 'disabled' Bootstrap class
+  $.fn.extend enable: ->
+    $(this).removeAttr('disabled').removeClass('disabled')
+
+)(jQuery)
diff --git a/app/assets/javascripts/note.js b/app/assets/javascripts/note.js
index 9cd3e36e87b47a0ce8947e44cb4ec421a0a7da2f..79ab086bfa2cd7572b387f1dabb1995e84571140 100644
--- a/app/assets/javascripts/note.js
+++ b/app/assets/javascripts/note.js
@@ -25,14 +25,14 @@ var NoteList = {
         $(this).closest('li').fadeOut(); });
 
       $(".note-form-holder").live("ajax:before", function(){
-        $(".submit_note").attr("disabled", "disabled");
+        $(".submit_note").disable()
       })
 
       $(".note-form-holder").live("ajax:complete", function(){
-        $(".submit_note").removeAttr("disabled");
+        $(".submit_note").enable()
       })
 
-      disableButtonIfEmtpyField(".note-text", ".submit_note");
+      disableButtonIfEmptyField(".note-text", ".submit_note");
 
       $(".note-text").live("focus", function(){
         $(this).css("height", "80px");
@@ -177,6 +177,6 @@ var PerLineNotes = {
         form.show();
         return false;
       });
-      disableButtonIfEmtpyField(".line-note-text", ".submit_inline_note");
+      disableButtonIfEmptyField(".line-note-text", ".submit_inline_note");
     }
 }
diff --git a/app/assets/javascripts/projects.js.coffee b/app/assets/javascripts/projects.js.coffee
index 85ab2a06dfffd5ca9dfc68c381981213ed725123..14738e145e5aebf658643701a4745f37db99b916 100644
--- a/app/assets/javascripts/projects.js.coffee
+++ b/app/assets/javascripts/projects.js.coffee
@@ -8,7 +8,7 @@ window.Projects = ->
     $('.save-project-loader').show()
 
   $('form #project_default_branch').chosen()
-  disableButtonIfEmtpyField '#project_name', '.project-submit'
+  disableButtonIfEmptyField '#project_name', '.project-submit'
 
 # Git clone panel switcher
 $ ->
diff --git a/app/views/layouts/_head_panel.html.haml b/app/views/layouts/_head_panel.html.haml
index d6247d36b0df86e5018ca6ac2b29e70e0c73e014..f5e423a5abf3c59331cebe0d22cf2384c50abf2e 100644
--- a/app/views/layouts/_head_panel.html.haml
+++ b/app/views/layouts/_head_panel.html.haml
@@ -34,12 +34,4 @@
       source: #{raw search_autocomplete_source},
       select: function(event, ui) { location.href = ui.item.url }
     });
-
-    $(document).keypress(function(e) {
-      if($(e.target).is(":input")) return;
-        switch(e.which)  {
-        case 115:  focusSearch();
-        e.preventDefault();
-      }
-    });
   });
diff --git a/app/views/merge_requests/_form.html.haml b/app/views/merge_requests/_form.html.haml
index b554c0519641e3e9b6ed2471f1201c91dbddb02d..d5271ed08c4a9aef00f798f9021bae02cdc1d264 100644
--- a/app/views/merge_requests/_form.html.haml
+++ b/app/views/merge_requests/_form.html.haml
@@ -60,7 +60,7 @@
 
 :javascript
   $(function(){
-    disableButtonIfEmtpyField("#merge_request_title", ".save-btn");
+    disableButtonIfEmptyField("#merge_request_title", ".save-btn");
     $('select#merge_request_assignee_id').chosen();
     $('select#merge_request_source_branch').chosen();
     $('select#merge_request_target_branch').chosen();
diff --git a/app/views/milestones/_form.html.haml b/app/views/milestones/_form.html.haml
index ce4145ba3e6f3c12b4c20a4da9602f6a50661f0e..194eac7783ce34067f49b80c4217dbc37e044a34 100644
--- a/app/views/milestones/_form.html.haml
+++ b/app/views/milestones/_form.html.haml
@@ -41,7 +41,7 @@
 
 :javascript
   $(function() {
-    disableButtonIfEmtpyField("#milestone_title", ".save-btn");
+    disableButtonIfEmptyField("#milestone_title", ".save-btn");
     $( ".datepicker" ).datepicker({
       dateFormat: "yy-mm-dd",
       onSelect: function(dateText, inst) { $("#milestone_due_date").val(dateText) }