Button Click Issues - javascript

I'm using buttons which when clicked on move fractionally down.
.button:active {
position: relative;
top: 2px;
}
The problem I'm having is users occasionally click right at the top of button, either just under or on the buttons border.
When the click goes down the button moves down and the cursor is no longer above the button. As a result a click is not actually registered.
I've replicated this in a fiddle:
http://jsfiddle.net/DJNEb/3/
If you click right on the top edge of the button, the button moves, but the click event handler is not fired. I'm seeing this behaviour in IE, Firefox, Chrome.
How can I resolve this?

I would put the button inside a div and add the event on the div, this way you can keep your effect without over complicating your code.
Another way would be to treat the mousedown and mouseup events and check if the cursor position has changed

Basically click() event is disturbed by the :active state moving objects.
Read more here.
Your solution by the way is a little different from the one of that answer;
Starting from the solution proposed by #cdanisor, you need to use mouseup() (in order to preserve the moving effect of the button AND to fire the event only when mouse is released)
Demo: http://jsfiddle.net/kEQjU/
<div id="alertMe">
<div class="button red"> test</div>
</div>
$("#alertMe").mouseup(function() {
alert("Handler for .click() called.");
});
EDIT
Obviously you can preserve the keyboard compatibility by using a button instead of a div, and binding the same function to the keyup event:
Demo: http://jsfiddle.net/kEQjU/1/
<div id="alertMe">
<input type="button" class="button red" value="test" />
</div>
$("#alertMe").mouseup(function() {
alert("Handler for .click() called.");
});
$("#alertMe").keyup(function() {
alert("Handler for .click() called.");
});

Related

jQuery event handling / propagation / bubbling?

I'm trying to create a menu for a website, I'm using jQuery for this and I've run into a little problem.
I have this structure
<div class="menuTitle menuDiv menuNode" id="menuNode_<?=$row_menu["id"]?>">
<a href="<?=$rt?>" class="menuAnchor" onclick="return registerMenuClick($(this).parent())">
<span><?=$nodeName?></span>
</a>
</div>
<div class="menuSelect" id="menuSelect_<?=$row_menu["id"]?>" align="center"><?=$nodeName?></div>
And in jQuery, I have
$(document).ready(function(){
$(".menuNode, .menuSelect").live("mouseover",function(event){
MenuBar.selectedID = $(this).attr("id").replace("menuNode_","").replace("menuSelect_","");
MenuBar.showThisBranch();
}).live("mouseout",function(event){
MenuBar.selectedID = $(this).attr("id").replace("menuNode_","").replace("menuSelect_","");
MenuBar.hideThisBranch();
});
})
When the user hovers over menuNode, the menuSelect should be shown (that, it does), but if I hover over menuAnchor, or the span, it fires the mouseout event, and then the mouseover event.
So, if say, I had the mouse over menuNode, and the move over to the span and then out to menuNode again, it would fire the mouseover event 3 times. I've had this behavior before on a click event, but it seems the method used to resolve this does not work on this problem.
Any suggestions?
As #Beetroot-Beetroot suggested, mouseenter/mouseleave helped, coupled with a TimeOut to change from the menuNode to the menuSelect (300 miliseconds on enter, 500 on leave).

onClick event doesn't fire if you move mouse

