Detect move of mouse while clicked and detect doubleclick - javascript

for the moment I have implemented different actions for when a person clicks on a canvas and when a person clicks and drags something. I did this by binding the mousedown event to my canvas and in that function there is made the difference between a drag or a mouseup. This works very good, but I have a problem when I also want to support doubleclicking on elements.
The normal way to implement this is like this:
$(canvas).click(function1);
$(canvas).dblclick(function2);
but I didn't implemented that way because I had to check whether or not the mouse moved (i.e. dragged). This is my current implementation:
var handler = {
clicked:function(e){
...
$(canvas).bind('mousemove', handler.dragged);
$(window).bind('mouseup', handler.dropped);
},
dragged:function(e){
...
},
dropped:function(e){
function loop(ctr){
if (ctr < 50) {
setTimeout(function(){loop(ctr+1)}, 2);
} else {
$(canvas).mousedown(handler.clicked);
handler.singleClick(e);
}
}
$(canvas).mousedown(handler.doubleclicked);
loop(0);
},
doubleClick: function(e){
...
},
singleClick: function(e){
...
}
}
$(canvas).mousedown(handler.clicked);
I tried to combine those two things (recognition of dragging and doubleclick) by implementing the dropped-function which waits for a period of time to listen for another click and if it didn't occur within that period it goes to the singleclick function. For the moment this not yet recognizes the second click.
I assume that there exist better ways to do this?

You might want to look at this:
http://threedubmedia.com/code/event/drag
It provides you with additional functionality .drag() in addition to .click() and .dblclick().
Theres also a drop version:
http://threedubmedia.com/code/event/drop

Related

How to decide the triggering order of different mouseDown function

I have two kinds of functions which will detect the mousedown event and trigger some functions.
window.onmousedown = function(...)
Raphael object:
var rec = paper.rect(10,10,10,10)
rec.mousedown(...)
the second one is a rectangle create by Raphael.js and the function will be triggered when you click the rectangle.
I need the second one to be triggered before the first one, but it seems that the order of triggering of the two functions is randomly decided by the browser?
Do I have any way to control it !?
thanks!!
I need the second one to be triggered before the first one
Look at the DEMO, mousedown even triggers on circle before window's.
window.onmousedown = function()
{
alert('Yes');
}
var paper = new Raphael(document.getElementById('paper'),500,400);
var circle = paper.circle(100,100,50).attr({fill:'orange', stroke:'green', 'stroke-width':3});
circle.mousedown(function() {
alert('No');
this.attr({fill:'green', stroke:'red', 'stroke-width':3});
});
circle.mouseout(function() {
this.attr({fill:'orange', stroke:'green', 'stroke-width':3});
});
Click on the circle and see that the alerts. Good luck

How defined in jQuery was it a regular click on the same element or double-click?

How can I define in jQuery was it a regular click on the same element or double-click?
For example we have element like this:
<div id="here">Click me once or twice</div>
And we need to perform different actions after regular click and double-click.
I tried something like this:
$("#here").dblclick(function(){
alert('Double click');
});
$("#here").click(function(){
alert('Click');
});
But, of course, it doesn't work, everytime works only 'click'.
Then, some people showed me this:
var clickCounter = new Array();
$('#here').click(function () {
clickCounter.push('true');
setTimeout('clickCounter.pop()', 50);
if (clickCounter.length > 2) {
//double click
clickCounter = new Array(); //drop array
} else {
//click
clickCounter = new Array(); //drop array !bug ovethere
}
});
Here we tried to set the interval between clicks, and then keep track of two consecutive events, but this have one problem.. it doesn't work too.
So, someone knows how to do this? or can someone share a link to the material, where I can read about it?
From QuirksMode:
Dblclick
The dblclick event is rarely used. Even when you use it, you should be
sure never to register both an onclick and an ondblclick event handler
on the same HTML element. Finding out what the user has actually done
is nearly impossible if you register both.
After all, when the user double–clicks on an element one click event
takes place before the dblclick. Besides, in Netscape the second click
event is also separately handled before the dblclick. Finally, alerts
are dangerous here, too.
So keep your clicks and dblclicks well separated to avoid
complications.
(emphasis mine)
What you are doing in your question, is exactly how it should be done.
$(".test").click(function() {
$("body").append("you clicked me<br />");
});
$(".test").dblclick(function() {
$("body").append("you doubleclicked me<br />");
});
It works and here is an demo for that.
Since, you want to detect separate single double click. There is a git project for this.
$("button").single_double_click(function () {
alert("Try double-clicking me!")
}, function () {
alert("Double click detected, I'm hiding")
$(this).hide()
})
It adds up events to detect single double clicks.
Hope it helps you now.

