Check when element is double-clicked with middle mouse button - javascript

<div style="width: 250px;
height: 100px;
background-color: Green;
border-style: solid;
border-color: Black;"></div>
With the code above, I create a green box with a black outline. Fiddle.
Below, I have a Javascript function myFunction().
function myFunction() {
window.alert("Hello world!");
}
How do I get this function to run when the user uses his middle mouse button twice in a row with his mouse in the green box (as quickly as how someone double-clicks with his left mouse button)?

Plain JavaScript 1:
Cross browser support
var div = document.getElementsByTagName("div")[0];
var count = 0;
var timeout;
div.onmouseup = function(e){ // thanks RobG, it should be `mouseup`
if(e.which == 2){
count++;
if(!timeout){
timeout = setTimeout(function(){
timeout = undefined;
check();
}, 250);
}
}else{
count = 0;
}
};
function check(){
if(count >= 2){
alert('y');
}
count = 0;
}
DEMO
With jQuery:
Not working in Firefox 27.0 - use "Plain JS 1"
$("div").dblclick(function(e){
if(e.which == 2)
alert('y');
})
DEMO
Plain JavaScript 2:
Doesn't work in Safari 7/FireFox 27.0 - use "Plain JS 1"
var div = document.getElementsByTagName("div")[0];
div.ondblclick = function (e) {
if(e.button == 1) alert('y');
};
DEMO

Start simple. Add a click handler to you div like this:
<div style="width: 250px;
height: 100px;
background-color: Green;
border-style: solid;
border-color: Black;" onclick="myFunction();"></div>
Get that working, then search for how to modify the click event to use other buttons

