 core/misc/edit.png                                 |    3 +
 core/modules/contextual/contextual.js              |   47 ++++++++--
 core/modules/contextual/contextual.theme.css       |   33 ++++---
 core/modules/edit/css/edit.css                     |   14 +--
 core/modules/edit/edit.module                      |   11 +++
 core/modules/edit/images/icon-edit-active.png      |    7 +-
 core/modules/edit/images/icon-edit.png             |    5 --
 core/modules/edit/js/app.js                        |   42 ++++++---
 .../editingWidgets/drupalcontenteditablewidget.js  |    8 +-
 .../edit/js/createjs/editingWidgets/formwidget.js  |   10 +--
 core/modules/edit/js/models/edit-app-model.js      |    1 +
 core/modules/edit/js/views/contextuallink-view.js  |   94 ++++++++++++++++++++
 core/modules/edit/js/views/menu-view.js            |   22 +++++
 .../edit/js/views/propertyeditordecoration-view.js |   20 +++++
 core/modules/edit/js/views/toolbar-view.js         |   18 ++--
 .../node/lib/Drupal/node/NodeRenderController.php  |    6 +-
 core/modules/node/node.module                      |    3 +-
 17 files changed, 274 insertions(+), 70 deletions(-)

diff --git a/core/misc/edit.png b/core/misc/edit.png
new file mode 100644
index 0000000..d176245
--- /dev/null
+++ b/core/misc/edit.png
@@ -0,0 +1,3 @@
+PNG
+
+   IHDR         !-  #IDATxڵ́@EєKH)%XHDDĀ(Fl,ᗐۻ0BI>80LҿfPԠȾjpŰG.E4־kdpa:Ǐǣ79Bp08OTYv;C	n8!C	fcp(#=^Uu%_V9T{l\Vy/X,E{n>Zwf5x@EQ t:C[L&9jȳ/$UW5    IENDB`
\ No newline at end of file
diff --git a/core/modules/contextual/contextual.js b/core/modules/contextual/contextual.js
index dee63e6..67a333e 100644
--- a/core/modules/contextual/contextual.js
+++ b/core/modules/contextual/contextual.js
@@ -7,6 +7,8 @@
 
 "use strict";
 
+var contextuals = [];
+
 /**
  * Attaches outline behavior for regions associated with contextual links.
  */
@@ -14,7 +16,14 @@ Drupal.behaviors.contextual = {
   attach: function (context) {
     $('ul.contextual-links', context).once('contextual', function () {
       var $this = $(this);
-      $this.data('drupal-contextual', new Drupal.contextual($this, $this.closest('.contextual-region')));
+      var contextual = new Drupal.contextual($this, $this.closest('.contextual-region'));
+      contextuals.push(contextual);
+      $this.data('drupal-contextual', contextual);
+    });
+    // Bind to global edit mode changes
+    $('body').once('contextual', function (index, element) {
+      $(document)
+        .on('drupalEditMode.contextual', toggleEditMode);
     });
   }
 };
