I have a scrollable list. It has the overflow-y property set to scroll and I can scroll with the scroll bar but I would like to be able to use my mouse to drag up and down.
Here is what I have so far
//Allows the user to scroll by dragging the mouse
element.on({
'mousemove': function(e)
{
if (self.get('clicked'))
{
const difference = self.get('clickY') - element.scrollTop();
const scrollY = difference + (e.pageY - element.offset().top);
element.scrollTop(scrollY);
}
},
'mousedown': function (e)
{
const clickY = (e.pageY - element.offset().top) + element.scrollTop();
self.set('clicked', true);
self.set('clickY', clickY);
},
'mouseup': function (e)
{
self.set('clicked', false);
},
'mouseleave': function(e)
{
self.set('clicked', false);
}
});
I have been playing around with it but just cant get it right, because I have to take into consideration the y position of the element, how much its already scrolled, the mouseY etc. Would someone be able to help me out with this please?
Related
im trying to create a small script for simulating a swipe on a web page, here is the code :
var startX;
var endX;
document.body.addEventListener('touchstart', function(e) {
startX = e.targetTouches[0].pageX;
console.log(startX);
}, false);
document.body.addEventListener('touchend', function(e) {
endX = e.targetTouches[0].pageX;
console.log(endX);
});
But when im swiping on the browser it says >TypeError: e.targetTouches[0] is undefined
I tried to only display the event with :
console.log(e);
and it seems there is no position for the touchend event.
I need help please :(
I am trying to catch when user press left button on mouse while hovering over cells in a html table using vanilla javascript. The purpose is to paint a cell in black when user is clicking with mouse while dragging (drawing like in MsPaint, when you draw a line for example)
I added an "over" event listener on each td of my table and used buttons property to check if left button is pressed or not:
celle = document.getElementsByTagName("td");
for (i=0;i<celle.length;i++)
celle[i].addEventListener("mouseover", function(e){
if(e.buttons == 1 ){
e.target.style.backgroundColor="black";
}
})
This code works but not always and not perfectly. First it starts setting the background color of the next element, not the one on which I pressed the mouse. Moreover, sometimes it doesn't set any color at all (there is a small icon like "accessed denied" in Chrome's window). It appears to work quite randomly and unpredicatably.
I tried also with jQuery, but I found similar problems. Anyone can help me?
Thanks a lot
Split the problem into several parts. I would add a mousedown and mouseup eventlistener to the whole window and set a global state if you're currently drawing:
var drawState=false
window.addEventListener("mousedown",function(e){
if(e.button===1){
drawState = true;
}});
window.addEventListener("mouseup",function(e){
if(e.button===1){
drawState = false;
}});
You can improve the window listeners with some checks, if the mouse is over a cell.
After this you can add a mouseenter listener to all your cells. Mouseenter is only fired once you enter a cell and not on every move inside the element:
celle[i].addEventListener("mouseenter", function(e){
if(drawState){
e.target.style.backgroundColor="black";
}
})
Instead of tracking mouseover, track three events:
mousemove - to constantly get the mouse position
mousedown - to set the mouse state as currently clicked down
mouseup - to set the mouse state as currently released
It works this way:
handleMousemove constantly updates the mouse position and check mouse state
When the mouse is clicked down, handleMousedown is fired
handleMousedown set the state as 'down'
When handleMousemove sees that mouse state is 'down', it fires click event at the current mouse position
When the mouse is released, handleMouseup is fired
handleMouseup set the state as 'released' and everything returns to normal
Repeat
var mouseIsDown = false;
var mousePosition = { x:-1, y:-1 };
let handleMousemove = (event) => {
// get the mouse position
mousePosition.x = event.x;
mousePosition.y = event.y;
if(mouseIsDown) // if mouse state is currently down, fire click at mouse position
{
let elem = document.elementFromPoint(mousePosition.x, mousePosition.y);
// you can add some conditions before clicking
if(something)
{
elem.click();
}
}
};
let handleMousedown = (event) => {
mouseIsDown = true;
// set the mouse state as 'down'
};
let handleMouseup = (event) => {
mouseIsDown = false;
// set the mouse state as 'release'
};
document.addEventListener('mousemove', handleMousemove);
document.addEventListener('mousedown', handleMousedown);
document.addEventListener('mouseup', handleMouseup);
Working fiddle: https://jsfiddle.net/Black3800/9wvh8bzg/5/
Thanks to everybody for your kind answers. Proposed codes work almost ok. The only problem is that sometimes browser shows the NO SYMBOL cursor. Unfortunately I can't post an image but you can find it here:
NO Symbol
and the only way to keep on drawing is clicking outside the table and then clicking again inside.
This is my code:
var mouseIsDown = false;
var mousePosition = { x:-1, y:-1 };
let handleMousemove = (event) => {
// get the mouse position
mousePosition.x = event.x;
mousePosition.y = event.y;
if(mouseIsDown) // if mouse state is currently down, fire click at mouse position
{
let elem = document.elementFromPoint(mousePosition.x, mousePosition.y);
// you can add some conditions before clicking
if (event.buttons==1)
{
elem.click();
}
}
};
let handleMousedown = (event) => {
mouseIsDown = true;
// set the mouse state as 'down'
};
let handleMouseup = (event) => {
mouseIsDown = false;
// set the mouse state as 'release'
};
document.addEventListener('mousemove', handleMousemove);
document.addEventListener('mousedown', handleMousedown);
document.addEventListener('mouseup', handleMouseup);
celle = document.getElementsByTagName("td");
for (i=0;i<celle.length;i++)
celle[i].addEventListener("click", function(e){
e.target.style.backgroundColor="black";
}
)
Isn't it easier to just add a listener for "click" ? If the element is clicked it also over the cell.
celle[i].addEventListener("click", function(e){
e.target.style.backgroundColor="black";
}
The image below illustrates a problem that I'm experiencing with jQuery's Draggable method. I have a list of products. When users swipe left or right, the products should scroll accordingly. When users swipe down, they should be able to drag the items downward. Here's the issue: although I can successfully differentiate between vertical and horizontal swipes, I can't enable and disable jQuery drag functionality at the right times.
Here is my code:
var touchPos = {
x: null,
y: null,
threshold: {
x: 20,
y: 20
}
};
// Shortcut for getting finger position from touch event
// This is working correctly
var getClient = function (ev, axis) {
var touches = ev.touches || ev.originalEvent.touches;
return touches[0]['client' + axis];
};
// All of the products are draggable by default
$el.draggable({
containment: '.pageWrapper',
cursor: 'move',
revert: 'invalid',
helper: 'clone',
disabled: false
});
function disableDragging () {
$el.draggable('option', 'cancel', '.planSquare');
$el.draggable("option", "disabled", true );
}
function enableDragging () {
$el.draggable('option', 'cancel', '.pageWrapper');
$el.draggable("option", "disabled", false);
}
// When the user starts moving a product
element.bind('touchstart', function (event) {
// Capture finger position
touchPos.x = getClient(event, 'X');
touchPos.y = getClient(event, 'Y');
if ($el.hasClass('unselectable')) {
return false;
}
$el.css('border-color', 'transparent');
});
element.bind('touchmove', function(event) {
// Update the position of the user's finger
var newY = getClient(event, 'Y');
var newX = getClient(event, 'X');
var draggingDown = newY - touchPos.y >= touchPos.threshold.y;
var draggingSideways = Math.abs(newX - touchPos.x) >= touchPos.threshold.x;
if (!draggingDown && draggingSideways) {
disableDragging();
}
});
// When the user stops moving a square
element.bind('touchend', function () {
touchPos.x = null;
touchPos.y = null;
enableDragging();
$el.css('border-color', '#ccc')
});
The enableDragging and disableDragging have the desired effect when I call them outside the context of the touch event. My hypothesis is that, using jQuery UI, I can't disable dragging once a drag event has already begun. To recap, my goal is to disable dragging and switch to native horizontal scrolling if the user is not dragging down.
Can someone recommend a good approach for toggling between dragging and native scrolling behavior?
I am trying to detect user scroll, if to left and to right then trigger and do something.
But if user use trackpad scroll to top or to bottom then it will accidentally scroll to left or to right.
I think, may be not just check timer define per scroll also need to check if user scroll distance smaller than 20, we can differentiate that as accidentally and don't do anything.
I can't find the way check if user scroll distance, the element is not be scrollable so can't use scrollTop scrollLeft....
Any idea?
var scroll_timer;
$('img').bind('mousewheel', function(e) {
if (e.originalEvent.wheelDeltaX < 0) {
clearTimeout(scroll_timer);
scroll_timer = setTimeout(function() {
// .. do something
// console.log('right');
}, 200);
} else if (e.originalEvent.wheelDeltaX > 0) {
clearTimeout(scroll_timer);
scroll_timer = setTimeout(function() {
// .. do something
// console.log('left');
}, 200);
}
});
Here is my JSFiddle
It looks like you can use e.originalEvent.wheelDeltaX to get scroll distance values. You could then use e.originalEvent.wheelDeltaY to see if the user is scrolling vertically more than horizontally and trigger stuff after that is true.
Here's a demo that works by testing if the value of scrolling Y is less that scrolling X and then allowing you to trigger if it's left or right after that. Seems to do the trick on my mac trackpad
var scroll_timer;
$('img').bind('mousewheel', function(e) {
if((Math.abs(e.originalEvent.wheelDeltaX) > Math.abs(e.originalEvent.wheelDeltaY)))
{
if (e.originalEvent.wheelDeltaX < 0) {
clearTimeout(scroll_timer);
scroll_timer = setTimeout(function() {
// .. do something
console.log('right');
}, 200);
} else if (e.originalEvent.wheelDeltaX > 0) {
clearTimeout(scroll_timer);
scroll_timer = setTimeout(function() {
// .. do something
console.log('left');
}, 200);
}
}
});
http://jsfiddle.net/andyface/5CfgT/
I'm trying to make a draggable navigation. The code works fine in chrome but for some reason this code won't work in firefox:
<script type="text/javascript">
$(document).ready(function() {
$('img').on('dragstart', function(event) { event.preventDefault(); });
$('body').mousemove(function (event) {
//button clicked
if (event.which)
{
//there is a previous movement
if (window.moveEvent)
{
//difference in position since last time
var xDiff = event.screenX - window.moveEvent.screenX;
var yDiff = event.screenY - window.moveEvent.screenY;
//Move the scroll bar by the same amount as we moved the mouse
$('body').scrollTop($('body').scrollTop() - yDiff);
$('body').scrollLeft($('body').scrollLeft() - xDiff);
//$('body').addClass('grabbing');
event.preventDefault();
}
window.moveEvent = event; //store for next time
}
else
{
//$('body').removeClass('grabbing');
window.moveEvent = false; //wipe the last one
}
});
//.mouseup(function () {$('body').addClass('grabbing');});
});
</script>
any help would be much appreciated
Thanks