I'm trying to make a sort of drag and drop puzzle website using uniform square images, and I've written the drag code to drag individual images by their <img> element.
However I noticed that while dragging an <img> element over another element with addEventListener("mousenter", function () {//code};) attached, the mouseenter event doesn't fire. If I move my mouse over the element without dragging the image, the event fires as normal.
Does anyone have any ideas on how to fix this problem? My only guess atm is that the <img> element is blocking the listener from seeing the mouse.
var dragImg = document.querySelector(".images img");
dragImg.addEventListener("mousedown", function () {
console.log("mousedown detected " + dragImg.clientHeight);
dragImg.setAttribute("id", "drag");
dragging = true;
});
dragImg.addEventListener("mousemove", function (event) {
if (dragging) {
dragImg.style.top = (event.clientY - dragImg.clientHeight/2) + "px";
dragImg.style.left = (event.clientX - dragImg.clientWidth/2) + "px";
}
});
dragImg.addEventListener("mouseup", function () {
console.log("mouseup detected");
dragging = false;
//reset position if not in clipboard
dragImg.removeAttribute("id");
dragImg.style.top = "";
dragImg.style.left = "";
});
//Clipboard behavior - This listener doesn't fire when dragging an img?
var clipboard = document.querySelector(".clipboard");
clipboard.addEventListener("mouseover", function () {
if (dragging) {
console.log("mouse entered clipboard!");
clipboard.style.backgroundColor = "red";
}
});
#drag {
position: absolute;
}
The problem is that the mouse never hover the .clipboard because the image always below the pointer.
The simple solution is to add pointer-events:none; (not supported on older browsers).
var dragImg = document.querySelector(".images img");
var dragging = false;
dragImg.addEventListener("mousedown", function (event) {
event.stopPropagation();
console.log("mousedown detected " + dragImg.clientHeight);
dragImg.setAttribute("id", "drag");
dragging = true;
document.addEventListener('mousedown', function documentMouseDown(){
if (dragging) {
dragImg.removeAttribute("id");
dragging = false;
document.removeEventListener('mousedown', documentMouseDown);
}
});
});
document.addEventListener("mousemove", function (event) {
if (dragging) {
dragImg.style.top = (event.clientY - dragImg.clientHeight/2) + "px";
dragImg.style.left = (event.clientX - dragImg.clientWidth/2) + "px";
}
});
dragImg.addEventListener("mouseup", function () {
console.log("mouseup detected");
dragging = false;
//reset position if not in clipboard
dragImg.removeAttribute("id");
dragImg.style.top = "";
dragImg.style.left = "";
});
//Clipboard behavior - This listener doesn't fire when dragging an img?
var clipboard = document.querySelector(".clipboard");
clipboard.addEventListener("mouseover", function () {
if (dragging) {
console.log("mouse entered clipboard!");
clipboard.style.backgroundColor = "red";
}
});
#drag {
position: absolute;
pointer-events:none;
}
.clipboard {
width:200px;
height:200px;
background:green;
}
img {
-webkit-user-select:none;
}
<div class="clipboard"></div>
<div class="images">
<img src="http://i.stack.imgur.com/NghNQ.jpg" />
</div>
http://jsbin.com/hugewi/edit?html,css,js
Related
I'm using the script below (adapted from https://htmldom.dev/drag-to-scroll/) which enables a website to be scrolled by dragging it. Additionally, I remove the default draggability for links and images via css such that the page can be dragged when the cursor is currently positioned on these elements.
document.addEventListener('DOMContentLoaded', () => {
let dragging; const pos = {};
const onClick = (e) => {
if(!dragging)
return;
e.preventDefault(); // somehow does not work: why?
e.stopImmediatePropagation();
};
const onMouseMove = (e) => {
dragging = true;
window.scroll(0, pos.top - (e.clientY - pos.y));
};
const onMouseUp = (e) => {
dragging = false;
e.target.removeEventListener('mousemove', onMouseMove);
e.target.removeEventListener('mouseup', onMouseUp);
e.target.removeEventListener('click', onClick);
};
const onMouseDown = (e) => {
pos.top = window.scrollY;
pos.y = e.clientY;
e.target.addEventListener('mousemove', onMouseMove);
e.target.addEventListener('mouseup', onMouseUp);
e.target.addEventListener('click', onClick);
};
document.addEventListener('mousedown', onMouseDown);
});
a, img {
user-drag: none;
-webkit-user-drag: none;
}
<div style="height:200vh; background:lightblue; padding:1em;">
<h1>Drag to scroll me</h1>
Dragging this link should NOT open the website (but does)
</div>
Problem
Preventing the default action (opening the link) does not work somehow. How can it be canceled in case of dragging?
The solution was a bit more complex than I thought, perhaps someone else has a better one. It requires an additional global function preventClick which prevents the event default and propagation.
The rest of the code looks like this now:
$(() => {
/*
require 'preventClick()';
*/
//------------------------------------------------------------------------------------
// $
//------------------------------------------------------------------------------------
const
$body = $('body'),
$head = $('head')
;
//------------------------------------------------------------------------------------
// var
//------------------------------------------------------------------------------------
const
pos = {}
;
let
clone
;
//------------------------------------------------------------------------------------
// ()
//------------------------------------------------------------------------------------
const
//------------------------------------------
onMouseMove = (e) => {
//------------------------------------------
window.scroll(0, pos.top - (e.originalEvent.clientY - pos.y));
},
//------------------------------------------
onMouseUp = function(e){
//------------------------------------------
$body.css('cursor', 'grab');
$(this)
.off('mousemove', null, onMouseMove)
.off('mouseup', null, onMouseUp)
;
}
;
//------------------------------------------------------------------------------------
// Events
//------------------------------------------------------------------------------------
$(document)
//------------------------------------------
.mousedown(function(e){
//------------------------------------------
$body.css('cursor', 'grabbing');
pos.top = window.scrollY;
pos.y = e.originalEvent.clientY;
$(this)
.one('dragstart', function(e){
clone = $(e.target).clone(true);
$(e.target)
.attr('onclick', 'preventClick(event)')
.one('click', function(e){
$(this).attr('onclick', clone.attr('onclick') || '');
})
;
})
.mousemove(onMouseMove)
.mouseup(onMouseUp)
;
})
;
$body
//------------------------------------------
.css('cursor', 'grab')
//------------------------------------------
;
//------------------------------------------------------------------------------------
// >>
//------------------------------------------------------------------------------------
$head.append(`<style>
a, img {
user-drag: none;
-webkit-user-drag: none;
}
</style>`);
});
I have a little script running so i can scroll trough a div with the mousedown option. Unfortunately it resets on each click and i can't quite figure out why it is doing this.
<script>
$(function () {
var clicked = false, clickX;
$("#gallery").on({
'mousemove': function(e) {
clicked && updateScrollPos(e);
},
'mousedown': function(e) {
clicked = true;
clickX = e.pageX;
},
'mouseup': function() {
clicked = false;
$('html').css('cursor', 'auto');
}
});
var updateScrollPos = function(e) {
$('#gallery').scrollLeft($(window).scrollLeft() + (clickX - e.pageX));
}
});
</script>
I am assuming it has something to do with
clickX = e.pageX;
$('#gallery').scrollLeft($(window).scrollLeft() + (clickX - e.pageX));
Why am I? because : "Returns the horizontal coordinate of the event relative to whole document."
So I am assuming it takes the original position when you click but it doesnt update when you actually scroll this. Anyone has a fix for this?
http://jsfiddle.net/fLr4d7kt/6/
We have fixed it like this :
$(function () {
var scroll = 0;
$(function () {
var clicked = false, clickX;
$("#gallery").on({
'mousemove': function(e) {
clicked && updateScrollPos(e);
},
'mousedown': function(e) {
clicked = true;
clickX = e.pageX;
scroll = $('#gallery').scrollLeft();
},
'mouseup': function() {
clicked = false;
$('html').css('cursor', 'auto');
}
});
var updateScrollPos = function(e) {
$('#gallery').scrollLeft(scroll + (clickX - e.pageX));
}
});
});
js: http://jsfiddle.net/fLr4d7kt/10/
I am developing an web application where I am trying simulate a popup window using tags , for style purpose. I done this with this javascript code:
<script>
function handleClick(url){
document.getElementById("results").style.display = 'block';
document.getElementById("about").innerHTML='<object type="text/html" data="'+url+'" ></object>';
}
function cleanDiv() {
document.getElementById("results").style.display = 'none';
document.getElementById("about").innerHTML=' ';
}
</script>
associated to this html code:
<section class="about" id="results">
<div align="right">Fechar</div>
<div id="about" algin="center"></div>
</section>
and the style is on my css file.
I have almost all what I want, but I wish this "popup window" don't stay fixed in a unique position on the page, and the user could move it around with the mouse.
Someone knows how to make this with javascript/html/css only?
You are looking for the HTML5 draggable attribute and events. Make the element draggable by setting draggable="true" and ondragstart="dragElem(event)". Then write your code in function dragElem(ev) { }. See W3Schools
After more search, I ended with this code, from site http://waseemblog.com/42/movable-div-using-javascript.html
html:
<section class="about" id="results" style="left: 183px; top: 111px;" onMouseDown="dragStart(event, 'results');">
<div align="right">X</div>
<div id="content" align="center"></div>
</section>
javascript:
function getID(id)
{
return document.getElementById(id);
}
// Global object to hold drag information.
var dragObj = new Object();
function dragStart(event, id) {
var x, y;
dragObj.elNode = getID(id);
// Get cursor position with respect to the page.
try {
x = window.event.clientX + document.documentElement.scrollLeft
+ document.body.scrollLeft;
y = window.event.clientY + document.documentElement.scrollTop
+ document.body.scrollTop;
}
catch (e) {
x = event.clientX + window.scrollX;
y = event.clientY + window.scrollY;
}
// Save starting positions of cursor and element.
dragObj.cursorStartX = x;
dragObj.cursorStartY = y;
dragObj.elStartLeft = parseInt(dragObj.elNode.style.left, 10);
dragObj.elStartTop = parseInt(dragObj.elNode.style.top, 10);
if (isNaN(dragObj.elStartLeft)) dragObj.elStartLeft = 0;
if (isNaN(dragObj.elStartTop)) dragObj.elStartTop = 0;
// Capture mousemove and mouseup events on the page.
try {
document.attachEvent("onmousemove", dragGo);
document.attachEvent("onmouseup", dragStop);
window.event.cancelBubble = true;
window.event.returnValue = false;
}
catch (e) {
document.addEventListener("mousemove", dragGo, true);
document.addEventListener("mouseup", dragStop, true);
event.preventDefault();
}
}
function dragGo(event) {
var x, y;
// Get cursor position with respect to the page.
try {
x = window.event.clientX + document.documentElement.scrollLeft
+ document.body.scrollLeft;
y = window.event.clientY + document.documentElement.scrollTop
+ document.body.scrollTop;
}
catch (e) {
x = event.clientX + window.scrollX;
y = event.clientY + window.scrollY;
}
// Move drag element by the same amount the cursor has moved.
var drLeft = (dragObj.elStartLeft + x - dragObj.cursorStartX);
var drTop = (dragObj.elStartTop + y - dragObj.cursorStartY);
if (drLeft > 0)
{
dragObj.elNode.style.left = drLeft + "px";
}
else
{
dragObj.elNode.style.left = "1px";
}
if (drTop > 0)
{
dragObj.elNode.style.top = drTop + "px";
}
else
{
dragObj.elNode.style.top = "1px";
}
try {
window.event.cancelBubble = true;
window.event.returnValue = false;
}
catch(e){
event.preventDefault();
}
}
function dragStop(event) {
// Stop capturing mousemove and mouseup events.
try {
document.detachEvent("onmousemove", dragGo);
document.detachEvent("onmouseup", dragStop);
}
catch (e) {
document.removeEventListener("mousemove", dragGo, true);
document.removeEventListener("mouseup", dragStop, true);
}
}
It can be bigger than your counterpart using jquery, but I guess it works fine in most browsers available today.
I am trying to make a div draggable using jQuery, but without jQuery UI, I can't figure out why I get an error if when I use the e.target.id, the value in this field at some point is empty or null.
If I hard code the Id in the function it works pretty well, what am I missing here?
I appreciate your help.
This is my code:
<div id="Div1" style="width: 100px; background-color: red">test</div>
$(document).ready(function () {
dragObject.init("Div1");
});
jQdrag.js
var dragObject = (function () {
var init = function (dragObj) {
addListeners(dragObj);
};
var addListeners = function (dragObj) {
document.getElementById(dragObj).addEventListener('mousedown', mouseDown, false);
window.addEventListener('mouseup', mouseUp, false);
};
mouseDown = function (e) {
window.addEventListener('mousemove', divMove, true);
};
mouseUp = function () {
window.removeEventListener('mousemove', divMove, true);
};
divMove = function (e) {
debugger
//var div = document.getElementById("Div1");
var div = document.getElementById(e.target.id); //ERROR
div.style.position = 'absolute';
div.style.top = e.clientY + 'px';
div.style.left = e.clientX + 'px';
};
return {
init: function (dragObj)
{
init(dragObj);
}
};
})();
I'm fairly new to JavaScript, so any help would be awesome!
I created this small block of code that let's me grab a div and drag it around. I assign the "dragme" id to the div and all is fine and dandy. The problem is that if I replace that div from my html and put an img element instead (obviously assigning the "dragme" id to the img), things don't work as expected.
When I click to drag the img, it actually moves for about 3 or 4 pixels then it freezes until I lift the mouse button (mouseup).
Is there some property or characteristic that would prevent the img element from acting the same way as the div does?
var isClicked = false;
var startClientX = 0;
var startClientY = 0;
var startLeft = 0;
var startTop = 0;
window.addEventListener("load", addListeners, true);
function addListeners()
{
document.getElementById("dragme").addEventListener("mousedown", mouseIsDown, false);
document.getElementById("dragme").addEventListener("mouseup", mouseIsUp, false);
window.addEventListener("mousemove", moveImage, false);
function mouseIsDown(e)
{
if (isClicked == false)
{
isClicked = true;
startClientX = e.clientX;
startClientY = e.clientY;
startLeft = document.getElementById("dragme").offsetLeft;
startTop = document.getElementById("dragme").offsetTop;
}
}
function mouseIsUp()
{
if (isClicked == true)
{
isClicked = false;
}
}
function moveImage(e)
{
if (isClicked == true)
{
imageLeftDif = e.clientX - startClientX;
imageTopDif = e.clientY - startClientY;
var newLeftPos = (startLeft + imageLeftDif) + "px";
var newTopPos = (startTop + imageTopDif) + "px";
document.getElementById("dragme").style.left = newLeftPos;
document.getElementById("dragme").style.top = newTopPos;
}
}
}
This fixed the problem (answer provided as a comment by syazdani):
I'd venture to say that the built in browser drag and drop for images
is kicking in. Try e.preventDefault and return false in the mousedown
handler. – syazdani Dec 2 '12 at 17:26