First dynamically-added TinyMCE editor displays, others do not - javascript

I'm building a javascript app that will be displaying a live-updated discussion thread. It will regularly poll the server for new data, and write it to the page. For posting comments and replies, we are trying to use the TinyMCE WYSIWYG editor, which converts a textarea into a nice HTML editor. This is my first experience with this editor. The app relies heavily on jQuery, so we are using TinyMCE's jQuery plugin to make it easier to work with.
Here's the issue... Every time our code generates a new textarea, we attach an editor to it. The first one shows up and works perfectly. When we add more, the TinyMCE code will hidfe the textarea, but won't generate the editor, and I don't know why.
I've gone ahead and built out a simple working example on jsFiddle:
http://jsfiddle.net/HUHKT/
function addTextArea(){
// find where the textareas will be placed
var container = $('#textareaContainer');
container.append( newTextArea() );
container.append( $(document.createElement('hr')) );
}
// define some configuration settings for the editor
var editorConfig = {
// Location of TinyMCE script
script_url: 'http://tinymce.cachefly.net/4.0/tinymce.min.js',
// setup parameters
menubar: false,
statusbar: false,
toolbar: 'bold italic underline | bullist numlist | undo redo | removeformat'
}
function newTextArea(){
var textarea = $(document.createElement('textarea'))
.attr('id',(new Date()).getTime()) // give it a unique timestamp ID
.val( 'This text area added # ' + new Date() )
.tinymce(editorConfig); // apply the WYSIWYG editor
return textarea;
}
Any help would be appreciated. Thank you.

You should add class for the new text area, then apply tinymce on that class every 5 sec
Here is an update to your jsfiddle that works
function timerElapsed(){
// limit this example so we don't fill up the page with too many textareas
if( $('#textareaContainer').find('textarea').length < 4 ){
addTextArea();
}
// define some configuration settings for the editor
var editorConfig = {
// Location of TinyMCE script
script_url: 'http://tinymce.cachefly.net/4.0/tinymce.min.js',
// setup parameters
menubar: false,
statusbar: false,
toolbar: 'bold italic underline | bullist numlist | undo redo | removeformat'
}
$('.tinymce-txt').tinymce(editorConfig);
}
function addTextArea(){
// find where the textareas will be placed
var container = $('#textareaContainer');
container.append( newTextArea() );
container.append( $(document.createElement('hr')) );
}
function newTextArea(){
var textarea = $(document.createElement('textarea'))
.attr('id',(new Date()).getTime()) // give it a unique timestamp ID
.val( 'This text area added # ' + new Date() )
.attr('class', 'tinymce-txt');// apply the WYSIWYG editor
return textarea;
}
$('#btnAdd').click( function(){ addTextArea(); } );
// set up the regular "polling" code
setInterval(function () {
timerElapsed();
}, 5000);
// NOTE: I also tried a repeating setTimeout function and had the same problem
http://jsfiddle.net/HUHKT/5/

`$('.tinymce-txt').tinymce(editorConfig);`
did not work with me, I replaced it with
tinymce.EditorManager.execCommand('mceAddEditor', false, uniqeId);

Related

TinyMCE Setting Content Issue

