I am working on a web app in which I want to have a different action happen to an element whether I left or right click on it.
So I first added a function to handle the click event with jQuery, and then added a second function to handle the oncontextmenu attribute of my element.
This is working well in Chrome & IE but causes a problem in Firefox: When I right click on an element, my function that handles the left click is surprisingly called, and then my function that handles the right click is called.
How can I make Firefox not call the left-click function when I right click?
Yeah, browsers traditionally send right-clicks to the onclick handler, with the event.which property set to 3 instead of 1. IE used oncontextmenu instead, then Firefox picked up oncontextmenu in addition to the usual onclick. To cater for the browsers you will have to catch both events — or find a plugin that will do it for you.
Note that even with this sorted out, you are still not guaranteed to get right click events or be able to disable the standard context menu. Because many web pages abused the ability, it is disablable in many browsers, and sometimes disabled by default (eg. in Opera). If your app provides right-click actions, always ensure there is an alternative way to bring them up.
My problem came from the fact that on one side I was using the insanely great jQuery live function for click and the oncontextmenu attribute on the other. (Using onclick and oncontextmenu was not a problem).
I've just modified my $.live("click"...) function by catching the event and not firing the rest when e.which is 3.
Problem solved!
Related
I use AngularJS 1.4.7
I have editable input. If we focus on input and after click outside of this input field, script will do function "save()" in ng-blur. Everything work correctly, but on iPhone 5/6 and iPad don't work (not execute anything in ng-blur). I don't know why, but I deduce that problem is in focus/touch action. Someone know where is the problem?
Fix ng-blur not working on empty space and most elements with iOS
Goal
In my app, we wanted to hide open menus or search results when clicking away from
the menu or search box.
Problem
iOS Safari does not blur properly when clicking away from the current element.
Note
You do not need a special directive. The problem is not with ng-blur, which works fine. The problem is that a blur event never occurs because of Apple's unusual design on iOS, regardless of whether you use ng-blur or a native DOM blur event.
Reason for Issue
Apple has designed mobile Safari to perform event bubbling differently than desktop browsers do. According to official Apple docs, if an element that is clicked has no click listener attached to it, then no click event is triggered. Without a click event, focus does not change and no blur event occurs, so the current element does not lose focus even though the user really did click elsewhere on the page.
The blur will only happen if the user clicked an element with a click event listener. Some elements like hyperlinks and inputs have "built-in" event listeners for click, and so will always register a click, causing blur to work.
Normally in desktop browsers, the click event is blindly fired whether there is a registered listener or not in the element's DOM hierarchy. That is why ng-blur works as expected in desktop browsers, even on "empty space".
Apple says that for iOS Safari they only dispatch the event if they find an element registered to listen for it.
Apple Docs - go to Figure 6-4
Apple's documentation makes it sound like they are looking for a registered event listener and handled on the target element, but that is not the case. I found the answers in the following article, and more importantly, one of the comments to it.
Quirksmode Article on iOS event delegation
First, observe that placing a listener on the document or body does not cause the click event to be dispatched on iOS Safari, if the target element has no click event listener and handler. It works in most browsers, but not on iOS.
It appears that Apple is checking the DOM hierarchy up to the <body> tag before dispatching the click event, but is not checking the <body> tag or above. Therefore, you need a click event listener attached to an element somewhere below the <body>.
Solution/Workaround
The solution then is very simple. All you need to do is to wrap all of the page content in a "master" container element just below the <body> element, and put the listener there instead of on the body or the document. It can even be an empty handler function. Apple is only checking to see if one is registered. The reason for wrapping all content is so that no matter where in the page the user clicks, the bubble-up process will eventually reach the master container.
If you do that, then ng-blur will work as expected in iOS, because the click event on empty space (an element with no click event listener) will pass the iOS check when it finds the parent container's click event listener and a click event will be dispatched normally, like it would be in any other browser.
Caution
This solution effectively causes iOS Safari to see a click event listener on every DOM element's hierarchy, tricking it into dispatching the click event on every element, just like a normal browser. I do not know if Apple has a performance reason they avoid this in iOS, or if it is just an aesthetic/developer type preference (see example). You will be changing the default iOS behavior in your app by using this workaround.
For example, iOS users may accidentally select text on your page that they did not mean too, and which would not normally occur without a click and hold gesture.
I don't know why that problem occurs.
but do one thing. create one small directive 'fake-blur' . then call your method in that directive
App.directive('fakeBlur', function(){
return {
restrict: 'A',
link: function(scope, element, attrs) {
element.blur(function(){
// call you function ex:
scope.save();
})
}
}
});
<input type="text" fake-blur/>
In my Rails site, I have an element that I want to act as a link when clicked by a mouse (e.g. on a desktop), but not when touched on a touch-screen device (because there is also a hover behavior).
My understanding is that the JQuery .click event should not get triggered on a touch.
My coffeescript for setting the click handler is simply
...
$(this).click ->
location.href = url
...
(where "this" is the element in question)
I know this code works, because the click action works with the mouse. To ensure that it doesn't get triggered on a touch device, I use the device emulation in Chrome's Developer Tools to emulate a touch. However, when I do this, the method still fires and follows the link.
Is this a problem with the Chrome emulation or with my code? I want to know whether it will behave this way on real touch devices.
edit: Same thing happens with Firefox, so I'm thinking it's my code...
I realized that touch events trigger click events as well, later on in the event chain. To get the functionality I wanted, I kept the .click handler, but added a .touchstart handler where I called event.preventDefault() to short-circuit the rest of the event chain. This way, the .click handler fires for mouse clicks, but not for touches.
I need to learn how to right click on an element in a webpage using IE8 document mode.
The webpage I am working with is PTC's windchill 10, which I believe is created usings sencha's extjs. I am not sure if extjs registers the .click() method as a click always. Some elements I need to use onmousedown and onmouseup to get a click to work.
This function I have tested on the iframe object psbIFrame to do a regular .click() and it works using autohotkey.
Autohotkey Syntax
click_event:=window_handle.document.all.psbIFrame.contentWindow.document.createEventObject()
click_event.button:=1 ;left button down
links[a_index-1].fireEvent("onclick", click_event)
Javascript Type Syntax
document.all.psbIFrame.contentWindow.document.createEventObject();
click_event.button=1;
links[a_index-1].fireEvent("onclick", click_event)
I also have this working for other elements not in an iframe.
event:=document.createEventObject()
event.button:=1 ;left button down
element.fireEvent("onmousedown", event)
element.fireEvent("onmouseup", event)
Those are all left clicks since the document mode is ie8. When I set the button to 2 and do either of those I don't get anything happening.
Does anyone else have access to a windchill page that can help me test?
element.fireEvent("oncontextmenu")
This does what I expect a right click to do. With fireEvent you don't even need to initialize the event most times it seems. FireEvent will do that in the background assuming some defaults. I don't know if what I was doing in my question with changing the button to 2 even makes sense.
http://help.dottoro.com/ljvtddtm.php for fireEvent
http://help.dottoro.com/lagstsiq.php/#MouseEvent_Members for a list of mouse events
I am working on an RTS game where you can select units and right click to make them go somewhere. You can also shift right click to queue up a list of points you would like the units to travel to.
In all browsers except FF this is working perfectly.
In Firefox however the shift right click triggers a context menu (right click without shift does not). I am handling the contextmenu event and calling preventDefault but that doesn't seem to do anything in FF when the shift button is held.
Is there any way to block this behavior in FF?
My game is here: https://mod.it/4plhXo3l and the code in question in in the RTSBoard.js file on line 36.
I managed to get this working in Firefox by setting event.shiftKey to false, then calling preventDefault(), and stopPropagation(), then returning false. I then set the document model's onclick event and ondblclick events to the same function you wound up using for yourself, plus the added setting of the shiftkey to false. I also had to do this for mouseup events, because clicking and dragging was also causing context menus to pop up.
I'm not sure it can be fully 100% disabled, but this looks to be about the closest you can get it.
Answering my own question. It appears that calling preventDefault and stopPropagation in the document.onclick event solves the issue.
See this reddit thread for more discussion: http://www.reddit.com/r/javascript/comments/1agoj8/is_it_possible_to_block_the_shift_right_click/
The webkit browser on iphone has a 300ms delay between when a user does a touch and when the javascript gets a click event. This happens because the browser needs to check if a user has done a double tap. My app doesn't allow zooming so a double tap is useless for me. A number of people have proposed solutions to this problem and they usually involve handling the 'click' on the touch end event and then ignoring the click generated by the browser. However, it doesn't seem to be possible to suppress a click that gets sent to an input element. This can cause a problem if you have a dialog that opens above a form then a user hits the close button and their click gets routed to an input element when the form disappears.
Example with jqtouch (for iphone only)
You have to capture your event on touchstart if you want to get the fastest possible responsiveness. Otherwise you'll be doomed with this input lag.
You have to remember though that capturing event on touchstart and responding to it makes it impossible to cancel action by dragging your finger out of responsive area.
I have personally used this in my PhoneGap html/js based iphone application and it worked perfect. The only solution to give this almost-native feel.
Now regarding your problem - have you tried to stop the propagation of the event? It should solve your problem.
$('.button').bind('touchstart', function(e){
e.stopPropagation();
// do something...
});
hope it helps,
Tom
My colleagues and I developed an open source library called FastClick for getting rid of the click delay in Mobile Safari. It converts touches to clicks and handles those special cases for input and select elements cleanly.
It's as easy as instantiating it on the body like so: new FastClick(document.body), then listening for click events as usual.
I made Matt's FastClick a jquery plugin:
stackoverflow link
Just had a comment about the onClick handler being called without the necessary scope being passed. I updated the code to make it work.
There also seems to be a problem when input elements lie under the ghost event's position: the focus event gets triggered without being busted.
I see two problems in the question. One is handling the delay in click and the other is handling input focus.
Yes, both of these have to be handled properly in mobile web.
The delay in click has deeper reasons. The reason for this 300ms delay is explained very well in this article.
Responsiveness of the click event.
Thankfully this problem is well known and solved by many libraries.
JQTouch, JQuery Mobile,
JQuery.tappable,
Mootools-mobile,
and tappable
Most of these libraries create a new event called tap. you can use the tap event similar to the click event. This jquery-mobile event handling might help.
$("#tappableElement").tap(function(){
// provide your implementation here. this is executed immediately without the 300ms delay.
});
Now, the second problem is with the handling of input focus.
There is a noticeable delay here also.
This can be solved by forcing focus on the element immediately for one of the touchstart or touchend events. This JQuery event handling might help.
$('#focusElement').bind('touchstart', function(e){
$(this).focus();
});
$('#focusElement').focus(function(e){
// do your work here.
});
You can do e.stopPropagation in 'touchstart' event handling to avoid propagation. But I would strongly advise against return false; or e.preventDefault as that would stop default functionality like copy/paste, selecting text etc.