Events stop firing when focused on readonly input on iPhone - javascript

I have readonly input filed:
<div class="wrapper">
<input type="text" readonly="readonly" />
</div>
it has "click" and "focus" events attached. Everything works well on all browsers except safari on iPhone (tested on iPhone 5, and iPhone 6). After few clicks on input field blue text cursor appears and input is no longer accepting clicks (event is not firing).
I read in similar question that you can just fire blur event on input when focused, but I need to keep track of focused element (I'm using focusin and focusout events on wrapper).
In addition I need this field to be focusable by Tab key on other browsers.
here is my code:
https://jsfiddle.net/0tr1afv2/
[edit]
I've changed the order of log message appearing - now on jsfiddle newer are on top. The screenshot is showing the log in other way.

I recently had issues with the click event using mobile devices. Try adding the following to your javascript:
input.addEventListener("touchstart", function () {c.log("input click");});
More information on the subject here:
https://developer.mozilla.org/en-US/docs/Web/API/Touch_events

Related

Input being hidden after focus on mobile browser

I have an input that appears and gains focus after a button is clicked. The issue is that, on a mobile browser only, after the input gains focus it receives a blur event and the touch keyboard hides. On a desktop browser the blur event doesn't even get received after it receives focus.
I'v tried to call preventDefault on the blur event but the problem is that doesn't help when I want the user to dismiss the input by clicking outside of it.
This is the code that show the input:
$('#searchbar-form').on('show.bs.collapse', function(){
$('#container-main-search').addClass('search-expanded');
});
the input inside #container-main-search has autofocus. This is the input code:
<input type="text" class="form-control searchbar-input" id="searchbar-input" role="searchbox" name="name" autofocus>

Firefox does not set focus to anchor element

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'};

Why is blur event not fired in iOS Safari Mobile (iPhone / iPad)?

I've two event handlers bound to an anchor tag: one for focus and blur.
The handlers fire on desktop, but in iphone and ipad only focus is fired correctly. Blur is not fired if I click outside the anchor tag (blur fires only when I click some other form elements in the page):
$("a").focus(function(){
console.log("focus fired");
});
$("a").blur(function(){
console.log("blur fired");
});
HTML:
<html>
<form>
test link
<div>
<input type="text" title="" size="38" value="" id="lname1" name="" class="text">
</div>
<div style="padding:100px">
<p>test content</p>
</div>
</form>
</html>
If an anchor has any events attached, the first tap on it in iOS causes the anchor to be put into the hover state, and focused. A tap away removes the hover state, but the link remains focused. This is by design. To properly control an application on iOS, you need to implement touch-based events and react to those instead of desktop ones.
There is a complete guide to using Javascript events in WebKit on iOS.
If you're working with touch devices you can use the touchleave or touchend event to handle when the user clicks outside the area.
$("a").on('touchleave touchcancel', function () {
// do something
});
For this to work you need to update your focus function to listen for an on click event as follows
$("a").on("click", function (e) {
if(e.handled !== true) {
e.handled = true
} else {
return false
}
// do something
})
I have check all the doc in the #NicholasShanks answer, but a little frustrated testing all the events.
Android and iOS:
Tested on Android Samsung S9
Tested on iOS iPad 5ºgen
Finally i have got a solution:
Seems iPad listen to mouseout as blur, and seems android listen perfectly to the blur event, i just add a ternary on this case to attach the right event (previously i have aimed to a mobile or tablet device instead of a computer.
// element >> element you want to trigger
// os >> function that return operative system 'ios' or 'android' in my case
element.addEventListener(os === 'ios' ? 'mouseout' : 'blur', () => {
// Do something
})
It's a hack, but you can get .blur to fire by registering a click handler on every DOM element. This removes focus from the previously focused element.
$('*').click();
$('html').css('-webkit-tap-highlight-color', 'rgba(0, 0, 0, 0)');
The second line removes the highlight when elements are clicked.
I know this is sub-optimal, but it may get you going.
The blur event does not fire because when you click outside the anchor tag on a non-clickable element, iOS ignores the click (and the click event does not fire).
There are a couple of threads regarding this (e.g. .click event not firing in Chrome on iOS). You can fix it by adding cursor: pointer to the <body> or some other element that the click will be performed on.
The simplest solution I've found is to just make document.body "clickable" at page initialization time:
document.body.onclick = function() {};
Then a click anywhere will blur the active element, just like on a desktop browser. Tested on iOS 15.3.1.

onfocus is not called when using the autofocus attribute on an input tag

In the following example, I get only one alert box. I read that the focus is put before the JavaScript code is executed. Is there a way to get this to work on?
<input id="i" type="text" autofocus onfocus="alert(1)">
<script type="text/javascript">
document.getElementById('i').addEventListener('focus', function() {
alert(2);
}, false);
</script>
(I have only tested this in Safari)
Edit:
I can obviously do it this way (Prototypejs selector):
var autofocusElement = $$('input[autofocus]')[0];
callListener(autofocusElement);
But it looks ugly compared to only add an event listener.
Edit:
Do not worry over a lack of browser support for the autofocus attribute. It solved easily as I have done in I fiddle links to below. There is also the best solution to the problem as I can see. My question is if I can do it in a less ugly than having to call the listener manually.
http://jsfiddle.net/tellnes/7TMBJ/3/
It works fine in Firefox 3.6 since Firefox does not support autofocus. But in Safari, which supports autofocus, are not the event called.
From the HTML5 working draft:
There must not be more than one
element in the document with the
autofocus attribute specified.
So you're asking for undefined behavior anyway.
With only one autofocus element, under Firefox 3.6, neither of the handlers get called on page load. Manually giving the focus to the element calls both handlers (then proceeds into an infinite loop, due to the alert boxes giving the focus back to the element when closing).
The HTML5 draft does say that autofocus should perform the focusing steps on page load, including raising the focus event, but chances are that browsers are not currently implementing that feature in a complete or consistent manner.
You might want to explicitly call your focus event handler during page load until the HTML5 spec is finished and browsers start aiming for complete support.
The following code from your current example:
<input id="i" type="text" autofocus onfocus="alert(1)">
<script type="text/javascript">
document.getElementById('i').addEventListener('focus', function() {
alert(2);
}, false);
</script>
Is going to cause an infinite loop of alerts going from 1 to 2
[eidt]
because: (this happens only in broswers that support autofocus )
input gets autofocus, fires event which fires an alert, alert grabs focus, click ok, input grabs focus, focus event fires new event triggering now two different alerts (DOM fully loaded now so new event is added with another alert), both alerts grab focus, click ok, click ok, input grabs focus fires new event triggering now two different alerts, alert grabs focus, click ok, next alert grabs focus, click ok, input grabs focus, fires both events, alert grabs focus, click ok, next alert grabs focus, click ok, input grabs focus, fires both events, alert grabs focus, click ok, next alert grabs focus, click ok, input grabs focus, fires both events, alert grabs focus, click ok, next alert grabs focus, click ok, input grabs focus, fires both events, input grabs focus, fires both events, alert grabs focus, click ok, next alert grabs focus, click ok, input grabs focus, fires both events, input grabs focus, fires both events, alert grabs focus, click ok, next alert grabs focus, click ok, input grabs focus, fires both events, input grabs focus, fires both events, alert grabs focus, click ok, next alert grabs focus, click ok, input grabs focus, fires both events...
Textual description of an infinite process FTW!....? :P
[/edit]
In your previous examples with two auto-focuses applied it seems that the last one will be executed as in the example I have attached at the bottom. I also added a way of adding a focus event to each input based on a class name... Not sure if you're looking for that but though it might be of some help.
JSFiddle Example of onfocus event
You need to give a value to autofocus.
<input id="i" type="text" onfocus="alert(1)" autofocus="">
Give autofoucs="autofocus" attribute after all events has been given to the input field.
You can also use addEventListener in .js file at the top.
It might be that the autofocus onfocus event fires before addEventListener adds the event listener.
I replaced autofocus with class="autofocus" on my input element, and set the focus like this near my addEventListener call:
if(searchInput.classList.contains('autofocus')) {
searchInput.focus();
}
If you need to execute a piece of javascript code, onfocus for either input, you could use jQuery: http://api.jquery.com/focus/

What events does an <input type="number" /> fire when its value is changed?

Just wondering whether anyone knows what events an HTML5 <input type="number" /> element fires when its up / down arrows are clicked:
I'm already using an onblur for when the focus leaves the input field.
change would be the event that is fired when the field's value changes.
I think the HTML5 event input would also fire.
I found that for jQuery the following code covered keyboard input, mousewheel changes and button clicks in Chrome, and also handled keyboard input in Firefox
$("input[type=number]").bind('keyup input', function(){
// handle event
});
I found that onkeyup and onchange covered everything in Chrome 19.
This handles direct value input, up down arrow keypress, clicking the buttons and scrolling the mousewheel.
onchange alone would be sufficient in Chrome, but other browsers that only render the field as a text box need the onkeyup binding, which works perfectly to read the new value.
Binding the mousewheel event separately was less successful. The event fired too early - before the field value was updated - and therefore always gave the field's previous value
The onchange event fires on blur but the oninput event fires as you type. Maybe you might want to put a timer on the oninput event and fire your onchange event when the user has stopped typing for a second?
There is a current bug in Edge preventing change or input from firing when using the arrow keys in a number input.

Categories