I'm working on a TinyMCE plugin and one thing I want it to do is register commands/buttons that toggle custom formatting.
For example if you click the bold button in TinyMCE it will show the bold button highlighted while in bold text. Digging into the source code I see this happens via: tinymce.EditorCommands.addCommands thought I can't seem to figure out how to duplicate it. The documentation of TinyMCE is just horrible as well =(
So given customFormat I want to be able to have a button setup by my plugin that when the customFormat is applied it shows as such like the Bold, Italics, and other such buttons do on the toolbar. And clicking on my customFormat toggles that format on/off. I can easily accomplish the toogle via "addCommand" and "addButton" but then it does not have state tracking like Bold and others do.
Showing my current non-working attempt (this code is inside init of my plugin create method):
tinymce.EditorCommands.call('addCommands', {
'MyFormat' : function(name) {
ed.formatter.toggle("customFormat");
}
},'exec');
tinymce.EditorCommands.call('addCommands', {
'MyFormat' : function(name) {
return ed.formatter.match('customFormat');
}
},'state');
ed.addButton('customformat', {cmd : 'MyFormat'});
And here is the link to the "documentation" of addCommands: http://www.tinymce.com/wiki.php/API3:method.tinymce.EditorCommands.addCommands
After a lot more looking around I found this which seems to be perfect: http://www.tinymce.com/wiki.php/API3:method.tinymce.Editor.addQueryStateHandler
But when I implement the code it doesn't change the state of the button:
ed.addCommand('MyFormat', function(ui, v) {
ed.formatter.toggle("thoughtFormat");
});
ed.addQueryStateHandler('MyFormat', function() {
return ed.formatter.match('thoughtFormat');
});
ed.addButton('myformat', {cmd : 'MyFormat'});
In case someone doesn't want to do it the 'plug-in' way, here's the guide for TinyMCE 4.x
.
First of all, you need to define a custom format:
formats: {
custom_format: {inline: 'span', styles: {color: "red"}, attributes: {class: 'some_css_class'}}
}
Then you'll have to add a button to your toolbar:
toolbar: "mybutton",
Next, you need to setup your button, so that it toggles the format:
setup: function(editor) {
editor.addButton('mybutton', {
text: 'My button',
icon: false,
onclick: function() {
tinymce.activeEditor.formatter.toggle('custom_format')
}
});
}
Furthermore, if you want the editor to set the state of the button to indicate the format of current node, automatically, add this to setup
function:
onPostRender: function() {
var ctrl = this;
editor.on('NodeChange', function(e) {
ctrl.active(e.element.className == "some_css_class")
});
}
Your tinymce.init
function should look like this:
tinymce.init({
selector: "textarea",
formats: {
// Other formats...
custom_format: {inline: 'span', styles: {color: "red"}, attributes: {class: 'some_css_class'}}
}
// Other default toolbars
toolbar_n: "mybutton",
// Finally, setup your button
setup: function(editor) {
editor.addButton('mybutton', {
text: 'My Button',
icon: false,
onclick: function() {
tinymce.activeEditor.formatter.toggle('custom_format')
},
onPostRender: function() {
var ctrl = this;
editor.on('NodeChange', function(e) {
ctrl.active(e.element.className == "some_css_class")
});
}
});
}
Note that class
attribute I added to my custom format. This approach made it possible for me define my custom styles in a separate stylesheet file and keep my markup as dry as possible (No inline styling!). Point content_css
option to your stylesheet and you'll be good to go.
However, due to fact that I'm using Rails as back-end and BatmanJS as front-end (and I'm fairly new to the latter), I couldn't figure out how assets routing works, and ended up adding my custom styles to default content stylesheet file of tinyMCE skin itself (located at skins/SKIN_NAME/content.min.css
).
Thanks to Thariama for insights that allowed me to dig deeper finally figuring out how to do this. I'm not sure its the "right way" but as I said TinyMCE has the worst documentation imaginable.
The key for me was to make an hook the onNodeChange event, using the setActive trick. Full example plugin with a custom button that activates when that format is present wherever the cursor is:
(function() {
tinymce.create('tinymce.plugins.CoolPlugin', {
init : function(ed, url) {
ed.addCommand('MyFormat', function(ui, v) {
ed.formatter.toggle("myFormat");
});
ed.addButton("coolformat", {
title : 'MyFormat Tooltip',
cmd : 'MyFormat',
image: url + '/coolformat.png',
});
ed.onNodeChange.add(function(ed, cm, n) {
active = ed.formatter.match('myFormat');
control = ed.controlManager.get('coolformat').setActive(active);
});
ed.onInit.add(function(ed, e) {
ed.formatter.register('myFormat',
{inline: 'span', classes : ['cool'] } );
});
}
});
// Register plugin
tinymce.PluginManager.add('cool', tinymce.plugins.CoolPlugin);
})();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With