Hook into onExecCommand event with TinyMCE 4 - tinymce

I am using TinyMCE 4 but the documentation is terrible. I am trying to provide a live preview of the content in another div (outside of the editor). Right now I am listening to these events:
$(document).on('tinymce:changed tinymce:init', ...)
This is working when text is entered, but it does not trigger when commands are executed (changing existing text to bold for example).
It looks like in TinyMCE 3.x there is an onExecCommand event that does what I want. But I can't find any documentation on how to listen to the global jQuery event like I am doing with with change and init. Does anyone know what event it is firing?

In the migration guide you can find the following example:
// Old event
editor.onInit(editor, args) {
// Custom logic
});
// New event
editor.on('init', function(args) {
// Custom logic
});
So the one problem is to get right event name and the right editor instance :)
The onExecCommand() event becomes 'ExecCommand' in v4.
So adding a handler on command execution should be like this (be sure that editors are already initialized when executing code below):
for (ed_id in tinymce.editors) {
tinymce.editors[ed_id].on('ExecCommand', function(args) {
alert(1);
});
}
For some reason this event fires twice when command is executed. I think you will overcome this issue.
Though this method does not uses jQuery bindings, it works for me and possibly will solve your problem too.

In case this helps anyone else, here is a list of all the events tinymce 4 allows:
http://www.tinymce.com/wiki.php/api4:class.tinymce.Editor

Related

what is the event listener that can be used after dialog content loaded.?