@@ -54,15 +63,32 @@ Drupal.contextual.prototype.init = function() {
     .attr('aria-pressed', false)
     .prependTo(this.$wrapper);
 
-  // Bind behaviors through delegation.
-  var highlightRegion = $.proxy(this.highlightRegion, this);
+  // The trigger behaviors are never detached or mutated.
   this.$region
     .on('click.contextual', '.contextual .trigger', $.proxy(this.triggerClickHandler, this))
-    .on('mouseenter.contextual', {highlight: true}, highlightRegion)
-    .on('mouseleave.contextual', {highlight: false}, highlightRegion)
     .on('mouseleave.contextual', '.contextual', {show: false}, $.proxy(this.triggerLeaveHandler, this))
-    .on('focus.contextual', '.contextual-links a, .contextual .trigger', {highlight: true}, highlightRegion)
-    .on('blur.contextual', '.contextual-links a, .contextual .trigger', {highlight: false}, highlightRegion);
+  // Attach highlight behaviors.
+  this.attachHighlightBehaviors();
+};
+
+/**
+ *
+ */
+Drupal.contextual.prototype.attachHighlightBehaviors = function () {
+  // Bind behaviors through delegation.
+  var highlightRegion = $.proxy(this.highlightRegion, this);
+  this.$region
+    .on('mouseenter.contextual.highlight', {highlight: true}, highlightRegion)
+    .on('mouseleave.contextual.highlight', {highlight: false}, highlightRegion)
+    .on('focus.contextual.highlight', '.contextual-links a, .contextual .trigger', {highlight: true}, highlightRegion)
+    .on('blur.contextual.highlight', '.contextual-links a, .contextual .trigger', {highlight: false}, highlightRegion);
+};
+
+/**
+ *
+ */
+Drupal.contextual.prototype.detachHighlightBehaviors = function () {
+  this.$region.off('.contextual.highlight');
 };
 
 /**
@@ -138,6 +164,13 @@ Drupal.contextual.prototype.showLinks = function(show) {
 
 };
 
+function toggleEditMode (event, data) {
+  for (var i = contextuals.length - 1; i >= 0; i--) {
+    contextuals[i][(data.editable) ? 'detachHighlightBehaviors' : 'attachHighlightBehaviors']();
+    contextuals[i].$region.toggleClass('contextual-region-active', data.editable);
+  };
+}
+
 /**
  * Wraps contextual links.
  *
diff --git a/core/modules/contextual/contextual.theme.css b/core/modules/contextual/contextual.theme.css
index aca019c..ac6a1c4 100644
--- a/core/modules/contextual/contextual.theme.css
+++ b/core/modules/contextual/contextual.theme.css
@@ -21,28 +21,31 @@
  * Contextual trigger.
  */
 .contextual .trigger {
-  background: transparent url("images/gear-select.png") no-repeat 2px 0;
-  border: 1px solid transparent;
-  border-radius: 4px 4px 0 0;
+  background-attachment: scroll;
+  background-color: #ffffff;
+  background-image: url("../../misc/edit.png");
+  background-position: center center;
+  background-repeat: no-repeat;
+  background-size: 16px 16px;
+  border: 1px solid #dddddd;
+  border-radius: 13px;
+  box-shadow: 1px 1px 2px rgba(0,0,0,0.3);
   /* Override the .element-focusable height: auto */
-  height: 18px !important;
+  height: 28px !important;
   float: right; /* LTR */
   margin: 0;
   overflow: hidden;
   padding: 0 2px;
   position: relative;
-  width: 34px;
+  right: 2px;
+  width: 28px;
   text-indent: -9999px;
   z-index: 2;
 }
-.no-touch .contextual .trigger:hover,
 .contextual-links-active .trigger {
-  background-position: 2px -18px;
-}
-.contextual-links-active .trigger {
-  background-color: #fff;
-  border-bottom: none;
-  border-color: #d6d6d6;
+  border-bottom-color: transparent;
+  border-radius: 13px 13px 0 0;
+  box-shadow: none;
 }
 
 /**
@@ -52,7 +55,7 @@
  */
 .contextual-region .contextual .contextual-links {
   background-color: #fff;
-  border: 1px solid #d6d6d6;
+  border: 1px solid #dddddd;
   border-radius: 4px 0 4px 4px; /* LTR */
   clear: both;
   float: right; /* LTR */
@@ -90,5 +93,7 @@
   text-decoration: none;
 }
 .no-touch .contextual-region .contextual .contextual-links li a:hover {
-  background-color: #bfdcee;
+  color: white;
+  background-image: -webkit-linear-gradient(rgb(78,159,234) 0%,rgb(65,126,210) 100%);
+  background-image: linear-gradient(rgb(78,159,234) 0%,rgb(65,126,210) 100%);
 }
diff --git a/core/modules/edit/css/edit.css b/core/modules/edit/css/edit.css
index 37e10eb..fcf8893 100644
--- a/core/modules/edit/css/edit.css
+++ b/core/modules/edit/css/edit.css
@@ -75,10 +75,10 @@
  * Toolbar.
  */
 .icon-edit:before {
-  background-image: url("../images/icon-edit.png");
+  background-image: url("../../../misc/edit.png");
 }
 .icon-edit:active:before,
