mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 12:05:37 +00:00
ENHANCEMENT Lazy-loading image and link dialogs for HtmlEditorField, to avoid unnecessary processing overhead on initial CMS load (also means they'll never get loaded if not required, e.g. in ReportAdmin)
This commit is contained in:
parent
c73b80049a
commit
b025b95ede
@ -24,12 +24,7 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="cms-editor-dialogs" class="hide">
|
$EditorToolbar
|
||||||
<% control EditorToolbar %>
|
|
||||||
$MediaForm
|
|
||||||
$LinkForm
|
|
||||||
<% end_control %>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- <div class="ss-cms-bottom-bar">
|
<!-- <div class="ss-cms-bottom-bar">
|
||||||
<div class="holder">
|
<div class="holder">
|
||||||
|
@ -267,6 +267,14 @@ class HtmlEditorField_Toolbar extends RequestHandler {
|
|||||||
$this->name = $name;
|
$this->name = $name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function forTemplate() {
|
||||||
|
return sprintf(
|
||||||
|
'<div id="cms-editor-dialogs" data-url-linkform="%s" data-url-mediaform="%s"></div>',
|
||||||
|
Controller::join_links($this->controller->Link($this->name), 'LinkForm', 'forTemplate'),
|
||||||
|
Controller::join_links($this->controller->Link($this->name), 'MediaForm', 'forTemplate')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Searches the SiteTree for display in the dropdown
|
* Searches the SiteTree for display in the dropdown
|
||||||
*
|
*
|
||||||
@ -627,6 +635,7 @@ class HtmlEditorField_Toolbar extends RequestHandler {
|
|||||||
$this->extend('updateAllowedExtensions', $exts);
|
$this->extend('updateAllowedExtensions', $exts);
|
||||||
return $exts;
|
return $exts;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -251,12 +251,10 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
|
|||||||
|
|
||||||
this._super();
|
this._super();
|
||||||
},
|
},
|
||||||
|
|
||||||
isChanged: function() {
|
isChanged: function() {
|
||||||
var ed = this.getEditor();
|
var ed = this.getEditor();
|
||||||
return (ed && ed.getInstance() && ed.isDirty());
|
return (ed && ed.getInstance() && ed.isDirty());
|
||||||
},
|
},
|
||||||
|
|
||||||
resetChanged: function() {
|
resetChanged: function() {
|
||||||
var ed = this.getEditor();
|
var ed = this.getEditor();
|
||||||
if(typeof tinyMCE == 'undefined') return;
|
if(typeof tinyMCE == 'undefined') return;
|
||||||
@ -265,7 +263,35 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
|
|||||||
var inst = tinyMCE.getInstanceById(this.attr('id'));
|
var inst = tinyMCE.getInstanceById(this.attr('id'));
|
||||||
if (inst) inst.startContent = tinymce.trim(inst.getContent({format : 'raw', no_events : 1}));
|
if (inst) inst.startContent = tinymce.trim(inst.getContent({format : 'raw', no_events : 1}));
|
||||||
},
|
},
|
||||||
|
openLinkDialog: function() {
|
||||||
|
this.openDialog('link');
|
||||||
|
},
|
||||||
|
openMediaDialog: function() {
|
||||||
|
this.openDialog('media');
|
||||||
|
},
|
||||||
|
openDialog: function(type) {
|
||||||
|
var capitalize = function(text) {
|
||||||
|
return text.charAt(0).toUpperCase() + text.slice(1).toLowerCase();
|
||||||
|
};
|
||||||
|
|
||||||
|
var url = $('#cms-editor-dialogs').data('url' + capitalize(type) + 'form'),
|
||||||
|
dialog = $('.htmleditorfield-' + type + 'dialog');
|
||||||
|
|
||||||
|
if(dialog.length) {
|
||||||
|
dialog.open();
|
||||||
|
} else {
|
||||||
|
// Show a placeholder for instant feedback. Will be replaced with actual
|
||||||
|
// form dialog once its loaded.
|
||||||
|
dialog = $('<div class="htmleditorfield-dialog htmleditorfield-' + type + 'dialog loading">');
|
||||||
|
$('body').append(dialog);
|
||||||
|
$.ajax({
|
||||||
|
url: url,
|
||||||
|
success: function(html) {
|
||||||
|
dialog.html(html);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
onunmatch: function() {
|
onunmatch: function() {
|
||||||
// TODO Throws exceptions in Firefox, most likely due to the element being removed from the DOM at this point
|
// 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'));
|
// var ed = tinyMCE.get(this.attr('id'));
|
||||||
@ -275,6 +301,35 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('.htmleditorfield-dialog').entwine({
|
||||||
|
onmatch: function() {
|
||||||
|
// Create jQuery dialog
|
||||||
|
this.dialog({autoOpen: true, bgiframe: true, modal: true, height: 500, width: '80%', ghost: true});
|
||||||
|
|
||||||
|
this._super();
|
||||||
|
},
|
||||||
|
getForm: function() {
|
||||||
|
return this.find('form');
|
||||||
|
},
|
||||||
|
open: function() {
|
||||||
|
this.dialog('open');
|
||||||
|
},
|
||||||
|
close: function() {
|
||||||
|
this.dialog('close');
|
||||||
|
},
|
||||||
|
toggle: function(bool) {
|
||||||
|
if(this.is(':visible')) this.close();
|
||||||
|
else this.open();
|
||||||
|
},
|
||||||
|
ondialogopen: function(e) {
|
||||||
|
this.getForm().updateFromEditor();
|
||||||
|
this.redraw();
|
||||||
|
},
|
||||||
|
ondialogclose: function(e) {
|
||||||
|
this.getForm().resetFields();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base form implementation for interactions with an editor instance,
|
* Base form implementation for interactions with an editor instance,
|
||||||
* mostly geared towards modification and insertion of content.
|
* mostly geared towards modification and insertion of content.
|
||||||
@ -286,40 +341,30 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
|
|||||||
|
|
||||||
// TODO Figure out how to keep bookmark reference in entwine, and still be allowed to delete the JS object
|
// TODO Figure out how to keep bookmark reference in entwine, and still be allowed to delete the JS object
|
||||||
// Bookmark: null,
|
// Bookmark: null,
|
||||||
|
|
||||||
onmatch: function() {
|
onmatch: function() {
|
||||||
// Move title from headline to (jQuery compatible) title attribute
|
// Move title from headline to (jQuery compatible) title attribute
|
||||||
var titleEl = this.find(':header:first');
|
var titleEl = this.find(':header:first');
|
||||||
this.attr('title', titleEl.text());
|
this.getDialog().attr('title', titleEl.text());
|
||||||
titleEl.remove();
|
titleEl.remove();
|
||||||
|
|
||||||
// Create jQuery dialog
|
|
||||||
this.dialog({autoOpen: false, bgiframe: true, modal: true, height: 500, width: '80%', ghost: true});
|
|
||||||
|
|
||||||
this.setEditor(ss.editorWrappers['default']());
|
this.setEditor(ss.editorWrappers['default']());
|
||||||
},
|
},
|
||||||
redraw: function() {
|
redraw: function() {
|
||||||
},
|
},
|
||||||
toggle: function() {
|
resetFields: function() {
|
||||||
if(this.is(':visible')) this.close();
|
|
||||||
else this.open();
|
|
||||||
},
|
|
||||||
close: function() {
|
|
||||||
this.dialog('close');
|
|
||||||
this.getEditor().onclose();
|
|
||||||
if(typeof window._ss_htmleditorfield_bookmark != 'undefined') window._ss_htmleditorfield_bookmark = null;
|
if(typeof window._ss_htmleditorfield_bookmark != 'undefined') window._ss_htmleditorfield_bookmark = null;
|
||||||
|
this.getEditor().onclose();
|
||||||
},
|
},
|
||||||
open: function() {
|
getDialog: function() {
|
||||||
this.updateFromEditor();
|
// TODO Refactor to listen to form events to remove two-way coupling
|
||||||
this.dialog('open');
|
return this.closest('.htmleditorfield-dialog');
|
||||||
this.redraw();
|
|
||||||
this.getEditor().onopen();
|
|
||||||
window._ss_htmleditorfield_bookmark = this.getEditor().createBookmark();
|
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* Update the view state based on the current editor selection.
|
* Update the view state based on the current editor selection.
|
||||||
*/
|
*/
|
||||||
updateFromEditor: function() {
|
updateFromEditor: function() {
|
||||||
|
this.getEditor().onopen();
|
||||||
|
window._ss_htmleditorfield_bookmark = this.getEditor().createBookmark();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -331,23 +376,16 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
|
|||||||
*/
|
*/
|
||||||
$('form.htmleditorfield-linkform').entwine({
|
$('form.htmleditorfield-linkform').entwine({
|
||||||
|
|
||||||
close: function() {
|
|
||||||
this._super();
|
|
||||||
|
|
||||||
this.resetFields();
|
|
||||||
},
|
|
||||||
|
|
||||||
// TODO Entwine doesn't respect submits triggered by ENTER key
|
// TODO Entwine doesn't respect submits triggered by ENTER key
|
||||||
onsubmit: function(e) {
|
onsubmit: function(e) {
|
||||||
this.insertLink();
|
this.insertLink();
|
||||||
this.close();
|
this.getDialog().close();
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
resetFields: function() {
|
resetFields: function() {
|
||||||
|
this._super();
|
||||||
this.find('fieldset :input:not(:radio)').val('').change();
|
this.find('fieldset :input:not(:radio)').val('').change();
|
||||||
},
|
},
|
||||||
|
|
||||||
redraw: function(setDefaults) {
|
redraw: function(setDefaults) {
|
||||||
this._super();
|
this._super();
|
||||||
|
|
||||||
@ -377,7 +415,6 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
|
|||||||
this.find(':input[name=TargetBlank]').attr('checked', (linkType == 'file'));
|
this.find(':input[name=TargetBlank]').attr('checked', (linkType == 'file'));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
insertLink: function() {
|
insertLink: function() {
|
||||||
var href, target = null, anchor = this.find(':input[name=Anchor]').val(), ed = this.getEditor();
|
var href, target = null, anchor = this.find(':input[name=Anchor]').val(), ed = this.getEditor();
|
||||||
|
|
||||||
@ -428,12 +465,10 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
|
|||||||
this.trigger('onafterinsert', attributes);
|
this.trigger('onafterinsert', attributes);
|
||||||
this.updateFromEditor();
|
this.updateFromEditor();
|
||||||
},
|
},
|
||||||
|
|
||||||
removeLink: function() {
|
removeLink: function() {
|
||||||
this.getEditor().removeLink();
|
this.getEditor().removeLink();
|
||||||
this.close();
|
this.close();
|
||||||
},
|
},
|
||||||
|
|
||||||
addAnchorSelector: function() {
|
addAnchorSelector: function() {
|
||||||
// Avoid adding twice
|
// Avoid adding twice
|
||||||
if(this.find(':input[name=AnchorSelector]').length) return;
|
if(this.find(':input[name=AnchorSelector]').length) return;
|
||||||
@ -466,7 +501,6 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
|
|||||||
self.find(':input[name="Anchor"]').val($(this).val());
|
self.find(':input[name="Anchor"]').val($(this).val());
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// this function collects the anchors in the currently active editor and regenerates the dropdown
|
// this function collects the anchors in the currently active editor and regenerates the dropdown
|
||||||
refreshAnchors: function() {
|
refreshAnchors: function() {
|
||||||
var selector = this.find(':input[name=AnchorSelector]'), anchors = [];
|
var selector = this.find(':input[name=AnchorSelector]'), anchors = [];
|
||||||
@ -485,7 +519,6 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
|
|||||||
selector.append($('<option value="'+anchors[j]+'">'+anchors[j]+'</option>'));
|
selector.append($('<option value="'+anchors[j]+'">'+anchors[j]+'</option>'));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
updateFromEditor: function() {
|
updateFromEditor: function() {
|
||||||
var htmlTagPattern = /<\S[^><]*>/g, fieldName, data = this.getCurrentLink();
|
var htmlTagPattern = /<\S[^><]*>/g, fieldName, data = this.getCurrentLink();
|
||||||
|
|
||||||
@ -502,7 +535,6 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return information about the currently selected link, suitable for population of the link
|
* Return information about the currently selected link, suitable for population of the link
|
||||||
* form.
|
* form.
|
||||||
@ -623,13 +655,11 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
|
|||||||
$(this).insertHTML();
|
$(this).insertHTML();
|
||||||
});
|
});
|
||||||
ed.repaint();
|
ed.repaint();
|
||||||
this.close();
|
this.getDialog().close();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
ondialogopen: function() {
|
updateFromEditor: function() {
|
||||||
this.redraw();
|
|
||||||
|
|
||||||
var self = this, ed = this.getEditor(), node = $(ed.getSelectedNode());
|
var self = this, ed = this.getEditor(), node = $(ed.getSelectedNode());
|
||||||
// TODO Depends on managed mime type
|
// TODO Depends on managed mime type
|
||||||
if(node.is('img')) {
|
if(node.is('img')) {
|
||||||
@ -645,16 +675,6 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
|
|||||||
// don't respect the z-index of the dialog overlay.
|
// don't respect the z-index of the dialog overlay.
|
||||||
// jQuery(ed.getContainer()).hide();
|
// jQuery(ed.getContainer()).hide();
|
||||||
},
|
},
|
||||||
ondialogclose: function() {
|
|
||||||
var ed = this.getEditor(), node = $(ed.getSelectedNode());
|
|
||||||
|
|
||||||
// HACK: See ondialogopen()
|
|
||||||
// jQuery(ed.getContainer()).show();
|
|
||||||
|
|
||||||
this.find('.ss-htmleditorfield-file').remove(); // Remove any existing views
|
|
||||||
this.find('.ss-gridfield-items .ui-selected').removeClass('ui-selected'); // Unselect all items
|
|
||||||
this.redraw();
|
|
||||||
},
|
|
||||||
redraw: function() {
|
redraw: function() {
|
||||||
this._super();
|
this._super();
|
||||||
|
|
||||||
@ -673,6 +693,18 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
|
|||||||
// Hide file selection and step labels when editing an existing file
|
// Hide file selection and step labels when editing an existing file
|
||||||
this.find('#MediaFormInsertImageTabs,.header-edit')[editingSelected ? 'hide' : 'show']();
|
this.find('#MediaFormInsertImageTabs,.header-edit')[editingSelected ? 'hide' : 'show']();
|
||||||
},
|
},
|
||||||
|
resetFields: function() {
|
||||||
|
var ed = this.getEditor(), node = $(ed.getSelectedNode());
|
||||||
|
|
||||||
|
// HACK: See ondialogopen()
|
||||||
|
// jQuery(ed.getContainer()).show();
|
||||||
|
|
||||||
|
this.find('.ss-htmleditorfield-file').remove(); // Remove any existing views
|
||||||
|
this.find('.ss-gridfield-items .ui-selected').removeClass('ui-selected'); // Unselect all items
|
||||||
|
this.redraw();
|
||||||
|
|
||||||
|
this._super();
|
||||||
|
},
|
||||||
getFileView: function(idOrUrl) {
|
getFileView: function(idOrUrl) {
|
||||||
return this.find('.ss-htmleditorfield-file[data-id=' + idOrUrl + ']');
|
return this.find('.ss-htmleditorfield-file[data-id=' + idOrUrl + ']');
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user