I'm trying to set the content of the TinyMCE editor but I'm not having much luck. I've tried both setting the HTML beforehand and initializing the editor, and setting the content after the editor is initialized but to no avail - I'm able to reproduce that one in this fiddle (I can't reproduce setting the content first because it uses variable HTML from the database to set it).
Pretty much what I'm trying to do is this with my own code:
Editor.innerHTML += '<label>Description</label><br><div id="AC-Description">' + data.Data.Description + '</div><br><br>'; // Editor is just a div & data is a json object return from an ajax call
tinymce.init({
selector: '#AC-Description'
});
tinymce.activeEditor.setContent(data.Data.Description); // does not work, same as in example fiddle.
tinymce.get('AC-Description').setContent(data.Data.Description); // does not work either, same as in example fiddle
Before the editor is initialized, the data.Data.Description does show text in the DIV and then TinyMCE ignores it when it initializes.
I'm just at a lost, especially since it isn't working on JSFiddle too. Anyone else have issues with this before and/or am I just missing something?
Try to set the content when the editor has been initialized by listening to the init event like:
tinymce.init({
selector: '#Editor'
});
tinymce.get('Editor').on('init', function(e){
e.target.setContent('test');
});
Without seeing running code I can't say for sure but the issue here is almost certainly a timing issue of when your JavaScript run.
The TinyMCE init() function is asynchronous. When you call init() it takes some time for the process to complete. In your code example you are immediately trying to call either activeEditor or get() but there is likely no initialized editor so both of these attempts are failing.
The correct way to make sure that TinyMCE is fully initialized is to rely on the init event. This event is fired after TinyMCE is fully initialized and ready for interaction.
To load content via the init() you can do something like this:
tinymce.init({
selector: "textarea",
plugins: ["advlist autolink lists ..."],
toolbar: "undo redo | bullist numlist ...",
setup: function (editor) {
editor.on('init', function (e) {
//this gets executed AFTER TinyMCE is fully initialized
editor.setContent('<p>This is content set via the init function</p>');
});
}
});
This worked for me:
import tinymce from 'tinymce';
tinymce.init({
selector: 'textarea', // change this value according to your HTML
toolbar: ' bold italic underline bullist',
menubar: '',
width : "926",
placeholder: $('.annotation-session').data('placeholder'),
plugins: 'lists',
lists_indent_on_tab: false,
setup: function (editor) {
editor.on('init', function (e) {
editor.setContent(window.userNotes.note);
});
}
});
//If you want you can set on startup line 12 - 14
//And also on another funcion doing this:
//Empty
tinymce.activeEditor.setContent('');
if (yourVariable !== '') {
tinymce.activeEditor.setContent(yourVariable)
}
<input type="text" class="annotation-session">

Handle Ctrl+Z (undo/redo) for text editor in single page application

I have single page application which consists of a text editor (kendo Editor). The data in the text editor are replaced somewhat like this
$("#editor").kendoEditor({
resizable: {
content: false,
toolbar: true
}
});
var editor = $("#editor").data("kendoEditor");
var setValue = function () {
editor.value($("#value").val());
};
see demo here.
The Issue:
So I am changing record of A then save it. Then I switch to B. Now if I do Ctrl+Z the text editor shows the record of A. How can I prevent this behavior.
Is a way to remove the undo history on demand, or something which would prevent the text editor replacing text with previous record?
Updated: Better Solution.
I contacted Kendo devs and they provided a neat solution.
var editor = $("#editor").data("kendoEditor");
editor.undoRedoStack.clear();
Note: this function is not documented in the public api and is
may change in newer version. This is working as of version
2016.3.1118
demo
Old Solution.
I ended up destroying and rebinding the widget to the textarea.
http://dojo.telerik.com/OjIZe
$("#destroy").click(function(){
var copy=$("#editor").clone();
$("#editor").data('kendoEditor').wrapper.find("iframe").remove();
$("#editor").data('kendoEditor').destroy();
$("#test").empty();
$("#test").append(copy);
$("#editor").kendoEditor({ resizable: {
content: false, toolbar: true
}
});
});

Changing the default font family in TinyMCE

I've successfully changed the default font inside the editor using the documentation here but that leaves me with a problem. The original default font no longer works in the font drop down list.
Original default: Verdana
New default: MyCustomFont
When I type into the editor I see my MyCustomFont font by default. If I try to change that to Verdana (original default) nothing happens. I can change it to any font family except Verdana. I noticed also that when I select MyCustomFont in the drop down list the content gets surrounded with a span with inline styles. This does not happen with the original default font (hence why nothing happens).
It seems to me like there's a key piece of documentation missing - how to tell the editor (the font feature in particular) that the font I've defined by default in the css is the default font.
I've Googled quite a bit but had no results. Everybody else seems to be settling for the documentation mentioned above. Am I the only one having this problem? If not, please help! :)
Please note, the answers to this question do not answer my question.
maybe too late but...
$('.tinymce').tinymce({
setup : function(ed) {
ed.onInit.add(function(ed) {
ed.execCommand("fontName", false, "Arial");
ed.execCommand("fontSize", false, "2");
});
}
});
EDIT
For TinyMCE 4, as #jason-tolliver and #georg states, the syntax is:
ed.on('init', function (ed) {
ed.target.editorCommands.execCommand("fontName", false, "Arial");
});
// Init TinyMCE
$('#content').tinymce({
setup : function(ed)
{
ed.on('init', function()
{
this.getDoc().body.style.fontSize = '12px';
this.getDoc().body.style.fontFamily = 'serif';
});
}
});
For those who init timymce with tinymce.init({ and cannot implement Radius Kuntoro answer directly.
My init looks like
tinymce.init({
selector: '#editor',
menubar: false,
plugins: ['bbcode'],
toolbar: 'undo redo | bold italic underline',
setup : function(ed)
{
ed.on('init', function()
{
this.getDoc().body.style.fontSize = '12';
this.getDoc().body.style.fontFamily = 'Arial';
});
},
});
For TinyMCE 4.6.3 this seems to be the way to go:
tinymce.init({
setup: function (ed) {
ed.on('init', function (e) {
ed.execCommand("fontName", false, "Verdana");
});
}
});
As refer to TinyMce website you can embed style sheet within your init function like this :
tinymce.init({
content_css : 'path/to/style/sheet',
body_class: 'define-class-name-without-dot-at-the-first'
});
It works and you do not need to setup anything.
check it out on tinyMCE webpage
Some of you will be working within the confines of the TinyMCE EditorManager, which offers two events: AddEditor and RemoveEditor. When a new instance of TinyMCE is being spawned and AddEditor is fired, the editor isn't actually initialized and so calling getDoc() will return null.
What you need to do is create an init listener within.
tinyMCE.EditorManager.on('AddEditor', function (event) {
... other code ...
event.editor.on('init', function() {
this.activeEditor.getDoc().body.style.fontSize = '12px';
this.activeEditor.getDoc().body.style.fontFamily = 'Times New Roman';
});
... other code ...
}
});
This is at least true as of version 4.3.8
I had difficulties with all solutions here in tinymce 4.x
I couldn't change neither fontsize nor fontname. After trying out a lot I found the solution.
First of all I can confirm Jareds answer, thank you for it! Those two commands will not work by default settings:
tinymce.EditorManager.execCommand("fontName", false, "12px");
tinymce.EditorManager.execCommand("fonSize", false, "Arial");
The default fontsize size is "pt", not "px." So either define displayed fontSize as "px" by [fontsize_formats][1] or just handover the desired size with "pt". With tinymce.EditorManager.execCommand tinymce is also not happy. You have to handover the whole font-family like 'arial, helvetica, sans-serif'. These commands worked on my site:
tinymce.EditorManager.execCommand("fontName", false, "12pt");
tinymce.EditorManager.execCommand("fonSize", false, "arial, helvetica, sans-serif");
None of the above solutions worked for me. So, somehow I managed to fix it using custom logic.
editor.on('change', function (e) {
let node = e.target.selection.getNode();
if (node.nodeName === 'P' || node.parentNode.nodeName === 'BODY') {
editor.dom.setStyle(node, 'font-size', "16px");
}
tinymce.triggerSave(); // to keep your textarea synced with above changes
});
This worked for me:
Look for functions.php in root of your themes directory inside /wp-content/themes/yourtheme/, open it up and add one line after php tag.
add_editor_style('custom-editor-style.css');
In the same directory, create a file called custom-editor-style.css with the following lines in it:
#import url(https://fonts.googleapis.com/css?family=Open+Sans:400,700);
* { font-family: 'Open Sans', sans-serif, Arial, Helvetica;}
Go ahead, clear your browser's cache and this is what you’ll see.
Refer link: https://blog.phi9.com/wordpress-editor-and-its-font/
I tried doing this way.
I use TinyMce 5 and inside the editor there is a body tag generated.
While initialising the editor I set the forced_root_block:'div', which means everytime something is being typed my root element will always be a div.
let tinyMceBody = tinymce.activeEditor.getBody();
let divs = $(tinyMceBody).children('div');
for(let i =0; i<divs.length; i++) {
divs[i].style.fontFamily = 'Nunito';
}
So I try catching all the root elements and set default styles to them.
When you edit something, tinymce surrounds whatever you have edited with a span block with a style attribute, so what ever you manually edit in the editor will be overrided. If you don't edit the text in editor then the default styling that we have attached on the parent element forced_root_block:'div' will be retained.
Try formulating a solution as per your custom req. using the above mentioned technique. Seems like the library doesn't have a prominent internal support for this. z
P.S:-
tinymce.activeEditor.dom.setStyles(tinymce.activeEditor.dom.select('div'), {'font-family' : 'Nunito'});
applies to all divs , but I wanted to apply only for the first level children of the body tag and not all divs( includes children of children). Otherwise this could be a solution too.
For tinymce 5 you can add fullpage plugin to plugins array then new key called
fullpage_default_font_family but i don't know if it works the same way for old versions or not.
This is the Answer. It work for me:
STEP # 1:
Look for functions.php in root of your themes directory inside /wp-content/themes/yourtheme/, open it up and add one line after php tag.
add_editor_style('custom-editor-style.css');
STEP # 2:
In the same directory, create a file called custom-editor-style.css with below lines in it
#import url(https://fonts.googleapis.com/css?family=Open+Sans:400,700);
* { font-family: 'Open Sans', sans-serif, Arial, Helvetica;}
Go ahead, clear your browsers cache and this is what you’ll see.
Tony Ngo

Reset tinyMce content

I'm trying to reset tinymce content.
On the beginning there is some 'A content'. User changed it to some 'B content', but he don't want to save it, so he can click 'cancel' button and whole content is back to 'A' version.
A content is text saved earlier, so it's not constant. How to reset tinyMce text to original one?
Html:
<div id="someDiv">Content A</div>
Would be nice to see something like this. If content was modified, cancel button will reset content to original:
if($('#someDiv').tinymce().isDirty()) {:
$('#someDiv').tinymce().reset();
}
This can be easily done.
You need to add this (using the setup parameter) to your configuration:
tinyMCE.init({
...
setup : function(ed) {
ed.onInit.add(function(ed, evt) {
ed.init_content = ed.getContent();
});
}
});
on buttonclick you call the following to reset the editor content
var ed = tinymce.get('your_editor_id');
ed.setContent(ed.init_content);
EDIT - For tinymce 4.x the syntax for attaching editor events has changed and is now:
tinymce.init({
...
setup: function (ed) {
ed.on('init', function () {
...
});
}
});

TinyMCE with ajax tabs

I'm using tabs component of JQuery UI 1.8, and I'm loading content of tabs via ajax (html content). In one of this tabs I'm using tinyMCE component, and when I load this tab the first time, the tiny initializates correctly but if I navegate to other tab and I recall the tab again the tiny breaks down.
This occurs when the import of tiny_mce.js is outside the contents of tabs. When I move the import into tab call, the tiny didn't load because it seems to be not initialized.
The question is: how can initialize tiny in an ajax tab?
Thanks in advance.
When I was having similar problems with TinyMCE and switching between ajax loaded tabs I found this wonderful piece of code at Ready4State so I thought I would share as I hope it helps others.
This will remove all instances of TinyMCE on the page.
var i, t = tinyMCE.editors;
for (i in t){
if (t.hasOwnProperty(i)){
t[i].remove();
}
}
Then you can safely reinitialize TinyMCE.
Personally I carry out the above code before using a switch statement to handle each ui.index, and I have a function that performs the initialisation for TinyMCE. So I just call that function in each of the relevant case statements.
Hope this helps someone else.
It might be worth re-initialising tiny MCE every time you switch back to the tab with the editor in. You can use the "select" event on the tab object.
$( ".selector" ).tabs({
select: function(event, ui) {
// initialise Tiny MCE here
}
});
You may have to destroy any previous instances of / references to the editor before re-initialising.
You need to shut down your tinymce instances before you switch to another tab else the editor element with that id will be blocked.
Remove the control before you switch the tab using
// the_editor_id equals the id of the underliing textarea
tinyMCE.execCommand('mceRemoveControl', false, the_editor_id);
I found the solution to my problem. The initialization of tinymce must be in load event of jquery tabs, like this:
$("div#tabs").tabs ({collapsible: false
,selected: -1
,fx: {opacity: 'toggle'}
,load: function (event, ui) {
// Tab with tinyMCE
if (ui.index == 0) {
tinyMCE.init({mode: "none",
theme: "advanced",
theme_advanced_toolbar_location: "top",
theme_advanced_toolbar_align: "left"
});
tinyMCE.execCommand ('mceAddControl', false, 'text_area_id');
}
else {
tinyMCE.triggerSave();
tinyMCE.execCommand('mceFocus', false, 'text_area_id');
tinyMCE.execCommand('mceRemoveControl', false, 'text_area_id');
}
}
});
I hope this helps others. Besides, if the content of the textarea is load via ajax, the command:
tinyMCE.triggerSave();
is not necesary.
Well, spent 3 hours on the same problem today... with Jquery UI 1.10 and TinyMCE 4.
The problem is, when unselected, the content of the ajax panel isnt removed from the DOM but just hidden. That means the textarea could be more than 1 time in the DOM (navigating the panels). => Death of tiny MCE...
There is no event in Jquery 1.10 to catch an "unselected panel". You have to deal with the before load event.
So the idea is to empty each "ajax loaded" panel before to load a panel. The code :
$( "#list_onglet_lecteur" ).tabs({
beforeLoad:
function( event, ui ) {
$("#list_onglet_lecteur div[role=tabpanel]").each(function(){
if($(this).attr("id") != "list_onglet_lecteur-accueil")$(this).empty();
});
$(ui.panel).html('<div style="width:100%;text-align:center"><img src="/images/ajax_loader_big.gif" alt=""></img><br />Chargement de l\'onglet</div>');
ui.jqXHR.error(function() {
ui.panel.html("Echec du chargement de l'onglet. Merci d'actualiser la page.");
});
}
})
Note i havn't find the way to make the difference between "ajax loaded panels" and "pre-loaded panels"...
That's a shame because you have to add each "pre-loaded panel" ids into the code...
Anyway, that resolve the tiny MCE problem. No need to init into the load event, and use the mceRemoveControl/mceAddControl commands.
Just init the tinyMCE edit in the "ajax loaded tab panel" view :
$(function() {
tinyMCE.init({
height : 300,
mode : "specific_textareas",
editor_selector : "mceEditor",
theme : "modern",
language : 'fr_FR',
plugins: [
"advlist autolink lists link image charmap print preview anchor",
"searchreplace visualblocks code fullscreen",
"insertdatetime media contextmenu paste moxiemanager"
],
toolbar: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image"
});
});

Categories

Resources