I'm trying to snap an element below another element and make it stay put. The function is ok, but it runs every time I move it 10px. So it moves 10px even further each time..
function move_box() {
if(el.offsetLeft = 10){
console.log('moved the element 10px to the left!');
el.setAttribute('class', 'snap_in'); // class with css (transform: translateY(10px)
let not_called = false;
console.log(not_called);
} else if (not_called = false){
console.log(not_called);
el.setAttribute('class', 'dont_move'); //class with css transform:translateY(0px);
}
}
}
use '==' instead of =
you are assigning not comparing
const el = document.querySelector('.item');
let not_called;
el.addEventListener('mousedown', mousedown);
function mousedown(e){
window.addEventListener('mousemove', mousemove);
window.addEventListener('mouseup', mouseup);
let prevX = e.clientX;
let prevY = e.clientY;
function mousemove(e) {
let newX = prevX - e.clientX;
let newY = prevY - e.clientY;
const rect = el.getBoundingClientRect();
el.style.left = rect.left - newX + "px";
el.style.top = rect.top - newY + "px";
prevX = e.clientX;
prevY = e.clientY;
}
function mouseup() {
window.removeEventListener('mousemove', mousemove);
window.removeEventListener('mouseup', mouseup);
console.log(el.offsetLeft);
console.log(el.offsetTop);
//let leftoffset = el.offsetLeft;
if (not_called == false){
console.log(not_called);
el.setAttribute('class', 'item');
}
else if(el.offsetLeft >= 180 && el.offsetLeft <= 220){
console.log('yes!');
el.setAttribute('class', 'snap_in');
not_called = false;
console.log(not_called);
}
}
}
Related
I made a text box and boxes on the corners for resizing. The first time I drag, it works perfectly fine, but after the 1st time, the dragging amount seems to multiply. (Don't mind the position of the dragging nodes). If you drag once, it scales fine with the mouse. It seems as if every time after that, when you drag, it scales farther and farther from the user's mouse, causing an 'uncontrollable' scale. I reset the values of the prevX and prevY values at the end of the move function. I'm not sure if that's the issue though. The issue, I believe, is with the scaling with getBoundingClientRect() in the resize portion. Moving the textbox, however, works perfectly fine. Here is my code:
var textBox = document.querySelector(".text-box");
var textArea = document.querySelector('.text-field');
textArea.focused = false;
textBox.addEventListener('mousedown', mousedown);
let isResizing = false;
let isTyping = false;
textArea.addEventListener('dblclick', type)
function type(){
if (!isTyping){
isTyping = true;
textArea.style.cursor = 'text';
}else {
isTyping = false;
textArea.style.cursor = 'default';
}
}
document.body.onclick = function(e){
if (e.target != textArea){
isTyping = false;
e.target.style.cursor = 'default';
}
}
function mousedown(e){
if (e.target == textArea){
e.target.style.cursor = 'default';
}
window.addEventListener('mousemove', mousemove);
window.addEventListener('mouseup', mouseup);
let prevX = e.clientX;
let prevY = e.clientY;
function mousemove(e){
if(!isResizing && !isTyping){
let newX = prevX - e.clientX;
let newY = prevY - e.clientY;
const rect = textBox.getBoundingClientRect();
textBox.style.left = rect.left - newX + "px";
textBox.style.top = rect.top - newY + "px";
prevX = e.clientX;
prevY = e.clientY;
}
}
function mouseup(){
window.removeEventListener('mousemove', mousemove);
window.removeEventListener('mouseup', mouseup);
}
const handles = document.querySelectorAll('.handle');
let currentHandle;
for(let handle of handles){
handle.addEventListener('mousedown', mousedown);
function mousedown(e){
currentHandle = e.target;
isResizing = true;
let prevX = e.clientX;
let prevY = e.clientY;
window.addEventListener('mousemove', mousemove);
window.addEventListener('mouseup', mouseup);
function mousemove(e){
const rect = textBox.getBoundingClientRect();
if (currentHandle.classList.contains("se")) {
textBox.style.width = rect.width - (prevX - e.clientX) + "px";
textBox.style.height = rect.height - (prevY - e.clientY) + "px";
} else if (currentHandle.classList.contains("sw")) {
textBox.style.width = rect.width + (prevX - e.clientX) + "px";
textBox.style.height = rect.height - (prevY - e.clientY) + "px";
textBox.style.left = rect.left - (prevX - e.clientX) + "px";
} else if (currentHandle.classList.contains("ne")) {
textBox.style.width = rect.width - (prevX - e.clientX) + "px";
textBox.style.height = rect.height + (prevY - e.clientY) + "px";
textBox.style.top = rect.top - (prevY - e.clientY) + "px";
} else {
textBox.style.width = rect.width + (prevX - e.clientX) + "px";
textBox.style.height = rect.height + (prevY - e.clientY) + "px";
textBox.style.top = rect.top - (prevY - e.clientY) + "px";
textBox.style.left = rect.left - (prevX - e.clientX) + "px";
}
prevX = e.clientX;
prevY = e.clientY;
}
function mouseup(){
window.removeEventListener('mousemove', mousemove);
window.removeEventListener('mouseup', mouseup);
textArea.focused = false;
isResizing = false;
}
}
}
}
.text-box{
height: 50px;
width: 150px;
position: absolute;
}
.handle{
position: absolute;
width: 5px;
height: 5px;
background-color: blue;
z-index: 2;
}
.ne{
top: -1px;
right: -1px;
cursor: ne-resize;
}
.nw{
top: -1px;
left: -1px;
cursor: nw-resize;
}
.sw{
bottom: -1px;
left: -1px;
cursor: sw-resize;
}
.se{
bottom: -1px;
right: -1px;
cursor: se-resize;
}
.text-field {
width: 100%;
height: 100%;
resize: none;
cursor: default;
}
<div class="text-box">
<textarea class="text-field">Click to add text...</textarea>
<div class="handle ne"></div>
<div class="handle nw"></div>
<div class="handle sw"></div>
<div class="handle se"></div>
</div>
It is just as Chris said on the comment, (However I tried many things before understanding the issue...)
One way very simple to solve it is to take out your for loop from inside your mousedown function.
var textBox = document.querySelector(".text-box");
var textArea = document.querySelector('.text-field');
textArea.focused = false;
textBox.addEventListener('mousedown', mousedown);
let isResizing = false;
let isTyping = false;
textArea.addEventListener('dblclick', type)
function type(){
if (!isTyping){
isTyping = true;
textArea.style.cursor = 'text';
}else {
isTyping = false;
textArea.style.cursor = 'default';
}
}
document.body.onclick = function(e){
if (e.target != textArea){
isTyping = false;
e.target.style.cursor = 'default';
}
}
function mousedown(e){
if (e.target == textArea){
e.target.style.cursor = 'default';
}
window.addEventListener('mousemove', mousemove);
window.addEventListener('mouseup', mouseup);
let prevX = e.clientX;
let prevY = e.clientY;
function mousemove(e){
if(!isResizing && !isTyping){
let newX = prevX - e.clientX;
let newY = prevY - e.clientY;
const rect = textBox.getBoundingClientRect();
textBox.style.left = rect.left - newX + "px";
textBox.style.top = rect.top - newY + "px";
prevX = e.clientX;
prevY = e.clientY;
}
}
function mouseup(){
window.removeEventListener('mousemove', mousemove);
window.removeEventListener('mouseup', mouseup);
}
}
const handles = document.querySelectorAll('.handle');
let currentHandle;
for(let handle of handles){
handle.addEventListener('mousedown', mousedown);
function mousedown(e){
currentHandle = e.target;
isResizing = true;
let prevX = e.clientX;
let prevY = e.clientY;
window.addEventListener('mousemove', mousemove);
window.addEventListener('mouseup', mouseup);
function mousemove(e){
const rect = textBox.getBoundingClientRect();
if (currentHandle.classList.contains("se")) {
textBox.style.width = rect.width - (prevX - e.clientX) + "px";
textBox.style.height = rect.height - (prevY - e.clientY) + "px";
} else if (currentHandle.classList.contains("sw")) {
textBox.style.width = rect.width + (prevX - e.clientX) + "px";
textBox.style.height = rect.height - (prevY - e.clientY) + "px";
textBox.style.left = rect.left - (prevX - e.clientX) + "px";
} else if (currentHandle.classList.contains("ne")) {
textBox.style.width = rect.width - (prevX - e.clientX) + "px";
textBox.style.height = rect.height + (prevY - e.clientY) + "px";
textBox.style.top = rect.top - (prevY - e.clientY) + "px";
} else {
textBox.style.width = rect.width + (prevX - e.clientX) + "px";
textBox.style.height = rect.height + (prevY - e.clientY) + "px";
textBox.style.top = rect.top - (prevY - e.clientY) + "px";
textBox.style.left = rect.left - (prevX - e.clientX) + "px";
}
prevX = e.clientX;
prevY = e.clientY;
}
function mouseup(){
window.removeEventListener('mousemove', mousemove);
window.removeEventListener('mouseup', mouseup);
textArea.focused = false;
isResizing = false;
}
}
}
Just one more thing, I added these lines to your code, to not remove the resize cursor when clicking the handler:
document.body.onclick = function(e){
if (e.target != textArea){
if(e.target.classList.contains('handle')){
isTyping = false
}
else{
isTyping = false;
e.target.style.cursor = 'default';
}
}
}
I would like to pan a canvas's viewport on a touch device, I wrote this code:
canvas.on('touch:drag', function (opt) {
var e = opt.e;
if (this.isDragging) {
if (e.clientX === undefined ) {
this.isDragging = false;
} else {
this.viewportTransform[4] += e.clientX - this.lastPosX;
this.viewportTransform[5] += e.clientY - this.lastPosY;
this.requestRenderAll();
this.lastPosX = e.clientX;
this.lastPosY = e.clientY;
}
} else {
this.isDragging = true;
this.selection = false;
this.lastPosX = e.clientX;
this.lastPosY = e.clientY;
}
});
This works well on my desktop PC but not on my smartphone (The viewport is not moving): Do you have an idea why?
In touch devices, normally you have e.touches[0].clientX instead of e.clientX
I wrote my own draggable & resizable code,
var startX, startY, startWidth, startHeight;
var div = document.getElementById('div'),
x1 = 0,
y1 = 0,
x2 = 0,
y2 = 0;
var element;
function reCalc() {
var x3 = Math.min(x1, x2);
var x4 = Math.max(x1, x2);
var y3 = Math.min(y1, y2);
var y4 = Math.max(y1, y2);
div.style.left = x3 + 'px';
div.style.top = y3 + 'px';
div.style.width = x4 - x3 + 'px';
div.style.height = y4 - y3 + 'px';
}
$(document).on("mousedown", function (e) {
var target = $(event.target);
x1 = e.clientX;
y1 = e.clientY;
if (element && element.find('.resizer').is(target)) {
return;
}
if (element) {
element.remove();
}
div.hidden = 0;
x1 = e.clientX;
y1 = e.clientY;
reCalc();
});
$(document).on("mousemove", function (e) {
x2 = e.clientX;
y2 = e.clientY;
reCalc();
});
$(document).on("mouseup", function (e) {
div.hidden = 1;
var target = $(event.target);
if (element && element.find('.resizer').is(target)) {
return;
}
element = $("<div>");
element[0].style.left = div.style.left;
element[0].style.top = div.style.top;
element[0].style.width = div.style.width;
element[0].style.height = div.style.height;
var resizer = document.createElement('div');
resizer.className = 'resizer';
element.append(resizer);
resizer.addEventListener('mousedown', initDrag, false);
$("body").append(element.show());
element.on("mousedown", function () {
event.stopImmediatePropagation();
});
element.on("mouseup", function () {
event.stopImmediatePropagation();
});
});
function initDrag(e) {
startX = e.clientX;
startY = e.clientY;
startWidth = parseInt(document.defaultView.getComputedStyle(element[0]).width, 10);
startHeight = parseInt(document.defaultView.getComputedStyle(element[0]).height, 10);
document.documentElement.addEventListener('mousemove', doDrag, false);
document.documentElement.addEventListener('mouseup', stopDrag, false);
}
function doDrag(e) {
element[0].style.width = (startWidth + e.clientX - startX) + 'px';
element[0].style.height = (startHeight + e.clientY - startY) + 'px';
}
function stopDrag(e) {
document.documentElement.removeEventListener('mousemove', doDrag, false);
document.documentElement.removeEventListener('mouseup', stopDrag, false);
}
but when I resize, It does not handle mousedown event properly. It should stop drag when i mouse up
Any solution??
http://jsfiddle.net/Dipak1991/7d8f65b8/1/
There is no listener to invoke your stopDrag() function:
resizer.addEventListener('mousedown', initDrag, false);
// Add
resizer.addEventListener('mouseup', stopDrag, false);
JSFiddle
Im struggling with seemingly a simple javascript exercise, writing a vanilla drag and drop. I think Im making a mistake with my 'addeventlisteners', here is the code:
var ele = document.getElementsByClassName ("target")[0];
var stateMouseDown = false;
//ele.onmousedown = eleMouseDown;
ele.addEventListener ("onmousedown" , eleMouseDown , false);
function eleMouseDown () {
stateMouseDown = true;
document.addEventListener ("onmousemove" , eleMouseMove , false);
}
function eleMouseMove (ev) {
do {
var pX = ev.pageX;
var pY = ev.pageY;
ele.style.left = pX + "px";
ele.style.top = pY + "px";
document.addEventListener ("onmouseup" , eleMouseUp , false);
} while (stateMouseDown === true);
}
function eleMouseUp () {
stateMouseDown = false;
document.removeEventListener ("onmousemove" , eleMouseMove , false);
document.removeEventListener ("onmouseup" , eleMouseUp , false);
}
Here's a jsfiddle with it working: http://jsfiddle.net/fpb7j/1/
There were 2 main issues, first being the use of onmousedown, onmousemove and onmouseup. I believe those are only to be used with attached events:
document.body.attachEvent('onmousemove',drag);
while mousedown, mousemove and mouseup are for event listeners:
document.body.addEventListener('mousemove',drag);
The second issue was the do-while loop in the move event function. That function's being called every time the mouse moves a pixel, so the loop isn't needed:
var ele = document.getElementsByClassName ("target")[0];
ele.addEventListener ("mousedown" , eleMouseDown , false);
function eleMouseDown () {
stateMouseDown = true;
document.addEventListener ("mousemove" , eleMouseMove , false);
}
function eleMouseMove (ev) {
var pX = ev.pageX;
var pY = ev.pageY;
ele.style.left = pX + "px";
ele.style.top = pY + "px";
document.addEventListener ("mouseup" , eleMouseUp , false);
}
function eleMouseUp () {
document.removeEventListener ("mousemove" , eleMouseMove , false);
document.removeEventListener ("mouseup" , eleMouseUp , false);
}
By the way, I had to make the target's position absolute for it to work.
you can try this fiddle too, http://jsfiddle.net/dennisbot/4AH5Z/
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>titulo de mi pagina</title>
<style>
#target {
width: 100px;
height: 100px;
background-color: #ffc;
border: 2px solid blue;
position: absolute;
}
</style>
<script>
window.onload = function() {
var el = document.getElementById('target');
var mover = false, x, y, posx, posy, first = true;
el.onmousedown = function() {
mover = true;
};
el.onmouseup = function() {
mover = false;
first = true;
};
el.onmousemove = function(e) {
if (mover) {
if (first) {
x = e.offsetX;
y = e.offsetY;
first = false;
}
posx = e.pageX - x;
posy = e.pageY - y;
this.style.left = posx + 'px';
this.style.top = posy + 'px';
}
};
}
</script>
</head>
<body>
<div id="target" style="left: 10px; top:20px"></div>
</body>
</html>
I've just made a simple drag.
It's a one liner usage, and it handles things like the offset of the mouse to the top left corner of the element, onDrag/onStop callbacks, and SVG elements dragging
Here is the code.
// simple drag
function sdrag(onDrag, onStop) {
var startX = 0;
var startY = 0;
var el = this;
var dragging = false;
function move(e) {
el.style.left = (e.pageX - startX ) + 'px';
el.style.top = (e.pageY - startY ) + 'px';
onDrag && onDrag(el, e.pageX, startX, e.pageY, startY);
}
function startDragging(e) {
if (e.currentTarget instanceof HTMLElement || e.currentTarget instanceof SVGElement) {
dragging = true;
var left = el.style.left ? parseInt(el.style.left) : 0;
var top = el.style.top ? parseInt(el.style.top) : 0;
startX = e.pageX - left;
startY = e.pageY - top;
window.addEventListener('mousemove', move);
}
else {
throw new Error("Your target must be an html element");
}
}
this.addEventListener('mousedown', startDragging);
window.addEventListener('mouseup', function (e) {
if (true === dragging) {
dragging = false;
window.removeEventListener('mousemove', move);
onStop && onStop(el, e.pageX, startX, e.pageY, startY);
}
});
}
Element.prototype.sdrag = sdrag;
and to use it:
document.getElementById('my_target').sdrag();
You can also use onDrag and onStop callbacks:
document.getElementById('my_target').sdrag(onDrag, onStop);
Check my repo here for more details:
https://github.com/lingtalfi/simpledrag
this is how I do it
var MOVE = {
startX: undefined,
startY: undefined,
item: null
};
function contentDiv(color, width, height) {
var result = document.createElement('div');
result.style.width = width + 'px';
result.style.height = height + 'px';
result.style.backgroundColor = color;
return result;
}
function movable(content) {
var outer = document.createElement('div');
var inner = document.createElement('div');
outer.style.position = 'relative';
inner.style.position = 'relative';
inner.style.cursor = 'move';
inner.style.zIndex = 1000;
outer.appendChild(inner);
inner.appendChild(content);
inner.addEventListener('mousedown', function(evt) {
MOVE.item = this;
MOVE.startX = evt.pageX;
MOVE.startY = evt.pageY;
})
return outer;
}
function bodyOnload() {
document.getElementById('td1').appendChild(movable(contentDiv('blue', 100, 100)));
document.getElementById('td2').appendChild(movable(contentDiv('red', 100, 100)));
document.addEventListener('mousemove', function(evt) {
if (!MOVE.item) return;
if (evt.which!==1){ return; }
var dx = evt.pageX - MOVE.startX;
var dy = evt.pageY - MOVE.startY;
MOVE.item.parentElement.style.left = dx + 'px';
MOVE.item.parentElement.style.top = dy + 'px';
});
document.addEventListener('mouseup', function(evt) {
if (!MOVE.item) return;
var dx = evt.pageX - MOVE.startX;
var dy = evt.pageY - MOVE.startY;
var sty = MOVE.item.style;
sty.left = (parseFloat(sty.left) || 0) + dx + 'px';
sty.top = (parseFloat(sty.top) || 0) + dy + 'px';
MOVE.item.parentElement.style.left = '';
MOVE.item.parentElement.style.top = '';
MOVE.item = null;
MOVE.startX = undefined;
MOVE.startY = undefined;
});
}
bodyOnload();
table {
user-select: none
}
<table>
<tr>
<td id='td1'></td>
<td id='td2'></td>
</tr>
</table>
While dragging, the left and right of the style of the parentElement of the dragged element are continuously updated. Then, on mouseup (='drop'), "the changes are committed", so to speak; we add the (horizontal and vertical) position changes (i.e., left and top) of the parent to the position of the element itself, and we clear left/top of the parent again. This way, we only need JavaScript variables for pageX, pageY (mouse position at drag start), while concerning the element position at drag start, we don't need JavaScript variables for that (just keeping that information in the DOM).
If you're dealing with SVG elements, you can use the same parent/child/commit technique. Just use two nested g, and use transform=translate(dx,dy) instead of style.left=dx, style.top=dy
I've created a simple code to drag and drop div element but not work well.
When you drag the div element quickly to any direction top, left, right, down, the mouse cursor will leave the div element, Although I'm still press on the button .
HTML
<div id="box"></div>
CSS
div#box {
background-color:yellowgreen;
width:150px; height:100px;
border:1px solid #ffff66;
position:relative;
}
JavaScript
var elem = document.getElementById('box');
var PositionX = 0;
var PositionY = 0;
var MouseX = 0
var MouseY = 0;
var mouseDown = false;
elem.onmousedown = function(e) {
PositionX = elem.offsetLeft;
PositionY = elem.offsetTop;
MouseX = e.clientX;
MouseY = e.clientY;
mouseDown = true;
};
elem.onmousemove = function(e) {
if (mouseDown) {
elem.style.left = PositionX + e.clientX - MouseX + "px";
elem.style.top = PositionY + e.clientY - MouseY + "px";
}
};
elem.onmouseover = function(e) {
elem.style.cursor = 'move';
};
elem.onmouseup = function(e) {
mouseDown = false;
};
You can see online
Try changing this one line:
elem.onmousemove = function(e) {
to:
document.onmousemove = function(e) {
try this hope it would have your work done :
var elem= document.getElementbyId('<%=box.ClientID%>');
elem.onmousemove= function(e) {
if (mouseDown) {
elem.style.left = PositionX + e.clientX - MouseX + "px";
elem.style.top = PositionY + e.clientY - MouseY + "px";
}
};