I have a simple button like this:
<a class="button" href="javascript:void(0);" onclick="submitActivity();">Add</a>
I also tried with:
<a class="button" href="javascript:submitActivity();">Add</a>
In both cases, it doesn't register the click if the mouse has moved a certain amount of pixels between mousedown and mouseup. This can lead users to believe they have submitted the info when they didn't
This is happening in Chrome. Haven't tested other browsers.
I want the event to fire regardless of where in the button you click and release.
Edit: The same thing is happening in Firefox, but visually it looks like I'm dragging the link. This way it at least makes sense to the user that it doesn't submit, but in Chrome there are no such visual indicator of what is happening.
A click is defined as "holding down the mouse button, and then letting go of the mouse button." It is a combination of a mouse down and mouse up event executed on the same element. If the user moves away from the element, they are no longer executing a click, simply a mousedown (and also a mouseout, and then a mouseup on a different element).
This is standard, intuitive behavior. Users don't expect their click to "matter" unless they let go of the mouse without moving.
If for your application it is really important than ANY click result in this submit happening for you, then don't go with an onclick, go with onmousedown.
<a class="button" href="javascript:void(0);" onmousedown="submitActivity();">Add</a>
EDIT: Misunderstood your problem. Perhaps this syntax that I am used to will work for you will work for you:
<INPUT type="button" value="Add" name="add_button" onClick="submitActivity()">
Solution was to do a preventDefault() on onmousedown.
$(".button").mousedown(function(event){
event.preventDefault();
return false;
});
Demo fiddle
<a class="button" href="javascript:void(0);" onMouseDown="submitActivity();">Add</a>
I stumbled upon the same problem but in another context. I created custom buttons using divs with onclick="..." and placing child divs into them for the button text and icon. When moving the cursor even one pixel over a child div between mousedown and mouseup, the parent div generated a mouseout event which prevented the click event to be fired. I could not find a way to disable the mouseout event, but found a simple CSS-solution to this problem. Just disable pointer-events for all children:
.buttondiv * {
pointer-events: none; /* prevent click problems in buttons containing child divs */
}

Prevent firing focus event when clicking on div

This question is similar to my previous question, Click action on Focused DIV,
but this time the main topic is, How to prevent focus event from triggering when I click one of the divs.
Last time I had one div with tabindex='-1' to make it focusable on click, now I have a list of divs with tabindex>0 so they can gain focus when tabbing as well.
<div tabindex='1'>Div one</div>
<div tabindex='1'>Div two</div>
<div tabindex='1'>Div tree</div>
<div tabindex='1'>Div four</div>
some styling:
div {
height: 20px;
width: 60%;
border: solid 1px blue;
text-align: center;
}
div:focus {
border: solid 2px red;
outline: none;
}
Now I'm using a flag(action) to fire an action(alert) when clicking the div for 2nd time, and with just one click if it's already focused,with TAB for example.
var action = false;
$('div')
.click(function(e){
e.stopImmediatePropagation();
if(action){alert('action');}
action = true;})
.focus(function(){action = true;})
.blur(function(){action = false;});
The problem with the code above is focus event is being fired, which means stopImmediatePropagation doesn't work the way I expected.. The two click action works commenting the focus event line, but you still need to double click when div gains focus on TAB.
Here is the example: http://jsfiddle.net/3MTQK/1/
DEMO here
I think you are missing some parts here,
event.stopPropagation() is used to stop the event from bubbling. You can read about it here.
event.stopImmediatePropagation() In addition to keeping any additional handlers on an element from being executed, this method also stops the bubbling by implicitly calling event.stopPropagation(). You can read about it here
If you want to stop browser events, then you should use event.preventDefault(). You can read about it here
click = mousedown + mouseup -> The focus will be set on a HTML element when the mouse down is successful. So instead of binding click event, you should use 'mousedown'. See my demo.
You cannot use 1 action boolean value to determine which div is clicked and how many times it has been clicked. Check my Demo to see how you can handle that.
To simply prevent firing focus when clicking on div just use mousedown + event.preventDefault(). Use mousedown rather than click because, as #Selvakumar Arumugam explained, focus fires when mousedown is succesfull and event.preventDefault() will stop browser events (including our focus).
Here's a code example:
$('#div').on('mousedown', function(event) {
// do your magic
event.preventDefault();
});
Simply,
// ❌ Don't (focus already set on mouse down)
onClick={e => e.preventDefault()}
// ✔️ Do (prevent focus)
onMouseDown={e => e.preventDefault()}
For the moment the apparent answer would be to restrict your selector from simply 'div' to a system of toggled class names, thereby you could control on what element your focus event would fire. It is more tedious and requires a bit more exception coding, but would do the job.
var action = false;
$('div')
.click(function(e){
e.stopImmediatePropagation();
if(action){alert('action');}
action = true;})
.focus(function(){action = true;})
.blur(function(){action = false;});

