iFrame inside draggable / scrollable area - javascript

I'm stuck at finding a solution to my problem.
Let's assume we have fixed-sized area with scrollbars. We need to place an iframe inside so we can preview it by either using the scrollbars or by dragging it. To prevent iframe capturing mouse events, I've put absolute positioned transparent div above it.
<div style="" id="scrolling_container">
<div id="drag_div"></div>
<div id="frame_div">
<iframe id="page_iframe" src="http://www.bbc.com/" scrolling="auto" frameborder="0"></iframe>
</div>
</div>
Then I used some code that transforms mouse dragging into div scrolling.
var draggableContainer = document.getElementById("drag_div");
var scrollingContainer = document.getElementById("scrolling_container");
draggableContainer.removeEventListener('mousedown', draggableContainer.md, 0);
window.removeEventListener('mouseup', draggableContainer.mu, 0);
window.removeEventListener('mousemove', draggableContainer.mm, 0);
var pushed = 0;
draggableContainer.addEventListener('mousedown',
draggableContainer.md = function(e) {
pushed = 1;
lastClientX = e.clientX;
lastClientY = e.clientY;
e.preventDefault();
e.stopPropagation();
draggableContainer.style.cursor = "move";
}, 0
);
window.addEventListener('mouseup',
draggableContainer.mu = function() {
pushed = 0;
draggableContainer.style.cursor = "pointer";
}, 0
);
window.addEventListener('mousemove',
draggableContainer.mm = function(e) {
if (pushed) {
var offsetLeft = - lastClientX + (lastClientX=e.clientX),
offsetTop = - lastClientY + (lastClientY=e.clientY);
scrollingContainer.scrollLeft -= offsetLeft;
scrollingContainer.scrollTop -= offsetTop;
}
}, 0
);
Please take a look at the demo: jsFiddle
The problem is, overlay div is not stretched across the whole iframe, it's only spread to visible div area:
Screenshot
It works fine though if I delete this
#scrolling_container {
position: relative;
}
But I need it to be like that because otherwise overlay div overlaps scrollbars and I can no longer use them.
Is there any cross-browser solution that prevents iframe from capturing mouse events so I could get rid of overlay div?

You can disable any mouse interaction with the iframe if you give it the pointer-events:none; property in CSS.

#drag_div {
background:transparent;
position:relative;
width:100%;
height:480px; /* your iframe height */
top:480px; /* your iframe height */
margin-top:-480px; /* your iframe height */
}
probably check this link
Disable mouse scroll wheel zoom on embedded Google Maps

Related

Using HTML Drag and Drop API to move container element smoothly

Trying to use the HTML Drag and Drop API to simply allow a user to reposition a container element while dragging from a drag handle.
I have the element moving and repositioning using drag and dragend but it's looking a bit glitchy - the element snaps back to it's previous position before re-rendering in its dropped position.
I know there's a simple(r) solution using mousedown but hoping to use the draggable API as my app has global mousedown listeners for another use case.
It seems just super poor performance, but probably I'm doing something totally wrong with the API here!
Thanks so much!
let dragHandle = document.getElementById("drag-handle");
let container = document.getElementById("drag-container");
dragHandle.addEventListener("drag", (event) => {
container.style.left = event.screenX + "px";
container.style.top = event.screenY + "px";
});
dragHandle.addEventListener("dragend", (event) => {
container.style.left = event.clientX + "px";
container.style.top = event.clientY + "px";
});
.drag-handle {
cursor: grab;
}
.container {
position: absolute;
top: 5px;
left: 5px;
}
<div class="container" id="drag-container">
<div
class="drag-handle"
id="drag-handle"
draggable="true">drag me</div>
<div>

ondragstart - How to remove animation?

