TinyMCE SetContent for multiple instances - javascript

I am trying to set the content of a number of text editors on page load. I am not too familiar with TinyMCE and have inherited the code somewhat. Here is how I am initializing the editors -
tinyMCE.init({
// General options
mode: "exact",
elements: "txtContent1,txtContent2,txtContent3,txtContent4,txtContent5,txtContentRight1,txtContentRight2,txtContentRight3,txtContentRight4,txtContentRight5",
theme: "advanced",
plugins: "layer,table,save,advhr,advimage,advlink,insertdatetime,preview,searchreplace,print,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras",
// Theme options
theme_advanced_buttons1: "bold,italic,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,format,selectcut,copy,paste,pastetext,pasteword,|,bullist,numlist,|,outdent,indent,blockquote,|,undo,redo,|,link,unlink,cleanup,help,code,",
theme_advanced_buttons2: "ComparativeFiguresTableButton",
//theme_advanced_buttons3: "ComparativeFiguresTableButton,tablecontrols,|,hr,|,sub,sup,|,print,|,ltr,rtl,|,fullscreen",
//theme_advanced_buttons4: "insertlayer,moveforward,movebackward,absolute,|,styleprops,|,cite,abbr,acronym,del,ins,attribs,|,visualchars,nonbreaking,template,pagebreak",
theme_advanced_toolbar_location: "top",
theme_advanced_toolbar_align: "left",
theme_advanced_statusbar_location: "bottom",
theme_advanced_resizing: true,
relative_urls: false,
document_base_url : "example.com",
remove_script_host: false,
setup: function(ed) {
// Add a custom button
ed.addButton('ComparativeFiguresTableButton', {
title: 'Comparative Figures Table',
image: 'images/icons/cumulativefiguresBtn.gif',
onclick: function() {
// Add you own code to execute something on click
ed.focus();
ed.selection.setContent('<p><strong>Comparative Figures</strong></p><table border="0" width="100%" cellspacing="0" cellpadding="0" style="font-size:12px; line-height:1.5em; font-family:Verdana, Arial, Helvetica, sans-serif;"><tbody><tr><td> </td><td><strong>Offered</strong></td><td><strong>Sold</strong></td><td><strong>Aggregate (€)</strong></td><td><strong>Average (€)</strong></td><td><strong>Median (€)</strong></td></tr><tr><td><strong>2009</strong></td><td>123</td><td>123</td><td>123,000</td><td>123,000</td><td>123,000</td></tr><tr><td><strong>2010</strong></td><td>123</td><td>123</td><td>123,000</td><td>123,000</td><td>123,000</td></tr></tbody></table><br clear="all" />');
}
});
}
Can anyone suggest the best way to set different html content for each editor on page load?
Thanks,
Tristan

From your config you have quite a few instances of TinyMCE on your page. In each, you have a button that allows the end user to insert some predefined content (a "Comparative Figures Table")
When you say you want to "set different html content for each editor on page load" I assume you mean you want to have each instance of TinyMCE load with the appropriate content (either some default or what you retrieved from your repository).
If that's the case then, as #russjman stated, each of the ID's in the elements config item refers to a TextArea/DIV on the page. All you need to do is put the appropriate content in those elements. Importantly, remember to HTML encode it.
For example
<textarea id="txtContent1">
<?php echo htmlentities("<p>This is the content from the first text area.</p>");?></textarea>
<textarea id="txtContent2">
<?php echo htmlentities("<p>This is the content from the second text area.</p><p><strong>Note</strong> This needed to be encoded using htmlentities in PHP</p>");?></textarea>
The other way to read your question is that you want the ComparativeFiguresTableButton to do something different in each instance of the editor. In this case you will need a different config for each element, each with a different value in the ed.selection.setContent() method
As #Thariama states, the best approach would be to create a simple plugin that adds a button and has a config parameter that is the content you want inserted when it's pressed.
Finally, if all you want to do is insert HTML fragments, then it may be worth checking out the template plugin.

I assume that you want set up TinyMCE for multiple textareas on the same page. The 'elements' variable should be doing what you are asking as long as they correspond to a textarea with an id.
<textarea id="txtContent1" ></textarea>
<textarea id="txtContent2" ></textarea>

Try creating your own plugin (it is pretty easy):
ed.onInit.add(function(ed){
ed.setContent('<p>my new content</p>');
}
Since every tinymce instance gets initialized using the same code - they all get the same content (right after the editor instance has loaded).
Alernative 1: I am not sure if the following init setting will work, but you might give it a try:
setup : function(ed) {
ed.setContent('<p>my new content</p>');
}
Alernative 2: Set the content of each textarea which gets transformated into a tinymce editor instance before tinymce.init gets called.

Related

TinyMCE update content_style

I'm using the Angular wrapper for TinyMCE 4, initializing the editor with some custom css like this:
editorInit: Settings = {
menubar: false,
statusbar: false,
toolbar: false,
content_style: '.highlight {background-color: #fff877;}'
};
I'd like to dynamically change this content_style later, for example like this:
editor.settings.content_style = ".highlight {background-color: none;}";
However, this change is not being applied. Do I need to re-initialize the edior somehow everytime I want to change the content css?
Since I don't want to re-initialize the whole editor I went ahead and updated the style tag manually. Of course you should make sure that you're updating the correct one, here's a simplified version:
editor.iframeElement.contentDocument.getElementsByTagName('style')[1].innerHTML = `
.highlight {
background: none;
}`;
Once the editor is loaded you cannot dynamically load different CSS - once TinyMCE processes the configuration it won't re-examine those variables.
You can certainly use remove() and init() to re-initialize TinyMCE.
With the Angular we provide you likely need to reload the component that includes TinyMCE to get the remove/init cycle to happen.

Configure TinyMCE 4 to allow inline element or anchor tag (a) to be the top level element

Basically, I want to place an anchor element as the top level element, but TinyMCE enforces it's own ideas every time the source code panel is closed.
Disclaimer: TinyMCE is an amazing free wysiwyg editor tool. I am just having a really bad day with it.
It pains me that TinyMCE, supposedly "the most advanced wysiwyg html editor", often can't even let you enter the html you want without screwing it all up for you the second you save or close the source code view.
All I want to do, is to be able to close the editor, leaving my code (or even just anchor elements) intact. But no matter what options or configuration I pass to TinyMCE, it repeatedly tears my code asunder; carelessly scattering elements about the document like shards of broken dreams.
<!-- Casually transforming this -->
<a class="box" href="#">
<div class="title">Box Title</div>
<p>This is the box content!</p>
</a>
<!-- into this -->
<p><a class="box" href="#"></a></p>
<div class="title"><a class="box" href="#">Box Title</a></div>
<p><a class="box" href="#">This is the box content!</a></p>
<p></p>
For some reason best known to themselves they have removed the life-saving cleanup option allowing you to disable this abomination entirely, and I cannot get any of the valid_elements/children options to work correctly. (a[*], etc)
I have spent the last 3 hours scouring their documentation, forums and stack overflow, but to no avail whatsoever. My only solace was finally being able to put block-level elements within anchor tags, but this only solves part of my problem.
The main issue I am facing is that TinyMCE will not allow me to place an anchor tag, containing block-level elements, at the top level. Anybody know how to configure TinyMCE to allow this?
TinyMCE Code (stripped down to relevant):
tinymce.init({
selector: 'textarea.wysiwyg',
schema: "html5",
element_format : 'html',
plugins: ['codemirror'],
convert_urls: false,
valid_elements: "*[*]",
valid_children: "+body[a],+a[div|h1|h2|h3|h4|h5|h6|p|#text]",
//apply_source_formatting: false, // removed I think
//verify_html: false, // removed :'(
codemirror: { indentOnInit: true },
content_css: '/Content/Styles/Sass/main.css'
});
The solution is to disable forced_root_block.
tinymce.init({
...
forced_root_block : false, // default = 'p' >= 3.0a1
});
This feature automatically ensures that any non block elements or text nodes are wrapped in block elements.
For example <strong>something</strong> will result in output like <p><strong>something</strong></p>.
Documentation Reference

CKEditor, custom object with children

I am trying to create a plugin for CKEditor that adds a custom object with children.
Example:
<div>
<img src="someimage.jpg" />
<p>
Some text
<span>Some subtext</span>
</p>
<img src="someStaticImage.jpg" />
</div>
In the onOk function i have:
---snip---
this.imgElement.setAttribute('src',path + data.imageSrc);
this.staticImgElement.setAttribute('src',path + 'images/staticimg.jpg');
this.imgElement.appendTo(this.element);
this.imgElement.appendTo(this.element);
this.staticImgElement.appendTo(this.element);
---snip---
I would like for this block to behave as a single element, meaning that pressing backspace deletes the whole block, double clicking on it opens the edit dialog...
Any idea how i could do that?
I came close with setting
this.element.setAttribute('contenteditable','false');
However this doesn't allow content to be inserted before "it", if "it" was the first element in the ckedit window.
EDIT:
More info:
I'm using CKEditor 4.0, inline version
I wish for my "object" to be like the "image" plugin, where when you double click on the image, a dialog opens, the same one as when you create the object (where you set the src, width...).
I managed to make it similar to it, but because it is a div with child elements, CKEditor treats each part as seperate, which makes the deleting of the object (with backspace) behave in a wierd way, only parts of it get deleted, backspace needs to be pressed multiple times to delete the entire object.
I'm a CKEditor core developer and I think that I've got an interesting news for you :). Coincidentally, right now we're working on Widgets feature which is exactly what you mean.
Making some fragments of the page non-editable by setting contenteditable=false make them unusable. Selecting, copying&pasting, right clicking, using arrow keys - all this is at least partially broken. And it's even worse if you try to add a nested editable element (editable inside non-editable), because e.g. it can be deleted from inside.
That's why we decided to implement a nice API for creating widgets and fix all these bugs under the hood. Maybe not all bugs and in all browsers at the beginning, because there's huge (really... I mean huuuuge :P) amount of them and of course no standard behaviour between browsers at all. But it will be a good start. First version of widgets that will be released in upcoming CKEditor 4.2 should be usable - this is our goal. Then we'll focus on stabilizing the implementation.
PS. CKEditor Roadmap says that CKE 4.2 will be ready in 11 days and this is not true, unfortunately. We're delayed, but I don't want to estimate now how much.
You indicated that you've created the plugin that handles the object, but that the problem you want to solve is the inability to insert content before the object when it's the first item.
It looks like this bug report is about this issue:
Can't move cursor behind non-editable element (or placeholder) in CKEditor
I used my plugin to insert this block of code into the editor:
<div contenteditable="false">
<img src="someimage.jpg" />
<p>
Some text
<span>Some subtext</span>
</p>
<img src="someStaticImage.jpg" />
</div>
You can also add the display: inline-block; style if you want (see discussion below):
From my tests, it seems like you can't put content before the object using the back arrow, but if you back arrow to that row of content and press the home key, you can type before the object. It also seems that if you click with your mouse in the upper left corner, you can add content before the object.
Both approaches push the object onto the next line because it's a <div>, you can change the style of the div to display: inline-block; if you want the object to stay on the first row. I tried just making the object <div> a <span> instead, but then it becomes possible to edit parts of the object.
You can't use backspace to delete the object, but you can click the object to select it and then delete it.
I checked the info discussed above with Firefox 20 and IE 9 on Win 7. Google Chrome has a bunch of problems:
When the block of HTML is inserted with the plugin, the contenteditable="false" attribute is stripped out.
So I tried to see how it worked if I just pasted that block of code into CkEditor while in source mode. The contenteditable="false" attribute wasn't stripped out, but the whole content area became uneditable.
My tests were using CkEditor 3.6.1, so this may not be a problem in CkEditor 4.X.
This bug report seems to be about the problem I encountered with being unable to do anything in the content area using Chrome, the report indicates version 3.X:
ContentEditable, Image and Chrome
Additional Info
Here's a plugin from CKSource that might be helpful:
Magic Line
The description:
With this plugin you can create new paragraphs into spaces where normally would be impossible to reach. For example, above a table at the beginning of the document.
Here's my plugin that inserts content into the editor, it doesn't solve the problem you have, but you might use it to add functionality to your plugin. I'll write the full instructions in case someone who hasn't created a plugin finds this and wants to give it a try.
Here's the code that goes in the ckeditor/plugins/cwmarinsertsnippet/plugin.js file:
/**
* Plugin to insert the contents of an element into the editor content area.
*/
// Register the plugin with the editor. cwmarinsertsnippet
// http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.plugins.html
CKEDITOR.plugins.add( 'cwmarinsertsnippet',
{
// The plugin initialization logic goes inside this method.
// http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.pluginDefinition.html#init
init: function( editor )
{
// Define an editor command that grabs the content of an element and inserts it into the content area.
// http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.editor.html#addCommand
editor.addCommand( 'cwMarInsertSnippet',
{
// Define a function that will be fired when the command is executed.
// http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.commandDefinition.html#exec
exec : function( editor )
{
// Create an element based on a native DOM element.
var codesnippet = new CKEDITOR.dom.element( document.getElementById( 'resmar' ) );
//alert( codesnippet.getHtml() );
// Insert the element content into the document.
// http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.editor.html#insertHtml
editor.insertHtml( codesnippet.getHtml() );
}
});
// Create a toolbar button that executes the plugin command.
// http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.ui.html#addButton
editor.ui.addButton( 'CwMarInsertSnippet',
{
// Toolbar button tooltip.
label: 'Insert Search Box',
// Reference to the plugin command name.
command: 'cwMarInsertSnippet',
// Button's icon file path.
icon: this.path + 'images/buttonicon.gif'
});
}
});
It needs to be added to the config file with:
config.extraPlugins = 'cwmarinsertsnippet';
and to make the button visible, the button name "CwMarInsertSnippet" needs to be added to the config toolbar entry:
CKEDITOR.config.toolbar_XXXX
[
Snip...
{ name: 'tools', items : [ 'About','CwMarInsertSnippet' ] },
... End Snip
];
The button for the plugin should be 13px X 13px (for CkEditor 3.X, not sure about version 4.X). It gets placed here:
ckeditor/plugins/cwmarinsertsnippet/images
The name should match the one used in the editor.ui.addButton function at the end of the plugin code (this path can really be anywhere you want).
Here's an example of the code to be added to the page where CkEditor is being used:
<div id ="resmar">
<div contenteditable="false">
<img src="someimage.jpg" />
<p>
Some text
<span>Some subtext</span>
</p>
<img src="someStaticImage.jpg" />
</div>
</div>
You can also add the display: inline-block; style if you want:
<div style="display:inline-block" contenteditable="false">
The container element can be hidden with styling if it shouldn't appear on the page.
Basically, just put the content you want to insert inside the element with the target ID
<div id ="resmar">
Content to be inserted.
</div>
Of course the plugin name and the element ID can be anything you like.

Codemirror doesn't work with different Id's

I'd like to use CodeMirror for two pages on my website. The first is a Code snippet uploading page, the second is a page to view code snippets. On the second page I'd like to make CodeMirror ReadOnly, obviously to not allow users to change its content.
So, the first page (the upload page) works flawlessly, it displays the plugin like it should, and works like it should.
Here's an image of it:
Here's its javascript: (it's an external script file)
var UploadPageCodeMirror = CodeMirror.fromTextArea(document.getElementById('CodeSnippetBody'), { mode: "javascript", theme: "default", lineNumbers: true });
HTML:
<textarea rows="15" cols="70" name="CodeSnippetBody" id="CodeSnippetBody" #Validation.For("CodeSnippetBody")></textarea>
The problem only persist on the second page, where the user can view uploaded snippets. For some reason it won't work with a different textarea ID, though I referenced it right. If I change the ID of this textarea to the one on the upload page (CodeSnippetBody) for some reason it works, but I can't change attributes of it.
Here is the js: (the same external script file)
var ReadOnlyCodeMirror = CodeMirror.fromTextArea(document.getElementById('CodeSnippetBodyReadOnly'), { mode: "javascript", theme: "default", lineNumbers: true });
And here's the HTML:
<textarea id="CodeSnippetBodyReadOnly">#code["CodeSnippetBody"]</textarea>
It displays like this:
As you can see the plugin won't initalize
If I change the ID of this textarea to CodeSnippetBody, so it matches the upload page's id it works:
<textarea id="CodeSnippetBody">#code["CodeSnippetBody"]</textarea>
Displays like this:
The problem with this, as I stated before, is that I can't change its attribute to ReadOnly.
What am I doing wrong?
I hope I gave you enough info, if you need more, please ask, I will provide. Thank you!

TinyMCE Stripping Out All Markup

I'm trying to insert a simple image link in a TinyMCE-wrapped text field, but it's stripping out all of my markup. My markup looks like:
<a class="video-launcher lightbox-video-launcher" href="http://www.youtube.com/watch?v=blah" ><span class="video-launcher-bg"></span><span class="video-launcher-button"></span></a>
My tinymce_config_url_init.html looks like:
{
"theme_advanced_toolbar_align":"left",
"content_css":"/media/css/cms_tinymce.css,/media/css/cms_tinymce_admin.css",
"theme_advanced_blockformats":"p,h2,h3,div,customformat",
"theme_advanced_statusbar_location":"bottom",
"theme_advanced_path":false,
"plugins":"fullscreen,paste",
"valid_elements":"*[*]",
"media_strict":false,
"paste_auto_cleanup_on_paste":true,
"theme_advanced_styles":"Header 1=header1;Header 2=header2;Header 3=header3;Table Row=tableRow1",
"width":"680",
"theme":"advanced",
"theme_advanced_font_sizes":"8px,10px,12px,14px,16px,18px,20px,24px,36px",
"theme_advanced_resizing":true,
"height":"300",
"relative_urls":false,
"theme_advanced_toolbar_location":"top",
"inline_styles":true,
"language":"en",
"theme_advanced_buttons1":"fullscreen,|,undo,redo,|,bullist,numlist,|,anchor,link,unlink,charmap,|,code,|,justifyleft,justifycenter,justifyright,|,image,",
"theme_advanced_buttons3":"",
"theme_advanced_buttons2":"removeformat,styleselect,formatselect,fontselect,fontsizeselect,|,bold,italic,underline,|,forecolor,backcolor",
"removeformat_selector":"span,div,p,h1,h2,h3"
}
I know the problem is with TinyMCE, because without submitting the form, and just clicking the "html" button again, TinyMCE's popup shows no content.
I'm assuming TinyMCE is striping out anything it thinks looks insecurity or invalid. For my app, it's being used in an admin section, so the content can be trusted. How do I disable the TinyMCE config causing this markup from being stripped out?
Add your website's css stylesheet to the "content_css" variable, perhaps?
And also set "paste_auto_cleanup_on_paste" to false, not true.
You should have a closer look at the tinymce configuration paramters valid_elements. You need to set them accoring to your needs and define valid elements and attributes.

Categories

Resources