Hello there I've been trying to find a fix for the many scroll events firing on one scroll. This is the only thing close to working for me so far. I want to smoothscroll between two divs (#boxes and #header) I want to use the scroll bar to trigger this smooth scroll and not a button. Any suggestions on how to only take one scroll event? I also used solutions based from prev stackoverflow questions. I used my own locator instead of offsets because thats also unreliable
$(window).scroll(function () {
if (timer) {
window.clearTimeout(timer);
}
timer = window.setTimeout(function () {
if (locator == 0) {
id = $("#boxes");
locator = 1;
} else if (locator = 1) {
id = $("#header");
locator = 0;
}
// target element
var $id = $(id);
if ($id.length === 0) {
return;
}
// top position relative to the document
var pos = $id.offset().top;
// animated top scrolling
$('html, body').animate({scrollTop: pos}, 1500, function () {
$('html, body').clearQueue();
$('html, body').stop();
});
}, 2);
});
So, to be clear, you want any minor scroll event to scroll between one item and the other? Note that when a user scrolls, there is a "momentum" that the browser implements, and you'll be battling with that.
Regardless: You don't need to wrap this in a setTimeout. Right now, your javascript is creating a new setTimeout function that is being fired every 2ms. Scroll events occur with every pixel of movement in the scroll, so if you scroll 100px, you're going to be firing 100 times every 2ms. (That's 50,000 times).
Instead, have a a variable (isScrolling) track the state, so, if you're in the middle of scrolling, the function won't fire.
var isScrolling = false;
var locator = 0;
$(window).scroll(function () {
if (isScrolling) return false;
if (locator == 0) {
id = $("#boxes");
locator = 1;
} else if (locator = 1) {
id = $("#header");
locator = 0;
}
// target element
var $id = $(id);
if ($id.length === 0) {
return;
}
// top position relative to the document
var pos = $id.offset().top;
// animated top scrolling
isScrolling = true;
$('html, body').animate({scrollTop: pos}, 1500, function () {
$('html, body').clearQueue();
$('html, body').stop();
isScrolling = false;
});
});
Here's a JSbin: http://jsbin.com/jugefup/edit?html,css,js,output
Based on this script I found on Stack Overflow, I tried adapting it to fade out an editor panel on a HTML page. Fading out works fine, but I'd like limit the fade-out from being triggered.
What I hope to accomplish is to prevent the fade-out whenever the mouse is over the editor panel (and child controls) or when there's keyboard activity in one of the input children.
var i = null;
// this part is working
$("#my-canvas").mousemove(function() {
clearTimeout(i);
$("#panel,#btn-panel-toggle,#fps").fadeIn(200);
var i = setTimeout('$("#panel,#btn-panel-toggle,#fps").fadeOut(800);', 3000);
})
// this part is not working
$("#panel").mouseover(function() {
clearTimeout(i);
})
For a live example, please check out this jsFiddle.
Two independent variables are needed here to indicate, whether the input#sc-url is focused and div#panel is hovered by mouse or not. Then you can handle the timer with these functions:
$(function () {
var t = null; //timer
var is_url_focused = false, is_panel_hovered = false;
var panel = $('#panel');
function hide_panel(){
if (t) {
clearTimeout(t);
}
t = setTimeout(function(){
if (is_url_focused || is_panel_hovered) {
return;
}
panel.stop().animate({
opacity:0
},800, function(){
panel.hide(); // == diplay:none
});
},2000);
}
function show_panel(){
panel.show().stop().animate({
opacity:1
},800);
}
$('#my-canvas').mouseenter(function(){
show_panel();
}).mouseleave(function(){
hide_panel();
});
$('#panel').hover(function(){
is_panel_hovered = true;
show_panel();
}, function(){
is_panel_hovered = false;
hide_panel();
});
$('#sc-url').focus(function(){
is_url_focused = true;
show_panel();
}).blur(function(){
is_url_focused = false;
hide_panel();
});
$('#btn-panel-toggle').click(function(){
if (panel.is(':hidden')) {
panel.css('opacity',1).show();
} else {
panel.css('opacity',0).hide();
}
});
});
http://jsfiddle.net/w9dv4/3/
Is it possible to capture when a user is swiping left on a page element, and then run a function while the swipe is taking place? I have somewhat of a solution, but what happens is if you're scrolling down on the page, and your finger slightly swipes to the left on an element, it runs the function.
My current solution:
function touchMove() {
finalCoord.x = event.targetTouches[0].pageX;
changeX = originalCoord.x - finalCoord.x;
var changeY = originalCoord.y - finalCoord.y;
if (changeY < threshold.y && changeY > (threshold.y * -1)) {
changeX = originalCoord.x - finalCoord.x;
if (changeX > threshold.x) {
$(document).off("touchmove", ".row");
if ($(event.target).attr("class") === "row-inside") {
var element = $(event.target);
}
if ($(event.target).attr("class") === "row-l") {
var element = $(event.target).parent();
}
if ($(event.target).attr("class") === "row-r") {
var element = $(event.target).parent();
}
setTimeout(function () {
$(document).on("touchmove", ".row", function () {
touchMove();
});
}, 800);
}
}
}
function touchStart() {
originalCoord.x = event.targetTouches[0].pageX;
finalCoord.x = originalCoord.x;
}
$(document).on("touchmove", ".row", function () {
touchMove();
});
$(document).on("touchstart", ".row", function () {
touchStart();
});
}
I thought about using jQuery mobile, but the swipeLeft event only fires when the swiping ended, not during.
The term for that is dragging.
I tried a lot of ways, the best way by far is to use Hammer.js.
Use the https://github.com/EightMedia/hammer.js/wiki/Getting-Started Hammer.js dragleft event.
Check some examples on your mobile device here: http://eightmedia.github.io/hammer.js/examples/carousel.html for dragleft try the carousel.
Is it possible to implement "long press" in JavaScript (or jQuery)? How?
(source: androinica.com)
HTML
Long press
JavaScript
$("a").mouseup(function(){
// Clear timeout
return false;
}).mousedown(function(){
// Set timeout
return false;
});
There is no 'jQuery' magic, just JavaScript timers.
var pressTimer;
$("a").mouseup(function(){
clearTimeout(pressTimer);
// Clear timeout
return false;
}).mousedown(function(){
// Set timeout
pressTimer = window.setTimeout(function() { ... Your Code ...},1000);
return false;
});
Based on Maycow Moura's answer, I wrote this. It also ensures that the user didn't do a right click, which would trigger a long press and works on mobile devices. DEMO
var node = document.getElementsByTagName("p")[0];
var longpress = false;
var presstimer = null;
var longtarget = null;
var cancel = function(e) {
if (presstimer !== null) {
clearTimeout(presstimer);
presstimer = null;
}
this.classList.remove("longpress");
};
var click = function(e) {
if (presstimer !== null) {
clearTimeout(presstimer);
presstimer = null;
}
this.classList.remove("longpress");
if (longpress) {
return false;
}
alert("press");
};
var start = function(e) {
console.log(e);
if (e.type === "click" && e.button !== 0) {
return;
}
longpress = false;
this.classList.add("longpress");
if (presstimer === null) {
presstimer = setTimeout(function() {
alert("long click");
longpress = true;
}, 1000);
}
return false;
};
node.addEventListener("mousedown", start);
node.addEventListener("touchstart", start);
node.addEventListener("click", click);
node.addEventListener("mouseout", cancel);
node.addEventListener("touchend", cancel);
node.addEventListener("touchleave", cancel);
node.addEventListener("touchcancel", cancel);
You should also include some indicator using CSS animations:
p {
background: red;
padding: 100px;
}
.longpress {
-webkit-animation: 1s longpress;
animation: 1s longpress;
}
#-webkit-keyframes longpress {
0%, 20% { background: red; }
100% { background: yellow; }
}
#keyframes longpress {
0%, 20% { background: red; }
100% { background: yellow; }
}
You can use taphold event of jQuery mobile API.
jQuery("a").on("taphold", function( event ) { ... } )
I created long-press-event (0.5k pure JS) to solve this, it adds a long-press event to the DOM.
Listen for a long-press on any element:
// the event bubbles, so you can listen at the root level
document.addEventListener('long-press', function(e) {
console.log(e.target);
});
Listen for a long-press on a specific element:
// get the element
var el = document.getElementById('idOfElement');
// add a long-press event listener
el.addEventListener('long-press', function(e) {
// stop the event from bubbling up
e.preventDefault()
console.log(e.target);
});
Works in IE9+, Chrome, Firefox, Safari & hybrid mobile apps (Cordova & Ionic on iOS/Android)
Demo
While it does look simple enough to implement on your own with a timeout and a couple of mouse event handlers, it gets a bit more complicated when you consider cases like click-drag-release, supporting both press and long-press on the same element, and working with touch devices like the iPad. I ended up using the longclick jQuery plugin (Github), which takes care of that stuff for me. If you only need to support touchscreen devices like mobile phones, you might also try the jQuery Mobile taphold event.
For modern, mobile browsers:
document.addEventListener('contextmenu', callback);
https://developer.mozilla.org/en-US/docs/Web/Events/contextmenu
jQuery plugin. Just put $(expression).longClick(function() { <your code here> });. Second parameter is hold duration; default timeout is 500 ms.
(function($) {
$.fn.longClick = function(callback, timeout) {
var timer;
timeout = timeout || 500;
$(this).mousedown(function() {
timer = setTimeout(function() { callback(); }, timeout);
return false;
});
$(document).mouseup(function() {
clearTimeout(timer);
return false;
});
};
})(jQuery);
$(document).ready(function () {
var longpress = false;
$("button").on('click', function () {
(longpress) ? alert("Long Press") : alert("Short Press");
});
var startTime, endTime;
$("button").on('mousedown', function () {
startTime = new Date().getTime();
});
$("button").on('mouseup', function () {
endTime = new Date().getTime();
longpress = (endTime - startTime < 500) ? false : true;
});
});
DEMO
For cross platform developers (Note All answers given so far will not work on iOS):
Mouseup/down seemed to work okay on android - but not all devices ie (samsung tab4). Did not work at all on iOS.
Further research its seems that this is due to the element having selection and the native magnification interupts the listener.
This event listener enables a thumbnail image to be opened in a bootstrap modal, if the user holds the image for 500ms.
It uses a responsive image class therefore showing a larger version of the image.
This piece of code has been fully tested upon (iPad/Tab4/TabA/Galaxy4):
var pressTimer;
$(".thumbnail").on('touchend', function (e) {
clearTimeout(pressTimer);
}).on('touchstart', function (e) {
var target = $(e.currentTarget);
var imagePath = target.find('img').attr('src');
var title = target.find('.myCaption:visible').first().text();
$('#dds-modal-title').text(title);
$('#dds-modal-img').attr('src', imagePath);
// Set timeout
pressTimer = window.setTimeout(function () {
$('#dds-modal').modal('show');
}, 500)
});
The Diodeus's answer is awesome, but it prevent you to add a onClick function, it'll never run hold function if you put an onclick. And the Razzak's answer is almost perfect, but it run hold function only on mouseup, and generally, the function runs even if user keep holding.
So, I joined both, and made this:
$(element).on('click', function () {
if(longpress) { // if detect hold, stop onclick function
return false;
};
});
$(element).on('mousedown', function () {
longpress = false; //longpress is false initially
pressTimer = window.setTimeout(function(){
// your code here
longpress = true; //if run hold function, longpress is true
},1000)
});
$(element).on('mouseup', function () {
clearTimeout(pressTimer); //clear time on mouseup
});
You could set the timeout for that element on mouse down and clear it on mouse up:
$("a").mousedown(function() {
// set timeout for this element
var timeout = window.setTimeout(function() { /* … */ }, 1234);
$(this).mouseup(function() {
// clear timeout for this element
window.clearTimeout(timeout);
// reset mouse up event handler
$(this).unbind("mouseup");
return false;
});
return false;
});
With this each element gets its own timeout.
This worked for me:
const a = document.querySelector('a');
a.oncontextmenu = function() {
console.log('south north');
};
https://developer.mozilla.org/docs/Web/API/GlobalEventHandlers/oncontextmenu
You can use jquery-mobile's taphold. Include the jquery-mobile.js and the following code will work fine
$(document).on("pagecreate","#pagename",function(){
$("p").on("taphold",function(){
$(this).hide(); //your code
});
});
Most elegant and clean is a jQuery plugin:
https://github.com/untill/jquery.longclick/,
also available as packacke:
https://www.npmjs.com/package/jquery.longclick.
In short, you use it like so:
$( 'button').mayTriggerLongClicks().on( 'longClick', function() { your code here } );
The advantage of this plugin is that, in contrast to some of the other answers here, click events are still possible. Note also that a long click occurs, just like a long tap on a device, before mouseup. So, that's a feature.
I needed something for longpress keyboard events, so I wrote this.
var longpressKeys = [13];
var longpressTimeout = 1500;
var longpressActive = false;
var longpressFunc = null;
document.addEventListener('keydown', function(e) {
if (longpressFunc == null && longpressKeys.indexOf(e.keyCode) > -1) {
longpressFunc = setTimeout(function() {
console.log('longpress triggered');
longpressActive = true;
}, longpressTimeout);
// any key not defined as a longpress
} else if (longpressKeys.indexOf(e.keyCode) == -1) {
console.log('shortpress triggered');
}
});
document.addEventListener('keyup', function(e) {
clearTimeout(longpressFunc);
longpressFunc = null;
// longpress key triggered as a shortpress
if (!longpressActive && longpressKeys.indexOf(e.keyCode) > -1) {
console.log('shortpress triggered');
}
longpressActive = false;
});
In vanila JS if need to detect long-click after click released:
document.addEventListener("mousedown", longClickHandler, true);
document.addEventListener("mouseup", longClickHandler, true);
let startClick = 0;
function longClickHandler(e){
if(e.type == "mousedown"){
startClick = e.timeStamp;
}
else if(e.type == "mouseup" && startClick > 0){
if(e.timeStamp - startClick > 500){ // 0.5 secound
console.log("Long click !!!");
}
}
}
May need to use timer if need to check long-click while clicking. But for most case after release click is enought.
For me it's work with that code (with jQuery):
var int = null,
fired = false;
var longclickFilm = function($t) {
$body.css('background', 'red');
},
clickFilm = function($t) {
$t = $t.clone(false, false);
var $to = $('footer > div:first');
$to.find('.empty').remove();
$t.appendTo($to);
},
touchStartFilm = function(event) {
event.preventDefault();
fired = false;
int = setTimeout(function($t) {
longclickFilm($t);
fired = true;
}, 2000, $(this)); // 2 sec for long click ?
return false;
},
touchEndFilm = function(event) {
event.preventDefault();
clearTimeout(int);
if (fired) return false;
else clickFilm($(this));
return false;
};
$('ul#thelist .thumbBox')
.live('mousedown touchstart', touchStartFilm)
.live('mouseup touchend touchcancel', touchEndFilm);
You can check the time to identify Click or Long Press [jQuery]
function AddButtonEventListener() {
try {
var mousedowntime;
var presstime;
$("button[id$='" + buttonID + "']").mousedown(function() {
var d = new Date();
mousedowntime = d.getTime();
});
$("button[id$='" + buttonID + "']").mouseup(function() {
var d = new Date();
presstime = d.getTime() - mousedowntime;
if (presstime > 999/*You can decide the time*/) {
//Do_Action_Long_Press_Event();
}
else {
//Do_Action_Click_Event();
}
});
}
catch (err) {
alert(err.message);
}
}
You can use jquery Touch events. (see here)
let holdBtn = $('#holdBtn')
let holdDuration = 1000
let holdTimer
holdBtn.on('touchend', function () {
// finish hold
});
holdBtn.on('touchstart', function () {
// start hold
holdTimer = setTimeout(function() {
//action after certain time of hold
}, holdDuration );
});
like this?
target.addEeventListener("touchstart", function(){
// your code ...
}, false);