If else statement for javascript click event

I have two statements. What I am trying to do is when someone clicks on #area_a then hide then entire #area_b div without activating the focusout for the #area_b_textbox. But I've tried different code (which I am not including here because it is incorrect and want to get your suggestions) and what is happening is it is activating the focusout everytime I click on the #area_a div.
JQuery base actions
$("#area_a").click(function() { $("#area_b").hide(); });
$("#area_b_textbox").focusout(function() {$("#area_b_error").show();});
HTML:
<div id="area_a"></div>
<div id="area_b">
<input id="area_b_textbox">
<div id="area_b_error"></div>
</div>
Thanks!
You could hack around the problem with a timer. Timers usually smell bad but I think it is your safest bet here. If you try using hover or other mouse events you might run into trouble with keyboard navigation and activation or the lack of "hoverish" events on touch interfaces (and we can't pretend those don't exist anymore).
Something like this:
var timer_kludge = {
start: function(fn) {
this.id = setTimeout(fn, 200);
},
stop: function() {
if(this.id)
clearTimeout(this.id);
this.id = null;
},
id: null
};
$('#area_a').click(function() {
timer_kludge.stop();
$('#out').append('<p>click</p>');
});
$('#area_b_textbox').focusout(function() {
timer_kludge.start(function() {
$('#out').append('<p>textarea focusout</p>');
});
});
$('#area_b_textbox').focusin(function() {
timer_kludge.stop();
});
Demo: http://jsfiddle.net/ambiguous/s8kw8/1/
You'd want to play with the 200 timeout a bit to see what works best in your circumstances.
Why not just add a flag to ignore next focusout (blur?) event.
ignoreNextFocus = false;
$("#area_a").click(function() { ignoreNextFocus=true; $("#area_b").hide(); });
$("#area_b_textbox").focusout(function() { if(!ignoreNextFocus)$("#area_b_error").show();ignoreNextFocus=false;});
On that note setting the flag on click event might be too late. If it is the case, try mousedown event.
this is not possible since you loose the focus automatically when you click somewhere else...
What you need to do is to unbind the focusout event on hover of the #area_a and rebind it later on...
$("#area_a").click(function() {
$("#area_b").hide()
}),hover(
function(){
$("#area_b_textbox").unbind("focusout")
},
function(){
$("#area_b_textbox").focusout(function() {$("#area_b_error").show();});
}
)
PS: what is your ultimate goal here?
I'm not sure this is possible since by definition the focus has to leave the #area_b_textbox if the user is going to click a button.

Make (possibly dynamically loaded) element clickable via JavaScript, but give precedence to links contained within

