Dragging: Replacement of the data - javascript

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');
});

Related

Access TinyMCE current input within iframe

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).

Can't load HTML code into a div when an image button is clicked

So I am making a website for radio streams and was told I should use Jquery and AJAX to load the HTML files into a div on button click so that I wouldn't have to make the user load a completely new HTML page for each radio stream. But I am a bit lost since I am new to this language and I am not entirely sure what I am doing wrong.
Currently I have a index.html page that loads each individual div and loads all the available radio stations in an iframe linking to an HTML file. In this HTML file there are around 40 buttons that each have to link to their own radio stream. On a button press I want said stream to load into the 'radio player' div for a smooth transition.
After trying to google the problem I was told to do this with the following JavaScript code:
$(function(){
$(".538").click(function(){
$("#div3").load("/includes/about-info.html");
});
});
Since each button is also showing its own image file, I tried to add class="538 to each image source so the JavaScript knows what is targeted. Unfortunately it doesn't seem to work at all and I have no clue what to do. I tried to do this in a separate index.js file which unfortunately didn't work, so I tried to use the JavaScript code in the HTML file itself, and this didn't seem to do the trick either.
TL/DR: trying to load HTML code in a div when an image button is clicked.
Is there perhaps a tutorial for this available? I tried to search the web but couldn't find anything at all. If anyone is able to help me out with this problem I'd love you forever.
I think what's happening is that you're working with dynamic elements. More importantly you should never use numbers to start off either a class name or id.
Unless you post a bit more code it's hard to figure out exactly what you're wanting to do.
If you work with dynamic html the click event won't work, because well you need do dynamically bind the event listener.
For that you can use
$('#dynamicElement').on('click', function() {
$(this).find('#elementYouWantToLoadInto').load('/includes/about-info.html');
});
The above code works if the element is nested in the button. If it's an external element then use.
$('#dynamicElement').on('click',function() {
$('#elementYouWantToLoadInto').load('/includes/abount-info.html');
});
You mentioned that this language is a bit new to you; If you're open to a bit of refactoring:
Your main page should have 2 sections:
<div id='myButtons'>
<input type='radio' data-url='/includes/about-info.html' />
<...>
</div>
<div id='myContent'></div>
<script>
$(function() { //jquery syntax - waits for the page to load before running
$('#myButtons').on('click', 'input', function() { // jquery: any click from an input inside of myButtons will be caught)
var button = $(this),
url = button.data('url'),
content = $('#myContent');
content.load(url);
});
</script>
Jquery: http://api.jquery.com/
you can try this
$('#myButtons').on('click', 'input', function() {
$.get("about-info.html", function(data) {
$("#div3").html(data);
});
});
or
$(document).ready(function(){
$(function(){
$(".radio538").click(function(){
$("#div3").load("/includes/about-info.html");
});
});
})
$(document).ready(function(){
$('#radio1').on('click',function(){
#('#loadradiohere').load('/includes/about-info.html');
});
});
Try that code in your .js file. I am still working for a similar project man.

jQuery .click() does not work in Safari

I have seen several similar posts with solutions that seemed to have worked for those people, but I CANNOT get this to work.
I am using http://tutorialzine.com/2013/05/mini-ajax-file-upload-form/ in my project. It works PERFECTLY, in all browsers, except in Safari the "BROWSE" button does not open a file dialog. The following code exists in script.js (which is included for the plugin to work):
$('#drop a').click(function(){
// Simulate a click on the file input button
// to show the file browser dialog
$(this).parent().find('input').click();
});
The .click() does not fire in Safari. I have tried the solution as per jQuery .click() works on every browser but Safari and implemented
$('#drop a').click(function(){
var a = $(this).parent().find('input');
var evObj = document.createEvent('MouseEvents');
evObj.initMouseEvent('click', true, true, window);
a.dispatchEvent(evObj);
});
But then I get the error that dispatchEvent is not a function. I then did some research on this, and tried the jQuery.noConflict() route, but this did not resolve the error. Also, I use a LOT of jQuery in my main file and I cannot have the noConflict() mode activated for the entire page. There is also no reason that the jQuery should be conflicting with anything as I am only using jQuery and normal javascript and I am not using anything like prototype or angular. Does anybody know of another way to simulate a click in Safari?
UPDATE: Just FYI, I have added an alert('test') in the mentioned function (which triggers when "BROWSE" is clicked), and I do get the alert in Safari, but it is not simulating the click of the file input element, i.e: it is not openening the file dialog.
The second section of code in my original question turned out to work, except for 2 things.
1) The method does not like jQuery, so instead of
var a = $(this).parent().find('input')[0];
I assigned an ID to my file input and instead called
var a = document.getElementById('upload_select');
2) Safari blatantly ignores this if the input is hidden (display:none;), which is was, so instead I made the input font-size = 1px; and opacity = 0.
Implementing these two changes got the code working.
You need to read that answer more closely. :-)
dispatchEvent is a function on the DOM element, not the jQuery object. You're trying to call it on the jQuery object. So:
$('#drop a').click(function(){
var a = $(this).parent().find('input')[0];
// Change here -----------------------^^^
var evObj = document.createEvent('MouseEvents');
evObj.initMouseEvent('click', true, true, window);
a.dispatchEvent(evObj);
});
Using the [0] on the jQuery object gives you the first DOM object in the jQuery object, or undefined if the jQuery object is empty.

