Reputation: 1097
I need to add contenteditable="false"
on all CKEditor content elements having CSS class="readonly"
and contenteditable="true"
to elements having CSS class="writable"
. Preferably on paste and instance ready.
I know of config.on.instanceReady
and config.on.paste
but what should I write into the function just eludes me ;)
Btw. I'm not using inline editor.
editor.document is listed as read only property in the documentation so I cannot use that.
Final solution thanks to Oleq for showing me to the right path. applyToAll is required if writables are within readonly.
// Add custom rule to dataFilter (when data comes *into* editor).
on{pluginsLoaded: function (evt){
this.dataProcessor.dataFilter.addRules( {
elements: {
$: function ( element ) {
if (element.hasClass('readonly'))
{
element.attributes.contenteditable = 'false';
}
if (element.hasClass('writable'))
{
element.attributes.contenteditable = 'true';
}
}
}
},{applyToAll: true});
this.dataProcessor.htmlFilter.addRules( {
elements: {
$: function ( element ) {
if(element.hasClass('readonly') || element.hasClass('writable'))
{
delete element.attributes.contenteditable;
}
}
}
},{applyToAll: true});
});
Upvotes: 1
Views: 1762
Reputation: 15895
You should use CKEditor's dataProcessor.dataFilter
. This is the standard mechanism used by the editor to filter input (JSFiddle). It handles data set with editor.setData
, data pasted by the user and, of course, initial HTML from textarea or any element to which CKEditor is attached.
CKEDITOR.replace( 'my-editor', {
// See http://stackoverflow.com/a/15659962/1485219
extraAllowedContent: 'span(readonly)',
// Just to make the interface clear.
toolbarGroups: [
{"name":"document","groups":["mode"]},
{"name":"basicstyles","groups":["basicstyles"]}
],
on: {
// When all plugins were loaded but editor data is not yet processed.
pluginsLoaded: function( evt ) {
// Add custom rule to dataFilter (when data comes *into* editor).
this.dataProcessor.dataFilter.addRules( {
elements: {
// Check all elements. Rules can be specific, i.e. for img or h2.
$: function( element ) {
if ( element.hasClass( 'readonly' ) ) {
element.attributes.contenteditable = "false";
}
}
}
} );
}
}
} );
EDIT: I created you a widget (JSFiddle) because I feel this is what you really wanted to do:
// This plugin brings a widget into editor.
CKEDITOR.plugins.add( 'myFirstWidget', {
// Widget plugin must be loaded (must be present in the build of CKEditor).
requires: 'widget',
init: function( editor ) {
editor.widgets.add( 'myFirstWidget', {
button: 'My First Widget Button',
// http://stackoverflow.com/a/15659962/1485219
allowedContent: 'span(readonly)',
requiredContent: 'span(readonly)',
// Make all <span class="readonly"> a non-editable widget.
upcast: function( element ) {
return element.name == 'span' && element.hasClass( 'readonly' );
}
} );
}
} );
CKEDITOR.replace( 'my-editor', {
// Use the plugin.
extraPlugins: 'myFirstWidget',
// Just to make the interface clear.
toolbar: [ [ 'Source', '-', 'MyFirstWidget' ] ]
} );
Learn more about widgets and awesomeness they bring.
Upvotes: 1
Reputation: 5249
You could do this in JavaScript:
var readOnlyEls = document.querySelectorAll('.readonly');
for (var i=0; i < readOnlyEls.length; i++) {
readOnlyEls[i].setAttribute("contenteditable", false);
}
var writableEls = document.querySelectorAll('.writable');
for (var i=0; i < writableEls .length; i++) {
writableEls[i].setAttribute("contenteditable", true);
}
Or if you are using jQuery:
$(".readonly").attr("contenteditable", false);
$(".writable").attr("contenteditable", true);
Upvotes: 0