Access TinyMCE current input within iframe - javascript

I am using TinyMCE and I am trying to output what the user is currently typing to a div below the TinyMCE editor. I want the user to see how there post would look like rendered.
The script I am using is this:
<script type="text/javascript">
$(function () {
$('#tinymce').keyup(function () {
$('#myDIVTag').html('<b>' + $(this).val() + '</b>');
});
});
</script>
I have placed the corresponding div in my begin form in the view:
<div id="myDIVTag">
</div>
However nothing is being rendered as I type.

There is no fiddle, which makes thing harder - but it got pointed out in the comment that TinyMCE editor itself is hidden within <iframe> element. This seems to be the root of the issue.
To be able to access anything within iframe element with JavaScript, we must remember about Cross-Domain Policy. In short - if iframe has src attribute set to another domain, and website under this source doesn't explicitly let us access its contents within iframe - we won't be able to do it, end of the story. More: http://blog.cakemail.com/the-iframe-cross-domain-policy-problem/ .
Luckily, I'm pretty sure it won't be of any problem here - unless TinyMCE within our iframe gets served from another domain.
Given all that, here's the snippet that should do the trick. Please alter selectors for your needs (I pointed them out with comments):
$('iframe') // iframe element
.contents()
.find('textarea') // textarea/other input *within* iframe
.keyup(function () {
$('#myDIVTag').html('<b>' + $(this).val() + '</b>');
});
EDIT:
It got suggested in the comment (thanks #charlietfl!) that the proper way to approach this problem is to use TinyMCE API event, not generic binding to textarea element within iframe. Here's a quick answer taking that into account:
HTML:
<textarea id="tinymce-textarea"></textarea>
<div class="text-mirror"></div>
JS:
tinymce.init({
selector: "#tinymce-textarea",
setup: function (editor) {
editor.on('change', function (e) {
var newVal = tinymce.get('tinymce-textarea').getContent();
$('.text-mirror').html(newVal);
});
}
});
JSFiddle: http://jsfiddle.net/c1zncmt8/1/ .
Basically: we're binding to TinyMCE editor "change" event, and whenever it gets triggered we get value of our input (var newVal = ...) and put it into separate div (.text-mirror).

Related

Suppressing an onclick link event without stopping the actual page re-direct

Is there a way to disable the onclick function but still use the href to re-direct the user to the requested link. Example a header menu there are many links that looks like below :
Phones
I am unable to remove the "DA_A('id', ':per:shop', this.href); return false;" from the HTML page. However using a tag manager how would one go about injecting a snippet of JavaScript code function which will de-activate/mute the "DA_A" function but still make the link work as normal? Is it possible? It seems the function "DA_A" is a function that calls another ".push" function and pass some data.
What are my options? as I am unable to edit the menus in questions?
You can probably remove the onclick from the element if you can run some javascript after the DOM renders:
var anchor = document.getElementById("someId"); // or tagname, querySelector, etc
anchor.onclick = "";
You could also disable the function it calls altogether, depending on whether it is needed elsewhere:
window.DA_A = function() { /* do nothing */ };
The first snippet would need to be run after the DOM was rendered (for example, if you are using jquery then enclose it in a $(function() {})), and the second snippet would need to run after the DA_A function is defined in the first place.
Either of these by themselves should disable the onclick, but still allow the anchor to navigate.
this code snippet will do the trick:
window.onload = function()
{
document.querySelctor("a").removeAttribute("onclick"); // make selector more specific
};

set tinymce in " javascript, $(document).ready...", my solution is not working

i use javascript made a function that every time i click button "add one more" button, html page will add another group of html elements, which i need to includes tinymce text area, but I cannot manage to do it.
here is part of my code,
<script>
$(document).ready(function (e) {
var html = '<textarea class="tinymce" name="CCV_product_full_description[]" id="childccv-product-full-description" />';
...
I defined tinymce in another js file and included in this html file, but it not works some how, i need some help :)
in another js file
tinymce.init({
selector:"textarea.tinymce"
});
here is the function for add another group of html elements
$("#add").click(function (e) {
$("#container").append(html);
});
It looks like you are trying to initialize the editor on DOM elements that don't yet exist.
Also, if you are trying to dynamically add several instances of TinyMCE, you need to remove TinyMCE first before you can call it again.
$("#add").on('click', function (e) {
e.preventDefault()
$("#container").append(html);
tinymce.remove()
tinymce.init({
selector:".yourSelectorName"
});
});

Rerun Jquery function onclick

I have a simple jquery script that changes the url path of the images. The only problem is the doesn't apply after I click the load more button. So I'm trying to do a workaround where it calls the script again after clicking the button.
<script type='text/javascript'>
$(document).ready(function ReplaceImage() {
$(".galleryItem img").each(function() {
$(this).attr("src", function(a, b) {
return b.replace("s72-c", "s300")
})
})
});
</script>
HTML
Load More
While Keith's answer will get you what you are looking for, I really can't recommend that approach. You are much better off with something like this.
<script type="text/javascript">
$(function() {
var replaceImage = function() {
$('.galleryItem img').each(function() {
$(this).attr('src', function(index, value) {
return value.replace('s72-c', 's300');
});
});
};
replaceImage();
$('.js-replace-image').on('click', replaceImage);
});
</script>
Using this html
<button class="js-replace-image">Load More</button>
By taking this approach, you do not expose any global variables onto the window object, which can be a point of issue if you work with other libraries (or developers) that don't manage their globals well.
Also, by moving to a class name and binding an event handler to the DOM node via JavaScript, you future proof yourself much more. Also allows yourself to easily add this functionality to more buttons very easily but just adding a class to it.
I updated the anchor tag to a button because of the semantics of what you need to do - it doesn't link out anywhere, it's just dynamic functionality on the page. This is what buttons are best served for.
I'd also recommend putting this in the footer of your site, because then, depending on your situation, you will already have the images updated properly without having to click the button. The only need for the button would be if you are dynamically inserting more images on the page after load, or if this script was in the head of your document (meaning jQuery couldn't know about the images yet).
I hope this helps, reach out if you have questions.

Find/Replace Inside Texareas WYSIWYG

I believe the problem with finding/replacing text is when a wysiwyg steps into the mix.
However, I'm sure someone has figured out how to do the magic.
Here's the textarea, with no editor attached:
<textarea id="template1" style="width:400px; height:200px;">
<div>Dear {{companyname}},</div>
<div>A new Support Case has been opened for you.</div>
<div>Support Case description:</div>
.........more html text follows
</textarea>
<script language="javascript" type="text/javascript">
$(document).ready(function(){
var str = $("#template1").val();
var newstr = str.replace("{{companyname}}", "ACME Inc");
$("#template1").val(newstr);
});
</script>
Without the editor, I'm good to go.
As soon as I apply my editor of choice (TinyMCE), the replace() method gets ignored.
Does anyone know why?
There are two reasons why your replace function doesn't work.
1. The contents of the former textarea get replaced, but you cannot see the result because tinymce hides the textarea and uses a contenteditable iframe to load and style the former contents. The editor content gets written back to the textarea onSave and onSubmit
2. $(document).ready all ressources of your page have been loaded, but the tinymce editor is not ready.
This will lead to the question on how to replace the code in the tinymce editor. $(document).ready won't help here. You will need use the tinymce configuration paramter onInit
// Adds an observer to the onInit event using tinyMCE.init
tinyMCE.init({
...
setup : function(ed) {
ed.onInit.add(function(ed) {
//console.debug('Editor is done: ' + ed.id);
// replace the editor content
var str = ed.getContent();
var newstr = str.replace("{{companyname}}", "ACME Inc");
ed.setContent(newstr);
});
}
});
If you look at the actual Html generated by tinymce in your favourite page inspector (firebug, dev tools, dragonfly etc), you will see that you are actually editing an iframe with contentEditable enabled. As far as i can tell it will use the textarea/input to set the initial content, and do some other sort of voodoo to set it back when you post the form back to the server.
If you want to do it manually there are methods to do so:
http://www.tinymce.com/wiki.php/API3:method.tinymce.Editor.getContent
http://www.tinymce.com/wiki.php/API3:method.tinymce.Editor.setContent
You could do your text processing via those.

Dragging: Replacement of the data

I got a webpage with some html elements including a textarea and an embedded contenteditable iframe (a rte).
Using this code i manage to catch the draggesture event on the main page and set the text/html-data
jQuery(document).bind('draggesture', function(event){
event.originalEvent.dataTransfer.setData('text/html', 'my_data');
});
Now, when dropping in a textarea on the main page 'my_data' gets dropped.
Dropping in the contenteditable iframe drops 'my_data' too.
But i got three issues here that i do not understand:
1. Binding this kind of handler to the iframes document works. I set the events data analog to the above code, but it does not work. When i drag it inside the iframe or to the textarea on the main page 'my_data' does not get inserted, but the original selected content. What can i do to set 'my_data'?
2. I tried to modify/set the data using the drop event in the iframe and the main page:
jQuery(ed.getDoc()).bind('drop', function(event){
event.originalEvent.dataTransfer.setData('text/html', 'my_data');
});
But i get a javascript error on both documents (main page and iframe) : "Modifications are not allowed for this document".
Why do i get this error? Is there a workaround for this?
Looks like pimvdb got an explantion for this.
3. When selecting <p>some text</p><hr><p>some text</p> from the main page and dragging this into the contenteditable iframe nothing gets inserted when i set 'my_data' (on Draggesture) using the first code example from above. Dragging into the textarea works. Does anyone know what gets wrong here? (problem does not occur using chrome!)
EDIT: Here is a jsFiddle demo to play around and understand the problem:
http://jsfiddle.net/R2rHn/5/
You are using draggesture but dragstart works.
Second, it does not make sense to set the dataTransfer data on drop, because the drag "package" has already arrived by then. It's being destroyed after the drop, so why would you like to change it at that point?
I cleaned your fiddle to get straight what was happening so as to be able to solve it, and this is the result. It seems to work on Chrome.
http://jsfiddle.net/R2rHn/7/
tinyMCE.init({
mode : "exact",
elements : "content",
skin : "o2k7",
skin_variant : "silver",
setup : function(ed) {
ed.onInit.add(function(ed, evt) {
var iframe = ed.getDoc();
jQuery(iframe).bind('dragstart', function(event){
event.originalEvent
.dataTransfer
.setData('text/plain', 'modified_content_from_iframe');
});
});
},
});
jQuery(document).bind('dragstart', function(event){ event.originalEvent
.dataTransfer
.setData('text/html', 'my_data_html');
event.originalEvent
.dataTransfer
.setData('text/plain', 'my_data_plain');
});

Categories