How should I update a TinyMCE plugin using tiny_mce_popup.js for version 4? - tinymce

TinyMCE4 documentation is currently dismal. I have an insert image plugin compatible with Ruby on Rails but it relies on the deprecated tiny_mce_popup.js. There's no information for how I should update a plugin to circumvent use of that file.

TinyMCE 4 deprecates the old file_browser_callback in favor of the new file_picker_callback which has the advantage that it can return metadata.
tinymce.init({
selector: 'textarea.tinymce',
file_picker_callback: function (callback, value, meta) {
myFilePicker(callback, value, meta);
},
plugins: ['link image'],
toolbar: 'undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image'
});
function myFilePicker(callback, value, meta) {
tinymce.activeEditor.windowManager.open({
title: 'File Manager',
url: '/Site/FileManager?type=' + meta.filetype,
width: 650,
height: 550,
}, {
oninsert: function (url) {
callback(url);
}
});
}
In your file browser to return the file to the main page you call mySubmit('/images/file_123.jpg') when you click on a hyperlink or a image.
function mySubmit(url) {
top.tinymce.activeEditor.windowManager.getParams().oninsert(url);
top.tinymce.activeEditor.windowManager.close();
}

TinyMCE 3 was reliant on tiny_mce_popup.js for exchanging variables between the parent and dialogue. TinyMCE 4 does away with dialog.htm and with tiny_mce_popup.js
If you have a look at the image plugin, following editor.windowManager.open you can see the dialogue is created through JS alone. This eliminates the need for goofy access to parent variables through opener. If you can, stick with this template method.
I chose to stick with dialog.htm but I served it from rails so I wouldn't have deal with exchanging the form auth_token with JS. If you do this, remember that inserting your content should come from the plugin and not from your dialogue. This is my simple image uploader :
tinymce.PluginManager.add('railsupload', function(editor, url) {
var win, data, dom = editor.dom
// Add a button that opens a window
editor.addButton('railsupload', {
icon: 'image',
tooltip: 'Insert image',
onclick: showDialog
});
function showDialog() {
win = editor.windowManager.open({
title: 'Insert image',
name: 'railsupload',
url: '/attachments/tinymce?owner_type=' + editor.settings.owner_type + '&owner_id=' + editor.settings.owner_id,
width: 200,
height: 220,
bodyType: 'tabpanel',
buttons: [{
text: 'Insert',
onclick: submitForm
}]
});
}
function submitForm() {
editor.insertContent("<img src=\"" + self.frames[1].document.img_url + "\" />")
win.close()
}
});
You'll need a rails attachments controller and you'll need to pass your attachment init params through the url. If I build this out in a gem, it will be compatible with tinymce-rails and I'll update this answer.
Update: TinyMCE now has this page on migrating from 3.x: http://www.tinymce.com/wiki.php/Tutorial:Migration_guide_from_3.x

Related

TinyMCE: getParams() got removed from v6