I am adding a custom data attribute data-js-href to various HTML elements, and these elements should behave just like a link when clicked. If a link within such an element is clicked, the link should take precedence and the data-js-href functionality should be ignored, though. Furthermore, the solution also needs to work with elements that are dynamically added at a later time.
So far, I have come up with the following solution. It basically checks if the click was performed on a link, or any child element of a link (think <a href='…'><img src='…' alt='…' /></a>).
// Make all elements with a `data-js-href` attribute clickable
$$('body').addEvent('click:relay([data-js-href])',
function(event, clicked) {
var link = clicked.get('data-js-href');
if (link && !event.target.match('a')) {
var parents = event.target.getParents();
for (var i = 0; i < parents.length && parents[i] != clicked; i++) {
if (parents[i].match('a')) {
return;
}
}
document.location.href = link;
}
});
It works, but it feels very clumsy, and I think that there has to be a more elegant solution. I tried something along the lines of
$$('body').addEvent('click:relay([data-js-href] a)',
function(event, clicked) {
event.stopPropagation();
}
but to no avail. (I littered the code with some console.log() messages to verify the behavior.) Any idea is welcome.
you can do this with 2 delegated events - no reverse lookups and it's cheap as they will share the same event. the downside is, it is the same event so it will fire for both and there's no stopping it via the event methods (already bubbled, it's a single event that stacks up multiple pseudo event callbacks and executes them in order--the event has stopped but the callbacks continue) That's perhaps an inconsistency in mootools event vs delegation implementation but it's a subject of another issue.
Workarounds for now can be:
to have the 2 event handlers communicate through each other. It will scale and work with any new els added.
to add the delegators on 2 different elements. eg. document.body and #mainWrap.
http://jsfiddle.net/dimitar/J59PD/4/
var showURL = function(howLong) {
// debug.
return function() {
console.log(window.location.href);
}.delay(howLong || 1000);
};
document.id(document.body).addEvents({
"click:relay([data-js-href] a))": function(e) {
// performance on lookup for repeat clicks.
var parent = this.retrieve("parent");
if (!parent) {
parent = this.getParent("[data-js-href]");
this.store("parent", parent);
}
// communicate it's a dummy event to parent delegator.
parent.store("linkEvent", e);
// let it bubble...
},
"click:relay([data-js-href])": function(e) {
// show where we have gone.
showURL(1500);
if (this.retrieve("linkEvent")) {
this.eliminate("linkEvent");
return;
}
var prop = this.get("data-js-href");
if (prop)
window.location.href = prop;
}
});
Discussed this with Ibolmo and Keeto from the mootools team on IRC as well when my initial attempt failed to work and both callbacks fired despite the event.stop: http://jsfiddle.net/dimitar/J59PD/
As a result, there was briefly a ticket open on the mootools github issues: https://github.com/mootools/mootools-core/issues/2105 but it then went into a discussion of what the right thing to do from the library standpoint is and how viable it is to pursue changing the way things work so...

How to Show Ballon tooltip when mouse stops

[edit]
So I used one of the javascript tooltips suggested below. I got the tips to show when you stop and hide if you move. The only problem is it works when I do this:
document.onmousemove = (function() {
var onmousestop = function() {
Tip('Click to search here');
document.getElementById('MyDiv').onmousemove = function() {
UnTip();
};
}, thread;
return function() {
clearTimeout(thread);
thread = setTimeout(onmousestop, 1500);
};
})();
But I want the function to only apply to a specific div and if I change the first line to "document.getElementById('MyDiv').onmousemove = (function() {" I get a javascript error document.getElementById('MyDiv') is null What am I missing....??
[/edit]
I want to display a balloon style message when the users mouse stops on an element from more than say 1.5 seconds. And then if they move the mouse I would like to hide the balloon. I am trying to use some JavaScript code I found posted out in the wild. Here is the code I am using to detect when the mouse has stopped:
document.onmousemove = (function() {
var onmousestop = function() {
//code to show the ballon
};
}, thread;
return function() {
clearTimeout(thread);
thread = setTimeout(onmousestop, 1500);
};
})();
So I have two questions. One, does anyone have a recommended lightweight javascript balloon that will display at the cursor location. And two, the detect mouse stopped code works ok but I am stumped on how to detect that the mouse has started moving again and hide the balloon. Thanks...
A bit late to be answering this, but this will be helpful for those in need.
I needed this function to be able to detect when the mouse stopped moving for a certain time to hide an HTML/JS player controller when hovering over a video. This is the revised code for the tooltip:
document.getElementById('MyDiv').onmousemove = (function() {
var onmousestop = function() {
Tip('Click to search here');
}, thread;
return function() {
UnTip();
clearTimeout(thread);
thread = setTimeout(onmousestop, 1500);
};
})();
In my case, I used a bit of jQuery for selecting the elements for my player controller:
$('div.video')[0].onmousemove = (function() {
var onmousestop = function() {
$('div.controls').fadeOut('fast');
}, thread;
return function() {
$('div.controls').fadeIn('fast');
clearTimeout(thread);
thread = setTimeout(onmousestop, 1500);
};
})();
The jQuery plugin hoverIntent provides a similar behaviour. It determines if the user 'meant' to hover over a particular element by checking if they slow the mouse down moving into the elements and spend a certain amount of time hovering over the element.
It only fires the "out" event when the user leaves the element, which doesn't sound like exactly what you're looking for, but the code is pretty simple.
Also watch out for binding things to mousemove when you don't need to be collecting the events, mousemove fires a lot of events quickly and can have serious effects on your site performance. hoverIntent only binds mousemove when the cursor enters the active element, and unbinds it afterwards.
If you do try hoverIntent I have had some trouble with the minified version not firing "out" events, so I would recommend using the full, unminified source.
Here's a nifty jQuery plugin for a nice float over tool tip.
http://jqueryfordesigners.com/demo/coda-bubble.html
[edit]
I guess without seeing the companion HTML it's hard to say what's wrong. I'd double check that the element has the appropriate ID specified in the tag. Apart from that, unless this is an academic exercise, I would suggest using something like the jQuery plugin that I referenced above. There are certainly many other pre-built tools like that which will have already dealt with all of the minutiae you're currently addressing.
document.onmousemove = (function() {
if($('balloon').visible) {
//mouse is moving again
}....//your code follows
Using Prototype.js syntax you can determine that the mouse has moved once the balloon is visible.

Categories