diff --git a/edit.module b/edit.module
index a116edd..dacb5a8 100644
--- a/edit.module
+++ b/edit.module
@@ -67,12 +67,12 @@ function edit_page_alter(&$page) {
       'content' => array(
         array(
           '#theme' => 'menu_local_task',
-          '#link' => array('title' => t('View'), 'href' => $_GET['q'], 'localized_options' => array('attributes' => array('class' => array('edit_view-edit-toggle', 'edit-view')))),
+          '#link' => array('title' => t('View'), 'href' => $_GET['q'], 'localized_options' => array('fragment' => 'view', 'attributes' => array('class' => array('edit_view-edit-toggle', 'edit-view')))),
           '#active' => TRUE,
         ),
         array(
           '#theme' => 'menu_local_task',
-          '#link' => array('title' => t('Quick edit'), 'href' => '#', 'localized_options' => array('attributes' => array('class' => array('edit_view-edit-toggle', 'edit-edit')))),
+          '#link' => array('title' => t('Quick edit'), 'href' => $_GET['q'], 'localized_options' => array('fragment' => 'quick-edit', 'attributes' => array('class' => array('edit_view-edit-toggle', 'edit-edit')))),
         ),
       ),
       '#attached' => array(
diff --git a/js/edit.js b/js/edit.js
index ef17159..48ab400 100644
--- a/js/edit.js
+++ b/js/edit.js
@@ -15,6 +15,55 @@ Drupal.behaviors.edit = {
 Drupal.edit.constants = {};
 Drupal.edit.constants.transitionEnd = "transitionEnd.edit webkitTransitionEnd.edit transitionend.edit msTransitionEnd.edit oTransitionEnd.edit";
 
+// Temporary helper function: logging.
+Drupal.edit.debug = true;
+Drupal.edit.log = function() {
+  if (Drupal.edit.debug && window.console) {
+    console.log(Array.prototype.slice.call(arguments));
+  }
+};
+
+// Temporary helper function: (async) confirm dialog.
+Drupal.edit.confirm = function(message, options, cb) {
+  // @todo: use whatever confirm-dialog implementation we need.
+  if (window.confirm(message)) {
+    cb(true);
+  } else {
+    cb(false);
+  }
+};
+
+// Define Drupal.edit.routers.EditRouter.
+Drupal.edit.routers = {};
+Drupal.edit.routers.EditRouter = Backbone.Router.extend({
+  routes: {
+    "quick-edit": "edit",
+    "view": "view",
+    "": "view"
+  },
+  edit: function() {
+    Drupal.edit.state.set('isViewing', false);
+  },
+  view: function(query, page) {
+    // Let's make sure we do not lose any changes, if there is a currently
+    // active editableField?
+    if (Drupal.edit.state.get('editedFieldView') && Drupal.edit.state.get('editedFieldView').isDirty()) {
+      var that = this;
+      Drupal.edit.confirm(Drupal.t('Currently edited field has changes, do you want to proceed?'), {}, function(confirmed) {
+        if (!confirmed) {
+          that.navigate('#quick-edit');
+          return false;
+        } else {
+          Drupal.edit.state.set('isViewing', true);
+          return true;
+        }
+      });
+    } else {
+      Drupal.edit.state.set('isViewing', true);
+    }
+  }
+});
+
 Drupal.edit.init = function() {
   // VIE instance for Editing
   Drupal.edit.vie = new VIE();
@@ -36,7 +85,7 @@ Drupal.edit.init = function() {
   if (Drupal.settings.edit.wysiwyg) {
     $(document).bind('edit-wysiwyg-ready.edit', function() {
       Drupal.edit.state.set('wysiwygReady', true);
-      console.log('edit: WYSIWYG ready');
+      Drupal.edit.log('edit: WYSIWYG ready');
     });
     Drupal.edit.wysiwyg[Drupal.settings.edit.wysiwyg].init();
   }
@@ -47,24 +96,20 @@ Drupal.edit.init = function() {
   // Instantiate FieldViews
   Drupal.edit.domService.findSubjectElements().each(Drupal.edit.prepareFieldView);
 
-  // Instantiate overlayview
+  // Instantiate OverlayView
   var overlayView = new Drupal.edit.views.OverlayView({
     state: Drupal.edit.state
   });
 
-  // Transition between view/edit states.
-  $("a.edit_view-edit-toggle").bind('click.edit', function(event) {
-    event.preventDefault();
-
-    var isViewing = $(this).hasClass('edit-view');
-    Drupal.edit.state.set('isViewing', isViewing);
-
-    // swap active class among the two links.
-    $('a.edit_view-edit-toggle').removeClass('active');
-    $('a.edit_view-edit-toggle').parent().removeClass('active');
-    $('a.edit_view-edit-toggle.edit-' + (isViewing ? 'view' : 'edit')).addClass('active');
-    $('a.edit_view-edit-toggle.edit-' + (isViewing ? 'view' : 'edit')).parent().addClass('active');
+  // Instantiate MenuView
+  var editMenuView = new Drupal.edit.views.MenuView({
+    state: Drupal.edit.state
   });
+
+  // Instantiate EditRouter
+  var editRouter = new Drupal.edit.routers.EditRouter();
+  // Start Backbone's history/route handling
+  Backbone.history.start();
 };
 
 Drupal.edit.prepareStateModel = function () {
diff --git a/js/ui-editables.js b/js/ui-editables.js
index 16e7025..bf9293d 100644
--- a/js/ui-editables.js
+++ b/js/ui-editables.js
@@ -10,81 +10,24 @@ Drupal.edit = Drupal.edit || {};
 
 Drupal.edit.form = {
   create: function($editable, cb) {
+    // @todo: this needs to be refactored, we should have access to the view
+    // rather than the $editable/$el of the view.
     var entity = Drupal.edit.vie.entities.get(Drupal.edit.util.getElementSubject($editable));
     var predicate = Drupal.edit.util.getElementPredicate($editable);
-    var edit_id = entity.getSubjectUri() + ':' + predicate;
     var $field = Drupal.edit.util.findFieldForEditable($editable);
-    // @todo: this needs to be refactored, we should have access to the view
-    // rather than the $editable/$el of the view.
-    // moreover, we should probably be de-coupling this and trigger events
-    // instead of mucking with the toolbar from here.
-    var toolbarView = Drupal.edit.state.get('editedFieldView').getToolbarView();
-    var $toolbar = toolbarView.getToolbarElement();
+    var fieldView = Drupal.edit.state.get('editedFieldView');
     // We only create a placeholder-div/form for the form-based instances.
     if (Drupal.edit.form.get($editable).length > 0) {
       return false;
     }
-    else {
-      // Indicate in the 'info' toolgroup that the form is loading. Animated.
-      setTimeout(function() {
-        toolbarView.addClass('info', 'loading');
-      }, 0);
-
-      // Indicate in the 'info' toolgroup that the form is loading.
-      // Drupal.edit.toolbar.addClass($editable, 'primary', 'info', 'loading');
-      toolbarView.addClass('info', 'loading');
-
-      // Render form container.
-      var $form = $(Drupal.theme('editFormContainer', {
-        id: this._id($editable),
-        loadingMsg: Drupal.t('Loading…')}
-      ));
-
-      // Insert in DOM.
-      if ($editable.css('display') == 'inline') {
-        $form.prependTo($editable.offsetParent());
-
-        var pos = $editable.position();
-        $form.css('left', pos.left).css('top', pos.top);
-        // Reset the toolbar's positioning because it'll be moved inside the
-        // form container.
-        // Drupal.edit.toolbar.get($editable).css('left', '').css('top', '');
-        $toolbar.css('left', '').css('top', '');
-      }
-      else {
-        $form.insertBefore($editable);
-      }
-
-      // Move  toolbar inside .edit-form-container, to let it snap to the width
-      // of the form instead of the field formatter.
-      // Drupal.edit.toolbar.get($editable).detach().prependTo('.edit-form');
-      $toolbar.detach().prependTo('.edit-form');
-    }
-
+    // Show a loading form indicator
+    fieldView.showLoadingFormIndicator();
     var onLoadCallback = function(status, $form) {
       // @todo: re-factor
       var $submit;
       if ($field.hasClass('edit-type-form')) {
         var formWrapperId = Drupal.edit.form._id($editable);
-        // $form.wrap('<div>');
         $('#' + formWrapperId + ' .placeholder').replaceWith($form);
-
-        // Indicate in the 'info' toolgroup that the form has loaded.
-        // Drupal.edit.toolbar.removeClass($editable, 'primary', 'info', 'loading');
-        toolbarView.removeClass('info', 'loading');
-
-        // Detect changes in this form.
-        Drupal.edit.form.get($editable)
-          .delegate(':input', 'formUpdated.edit', function () {
-            $editable
-              .data('edit-content-changed', true)
-              .trigger('edit-content-changed.edit');
-          })
-          .delegate('input', 'keypress.edit', function (event) {
-            if (event.keyCode == 13) {
-              return false;
-            }
-          });
         $submit = Drupal.edit.form.get($editable).find('.edit-form-submit');
       } else if ($field.hasClass('edit-type-direct')) {
         // Direct forms are stuffed into #edit_backstage, apparently.
@@ -93,9 +36,7 @@ Drupal.edit.form = {
       }
       Drupal.edit.form._setupAjaxForm($editable, $field, $submit);
 
-      // Animations.
-      // Drupal.edit.toolbar.show($editable, 'ops');
-      toolbarView.show('ops');
+      // Trigger that the form has loaded.
       $editable.trigger('edit-form-loaded.edit');
 
       // callback to be able to decorate / continue with the editable...
@@ -132,7 +73,7 @@ Drupal.edit.form = {
   },
 
   remove: function($editable) {
-    console.log('Drupal.edit.form.remove', Drupal.edit.form.get($editable));
+    Drupal.edit.log('Drupal.edit.form.remove', Drupal.edit.form.get($editable));
     Drupal.edit.form.get($editable).remove();
   },
 
@@ -205,6 +146,7 @@ Drupal.edit.form = {
           // Stop the editing.
           var currentEditorView = Drupal.edit.state.get('editedFieldView');
           if (currentEditorView) {
+            // @todo: trigger event on the currentEditorView.
             currentEditorView.disableEditor();
           }
           // this is different from edit.module. did not understand what the
@@ -228,7 +170,7 @@ Drupal.edit.form = {
 
         // Shove the value into any field that isn't hidden or a submit button.
         $('#edit_backstage form').find(':input[type!="hidden"][type!="submit"]').val(value);
-        console.log('submitDirectForm', $submit, base, $('#edit_backstage form'));
+        Drupal.edit.log('submitDirectForm', $submit, base, $('#edit_backstage form'));
         // Set the callback.
         Drupal.ajax[base].commands.edit_field_form_saved = function(ajax, response, status) {
           // Direct forms are stuffed into #edit_backstage, apparently.
@@ -236,19 +178,15 @@ Drupal.edit.form = {
           $('#edit_backstage form').remove();
           // Removing Drupal.ajax-thingy.
           delete Drupal.ajax[base];
-          // @todo: title currently returns success but no response.data.
-          if (response.data) {
-            // Stop the editing.
-            var currentEditorView = Drupal.edit.state.get('editedFieldView');
-            if (currentEditorView) {
-              currentEditorView.disableEditor();
-            }
-            callback(null, $editable);
-          } else {
-            // @todo: handle errors, empty response?
-            console.log('no response data', response, status);
-            callback(true, $editable);
+          // @note: title currently returns success but no response.data.
+          // Stop the editing.
+          var currentEditorView = Drupal.edit.state.get('editedFieldView');
+          if (currentEditorView) {
+            // @todo: trigger event on the currentEditorView.
+            currentEditorView.disableEditor();
           }
+          // First argument is TRUE if response.data was returned.
+          callback(!!response.data, $editable);
         };
         $submit.trigger('click.edit');
       };
diff --git a/js/views.js b/js/views.js
index 2ef368a..96b57b8 100644
--- a/js/views.js
+++ b/js/views.js
@@ -8,7 +8,34 @@
     $toolbar:null,
     initialize:function (options) {
       this.fieldView = options.fieldView;
+      _.bindAll(this, 'fieldChanged', 'showLoadingFormIndicator');
+      // @note: we're binding events of the parent view. If we had a FieldModel
+      // we could bind to changes there.
+      this.fieldView.on('fieldChanged', this.fieldChanged);
+      this.fieldView.on('showLoadingFormIndicator', this.showLoadingFormIndicator);
+    },
+    // Adjust colour of Save button, when FieldView state is "dirty".
+    fieldChanged: function(dirty) {
+      if (dirty) {
+        this.getToolbarElement()
+          .find('a.save')
+          .addClass('blue-button')
+          .removeClass('gray-button');
+      }
+    },
+    // Adjust toolbar as editable is loading form.
+    showLoadingFormIndicator: function() {
+      // var that = this;
+      // Indicate in the 'info' toolgroup that the form is loading. Animated.
+      /* setTimeout(function() {
+        that.addClass('info', 'loading');
+      }, 0); */
+      // @todo: why do we do this twice?
+      // Indicate in the 'info' toolgroup that the form is loading.
+      // Drupal.edit.toolbar.addClass($editable, 'primary', 'info', 'loading');
+      this.addClass('info', 'loading');
     },
+
     getEditable:function () {
       return this.fieldView.$el;
     },
@@ -53,7 +80,7 @@
         .bind('mouseleave.edit', function (e) {
           var el = $editable[0];
           if (e.relatedTarget != el && !jQuery.contains(el, e.relatedTarget)) {
-            console.log('triggering mouseleave on ', $editable);
+            Drupal.edit.log('triggering mouseleave on ', $editable);
             $editable.trigger('mouseleave.edit');
           }
           // Prevent triggering the entity's mouse leave event.
@@ -174,6 +201,22 @@
     }
   });
 
+  Drupal.edit.views.MenuView = Backbone.View.extend({
+    initialize: function (options) {
+      this.state = options.state;
+      _.bindAll(this, 'stateChange');
+      this.state.bind('change:isViewing', this.stateChange);
+      // we have to call stateChange here, because theme_menu_local_task links
+      // do not take URL-fragments for consideration.
+      this.stateChange();
+    },
+    stateChange: function () {
+      $('a.edit_view-edit-toggle').removeClass('active');
+      $('a.edit_view-edit-toggle').parent().removeClass('active');
+      $('a.edit_view-edit-toggle.edit-' + (this.state.get('isViewing') ? 'view' : 'edit')).addClass('active').parent().addClass('active');
+    }
+  });
+
   Drupal.edit.views.OverlayView = Backbone.View.extend({
     state: null,
 
@@ -186,7 +229,6 @@
       _.bindAll(this, 'stateChange', 'escapeEditor');
       this.state.bind('change:isViewing', this.stateChange);
     },
-
     stateChange: function () {
       if (this.state.get('isViewing')) {
         this.hideOverlay();
@@ -194,7 +236,6 @@
       }
       this.showOverlay();
     },
-
     showOverlay: function () {
       $(Drupal.theme('editOverlay', {}))
       .appendTo('body')
@@ -247,6 +288,8 @@
     state: null,
     editable: false,
     editing: false,
+    // dirty state, i.e. unpersisted changes - @todo: move to a FieldModel?
+    dirty: false,
     vie: null,
     editableViews: [],
     toolbarView: null,
@@ -255,17 +298,24 @@
       'mouseenter': 'mouseEnter',
       'mouseleave': 'mouseLeave'
     },
+    // @todo - refactor into a Model?
+    isDirty: function() {
+      return this.dirty === true;
+    },
+    setDirty: function(value) {
+      // @todo - shouldn't we use FieldModel
+      this.trigger('fieldChanged', value);
+      this.dirty = value;
+    },
 
     initialize: function (options) {
       this.state = this.options.state;
       this.predicate = this.options.predicate;
       this.vie = this.options.vie;
 
-      _.bindAll(this, 'stateChange', 'mouseEnter', 'mouseLeave', 'checkHighlight');
+      _.bindAll(this, 'stateChange', 'mouseEnter', 'mouseLeave');
 
       this.state.on('change:isViewing', this.stateChange);
-      this.state.on('change:fieldBeingHighlighted', this.checkHighlight);
-
     },
 
     stateChange: function () {
@@ -302,7 +352,7 @@
       var self = this;
       Drupal.edit.util.ignoreHoveringVia(event, '.edit-toolbar-container', function () {
         if (!self.editing) {
-          console.log('field:mouseenter', self.model.id, self.predicate);
+          Drupal.edit.log('field:mouseenter', self.model.id, self.predicate);
           self.startHighlight();
         }
         event.stopPropagation();
@@ -320,7 +370,7 @@
       var self = this;
       Drupal.edit.util.ignoreHoveringVia(event, '.edit-toolbar-container', function () {
         if (!self.editing) {
-          console.log('field:mouseleave', self.model.id, self.predicate);
+          Drupal.edit.log('field:mouseleave', self.model.id, self.predicate);
           self.stopHighlight();
         }
         event.stopPropagation();
@@ -328,7 +378,7 @@
     },
 
     startHighlight: function () {
-      console.log('startHighlight', this.model.id, this.predicate);
+      Drupal.edit.log('startHighlight', this.model.id, this.predicate);
 
       // Animations.
       var self = this;
@@ -342,7 +392,7 @@
     },
 
     stopHighlight: function () {
-      console.log('stopHighlight', this.model.id, this.predicate);
+      Drupal.edit.log('stopHighlight', this.model.id, this.predicate);
       // Animations
       this.$el.removeClass('edit-highlighted');
       this.state.set('fieldBeingHighlighted', []);
@@ -352,14 +402,6 @@
 
     },
 
-    checkHighlight: function () {
-      // @todo: check why we just return here.
-      return;
-      /* if (this.state.get('fieldBeingHighlighted') === this.$el) {
-        return;
-      }
-      this.stopHighlight();*/
-    },
     enableToolbar: function () {
       if (!this.toolbarView) {
         this.toolbarView = new Drupal.edit.views.ToolbarView({
@@ -408,10 +450,9 @@
       this.predicate = this.options.predicate;
       this.vie = this.options.vie;
 
-      _.bindAll(this, 'stateChange', 'mouseEnter', 'mouseLeave', 'checkHighlight', 'enableEditor', 'editorEnabled', 'editorDisabled', 'contentChanged');
+      _.bindAll(this, 'stateChange', 'mouseEnter', 'mouseLeave', 'enableEditor', 'editorEnabled', 'editorDisabled', 'contentChanged');
 
       this.state.on('change:isViewing', this.stateChange);
-      this.state.on('change:fieldBeingHighlighted', this.checkHighlight);
     },
 
     stateChange: function () {
@@ -448,6 +489,11 @@
     },
 
     enableEditor: function (event) {
+      if (event) {
+        event.stopPropagation();
+        event.preventDefault();
+      }
+
       if (!this.editable) {
         // Not in edit state, ignore
         return;
@@ -458,34 +504,44 @@
         return;
       }
 
-      if (event) {
-        event.stopPropagation();
-        event.preventDefault();
-      }
-
-      this.startHighlight();
-
-      this.$el
-      .addClass('edit-editing')
-      .css('background-color', this.$el.data('edit-background-color'));
+      var that = this;
+      var _enableEditor = function() {
+        that.startHighlight();
+        that.$el
+        .addClass('edit-editing')
+        .css('background-color', that.$el.data('edit-background-color'));
 
-      // Ensure others are not editable when we are
-      if (this.state.get('editedFieldView')) {
-        this.state.get('editedFieldView').disableEditor();
+        // Ensure others are not editable when we are
+        if (that.state.get('editedFieldView')) {
+          that.state.get('editedFieldView').disableEditor();
+        }
+        // @todo: we currently need to set that to access the current FieldView
+        // in ui-editable.js which is horrible.
+        that.state.set('editedFieldView', that);
+        // Start the Create.js editable widget
+        that.enableEditableWidget();
+        // Enable the toolbar with the save and close buttons
+        that.enableToolbar();
+
+        that.state.set('fieldBeingEdited', that.$el);
+        that.state.set('editedEditable', Drupal.edit.util.getID(that.$el));
+        that.state.set('editedFieldView', that);
+      };
+
+      // Let's make sure we do not lose any changes, if there is a currently
+      // active editableField?
+      if (this.state.get('editedFieldView') && this.state.get('editedFieldView').isDirty()) {
+        // (Async) confirmation of possibly losing changes.
+        Drupal.edit.confirm(Drupal.t('Currently edited field has changes, do you want to proceed?'), {}, function(confirmed) {
+          if (!confirmed) {
+            return false;
+          }
+          _enableEditor();
+        });
+      } else {
+        _enableEditor();
       }
-      // @todo: we currently need to set this to access the current FieldView
-      // in ui-editable.js which is horrible.
-      this.state.set('editedFieldView', this);
-      // Start the Create.js editable widget
-      this.enableEditableWidget();
-      // Enable the toolbar with the save and close buttons
-      this.enableToolbar();
-
-      this.state.set('fieldBeingEdited', this.$el);
-      this.state.set('editedEditable', Drupal.edit.util.getID(this.$el));
-      this.state.set('editedFieldView', this);
     },
-
     enableEditableWidget: function () {
       this.$el.createEditable({
         vie: this.vie,
@@ -494,7 +550,7 @@
     },
 
     disableEditor: function () {
-      console.log('disableEditor', this.model.id, this.predicate);
+      Drupal.edit.log('disableEditor', this.model.id, this.predicate);
 
       this.$el
       .removeClass('edit-editing')
@@ -521,7 +577,7 @@
     },
 
     editorEnabled: function () {
-      console.log("editorenabled", this.model.id, this.predicate);
+      Drupal.edit.log("editorenabled", this.model.id, this.predicate);
       // Avoid re-"padding" of editable.
       if (!this.editing) {
         this.padEditable();
@@ -531,8 +587,8 @@
       this.getToolbarView().show('wysiwyg');
       // Show the ops (save, close) as well.
       this.getToolbarView().show('ops');
-      // hmm, why in the DOM?
-      this.$el.data('edit-content-changed', false);
+
+      this.setDirty(false);
       this.$el.trigger('edit-form-loaded.edit');
       this.editing = true;
     },
@@ -617,7 +673,7 @@
 
       // 1) Set the empty width again.
       if (this.$el.data('edit-width-empty') === true) {
-        console.log('restoring width');
+        Drupal.edit.log('restoring width');
         this.$el
         .addClass('edit-animate-disable-width')
         .css('width', '');
@@ -668,16 +724,11 @@
       this.$el.removeClass('edit-wysiwyg-attached');
 
       this.editing = false;
+      this.setDirty(false);
     },
 
     contentChanged: function () {
-      this.$el.data('edit-content-changed', true);
-      this.$el.trigger('edit-content-changed.edit');
-
-      this.getToolbarElement()
-      .find('a.save')
-      .addClass('blue-button')
-      .removeClass('gray-button');
+      this.setDirty(true);
     }
   });
 
@@ -692,6 +743,19 @@
         vie: this.vie,
         disabled: false
       });
+
+      var toolbarView = this.getToolbarView();
+      var that = this;
+      // @todo - use backbone events.
+      this.$el.bind('edit-form-loaded.edit', function() {
+        // Indicate in the 'info' toolgroup that the form has loaded.
+        // Drupal.edit.toolbar.removeClass($editable, 'primary', 'info', 'loading');
+        toolbarView.removeClass('info', 'loading');
+        toolbarView.show('ops');
+
+        // Bind events
+        that.bindFormChanges();
+      });
     },
 
     disableEditableWidget: function () {
@@ -699,6 +763,7 @@
         vie: this.vie,
         disabled: true
       });
+      this.$el.unbind('edit-form-loaded.edit');
     },
 
     saveClicked: function (event) {
@@ -716,8 +781,62 @@
         // Restart the editable.
         that.startEditable();
       });
-    }
+    },
+    // Refactored from ui-editables.js
+    showLoadingFormIndicator: function() {
+      // Render form container.
+      var $form = $(Drupal.theme('editFormContainer', {
+        id: Drupal.edit.form._id(this.$el),
+        loadingMsg: Drupal.t('Loading…')}
+      ));
 
+      var $editable = this.$el;
+      // Append  & insert in DOM.
+      if ($editable.css('display') == 'inline') {
+        $form.prependTo($editable.offsetParent());
+
+        var pos = $editable.position();
+        $form.css('left', pos.left).css('top', pos.top);
+        // Reset the toolbar's positioning because it'll be moved inside the
+        // form container.
+        // Drupal.edit.toolbar.get($editable).css('left', '').css('top', '');
+        this.getToolbarElement().css('left', '').css('top', '');
+      }
+      else {
+        $form.insertBefore($editable);
+      }
+
+      // Move  toolbar inside .edit-form-container, to let it snap to the width
+      // of the form instead of the field formatter.
+      // Drupal.edit.toolbar.get($editable).detach().prependTo('.edit-form');
+      this.getToolbarElement().detach().prependTo('.edit-form');
+
+      // Trigger this event to propagate to the appropriate ToolbarView.
+      this.trigger('showLoadingFormIndicator');
+    },
+    // Refactored from ui-editables.js
+    bindFormChanges: function() {
+      var that = this;
+      // Detect changes in this form.
+      Drupal.edit.form.get(this.$el)
+        .delegate(':input', 'change.edit', function () {
+          // Make sure we track changes
+          // @todo: trigger createjs' 'createeditablechanged' event rather
+          // than calling the method directly?
+          that.contentChanged();
+        })
+        .delegate('input', 'keypress.edit', function (event) {
+          if (event.keyCode == 13) {
+            return false;
+          }
+        });
+    },
+    // Refactored from ui-editables.js
+    unbindFormChanges: function() {
+      Drupal.edit.form.get(this.$el)
+        .undelegate(':input', 'change.edit')
+        .undelegate('input', 'keypress.edit');
+    }
   });
 
 })(jQuery);