I am migrating from v4 to v6. We are using top.tinymce.activeEditor.windowManager.getParams(). However, getParams() has been removed from new version. And I am not able to figure what to use in replacement.
In my example, oninsert() is the custom method in openUrl(). I am not sure if we can use the custom property/methods in v6. It was working fine in v4.
Below is the code snippet
tinymce.init({
selector: '.tinymce-large',
plugins: [
'advlist', 'autolink', 'link', 'image', 'lists', 'charmap', 'preview', 'anchor', 'pagebreak',
'searchreplace', 'wordcount', 'visualblocks', 'visualchars', 'code', 'insertdatetime',
'media', 'table', 'template'
],
toolbar: 'undo redo | styles | bold italic | alignleft aligncenter alignright alignjustify | ' +
'bullist numlist outdent indent | link image media| code preview ',
menubar: 'file edit insert view',
browser_spellcheck: true,
file_picker_types: 'image',
file_picker_callback: function (callback, value, meta) {
myImagePicker(callback, value, meta);
}
});
function myImagePicker(callback, value, meta) {
tinymce.activeEditor.windowManager.openUrl({
title: 'Image Browser',
url: '/FileManager/Picker?type=' + meta.filetype,
width: window.innerWidth - 200,
height: 600
},
oninsert: function (url, objVals) {
callback(url, objVals);
}
});
}
//myImagePicker() will open up our custom file manager. Through file manager, the user will select an image and through JS, I want to pass the url in oninsert event through below code
top.tinymce.activeEditor.windowManager.getParams().oninsert(url, objVals);
TinyMCE 5 and 6 no longer recommends using the window.top variable to access the original window TinyMCE API and as such getParams has been removed. Instead, it's built around the more modern postMessage API instead.
Now, for this specific case it sounds like a custom message might be what you need. So as it's done via messaging you should be able to do something like this instead:
// TinyMCE window
function myImagePicker(callback, value, meta) {
tinymce.activeEditor.windowManager.openUrl({
title: 'Image Browser',
url: '/FileManager/Picker?type=' + meta.filetype,
width: window.innerWidth - 200,
height: 600,
onMessage: function(api, details) {
if (details.mceAction === 'customInsertImage') {
var data = details.data;
api.close();
callback(data.url, data.objVals);
}
}
});
}
// Filemanager window
window.parent.postMessage({
mceAction: 'customInsertImage',
data: {
url: url,
objVals: objVals
}
}, '*');
There are somethings to remember though, the data must be serializable to be sent via postMessage. Also be sure to use something other than the * wildcard for the message target for security purposes as noted in the documentation.
Also in case you haven't seen it yet, the documentation for URL dialogs can be found here at https://www.tiny.cloud/docs/tinymce/6/urldialog/ and https://www.martyfriedel.com/blog/tinymce-5-url-dialog-component-and-window-messaging is also a good blog post describing how they work in TinyMCE 5.

