Last active
April 26, 2020 04:09
-
-
Save ricardocanelas/85457c2705d5124a3c5d1cd18f8a4260 to your computer and use it in GitHub Desktop.
Draggable
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function draggable({ dragElem, zoneElemBefore }) { | |
const $dragElem = document.querySelector(dragElem) | |
const $zoneElem = $dragElem.closest(zoneElemBefore) | |
const margin = 10 | |
$dragElem.onmousedown = function (event) { | |
if (event.target.tagName === "TEXTAREA") return; | |
event.preventDefault(); | |
let shiftY = event.clientY - $dragElem.getBoundingClientRect().top; | |
document.addEventListener('mousemove', onMouseMove); | |
document.addEventListener('mouseup', onMouseUp); | |
function onMouseMove(event) { | |
let boxBottomEdge = (event.clientY + ($dragElem.getBoundingClientRect().height - shiftY)) | |
let newB = $zoneElem.getBoundingClientRect().bottom - boxBottomEdge | |
let topEdge = ($zoneElem.offsetHeight - $dragElem.offsetHeight); | |
if (newB < margin) newB = margin | |
if (newB > topEdge - margin) newB = topEdge - margin | |
$dragElem.style.bottom = newB + 'px'; | |
} | |
function onMouseUp() { | |
document.removeEventListener('mouseup', onMouseUp); | |
document.removeEventListener('mousemove', onMouseMove); | |
} | |
}; | |
$dragElem.ondragstart = function() { | |
return false; | |
}; | |
} | |
draggable.reset = function (dragElem, pos) { | |
const $dragElem = document.querySelector(dragElem) | |
$dragElem.style.bottom = pos | |
} | |
export default draggable |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
draggable({ | |
dragElem: document.querySelector('.draggable-box'), | |
zoneElem: document.querySelector('.draggable-zone') | |
}) | |
function draggable({ dragElem, zoneElem }) { | |
dragElem.style.position = 'relative !important'; | |
dragElem.onmousedown = function(event) { | |
event.preventDefault(); | |
let shiftY = event.clientX - dragElem.getBoundingClientRect().top; | |
document.addEventListener('mousemove', onMouseMove); | |
document.addEventListener('mouseup', onMouseUp); | |
function onMouseMove(event) { | |
let newTop = event.clientY - shiftY - zoneElem.getBoundingClientRect().top; | |
let bottomEdge = zoneElem.offsetHeight - dragElem.offsetHeight; | |
if (newTop < 0) newTop = 0; | |
if (newTop > bottomEdge) newTop = bottomEdge; | |
dragElem.style.top = newTop + 'px'; | |
} | |
function onMouseUp() { | |
document.removeEventListener('mouseup', onMouseUp); | |
document.removeEventListener('mousemove', onMouseMove); | |
} | |
}; | |
dragElem.ondragstart = function() { | |
return false; | |
}; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
- With support to mobile devices | |
- The position is based by bottom | |
How to use: | |
draggable({ dragElem: '.draggable-box', zoneElemBefore: '.draggable-zone' }) | |
*/ | |
function draggable({ dragElem, zoneElemBefore }) { | |
const $dragElem = document.querySelector(dragElem); | |
const $zoneElem = $dragElem.closest(zoneElemBefore); | |
const margin = 10; | |
let isClicked = false; | |
let shiftY = 0; | |
$dragElem.addEventListener("touchstart", onTouchStart); | |
$dragElem.addEventListener("touchmove", onTouchMove); | |
$dragElem.addEventListener("touchend", onTouchEnd); | |
$dragElem.addEventListener("mousedown", onMouseDown); | |
$dragElem.style.cursor = "grab"; | |
function onTouchStart(event) { | |
start() | |
shiftY = getShiftY(event) | |
} | |
function onTouchMove(event) { | |
moveBox(event) | |
} | |
function onTouchEnd(event) { | |
end() | |
} | |
function onMouseDown(event) { | |
if (event.target.tagName === "TEXTAREA") return; // just an example to skip the action to drag | |
start() | |
event.preventDefault(); | |
$dragElem.style.cursor = "grabbing"; | |
shiftY = getShiftY(event) | |
document.addEventListener("mousemove", onMouseMove); | |
document.addEventListener("mouseup", onMouseUp); | |
function onMouseMove(event) { | |
moveBox(event, shiftY) | |
} | |
function onMouseUp() { | |
end() | |
document.removeEventListener("mousemove", onMouseMove); | |
document.removeEventListener("mouseup", onMouseUp); | |
} | |
} | |
$dragElem.ondragstart = function() { | |
return false; | |
}; | |
// helpers | |
function start() { | |
isClicked = true; | |
$dragElem.style.cursor = "grabbing"; | |
} | |
function end() { | |
isClicked = false; | |
$dragElem.style.cursor = "grab"; | |
} | |
function moveBox(event) { | |
if(!isClicked) return; | |
let points = getClientPoints(event) | |
let boxBottomEdge = | |
points.clientY + ($dragElem.getBoundingClientRect().height - shiftY); | |
let newB = $zoneElem.getBoundingClientRect().bottom - boxBottomEdge; | |
let topEdge = $zoneElem.offsetHeight - $dragElem.offsetHeight; | |
if (newB < margin) newB = margin; | |
if (newB > topEdge - margin) newB = topEdge - margin; | |
$dragElem.style.bottom = newB + "px"; | |
} | |
function getClientPoints(event) { | |
return event.touches | |
? event.touches[0] || event.changedTouches[0] | |
: { clientY: event.clientY, clientX: event.clientX }; | |
} | |
function getShiftY(event) { | |
let points = getClientPoints(event) | |
return points.clientY - $dragElem.getBoundingClientRect().top; | |
} | |
} | |
draggable.reset = function(dragElem, pos) { | |
const $dragElem = document.querySelector(dragElem); | |
$dragElem.style.bottom = pos; | |
}; | |
export default draggable; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Transform to class | |
// Because it will be easy to unmount the events and scale | |
function Draggable() { | |
this.version = 2.1; | |
this.$dragElem = undefined; | |
this.$zoneElem = undefined; | |
this.isClicked = false; | |
this.margin = 10; | |
this.shiftY = 0; | |
this.events = {}; | |
this.helpers = {}; | |
} | |
Draggable.prototype.init = function({ dragElem, zoneElemBefore }) { | |
this.initHelpers() | |
this.initEvents() | |
this.$dragElem = document.querySelector(dragElem); | |
this.$zoneElem = this.$dragElem.closest(zoneElemBefore); | |
this.ontouchstart = this.events.onTouchStart.bind(this) | |
this.ontouchmove = this.events.onTouchMove.bind(this) | |
this.ontouchend = this.events.onTouchEnd.bind(this) | |
this.onmousedown = this.events.onMouseDown.bind(this) | |
this.$dragElem.addEventListener("touchstart", this.ontouchstart); | |
this.$dragElem.addEventListener("touchmove", this.ontouchmove); | |
this.$dragElem.addEventListener("touchend", this.ontouchend); | |
this.$dragElem.addEventListener("mousedown", this.onmousedown); | |
this.$dragElem.style.cursor = "grab"; | |
this.$dragElem.ondragstart = function() { | |
return false; | |
}; | |
}; | |
Draggable.prototype.initHelpers = function() { | |
const that = this | |
that.helpers.start = function() { | |
that.isClicked = true; | |
that.$dragElem.style.cursor = "grabbing"; | |
}; | |
that.helpers.end = function() { | |
that.isClicked = false; | |
that.$dragElem.style.cursor = "grab"; | |
}; | |
that.helpers.moveBox = function(event) { | |
if (!that.isClicked) return; | |
let points = that.helpers.getClientPoints(event); | |
let boxBottomEdge = | |
points.clientY + | |
(that.$dragElem.getBoundingClientRect().height - that.shiftY); | |
let newB = that.$zoneElem.getBoundingClientRect().bottom - boxBottomEdge; | |
let topEdge = that.$zoneElem.offsetHeight - that.$dragElem.offsetHeight; | |
if (newB < that.margin) newB = that.margin; | |
if (newB > topEdge - that.margin) newB = topEdge - that.margin; | |
that.$dragElem.style.bottom = newB + "px"; | |
}; | |
that.helpers.getClientPoints = function(event) { | |
return event.touches | |
? event.touches[0] || event.changedTouches[0] | |
: { clientY: event.clientY, clientX: event.clientX }; | |
}; | |
that.helpers.getShiftY = function(event) { | |
let points = that.helpers.getClientPoints(event); | |
return points.clientY - that.$dragElem.getBoundingClientRect().top; | |
}; | |
}; | |
Draggable.prototype.initEvents = function() { | |
const that = this | |
that.events.onTouchStart = function(event) { | |
that.helpers.start(); | |
that.shiftY = that.helpers.getShiftY(event); | |
}; | |
that.events.onTouchMove = function(event) { | |
that.helpers.moveBox(event); | |
}; | |
that.events.onTouchEnd = function(_event) { | |
that.helpers.end(); | |
}; | |
that.events.onMouseDown = function (event) { | |
if (event.target.tagName === "TEXTAREA") return; | |
that.helpers.start(); | |
event.preventDefault(); | |
that.$dragElem.style.cursor = "grabbing"; | |
that.shiftY = that.helpers.getShiftY(event); | |
document.addEventListener("mousemove", that.events.onMouseMove); | |
document.addEventListener("mouseup", that.events.onMouseUp); | |
}; | |
that.events.onMouseMove = function(event) { | |
that.helpers.moveBox(event, that.shiftY); | |
}; | |
that.events.onMouseUp = function() { | |
that.helpers.end(); | |
document.removeEventListener("mousemove", that.events.onMouseMove); | |
document.removeEventListener("mouseup", that.events.onMouseUp); | |
}; | |
}; | |
Draggable.prototype.reset = function(pos) { | |
this.$dragElem.style.bottom = pos; | |
}; | |
Draggable.prototype.unmount = function() { | |
this.helpers.end() | |
this.$dragElem.style.cursor = "initial"; | |
this.$dragElem.removeEventListener("touchstart", this.ontouchstart); | |
this.$dragElem.removeEventListener("touchmove", this.ontouchmove); | |
this.$dragElem.removeEventListener("touchend", this.ontouchend); | |
this.$dragElem.removeEventListener("mousedown", this.onmousedown); | |
}; | |
export default new Draggable(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Draggable() { | |
this.version = 2.2; | |
this.$dragElem = undefined; | |
this.$zoneElem = undefined; | |
this.isClicked = false; | |
this.margin = 0; | |
this.shiftY = 0; | |
this.shiftX = 0; | |
this.events = {}; | |
this.helpers = {}; | |
} | |
Draggable.prototype.init = function({ | |
dragElem, | |
zoneElemBefore, | |
vertical, | |
horizontal | |
}) { | |
this.initHelpers(); | |
this.initEvents(); | |
this.options = { | |
vertical: vertical || true, | |
horizontal: horizontal || true | |
}; | |
this.$dragElem = document.querySelector(dragElem); | |
this.$zoneElem = this.$dragElem.closest(zoneElemBefore); | |
this.ontouchstart = this.events.onTouchStart.bind(this); | |
this.ontouchmove = this.events.onTouchMove.bind(this); | |
this.ontouchend = this.events.onTouchEnd.bind(this); | |
this.onmousedown = this.events.onMouseDown.bind(this); | |
this.$dragElem.addEventListener("touchstart", this.ontouchstart); | |
this.$dragElem.addEventListener("touchmove", this.ontouchmove); | |
this.$dragElem.addEventListener("touchend", this.ontouchend); | |
this.$dragElem.addEventListener("mousedown", this.onmousedown); | |
this.$dragElem.style.cursor = "grab"; | |
this.$dragElem.ondragstart = function() { | |
return false; | |
}; | |
}; | |
Draggable.prototype.initHelpers = function() { | |
const that = this; | |
that.helpers.start = function() { | |
that.isClicked = true; | |
that.$dragElem.style.cursor = "grabbing"; | |
}; | |
that.helpers.end = function() { | |
that.isClicked = false; | |
that.$dragElem.style.cursor = "grab"; | |
}; | |
that.helpers.moveBox = function(event) { | |
if (!that.isClicked) return; | |
let points = that.helpers.getClientPoints(event); | |
// --- vertical | |
let newTop = | |
points.clientY - that.shiftY - that.$zoneElem.getBoundingClientRect().top; | |
let bottomEdge = that.$zoneElem.offsetHeight - that.$dragElem.offsetHeight; | |
if (newTop < 0) newTop = 0; | |
if (newTop > bottomEdge) newTop = bottomEdge; | |
// --- horizontal | |
let newLeft = | |
points.clientX - | |
that.shiftX - | |
that.$zoneElem.getBoundingClientRect().left; | |
let rightEdge = that.$zoneElem.offsetWidth - that.$dragElem.offsetWidth; | |
if (newLeft < 0) newLeft = 0; | |
if (newLeft > rightEdge) newLeft = rightEdge; | |
// --- | |
if (that.options.horizontal) that.$dragElem.style.left = newLeft + "px"; | |
if (that.options.vertical) that.$dragElem.style.top = newTop + "px"; | |
const percentHorizontal = (that.$dragElem.offsetLeft * 100) / rightEdge; | |
const percentVertical = (that.$dragElem.offsetTop * 100) / bottomEdge; | |
if (that.onchange) that.onchange(percentHorizontal, percentVertical); | |
}; | |
that.helpers.getClientPoints = function(event) { | |
return event.touches | |
? event.touches[0] || event.changedTouches[0] | |
: { clientY: event.clientY, clientX: event.clientX }; | |
}; | |
that.helpers.getShiftY = function(event) { | |
let points = that.helpers.getClientPoints(event); | |
return points.clientY - that.$dragElem.getBoundingClientRect().top; | |
}; | |
that.helpers.getShiftX = function(event) { | |
let points = that.helpers.getClientPoints(event); | |
return points.clientX - that.$dragElem.getBoundingClientRect().left; | |
}; | |
}; | |
Draggable.prototype.initEvents = function() { | |
const that = this; | |
that.events.onTouchStart = function(event) { | |
that.helpers.start(); | |
that.shiftY = that.helpers.getShiftY(event); | |
that.shiftX = that.helpers.getShiftX(event); | |
}; | |
that.events.onTouchMove = function(event) { | |
that.helpers.moveBox(event); | |
}; | |
that.events.onTouchEnd = function(_event) { | |
that.helpers.end(); | |
}; | |
that.events.onMouseDown = function(event) { | |
that.helpers.start(); | |
event.preventDefault(); | |
that.$dragElem.style.cursor = "grabbing"; | |
that.shiftY = that.helpers.getShiftY(event); | |
that.shiftX = that.helpers.getShiftX(event); | |
document.addEventListener("mousemove", that.events.onMouseMove); | |
document.addEventListener("mouseup", that.events.onMouseUp); | |
}; | |
that.events.onMouseMove = function(event) { | |
that.helpers.moveBox(event); | |
}; | |
that.events.onMouseUp = function() { | |
that.helpers.end(); | |
document.removeEventListener("mousemove", that.events.onMouseMove); | |
document.removeEventListener("mouseup", that.events.onMouseUp); | |
}; | |
}; | |
Draggable.prototype.setHorizontal = function(perc) { | |
// TODO | |
}; | |
Draggable.prototype.reset = function(pos) { | |
this.$dragElem.style.bottom = pos; | |
}; | |
Draggable.prototype.unmount = function() { | |
this.helpers.end(); | |
this.$dragElem.style.cursor = "initial"; | |
this.$dragElem.removeEventListener("touchstart", this.ontouchstart); | |
this.$dragElem.removeEventListener("touchmove", this.ontouchmove); | |
this.$dragElem.removeEventListener("touchend", this.ontouchend); | |
this.$dragElem.removeEventListener("mousedown", this.onmousedown); | |
}; | |
export default new Draggable(); | |
/** | |
draggable.init({ | |
dragElem: ".slider .thumb", | |
zoneElemBefore: ".slider", | |
vertical: false, | |
horizontal: true | |
}); | |
draggable.onchange = (pX, pY) => { | |
console.log('percentHorizontal', pX) | |
}; | |
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div class="card draggable-zone"> | |
<div class="wrapper draggable-box"> | |
<div class="qx-question-result "> | |
<div>Draggable</div> | |
</div> | |
</div> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.draggable-zone{ | |
height: 500px; | |
width: 400px; | |
} | |
.draggable-box{ | |
position: relative; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Preview: https://jsfiddle.net/w9y7pmeb/1/ and https://codesandbox.io/s/draggable-xbjfx and https://codesandbox.io/s/draggable-22-p5exg