diff --git a/CHANGELOG.txt b/CHANGELOG.txt index a5b5a53bd9..a62aa1645c 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -4,6 +4,7 @@ Changelog 1.4 (xx.xx.xxxx) ~~~~~~~~~~~~~~~~ + * The page editor now produces a warning if the user navigates away without saving changes * The `Document` model can now be overridden using the new `WAGTAILDOCS_DOCUMENT_MODEL` setting (Alex Gleason) * Wagtail no longer depends on django-compressor * Snippets now support a custom `edit_handler` property (Mikalai Radchuk) diff --git a/docs/releases/1.4.rst b/docs/releases/1.4.rst index 72ed2dffc4..f99575b83a 100644 --- a/docs/releases/1.4.rst +++ b/docs/releases/1.4.rst @@ -10,6 +10,11 @@ Wagtail 1.4 release notes - IN DEVELOPMENT What's new ========== +Protection against unsaved changes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The page editor interface now produces a warning if the user attempts to navigate away while there are unsaved changes. + Custom document models ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/wagtail/wagtailadmin/static_src/wagtailadmin/js/core.js b/wagtail/wagtailadmin/static_src/wagtailadmin/js/core.js index a86d4fd1ea..4691fa859d 100644 --- a/wagtail/wagtailadmin/static_src/wagtailadmin/js/core.js +++ b/wagtail/wagtailadmin/static_src/wagtailadmin/js/core.js @@ -36,6 +36,49 @@ function initTagField(id, autocompleteUrl) { }); } +/* + * Enables a "dirty form check", prompting the user if they are navigating away + * from a page with unsaved changes. + * + * It takes the following parameters: + * + * - formSelector - A CSS selector to select the form to apply this check to. + * + * - options - An object for passing in options. Possible options are: + * - ignoredButtonsSelector - A CSS selector to find buttons to ignore within + * the form. If the navigation was triggered by one of these buttons, The + * check will be ignored. defaults to: input[type="submit"]. + * - confirmationMessage - The message to display in the prompt. + * - alwaysDirty - When set to true the form will always be considered dirty, + * prompting the user even when nothing has been changed. +*/ +function enableDirtyFormCheck(formSelector, options) { + var $form = $(formSelector); + var $ignoredButtons = $form.find( + options.ignoredButtonsSelector || 'input[type="submit"],button[type="submit"]' + ); + var confirmationMessage = options.confirmationMessage || ' '; + var alwaysDirty = options.alwaysDirty || false; + var initialData = $form.serialize(); + + window.addEventListener('beforeunload', function(event) { + // Ignore if the user clicked on an ignored element + var triggeredByIgnoredButton = false; + var $trigger = $(event.target.activeElement); + + $ignoredButtons.each(function() { + if ($(this).is($trigger)) { + triggeredByIgnoredButton = true; + } + }); + + if (!triggeredByIgnoredButton && (alwaysDirty || $form.serialize() != initialData)) { + event.returnValue = confirmationMessage; + return confirmationMessage; + } + }); +} + $(function() { // Add class to the body from which transitions may be hung so they don't appear to transition as the page loads $('body').addClass('ready'); @@ -207,4 +250,3 @@ $(function() { }, 10); }); }); - diff --git a/wagtail/wagtailadmin/templates/wagtailadmin/pages/create.html b/wagtail/wagtailadmin/templates/wagtailadmin/pages/create.html index 5f69300790..13e8916dc1 100644 --- a/wagtail/wagtailadmin/templates/wagtailadmin/pages/create.html +++ b/wagtail/wagtailadmin/templates/wagtailadmin/pages/create.html @@ -74,6 +74,19 @@ {% endblock %} diff --git a/wagtail/wagtailadmin/templates/wagtailadmin/pages/edit.html b/wagtail/wagtailadmin/templates/wagtailadmin/pages/edit.html index 81e4566203..b6c6d92fcc 100644 --- a/wagtail/wagtailadmin/templates/wagtailadmin/pages/edit.html +++ b/wagtail/wagtailadmin/templates/wagtailadmin/pages/edit.html @@ -33,7 +33,7 @@