Updated (with additions from answer)
(function($) {
$.fn.longpress = function(longCallback, duration) {
// set some defaults
let defaults = {
click: function(el, e) {},
start: function(el, e) { el.css("color", "#000"); },
complete: function(el, e) { el.css("color", "#FFF"); },
cancel: function(el, e) { el.css("color", "#F00"); },
duration: 1000
};
// extend the options
let options = $.extend({}, defaults);
return this.each(function() {
var $this = $(this);
// to keep track of how long something was pressed
var mouse_down_time;
var timeout;
$this.data("clicked", "false");
// mousedown or touchstart callback
function mousedown_callback(e) {
// start callback
options.start($this, e);
$this.data("clicked", "true");
mouse_down_time = new Date().getTime();
var context = $(this);
// set a timeout to call the longpress callback when time elapses
timeout = setTimeout(function() {
if (typeof longCallback === "function") {
longCallback.call(context, e);
options.complete($this, e);
$this.data("clicked", "false");
} else {
$.error('Callback required for long press. You provided: ' + typeof longCallback);
}
}, options.duration);
}
// mouseup or touchend callback
function mouseup_callback(e) {
var press_time = new Date().getTime() - mouse_down_time;
if (press_time < options.duration) {
// cancel the timeout
clearTimeout(timeout);
$this.data("clicked", "false");
// call the click if provided
options.click($this, e);
}
}
// cancel long press event if the finger or mouse was moved
function move_callback(e) {
let isClicked = $this.data("clicked");
if (isClicked == "false")
return;
// call the cancel callback
options.cancel($this, e);
clearTimeout(timeout);
$this.data("clicked", "false");
}
// Browser Support
$this.on('mousedown', mousedown_callback);
$this.on('mouseup', mouseup_callback);
$this.on('mousemove', move_callback);
// Mobile Support
$this.on('touchstart', mousedown_callback);
$this.on('touchend', mouseup_callback);
$this.on('touchmove', move_callback);
});
};
}(jQuery));
I have a jQuery plugin that I found a while ago (cant remember the source) which allowed me to have long press features on a website:
(function(b) {
b.fn.longpress = function(e, c, d) {
"undefined" === typeof d && (d = 1000);
return this.each(function() {
function g(a) {
h = (new Date).getTime();
var c = b(this);
f = setTimeout(function() {
"function" === typeof e ? e.call(c, a) : b.error("Callback required for long press. You provided: " + typeof e)
}, d)
}
function k(a) {
(new Date).getTime() - h < d && (clearTimeout(f), "function" === typeof c ? c.call(b(this), a) : "undefined" !== typeof c && b.error("Optional callback for short press should be a function."))
}
function l(a) {
clearTimeout(f)
}
var a = b(this),
h, f;
a.on("mousedown", g);
a.on("mouseup", k);
a.on("mousemove", l);
a.on("touchstart", g);
a.on("touchend", k);
a.on("touchmove", l)
})
}
})(jQuery);
It works great, but I was wondering if there was a way to have say the background go from #fff
to #000
or make any other custom animation based on the duration of the long press.
I was toying around, but couldn't figure it out. I was trying to add a class for every second the long press was held, then have a CSS rule for each. I then tried using steps
in CSS to make it time too, but couldn't get that to work as the classes would only add when the long press was successful not loading.
The original plugin can be found here: https://github.com/vaidik/jquery-longpress.
I have modified to accept an object of options (explained in comments). Here is an example:
(function($) {
$.fn.longpress = function(opts) {
let defaults = {
click: function(el, e) {},
start: function(el, e) {},
complete: function(el, e) {},
duration: 500
};
let options = $.extend({}, defaults, opts);
return this.each(function() {
var $this = $(this);
// to keep track of how long something was pressed
var mouse_down_time;
var timeout;
$this.data("clicked", "false");
// mousedown or touchstart callback
function mousedown_callback(e) {
// start callback
options.start($this, e);
$this.data("clicked", "true");
mouse_down_time = new Date().getTime();
var context = $(this);
// set a timeout to call the longpress callback when time elapses
timeout = setTimeout(function() {
options.complete($this, e);
$this.data("clicked", "false");
}, options.duration);
}
// mouseup or touchend callback
function mouseup_callback(e) {
var press_time = new Date().getTime() - mouse_down_time;
if (press_time < options.duration) {
// cancel the timeout
clearTimeout(timeout);
$this.data("clicked", "false");
// call the click if provided
options.click($this, e);
}
}
// cancel long press event if the finger or mouse was moved
function move_callback(e) {
let isClicked = $this.data("clicked");
if (isClicked == "false")
return;
// call the cancel callback
options.cancel($this, e);
clearTimeout(timeout);
$this.data("clicked", "false");
}
// Browser Support
$this.on('mousedown', mousedown_callback);
$this.on('mouseup', mouseup_callback);
$this.on('mousemove', move_callback);
// Mobile Support
$this.on('touchstart', mousedown_callback);
$this.on('touchend', mouseup_callback);
$this.on('touchmove', move_callback);
});
};
}(jQuery));
let options = {
// Callback after a "normal" click has completed
click: function(el, event) {
el.removeClass("rotate");
},
// callback after longpress completed
complete: function(el, event) {
el.removeClass("rotate");
},
// callback before click starts (for both normal and longpress clicks)
start: function(el, event) {
el.addClass("rotate");
},
// Callback when click is cancelled (user moves mouse)
cancel: function(el, event) {
el.removeClass("rotate");
},
// Longpress duration
duration: 5000
};
$('#button').longpress(options);
div {
border: 1px solid;
width: 200px;
height: 200px;
left: 50px;
top: 50px;
position: relative;
}
.rotate {
animation: 1s rotate infinite linear;
}
@keyframes rotate {
100% {
transform: rotate(1turn);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='button'>
</div>
Since you define the plugin, you can add some behaviors. One way to animate would be to use transitions based on classes you would add at different steps. And for the duration you can define it in the plugin so it has the same length as the longpress delay. Like this for example:
(function(b) {
b.fn.longpress = function(e, c, d) {
"undefined" === typeof d && (d = 1000);
return this.each(function() {
function g(a) {
h = (new Date).getTime();
var c = b(this);
// here you define transition duration using user defined or default long press delay
c.css("transition-duration", d + 'ms');
// the class while element is being pressed
c.addClass("pressing");
f = setTimeout(function() {
// when delay is done you remove pressing, add another class to signify the element has been long pressed
c.removeClass("pressing").addClass("pressed");
"function" === typeof e ? e.call(c, a) : b.error("Callback required for long press. You provided: " + typeof e)
}, d)
}
function k(a) {
// this is the cancel callback, so you remove pressing
$(this).removeClass("pressing");
(new Date).getTime() - h < d && (clearTimeout(f), "function" === typeof c ? c.call(b(this), a) : "undefined" !== typeof c && b.error("Optional callback for short press should be a function."))
}
function l(a) {
clearTimeout(f)
}
var a = b(this),
h, f;
a.on("mousedown", g);
a.on("mouseup", k);
a.on("mousemove", l);
a.on("touchstart", g);
a.on("touchend", k);
a.on("touchmove", l)
})
}
})(jQuery);
$('#a').longpress(function(e) {
this.text('pressed')
}, function() {}, 1500)
div {
background-color: #fff;
transition: background-color;
transition-timing-function: linear;
cursor: pointer;
}
.pressing {
background-color: #000;
}
.pressed {
background-color: #FF0;
transition: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id=a>
long press me
</div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With