How do you avoid losing focus on a contenteditable element when a user clicks outside that element?

I want to prevent a contentEditable area from losing focus if a click is made outside that area. Some sample HTML looks like this:
<div id="content">
<p>Hello</p>
</div>
<div id="clickThis">
<p>If you click on this or anywhere for that matter after focusing on Hello, you lose your focus on Hello</p>
</div>
Sample Javascript looks as follows:
$(document).ready(function()
{
$('#content')[0].contentEditable=true;
$('#clickThis').bind('click',function(e)
{
console.log(window.getSelection().getRangeAt(0).startContainer);
e.preventDefault();
});
});
When you click on the #clickThis div or anywhere outside the #content div, you lose focus on the #content div even if you call the click event's preventDefault function.
In addition, the range changes the moment the click event is fired, so I can't just return to the previous range after the click has occurred. Is there a way to maintain the cursor position and focus after a click occurs?
jsFiddle: http://jsfiddle.net/VivekVish/FKDhe/4/
Putting Juan's question into an answer, instead of using the click event, you have to use the mousedown event as follows:
$(document).ready(function()
{
$('#content')[0].contentEditable=true;
$('#clickThis').bind('mousedown',function(e)
{
console.log(window.getSelection().getRangeAt(0).startContainer);
e.preventDefault();
});
});
You can see it working here:
http://jsfiddle.net/FKDhe/7/
The answer is to add event.preventDefault() to the mouseDown event.
const button = document.getElementById('boldFormat')
button.addEventListener('mousedown', (event) => {
event.preventDefault() // prevent loss of focus
document.execCommand('bold', false)
})
The problem occurred because the you are listening to the click event which causes the contentEditable element to lose focus; regardless of whether you run preventDefault or not.
try adding $('#content').focus(); after e.preventDefault();
it's not a perfect solution, since it jumps to the beginning, but give it a try.
anyway, are you sure it's a good idea to force the user back to this area? :)

How can I make a right-click behave as a left-click for the purpose of selecting or focusing an object

Event though a right-click (as far as I know) fires a mousedown event, that mousedown seems to be ignored in most cases. I'm currently working on displaying a custom context menu via a right-click, but I'd also like to be able to select an option from a list while I'm right-clicking. As of right now my recognizes the click from both buttons enough to run some javascript tied to the onmousedown attribute but not enough to select the option the mouse is over when the mousedown comes from the right button.
Is there a way to bypass a browser's default behavior of ignoring the mousedown event of a right-click or fool it into thinking the mousedown was generated by the left button instead?
Thanks in advance.
You can use the oncontextmenu event.
Edit: To simulate the default click behavior on an <option> during a right mouse click, put this code in your event handler when handling right click:
clickedOption.parentNode.selectedIndex = clickedOption.index;
If you are willing to use jQuery, you can simply use mousedown:
$(document).bind('contextmenu', function(event)
{
// on right click
if (event.which == 3)
{
// prevent right click from being interpreted by the browser:
event.preventDefault();
$(document).mousedown(); // simulate left click
}
});
Of course you can use a fitting selector. This is great since that way, the right click is only serving as a left click on certain elements of your website. That way, it's still possible to use the mouse as expected most of the time (depending on your selectors).
EDIT: better example
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script>
$(document).ready(function() {
$("#rightclick").bind('contextmenu', function(event) {
// on right click
if (event.which == 3)
{
// prevent right click from being interpreted by the browser:
event.preventDefault();
$(this).click(); // simulate left click
}
});
$('#rightclick').click(function() {
$(this).html("i have been clicked!");
});
});
</script>
</head>
<body>
<p>This is a web page.</p>
<div id="rightclick" style="width:200px; height:100px; background-color: orange">
Click me with the right or left mouse button. Both will work!
</div>
</body>
</html>

Categories