Permalink
Browse files

BUGFIX Fixed form change tracking in the CMS, integrated it into menu…

… changes. Reduced TinyMCE coupling.
  • Loading branch information...
1 parent a6e2316 commit 482324b6ae5f5a31c30a4f32b16607d3abb59e3c @chillu chillu committed Dec 15, 2011
@@ -70,7 +70,7 @@
}
// Alert when unsaved changes are present
- if(form._checkChangeTracker(true) == false) return false;
+ if(!form.confirmUnsavedChanges()) return false;
// hide existing form - shown again through _loadResponse()
form.addClass('loading');
@@ -138,14 +138,12 @@
// default to first button if none given - simulates browser behaviour
if(!button) button = this.find('.Actions :submit:first');
+ form.trigger('beforesave');
this.trigger('submitform', {form: form, button: button});
// set button to "submitting" state
$(button).addClass('loading');
- // @todo TinyMCE coupling
- if(typeof tinyMCE != 'undefined') tinyMCE.triggerSave();
-
// validate if required
if(!form.validate()) {
// TODO Automatically switch to the tab/position of the first error
@@ -252,7 +250,7 @@
removeForm: function(form, placeholderHtml) {
if(!placeholderHtml) placeholderHtml = this.getPlaceholderHtml();
// Alert when unsaved changes are present
- if(form._checkChangeTracker(true) == false) return;
+ if(!form.confirmUnsavedChanges()) return;
this.trigger('removeform');
this.html(placeholderHtml);
// TODO This should be using the plugin API
@@ -113,34 +113,20 @@
},
/**
- * Function: _checkChangeTracker
+ * Function: confirmUnsavedChanges
*
- * Checks the jquery.changetracker plugin status for this form.
- * Usually bound to window.onbeforeunload.
- *
- * Parameters:
- * {boolean} isUnloadEvent - ..
+ * Checks the jquery.changetracker plugin status for this form,
+ * and asks the user for confirmation via a browser dialog if changes are detected.
+ * Doesn't cancel any unload or form removal events, you'll need to implement this based on the return
+ * value of this message.
*
* Returns:
- * (String) Either a string with a confirmation message, or the result of a confirm() dialog,
- * based on the isUnloadEvent parameter.
+ * (Boolean) FALSE if the user wants to abort with changes present, TRUE if no changes are detected
+ * or the user wants to discard them.
*/
- _checkChangeTracker: function(isUnloadEvent) {
- var self = this;
-
- // @todo TinyMCE coupling
- if(typeof tinyMCE != 'undefined') tinyMCE.triggerSave();
-
- // check for form changes
- if(self.is('.changed')) {
- // returned string will trigger a confirm() dialog,
- // but only if the method is triggered by an event
- if(isUnloadEvent) {
- return confirm(ss.i18n._t('LeftAndMain.CONFIRMUNSAVED'));
- } else {
- return ss.i18n._t('LeftAndMain.CONFIRMUNSAVEDSHORT');
- }
- }
+ confirmUnsavedChanges: function() {
+ this.trigger('beforesave');
+ return (this.is('.changed')) ? confirm(ss.i18n._t('LeftAndMain.CONFIRMUNSAVED')) : true;
},
/**
@@ -205,6 +191,13 @@
* Constructor: onmatch
*/
onmatch : function() {
+ var self = this;
+ this.closest('form').bind('beforesave', function() {
+ tinyMCE.triggerSave();
+ // TinyMCE assigns value attr directly, which doesn't trigger change event
+ self.trigger('change');
+ });
+
// Only works after TinyMCE.init() has been invoked, see $(window).bind() call below for details.
this.redraw();
@@ -22,6 +22,9 @@
* </ul>
* </li>
* </ul>
+ *
+ * Custom Events:
+ * - 'select': Fires when a menu item is selected (on any level).
*/
$('.cms-menu-list').entwine({
onmatch: function() {
@@ -82,7 +85,7 @@
this.siblings().find('li').removeClass('current');
if(parent) parent.addClass('current').siblings().removeClass('current');
this.getMenu().updateItems();
-
+
this.trigger('select');
}
});
@@ -108,24 +111,22 @@
// Ignore external links, fallback to standard link behaviour
if(e.which > 1 || this.is(':external')) return;
e.preventDefault();
-
- // Expand this, and collapse all other items
+
var item = this.getMenuItem();
- item.select();
var url = this.attr('href');
if(this.is(':internal')) url = $('base').attr('href') + url;
var children = item.find('li');
if(children.length) {
children.first().find('a').click();
- } else if(window.History.enabled) {
- // Active menu item is set based on X-Controller ajax header,
- // which matches one class on the menu
- window.History.pushState({}, '', url);
} else {
- window.location = url;
+ // Load URL, but give the loading logic an opportunity to veto the action
+ // (e.g. because of unsaved changes)
+ if(!$('.cms-container').loadPanel(url)) return false;
}
+
+ item.select();
}
});
@@ -112,7 +112,16 @@
*/
loadPanel: function(url, title, data) {
var data = data || {}, selector = data.selector || '.cms-content', contentEl = $(selector);
-
+ // Check change tracking (can't use events as we need a way to cancel the current state change)
+ var trackedEls = contentEl.find(':data(changetracker)').add(contentEl.filter(':data(changetracker)'));
+ if(trackedEls.length) {
+ var abort = false;
+ trackedEls.each(function() {
+ if(!$(this).confirmUnsavedChanges()) abort = true;
+ });
+ if(abort) return;
+ }
+
if(window.History.enabled) {
// Active menu item is set based on X-Controller ajax header,
// which matches one class on the menu
@@ -68,6 +68,8 @@
.each(function() {
$(this).data('changetracker.origVal', $(this).val());
});
+
+ this.data('changetracker', true);
};
/**

0 comments on commit 482324b

Please sign in to comment.