Whenever the user starts dragging an element with draggable="true", the element has a translucent copy of the element you are dragging. Here is the example from W3Schools:
stop starting animation
Right side of the photo is important. That is the animation you get when you start dragging an element.
https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_ondrag
I have tried to use event.preventDefault(). However, the problem here is that this prevents onDrag from going at all while the element is moving and I need the data (mouse position and such) from onDrag.
It seems there are posts out there for how to stop the animation when you drop it but not start.
Just going off the example on the W3Schools site, I want the drag information without the ondragstart animation.
So if I modify the code by adding a preventDefault() on the ondragstart function:
function dragStart(event) {
console.log(event);
event.preventDefault(); //stops animation in right side of photo, but then won't let ondrag fire
event.dataTransfer.setData("Text", event.target.id);
}
function dragging(event) {
console.log(event);
document.getElementById("demo").innerHTML = "The p element is being dragged";
}
The animation you get when dragging goes away. However (as shown by my console.log) lines, the ondrag won't fire with this preventDefault on ondragstart. This is the information I need.
preventDefault inside ondrag doesn't stop that animation. Is this even possible?
SOLUTION
If anyone is wondering, I found what I needed to do in this case. You can set the image in javascript to a transparent one:
How to remove drag(Ghost) image?
so drag is still technically running but that ghostly image is gone. Wasn't thinking of right search terms.
In this case i would go for a different approach:
https://codepen.io/deibl31/pen/oNeXmPE?editors=1111
// HTML
<div id="myDiv">
</div>
// CSS
#myDiv {
position: absolute;
height: 100px;
width: 100px;
background: black;
color: white;
}
// JS
let myDiv = document.getElementById('myDiv');
let mouseDown = false;
let divPos = {x: 0, y: 0};
myDiv.addEventListener('mousedown', (event) => {
mouseDown = true;
});
window.addEventListener('mousemove', (event) => {
if (mouseDown) {
divPos.x = event.clientX;
divPos.y = event.clientY;
}
});
window.addEventListener('mouseup', (event) => {
if (mouseDown) {
myDiv.style.top = divPos.y + 'px';
myDiv.style.left = divPos.x + 'px';
}
mouseDown = false;
});
If anyone is wondering, I found what I needed to do in this case. You can set the image in JavaScript to a transparent one:
How to remove drag(Ghost) image?
so drag is still technically running but that ghostly image is gone. Wasn't thinking of right search terms.

How to make a draggable element stay at the new position when dropped (HTML5 not jQuery)?

I have just learned the basics of HTML5 draggable and droppable API. I do not know how to retain the dragged position at its dropped position. On dropping it changes its position.
Here is the basic HTML (relevant elements only):
onDragStart = function(ev) {
//...
}
drop_handler = function(ev) {
ev.preventDefault();
ev.target.appendChild(document.getElementById("id1"));
}
dragover_handler = function(ev) {
ev.preventDefault();
ev.dataTransfer.dropEffect = "move";
}
<div id="id1" draggable="true" ondragstart="onDragStart(event)" style="border:2px solid green; cursor:pointer;width:100px;height:50px;">Dragged Div</div>
<div id="id2" style="position:absolute;left:100px;top:200px;border:2px solid red; cursor:pointer;width:200px;height:200px;" ondrop="drop_handler(event)" ondragover="dragover_handler(event)">Drop Div
</div>
I want the dragged element to remain at its final position where it it is dropped. Any pointers will be appreciated.
As mentioned in my comment, <div id="id1" ...> still has the default positioning which is static. Once you append it to the dropDiv, it assumes normal document flow behavior. Because it's a block element, it goes underneath the text that is already there and fills the width of the block.
If you want it to stay exactly where it is when you drop it, you need to give it position: absolute and take into account how the mouse moved while dragging it on the screen. In the dragStart event, we capture the original coordinates of the dragDiv and account for where the mouse was inside relative to the top-left corner. When we drop the dragDiv into the dropDiv, we set the absolute positioning and account for how much the mouse moved during the drag.
Since dragDiv is now a child of dropDiv, we need our new top and left values to be relative to dropDiv's coordinates rather than the entire screen, so we subtract out dropDiv's top and left values. Note well that some of these methods may not take into account the borders around the elements which may make it look like it's a pixel or two off -- to fix that you can either subtract a one or two pixels in the calculation or give them box-sizing: border-box.
let offsetX;
let offsetY;
onDragStart = function(ev) {
const rect = ev.target.getBoundingClientRect();
offsetX = ev.clientX - rect.x;
offsetY = ev.clientY - rect.y;
};
drop_handler = function(ev) {
ev.preventDefault();
const left = parseInt(id2.style.left);
const top = parseInt(id2.style.top);
id1.style.position = 'absolute';
id1.style.left = ev.clientX - left - offsetX + 'px';
id1.style.top = ev.clientY - top - offsetY + 'px';
id2.appendChild(document.getElementById("id1"));
};
dragover_handler = function(ev) {
ev.preventDefault();
ev.dataTransfer.dropEffect = "move";
};
<div id="id1" draggable="true" ondragstart="onDragStart(event)" style="border:2px solid green; cursor:pointer;width:100px;height:50px;">Dragged Div</div>
<div id="id2" style="position:absolute;left:200px;top:50px;border:2px solid red; cursor:pointer;width:200px;height:200px;" ondrop="drop_handler(event)" ondragover="dragover_handler(event)">Drop Div
</div>

