How to embed Instagram post using Tiny MCE editor - tinymce

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]'

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

tinymce 5 line break plugin

I've created a small TinyMCE v5 plugin that adds a line break button to the menu or toolbar :
/* Plugin code */
(function () {
'use strict';
var global = tinymce.util.Tools.resolve('tinymce.PluginManager');
var register = function (editor) {
// Translate button text
tinymce.util.I18n.add('fr_FR', {'Inser Line Break' : 'Insérer un saut de ligne'});
// Register new Icon
editor.ui.registry.addIcon('line-break', '<svg width="24" height="24"><path d="M 6.4,15.129563 H 12 c 3.7,0 6.2,-2 6.8,-5.1 0.6,-2.7 -0.4,-5.6 -2.3,-6.8 a 1.029563,1.029563 0 0 0 -1,1.8 c 1.1,0.6 1.8,2.7 1.4,4.6 -0.5,2.1 -2.1,3.5 -4.9,3.5 H 6.4 l 3.3,-3.3 a 1,1 0 1 0 -1.4,-1.4 l -5,5 a 1,1 0 0 0 0,1.4 l 5,5 a 1,1 0 0 0 1.4,-1.4 z" fill-rule="nonzero"/></svg>');
editor.addCommand('InsertLineBreak', function () {
editor.execCommand('mceInsertContent', false, '<br>');
});
};
var register$1 = function (editor) {
editor.ui.registry.addButton('br', {
icon: 'line-break',
tooltip: 'Inser Line Break',
onAction: function () {
return editor.execCommand('InsertLineBreak');
}
});
editor.ui.registry.addMenuItem('br', {
icon: 'line-break',
text: 'Inser Line Break',
onAction: function () {
return editor.execCommand('InsertLineBreak');
}
});
};
function Plugin () {
global.add('br', function (editor) {
register(editor);
register$1(editor);
});
}
Plugin();
}());
/* Main code */
tinymce.init({
selector : "textarea#mceEditor",
menubar: "",
language : "fr_FR",
plugins: ["advlist autolink link image lists preview hr anchor pagebreak wordcount fullscreen media nonbreaking emoticons template paste help", "br"],
toolbar: "fullscreen undo redo | formatselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist | link unlink image hr br ihtml | media | emoticons ",
block_formats: "Paragraph=p;Header 2=h2",
branding: false,
elementpath: false,
content_css : "https://www.dev-book.fr/styles/editor.css?v=36",
valid_elements : "h1,h2,hr,br,ul,ol,li,strong/b,em/i,p/div[align|style],a[href|target],img[class|src|border=0|width|height|align|style|alt],iframe[src|width|height]",
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/tinymce/5.7.1/tinymce.min.js"></script>
<textarea name="page_texte" style="height:"400px" id="mceEditor"></textarea>
The only way to make it works is adding a space behind <br> on line :
editor.execCommand('mceInsertContent', false, '<br> ');
otherwise the <br> tag is inserted but it has no effects meaning no line return occurs in the editor. The problem by adding this space is that it adds a space char at new line startup and I don't wan't that ...
I just want the same behavior when clicking my plugin button as hitting "MAJ+ENTER" on keyboard to insert line break instead of default new paragraph.
Unfortunately the code snippet does not work because of external TinyMCE CDN resource not being able to access Stack Overflow DOM. If one has suggestions to this sub-questions.
I found replacing '<br> ' by '<br>\u200C' was fixing my issue. \u200C is a code for "zero width non joiner"
Not sure this is the perfect answer but will go on with it waiting for a better one !

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

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

Display Media Uploader in Own Plugin on Wordpress 3.5

I have little problem with Media Uploader in new WordPress 3.5. I created own plugin which is upload the picture. I'm using this code JS:
<script type="text/javascript">
var file_frame;
jQuery('.button-secondary').live('click', function( event ){
event.preventDefault();
if ( file_frame ) {
file_frame.open();
return;
}
file_frame = wp.media.frames.file_frame = wp.media(
{
title: 'Select File',
button: {
text: jQuery( this ).data( 'uploader_button_text' )
},
multiple: false
}
);
file_frame.on('select', function() {
attachment = file_frame.state().get('selection').first().toJSON();
jQuery('#IMGsrc').val(attachment.url);
});
file_frame.open();
});
</script>
The code works fine, but unfortunately forms appears incomplete. When I select any picture doesn't show me 'Attachment Display Settings' on right side. I don't know why. I try add options to media:
displaySettings: true,
displayUserSettings: true
But it also doesn't work.
Does the page have the <script type="text/html" id="tmpl-attachment-details">... template in the source? If not, you'll need to call wp_print_media_templates(), to write the styles from wp-includes/media-template.php
This is the code I use. Source: http://mikejolley.com/2012/12/using-the-new-wordpress-3-5-media-uploader-in-plugins/ It seems to work pretty well, but the sidebar on the left is missing. (Intentional, but I don't want it anyways).
<?php wp_enqueue_media(); ?>
<script>
function showAddPhotos() {
// Uploading files
var file_frame;
// event.preventDefault();
// If the media frame already exists, reopen it.
if ( file_frame ) {
file_frame.open();
return;
}
// Create the media frame.
file_frame = wp.media.frames.file_frame = wp.media({
title: jQuery( this ).data( 'uploader_title' ),
button: {
text: jQuery( this ).data( 'uploader_button_text' ),
},
multiple: false // Set to true to allow multiple files to be selected
});
// When an image is selected, run a callback.
file_frame.on( 'select', function() {
// We set multiple to false so only get one image from the uploader
attachment = file_frame.state().get('selection').first().toJSON();
// Do something with attachment.id and/or attachment.url here
});
// Finally, open the modal
file_frame.open();
}
</script>