Is it possible to prevent an event from reaching listener set at document.window with capturing enabled?
Context
I am working on a chrome extension where I add some dom element (including some input element) to the dom from content-script. In a page, there is an event listener attached to the document.window with capture enabled, that listener takes away focus form my input element on any keydown event. As a result my input element is basically not working. I need to prevent that event from reaching the listener at window somehow.
Related
I need to add a code snippet to an existing site (actually it's SharePoint site) with a button that starts a Javascript function on click event.
The problem is that SharePoint already has several click events attached to body element. Some of them fire before my function get executed and some of them after.
I need to make only my click event fire.
The function that starts after mine I manage to stopped by stopPropagation() function. But what can I do to stop functions that fire before my event?
I assume the idea is to somehow stop capturing from child element...
If you don't need the click events attached to body to trigger when you click on the button, you can add a check in the event handlers attached to body click and stop the execution of code if your button is the originator of that event.
if(event.target == document.getElementById("your_buton_id")){return;}
Say I listen for clicks on a button
btn.addEventListener("click", function(e) {
console.log("button clicked");
});
This now activates a click listener, and if the user clicks on my button, the click event will fire on my button and then propagate to all its parents (unless the bubbling is prevented). But what if the user clicks on a completely unrelated element? Will this cause the event to fire on that element and then propagate to all of its parents too or not? (Even though there is no interest in handling those click events)
My guess is that yes, it will, because there should be a listener for clicks on the entire window once I start listening for them on a specific element. But I am not sure.
From JavaScript Essentials by O'Reilly:
When an event happens, the browser checks to see if you've defined an
event handler for that event; if you have, that function is run. Once
the function is complete, the browser begins the event loop again.
This event loop continues as long as the web page is loaded.
This means that, every click method is handled by browser. However, if you there's no listener assigned, it does not go further. But at least, it knows when anything is clicked.
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/>
I have a page with an input field. I want to run some javascript code on blur. Like this,
$('#inputfield').on('blur', function() {
...
});
It works fine on a desktop browser, if I tab away or click the mouse outside the field. On an iPad Safari browser, it works fine if I tap outside the input field.
But if I click on the hide keyboard button on the lower left corner, blur event is not triggered. Doesn't blur event fire on keyboard hide? I see the pointer/cursor moves away from the input field on keyboard hide. Is there any way to capture the keyboard hide event?
Thanks.
From Inforbiro:
jQuery - Focusout() and Blur() Event Differences
You can find many examples on Internet where you can see that focusout and blur events are used as synonyms and you can be confused with their usage.
What is difference between jQuery's .focusout() and .blur() events?
The difference between .focusout() and blur() jQuery event is that the .focusout() is sent to an element when it, or any element inside of it, loses focus. The .blur() event supports detecting the loss of focus from parent elements (i.e., it supports event bubbling)
What is event bubbling
Event bubbling in jQuery represents propagating event fired in one element to upper or lower elements in DOM hierarchy.
I've had problems in the past with blur, now I just stick to focusout
Take a look at the jQuery Documentation, they show an example of focusout vs blur
I have an iframe on my page. The iframe has the same origin as my page, so I shouldn't need to worry too much about cross-origin security problems.
On the parent frame, I have a keydown event listener watching for certain key presses. But if the iframe has the focus, the keydown events are registered in the iframe only.
I would like to duplicate the iframe keydown event on the parent frame.
Is this possible? I have been looking at document.createEvent and evt.initEvent but I am not there yet. Also, if I create a keydown event, will this actually act like the user typed a character? I.e., can I direct them to a field on the parent document?
if you are using jquery, declare a wrapper function in your parent that trigger keydown of your input element:
function triggerKeyDown(){
$("#my_input").keydown();
}
In your iframe, call
window.parent.triggerKeyDown();
to trigger the keydown event in your parent window.