-.active .icon-edit:before {
+.active.icon-edit:before {
   background-image: url("../images/icon-edit-active.png");
 }
 .toolbar .tray.edit.active {
@@ -103,11 +103,10 @@
 
 #edit_overlay {
   position: fixed;
-  z-index: 250;
+  /* @todo remove edit-overlay, not needed in this model */
+  z-index: -200000;
   width: 100%;
   height: 100%;
-  background-color: #fff;
-  background-color: rgba(255,255,255,.5);
   top: 0;
   left: 0;
 }
@@ -127,6 +126,7 @@
 
 /* Highlighted (hovered) editable. */
 .edit-editable.edit-highlighted {
+  z-index: 305;
   min-width: 200px;
 }
 .edit-field.edit-editable.edit-highlighted,
@@ -279,6 +279,10 @@
   bottom: 1px;
   box-shadow: 0 0 1px 1px #0199ff, 0 0 3px 3px rgba(153, 153, 153, .5);
   background: #fff;
+  display: none;
+}
+.edit-highlighted .edit-toolbar-heightfaker {
+  display: block;
 }
 
 /* The toolbar; these are not necessarily visible. */
diff --git a/core/modules/edit/edit.module b/core/modules/edit/edit.module
index 584cace..cb67596 100644
--- a/core/modules/edit/edit.module
+++ b/core/modules/edit/edit.module
@@ -98,6 +98,7 @@ function edit_library_info() {
       // Views.
       $path . '/js/views/propertyeditordecoration-view.js' => $options,
       $path . '/js/views/menu-view.js' => $options,
+      $path . '/js/views/contextuallink-view.js' => $options,
       $path . '/js/views/modal-view.js' => $options,
       $path . '/js/views/overlay-view.js' => $options,
       $path . '/js/views/toolbar-view.js' => $options,
@@ -171,6 +172,16 @@ function edit_preprocess_field(&$variables) {
 }
 
 /**
+ * Implements hook_preprocess_HOOK() for node.tpl.php.
+ *
+ * @todo Move towards hook_preprocess_entity() once that's available.
+ */
+function edit_preprocess_node(&$variables) {
+  $node = $variables['elements']['#node'];
+  $variables['attributes']['data-edit-entity'] = 'node/' . $node->nid;
+}
+
+/**
  * Form constructor for the field editing form.
  *
  * @ingroup forms
diff --git a/core/modules/edit/images/icon-edit-active.png b/core/modules/edit/images/icon-edit-active.png
index ad84761..a9143aa 100644
--- a/core/modules/edit/images/icon-edit-active.png
+++ b/core/modules/edit/images/icon-edit-active.png
@@ -1,3 +1,8 @@
 PNG
 
-   IHDR         j	   `PLTE   [   tRNS@ P00p`ϟ Dƙ   IDATxe DQ8Ϩ/BDU9xV+D\?x@qWcF8wicS B}?v;Vf.V$JgX=Kضp0XS"iRw\:LL\~;Z5wu 5E)L    IENDB`
\ No newline at end of file
+   IHDR         !-  IDATxڭmP]@	)(%P GܕHX@JH<(4p|O%}y Y~
+tu&0hA+\l'Sv'`^+yX
+)DsqV+9%FaHrTCͦs"6
+sPa%"y{{Soր=!_\Ay}O`|l0GE+!&hdY0'/M`NR!C2Nh~CR˂sW9yiH.	"D0G\Od2Q
+R>Hq.APa`0.h߹#.~_az&.w&Ha*ѿ
+⹆M0Gia	MHn0GCNsn+Cժa"B O+}37    IENDB`
\ No newline at end of file
diff --git a/core/modules/edit/images/icon-edit.png b/core/modules/edit/images/icon-edit.png
deleted file mode 100644
index 4f0dcc2..0000000
--- a/core/modules/edit/images/icon-edit.png
+++ /dev/null
@@ -1,5 +0,0 @@
-PNG
-
-   IHDR         j	   PLTE̻ʪ̡̜ˠ̣̽¼Ƿ   ʨªZ(e   +tRNSϟ `π@`0p0p`0Pϟϟ c   IDATxeW0 {W
-H"ʵ,y{Hpyo?mf,RBRxBvL;&LPJaRb\(Tbn(1wϔJ)ԈkS
-58äT^4 P6c}[i	<ާ'-+HP>K    IENDB`
\ No newline at end of file
diff --git a/core/modules/edit/js/app.js b/core/modules/edit/js/app.js
index 00bba20..10c936b 100644
--- a/core/modules/edit/js/app.js
+++ b/core/modules/edit/js/app.js
@@ -60,7 +60,7 @@
       });
 
       // When view/edit mode is toggled in the menu, update the editor widgets.
-      this.model.on('change:isViewing', this.appStateChange);
+      this.model.on('change:activeEntity', this.appStateChange);
     },
 
     /**
@@ -74,7 +74,7 @@
      */
     findEditableProperties: function($context) {
       var that = this;
-      var newState = (this.model.get('isViewing')) ? 'inactive' : 'candidate';
+      var activeEntity = this.model.get('activeEntity');
 
       this.domService.findSubjectElements($context).each(function() {
         var $element = $(this);
@@ -103,10 +103,17 @@
           .on('destroyedPropertyEditor.edit', function(event, editor) {
             that.undecorateEditor(editor);
             that.$entityElements = that.$entityElements.not($(this));
-
           })
-          // Transition the new PropertyEditor into the current state.
-          .createEditable('setState', newState);
+          // Transition the new PropertyEditor into the default state.
+          .createEditable('setState', 'inactive');
+
+        // If the new PropertyEditor is for the entity that's currently being
+        // edited, then transition it to the 'candidate' state.
+        // (This happens when a field was modified and is re-rendered.)
+        var entityOfProperty = $element.createEditable('option', 'model');
+        if (entityOfProperty.getSubjectUri() === activeEntity) {
+          $element.createEditable('setState', 'candidate');
+        }
 
         // Add this new EditableEntity widget element to the list.
         that.$entityElements = that.$entityElements.add($element);
@@ -116,18 +123,30 @@
     /**
      * Sets the state of PropertyEditor widgets when edit mode begins or ends.
      *
-     * Should be called whenever EditAppModel's "isViewing" changes.
+     * Should be called whenever EditAppModel's "activeEntity" changes.
      */
     appStateChange: function() {
       // @todo: BLOCKED_ON(Create.js, https://github.com/bergie/create/issues/133, https://github.com/bergie/create/issues/140)
       // We're currently setting the state on EditableEntity widgets instead of
       // PropertyEditor widgets, because of
       // https://github.com/bergie/create/issues/133.
-      var newState = (this.model.get('isViewing')) ? 'inactive' : 'candidate';
+
+      var activeEntity = this.model.get('activeEntity');
+      var $editableFieldsForEntity = $('[data-edit-id^="' + activeEntity + '/"]');
+
+      // First, change the status of all PropertyEditor widgets to 'inactive'.
       this.$entityElements.each(function() {
-        $(this).createEditable('setState', newState);
+        $(this).createEditable('setState', 'inactive', null, {reason: 'stop'});
       });
+
+      // Then, change the status of PropertyEditor widgets of the currently
+      // active entity to 'candidate'.
+      $editableFieldsForEntity.each(function() {
+        $(this).createEditable('setState', 'candidate');
+      });
+
       // Manage the page's tab indexes.
+      /*
       if (newState === 'candidate') {
         this._manageDocumentFocus();
         Drupal.edit.setMessage(Drupal.t('In place edit mode is active'), Drupal.t('Page navigation is limited to editable items.'), Drupal.t('Press escape to exit'));
@@ -136,6 +155,7 @@
         this._releaseDocumentFocusManagement();
         Drupal.edit.setMessage(Drupal.t('Edit mode is inactive.'), Drupal.t('Resume normal page navigation'));
       }
+      */
     },
 
     /**
@@ -159,9 +179,9 @@
 
       // If the app is in view mode, then reject all state changes except for
       // those to 'inactive'.
-      if (this.model.get('isViewing')) {
-        if (to !== 'inactive') {
-          accept = false;
+      if (context && context.reason === 'stop') {
+        if (from === 'candidate' && to === 'inactive') {
+          accept = true;
         }
       }
       // Handling of edit mode state changes is more granular.
diff --git a/core/modules/edit/js/createjs/editingWidgets/drupalcontenteditablewidget.js b/core/modules/edit/js/createjs/editingWidgets/drupalcontenteditablewidget.js
index 5671f39..caac604 100644
--- a/core/modules/edit/js/createjs/editingWidgets/drupalcontenteditablewidget.js
+++ b/core/modules/edit/js/createjs/editingWidgets/drupalcontenteditablewidget.js
@@ -29,13 +29,6 @@
     _initialize: function() {
       var that = this;
 
-      // Sets the state to 'activated' upon clicking the element.
-      this.element.on("click.edit", function(event) {
-        event.stopPropagation();
-        event.preventDefault();
-        that.options.activated();
-      });
-
       // Sets the state to 'changed' whenever the content has changed.
       var before = jQuery.trim(this.element.text());
       this.element.on('keyup paste', function (event) {
@@ -68,6 +61,7 @@
         case 'highlighted':
           break;
         case 'activating':
+          this.options.activated();
           break;
         case 'active':
           // Sets the "contenteditable" attribute to "true".
diff --git a/core/modules/edit/js/createjs/editingWidgets/formwidget.js b/core/modules/edit/js/createjs/editingWidgets/formwidget.js
index 3238566..ac89857 100644
--- a/core/modules/edit/js/createjs/editingWidgets/formwidget.js
+++ b/core/modules/edit/js/createjs/editingWidgets/formwidget.js
@@ -29,15 +29,7 @@
     /**
      * Implements Create's _initialize() method.
      */
-    _initialize: function() {
-      // Sets the state to 'activating' upon clicking the element.
-      var that = this;
-      this.element.on("click.edit", function(event) {
-        event.stopPropagation();
-        event.preventDefault();
-        that.options.activating();
-      });
-    },
+    _initialize: function() {},
 
     /**
      * Makes this PropertyEditor widget react to state changes.
diff --git a/core/modules/edit/js/models/edit-app-model.js b/core/modules/edit/js/models/edit-app-model.js
index b6ff36f..1e4dcc6 100644
--- a/core/modules/edit/js/models/edit-app-model.js
+++ b/core/modules/edit/js/models/edit-app-model.js
@@ -12,6 +12,7 @@ Drupal.edit.models.EditAppModel = Backbone.Model.extend({
   defaults: {
     // We always begin in view mode.
     isViewing: true,
+    activeEntity: null,
     highlightedEditor: null,
     activeEditor: null,
     // Reference to a ModalView-instance if a transition requires confirmation.
diff --git a/core/modules/edit/js/views/contextuallink-view.js b/core/modules/edit/js/views/contextuallink-view.js
new file mode 100644
index 0000000..cb6a2f6
--- /dev/null
+++ b/core/modules/edit/js/views/contextuallink-view.js
@@ -0,0 +1,94 @@
+/**
+ * @file
+ * A Backbone View that a dynamic contextual link.
+ */
+(function ($, _, Backbone, Drupal) {
+
+"use strict";
+
+Drupal.edit = Drupal.edit || {};
+Drupal.edit.views = Drupal.edit.views || {};
+Drupal.edit.views.ContextualLinkView = Backbone.View.extend({
+
+  entity: null,
+
+  events: {
+    'click': 'onClick'
+  },
+
+  /**
+   * Implements Backbone Views' initialize() function.
+   *
+   * @param options
+   *   An object with the following keys:
+   *   - entity: the entity ID (e.g. node/1) of the entity
+   */
+  initialize: function (options) {
+    this.entity = options.entity;
+
+    // Initial render.
+    this.render();
+
+    // Re-render whenever the app state's active entity changes.
+    this.model.on('change:activeEntity', this.render, this);
+  },
+
+  /**
+   * Equates clicks anywhere on the overlay to clicking the active editor's (if
+   * any) "close" button.
+   *
+   * @param {Object} event
+   */
+  onClick: function (event) {
+    event.preventDefault();
+
+    var that = this;
+    var updateActiveEntity = function() {
+      // The active entity is the current entity, i.e. stop editing the current
+      // entity.
+      if (that.model.get('activeEntity') === that.entity) {
+        that.model.set('activeEntity', null);
+      }
+      // The active entity is different from the current entity, i.e. start
+      // editing this entity instead of the previous one.
+      else {
+        that.model.set('activeEntity', that.entity);
+      }
+    };
+
+    // If there's an active editor, attempt to set its state to 'candidate', and
+    // only then do what the user asked.
+    // (Only when all PropertyEditor widgets of an entity are in the 'candidate'
+    // state, it is possible to stop editing it.)
+    var activeEditor = this.model.get('activeEditor');
+    if (activeEditor) {
+      var editableEntity = activeEditor.options.widget;
+      var predicate = activeEditor.options.property;
+      editableEntity.setState('candidate', predicate, { reason: 'stop or switch' }, function(accepted) {
+        if (accepted) {
+          updateActiveEntity();
+        }
+        else {
+          // No change.
+        }
+      });
+    }
+    // Otherwise, we can immediately do what the user asked.
+    else {
+      updateActiveEntity();
+    }
+  },
+
+  /**
+   * Render the "Quick edit" contextual link.
+   */
+  render: function () {
+    var activeEntity = this.model.get('activeEntity');
+    var string = (activeEntity !== this.entity) ? Drupal.t('Quick edit') : Drupal.t('Stop quick edit');
+    this.$el.html('<a href="">' + string + '</a>');
+    return this;
+  }
+
+});
+
+})(jQuery, _, Backbone, Drupal);
diff --git a/core/modules/edit/js/views/menu-view.js b/core/modules/edit/js/views/menu-view.js
index ac7c4e4..d5e34d4 100644
--- a/core/modules/edit/js/views/menu-view.js
+++ b/core/modules/edit/js/views/menu-view.js
@@ -34,13 +34,33 @@ Drupal.edit.views.MenuView = Backbone.View.extend({
     $('#toolbar-administration').on('click.edit', '.bar a:not(#toolbar-tab-edit)', _.bind(function (event) {
       this.model.set('isViewing', true);
     }, this));
+
     // We have to call stateChange() here because URL fragments are not passed
     // to the server, thus the wrong anchor may be marked as active.
     this.stateChange();
+
+    // Add "Quick edit" links to all contextual menus where editing the full
+    // node is possible.
+    // @todo Generalize this to work for all entities.
+    var that = this;
+    $('ul.contextual-links li.node-edit')
+      .before('<li class="quick-edit"></li>')
+      .each(function() {
+        // Instantiate ContextualLinkView.
+        var $editContextualLink = $(this).prev();
+        var editContextualLinkView = new Drupal.edit.views.ContextualLinkView({
+          el: $editContextualLink.get(0),
+          model: that.model,
+          entity: $editContextualLink.parents('[data-edit-entity]').attr('data-edit-entity')
+        });
+      });
   },
 
   /**
    * Listens to app state changes.
+   *
+   * @todo This stuff is all for the "Edit mode" toggle, which doesn't really
+   * belong in Edit.module anymore.
    */
   stateChange: function() {
     var isViewing = this.model.get('isViewing');
@@ -64,6 +84,8 @@ Drupal.edit.views.MenuView = Backbone.View.extend({
         Drupal.toolbar.setHeight();
       }
     }
+    // Let other modules respond to the edit mode change.
+    $(document).trigger('drupalEditMode', {'editable': !isViewing});
   },
   /**
    * Handles clicks on the edit tab of the toolbar.
diff --git a/core/modules/edit/js/views/propertyeditordecoration-view.js b/core/modules/edit/js/views/propertyeditordecoration-view.js
index 0eb4e45..aad9832 100644
--- a/core/modules/edit/js/views/propertyeditordecoration-view.js
+++ b/core/modules/edit/js/views/propertyeditordecoration-view.js
@@ -19,6 +19,7 @@ Drupal.edit.views.PropertyEditorDecorationView = Backbone.View.extend({
   events: {
     'mouseenter.edit' : 'onMouseEnter',
     'mouseleave.edit' : 'onMouseLeave',
+    'click': 'onClick',
     'tabIn.edit': 'onMouseEnter',
     'tabOut.edit': 'onMouseLeave'
   },
@@ -38,7 +39,12 @@ Drupal.edit.views.PropertyEditorDecorationView = Backbone.View.extend({
     this.editor = options.editor;
     this.toolbarId = options.toolbarId;
 
+    this.predicate = this.editor.options.property;
+
     this.$el.css('background-color', this._getBgColor(this.$el));
+
+    // Only start listening to events as soon as we're no longer in the 'inactive' state.
+    this.undelegateEvents();
   },
 
   /**
@@ -113,13 +119,27 @@ Drupal.edit.views.PropertyEditorDecorationView = Backbone.View.extend({
     });
   },
 
+  /**
+   * Clicks: transition to 'activating' stage.
+   *
+   * @param event
+   */
+  onClick: function(event) {
+    var editableEntity = this.editor.options.widget;
+    editableEntity.setState('activating', this.predicate);
+    event.preventDefault();
+    event.stopPropagation();
+  },
+
   decorate: function () {
     this.$el.addClass('edit-animate-fast edit-candidate edit-editable');
+    this.delegateEvents();
   },
 
   undecorate: function () {
     this.$el
       .removeClass('edit-candidate edit-editable edit-highlighted edit-editing');
+    this.undelegateEvents();
   },
 
   startHighlight: function () {
diff --git a/core/modules/edit/js/views/toolbar-view.js b/core/modules/edit/js/views/toolbar-view.js
index 90f5db7..b052362 100644
--- a/core/modules/edit/js/views/toolbar-view.js
+++ b/core/modules/edit/js/views/toolbar-view.js
@@ -29,7 +29,7 @@ Drupal.edit.views.ToolbarView = Backbone.View.extend({
     'click.edit button.label': 'onClickInfoLabel',
     'mouseleave.edit': 'onMouseLeave',
     'click.edit button.field-save': 'onClickSave',
-    'click.edit button.field-close': 'onClickClose'
+    'click.edit button.field-close': 'onClickClose',
   },
 
   /**
@@ -66,19 +66,26 @@ Drupal.edit.views.ToolbarView = Backbone.View.extend({
   stateChange: function(from, to) {
     switch (to) {
       case 'inactive':
-        // Nothing happens in this stage.
+        if (from) {
+          this.remove();
+        }
         break;
       case 'candidate':
-        if (from !== 'inactive') {
+        if (from === 'inactive') {
+          this.render();
+        }
+        else {
+          // Remove all toolgroups; they're no longer necessary.
+          this.$el
+            .removeClass('edit-highlighted edit-editing')
+            .find('.edit-toolbar .edit-toolgroup').remove();
           if (from !== 'highlighted' && this.getEditUISetting('padding')) {
             this._unpad();
           }
-          this.remove();
         }
         break;
       case 'highlighted':
         // As soon as we highlight, make sure we have a toolbar in the DOM (with at least a title).
-        this.render();
         this.startHighlight();
         break;
       case 'activating':
@@ -275,6 +282,7 @@ Drupal.edit.views.ToolbarView = Backbone.View.extend({
     }
 
     this.$el
+      .addClass('edit-highlighted')
       .find('.edit-toolbar')
       // Append the "info" toolgroup into the toolbar.
       .append(Drupal.theme('editToolgroup', {
diff --git a/core/modules/node/lib/Drupal/node/NodeRenderController.php b/core/modules/node/lib/Drupal/node/NodeRenderController.php
index e829e40..6a6608a 100644
--- a/core/modules/node/lib/Drupal/node/NodeRenderController.php
+++ b/core/modules/node/lib/Drupal/node/NodeRenderController.php
@@ -88,11 +88,7 @@ public function buildContent(array $entities, array $displays, $view_mode, $lang
    */
   protected function alterBuild(array &$build, EntityInterface $entity, EntityDisplay $display, $view_mode, $langcode = NULL) {
     parent::alterBuild($build, $entity, $display, $view_mode, $langcode);
-    // Add contextual links for this node, except when the node is already being
-    // displayed on its own page. Modules may alter this behavior (for example,
-    // to restrict contextual links to certain view modes) by implementing
-    // hook_node_view_alter().
-    if (!empty($entity->nid) && !($view_mode == 'full' && node_is_page($entity))) {
+    if (!empty($entity->nid)) {
       $build['#contextual_links']['node'] = array('node', array($entity->nid));
     }
   }
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index f2206a0..ff073ae 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -1769,7 +1769,7 @@ function node_menu() {
     'access arguments' => array('update', 1),
     'weight' => 0,
     'type' => MENU_LOCAL_TASK,
-    'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE,
+    'context' => MENU_CONTEXT_INLINE,
     'file' => 'node.pages.inc',
   );
   $items['node/%node/delete'] = array(
@@ -1791,6 +1791,7 @@ function node_menu() {
     'access arguments' => array(1),
     'weight' => 2,
     'type' => MENU_LOCAL_TASK,
+    'context' => MENU_CONTEXT_INLINE,
     'file' => 'node.pages.inc',
   );
   $items['node/%node/revisions/%node_revision/view'] = array(
