Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

MDL-31315 Ask before moving away from a modified form

  • Loading branch information...
commit 00e8d08dba6a86616ea028bd9216d3da62cfbcda 1 parent 216f6d8
@andrewnicols andrewnicols authored
View
10 admin/settings.php
@@ -131,6 +131,12 @@
echo '</form>';
}
-echo $OUTPUT->footer();
-
+$PAGE->requires->yui_module('moodle-core-formslib',
+ 'M.core.init_formslib',
+ array(array(
+ 'formid' => 'adminsettings'
+ ))
+);
+$PAGE->requires->string_for_js('changesmadereallygoaway', 'moodle');
+echo $OUTPUT->footer();
View
1  lang/en/moodle.php
@@ -219,6 +219,7 @@
$string['idnumbercoursecategory'] = 'Category ID number';
$string['idnumbercoursecategory_help'] = 'The ID number of a course category is only used when matching the category against external systems and is not displayed anywhere on the site. If the category has an official code name it may be entered, otherwise the field can be left blank.';
$string['categoryupdated'] = 'The category \'{$a}\' was updated';
+$string['changesmadereallygoaway'] = 'You have made changes. Are you sure you want to navigate away and lose your changes?';
$string['city'] = 'City/town';
$string['clambroken'] = 'Your administrator has enabled virus checking for file uploads but has misconfigured something.<br />Your file upload was NOT successful. Your administrator has been emailed to notify them so they can fix it.<br />Maybe try uploading this file later.';
$string['clamdeletedfile'] = 'The file has been deleted';
View
5 lib/form/filemanager.js
@@ -144,6 +144,7 @@ M.form_filemanager.init = function(Y, options) {
this.filecount++;
this.check_buttons();
this.refresh(this.currentpath);
+ M.util.set_form_changed();
},
check_buttons: function() {
var button_addfile = Y.one("#btnadd-"+this.client_id);
@@ -213,6 +214,7 @@ M.form_filemanager.init = function(Y, options) {
scope.mkdir_dialog.hide();
scope.refresh(filepath);
Y.one('#fm-newname').set('value', '');
+ M.util.set_form_changed();
}
});
}
@@ -559,6 +561,7 @@ M.form_filemanager.init = function(Y, options) {
callback: function(id, obj, args) {
scope.filecount--;
scope.refresh(obj.filepath);
+ M.util.set_form_changed();
if (scope.filecount < scope.maxfiles && scope.maxfiles!=-1) {
var button_addfile = Y.one("#btnadd-"+scope.client_id);
button_addfile.setStyle('display', 'inline');
@@ -606,6 +609,7 @@ M.form_filemanager.init = function(Y, options) {
alert(M.str.repository.fileexists);
} else {
scope.refresh(obj.filepath);
+ M.util.set_form_changed();
}
Y.one('#fm-rename-input').set('value', '');
scope.rename_dialog.hide();
@@ -683,6 +687,7 @@ M.form_filemanager.init = function(Y, options) {
}
dialog.cancel();
scope.refresh(p);
+ M.util.set_form_changed();
}
});
}
View
9 lib/formslib.php
@@ -2255,6 +2255,7 @@ function setAdvancedElements($elements){
* @param object $form MoodleQuickForm
*/
function startForm(&$form){
+ global $PAGE;
$this->_reqHTML = $form->getReqHTML();
$this->_elementTemplates = str_replace('{req}', $this->_reqHTML, $this->_elementTemplates);
$this->_advancedHTML = $form->getAdvancedHTML();
@@ -2267,7 +2268,13 @@ function startForm(&$form){
$this->_hiddenHtml .= $form->_pageparams;
}
-
+ $PAGE->requires->yui_module('moodle-core-formslib',
+ 'M.core.init_formslib',
+ array(array(
+ 'formid' => $form->getAttribute('id')
+ ))
+ );
+ $PAGE->requires->string_for_js('changesmadereallygoaway', 'moodle');
}
/**
View
68 lib/javascript-static.js
@@ -1752,4 +1752,72 @@ M.util.load_flowplayer = function() {
fileref.onreadystatechange = embed_function;
document.getElementsByTagName('head')[0].appendChild(fileref);
}
+};
+
+/**
+ * Set the form changed state to true
+ */
+M.util.set_form_changed = function() {
+ M.cfg.form_changed = 1;
+};
+
+/**
+ * Set the form submitted state to true
+ */
+M.util.set_form_submitted = function() {
+ M.cfg.form_submitted = 1;
}
+
+/**
+ * Attempt to determine whether the form has been modified in any way and
+ * is thus 'dirty'
+ *
+ * @return Integer 1 is the form is dirty; 0 if not
+ */
+M.util.get_form_dirty_state = function() {
+ // If the form was submitted, then return a non-dirty state
+ if (M.cfg.form_submitted) {
+ return 0;
+ }
+
+ // If any fields have been marked dirty, return a dirty state
+ if (M.cfg.form_changed) {
+ return 1;
+ }
+
+ // Handle TinyMCE editor instances
+ // We can't add a listener in the initializer as the editors may not have been created by that point
+ // so we do so here instead
+ if (typeof tinyMCE != 'undefined') {
+ for (var editor in tinyMCE.editors) {
+ if (tinyMCE.editors[editor].isDirty()) {
+ return 1;
+ }
+ }
+ }
+
+ // If we reached here, then the form hasn't met any of the dirty conditions
+ return 0;
+};
+
+/**
+ * Return a suitable message if changes have been made to a form
+ */
+M.util.report_form_dirty_state = function(e) {
+ if (!M.util.get_form_dirty_state()) {
+ // the form is not dirty, so don't display any message
+ return;
+ }
+
+ // This is the error message that we'll show to browsers which support it
+ var returnValue = M.util.get_string('changesmadereallygoaway', 'moodle');
+
+ // Most browsers are happy with the returnValue being set on the event
+ // But some browsers do not consistently pass the event
+ if (e) {
+ e.returnValue = returnValue;
+ }
+
+ // But some require it to be returned instead
+ return returnValue;
+};
View
59 lib/yui/formslib/formslib.js
@@ -0,0 +1,59 @@
+YUI.add('moodle-core-formslib',
+ function(Y) {
+ // The CSS selectors we use
+ var CSS = {
+ };
+
+ var FORMSLIBNAME = 'core-formslib';
+
+ var FORMSLIB = function() {
+ FORMSLIB.superclass.constructor.apply(this, arguments);
+ }
+
+ Y.extend(FORMSLIB, Y.Base, {
+ /**
+ * Initialize the module
+ */
+ initializer : function(config) {
+ var formid = 'form#' + this.get('formid');
+
+ // Add change events to the form elements
+ Y.all(formid + ' input').on('change', M.util.set_form_changed, this);
+ Y.all(formid + ' textarea').on('change', M.util.set_form_changed, this);
+ Y.all(formid + ' select').on('change', M.util.set_form_changed, this);
+
+ // We need any submit buttons on the form to set the submitted flag
+ Y.one(formid).on('submit', M.util.set_form_submitted, this);
+
+ // YUI doesn't support onbeforeunload properly so we must use the DOM to set the onbeforeunload. As
+ // a result, the has_changed must stay in the DOM too
+ window.onbeforeunload = M.util.report_form_dirty_state;
+ },
+
+ /**
+ * Unset the form dirty state and also set the form submitted flag to true
+ */
+ unset_changed : function(e) {
+ M.util.set_form_changed();
+ }
+ },
+ {
+ NAME : FORMSLIBNAME,
+ ATTRS : {
+ formid : {
+ 'value' : ''
+ }
+ }
+ }
+ );
+
+ M.core = M.core || {};
+ M.core.init_formslib = function(config) {
+ return new FORMSLIB(config);
+ }
+
+ },
+ '@VERSION@', {
+ requires : ['base']
+ }
+);
Please sign in to comment.
Something went wrong with that request. Please try again.