How to wrap TinyMCE element with custom HTML code without external JavaScript - javascript

I am trying to wrap some elements of TinyMCE with my custom HTML code.
For example, let us consider the user wants to add Media or Image element, the user will just click on Media or Image element icon, and he will be asked to enter the link, and TinyMCE will generate the required HTML code for that.
What I want to achieve is wrapping that generated HTML code with my custom code. I.e., so I will simply get this:
<div>
... What TinyMCE has generated for the image or media ...
</div>
For Media element, I tried using media_url_resolver, but that does not work for me, because this function does not give the ability to wrap the default behaviour, but only to rewrite the whole logic (which is a bad idea).
Could some one tell me if there is any TinyMCE native solution to get that (without any custom external JavaScript)?

There is no configuration option to do what you want but you can get notified when content is set into the editor and modify it before its inserted:
http://fiddle.tinymce.com/prgaab
The key code is here:
editor.on('BeforeSetContent', function (e) {
//Look at this object - it tells you a bunch of stuff about the insert activity
//such as was it via paste? Was there selected content in TinyMCE that will be overwritten?
//Using the browser tooling you can inspect the e object and learn a lot about the content that will be set.
console.log(e);
//Then you can modify that content if you want...for example:
if (e.content.startsWith("<a href=")) {
console.log('ADDING CONTENT');
e.content = '<p>BEFORE</p>' + e.content + '<p>AFTER</p>';
}
});

Related

How to dynamically add css to ckeditor without a css file

I have a situation where I am storing dynamic css data about a text object in a database as json. I need to map that same css data into styles in CKEditor. I am successfully able to load the classes into the CKEDITOR styles dropdown by parsing the json into the style set by running:
CKEDITOR.stylesSet.add('myStyles',styleObj);
Unfortunately this does not fully work with the onscreen text because the css does not exists as a file.
I've also successfully generate the css into the head of the dom by appending the dynamically generated css to a style tag. Unfortunately this still does not connect the actual css generated to the CKEDITOR because it is in a separate context.
Does anyone know how I can either connect document level css to the CKEDITOR instance or generate the CSS in a way that CKEDITOR understands? I'd prefer not to write a temporary CSS file to disk for every single user who needs to view the text object.
I figured out the answer to this by using the CKEDITOR.addCss() function.
Instead of trying to load the css into the document head as styles, the process can be much simpler by running CKEDITOR.addCss() function.
The code looks like:
for each css style found in the json:
styleObj.push({name:this.name,element:'p',attributes: { 'class':cssClassName}});
var cssSheetString = '.'+cssClassName+' {font-family:'+this.fontFamily+'; font-size:'+fontSize+'; font-weight:'+this.fontStyle+'; text-decoration:'+textDecoration+'; } ';
CKEDITOR.addCss(cssSheetString);
after the loop ends then also add the styles object:
if(!CKEDITOR.stylesSet.registered.myStyles){
CKEDITOR.stylesSet.add('myStyles',styleObj);
}
Just for posterity. I've seen answers that say this will work
CKEDITOR.on('instanceCreated', function (event) {
event.editor.addCss(styles);
});
but it does not, you have to use
CKEDITOR.on('instanceCreated', function (event) {
CKEDITOR.addCss(styles);
});
also if your styles variable changes you have to destroy and recreate your ckeditor instance with the new styles.

How to define custom html tags in ckeditor

How can I define custom html tags in ckeditor.
When user select a word e.g. Apple.
Then I want to replace this with profileTag Apple /profileTag".
But if the selected word already has a tag then it should append the profile tag.
For example if anchorTag Apple /anchorTag then after user selection it will be profileTag anchorTag Apple /anchorTag /profileTag.
The above thing is working. But when I execute the below code the output is null in case of custom html tag like profile tag.
var current_selected_element = editor.getSelection().getSelectedElement();
console.log(current_selected_element);
The problem is that CKeditor's advanced content filter is filtering out your custom tags ... you're going to have to configure the ACF to accept the custom tags your plugin is creating and inserting into the DOM. There are a couple ways this can be done. The most basic would be to implement config.extraAllowedContent = 'profile' or whatever the name of your custom markup will be. Otherwise you can work with the global CKEditor.filter object. There's more documentation on the CKEDITOR.filter object here.

Lightbox 2 with ember js and Froala editor (image preview on click)