TinyMCE and Piranha CMS not allowing me to set <style> tags as valid elements :(

I'm trying to add <style>// custom css here</style> into the tiny mce editor but currently it deletes the style tags and anything in between them on save.
I am trying to set valid_elements: "style" and/or custom_elements: "sabioStyle", and/or extended_valid_elements: "style". I've also tried: "[]" according to tiny's docs but it seems to have no effect on anything. I see that the init function:
piranha.editor.addInline = function (id, toolbarId) {
tinymce.init({
selector: "#" + id,
browser_spellcheck: true,
fixed_toolbar_container: "#" + toolbarId,
menubar: false,
branding: false,
statusbar: false,
inline: true,
convert_urls: false,
plugins: [
piranha.editorconfig.plugins
],
width: "100%",
autoresize_min_height: 0,
toolbar: piranha.editorconfig.toolbar,
extended_valid_elements: piranha.editorconfig.extended_valid_elements,
block_formats: piranha.editorconfig.block_formats,
style_formats: piranha.editorconfig.style_formats,
file_picker_callback: function(callback, value, meta) {
// Provide file and text for the link dialog
if (meta.filetype == 'file') {
piranha.mediapicker.openCurrentFolder(function (data) {
callback(data.publicUrl, { text: data.filename });
}, null);
}
// Provide image and alt text for the image dialog
if (meta.filetype == 'image') {
piranha.mediapicker.openCurrentFolder(function (data) {
callback(data.publicUrl, { alt: "" });
}, "image");
}
}
});
$("#" + id).parent().append("<a class='tiny-brand' href='https://www.tiny.cloud' target='tiny'>Powered by Tiny</a>");
};
Piranha uses sets extended_valid_elements: piranha.editorconfig.extended_valid_elements but my dev tools are not showing the value that I type in editorconfig.json...
editorconfig.json
devTools
I've tried everything their docs say, I have a question open on github with Piranha as well.. Any suggestions would be great! Thanks
See the complete answer here: https://github.com/PiranhaCMS/piranha.core/issues/1663

Inserting custom element, attribute gets stripped

I made a tinymce fiddle about this problem: http://fiddle.tinymce.com/O0gaab
I add a custom element "custom-block" and a custom plugin to insert that element.
tinymce.PluginManager.add('custom', function(editor, url) {
editor.addButton('custom', {
text: 'CUSTOM',
onclick: function() {
// Open window
editor.windowManager.open({
title: 'Custom plugin',
body: [
{type: 'textbox', name: 'src', label: 'SRC'},
{type: 'label', name: 'title', text: 'Insert content bellow:'},
{type: 'textbox', name: 'content', multiline: true, style: 'width:500px;height:100px;'}
],
onsubmit: function(e) {
console.log(e.data);
editor.insertContent('<custom-block src="' + e.data.src + '">' + e.data.content + '</custom-block>');
}
});
}
});
});
tinymce.init({
selector: "textarea",
plugins: [
"advlist autolink lists link image charmap print preview anchor",
"searchreplace visualblocks code fullscreen",
"insertdatetime media table contextmenu paste custom"
],
toolbar: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image | custom",
//valid_elements: "+*[*]", //when using this option trying to allow everything get an error "Cannot read property 'src' of undefined"
extend_valid_elements: "custom-block[src]",
custom_elements: "custom-block"
});
The element, get inserted correctly but without the src attribute.
From the documentation I though that extend_valid_elements: "custom-block[src]" would allow src attribute on a custom-block but it gets stripped everytime.
I also tried to set valid_elements to everything(+*[*]) just in case, but then gets worse because at inserting, I get an error: "Cannot read property 'src' of undefined".
I am making any mistake or what is the problem?
The name of the configuration option is extended_valid_elements so you simply named it wrong in your configuration. It should be:
extended_valid_elements: "custom-block[src]"
I have updated your fiddle (http://fiddle.tinymce.com/O0gaab/1) and things appear to work.

How to embed Instagram post using Tiny MCE editor

I'm copying instagram embed code in tinymce source code and i can see the block of instagram but couldn't able to see the image. Please help me fix this issue
The problem is that when you add the embed code to tinymce. The code gets rendered in an iframe and the source code does not execute. The best approach in this case is to add a popup to take the embed code, extract the src from it and append it to the head of the iframe. This way the source code will execute and you will get a rendered html.
var editor_id = "";
tinymce.PluginManager.add('instagram', function(editor, url) {
// Add a button that opens a window
editor.addButton('instagram', {
text: 'Instagram',
icon: false,
onclick: function() {
// Open window
editor.windowManager.open({
title: 'Instagram Embed',
body: [
{ type: 'textbox',
size: 40,
height: '100px',
name: 'instagram',
label: 'instagram'
}
],
onsubmit: function(e) {
// Insert content when the window form is submitted
var embedCode = e.data.instagram;
var script = embedCode.match(/<script.*<\/script>/)[0];
var scriptSrc = script.match(/".*\.js/)[0].split("\"")[1];
var sc = document.createElement("script");
sc.setAttribute("src", scriptSrc);
sc.setAttribute("type", "text/javascript");
var iframe = document.getElementById(editor_id + "_ifr");
var iframeHead = iframe.contentWindow.document.getElementsByTagName('head')[0];
tinyMCE.activeEditor.insertContent(e.data.instagram);
iframeHead.appendChild(sc);
// editor.insertContent('Title: ' + e.data.title);
}
});
}
});
});
tinymce.init({
selector:'textarea',
toolbar: 'bold italic | alignleft aligncenter alignright alignjustify | undo redo | link image media | code preview | fullscreen | instagram',
plugins: "wordcount fullscreen link image code preview media instagram",
menubar: "",
extended_valid_elements : "script[language|type|async|src|charset]",
setup: function (editor) {
console.log(editor);
editor.on('init', function (args) {
editor_id = args.target.id;
});
}
});
Refer the JSFiddle - https://jsfiddle.net/z3o2odhx/1/
You can add the embed html from the Instagram toolbar button and get the rendered html, but this also messes the source code. Hope this is helpful.
Alternatively, if you have the option of adjusting the html of the page, you can just add <script async defer src="//www.instagram.com/embed.js"></script> somewhere on that page, since it looks like TinyMCE is stripping the js include.
If you want to selectively include it, you can also use something like this in that page's js:
if($(".instagram-media").length) {
var tag = document.createElement('script');
tag.src = "//www.instagram.com/embed.js";
tag.defer = true;
tag.async = true;
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
}
TinyMCE changed a bit in the last version (v5) - here is updated version of working Ananth Pais' solution:
tinymce.PluginManager.add('instagram', function(editor, url) {
editor.ui.registry.addButton('instagram', {
text: 'Instagram',
onAction: function() {
editor.windowManager.open({
title: 'Instagram Embed',
body: {
type: 'panel',
items: [
{
type: 'textarea',
height: '300px',
name: 'instagram',
label: 'Instagram embed code',
}
],
},
buttons: [
{
type: 'submit',
name: 'submitButton',
text: 'Embed',
disabled: false,
primary: true,
align: 'start',
}
],
onSubmit: function(e) {
var data = e.getData();
var embedCode = data.instagram;
var script = embedCode.match(/<script.*<\/script>/)[0];
var scriptSrc = script.match(/".*\.js/)[0].split("\"")[1];
var sc = document.createElement("script");
sc.setAttribute("src", scriptSrc);
sc.setAttribute("type", "text/javascript");
var iframe = document.getElementById(editor_id + "_ifr");
var iframeHead = iframe.contentWindow.document.getElementsByTagName('head')[0];
tinyMCE.activeEditor.insertContent(data.instagram);
iframeHead.appendChild(sc);
e.close();
}
});
}
});
});
tinymce.init({
selector:'textarea',
toolbar: 'bold italic | alignleft aligncenter alignright alignjustify | undo redo | link image media | code preview | fullscreen | instagram',
plugins: "wordcount fullscreen link image code preview media instagram",
menubar: "",
extended_valid_elements : "script[language|type|async|src|charset]",
setup: function (editor) {
console.log(editor);
editor.on('init', function (args) {
editor_id = args.target.id;
});
}
});
https://www.tiny.cloud/docs/configure/content-filtering/#usingextended_valid_elementstoallowscriptelements
by default tinmye prevent script codes.
enable them on tinymce options
extended_valid_elements : 'script[src|async|defer|type|charset]'

Uncaught TypeError: $(...).tinymce is not a function

I get this error with an tinymce form
$(document).ready(function () {
if (typeof(base_url) == "undefined") {
var base_url = location.protocol + '//' + location.host + '/';
}
$("#additional-information").tinymce({
script_url : 'http://sab-solutions.com/phpformbuilder/plugins/tinymce/tinymce.min.js',
document_base_url: base_url,
relative_urls: false,
theme: "modern",
language: 'fr_FR',
element_format: "html",
menubar: false,
plugins: [
"autolink autoresize charmap contextmenu link lists paste table"
],
entity_encoding : "raw",
contextmenu: "link inserttable | cell row column deletetable",
toolbar: "undo redo | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist | link",
schema: "html5"
});
});
The form are in this website
sab-solutions.com/site/emploi.php
The error message is telling you that there is no tinymce property or method on the jQuery object - when you call
$("#additional-information").tinymce...
You are trying to access a method or property on the $("#additional-information") jQuery object that does not exist.
There is no issue using document ready to init TinyMCE you just can't do what you have in that code.
Instead do something like:
tinymce.init({
selector: '#additional-information',
.
.
.
});
This will get you the same end result (TinyMCE will take over that field).
If you are still stuck I would suggest creating a simple TinyMCE Fiddle that shows what you have so people can see all the code that you are trying to run.
Note: When you use $("#additional-information").tinymce... that would only work with the jQuery version of TinyMCE. If you are using the regular distribution those calls won't work. My recommendation would be to use the regular distribution as it does not add the overhead of creating additional jQuery objects to make TinyMCE play within the jQuery environment.
You need to include a reference to the tinyMCE JS library. They have a version hosted on CDN at //cdn.tinymce.com/4/tinymce.min.js, you can download it manually, or use a package manager like bower.
To refernece an external javascript file use the script tag with a src attribute:
<script src="//cdn.tinymce.com/4/tinymce.min.js" type="text/javascript"></script>
solved!
the problem was that i included twice the jquery js