Here is a function version of Gaurang's answer, however I can't get it to work reliably on Mac OS (nor is Gaurang's answer reliable). Anyway, it might be useful.
// Listener to add
function foo(e) {
console.log(this.id + ':' + e.button);
}
// Main function
var addNonPrimaryDblclick = (function() {
var timeout = null,
count = 0,
delay = 250;
// If timeout expires, reset everything
function checkTimeout() {
if (timeout) {
clearTimeout(timeout);
timeout = null;
count = 0;
}
}
return function(element, listener, newDelay) {
if (typeof newDelay != 'undefined') delay = newDelay;
// Add isDoubleClick as listener
element.addEventListener('mouseup', isDoubleClick, false);
function isDoubleClick(e) {
// A bit of debug
console.log('button: ' + e.button + ' which: ' + e.which);
e.preventDefault();
// 2 is the secondary button, equivalent to 3 in "which" scheme
if (e.button == 2) {
count++;
if (timeout) {
// If this is second click within delay, reset everything
// and call listener
if (count == 2) {
clearTimeout(timeout);
timeout = null;
count = 0;
// Set element to "this" in the listener and pass event
listener.call(element, e);
return;
}
// If no timeout setup, doso
} else {
timeout = setTimeout(checkTimeout, delay);
}
}
}
}
}());
// Example use - set long delay for testing
addNonPrimaryDblclick(document.getElementById('d0'), foo, 1000);

Related

Why is the mousedown event being fired after click instead of during?

I have a div class "guessed" and have a timer to detect whether a short press and long press. When testing, the console logs "MOUSEDOWN" after the press instead of on the press.
The console also logs "SHORT PRESS" even if it's held for longer than 2 seconds.
I've tested the code on JSFiddle and it's working fine. However within my website, the code doesn't work. Can anyone spot the error? Many thanks
var timer = 0;
var timerInterval;
$(document).on('mousedown', '.guessed', function() {
console.log("MOUSEDOWN");
timerInterval = setInterval(function() {
timer += 1;
}, 300);
});
$(document).on('mouseup', '.guessed', function() {
if (timer < 1) {
console.log("SHORT PRESS");
clearInterval(timerInterval);
timer = 0;
return;
}
console.log("LONG PRESS");
clearInterval(timerInterval);
timer = 0;
});
.guessed { border:1px solid red; width:100px; height:100px; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='guessed'>mouse me</div>
You can simply use html attributes for mouseup and mousedown events and call custom defined JavaScript functions just like in the following example :
var timer = 0,timerInterval;
function mousedownfunction() {
console.log("MOUSE DOWN");
timerInterval = setInterval(function() {
timer += 1;
}, 300);
}
function mouseupfunction() {
console.log("MOUSE UP");
if (timer < 1) {
console.log("SHORT PRESS");
clearInterval(timerInterval);
timer = 0;
return;
} else {
console.log("LONG PRESS");
clearInterval(timerInterval);
timer = 0;
return;
}
}
<div class="guessed" onmousedown="mousedownfunction()" onmouseup="mouseupfunction()">
<p>Mouse</p>
</div>

Find x-axis location to make an element move

I'm trying to make an element move backward on the X axis when the user presses "a". However, I don't know how to make it move farther every time the users presses that key :(. I'm new to JS
document.addEventListener("keypress", function (e) {
let moveBy = 20;
if (e.key === "a") {
moveBy++;
element.style.webkitTransform = `translateX(-${moveBy}px)`;
}
}
Thank you!
Define moveBy outside of function and increment every keypress
const element = document.querySelector('div');
let moveBy = 20;
document.addEventListener("keypress", function (e) {
if (e.key === "a") {
moveBy++;
element.style.webkitTransform = `translateX(-${moveBy}px)`;
moveBy+=20
}
})
div {
width: 200px;
height: 200px;
background: red;
}
<div></div>

Touchscreen Press & Hold

I want the user to be able to touch and hold a button, and after a certain period of time, a function is called.
E.g. the button text starts as black, turns orange after 0.2s of pressing, and then green after 0.5s of pressing. If it is green, a function, myFunction(), is triggered.
I have made a start on it, more help would be appreciated. Thanks :)
var btn = document.getElementById("pressBtn");
var pressedTime = 0;
var elaspedHoldTime;
btn.onmousedown = function() {
if (pressedTime != 0) {
pressedTime = performance.now();
} else {
elaspedHoldTime = performance.now() - pressedTime;
}
if (elaspedHoldTime > 200) {
btn.style.color = "orange";
}
if (elaspedHoldTime > 1000) {
btn.style.color = "green";
}
};
btn.addEventListener("mouseup", function() {
elaspedHoldTime = performance.now() - pressedTime;
btn.style.color = "black";
if (elaspedHoldTime > 500) {
console.log("Call Function Here");
}
pressedTime = 0;
elaspedHoldTime = 0;
});
<button id="btn">Button Text</button>
(It also has a bug for some reason)
UPDATED
for not fully functioanlity I edited the code and also changed the logic
I come up with variable timerValue which increases in every 0.1s when mouse is pressed and when that timerValue reaches 2, button changes color to orange and on 5 changes on red and prints triggered as well
and on mouseup which will be called after user picks up finger from mouse, timerValue backs to 0 and resets also button class
interval is variable where are I store setInterval function and on mouse release I clear it
I included also paragpraph tag where is shown the timer to understand how it works
const btn = document.querySelector(".btn")
const timer = document.querySelector("p") //can be deleted
let timerValue = 0
let interval;
const mousePress = () => {
interval = setInterval(() => {
timerValue++
timer.innerHTML = timerValue //can be deleted
if(timerValue === 2) btn.classList.toggle("orange")
if(timerValue === 5) {
btn.classList.toggle("red")
console.log("triggered")
}
}, 100)
}
const mouseRelease = () => {
clearInterval(interval)
timerValue = 0
timer.innerHTML = timerValue //can be deleted
btn.className = "btn"
}
btn.addEventListener("mousedown", mousePress)
btn.addEventListener("mouseup", mouseRelease)
.btn.orange{
color: orange;
}
.btn.red{
color: red;
}
<button class="btn">Click</button>
<p></p>
mousedown, mouseup, touchstart, touchend triggers just once when the key is pressed.
To check, if the user is still holding it, you can check for a truly variable inside a setTimeout() function-call, stop the timeout on release or use a setInterval()-function-call that only runs when it's pressed.
For example:
let pressed = false;
button.addEventListener("mousedown", () => {
pressed = true;
setTimeout(() => {
if (pressed) { ... }
}, 200);
});
button.addEventListener("mouseup", () => { pressed = false; });
let timer = null;
button.addEventListener("mousedown", () => {
pressed = true;
timer = setTimeout(() => { ... }, 200);
});
button.addEventListener("mouseup", () => { clearTimeout(timer) });
As there is already an answer with setTimeout(), here is another solution with setInterval().
let vars = {
interval: null, // used to store the interval id
start: 0, // changes to Date.now() on every start.
// used to avoid myFunction be called more than once per "hold"
myFunctionCalled: false
}, myFunction = () => console.log("Yes...?");
button.addEventListener("mousedown", (event) => {
// avoid start w/ rightclick
if (event.which == 1) {
vars.start = Date.now();
vars.myFunctionCalled = false;
vars.interval = setInterval(() => {
let dur = Date.now() - vars.start;
if (dur > 1000) {
button.style.color = "green";
if (!vars.myFunctionCalled) {
vars.myFunctionCalled = true;
myFunction();
}
} else if (dur > 500) {
button.style.color = "orange";
} else if (dur > 100) {
button.style.color = "red";
}
}, 10);
}
});
// using window, so the user can move the mouse
window.addEventListener("mouseup", (event) => {
// checking again for the mouse key, to avoid disabling it on rightlick
if (vars.interval && event.which == 1) {
// stop the interval and reset the color to default
clearInterval(vars.interval);
button.style.color = "";
vars.interval = null;
}
})
<button id="button">Hold me</button>
If you're making it for a touchscreen, you need to use TouchEvents:
ontouchstart -> when a target is being pressed by a finger
ontouchmove -> the active finger moves off the target
ontouchcancel -> when the the target has lost focus of a touch event
ontouchend -> lifting the finger off of the target
MouseEvents are reserved for mouse / trackpad-controlled devices, such as Computers.
TouchEvents are reserved for touch-screen devices, such as tablets and phones.
Also read this answer for code.

how to make hide/show text javascript smoother?

I am using this script to hide and show text however, I want to make the transition smoother but I am not sure how to. Here's a demo of it: http://jsfiddle.net/LnE5U/.
Please help me change it to make it smoother.
hide/show text
<div id="showOrHideDiv" style="display: none">hidden text</div>
<script language="javascript">
function showOrHide()
{
var div = document.getElementById("showOrHideDiv");
if (div.style.display == "block")
{
div.style.display = "none";
}
else
{
div.style.display = "block";
}
}
</script>
Here is an example using jQuery's fadeToggle (a shortcut for a more complicated animate)
// assuming jQuery
$(function () { // on document ready
var div = $('#showOrHideDiv'); // cache <div>
$('#action').click(function () { // on click on the `<a>`
div.fadeToggle(1000); // toggle div visibility over 1 second
});
});
HTML
<a id="action" href="#">hide/show text</a>
<div id="showOrHideDiv" style="display: none;">hidden text</div>
DEMO
An example of a pure JavaScript fader. It looks complicated because I wrote it to support changing direction and duration mid-fade. I'm sure there are still improvements that could be made to it, though.
function generateFader(elem) {
var t = null, goal, current = 0, inProgress = 0;
if (!elem || elem.nodeType !== 1) throw new TypeError('Expecting input of Element');
function visible(e) {
var s = window.getComputedStyle(e);
return +!(s.display === 'none' || s.opacity === '0');
}
function fader(duration) {
var step, aStep, fn, thisID = ++current, vis = visible(elem);
window.clearTimeout(t);
if (inProgress) goal = 1 - goal; // reverse direction if there is one running
else goal = 1 - vis; // else decide direction
if (goal) { // make sure visibility settings correct if hidden
if (!vis) elem.style.opacity = '0';
elem.style.display = 'block';
}
step = goal - +window.getComputedStyle(elem).opacity;
step = 20 * step / duration; // calculate how much to change by every 20ms
if (step >= 0) { // prevent rounding issues
if (step < 0.0001) step = 0.0001;
} else if (step > -0.0001) step = -0.0001;
aStep = Math.abs(step); // cache
fn = function () {
// console.log(step, goal, thisID, current); // debug here
var o = +window.getComputedStyle(elem).opacity;
if (thisID !== current) return;
if (Math.abs(goal - o) < aStep) { // finished
elem.style.opacity = goal;
if (!goal) elem.style.display = 'none';
inProgress = 0;
return;
}
elem.style.opacity = (o + step).toFixed(5);
t = window.setTimeout(fn, 20);
}
inProgress = 1; // mark started
fn(); // start
}
return fader;
}
And using it
window.addEventListener( // this section matches the code above
'load',
function () {
var fader = generateFader(document.getElementById('showOrHideDiv'));
document.getElementById('action').addEventListener(
'click',
function () {
fader(1000);
}
);
}
);
DEMO of this
This is quite simple. I have just made a demo and i used setInterval
Here's how it works
var fadeout = function( element ) { // 1
element.style.opacity = 1; // 2
window.setInterval(function() { // 3
if(element.style.opacity > 0) { // 4
element.style.opacity = parseFloat(element.style.opacity - 0.01).toFixed(2); // 5
} else {
element.style.display = 'none'; // 6
}
}, 50);
};
JSFiddle Demo Link
Steps
Create a function that accepts a DOM element
Set the opacity of the element to 1
Create a function that loops every 50ms
If the opacity is greater than 0 -> continue
Take away 0.01 from the opacity
if it's less than 0 the animation is complete and hide it completely
Note this is a really simple example and will need a bit of work
You can use somthing like this
$('.showOrHideDiv').toggle(function() {
$('showOrHideDiv').fadeIn('slow', function() {
//fadeIn or fadeOut, slow or fast, all the stuffs you want to trigger, "a function to execute every odd time the element is clicked," says the [jquery doc][1]
});
}, function() {
//here comes "additional handlers to cycle through after clicks," says the [jquery doc][1]
});
I used OPACITY to make it show/hide. See this Example, Full code (without jQuery):
Click here
<div id="MyMesage" style="display:none; background-color:pink; margin:0 0 0 100px;width:200px;">
blablabla
</div>
<script>
function ShowDiv(name){
//duration of transition (1000 miliseconds equals 1 second)
var duration = 1000;
// how many times should it should be changed in delay duration
var AmountOfActions=100;
var diiv= document.getElementById(name);
diiv.style.opacity = '0'; diiv.style.display = 'block'; var counte=0;
setInterval(function(){counte ++;
if ( counte<AmountOfActions) { diiv.style.opacity = counte/AmountOfActions;}
},
duration / AmountOfActions);
}
</script>
I followed iConnor solution and works fine but it had a small issue setInterval will not stop after the element be hidden I added stop interval to make it better performance
var fadeout = function( element ) { // 1
element.style.opacity = 1; // 2
let hidden_process = window.setInterval(function() { // 3
if(element.style.opacity > 0) { // 4
element.style.opacity = parseFloat(element.style.opacity - 0.01).toFixed(2); // 5
} else {
element.style.display = 'none'; // 6
console.log('1');
clearInterval(hidden_process);
}
}, 50);
};

Restart / Refresh Javascript Function or Timer

I have the following code on my website....
At the moment, when "Test 1" is clicked the animation starts. After that, when "Test 2" or "Test 3" is clicked the animation does not restart...
How would I restart the animation when any of the links are clicked ?
And is it possible to have a Fade out and Fade In, after a link has been clicked ?
HTML Markup:
<div id="anim"></div>
</br>
</br>
<li id="item1"><span></span>Test 1</li>
<li id="item2"><span></span>Test 2</li>
<li id="item3"><span></span>Test 3</li>
CSS:
#anim {
width: 14px; height: 14px;
background-image: url(http://mail.google.com/mail/im/emotisprites/wink2.png);
background-repeat: no-repeat;
}
Javascript:
var scrollUp = (function () {
var timerId, height, times ,i = 0 , element;
return {
stop : function(){
clearInterval( timerId );
},
init :function( h, t, el ){
height = h;
times = t;
element =el ;
},
start : function ( ) {
timerId = setInterval(function () {
if (i > times) // if the last frame is reached, set counter to zero
clearInterval(timerId);
element.style.backgroundPosition = "0px -" + i * height + 'px'; //scroll up
i++;
}, 100); // every 100 milliseconds
}
};
})();
scrollUp.init(14, 40, document.getElementById('anim'));
// start animation:
document.getElementById('item1').addEventListener('click', function(){
scrollUp.start();
}, false );
Here's a Fiddle : http://jsfiddle.net/ctF4t/3/
As far as I understand, you want the animation (whatever state it is currently) to restart if one of the buttons is clicked?
Well, if so, first you should call the stop function everytime before the start:
document.getElementById('item1').addEventListener('click', function(){
scrollUp.stop();
scrollUp.start();
}, false );
Additionally, the index has to be reset in the stop:
stop : function(){
clearInterval( timerId );
i = 0;
},
This will do the job for the button #item1. Here is a demo. Applying this to the others should not be the big trouble now. For example bind the event to the <body/> and read the target:
function startAnimation(e) {
e = e || window.event;
var target = e.target || e.srcElement;
target = target.parentNode;
if (!target.id.match(/item[0-3]/)) {
return e;
}
scrollUp.stop();
scrollUp.start();
}
document.body.addEventListener('click',startAnimation,false);
Here is the complete demo.
How would I restart the animation when any of the links are clicked ?
To define a restart, you'll want to stop any still-running intervals, reset i to 0 since that marks the "beginning," and start a new interval:
return {
// ...
restart: function () {
this.stop();
i = 0;
this.start();
}
};
You then need to bind to each li so they can all perform a restart():
var items = document.querySelectorAll('#item1, #item2, #item3');
for (var i = 0, l = items.length; i < l; i++) {
items[i].addEventListener('click', function () {
scrollUp.restart();
}, false);
}
I changed your fiddle to this: http://jsfiddle.net/M5pe8/1/
It seems you didn't reset the "i" var, so the animation couldn't restart from the beginning (i.e., from "zero"); i left the alert line (but is commented out), to show you how i got to my conclusions:
if (i > times) // if the last frame is reached, set counter to zero
{
//alert(i + ' > ' + times);
clearInterval(timerId);
i = 0;
}
else
{
element.style.backgroundPosition = "0px -" + i * height + 'px'; //scroll up
i++;
}
And, of course, i added the lines to bind the click event that starts the animation to the other two links (just for completeness). Now, clicking the second time the animation restarts. Is that what you needed?
EDIT: Link to fiddle corrected

Categories

Resources