is there any way to get the dragged item position in the dragover/dragenter/dragleave events in terms of X and Y related to the page? i know i can get the mouse position by calling event.clientX or event.clientY, but i would like to know the position of the floating element that created by the drag (the one that can be set by event.dataTransfer.setDragImage() function)
for example this code will print the mouse location when dragging, and not the real offset of the floating element:
function dragOver(event) {
console.log(event.clientX
});
With help of jQuery library you can achieve it,You can use console to print values, just to show you I'm printing positions on screen.
$('#dragMe').draggable(
{
containment: $('body'),
drag: function(){
var position = $(this).position();
var xPos = position.left;
var yPos = position.top;
$('#positionX').text('positionX: ' + xPos);
$('#positionY').text('positionY: ' + yPos);
},
accept: '#dragMe',
over : function(){
$(this).animate({'border-width' : '5px',
'border-color' : '#0f0'
}, 500);
$('#dragThis').draggable('option','containment',$(this));
}
});
#dragMe {
width: 10em;
height: 6em;
padding: 0.5em;
border: 4px solid #ccc;
border-radius: 0 2em 2em 2em;
background-color: #fff;
background-color: rgba(255,255,255,0.5);
}
#dropMe {
width: 12em;
height: 12em;
padding: 0.5em;
margin: 0 auto;
}
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div id="dragMe">
<p>DRAG ME</p>
<ul>
<li id="positionX"></li>
<li id="positionY"></li>
</ul>
</div>
<div id="dropMe"></div>
Related
I'm trying to get my png to move to the mouse click position when the user clicks within the container but I cant get the png to respond. I'm following this tutorial (https://www.youtube.com/watch?v=b4GwvdhrEQg), and stuck on the first test. my target doesnt respond to clicks at all.
Please help
var theGirl = document.querySelector("#girl");
var container = document.querySelector("#floor");
container.addEventListener("click", getClickPosition, false);
function getClickPosition(e) {
var xPosition = e.clientX - (theGirl.offsetWidth / 2);
var yPosition = e.clientY; - (theGirl.offsetHeight / 2)
var translate3dValue = "translate3d(" + xPosition + "px" + yPosition + "px, 0)";
theGirl.style.transform = translate3dValue;
}
#floor {
width: 700px;
height: 600px;
cursor: pointer;
overflow: visible;
border: 10px #EDEDED solid;
}
#girl {
height: 450px;
width: 200px;
border: 15px red solid;
transform: translate3d(50px, 50px, 0);
}
<body>
<div id="floor">
<div>
<img src="girl.png" id="girl"> </div>
</div>
Change #girl's position to absolute. I think it works after that.
In my web app, there is a draggable element.
I need to set the left position of this element when the element reaches a certain limit while dragging.
Using jQuery draggable widget, I have access to the position of the element:
function drag(e, ui) {
console.log(ui.position.left);
}
Let say my left attribute is setted to 1100px, I need to set it to 500px and this, without stopping the dragging.
I have three functions: dragStart, drag, and gradEnd.
Currently, I managed to get only one result: when setting ui.position.left = 500; on the drag function (using a condition), the left position is set to 500 but of course, the element is then stuck at 500px. The reason is that every time the drag function is triggered, the left position is setted to 500.
If the code runs only once the line ui.position.left = 500; the position left attribute is set to 500, but directly reset to 1100.
How can I set the left attribute once and for all?
$("#divId").draggable({
drag: drag,
})
function drag(e, ui) {
if (ui.position.top > 50) {
ui.position.left = 100;
}
}
#divId {
height: 70px;
background-color: white;
border: 4px solid #000000;
text-align: center;
color: black;
cursor: grab;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div id="divId">
Bubble
</div>
I am not sure how jQuery Draggable handles things under the hood, but even after setting ui.position.left = 100, it does not register in the event until after dragging has stopped - that is why I opted to check the actual CSS property of the element that is being targeted.
I have also provided an example (closure/functional based) which demonstrates how to handle this without having to check CSS..
First example:
$("#divId").draggable({
drag: drag
});
function drag(e, ui) {
if (ui.position.top > 50) {
$("#container").css('padding-left', '100px');
$(this).css('left', '0px');
}
if (ui.position.left < 0) {
ui.position.left = 0
}
}
#divId {
height: 70px;
background-color: white;
border: 4px solid #000000;
text-align: center;
color: black;
width: 300px;
cursor: grab;
}
#container {
height: 100vh;
width: 1000px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div id="container">
<div id="divId">
Bubble
</div>
</div>
Second example, more of a 'closure based functional approach': does not require you to check CSS..
$("#divId").draggable({
drag: drag()
});
function drag(e, ui) {
let TRIGGER = false, TOP_THRESHOLD = 50, LEFT_POSITION = 100;
return function(e, ui) {
if (TRIGGER) {
ui.position.left = LEFT_POSITION;
} else if (ui.position.top > TOP_THRESHOLD) {
TRIGGER = true;
ui.position.left = LEFT_POSITION;
}
}
}
#divId {
height: 70px;
background-color: white;
border: 4px solid #000000;
text-align: center;
color: black;
cursor: grab;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div id="divId">
Bubble
</div>
I have this code:
<template>
<div class="chart"
v-bind:style="chartStyleObject"
v-on:mousedown.left="initHandleMousedown($event)"
v-on:mouseup.left="initHandleMouseup()"
v-on:mouseout="initHandleMouseup()">
<div class="chartContent">
</div>
<!-- <div class="chartContent"> end -->
</div>
<!-- <div class="chart"> end -->
</template>
<script>
import axios from 'axios';
export default{
created () {
},
data () {
return {
ticket: null,
chartStyleObject: {
width: '500px',
widthWrapper: '1600px',
heightWrapper: '500px',
height: '247px',
marginTop: '15px',
marginRight: '0px',
marginBottom: '0px',
marginLeft: '15px',
},
XCoord: null,
YCoord: null,
}
},
methods: {
initHandleMousedown(event) {
this.startMousedownXCoord = event.clientX;
this.startMousedownYCoord = event.clientY;
this.XCoord = event.clientX;
this.YCoord = event.clientY;
console.log('XCoord', this.XCoord);
console.log('YCoord', this.YCoord);
window.addEventListener('mousemove', this.initHandleMouseMove);
},
initHandleMouseMove(event) {
this.XCoord = event.clientX;
this.YCoord = event.clientY;
console.log('XCoord', this.XCoord);
console.log('YCoord', this.YCoord);
},
initHandleMouseup() {
window.removeEventListener('mousemove', this.initHandleMouseMove);
},
},
}
</script>
<style scoped>
.chart{
position: relative;
border-radius: 10px;
padding: 27px 10px 10px 10px;
background-color: #45788b;
box-sizing: border-box;
cursor: move;
}
.chart .chartContent{
position: relative;
top: 0;
left: 0;
height: 100%;
width: 100%;
margin: 0 0 0 0;
background-color: #2f2c8b;
}
</style>
HTML design consists of 2 blocks:
(parent and child)
The event is tied to the parent tag `<div class =" chart ">`
Also, the parent block has padding on all 4 sides:
If you click on the parent block and drive with the mouse (holding the button pressed) without affecting the padding space, the mousemove event will fire without problems.
But as soon as the mouse cursor touches the padding territory, the event ceases to function.
If you click on the padding, the event also works correctly - but it stops working if I move the mouse cursor over the block space outside the paddings (internal space)
Question:
Why is this happening - and is this behavior normal for js + nuxt.js?
I can't exactly follow your descriptions of the various regions of the page but I can have a go at explaining what I think you're seeing.
The key to this is that you have a mouseout listener that removes your mousemove listener. The mouseout event propagates, which means it will fire even if the mouseout occurred on a child element. Contrast with mouseleave which will only fire if the event occurs on the element itself.
The example below illustrates how a mouseout listener will fire even if the mouse cursor doesn't leave the root element. Just moving the cursor outside a child is sufficient.
document.getElementById('outer').addEventListener('mouseout', () => {
document.getElementById('out').innerHTML += 'mouseout\n'
})
div {
border: 1px solid;
display: inline-block;
padding: 20px;
}
<div id="outer">
<div></div>
</div>
<pre id="out"></pre>
I suspect that when you observe the event ceasing to function what is actually happening is that a mouseout event is occurring and that is removing the mousemove listener.
skirtle answer is correct. I am only providing this answer to illustrate how to do it using your own code. The only line I changed was this v-on:mouseleave="initHandleMouseup(). Notice I changed it to mouseout to mouseleave.
To summarize:
mouseleave is fired once per element regardless of its children
hover.
mouseout is fired every time the element abandoned (whether
moving the mouse away or hovering over its children).
new Vue({
el: "#app",
template: `
<div class="chart"
v-bind:style="chartStyleObject"
v-on:mousedown.left="initHandleMousedown($event)"
v-on:mouseup.left="initHandleMouseup()"
v-on:mouseleave="initHandleMouseup()">
<div class="chartContent">
</div>
<!-- <div class="chartContent"> end -->
</div>
<!-- <div class="chart"> end -->
`,
created: function() {},
data() {
return {
ticket: null,
chartStyleObject: {
width: '500px',
widthWrapper: '1600px',
heightWrapper: '500px',
height: '247px',
marginTop: '15px',
marginRight: '0px',
marginBottom: '0px',
marginLeft: '15px',
},
XCoord: null,
YCoord: null,
}
},
methods: {
initHandleMousedown: function(event) {
this.startMousedownXCoord = event.clientX;
this.startMousedownYCoord = event.clientY;
this.XCoord = event.clientX;
this.YCoord = event.clientY;
console.log('XCoord', this.XCoord);
console.log('YCoord', this.YCoord);
window.addEventListener('mousemove', this.initHandleMouseMove);
},
initHandleMouseMove: function(event) {
this.XCoord = event.clientX;
this.YCoord = event.clientY;
console.log('XCoord', this.XCoord);
console.log('YCoord', this.YCoord);
},
initHandleMouseup: function() {
window.removeEventListener('mousemove', this.initHandleMouseMove);
}
}
});
.chart {
position: relative;
border-radius: 10px;
padding: 27px 10px 10px 10px;
background-color: #45788b;
box-sizing: border-box;
cursor: move;
}
.chart .chartContent {
position: relative;
top: 0;
left: 0;
height: 100%;
width: 100%;
margin: 0 0 0 0;
background-color: #2f2c8b;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id='app'></div>
To see the different between mouseout/mouseover vs mouseenter/mouseleave events see this demo (taken from jQuery documentation) :
var i = 0;
$("div.overout")
.mouseout(function() {
$("p", this).first().text("mouse out");
$("p", this).last().text(++i);
})
.mouseover(function() {
$("p", this).first().text("mouse over");
});
var n = 0;
$("div.enterleave")
.on("mouseenter", function() {
$("p", this).first().text("mouse enter");
})
.on("mouseleave", function() {
$("p", this).first().text("mouse leave");
$("p", this).last().text(++n);
});
div.out {
width: 40%;
height: 120px;
margin: 0 15px;
background-color: #d6edfc;
float: left;
}
div.in {
width: 60%;
height: 60%;
background-color: #fc0;
margin: 10px auto;
}
p {
line-height: 1em;
margin: 0;
padding: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="out overout">
<p>move your mouse</p>
<div class="in overout">
<p>move your mouse</p>
<p>0</p>
</div>
<p>0</p>
</div>
<div class="out enterleave">
<p>move your mouse</p>
<div class="in enterleave">
<p>move your mouse</p>
<p>0</p>
</div>
<p>0</p>
</div>
I have a table full of data that tends to be larger than the screen.
I put the table in a DIV and set the "overflow" to "auto" in CSS
div.scrolling-comps {
width : 970px;
height : 800px;
overflow : auto;
}
So the DIV can be scrolled up/down, left right using the browser's built-in scroll bars.
Problem is, the table can be WAAY bigger than the screen. And while the mousewheel will scroll it up/down, scrolling left/right is a pain in the hooch.
So, looking for a javascript/jquery or CSS way to scroll the div NATURALLY.
In other words, when someone viewing the huuuge table moves their mouse to the right, the DIV goes to the left (thus scrolling without using the scroll bars).
Something similar to this, but instead of following the mouse, the div would move opposite the mouse...
window.onload = function() {
var bsDiv = document.getElementById("box-shadow-div");
var x, y;
// On mousemove use event.clientX and event.clientY to set the location of the div to the location of the cursor:
window.addEventListener('mousemove', function(event) {
x = event.clientX;
y = event.clientY;
if (typeof x !== 'undefined') {
bsDiv.style.left = x + "px";
bsDiv.style.top = y + "px";
}
}, false);
}
#box-shadow-div {
position: fixed;
width: 1000px;
height: 800px;
border-radius: 0%;
background-color: black;
box-shadow: 0 0 10px 10px black;
top: 49%;
left: 48.85%;
}
<div id="box-shadow-div"></div>
The example you have about using the mouse position is interesting... But it is not what you need to achieve what you described.
In fact... What you need to know is the "ratio" between the div wrapping the table and its scrollWidth
Then, using the X position of the mouse, you can apply a scroll to the div in order to make it "move".
I used jQuery to do it using very few lines.
// Just to fake a big table
var fakeCell = $("<td>Some data</td>");
for(i=0;i<100;i++){
var fakeRow = $("<tr>");
for(k=0;k<50;k++){
fakeRow.append(fakeCell.clone().append(" "+k));
}
$("#test").append(fakeRow.clone());
}
// ---------------------------------------------------
// Calculate the "ratio" of the box-div width versus its scrollable width
var ratio = $("#box-div")[0].scrollWidth / $("#box-div").width();
console.log("Ratio: "+ratio);
// Scroll left/rigth based on mouse movement
$(window).on("mousemove", function(e){
var X = ratio * e.pageX;
// Scroll the div using the mouse position multiplyed by the ratio
$("#box-div").scrollLeft(X);
});
td{
white-space: nowrap;
border: 1px solid black;
}
#box-div{
overflow:auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div id="box-div">
<table id="test">
</table>
</div>
</body>
So while the user moves the mouse over the div's width, you apply a scroll multiplied by the ratio... The effect is the user can scroll it all from the most left to most right ends easilly.
How about this?
wrap a table in div (i.e. parent-div) which is relatively positioned
Give position absolute to the target div.
And change left & top position of target div on mousemove event.
window.onload = function() {
var bsDiv = document.getElementById("box-shadow-div");
var x, y;
// On mousemove use event.clientX and event.clientY to set the location of the div to the location of the cursor:
window.addEventListener('mousemove', function(event) {
x = event.clientX;
y = event.clientY;
if (typeof x !== 'undefined') {
bsDiv.style.left = -x + "px";
bsDiv.style.top = -y + "px";
}
}, false);
}
.parent-div {
position: relative;
}
#box-shadow-div {
position: absolute;
width: 1000px;
height: 800px;
border-radius: 0%;
background-color: black;
box-shadow: 0 0 10px 10px black;
top: 0;
left: 0;
}
<div class="parent-div">
<div id="box-shadow-div"></div>
</div>
Have you tried changing x to -x? this will technically "invert" the effect.
window.onload = function() {
var bsDiv = document.getElementById("box-shadow-div");
var x, y;
// On mousemove use event.clientX and event.clientY to set the location of the div to the location of the cursor:
window.addEventListener('mousemove', function(event) {
x = event.clientX;
y = event.clientY;
if (typeof x !== 'undefined') {
bsDiv.style.left = -x + "px";
bsDiv.style.top = -y + "px";
}
}, false);
}
#box-shadow-div {
position: fixed;
width: 1000px;
height: 800px;
border-radius: 0%;
background-color: black;
box-shadow: 0 0 10px 10px black;
top: 49%;
left: 48.85%;
}
<div id="box-shadow-div"></div>
Please run the snippet and drag you mouse over the bar to make it red.
If you drag the mouse very slowly, you will fill it red, but if you move it fast, there will be white holes in it.
How to fix it? (the white holes)
I want to make a bar divided into 500 parts and if you hover it, it becomes red and being able to drag fast and fill it without holes.
Any help appreciated :)
$(function() {
var line = $("#line");
for ( var i = 0; i < 500; i++) {
line.append('<div class="tile" id="t'+(i+1)+'"></div>');
}
var tile = $(".tile");
tile.hover (
function() { //hover-in
$(this).css("background-color","red");
},
function() { //hover-out
}
);
});
#line{
height: 50px;
background-color: #000;
width: 500px;
}
.tile {
height: 50px;
float: left;
background-color: #ddd;
width: 1px;
}
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js"></script>
<div id="line"></div>
With your design one way would be to iterate over the first to your current hovered element and fill it, which would lead no spaces. That said you may want to consider using the HTML5 Canvas and drawing a rectangle from 0 to your mouse position, which will perform significantly faster.
$(function() {
var line = $("#line");
for ( var i = 0; i < 500; i++) {
line.append('<div class="tile" id="t'+(i+1)+'"></div>');
}
var tile = $(".tile");
tile.hover (
function() { //hover-in
var self = this;
$("#line").children().each(function(){
$(this).css("background-color","red");
if(this == self) return false;
});
},
function() { //hover-out
}
);
});
#line{
height: 50px;
background-color: #000;
width: 500px;
}
.tile {
height: 50px;
float: left;
background-color: #ddd;
width: 1px;
}
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js"></script>
<div id="line"></div>
Edit
Below is an example doing the same task but using the HTML 5 Canvas:
$("#line").mousemove(function(e){
var canvas = $(this)[0];
var ctx = canvas.getContext("2d");
var rect = canvas.getBoundingClientRect()
var x = e.clientX - rect.left;
ctx.fillStyle="red";
ctx.fillRect(0, 0, x, canvas.height);
});
#line{ background-color: #ddd; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="line" width=500 height=50 ></canvas>
This is another approach with nextUntil to select siblings..
$(function() {
var line = $("#line");
for ( var i = 0; i < 500; i++) {
line.append('<div class="tile" id="t'+(i+1)+'"></div>');
}
var tile = $(".tile");
line.on( 'mouseover', function(ev){
$('.tile').first().nextUntil( $('.tile').eq(ev.pageX) ).css("background-color","red");
});
line.on( 'mouseleave', function(ev){
$('.tile').css("background-color","#ddd");
});
});
#line{
height: 50px;
background-color: #000;
width: 500px;
}
.tile {
height: 50px;
float: left;
background-color: #ddd;
width: 1px;
}
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js"></script>
<div id="line"></div>
Another solution makes use of jQuery's mousemove method. This allows the bar to go both forward and backwards, simply following the cursors position.
This detects movement inside of the div, then I calculate the position of the cursor within the div as a percentage and apply it as the width of the red bar.
$( ".bar" ).mousemove(function( event ) {
var xCord = event.pageX;
xPercent = (xCord + $('.pct').width()) / $( document ).width() * 100;
$('.pct').width(xPercent+'%');
});
.bar{
background:'#999999';
width:50%;
height:50px;
}
.pct{
height:100%;
background:red;
width:0%;
}
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js">
</script>
<div class="bar" style="background:#999999">
<div class="pct"></div>
</div>