I am using ember js as my front end MVC. I have a Question and Answers module which is similar to stack overflow where there are 2 fields one for the title and the other for the description.
Since the description is a text area and I have plugged it with Froala wysiwug editor.
Now I get the content typed in the froala text editor in ember by using
var editorText = $('.froala-element');
var desciption = editorText.html();
in the ember controller.
For example, if I console log what comes from the textarea
<p><img class="fr-fin" data-fr-image-preview="false" alt="Image title" src="/img/4ad38ae5b4a73cbad30987ac441075998d1e6b35.jpg" width="300"></p><p><br></p>
And I save this string in the database. All works good.
Now I want to use lightbox plugin
And as you notice, to make use of the plugin the image needs to be wrapped inside an anchor tag and added few data-lightbox attributes
Since I am stroing the image tag markup in the database, what is the best approach wrap the image inside the anchor tag
I got 2 options -
1) Before saving the image in the database, do a pattern match with javascript and find the image and wrap it inside an anchor tag.
2) In the didInsertElement hook of ember view, find all the images on the page and perform a dom manuplation and wrap the images inside anchor tag.
Is there any other way I could get this working ? Need some suggestions.
First of all you should get the HTML inside the editable area using the methods that are available in the editor, in this case getHTML method http://editor.froala.com/examples/getHTML. It is preferable to do so because there are some cleanups which the getHTML method does and it's good to make them.
$('#edit').editable('getHTML', false, true);
You can use the RegEx approach that you suggested, but you have to take into consideration not to wrap it twice. Another option would be to do that using jQuery which is easier.
var editorText = $('#edit').editable('getHTML', false, true);
var $div = $('<div>').html(editorText);
// Wrap image.
$div.find('img').each (function (index, img) {
var $img = $(img);
// Check if image is already wrapped in your anchor tag.
if (!$img.parents('a.your_anchor_selector').length) {
$img.wrap('<a class="your_anchor"></a>');
}
});
var description = $div.html();

Best way to move html content from .js file to .html file - completed

I have links such that when the user clicks on them, the DOM is quckly updated using the methods below.
Basically, I just set the innerHTML document to the text and the page updates.
However I would like html code with other html code when applicable. This is the only place in my .js file that has a significant amount of text. How do I move this?
/*
link - quick dom links - would like to find a way to move this into xhtml where it belongs
*/
function o2(a,b)
{
return document.getElementById(a).innerHTML=b;
}
function l1()
{
........
I would recommend putting all of the possible HTML into your HTML file. Assign a unique id to each element and use CSS to hide them all or all but one by default (using 'display: none'). Then your javascript function can simply change CSS based on which html fragment you need to be visible.

Create new (not change) stylesheets using jQuery

We've got a little tool that I built where you can edit a jQuery template in one field and JSON data in another and then hit a button to see the results immediately within the browser.
I really need to expand this though so the designer can edit a full CSS stylesheet within another field and when we render the template, it will have the CSS applied to it. The idea being that once we've got good results we can take the contents of these three fields, put them in files and use them in our project.
I found the jQuery.cssRule plugin but it looks like it's basically abandoned (all the links go nowhere and there's been no development in three years). Is there something better or is it the only game in town?
Note: We're looking for something where someone types traditional CSS stylesheet data in here and that is used immediately for rendering within the page and that can be edited and changed at will with the old rules going away and new ones used in their stead. I'm not looking for something where the designer has to learn jQuery syntax and enter in individual .css("attribute", "value") type calls to jQuery.
Sure, just append a style tag to the head:
$("head").append("<style>p { color: blue; }</style>");
See it in action here.
You can replace the text in a dynamically added style tag using something like this:
$("head").append("<style id='dynamicStylesheet'></style>");
$("#dynamicStylesheet").text(newStyleTextGoesHere);
See this in action here.
The cleanest way to achieve this is by sandboxing your user-generated content into an <iframe>. This way, changes to the CSS won't affect the editor. (For example, input { display:none; } can't break your page.)
Just render out your HTML (including the CSS in the document's <head>, and write it into the <iframe>.
Example:
<iframe id="preview" src="about:blank">
var i = $('#preview')[0];
var doc = i.contentWindow || i.contentDocument;
if (doc.document) doc = doc.document;
doc.open('text/html',true);
doc.write('<!DOCTYPE html><html>...</html>');
doc.close();
If the user should be able to edit a whole stylesheet, not only single style attributes, then you can store the entered stylesheet in a temporary file and load it into your html document using
$('head').append('<link rel="stylesheet" href="temp.css" type="text/css" />');
sounds like you want to write an interpreter for the css? if it is entered by hand in text, then using it later would be as simple as copy and pasting it into a css file.
so if you have a textarea on your page to type in css and want to apply those rules when you press the button, you could use something like this (only pseudocode, needs work):
//for each css id in the text area
$.each($('textarea[name=cssTextArea]').html().split('#'), function({
//now get each property
$.each($(this).split(';'), function(){
$(elem).css({property:value});
});
});
then you could write something to go through each element that your designer typed in, and get the current css rules for it (including those that you applied using some code like the snippet above) and create a css string from that which could then be output or saved in a db. It's a pain and much faffing around with substrings but unfortunately I don't know of a faster or more efficient way.
Hope this atleast gives you some ideas

Categories