I'm developing a small library in which I have an input which when focussed, can't be blurred by clicking/tapping a specific div (by returning false on the mousedown event). Other elements are fine (normal behavior). Mentioned div contains in the actual implementation a few buttons which add text to the input field. The focus is not required for that to work, but I want keyboard input accepted there as well, so I want it to work the way I explained.
I noticed somewhat strange behavior on mobile though.
When longpressing (click and hold a few hundred ms) the unclickable div whilst focussed on the input, the mousedown event doesn't occur and the blur event magically triggers. I noticed that another event did not occur either, so it's not only the mousedown event.
Example:
<input id="input" type="text" />
<div id="disabledArea" class="flex-center">
Blur disabled when clicking here.
</div>
With the following JavaScript:
var input = document.getElementById('input');
var disabledArea = document.getElementById('disabledArea');
input.addEventListener('blur', () => {
console.log("blur");
});
disabledArea.addEventListener('mousedown', (e) => {
console.log("mousedown");
e.preventDefault();
return false;
});
https://jsfiddle.net/pgukmmjo/
Can anybody help me with this? It's kinda hard to explain, but very obvious once you understand the problem.
I recommend the example JSFiddle to be viewed in Chrome with DevTools open (CTRL + SHIFT + I) and device toolbar on (CTRL + SHIFT + M) which simulates mobile touch. Alternatively you can change the console logs with alerts and view it on mobile.
Related
I have created a Skip to Content link on my page that skips to a button. In IE and Chrome, the focus is set on the button which allows me to activate it with Enter. In Firefox however, it does not set focus to the button. It seems to be focusing after the button as I need to Shift+Tab (Tab backwards) to get focus on the button.
Skip to play button
<button id="player__button">
Play
</button>
I've created a Fiddle https://jsfiddle.net/chadfawcett/p4t2wv21/5/. You should be able to reproduce the issue by Tabbing to the Skip to play button link, hitting Enter, which will put focus on the button. In Chrome and IE you can then hit Enter repeatedly to have the onclick listener fire.
This is a known bug in Firefox since many and many years (2005 at least) :
Following an on-page anchor link loses the focus
The visual focus is changed, but not the keyboard focus
The only thing Gecko does correct and Blink, WebKit and Trident fail is updating the "sequential focus navigation starting point" when :target is not focusable.
There's also an open similar bug which concerns form elements:
form controls should get focus when a URI points to them (with a fragment identifier)
While writing this question up, I was able to find a JS workaround, but I would prefer an HTML solution. Hopefully someone can chime in with a better answer.
After finding this SO Question, I was able to get the desired behaviour working in Firefox by using Javascript to set the focus.
link.addEventListener('click', e => {
e.preventDefault()
button.focus()
})
https://jsfiddle.net/chadfawcett/p4t2wv21/8/
I'm pretty sure this fixes your issue. It just comes down to code interpretation between browsers, and changing the syntax of your code to less ambiguous/more universal is key.
https://jsfiddle.net/ws88pwo6/3/
<button type="button" onclick="focusMethod()">Skip to play button</button>
<p></p>
<button id="player__button">
Play
</button>
<textarea id="output" disabled>
</textarea>
Js
const button = document.getElementById('player__button')
const output = document.getElementById('output')
focusMethod = function getFocus() {
document.getElementById("player__button").focus();
}
player__button.onclick = function(){output.innerHTML += 'Button clicked\n'};
Using Hammer.js and the Touch Emulator found here:
https://github.com/hammerjs/touchemulator
Cannot seem to click into a text input at all let alone edit it.
I have figured it out!
When creating the Hammer event add a Tap event to it. In the handler for the tap event focus and click of the target element. This will allow input fields and buttons to be utilized that are wrapped in the Hammer object.
Hammer v2.04
var el = document.querySelector("#touchable");
var mc = new Hammer.Manager(el, {});
mc.add(new Hammer.Tap({ }));
mc.on("tap", function (ev) {
ev.target.focus()//This allows text fields to be focused on
ev.target.click()//This allows buttons and other objects to be clicked
});
This Works best for IOS and Android devices specifically
Not a perfect solution but I have been able to edit inputs by placing this line at the top of the onMouse function.
if (!ev.shiftKey && ev.target.nodeName === 'INPUT') return;
Roughly translated to, no multitouch and you're clicking an input, ok I'll do nothing...
We are using W2UI (Javascript UI) controls. It has a "Multi Select" input control with associated div container with suggestion data. Whenever user clicks on input control a suggestion div is popped up and user can select multiple items from the list. Please find below screenshot
We have set overfloaw:auto of div When suggestion list has more than 10 records. (Refer below screenshot)
At this point, clicking on scrollbar works fine in Chrome and Mozilla but in case of IE it closes / hides the div.
We have made initial RCA of this as follow.
When a scrollbar is associated to a div, clicking on scrollbar causes blur event to fire for that div.
In W2UI library, blur event is used to hide the suggestion div causing it to close. We also found that, clicking on scrollbar does not cause blur event to fire in chrome & firefox.
Now we want to suppress blur event when user clicks on "scrollbar" in case of IE.
We are unable to identify scrollbar click.
Please share your thoughts / workarounds about suppressing blur() event conditionally.
I am also facing same issue we have made some changes in w2ui lbrary
we have set global variable flagClick first time it is false. & added below events
var div = $('#w2ui-global-items');
div.on('mouseover', function (event)
{
flagClick = false;
$('.w2ui-list').find('input').focus();
});
div.on('mouseout', function (event)
{
flagClick = true;
});
and changed blur event logic of div
as below --
.on('blur', function (event)
{
if (flagClick)
{
$(div).css('outline', 'none');
obj.hide();
if (event.stopPropagation) event.stopPropagation();
else event.cancelBubble = true;
}
})
almost this logic have solved our issue, except one .
When we click on search textbox then list will populate , if after that we click on list scroolbar and after that click on outside list div , List not getting hide (div blur event not getting fired).
try this solution , it will help u .
If you get solution to our problem pls post on same .
An updated version of w2ui came out just a few days ago where controls, including multiselect, have been refactored. It seems to work fine for me with 1.4 version.
First of all, this is my first question here, sorry if it is not asked properly.
I have a bug in a web app we developed in the office. The app is nearly done but In IE < 9 it happens that a text-box which has focus and blur events attached with jQuery raises the blur event as soon as you click on it.
You can see this in this picture (just clicked in the text-box):
https://www.dropbox.com/s/yn10xfrfxsr38bq/screen.PNG
$('#divVolee [type="text"]')
has no focusin or focus events attached.
The URL to the application:
http://86.126.255.70:2213/Anoxa/
If you want you can enter using the "Demarrer" button.
I do not ask anybody to write code for me or anything like that, I just don't know after days of searching in the code and on the net what could cause that.
I tried focusin, focus, focusout, blur, attaching directly or using delegates, the same thing. As soon as I click in the input field it raises the blur / focusout event.
Thank you for your help.
I found it. I started to comment everything out until I found the culprit:
function resizeAccordion() {
var active = $('#divAccordion').accordion('option', 'active');
$('#divAccordion').accordion('destroy').accordion({ heightStyle: "fill", active: active });
}
var resizeId;
$(window).resize(function () {
clearTimeout(resizeId);
resizeId = setTimeout(resizeAccordion, 600);
});
This code was supposed to re-size and re arrange the accordion in the page if the user re-sized the browser. Somehow in IE<9 it got triggered without reason and this caused the blur event to be triggered.
After so many hours. Maybe it is may thinking or code that was wrong, but i still hate IE for it.
I cannot reproduce this bug (using IE8 mode under IE9). But a simple workaround could be: (even quite weird)
$('#divVolee [type="text"]').focus(function(){
//>>code for FOCUS here<<
$(this).blur(blurcallback);
});
function blurcallback()
{
//>>code for BLUR here<<
$(this).off('blur');
}
I have a div that acts like a drop-down. So it pops-up when you click a button and it allows you to scroll through this big list. So the div has a vertical scroll bar. The div is supposed to disappear if you click outside of the div, i.e. on blur.
The problem is that when the user clicks on the div's scrollbar, IE wrongly fires the onblur event, whereas Firefox doesn't. I guess Firefox still treats the scrollbar as part of the div, which I think is correct. I just want IE to behave the same way.
I've had a similar problem with a scrollbar in an autocomplete dropdown. Since the dropdown should be hidden when the form element it is attached to loses focus, maintaining focus on the correct element became an issue. When the scrollbar was clicked, only Firefox (10.0) kept focus on the input element. IE (8.0), Opera (11.61), Chrome (17.0) and Safari (5.1) all removed focus from the input, resulting in the dropdown being hidden, and since it was hidden, click events would not fire on the dropdown.
Fortunately, the shift of focus can be easily prevented in most of the problem browsers. This is done by canceling the default browser action:
dropdown.onmousedown = function(event) {
// Do stuff
return false;
}
Adding a return value to the event handler sorted out the problem on all browsers except IE. Doing this cancels the default browser action, in this case the focus shift. Also, using mousedown instead of click meant that the event handler would be executed before the blur event fired on the input element.
This left IE as the only remaining problem (no surprise there). It turns out that there is no way to cancel the focus shift on IE. Fortunately, IE is the only browser that fires a focus event on the dropdown, meaning focus on the input element can be restored with an IE-exclusive event handler:
dropdown.onfocus = function() {
input.focus();
}
This solution for IE is not perfect, but while the focus shift is not cancelable, this is the best you can do. What happens is that the blur event fires on the input, hiding the dropdown, after which focus fires on the now hidden dropdown, which restores focus on the input and triggers showing the dropdown. In my code it also triggers repopulating the dropdown, resulting in a short delay and loss of the selection, but if the user wants to scroll the selection is probably useless anyway, so I deemed this acceptable.
I hope this is helpful, even though my example is slightly different than in the question. From what I gathered, the question was about IE firing a blur event on the dropdown itself, rather than the button that opened it, which makes no sense to me... Like my use of a focus event handler indicates, clicking on a scrollbar should move focus to the element the scrollbar is part of on IE.
Late answer, but I had the same issue and the current answers didn't work for me.
The hover state of the popup element works as expected, so in your blur event you can check to see if your popup element is hovered, and only remove/hide it if it isn't:
$('#element-with-focus').blur(function()
{
if ($('#popup:hover').length === 0)
{
$('#popup').hide()
}
}
You'll need to shift focus back to the original element that has the blur event bound to it. This doesn't interfere with the scrolling:
$('#popup').focus(function(e)
{
$('#element-with-focus').focus();
});
This does not work with IE7 or lower - so just drop support for it...
Example: http://jsfiddle.net/y7AuF/
I'm having a similar problem with IE firing the blur event when you click on a scrollbar. Apparently it only happens n IE7 and below, and IE8 in quirksmode.
Here's something I found via Google
https://prototype.lighthouseapp.com/projects/8887/tickets/248-results-popup-from-ajaxautocompleter-disappear-when-user-clicks-on-scrollbars-in-ie6ie7
Basically you only do the blur if you know the person clicked somewhere on the document other than the currently focused div. It's possible to inversely detect the scrollbar click because document.onclick doesn't fire when you click on the scrollbar.
This is an old question but since it still applies to IE11 here is what I did.
I listen to the mousedown event on the menu and set a flag on this event. When I catch the blur event, if the mousedown flag is on, I set the focus back. Since Edge, FF and Chrome won't fire the blur event but will fire the mouseup event (which IE won't), I reset the mousedown flag on the mouseup for them (on the blur for IE).
mousedown: function (e) {
this.mouseddown = true;
this.$menu.one("mouseup", function(e){
// IE won't fire this, but FF and Chrome will so we reset our flag for them here
this.mouseddown = false;
}.bind(this));
}
blur: function (e) {
if (!this.mouseddown && this.shown) {
this.hide();
this.focused = false;
} else if (this.mouseddown) {
// This is for IE that blurs the input when user clicks on scroll.
// We set the focus back on the input and prevent the lookup to occur again
this.skipShowHintOnFocus = true; // Flag used to avoid repopulating the menu
this.$element.focus();
this.mouseddown = false;
}
},
That way the menu stays visible and user doesn't loose anything.
Use focusout, and focusin (IE specific events)
$(document).bind('focusout', function(){
preventHiding = false;
//trigger blur event
this.$element.trigger('blur');
});
$(document).bind('focusin', function(){
preventHiding = true;
});
$(document).bind('blur', function(){
// Did anyone want us to prevent hiding?
if (this.preventHiding) {
this.preventHiding = false;
return;
}
this.hide();
});
I had the same probleme. Resolved by putting the menu in a wrapping (bigger) div. With the blur applied to the wrapper, it worked!
Perhaps try adding the tabindex attribute set to -1 to the div node.
I don't think this is an IE issue.
It's more a case of how to design your interaction and where to handle which event.
If you have a unique css-class-accessor for the related target, canceling a blur event can be done by checking the classList of the event.relatedTarget for the element you want to allow or disallow to initiate the blur event. See my onBlurHandler from a custom autocomplete dropdown in an ES2015 project of mine (you might need to work around contains() for older JS support):
onBlurHandler(event: FocusEvent) {
if (event.relatedTarget
&& (event.relatedTarget as HTMLElement).classList.contains('folding-select-result-list')) {
// Disallow any blur event from `.folding-select-result-list`
event.preventDefault();
} else if (!event.relatedTarget
|| event.relatedTarget
&& !(event.relatedTarget as HTMLElement).classList.contains('select-item')) {
// If blur event is from outside (not `.select-item`), clear the suggest list
// onClickHandler of `.select-item` will clear suggestList as configured with this.clearAfterSelect
this.clearOptions(this.clearAfterBlur);
}
}
.folding-select-result-list is my suggestions-dropdown having 'empty spots' and 'possibly a scrollbar', where I don't need this blur event.
.select-item has it's own onClickHandler that fires the XHR-request of the selection, and closes the dropdown when another property of the component this.clearAfterSelect is true.