mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 12:05:37 +00:00
Merge pull request #2345 from hafriedlander/fix/performance
Couple of performance fixes - eliminate un-necessary redraws and preview updating
This commit is contained in:
commit
afd3e3f0d0
@ -104,9 +104,21 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate what columns are already hidden pre-layout
|
||||
var prehidden = {
|
||||
content: spec.content.hasClass('column-hidden'),
|
||||
preview: spec.preview.hasClass('column-hidden')
|
||||
};
|
||||
|
||||
// Calculate what columns will be hidden (zero width) post-layout
|
||||
var posthidden = {
|
||||
content: contentWidth === 0,
|
||||
preview: previewWidth === 0
|
||||
};
|
||||
|
||||
// Apply classes for elements that might not be visible at all.
|
||||
spec.content.toggleClass('column-hidden', contentWidth===0);
|
||||
spec.preview.toggleClass('column-hidden', previewWidth===0);
|
||||
spec.content.toggleClass('column-hidden', posthidden.content);
|
||||
spec.preview.toggleClass('column-hidden', posthidden.preview);
|
||||
|
||||
// Apply the widths to columns, and call subordinate layouts to arrange the children.
|
||||
menu.bounds({'x': left, 'y': top, 'height': bottom - top, 'width': menuWidth});
|
||||
@ -115,12 +127,15 @@
|
||||
left += menuWidth;
|
||||
|
||||
content.bounds({'x': left, 'y': top, 'height': bottom - top, 'width': contentWidth});
|
||||
content.doLayout();
|
||||
if (!posthidden.content) content.doLayout();
|
||||
|
||||
left += contentWidth;
|
||||
|
||||
preview.bounds({'x': left, 'y': top, 'height': bottom - top, 'width': previewWidth});
|
||||
preview.doLayout();
|
||||
if (!posthidden.preview) preview.doLayout();
|
||||
|
||||
if (posthidden.content !== prehidden.content) spec.content.trigger('columnvisibilitychanged');
|
||||
if (posthidden.preview !== prehidden.preview) spec.preview.trigger('columnvisibilitychanged');
|
||||
|
||||
return container;
|
||||
};
|
||||
|
@ -30,7 +30,7 @@
|
||||
|
||||
WidthCollapsed: null,
|
||||
|
||||
onmatch: function() {
|
||||
onadd: function() {
|
||||
if(!this.find('.cms-panel-content').length) throw new Exception('Content panel for ".cms-panel" not found');
|
||||
|
||||
// Create default controls unless they already exist.
|
||||
@ -62,9 +62,6 @@
|
||||
|
||||
this._super();
|
||||
},
|
||||
onunmatch: function() {
|
||||
this._super();
|
||||
},
|
||||
/**
|
||||
* @param {Boolean} TRUE to expand, FALSE to collapse.
|
||||
* @param {Boolean} TRUE means that events won't be fired, which is useful for the component initialization phase.
|
||||
@ -89,7 +86,7 @@
|
||||
|
||||
// Save collapsed state in cookie
|
||||
if($.cookie && this.attr('id')) $.cookie('cms-panel-collapsed-' + this.attr('id'), !bool, {path: '/', expires: 31});
|
||||
|
||||
|
||||
// TODO Fix redraw order (inner to outer), and re-enable silent flag
|
||||
// to avoid multiple expensive redraws on a single load.
|
||||
// if(!silent) {
|
||||
|
@ -198,6 +198,7 @@
|
||||
* Caveat: the preview will be automatically enabled when ".cms-previewable" class is detected.
|
||||
*/
|
||||
disablePreview: function() {
|
||||
this.setPendingURL(null);
|
||||
this._loadUrl('about:blank');
|
||||
this._block();
|
||||
this.changeMode('content', false);
|
||||
@ -304,6 +305,18 @@
|
||||
}
|
||||
},
|
||||
|
||||
/** @var string A URL that should be displayed in this preview panel once it becomes visible */
|
||||
PendingURL: null,
|
||||
|
||||
oncolumnvisibilitychanged: function() {
|
||||
var url = this.getPendingURL();
|
||||
if (url && !this.is('.column-hidden')) {
|
||||
this.setPendingURL(null);
|
||||
this._loadUrl(url);
|
||||
this._unblock();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Update preview whenever a form is submitted.
|
||||
* This is an alternative to the LeftAndmMain::loadPanel functionality which we already
|
||||
@ -369,20 +382,37 @@
|
||||
});
|
||||
}
|
||||
|
||||
var url = null;
|
||||
|
||||
if (currentState[0]) {
|
||||
// State is available on the newly loaded content. Get it.
|
||||
this._loadUrl(currentState[0].url);
|
||||
this._unblock();
|
||||
url = currentState[0].url;
|
||||
} else if (states.length) {
|
||||
// Fall back to the first available content state.
|
||||
this.setCurrentStateName(states[0].name);
|
||||
this._loadUrl(states[0].url);
|
||||
this._unblock();
|
||||
url = states[0].url;
|
||||
} else {
|
||||
// No state available at all.
|
||||
this.setCurrentStateName(null);
|
||||
}
|
||||
|
||||
// If this preview panel isn't visible at the moment, delay loading the URL until it (maybe) is later
|
||||
if (this.is('.column-hidden')) {
|
||||
this.setPendingURL(url);
|
||||
this._loadUrl('about:blank');
|
||||
this._block();
|
||||
}
|
||||
else {
|
||||
this.setPendingURL(null);
|
||||
|
||||
if (url) {
|
||||
this._loadUrl(url);
|
||||
this._unblock();
|
||||
}
|
||||
else {
|
||||
this._block();
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
@ -104,8 +104,7 @@ jQuery.noConflict();
|
||||
statusMessage(decodeURIComponent(msg), msgType);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Main LeftAndMain interface with some control panel and an edit form.
|
||||
*
|
||||
@ -190,13 +189,22 @@ jQuery.noConflict();
|
||||
},
|
||||
|
||||
/**
|
||||
* Change the options of the threeColumnCompressor layout, and trigger layouting. You can provide any or
|
||||
* all options. The remaining options will not be changed.
|
||||
* Change the options of the threeColumnCompressor layout, and trigger layouting if needed.
|
||||
* You can provide any or all options. The remaining options will not be changed.
|
||||
*/
|
||||
updateLayoutOptions: function(newSpec) {
|
||||
var spec = this.getLayoutOptions();
|
||||
$.extend(spec, newSpec);
|
||||
this.redraw();
|
||||
|
||||
var dirty = false;
|
||||
|
||||
for (var k in newSpec) {
|
||||
if (spec[k] !== newSpec[k]) {
|
||||
spec[k] = newSpec[k];
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (dirty) this.redraw();
|
||||
},
|
||||
|
||||
/**
|
||||
@ -206,7 +214,6 @@ jQuery.noConflict();
|
||||
this.updateLayoutOptions({
|
||||
mode: 'split'
|
||||
});
|
||||
this.redraw();
|
||||
},
|
||||
|
||||
/**
|
||||
@ -216,7 +223,6 @@ jQuery.noConflict();
|
||||
this.updateLayoutOptions({
|
||||
mode: 'content'
|
||||
});
|
||||
this.redraw();
|
||||
},
|
||||
|
||||
/**
|
||||
@ -226,10 +232,13 @@ jQuery.noConflict();
|
||||
this.updateLayoutOptions({
|
||||
mode: 'preview'
|
||||
});
|
||||
this.redraw();
|
||||
},
|
||||
|
||||
RedrawSuppression: false,
|
||||
|
||||
redraw: function() {
|
||||
if (this.getRedrawSuppression()) return;
|
||||
|
||||
if(window.debug) console.log('redraw', this.attr('class'), this.get(0));
|
||||
|
||||
// Reset the algorithm.
|
||||
@ -247,9 +256,9 @@ jQuery.noConflict();
|
||||
this.layout();
|
||||
|
||||
// Redraw on all the children that need it
|
||||
this.find('.cms-panel-layout').redraw();
|
||||
this.find('.cms-content-fields[data-layout-type]').redraw();
|
||||
this.find('.cms-edit-form[data-layout-type]').redraw();
|
||||
this.find('.cms-panel-layout').redraw();
|
||||
this.find('.cms-content-fields[data-layout-type]').redraw();
|
||||
this.find('.cms-edit-form[data-layout-type]').redraw();
|
||||
this.find('.cms-preview').redraw();
|
||||
this.find('.cms-content').redraw();
|
||||
},
|
||||
@ -504,62 +513,67 @@ jQuery.noConflict();
|
||||
newFragments[guessFragment] = $data;
|
||||
}
|
||||
|
||||
// Replace each fragment individually
|
||||
$.each(newFragments, function(newFragment, html) {
|
||||
var contentEl = $('[data-pjax-fragment]').filter(function() {
|
||||
return $.inArray(newFragment, $(this).data('pjaxFragment').split(' ')) != -1;
|
||||
}), newContentEl = $(html);
|
||||
this.setRedrawSuppression(true);
|
||||
try {
|
||||
// Replace each fragment individually
|
||||
$.each(newFragments, function(newFragment, html) {
|
||||
var contentEl = $('[data-pjax-fragment]').filter(function() {
|
||||
return $.inArray(newFragment, $(this).data('pjaxFragment').split(' ')) != -1;
|
||||
}), newContentEl = $(html);
|
||||
|
||||
// Add to result collection
|
||||
if(newContentEls) newContentEls.add(newContentEl);
|
||||
else newContentEls = newContentEl;
|
||||
|
||||
// Update panels
|
||||
if(newContentEl.find('.cms-container').length) {
|
||||
throw 'Content loaded via ajax is not allowed to contain tags matching the ".cms-container" selector to avoid infinite loops';
|
||||
}
|
||||
|
||||
// Set loading state and store element state
|
||||
var origStyle = contentEl.attr('style');
|
||||
var origParent = contentEl.parent();
|
||||
var origParentLayoutApplied = (typeof origParent.data('jlayout')!=='undefined');
|
||||
var layoutClasses = ['east', 'west', 'center', 'north', 'south', 'column-hidden'];
|
||||
var elemClasses = contentEl.attr('class');
|
||||
var origLayoutClasses = [];
|
||||
if(elemClasses) {
|
||||
origLayoutClasses = $.grep(
|
||||
elemClasses.split(' '),
|
||||
function(val) { return ($.inArray(val, layoutClasses) >= 0);}
|
||||
);
|
||||
}
|
||||
|
||||
newContentEl
|
||||
.removeClass(layoutClasses.join(' '))
|
||||
.addClass(origLayoutClasses.join(' '));
|
||||
if(origStyle) newContentEl.attr('style', origStyle);
|
||||
// Add to result collection
|
||||
if(newContentEls) newContentEls.add(newContentEl);
|
||||
else newContentEls = newContentEl;
|
||||
|
||||
// Allow injection of inline styles, as they're not allowed in the document body.
|
||||
// Not handling this through jQuery.ondemand to avoid parsing the DOM twice.
|
||||
var styles = newContentEl.find('style').detach();
|
||||
if(styles.length) $(document).find('head').append(styles);
|
||||
// Update panels
|
||||
if(newContentEl.find('.cms-container').length) {
|
||||
throw 'Content loaded via ajax is not allowed to contain tags matching the ".cms-container" selector to avoid infinite loops';
|
||||
}
|
||||
|
||||
// Replace panel completely (we need to override the "layout" attribute, so can't replace the child instead)
|
||||
contentEl.replaceWith(newContentEl);
|
||||
// Set loading state and store element state
|
||||
var origStyle = contentEl.attr('style');
|
||||
var origParent = contentEl.parent();
|
||||
var origParentLayoutApplied = (typeof origParent.data('jlayout')!=='undefined');
|
||||
var layoutClasses = ['east', 'west', 'center', 'north', 'south', 'column-hidden'];
|
||||
var elemClasses = contentEl.attr('class');
|
||||
var origLayoutClasses = [];
|
||||
if(elemClasses) {
|
||||
origLayoutClasses = $.grep(
|
||||
elemClasses.split(' '),
|
||||
function(val) { return ($.inArray(val, layoutClasses) >= 0);}
|
||||
);
|
||||
}
|
||||
|
||||
// Force jlayout to rebuild internal hierarchy to point to the new elements.
|
||||
// This is only necessary for elements that are at least 3 levels deep. 2nd level elements will
|
||||
// be taken care of when we lay out the top level element (.cms-container).
|
||||
if (!origParent.is('.cms-container') && origParentLayoutApplied) {
|
||||
origParent.layout();
|
||||
}
|
||||
});
|
||||
newContentEl
|
||||
.removeClass(layoutClasses.join(' '))
|
||||
.addClass(origLayoutClasses.join(' '));
|
||||
if(origStyle) newContentEl.attr('style', origStyle);
|
||||
|
||||
// Re-init tabs (in case the form tag itself is a tabset)
|
||||
var newForm = newContentEls.filter('form');
|
||||
if(newForm.hasClass('cms-tabset')) newForm.removeClass('cms-tabset').addClass('cms-tabset');
|
||||
// Allow injection of inline styles, as they're not allowed in the document body.
|
||||
// Not handling this through jQuery.ondemand to avoid parsing the DOM twice.
|
||||
var styles = newContentEl.find('style').detach();
|
||||
if(styles.length) $(document).find('head').append(styles);
|
||||
|
||||
// Replace panel completely (we need to override the "layout" attribute, so can't replace the child instead)
|
||||
contentEl.replaceWith(newContentEl);
|
||||
|
||||
// Force jlayout to rebuild internal hierarchy to point to the new elements.
|
||||
// This is only necessary for elements that are at least 3 levels deep. 2nd level elements will
|
||||
// be taken care of when we lay out the top level element (.cms-container).
|
||||
if (!origParent.is('.cms-container') && origParentLayoutApplied) {
|
||||
origParent.layout();
|
||||
}
|
||||
});
|
||||
|
||||
// Re-init tabs (in case the form tag itself is a tabset)
|
||||
var newForm = newContentEls.filter('form');
|
||||
if(newForm.hasClass('cms-tabset')) newForm.removeClass('cms-tabset').addClass('cms-tabset');
|
||||
}
|
||||
finally {
|
||||
this.setRedrawSuppression(false);
|
||||
}
|
||||
|
||||
this.redraw();
|
||||
|
||||
this.restoreTabState((state && typeof state.data.tabState !== 'undefined') ? state.data.tabState : null);
|
||||
|
||||
return newContentEls;
|
||||
|
Loading…
x
Reference in New Issue
Block a user