diff --git a/xwiki-platform-core/xwiki-platform-web/src/main/webapp/resources/js/xwiki/actionbuttons/actionButtons.js b/xwiki-platform-core/xwiki-platform-web/src/main/webapp/resources/js/xwiki/actionbuttons/actionButtons.js
index 2194d03a0e05a06f0074dffdf6539d9351d9170f..9b551355a9343f6124bd9acc6009c1f67fc78840 100644
--- a/xwiki-platform-core/xwiki-platform-web/src/main/webapp/resources/js/xwiki/actionbuttons/actionButtons.js
+++ b/xwiki-platform-core/xwiki-platform-web/src/main/webapp/resources/js/xwiki/actionbuttons/actionButtons.js
@@ -106,7 +106,7 @@ var XWiki = (function(XWiki) {
           return false;
         }
       }
-      var commentField = form.comment;
+      var commentField = (form && form.comment) || $('#commentinput');
       if (commentField && (($xwiki.isEditCommentSuggested()) || $xwiki.isEditCommentMandatory())) {
         while (commentField.value == '') {
           var response = prompt("$services.localization.render('core.comment.prompt')", '');
@@ -122,15 +122,18 @@ var XWiki = (function(XWiki) {
     onCancel : function(event) {
       event.stop();
 
-      // Notify others we are going to cancel
+      // Notify the others that we are going to cancel.
       this.notify(event, "cancel");
 
-      // Optimisation: Do not send the entire form's data when all we want is to cancel editing.
-
+      // Optimisation: Do not submit the entire form's data when all we want is to cancel editing.
+      var form = event.element().form;
+      form && this.cancelForm(form);
+    },
+    cancelForm: function(form) {
       // Determine the form's action and clean it by removing any anchors.
-      var location = event.element().form.action;
+      var location = form.action;
       if (typeof location != "string") {
-        location = event.element().form.attributes.getNamedItem("action");
+        location = form.attributes.getNamedItem("action");
         if (location) {
           location = location.nodeValue;
         } else {
@@ -144,19 +147,20 @@ var XWiki = (function(XWiki) {
         location += '?';
       }
 
-      // Make sure that we call the CancelAction using XWiki's ActionFilter, no matter what XWiki action was set in the form's action.
+      // Make sure that we call the CancelAction using XWiki's ActionFilter, no matter what XWiki action was set in the
+      // form's action.
       var cancelActionParameter = '&action_cancel=true';
 
       // Include the xredirect element, if it exists.
-      var xredirectElement = event.element().form.select('input[name="xredirect"]')[0];
+      var xredirectElement = form.select('input[name="xredirect"]')[0];
       var xredirectParameter = xredirectElement ? '&xredirect=' + escape(xredirectElement.value) : '';
 
       // Include the language parameter if it exists
-      var language = event.element().form.select('input[name="language"]')[0];
+      var language = form.select('input[name="language"]')[0];
       var languageParameter = language ? '&language=' + escape(language.value) : '';
 
-      // Optimisation: Prevent a redundant request to remove the edit lock when the page unload event is triggered. Both the cancel action
-      // and the page unload event would unlock the document, so no point in doing both.
+      // Optimisation: Prevent a redundant request to remove the edit lock when the page unload event is triggered. Both
+      // the cancel action and the page unload event would unlock the document, so no point in doing both.
       XWiki.EditLock && XWiki.EditLock.setLocked(false);
 
       // Call the cancel URL directly instead of submitting the form. (optimisation)
@@ -182,8 +186,8 @@ var XWiki = (function(XWiki) {
       // listeners shouldn't be aware of the original event.
       var stopped = event.stopped || originalEvent.stopped;
       // Stop the original event if the current event has been stopped. Also, in Internet Explorer the original event
-      // can't be stopped from the current event's handlers, so in case some old code has tried to stop the original event
-      // we must call stop() again here.
+      // can't be stopped from the current event's handlers, so in case some old code has tried to stop the original
+      // event we must call stop() again here.
       if (stopped) {
         originalEvent.stop();
       }
@@ -227,16 +231,14 @@ var XWiki = (function(XWiki) {
         return;
       }
 
-      var isContinue = event.memo["continue"];
-
-      this.form = $(event.memo.form);
       this.savedBox.hide();
       this.failedBox.hide();
-
-      var isCreateFromTemplate = (this.form.template && this.form.template.value);
+      
+      var isContinue = event.memo["continue"];
+      this.form = $(event.memo.form);
 
       // This could be a custom form, in which case we need to keep it simple to avoid breaking applications.
-      var isCustomForm = (this.form.action.indexOf("/preview/") == -1 && this.form.action.indexOf("/save/") == -1);
+      var isCustomForm = this.form.action.indexOf("/preview/") == -1 && this.form.action.indexOf("/save/") == -1;
       if (isCustomForm && !isContinue) {
         return;
       }
@@ -271,6 +273,8 @@ var XWiki = (function(XWiki) {
         }
       }
 
+      var isCreateFromTemplate = (this.form.template && this.form.template.value);
+
       // Handle explicitly requested synchronous operations (mainly for backwards compatibility).
       var isAsync = (this.form.async && this.form.async.value === 'true');
 
@@ -361,11 +365,6 @@ var XWiki = (function(XWiki) {
           this.progressBox.hide();
           this.savingBox.replace(this.savedBox);
         }
-      } else if (!isCreateFromTemplate && (!isContinue  || $('body').hasClassName('previewbody'))) {
-        document.fire("xwiki:document:saved");
-        if (this.maybeRedirect(isContinue)) {
-          return;
-        }
       } else {
         this.progressBox.hide();
         if (response.responseJSON && response.responseJSON.mergedDocument) {
@@ -373,6 +372,12 @@ var XWiki = (function(XWiki) {
         } else {
           this.savingBox.replace(this.savedBox);
         }
+        if (!isContinue || $('body').hasClassName('previewbody')) {
+          document.fire("xwiki:document:saved");
+          if (this.maybeRedirect(isContinue)) {
+            return;
+          }
+        }
       }
 
       if (response.responseJSON && response.responseJSON.newVersion) {
@@ -397,7 +402,8 @@ var XWiki = (function(XWiki) {
         defaultInteractionParameters : {},
         /** Constructor. Registers the key listener that pops up the dialog. */
         initialize : function($super, interactionParameters) {
-          this.interactionParameters = Object.extend(Object.clone(this.defaultInteractionParameters), interactionParameters || {});
+          this.interactionParameters = Object.extend(Object.clone(this.defaultInteractionParameters),
+            interactionParameters || {});
           // call constructor from ModalPopup with params content, shortcuts, options
           $super(
             createContent(this.interactionParameters, this),
@@ -460,58 +466,59 @@ var XWiki = (function(XWiki) {
     },
     // 403 happens in case of CSRF issue
     on403 : function (response, isContinue, isCreateFromTemplate) {
+      if (!response.responseJSON || !response.responseJSON.errorType === "CSRF") {
+        return this.on401(response);
+      }
+
       this.progressBox.hide();
       this.savingBox.hide();
       this.savedBox.hide();
       this.failedBox.hide();
 
-      if (response.responseJSON && response.responseJSON.errorType === "CSRF") {
-        var answerJson = response.responseJSON;
-        var self = this;
-        var createContent = function (data, modal) {
-          var resubmit = function () {
-            $$('input[name=form_token]').each(function (item) {
-              item.value = answerJson.newToken;
-            });
-            new Ajax.Request(answerJson.resubmissionURI, {
-              method : 'post',
-              parameters : "form_token=" + answerJson.newToken,
-              onSuccess : self.onSuccess.bindAsEventListener(self, isContinue, isCreateFromTemplate),
-              on1223 : self.on1223.bindAsEventListener(self),
-              on0 : self.on0.bindAsEventListener(self),
-              on409 : self.on409.bindAsEventListener(self, isContinue),
-              on401 : self.on401.bindAsEventListener(self),
-              on403 : self.on403.bindAsEventListener(self, isContinue, isCreateFromTemplate),
-              onFailure : self.onFailure.bind(self)
-            });
-            modal.closeDialog();
-          };
-
-          var content =  new Element('div', {'class': 'modal-popup', 'id': 'csrf-warning-modal'});
-          var buttonsDiv =  new Element('div');
-
-          // the confirmation message contains some double quotes that should be escaped.
-          content.insert("$escapetool.json($services.localization.render('csrf.confirmation'))");
-          content.insert(new Element('br'));
-          var buttonCreate = new Element('button', {'class': 'btn btn-default', 'id': 'force-save-csrf'});
-          buttonCreate.insert("$services.localization.render('yes')");
-          buttonsDiv.insert(buttonCreate);
-          buttonCreate.on("click", resubmit);
-
-          buttonCreate = new Element('button', {'class': 'btn btn-primary', 'id': 'cancel-save-csrf'});
-          buttonCreate.insert("$services.localization.render('no')");
-          buttonsDiv.insert(buttonCreate);
-          buttonCreate.on("click", function () {
-            modal.closeDialog();
+      var answerJson = response.responseJSON;
+      var self = this;
+      var createContent = function (data, modal) {
+        var resubmit = function () {
+          $$('input[name=form_token]').each(function (item) {
+            item.value = answerJson.newToken;
+          });
+          new Ajax.Request(answerJson.resubmissionURI, {
+            method : 'post',
+            parameters : "form_token=" + answerJson.newToken,
+            onSuccess : self.onSuccess.bindAsEventListener(self, isContinue, isCreateFromTemplate),
+            on1223 : self.on1223.bindAsEventListener(self),
+            on0 : self.on0.bindAsEventListener(self),
+            on409 : self.on409.bindAsEventListener(self, isContinue),
+            on401 : self.on401.bindAsEventListener(self),
+            on403 : self.on403.bindAsEventListener(self, isContinue, isCreateFromTemplate),
+            onFailure : self.onFailure.bind(self)
           });
-          content.insert(buttonsDiv);
-          return content;
+          modal.closeDialog();
         };
-        this.enableEditors();
-        this.displayErrorModal(createContent);
-      } else {
-        this.on401(response);
-      }
+
+        var content =  new Element('div', {'class': 'modal-popup', 'id': 'csrf-warning-modal'});
+        var buttonsDiv =  new Element('div');
+
+        // the confirmation message contains some double quotes that should be escaped.
+        content.insert("$escapetool.json($services.localization.render('csrf.confirmation'))");
+        content.insert(new Element('br'));
+        var buttonCreate = new Element('button', {'class': 'btn btn-default', 'id': 'force-save-csrf'});
+        buttonCreate.insert("$services.localization.render('yes')");
+        buttonsDiv.insert(buttonCreate);
+        buttonCreate.on("click", resubmit);
+
+        buttonCreate = new Element('button', {'class': 'btn btn-primary', 'id': 'cancel-save-csrf'});
+        buttonCreate.insert("$services.localization.render('no')");
+        buttonsDiv.insert(buttonCreate);
+        buttonCreate.on("click", function () {
+          modal.closeDialog();
+        });
+        content.insert(buttonsDiv);
+        return content;
+      };
+
+      this.enableEditors();
+      this.displayErrorModal(createContent);
 
       // Announce that a document save attempt has failed
       document.fire("xwiki:document:saveFailed", {'response' : response});
@@ -725,7 +732,8 @@ var XWiki = (function(XWiki) {
       if (dotIndex > -1) {
         var stringProgress = stringProgress.substring(0, dotIndex + 2);
       }
-      var newProgressBox = new XWiki.widgets.Notification(this.progressMessageTemplate.replace('__PROGRESS__', stringProgress), "inprogress");
+      var newProgressBox = new XWiki.widgets.Notification(this.progressMessageTemplate.replace('__PROGRESS__',
+        stringProgress), "inprogress");
       this.progressBox.replace(newProgressBox);
       this.progressBox = newProgressBox;
     },