CKEditor Custom Toolbar Configuration - javascript

I've looked through several questions in this forum and the CKEditor site about this topic, but nothing's helped so far. First of all, I'm running CKEditor 4.3.2 on a SharePoint 2010 site, using inline editors within a jQuery UI modal dialog. Adding CKEditor to the dialog was painless, but I can't say the same for setting up a slimmer toolbar. Here's what I've done so far:
slimConfig.js
CKEDITOR.editorConfig = function(config) {
config.toolbar = [
{name: "basicstyles", items: ["Bold", "Italic", "Underline", "Strike", "Subscript", "Superscript", "-", "RemoveFormat"]},
{name: "paragraph", items: ["NumberedList", "BulletedList"]}
];
}
Source JavaScript
setToolbar("notes");
setToolbar("access");
//. . .[several other fields]. . .
function setToolbar(divName) {
CKEDITOR.replace(divName, {customConfig: "/customConfigs/slimConfig.js"});
}
Additionally, I've set up the target fields as divs using contenteditable set to true, like this:
<div id="notes" contenteditable="true"></div>
The script seems to run well until it hits an exception on ckeditor.js line 308, where the error text is "The editor instance is already attached to the provided element." After a few more steps, it returns to the same area on line 308, at which point I get a terminal exception with the message, "Exception thrown and not caught."
I believe I have everything set up properly right now, but don't know what to make of this error. Does anyone have experience with getting customized toolbars set up?

By default CKEditor replaces all elements of contenteditable="true" with inline editors. So when you try to replace it once again, it will throw an error because it doesn't make sense.
If you want to take a full control over your editors, set CKEDITOR.disableAutoInline to false and take care of all instances manually. Of course, you can always find your instance in CKEDITOR.instances object and call editor.destroy() if you want to.
See http://docs.ckeditor.com/#!/guide/dev_inline

Related

CKEditor adds <p> </p> after initializing

I have tried all kinds of settings to get rid of this issue, but so far I haven't had any luck. I am running CKEditor in my angular(1.5.6) app. First I was using this angular directive, but after running into this problem, I tried running CKEditor with as little things as possible to find the cause to this.
Atm this is all I have in my controller:
$scope.description = "<p>test</p><p>test</p>";
CKEDITOR.replace('description');
CKEDITOR.instances['description'].setData($scope.description);
In my view:
<div id="description"></div>
After initializing this is what I will have in the editor:
<p>test</p>
<p>test</p>
<p> </p>
Every time the CKEditor is loaded it will add this empty paragraph. Now if I save this the empty paragraph gets saved to database. When loaded again, it will have 2 empty paragraphs.
Here is list of settings I have tried to fix this. Mostly I have used them one by one.
$scope.ckEditorOptions = {
ignoreEmptyParagraph: false,
enterMode: CKEDITOR.ENTER_BR,
autoParagraph: false,
fillEmptyBlocks: false,
shiftEnterMode: CKEDITOR.ENTER_BR,
basicEntities: false,
tabSpaces: 0,
};
I'm using V4.16. It adds a p tag, and a non breaking space at the beginning and end of the text, every time I hit the "save" button. I went through all the suggested twiddles with the config file, but no luck. So now I use the PHP function str_replace() on the text from the editor on its way to the database. Not very elegant, but works a treat !
I've been confused by a similar issue (using CKGEdit for DokuWiki and CKEditor is adding empty paragraphs at the top of the page and below some elements).
Have bodged around it for now by adding this to to the bottom of config.js:
var ed = CKEDITOR.instances.wiki__text;
var t = ed.getData().replace(/<p>[\s*| ]<\/p>/gm,'');
ed.setData(t, function() {
this.checkDirty();
});
..which might be the basis of something useful for anyone else in the same situation.
None of the editor options helped without introducing other issues (e.g. breaking wiki markup).

Inline CKEditor toolbar has no alignment buttons for h2 elements