TinyMCE on IE8: text cursor problem

when i type something on ie 8, and press 'bold' on toolbar on top of the text editor, the cursor will go to the beginning of the entire text editor. is this bug in tiny mce?
on the other hand, if i select text i typed, and pressed control+b, no problem ; both are fine in firefox,ie6
Have you tried turning off "View->Caret Browsing" in IE8 ? (it is toggled by F7)
That worked for me
I had a similar problem where the image that I wanted to insert was always going to the top of the editor. I solved it by setting the 'onchange_callback' field in the editor's init:
tinyMCE.init({..., onchange_callback: 'updateSelectionBookmark', ...});
This will call my 'updateSelectionBookmark' function when anything is changed on the screen, including the editor being blurred (Read more: http://tinymce.moxiecode.com/wiki.php/Configuration:onchange_callback). My updateSelectionBookmark looked something like:
function updateSelectionBookmark (ed) {
ed.updatedSelectionBookmark = ed.selection.getBookmark(1);
}
This will add a custom property to the editor object which will always contain the latest bookmark.
I then make use of the stored bookmark whenever I need to add the content:
ed.selection.moveToBookmark(ed.updatedSelectionBookmark);
I wanted to insert HTML so I put this before my call to the instance command (In my case, mceInsertRawHTML).
I hope this helps someone, even if my answer is a few months late.
Edit (A few months later): So I originally found this solution while working with TinyMCE 3.2.2.3 but we recently updated to 3.4.4 for compatibility with IE9. Looks like the above solution doesn't work as well as I thought it did. I've since found a (as far as I can tell) perfect solution to this. It's similar to the above except when and where to trigger the callback. Instead of using onchange_callback in the settings, you should use the editor's onEvent event:
tinyMCE.init({
...,
setup: function (ed) {
ed.onEvent.add(function (ed, e) {
ed.updatedSelectionBookmark = ed.selection.getBookmark(1);
});
},
...
});
This replaces the need for the updateSelectionBookmark function or the onchange_callback setting. The reason onEvent works better than onChange is because it gets called after any possible event, including mouse or key presses so the cursor's position is guaranteed to be saved even if moved but the content isn't changed.
After setting up the editor with the above event callback, just use moveToBookmark as stated above to restore the selection. I've tested this on IE9, Chrome, FF6, it works when inserting images/text inside text/tables.
I would'nt say that it's a bug in IE8.
A cursor does'nt move by magic, someone(tinymce) put's him somewhere.
So if the cursor does'nt appear at the expected position, it has to be a misbehaviour in tinymce.
But I can't provide a "bugfix", because this not occurs with my IE8(Win7).
What's your environment?

How can I tell if a page has jumped to the anchor (#) in JavaScript?

I have some JavaScript that can appear on many different pages. Sometimes those pages have been accessed via a URL containing an anchor reference (#comment-100, for instance). In those cases I want the JavaScript to delay executing until after the window has jumped. Right now I'm just using a delay but that's pretty hackish and obviously doesn't work in all cases. I can't seem to find any sort of DOM event that corresponds to the window "jump".
Aside from the simple delay, the only solution I've come up with is to have the JS look for the anchor in the URL and, if it finds one, watch for changes in scrollTop. But that seems buggy, and I'm not 100% sure that my script will always get fired before the scrolling happens so then it would only run if the user manually scrolled the page. Anyhow, I don't really like the solution and would prefer something more event driven. Any suggestions?
Edit to clarify:
I'm not trying to detect a hash change. Take the following example:
Page index.php contains a link to post.php#comment-1
User clicks the link to post.php#comment-1
post.php#comment-1 loads
$(document).ready fires
Not long later the browser scrolls down to #comment-1
I'm trying to reliably detect when step 5 happens.
You can check window.onhashchange in modern browsers. If you want cross compatible, check out http://benalman.com/projects/jquery-hashchange-plugin/
This page has more info on window.onhashchange as well.
EDIT: You basically replace all anchor names with a similar linking convention, and then use .scrollTo to handle the scrolling:
$(document).ready(function () {
// replace # with #_ in all links containing #
$('a[href*=#]').each(function () {
$(this).attr('href', $(this).attr('href').replace('#', '#_'));
});
// scrollTo if #_ found
hashname = window.location.hash.replace('#_', '');
// find element to scroll to (<a name=""> or anything with particular id)
elem = $('a[name="' + hashname + '"],#' + hashname);
if(elem) {
$(document).scrollTo(elem, 800,{onAfter:function(){
//put after scroll code here }});
}
});
See jQuery: Scroll to anchor when calling URL, replace browsers behaviour for more info.
Seems like you could use window.onscroll. I tested this code just now:
<a name="end" />
<script type="text/javascript">
window.onscroll = function (e) {
alert("scrolled");
}
</script>
which seems to work.
Edit: Hm, it doesn't work in IE8. It works in both Firefox and Chrome though.
Edit: jQuery has a .scroll() handler, but it fires before scrolling on IE and doesn't seem to work for Chrome or Firefox.
To detect when the element appears on the screen, use the appear plugin:
$('#comment-1').appear(function() {
$(this).text('scrolled');
});

Categories