The following code:
<!DOCTYPE HTML>
<html>
<head>
<style type="text/css">
#div1 {width:350px;height:70px;padding:10px;border:1px solid #aaaaaa;}
</style>
<script>
function allowDrop(ev)
{
console.log(ev.dataTransfer.getData("Text"));
ev.preventDefault();
}
function drag(ev)
{
ev.dataTransfer.setData("Text",ev.target.id);
}
function drop(ev)
{
ev.preventDefault();
var data=ev.dataTransfer.getData("Text");
ev.target.appendChild(document.getElementById(data));
}
</script>
</head>
<body>
<p>Drag the W3Schools image into the rectangle:</p>
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<br>
<img id="drag1" src="img_logo.gif" draggable="true" ondragstart="drag(event)" width="336" height="69">
</body>
</html>
with Firefox get correctly the dataTransfer object and returns the image's id (drag1) when the allowDrop function called by ondragover event is executed, but in Chrome getData returns an empty string.
Is it a bug or Chrome returns a valid dataTransfer object only with the ondrop event?
Chrome doesn't set the dataTransfer before drop.
I just set my drag reference in a "global" variable instead. :-)
You can't use dataTransfer in chrome except in the drop event .
you should declare a Global variable instead .
for your situation try this :
function drag(ev)
{
el = ev.target;
ev.dataTransfer.setData("Text",ev.target.id);
}
function allowDrop(ev)
{
console.log(el);
ev.preventDefault();
}
Actually, it's very trick in Chrome. I have a simple page to drag some div into some container. I set the dragging div element id into dataTransfer at ondragstart method. I try to get the dragging div from dataTransfer in ondrop callback, and then copy it to the container. Everything works very well in Chrome on local(I mean just open it from explorer, file://). But when I deploy it to web site, and then open it via http://. It does not work in chrome. So I use the same solution with Per Digre. Set the global variable on dragstart, clean the variable on dragend. Hope it help you!
Related
With HTML5, is there any way in IE11/Edge to populate a sandboxed iframe (<iframe sandbox></iframe>) with HTML other than using a src url? I am looking for a solution like srcdoc which works with all other modern browsers.
Using src with a data URI is not an option according to Microsoft as it "cannot be used [to] populate frame or iframe elements." Surprisingly, this does works for me in Edge but only for data URIs with less than 4096 characters.
All other options that I have found, e.g. in Alternatives to iframe srcdoc? and Html code as IFRAME source rather than a URL do not work for a sandboxed iframe.
Assuming usage of <iframe sandbox="allow-scripts"> is desired or acceptable, a possible workaround would be using window.postMessage() with the following setup:
index.html:
<!doctype html>
<html>
<body>
<iframe onload="connectIframe()" sandbox="allow-scripts" src="iframeConnect.html" name="srcdocloader"></iframe>
<script>
var SRCDOC_HTML = '<html><body><script src="https://code.jquery.com/jquery-3.2.1.js"><\/script><script>console.log("loaded srcdoc and dependencies", jQuery);<\/script><h1>done!</h1></body></html>';
var loaded;
function connectIframe (event) {
if (!loaded) {
loaded = true;
window.frames.srcdocloader.postMessage(SRCDOC_HTML, '*');
} else {
onloadSrcdoc();
}
}
function onloadSrcdoc () {
// ...
}
</script>
</body>
</html>
iframeConnect.html:
<!doctype html>
<script>
window.addEventListener("message", handler);
function handler(event) {
if (event.source === window.parent) {
window.removeEventListener("message", handler);
document.write(event.data);
document.close();
}
}
</script>
Note that the iframe's onload event will be triggered two times. The second time will be after the srcdoc html and all its dependencies got loaded.
I'm attempting to add drag-and-drop to my chrome app. Here is the code, but I can't get it to work. Is there something I need to enable? Or am I not including something? I'm simply trying to get something to work that places one div inside another.
<!DOCTYPE html>
<html>
<head>
<title>EOS</title>
<link rel="stylesheet" type="text/css" href="/css/main.css">
</head>
<body>
<div id="open-player-position" class="open-position" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div id="player1" class="collapsed-player" draggable="true" ondragstart="drag(event)">
<h4>Player 1</h4>
</div>
</body>
<script type="text/javascript">
function allowDrop(ev)
{
ev.preventDefault();
}
function drag(ev)
{
ev.dataTransfer.setData("Text",ev.target.id);
}
function drop(ev)
{
ev.preventDefault();
var data=ev.dataTransfer.getData("Text");
ev.target.appendChild(document.getElementById(data));
}
</script>
</html>
First, you must include your script code in javascript files, not inline, due to packaged apps Content Security Policy. This alone is likely the cause of your code not working.
Then, see examples of drag in drop in the samples. E.g. Image Edit which uses the utility code from dnd.js.
I need to make a parent iFrame on domain A go fullscreen from its postMessage event handler which gets triggered by a postMessage from the window in domain B. I have the postMessage communication setup perfectly. The "allowfullscreen" attribute is set on the iframe too. But the requestFullScreen() method seems to silently quit. After searching I found that due to security reasons, requestFullScreen works only on event handlers for events like mouse clicks,
keypress etc. I tried forcefully executing a click on the iFrame using jquery click() and it comes into the click handler too but the requestFullScreen doesn't work. I tried clicking on the iFrame directly and it goes fullscreen.
How do I make this work?
Here's my code - for the parent on domainA.
I have made sure that the post message handler is executed when my child on domain B posts a message
<!DOCTYPE HTML>
<html>
<script type="text/javascript" src="jquery.js"></script>
<script>
var container;
$(function(){
container = $('#parentFrame')[0];
container.addEventListener("click",goFullScreen);
window.addEventListener("message", receiveMessage, false);
});
function receiveMessage(event)
{
/* Use this code to restrict request from only one particular domain & Port!
Port not needed in this case*/
if (event.origin !== "http://myChildDomain.com")
{
return;
}
/*Retrieving relevant variables*/
var message=event.data;
var source=event.source;
var origin=event.origin;
//Forcefully generating a click event because fullscreen won't work when directly requested!
container.click();
}
goFullScreen = function (){
if (container.mozRequestFullScreen) {
// This is how to go into fullscren mode in Firefox
// Note the "moz" prefix, which is short for Mozilla.
container.mozRequestFullScreen();
} else if (container.webkitRequestFullScreen) {
// This is how to go into fullscreen mode in Chrome and Safari
// Both of those browsers are based on the Webkit project, hence the same prefix.
container.webkitRequestFullScreen();
}
}
</script>
<body>
<iframe id="parentFrame" src="http://myChildDomain/child.html" width="804" height="600" frameborder="0" scrolling="no" allowfullscreen style="border: 5px solid #00ff00">
</iframe>
</body>
</html>
I have built a jquery html5 canvas sketching app that accepts mouse events for desktop (pen tablets just use mouse events). I would also like to allow drawing with the finger on iphone, ipad, andriod devices as a mobile web enabled app. Since mobile devices also trigger mouse click events on their own: Does this mean that I should detect the type of browser and replace all mouse bindings with touch bindings in order to prevent events from double firing?
Here is a stupid example:
<!DOCTYPE html>
<html>
<head>
<script src="jquery.min.js"></script>
</head>
<body>
<canvas id="myCanvas" width="1600px" height="1600px" style="border:1px dashed gray;background-color:white;">
</canvas>
<script>
function brushStart() {
$('#myCanvas').css('background-color','blue');
}
function brushEnd() {
$('#myCanvas').css('background-color','red');
}
function brushMove() {
$('#myCanvas').css('background-color','yellow');
}
$('#myCanvas').bind('mousedown', brushStart);
$('#myCanvas').bind('mouseup', brushEnd);
$('#myCanvas').bind('mousemove', brushMove);
$('#myCanvas')[0].addEventListener('touchstart',brushStart,false);
$('#myCanvas')[0].addEventListener('touchend',brushEnd,false);
$('#myCanvas')[0].addEventListener('touchmove',brushMove,false);
</script>
</body>
</html>
I've used the following to do what you're looking for:
$("#myCanvas").bind("touchstart mousedown", function (event) {
var e = event.originalEvent;
e.preventDefault();
startX = (e.targetTouches != undefined) ? e.targetTouches[0].screenX : e.offsetX;
startY = (e.targetTouches != undefined) ? e.targetTouches[0].screenY : e.offsetY;
});
A couple of points -- you need to access the originalEvent in jQuery in order to work with targetTouches. Also, as I'm sure is apparent, you can substitute any property pair you need for offsetX/Y for the mouse events.
How do I prevent scrolling without preventing default, because I still want the touchmove event to be processed:
<!DOCTYPE html>
<html>
<head>
<script src="jquery.min.js"></script>
</head>
<body>
<canvas id="myCanvas" width="1600px" height="1600px" style="border:1px dashed gray;background-color:white;">
</canvas>
<script>
function brushStart() {
$('#myCanvas').css('background-color','blue');
}
function brushEnd() {
$('#myCanvas').css('background-color','red');
}
function brushMove() {
$('#myCanvas').css('background-color','yellow');
}
$('#myCanvas').bind('mousedown', brushStart);
$('#myCanvas').bind('mouseup', brushEnd);
$('#myCanvas').bind('mousemove', brushMove);
$('#myCanvas')[0].addEventListener('touchstart',brushStart,false);
$('#myCanvas')[0].addEventListener('touchend',brushEnd,false);
$('#myCanvas')[0].addEventListener('touchmove',brushMove,false);
</script>
</body>
</html>
When you say you want it to be processed - it still can be. Just write it like this:
$('#myCanvas')[0].addEventListener('touchmove', function(e) {
e.preventDefault();
brushMove();
},false);
I don't guarantee that preventDefault alone will stop the scrolling, but that's how you'd write it if you wanted it to prevent the default and do your own method too. You could also put the call in brushMove itself.
Let me just say that you probably need to be doing preventDefault in touchStart and not touchMove. touchMove might actually be too late, because if it is scrolling there might be no touchMove events to be had!