(also on their demo page http://ckeditor.com/demo#inline)
Why is this the case? Even if I take their inline sample (http://nightly.ckeditor.com/13-02-08-08-51/standard/samples/inlineall.html) and remove the js code for separate toolbars for heading blocks, I still don't get the alignment option.
I'd like to give users the option to align headings. What am I missing?
I'm also not getting other "block" options like BulletedList, but that's less of an issue.
UPDATE: To repeat the issue you need to have contenteditable="true" applied to a heading element. So, one fix is to wrap the heading in a div with the contenteditable="true". But this doesn't help my case.
You need the Justify plugin since CKEditor 4.
Download Justify plugin here
Paste it into ckeditor/plugins/
Add the plugin to your ckeditor.
Here is the javascript code :
$(function() {
CKEDITOR.config.extraPlugins = 'justify';
});
You don't have anything more to do, Justify plugin will be automatically added to the paragraph toolbarGroup
EDIT
By alignment, I thought you were talking about right|center|left align.
Here, for h tags, we've got those groups :
if ( element.is( 'h1', 'h2', 'h3' ) || element.getAttribute( 'id' ) == 'taglist' ) {
editor.on( 'configLoaded', function() {
editor.config.removePlugins = 'colorbutton,find,flash,font,' +
'forms,iframe,image,newpage,removeformat,scayt,' +
'smiley,specialchar,stylescombo,templates,wsc';
editor.config.toolbarGroups = [
{ name: 'editing', groups: [ 'basicstyles', 'links' ] },
{ name: 'undo' },
{ name: 'clipboard', groups: [ 'selection', 'clipboard' ] },
{ name: 'about' }
];
});
}
['basicstyles', 'links', 'undo', 'selection', 'clipboard', 'about'], there's no align group, simply add it.
You don't event have to modify anything after a new CKEditor install, this group is already in the inline basic configuration
It's impossible to enable align buttons on h2 editable. CKEditor cannot modify editable container, because that change simply wouldn't be visible in data got from editor, because editor.getData() returns innerHTML not outerHTML.
I'm also afraid that simple bypass doesn't exist. You can wrap h2 with editable div, set enterMode=BR, remove buttons like format combo from toolbar, but that would be still incomplete solution, because user will be able to remove that h2, split it by pasting some block elements or leave it somehow and write outside it. This issues may be fixed, but I guess that you don't want to spend on this another month :).
So, one year later I came back and handled it differently. I took the justify plugin, and made a copy of it that only works the elements with which the original plugin doesn't. I had to modify it to suit my needs, but commenting the following out was a start(plugin.js):
if ( editor.blockless )
return;
I don't know how interesting this is, but if anyone needs it, leave a comment and I'll post the entire source. It basically adds the text-align css to the editor element, instead of the inner block elements.
ensure you are using Full CKEditor version

Calling UI button externally

Answered:
Result can bee seen here: http://apitecture.com/dev/cked/index.2.html
Working code excerpt:
$('a.color').on({
click : function()
{
var self = $(this);
var editor = self.data('editor-instance') || CKEDITOR.instances['one'];
var button = self.data('editor-button') || editor.ui.create('TextColor');
if (!self.data('editor-instance'))
{
self.data('editor-instance', editor);
}
if (!self.data('editor-button'))
{
button._.id = self.attr('id');
self.data('editor-button', button);
}
button.click( editor );
}
});
I am working on a rich GUI based content editor.
I have come to conclusion, to use CKEditor for the text styling part, because it's 4th version comes with a lot of customization and configuration options, plus, is very well built.
I started to implement some of the commands in CK to my own toolbar, that isn't connected with CK. Apparently, my ventures weren't as easy as I thought they'd be...
http://apitecture.com/dev/cked/ <- here I have deployed a sandbox version.
On the left hand side, you can see a veeeery stripped down version of CK, and a custom toolbar.
On the right, exact replica, but with CK's native toolbar.
Simple commands, like Link and Bold, as you can see, are working, due to their simple nature.
The problem is with the Text Color button. It isn't bound to a command in CK, therefore I cannot execute it externally - well, at least I haven't found a way how.
Maybe somebody is pro enough with CK and could help me to figure this out?
The goal is to have the same functionality on my toolbar's button as the CK one.
I have found out, that upon clicking the Text Color, the color selection popup is appended to body, so, it doesn't extend upon CK styles and should, in theory, work standalone. Though, I cannot seem to find the code where the HTML is appended to body.
I have tried to get the UI button instance:
var color = CKEDITOR.instances['one'].ui.create('TextColor');
// and fire click on it
color.click();
But, that caused a partially expected (due to click not being started from toolbar) exception:
Uncaught TypeError: Cannot read property 'elementMode' of undefined ckeditor.js:552
CKEDITOR.ui.floatPanel.CKEDITOR.tools.createClass.$ ckeditor.js:552
CKEDITOR.ui.panelButton.CKEDITOR.tools.createClass.proto.createPanel ckeditor.js:541
e ckeditor.js:540
$.on.click cktest.js:59
v.event.dispatch jquery.min.js:2
o.handle.u
Seeing (from: console.log(color.click)) that the function accepts a parameter, I thought that I could provide any DOM element to it, by calling color.click( element );, that also caused error:
Uncaught TypeError: Cannot read property 'baseFloatZIndex' of undefined ckeditor.js:547
CKEDITOR.ui.panel.render ckeditor.js:547
o ckeditor.js:552
CKEDITOR.ui.floatPanel.CKEDITOR.tools.createClass.$ ckeditor.js:553
CKEDITOR.ui.panelButton.CKEDITOR.tools.createClass.proto.createPanel ckeditor.js:541
e ckeditor.js:540
$.on.click cktest.js:59
v.event.dispatch jquery.min.js:2
o.handle.u
Here is link to the source where the color plugin and it's buttons is introduced: https://github.com/ckeditor/ckeditor-dev/blob/master/plugins/colorbutton/plugin.js
Update:
I think this happens with every single button, that has dropdowns instead of dialogs.
Update 2:
Reinmar's answer did show some light at the end of the tunnel: http://apitecture.com/dev/cked/index.2.html
In the example, the "Color" text-link on the right can be clicked, and the dropdown shows, plus, it functions perfectly (besides that the shadow is enforced). The only catch here is, it works for the first time. Resulting in:
TypeError: Cannot read property 'title' of undefined
at CKEDITOR.ui.panel.block.CKEDITOR.tools.createClass.$ (http://apitecture.com/dev/cked/ckeditor/ckeditor.js:549:298)
at new b (http://apitecture.com/dev/cked/ckeditor/ckeditor.js:26:149)
at Object.CKEDITOR.ui.panel.addBlock (http://apitecture.com/dev/cked/ckeditor/ckeditor.js:547:503)
at CKEDITOR.ui.floatPanel.CKEDITOR.tools.createClass.proto.addBlock (http://apitecture.com/dev/cked/ckeditor/ckeditor.js:553:409)
at CKEDITOR.ui.panelButton.CKEDITOR.tools.createClass.proto.createPanel (http://apitecture.com/dev/cked/ckeditor/ckeditor.js:541:333)
at e [as click] (http://apitecture.com/dev/cked/ckeditor/ckeditor.js:540:304)
at HTMLAnchorElement.$.on.click (http://apitecture.com/dev/cked/cktest.2.js:64:24)
at HTMLAnchorElement.v.event.dispatch (http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js:2:38053)
at HTMLAnchorElement.o.handle.u (http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js:2:33916)
For every subsequent click.
You've asked a hardcore question :). I'm CKEditor core dev for last 1 year and I had to spend an hour digging in toolbar, panels and buttons. This part of CKE's API is really twisty and definitely lacks of documentation. But the worst part of it is that it's not really reusable, cause all the parts are tightly coupled.
Anyway. I tried to reuse colorbutton and I succeeded. On editor without toolbar plugin (this is important) I was able to open it for specified element:
And it even seems to work :) (at least on Chrome).
I'm curious how hard it will be for you to replace toolbar plugin with your own basic implementation (perhaps without a11y support and other heavy stuff). At the moment your bold and link buttons work correctly on Chrome, FF, Opera and IE7-9 (this in fact proves how cool CKE is because it does a lot in the background ;). I hope that you won't encounter any serious troubles.
Some tips:
You don't need to call editor.getCommand().exec(). There is an editor.execCommand() method.
You'll probably want to activate/deactivate buttons depending on context (caret location). Each command has its state and it's automatically updated on selectionChange event.
Good luck. And it will be cool if you share your thoughts and result of work with us :). Feedback will be very useful if someday we'll decide to improve this part of API.

Unable to get/set contents of tiny mce editor

I am using Tiny MCE editor version : 3.5.7
I am using multiple instances of text editor on same page with unique IDs and I have wrapped these editors in a div to show and hide these editors. Everything was working fine. Now I want to clear the contents of the editor when user hide it (so that when it is displayed again the previous contents are removed). I tried to do it using tinyMCE.get('editorId').setContent(''), it works fine only once.... I mean once I have used the above function than I am unable to set or even get the contents of that editor instance. The structure that I have used is as follows:
<div id="parentDIV">
<div id="1_editor">
</div>
</div>
tinyMCE.init({
mode: "exact",
max_char: "2000",
elements: "1_editor",
// Setting up ToolBar
theme: "advanced",
theme_advanced_layout_manager: "SimpleLayout",
theme_advanced_buttons1: "bold,italic,underline, strikethrough, separator,justifyleft, justifycenter,justifyright, justifyfull, separator,bullist,numlist,separator,fontselect ,fontsizeselect",
theme_advanced_toolbar_location: "top",
theme_advanced_toolbar_align: "left",
});
To show and hide the editor I doing something like this:
$('#parentDIV').hide();
$('#parentDIV').show();
Can anyone help please?
I am not totally sure why this happens. One option is if an editor gets moved around the dom. For you it might be a better way to shut down your editors explicitly then to just hide them.
To shut down an edtor instance use:
tinymce.execCommand('mceRemoveControl',true,'editor_id');
To reinitialize use
tinymce.execCommand('mceAddControl',true,'editor_id');

Preserving SCRIPT tags (and more) in CKEditor

Is it possible to create a block of code within the CKEditor that will not be touched by the editor itself, and will be maintained in its intended-state until explicitly changed by the user? I've been attempting to input javascript variables (bound in script tags) and a flash movie following, but CKEditor continues to rewrite my pasted code/markup, and in doing so breaking my code.
I'm working with the following setup:
<script type="text/javascript">
var editor = CKEDITOR.replace("content", {
height : "500px",
width : "680px",
resize_maxWidth : "680px",
resize_minWidth : "680px",
toolbar :
[
['Source','-','Save','Preview'],
['Cut','Copy','Paste','PasteText','PasteFromWord','-','Print', 'SpellChecker', 'Scayt'],
['Undo','Redo','-','Find','Replace','-','SelectAll','RemoveFormat'],
['Bold','Italic','Underline','Strike','-','Subscript','Superscript'],
['NumberedList','BulletedList','-','Outdent','Indent','Blockquote'],
['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'],
['Link','Unlink','Anchor'],
['Image','Table','HorizontalRule','SpecialChar']
]
});
CKFinder.SetupCKEditor( editor, "<?php print url::base(); ?>assets/ckfinder" );
</script>
I suppose the most ideal solution would be to preserve the contents of any tag that contains class="preserve" enabling much more than the limited exclusives.
Update: I'm thinking the solution to this problem is in CKEDITOR.config.protectedSource(), but my regular-expression experience is proving to be too juvenile to handle this issue. How would I go about exempting all tags that contain the 'preserved' class from being touched by CKEditor?
In CKEDITOR folder you have a config.js file. Open it and paste the code:
CKEDITOR.editorConfig = function( config ) {
config.allowedContent = {
script: true,
$1: {
// This will set the default set of elements
elements: CKEDITOR.dtd,
attributes: true,
styles: true,
classes: true
}
};
};
It will allow <script>...</script> tags in Source mode.
Suggestion 1: Create separate plain textarea for the admin to enter the scripts / HTML code.
Suggestion 2: Introduce a bbcode, like [script][/script] or [html][/html] that the admins can use to put the scripts / HTML code and have your server-side translate them into <script></script> and HTML code. Make sure when showing a saved content into the CKEditor, you need to have your server-side translate them into the bbcode first (or CKEditor will strip them out). Or the less-hassle way is to store the submitted content in the database as it is entered and only do the translation when displaying the page.
Suggestion 3: Since you want to use class="preserve" to mark tags you don't want CKEditor to strip out, then add the following JavaScript lines when initializing the editor:
// protect <anytag class="preserve"></anytag>
CKEDITOR.config.protectedSource.push( /<([\S]+)[^>]*class="preserve"[^>]*>.*<\/\1>/g );
// protect <anytag class="preserve" /><
CKEDITOR.config.protectedSource.push( /<[^>]+class="preserve"[^>\/]*\/>/g );
The issue is not with the CKEditor. Instead, the issue was with the MVC-Engine running the Site itself. Kohana has a global_xss_filtering within its configuration that is enabled by default. This prevents the submission of script tags, to prevent scripting-attacks on your site. Changing this value to false will permit the submission of <script> tags in forms, but it also opens up the site to potential security issues that can be very serious. It is advisable that you not disable global_xss_filtering.
/* /(system|application)/config/config.php - line 66 */
/**
* Enable or disable global XSS filtering of GET, POST, and SERVER data. This
* option also accepts a string to specify a specific XSS filtering tool.
*/
$config['global_xss_filtering'] = FALSE;

Categories