Am trying to use $document.on("dialog-ready", function() { .. } for touch UI dialog customization. Where as i can see the dialog-ready event fires before the dialog content is fully loaded which gives me a unavailability of tags for traversal of dialog html.
Is there any event listener that i can use for triggering a call after my
dialog is fully loaded with all widgets and its values.?
Is there any documentation link where i can find these event
listeners apart from Adobe Experience Manager Help | Using Event
Handlers in Adobe Experience Manager Touch UI Components .?
Also what is the order of sequence AEM loads $document.on("dialog-ready", function() { .. } when compares with $(document).on("foundation-contentloaded", function (e) { .. }.
?
Dialog ready is fired when a dialog is opened. Not necessarily after all values are populated.
Foundation contentloaded is fired when new fields are injected into the dialog. More specifically, according to the documentation, "it should be triggered when a container is injected".
So using foundation-contentloaded is ideal when working with multifields where new fields get added much later. Also, dialog-ready will not be fired in page creation wizard. We have to use foundation-contentloaded here.
Neither of the two will guarantee that all content will be populated for us to start using their values in JavaScript. Especially when we have RTE/multifields in our dialog.
To answer your question,
There are no event listeners that you can use that indicates the dialog is fully loaded.
I noticed foundation-contentloaded fires before dialog-ready
Coral.commons.ready ensures initialization. Especially helpful when working with multifields and RTEs.
Coral.commons.ready(this, () => {
/*
logic to run once coral element 'this' is pointing to is initialized (initialize or _render methods are invoked)
*/
});
More information on foundation-contentloaded and Coral.commons.ready
You can use:
$(document).on("foundation-contentloaded", function(e) {
var container = e.target;
});
Check this link.
Here are more examples:
https://helpx.adobe.com/experience-manager/using/creating-touchui-events.html

Can't instantiate multiple tinymce editors in different EPiServer gadgets

I'm developing two gadgets in an EPiServer CMS 9.2 site using the old (MVC Controller) style gadgets. Both gadgets need a rich text editor. I've wired in TinyMCE and it work's fine the first time one of the gadgets instantiates the editor but then fails silently after that.
The code to instantiate the element is triggered using the GadgetAttribute.ClientScriptInitMethod and my init function looks like:
MyGadget.init = function (e, gadget) {
$(gadget.element).find('textarea.tinymce').tinymce({
theme: "modern"
});
};
On subsequent invocations even in the same gadget, the call to tinymce() completes without error but the editor is not present in the DOM (as the element before the related <textarea> and the underlying <textarea> is not visible.
What could be causing this? How might I fix it?
You probably need to call the init function for tinymce and pass a selector.
Something along these lines perhaps? (untested)
tinymce.init({
selector: '#gadgetElementId textarea.tinymce',
});
More info here

mousedown event on options in select with jquery .on

I was reading the documentation of the .on event handler of jQuery and I started playing around with it.
I have a simple <select> element with the multiple attribute set to true.
However, I want the user to be able to select multiple items without having to press the ctrl or shift key(s)
According to the .on documentation, if you specify a selector it will automatically add those event handlers to any new items added inside that container that match the selector specified.
So in my case, I could for example decide to replace the <option> elements available in the listbox, but I still want to have the same functionality for those options without having to rebind those events etc.
One might think that the following snippet should do the trick (atleast, I did):
$('#dropdownlist').on('mousedown', 'option', function(e){
e.preventDefault();
$(this).prop('selected', $(this).prop('selected') ? false : true);
return false;
});
So when a users clicks on an option in that listbox, the default action will be cancelled and depending wether the item is already selected or not, it will invert that selection.
I have created a small fiddle demonstrating this behaviour: fiddle
In that fiddle, the first dropdownlist is behaving as expected, but the functionality is lost when replacing the items. This only works in FF & Chrome.
The second dropdownlist is how I thought it should've been (event handling wise), but that doesn't seem to work besides in Chrome -.-
The functionality is kept when replacing items, because the console will still log '2' when clicking on an item after replacing them.
Can someone explain me why this is happening? Am I doing something wrong?
Please point me in the right direction!
Thanks!
~ Dirk
IE doesn't respect the mousedown event on the option tag itself. You've got to use the OnChange event of the select tag, which is not what you (nor I) want. I was trying to do the exact same thing as you and was stopped at every attempt. I finally gave up and made it a list of checkboxes because I can get the same behavior out of mine that you are trying to do here.
You can see this question for some options, but I never did get it to work the way you are describing.

tinyMCE setup callback versus onAddEditor

When you initialize a tinyMCE editor I have noticed two different ways to get called when the editor is created.
One way is using the setup callback that is part of tinyMCE.init:
tinyMCE.init({
...
setup : function(ed) {
// do things with editor ed
}
});
The other way is to hook up to the onAddEditor event:
tinyMCE.onAddEditor.add(function(mgr,ed) {
// do things with editor ed
});
What are the differences between using these two methods?
Is the editor in a different state in one versus the other? For example, are things not yet loaded if I try to access properties on the editor object.
What are reasons to use one over the other?
The difference here is that tinyMCE.onAddEditor adds code to be executed onthe AddEditor event and fires when a new editor instance is added to the tinymce collection
while the setup setting lets you add events to the editor. It gets executed before the editor instances gets rendered.
One other difference is that setup is to be set inside the tinymce initialization call (the configuration setting) while onAddEditor usually gets called inside a tinymce plugin (but you may also set it inside the setup function).
onAddEditor.add gives warning in the latest TinyMCE 4:
Deprecated TinyMCE API call: <target>.onAddEditor.add(..)
.on(nameofevent, function(){...} ) is the proper way to do this in MCE4 if you don't have the backward-compatibility plugin.

google wave: how did they make divs clickable

As we are facing GWT performance issues in a mobile app I peeked into Google Wave code since it is developed with GWT.
I thought that all the buttons there are widgets but if you look into generated HTML with firebug you see no onclick attribute set on clickable divs. I wonder how they achieve it having an element that issues click or mousedown events and seemingly neither being a widget nor injected with onclick attribute.
Being able to create such components would surely take me one step further to optimizing performance.
Thanks.
ps: wasnt google going to open source client code too. Have not been able to find it.
You don't have to put an onclick attribute on the HTML to make it have an onclick handler. This is a very simple example:
<div id="mydiv">Regular old div</div>
Then in script:
document.getElementById('mydiv').onclick = function() {
alert('hello!');
}
They wouldn't set the onclick property directly, it would have been set in the GWT code or via another Javascript library.
The GWT documentation shows how to create handlers within a GWT Java app:
public void anonClickHandlerExample() {
Button b = new Button("Click Me");
b.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
// handle the click event
}
});
}
This will generate an HTML element and bind a click handler to it. However, in practice this has the same result as using document.getElementById('element').onclick() on an existing element in your page.
You can hook functions to the onclick event using JavaScript. Here's an example using jQuery:
$(document).ready(function(){
$("#div-id").click(function(){
/* Do something */
});
});
If you're interested in optimizing performance around this, you may need to investigate event delegation, depending on your situation.
A click event is generated for every DOM element within the Body. The event travels from the Body down to the element clicked (unless you are using Internet Explorer), hits the element clicked, and then bubbles back up. The event can be captured either through DOM element attributes, event handlers in the javascript, or attributes at any of the parent levels (the bubbling or capturing event triggers this).
I'd imagine they've just set it in a .js file.
Easily done with say jQuery with $(document).ready() for example.