Css :hover although element not in front

im writing a website on which pictures, ordered in a grid, are shown. I want to make it possible to drag them around with the mouse and zoom in and out with the mouse wheel. This already works so far. here is what my code looks like:
var clicked = [0,0];
var pos = [0,0]; // <-- This ist the position of the image(s)
var dragging = false
var zoom = 1;
//this function is for zooming in and out
window.onmousewheel = function(event)
{
if (event.deltaY > 0)
{
zoom *= 0.9;
}
else
{
zoom *= 1.1;
}
update(0, 0);
}
window.onmousedown = function(event)
{
clicked = [event.clientX, event.clientY];
dragging = true;
}
window.onmousemove = function(event)
{
if (dragging == false){return;}
update((event.clientX-clicked[0]),(event.clientY-clicked[1]))
}
window.onmouseup = function(event)
{
pos = [pos[0] + (event.clientX-clicked[0]), pos[1] + (event.clientY-clicked[1])];
dragging = false;
}
function update(addX, addY) //<-- this function just updades the position of the images by using the zoom and pos variable and the addX and addY parameter
All of this works very fine. But it has one Bug: When i'm start draging while the mouse is directly over one of the images, then when i release the mouse the mouseup event is not triggered an so everything is still moving until you click again with your mouse. What i also do not like is that if you are dragging while the mouse is over one of the images, it shows this standard chrome browser image moving thing.
My Idea for solving this problems was, making a div with opacity: 0; in the front over everything, which fits the whole screen. looks like this:
(css)
#controller
{
position:absolute;
top:0;
left:0;
bottom:0;
right:0;
height:100%;
width:100%;
z-index: 999;
opacity: 0;
}
(html)
<div id="controller"></div>
And now it works fine. I also can drag when i start with the mouse direct over an image. But then i realized that now i can not make any click event or an simple css :hover over one of the images anymore, obviously because the invisible div is now in the front :(
Has anyone of you an idea how two solve this problem?
Put the onmouseup inside onmousedown:
window.onmousedown = function(event)
{
clicked = [event.clientX, event.clientY];
dragging = true;
window.onmouseup = function(event)
{
pos = [pos[0] + (event.clientX-clicked[0]), pos[1] + (event.clientY-clicked[1])];
dragging = false;
}
}

Flickering when using mouse in and mouse out

I am trying to create an effect where when mouse is moved over the image it should display a translucent black box on the image and display some details on top. These div's contain images and the problem is this mouseover and mouseout event are creating flickering of the black translucent div added on top.
Here is the code,
function addfocus(elem)
{
// getting dimensions of current div.
var currelem = document.getElementById(elem);
var left = currelem.offsetLeft;
var top = currelem.offsetTop;
var w = currelem.offsetWidth;
var h = currelem.offsetHeight;
// create a new div to match up these dimensions.
var ddiv = document.createElement("div");
ddiv.style.position = "absolute";
ddiv.style.top = top + "px";
ddiv.style.left = left + "px";
ddiv.style.width = w + "px";
ddiv.style.height = h + "px";
ddiv.style.backgroundColor= "rgba(0,0,0,0.5)";
document.body.appendChild(ddiv);
}
function rmvfoucs(elem)
{
document.body.removeChild(document.getElementById(elem));
}
When there is only text in the div, the flickering is not seen. Only when the image is included in the div, do I see the flickering.
Please help if you have any solution to this.
Thanks.
Your problem is that when you add your overlay it causes a mouseout event which removes the overlay. So when you move the mouse you constantly adds and removes the overlay.
But I'm not sure why you use Javascript for this. It can be accomplished in CSS, using :hover.
<div class="item">
<div class="info">...</div>
<img src="..." />
</div>
Show your overlay on hover
.info {
display:none;
}
.item:hover .info {
display:block;
}
See example: http://jsfiddle.net/jj8X6/

Categories

Resources