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 id="cms-editor-dialogs" class="hide">
|
||||
<% control EditorToolbar %>
|
||||
$MediaForm
|
||||
$LinkForm
|
||||
<% end_control %>
|
||||
</div>
|
||||
$EditorToolbar
|
||||
|
||||
<!-- <div class="ss-cms-bottom-bar">
|
||||
<div class="holder">
|
||||
|
@ -267,6 +267,14 @@ class HtmlEditorField_Toolbar extends RequestHandler {
|
||||
$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
|
||||
*
|
||||
@ -627,6 +635,7 @@ class HtmlEditorField_Toolbar extends RequestHandler {
|
||||
$this->extend('updateAllowedExtensions', $exts);
|
||||
return $exts;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -251,12 +251,10 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
|
||||
|
||||
this._super();
|
||||
},
|
||||
|
||||
isChanged: function() {
|
||||
var ed = this.getEditor();
|
||||
return (ed && ed.getInstance() && ed.isDirty());
|
||||
},
|
||||
|
||||
resetChanged: function() {
|
||||
var ed = this.getEditor();
|
||||
if(typeof tinyMCE == 'undefined') return;
|
||||
@ -265,7 +263,35 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
|
||||
var inst = tinyMCE.getInstanceById(this.attr('id'));
|
||||
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() {
|
||||
// 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'));
|
||||
@ -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,
|
||||
* 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
|
||||
// Bookmark: null,
|
||||
|
||||
onmatch: function() {
|
||||
// Move title from headline to (jQuery compatible) title attribute
|
||||
var titleEl = this.find(':header:first');
|
||||
this.attr('title', titleEl.text());
|
||||
this.getDialog().attr('title', titleEl.text());
|
||||
titleEl.remove();
|
||||
|
||||
// Create jQuery dialog
|
||||
this.dialog({autoOpen: false, bgiframe: true, modal: true, height: 500, width: '80%', ghost: true});
|
||||
|
||||
this.setEditor(ss.editorWrappers['default']());
|
||||
},
|
||||
redraw: function() {
|
||||
},
|
||||
toggle: function() {
|
||||
if(this.is(':visible')) this.close();
|
||||
else this.open();
|
||||
},
|
||||
close: function() {
|
||||
this.dialog('close');
|
||||
this.getEditor().onclose();
|
||||
resetFields: function() {
|
||||
if(typeof window._ss_htmleditorfield_bookmark != 'undefined') window._ss_htmleditorfield_bookmark = null;
|
||||
this.getEditor().onclose();
|
||||
},
|
||||
open: function() {
|
||||
this.updateFromEditor();
|
||||
this.dialog('open');
|
||||
this.redraw();
|
||||
this.getEditor().onopen();
|
||||
window._ss_htmleditorfield_bookmark = this.getEditor().createBookmark();
|
||||
getDialog: function() {
|
||||
// TODO Refactor to listen to form events to remove two-way coupling
|
||||
return this.closest('.htmleditorfield-dialog');
|
||||
},
|
||||
/**
|
||||
* Update the view state based on the current editor selection.
|
||||
*/
|
||||
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({
|
||||
|
||||
close: function() {
|
||||
this._super();
|
||||
|
||||
this.resetFields();
|
||||
},
|
||||
|
||||
// TODO Entwine doesn't respect submits triggered by ENTER key
|
||||
onsubmit: function(e) {
|
||||
this.insertLink();
|
||||
this.close();
|
||||
this.getDialog().close();
|
||||
return false;
|
||||
},
|
||||
|
||||
resetFields: function() {
|
||||
this._super();
|
||||
this.find('fieldset :input:not(:radio)').val('').change();
|
||||
},
|
||||
|
||||
redraw: function(setDefaults) {
|
||||
this._super();
|
||||
|
||||
@ -377,7 +415,6 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
|
||||
this.find(':input[name=TargetBlank]').attr('checked', (linkType == 'file'));
|
||||
}
|
||||
},
|
||||
|
||||
insertLink: function() {
|
||||
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.updateFromEditor();
|
||||
},
|
||||
|
||||
removeLink: function() {
|
||||
this.getEditor().removeLink();
|
||||
this.close();
|
||||
},
|
||||
|
||||
addAnchorSelector: function() {
|
||||
// Avoid adding twice
|
||||
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());
|
||||
});
|
||||
},
|
||||
|
||||
// this function collects the anchors in the currently active editor and regenerates the dropdown
|
||||
refreshAnchors: function() {
|
||||
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>'));
|
||||
}
|
||||
},
|
||||
|
||||
updateFromEditor: function() {
|
||||
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
|
||||
* form.
|
||||
@ -623,13 +655,11 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
|
||||
$(this).insertHTML();
|
||||
});
|
||||
ed.repaint();
|
||||
this.close();
|
||||
this.getDialog().close();
|
||||
|
||||
return false;
|
||||
},
|
||||
ondialogopen: function() {
|
||||
this.redraw();
|
||||
|
||||
updateFromEditor: function() {
|
||||
var self = this, ed = this.getEditor(), node = $(ed.getSelectedNode());
|
||||
// TODO Depends on managed mime type
|
||||
if(node.is('img')) {
|
||||
@ -645,16 +675,6 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
|
||||
// don't respect the z-index of the dialog overlay.
|
||||
// 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() {
|
||||
this._super();
|
||||
|
||||
@ -673,6 +693,18 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
|
||||
// Hide file selection and step labels when editing an existing file
|
||||
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) {
|
||||
return this.find('.ss-htmleditorfield-file[data-id=' + idOrUrl + ']');
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user