Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

BUGFIX: Use new jQuery.Entwine event capturing, onadd and onremove fe…

…atures to plug some memory leaks
  • Loading branch information...
commit b86a787521b5cb9ae7c854ef9b26f4dbe7ec91fa 1 parent bbd1bb7
@hafriedlander hafriedlander authored chillu committed
View
28 admin/javascript/LeftAndMain.AddForm.js
@@ -15,12 +15,6 @@
*/
$('.cms-edit-form.cms-add-form').entwine({
/**
- * Variable: Tree
- * (DOMElement)
- */
- Tree: null,
-
- /**
* Variable: OrigOptions
* (Array) Map of <option> values to an object of "title" and "value"
*/
@@ -31,18 +25,24 @@
* (Array) Internal counter to create unique page identifiers prior to ajax saving
*/
NewPages: [],
-
+
+ getTree: function() {
+ return $('.cms-tree');
+ },
+
+ fromTree: {
+ onselect_node: function(e, data){
+ self.refresh(data.rslt.obj);
+ }
+ },
+
/**
* Constructor: onmatch
*/
- onmatch: function() {
+ onadd: function() {
var self = this, typeDropdown = this.find(':input[name=PageType]');
- var tree = $('.cms-tree');
- this.setTree(tree);
-
// Event bindings
- $(tree).bind('select_node.jstree', function(e, data) {self.refresh(data.rslt.obj);});
typeDropdown.bind('change', function(e) {self.refresh();});
// TODO Bind on tree initialization to set dropdown for selected node
@@ -56,9 +56,7 @@
this._super();
},
- onunmatch: function() {
- this._super();
- },
+
/**
* Function: onsubmit
*
View
54 admin/javascript/LeftAndMain.BatchActions.js
@@ -19,50 +19,46 @@
$('#Form_BatchActionsForm').entwine({
/**
- * Variable: Tree
- * (DOMElement)
- */
- Tree: null,
-
- /**
* Variable: Actions
* (Array) Stores all actions that can be performed on the collected IDs as
* function closures. This might trigger filtering of the selected IDs,
* a confirmation message, etc.
*/
Actions: [],
-
+
+ getTree: function() {
+ return $('.cms-tree');
+ },
+
+ fromTree: {
+ oncheck_node: function(e, data){
+ this.serializeFromTree();
+ }
+ },
+
/**
* Constructor: onmatch
*/
- onmatch: function() {
- var self = this, tree = $('.cms-tree');
-
- this.setTree(tree);
-
- tree.bind('check_node.jstree', function(e, data) {
- self.serializeFromTree();
- });
-
- $('.cms-tree-view-modes :input[name=view-mode]').bind('click', function(e) {
- var val = $(e.target).val(), dropdown = self.find(':input[name=Action]');
+ onadd: function() {
+ this._updateStateFromViewMode();
+ this._super();
+ },
+
+ 'from .cms-tree-view-modes :input[name=view-mode]': {
+ onclick: function(e){
+ var val = $(e.target).val(), dropdown = this.find(':input[name=Action]'), tree = this.getTree();
+
if(val == 'multiselect') {
tree.addClass('multiple');
- self.serializeFromTree();
+ this.serializeFromTree();
} else {
- tree.removeClass('multiple');
+ tree.removeClass('multiple');
}
- self._updateStateFromViewMode();
- });
-
- self._updateStateFromViewMode();
-
- this._super();
- },
- onunmatch: function() {
- this._super();
+ this._updateStateFromViewMode();
+ }
},
+
/**
* Updates the select box state according to the current view mode.
*/
View
12 admin/javascript/LeftAndMain.Content.js
@@ -10,7 +10,7 @@
*/
$('.cms-content').entwine({
- onmatch: function() {
+ onadd: function() {
var self = this;
// Force initialization of certain UI elements to avoid layout glitches
@@ -19,10 +19,7 @@
this._super();
},
- onunmatch: function() {
- this._super();
- },
-
+
redraw: function() {
if(window.debug) console.log('redraw', this.attr('class'), this.get(0));
@@ -39,7 +36,7 @@
* Load edit form for the selected node when its clicked.
*/
$('.cms-content .cms-tree').entwine({
- onmatch: function() {
+ onadd: function() {
var self = this;
this._super();
@@ -80,9 +77,6 @@
self.removeForm();
}
});
- },
- onunmatch: function() {
- this._super();
}
});
View
4 admin/javascript/LeftAndMain.EditForm.js
@@ -50,7 +50,7 @@
/**
* Constructor: onmatch
*/
- onmatch: function() {
+ onadd: function() {
var self = this;
// Turn off autocomplete to fix the access tab randomly switching radio buttons in Firefox
@@ -106,7 +106,7 @@
this._super();
},
- onunmatch: function() {
+ onremove: function() {
this.changetracker('destroy');
this._super();
},
View
52 admin/javascript/LeftAndMain.Menu.js
@@ -78,23 +78,6 @@
onmatch: function() {
var self = this;
- var updateMenuFromResponse = function(xhr) {
- var controller = xhr.getResponseHeader('X-Controller');
- if(controller) {
- var item = self.find('li#Menu-' + controller);
- if(!item.hasClass('current')) item.select();
- }
- self.updateItems();
- };
- $('.cms-container').live('afterstatechange aftersubmitform', function(e, data) {
- updateMenuFromResponse(data.xhr);
- });
-
- // Sync collapsed state with parent panel
- this.parents('.cms-panel:first').bind('toggle', function(e) {
- self.toggleClass('collapsed', $(this).hasClass('collapsed'));
- });
-
// Select default element (which might reveal children in hidden parents)
this.find('li.current').select();
@@ -105,6 +88,41 @@
onunmatch: function() {
this._super();
},
+
+ updateMenuFromResponse: function(xhr) {
+ var controller = xhr.getResponseHeader('X-Controller');
+ if(controller) {
+ var item = this.find('li#Menu-' + controller);
+ if(!item.hasClass('current')) item.select();
+ }
+ this.updateItems();
+ },
+
+ 'from .cms-container': {
+ onafterstatechange: function(e, data){
+ this.updateMenuFromResponse(data.xhr);
+ },
+ onaftersubmitform: function(e, data){
+ this.updateMenuFromResponse(data.xhr);
+ }
+ },
+
+ 'from .cms-edit-form': {
+ onrelodeditform: function(e, data){
+ this.updateMenuFromResponse(data.xmlhttp);
+ }
+ },
+
+ getContainingPanel: function(){
+ return this.closest('.cms-panel');
+ },
+
+ fromContainingPanel: {
+ ontoggle: function(e){
+ this.toggleClass('collapsed', $(e.target).hasClass('collapsed'));
+ }
+ },
+
updateItems: function() {
// Hide "edit page" commands unless the section is activated
var editPageItem = this.find('#Menu-CMSMain');
View
6 admin/javascript/LeftAndMain.Ping.js
@@ -11,15 +11,11 @@
*/
PingIntervalSeconds: 5*60,
- onmatch: function() {
+ onadd: function() {
this._setupPinging();
this._super();
},
- onunmatch: function() {
- this._super();
- },
-
/**
* Function: _setupPinging
*
View
62 admin/javascript/LeftAndMain.Preview.js
@@ -43,34 +43,6 @@
if(!self.is('.is-collapsed')) self.loadCurrentPage();
});
- var updateAfterXhr = function() {
- $('.cms-preview-toggle-link')[self.canPreview() ? 'show' : 'hide']();
-
- // Only load when panel is visible (see details in iframe load event handler).
- if(self.is('.is-collapsed')) return;
-
- // var url = ui.xmlhttp.getResponseHeader('x-frontend-url');
- var url = $('.cms-edit-form').find(':input[name=StageURLSegment]').val();
- if(url) {
- self.loadUrl(url);
- self.unblock();
- } else {
- self.block();
- }
- };
-
- // Listen to history state changes
- $('.cms-container').bind('afterstatechange aftersubmitform', function(e) {
- updateAfterXhr();
- });
-
- // Toggle preview when new menu entry is selected.
- // Only do this when preview is actually shown,
- // to avoid auto-expanding the menu in normal CMS mode
- $('.cms-menu-list li').bind('select', function(e) {
- if(!self.hasClass('is-collapsed')) self.collapse();
- });
-
if(this.hasClass('is-expanded')) this.expand();
else this.collapse();
this.data('cms-preview-initialized', true);
@@ -91,6 +63,40 @@
this.find('iframe').attr('src', url);
},
+ updateAfterXhr: function(){
+ $('.cms-preview-toggle-link')[this.canPreview() ? 'show' : 'hide']();
+
+ // Only load when panel is visible (see details in iframe load event handler).
+ if(this.is('.is-collapsed')) return;
+
+ // var url = ui.xmlhttp.getResponseHeader('x-frontend-url');
+ var url = $('.cms-edit-form').find(':input[name=StageURLSegment]').val();
+ if(url) {
+ this.loadUrl(url);
+ this.unblock();
+ } else {
+ this.block();
+ }
+ },
+
+ 'from .cms-container': {
+ onaftersubmitform: function(){
+ this.updateAfterXhr();
+ },
+ onafterstatechange: function(){
+ this.updateAfterXhr();
+ }
+ },
+
+ // Toggle preview when new menu entry is selected.
+ // Only do this when preview is actually shown,
+ // to avoid auto-expanding the menu in normal CMS mode
+ 'from .cms-menu-list li': {
+ onselect: function(){
+ if(!this.hasClass('is-collapsed')) this.collapse();
+ }
+ },
+
/**
* Loads the matching edit form for a page viewed in the preview iframe,
* based on metadata sent along with this document.
View
22 admin/javascript/LeftAndMain.Tree.js
@@ -9,8 +9,8 @@
$('.cms-tree').entwine({
Hints: null,
-
- onmatch: function() {
+
+ onadd: function(){
this._super();
// Don't reapply (expensive) tree behaviour if already present
@@ -96,16 +96,22 @@
}
});
});
-
- $('.cms-container').bind('afterstatechange.tree aftersubmitform.tree', function(e, data) {
- self.updateFromEditForm(e.origData);
- });
},
- onunmatch: function() {
- $('.cms-container').unbind('afterstatechange.tree aftersubmitform.tree');
+ onremove: function(){
+ this.jstree('destroy');
this._super();
},
+ 'from .cms-container': {
+ onafterstatechange: function(e){
+ this.updateFromEditForm(e.origData);
+ },
+
+ onaftersubmitform: function(e){
+ this.updateFromEditForm(e.origData);
+ }
+ },
+
getTreeConfig: function() {
var self = this;
return {
View
48 admin/javascript/LeftAndMain.js
@@ -73,7 +73,7 @@ jQuery.noConflict();
/**
* Constructor: onmatch
*/
- onmatch: function() {
+ onadd: function() {
var self = this;
// Browser detection
@@ -92,34 +92,27 @@ jQuery.noConflict();
// Initialize layouts
this.redraw();
- // Monitor window resizes, panel changes and edit form loads for layout changes.
- // Also triggers redraw through handleStateChange()
- $(window).resize(function() {
- self.redraw();
- });
-
- $('.cms-panel').live('toggle', function() {
- self.redraw();
- });
-
// Remove loading screen
$('.ss-loading-screen').hide();
$('body').removeClass('loading');
$(window).unbind('resize', positionLoadingSpinner);
- History.Adapter.bind(window,'statechange',function(){
- self.handleStateChange();
- });
-
this._super();
},
- onunmatch: function() {
- this._super();
+
+ fromWindow: {
+ onstatechange: function(){ this.handleStateChange(); },
+ onresize: function(){ this.redraw(); }
},
- onaftersubmitform: function() {
- this.redraw();
+
+ 'from .cms-panel': {
+ ontoggle: function(){ this.redraw(); }
},
-
+
+ 'from .cms-container': {
+ onaftersubmitform: function(){ this.redraw(); }
+ },
+
redraw: function() {
if(window.debug) console.log('redraw', this.attr('class'), this.get(0));
@@ -457,12 +450,13 @@ jQuery.noConflict();
});
$('.cms .ss-ui-button').entwine({
- onmatch: function() {
+ onadd: function() {
if(!this.data('button')) this.button();
this._super();
},
- onunmatch: function() {
+ onremove: function() {
+ this.button('destroy');
this._super();
}
});
@@ -744,11 +738,12 @@ jQuery.noConflict();
*/
window._panelDeferredCache = {};
$('.cms-panel-deferred').entwine({
- onmatch: function() {
+ onadd: function() {
this._super();
this.redraw();
},
- onunmatch: function() {
+ onremove: function() {
+ console.log('saving', this.data('url'), this);
// Save the HTML state at the last possible moment.
// Don't store the DOM to avoid memory leaks.
if(!this.data('deferredNoCache')) window._panelDeferredCache[this.data('url')] = this.html();
@@ -790,12 +785,13 @@ jQuery.noConflict();
* for forms inside the CMS layout.
*/
$('.cms-tabset').entwine({
- onmatch: function() {
+ onadd: function() {
// Can't name redraw() as it clashes with other CMS entwine classes
this.redrawTabs();
this._super();
},
- onunmatch: function() {
+ onremove: function() {
+ this.tabs('destroy');
this._super();
},
redrawTabs: function() {
View
7 admin/javascript/ssui.core.js
@@ -5,13 +5,8 @@
* Creates a jQuery UI tab navigation bar, detached from the container DOM structure.
*/
$('.ss-ui-tabs-nav').entwine({
- onmatch: function() {
+ onadd: function() {
this.redraw();
-
- this._super();
- },
- onunmatch: function() {
- this._super();
},
redraw: function() {
this.addClass('ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-panel ui-corner-bottom');
View
96 javascript/HtmlEditorField.js
@@ -198,44 +198,47 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
$('textarea.htmleditor').entwine({
Editor: null,
-
+
/**
* Constructor: onmatch
*/
- onmatch : function() {
- var self = this, edClass = this.data('editor') || ss.editorWrappers['default'], ed = edClass();
+ onadd: function() {
+ var edClass = this.data('editor') || ss.editorWrappers['default'], ed = edClass();
this.setEditor(ed);
- this.closest('form').bind('beforesubmitform', function() {
- // TinyMCE modifies input, so change tracking might get false
- // positives when comparing string values - don't save if the editor doesn't think its dirty.
- if(self.isChanged()) {
- ed.save();
-
- // TinyMCE assigns value attr directly, which doesn't trigger change event
- self.trigger('change');
- }
- });
// Using a global config (generated through HTMLEditorConfig PHP logic).
// Depending on browser cache load behaviour, entwine's DOMMaybeChanged
// can be called before the bottom-most inline script tag is executed,
// which defines the global. If that's the case, wait for the window load.
- if(typeof ssTinyMceConfig != 'undefined') {
- this.redraw();
- } else {
- $(window).bind('load', function() {
- self.redraw();
- });
- }
+ if(typeof ssTinyMceConfig != 'undefined') this.redraw();
this._super();
},
- onunmatch: function() {
- // TODO Throws exceptions in Firefox, most likely due to the element being removed from the DOM at this point
- // var ed = tinyMCE.get(this.attr('id'));
- // if(ed) ed.remove();
+ onremove: function() {
+ var ed = tinyMCE.get(this.attr('id'));
+ if (ed) ed.remove();
this._super();
},
+
+ getContainingForm: function(){
+ return this.closest('form');
+ },
+
+ fromContainingForm: {
+ onbeforesave: function(){
+ if(this.isChanged()) {
+ this.getEditor().save();
+ this.trigger('change'); // TinyMCE assigns value attr directly, which doesn't trigger change event
+ }
+ }
+ },
+
+ fromWindow: {
+ onload: function(){
+ this.redraw();
+ }
+ },
+
redraw: function() {
// Using a global config (generated through HTMLEditorConfig PHP logic)
var config = ssTinyMceConfig, self = this, ed = this.getEditor();
@@ -253,16 +256,18 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
self.css('visibility', 'visible');
});
- // Handle editor de-registration by hooking into state changes.
- // TODO Move to onunmatch for less coupling (once we figure out how to work with detached DOM nodes in TinyMCE)
- $('.cms-container').bind('beforestatechange', function() {
- self.css('visibility', 'hidden');
- var container = ed.getInstance() ? ed.getContainer() : null;
- if(container && container.length) container.remove();
- });
-
this._super();
},
+
+ 'from .cms-container': {
+ onbeforestatechange: function(){
+ this.css('visibility', 'hidden');
+
+ var ed = this.getEditor(), container = ed.getInstance() ? ed.getContainer() : null;
+ if(container && container.length) container.remove();
+ }
+ },
+
isChanged: function() {
var ed = this.getEditor();
return (ed && ed.getInstance() && ed.isDirty());
@@ -1103,17 +1108,21 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
});
$('div.ss-assetuploadfield .ss-uploadfield-item-edit, div.ss-assetuploadfield .ss-uploadfield-item-name').entwine({
+ getEditForm: function() {
+ return this.closest('.ss-uploadfield-item').find('.ss-uploadfield-item-editform');
+ },
+
+ fromEditForm: {
+ onchange: function(e){
+ var form = $(e.target);
+ form.removeClass('edited'); //so edited class is only there once
+ form.addClass('edited');
+ }
+ },
+
onclick: function(e) {
- var editForm = this.closest('.ss-uploadfield-item').find('.ss-uploadfield-item-editform');
+ var editForm = this.getEditForm();
- // Mark the row as changed if any of its form fields are edited
- editForm.ready(function() {
- editForm.find(':input').bind('change', function(e){
- editForm.removeClass('edited'); //so edited class is only there once
- editForm.addClass('edited');
- });
- });
-
editForm.parent('.ss-uploadfield-item').removeClass('ui-state-warning');
editForm.toggleEditForm();
@@ -1153,7 +1162,7 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
$('form.htmleditorfield-mediaform #ParentID .TreeDropdownField').entwine({
- onmatch: function() {
+ onadd: function() {
this._super();
// TODO Custom event doesn't fire in IE if registered through object literal
@@ -1163,9 +1172,6 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
fileList.setState('ParentID', self.getValue());
fileList.reload();
});
- },
- onunmatch: function() {
- this._super();
}
});
View
5 javascript/TabSet.js
@@ -4,12 +4,13 @@
* Lightweight wrapper around jQuery UI tabs.
*/
$('.ss-tabset').entwine({
- onmatch: function() {
+ onadd: function() {
// Can't name redraw() as it clashes with other CMS entwine classes
this.redrawTabs();
this._super();
},
- onunmatch: function() {
+ onremove: function() {
+ this.tabs('destroy');
this._super();
},
redrawTabs: function() {
Please sign in to comment.
Something went wrong with that request. Please try again.