Firefox does not set focus to anchor element - javascript

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

Related

How can I prevent a user using inspect element to enable a disabled element?

I have a button as follows:
<input type="submit" class="button" value="FooBar" name="FooBar" id="FooBar" disabled="disabled">
I am enabling this button only when certain parameters are met. To test whether it was secure, I pressed F12 (or right click -> Inspect Element) and edited out the text disabled="disabled". Doing this overrides my code and that is scary. How can I prevent someone from changing it in this manner?
I am using php and jquery in this page and using the latter to enable or disable the button. I have checked the jquery click function and it not only executes, but shows the button as not disabled. The alert below reads Disabled: false
$("#FooBar").click(function(){
alert('Disabled: ' + $(this).is('[disabled=disabled]'));
})
So how can I prevent a user from changing the button disabled state and thus overriding my logic?
You can disable the right-click by doing:
document.addEventListener('contextmenu', event => event.preventDefault());
but it is not recommended. Why? It achieves nothing other than the annoying user
OR
Alternatively, a better approach is to recheck your validations in submit action and simply returns if it fails, in this case, if user inspects and changed the state of a button, the button stays idle and will not allow to proceed
$("#FooBar").click(function() {
if (!this.acceptenceCriteria()) {
return;
}
alert('Disabled: ' + $(this).is('[disabled=disabled]'));
})
You can't stop people from using dev tools.
You can try a couple of tricks to disable right clicking (like the one below) which will stop some number of people but ultimately the solution to your problem is to use html and http properly.
$(document).bind("contextmenu",function(e) {
e.preventDefault();
});

mousedown event doesn't get called on longpress

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.

Events stop firing when focused on readonly input on iPhone

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

Keyup event for text input box being capture by Google Chrome address bar

I am using the keyup event to fire the same event as clicking on the search button when a user presses the return key. When the search button is clicked it uses an Ajax request to load search results on the page.
The call works fine, but the keyup event is being captured when I press the return button in the address bar in google chrome after previously having focus on the input box, e.g. if the user types in a search query without pressing return, and instead goes to a new webpage using the Google Chrome address bar, when they press return on the address bar the search in my page is being submitted at the same time as the keyup event is being trigger even though the page, and certainly the input box, should no longer have focus.
JavaScript
$("#search-box").on("keyup", function(event) {
if(event.keyCode == 13){
$("#search-submit-btn").click();
}
});
HTML
<div class="input-append"/>
<input id="search-box" type="text" />
<button class="btn" id="search-submit-btn">Search</button>
</div>
I'm also using Twitter bootstrap to style the Input box, but I don't think this is causing the problem.
I've tested this page in Firefox and Safari without any issue. Does Google Chrome have a problem with the keyup event/is this a know issue? I'm struggling to find any information on the issue.
EDIT
I think I've solved my issue by using keydown instead of keyup. I've also added in a check if the element is still focused, but I don't think this makes a difference, since it still has the same affect with keyup.
$("#search-box").on("keydown", function(event) {
if($("#search-box").is(":focus")){
if(event.keyCode == 13){
$("#search-submit-btn").click();
}
}
});
This appears to be an okay solution for me, but it doesn't explain why keyup behaves so strangely in Google Chrome though. If anyone has anymore information about why keyup is this way in Google Chrome or if I am just doing something wrong, I'd be very interested to hear.

Suppress Safari’s “You have entered text…” warning?

Safari helpfully (?) prompts before closing a tab or window when text has been entered into an input.
There are some cases where, as a web developer, this isn’t desirable — for example, when the input is a live search where the user has probably already gotten the results he’s looking for when the window is closed, even though there’s still text in the field.
How can I let Safari know that text in a particular input doesn’t need its protection?
It seems like you are able to disable this warning for an entire page by having an onbeforeunload handler on <body> (even an empty one will do). For example, the following will not produce the warning:
<body onbeforeunload="">
<form method="get"><input></form>
</body>
I'm not sure if this is the intended behaviour, or a bug.
I think I've got a solution to this problem, though it's unquestionably a hack (i.e. if Safari changes how this feature is implemented, it could stop working). Shown here with a touch of jQuery:
$('.unimportant').live('blur', function(){
var olddisplay = this.style.display;
this.style.display = 'none';
this.clientLeft; // layout
this.style.display = olddisplay;
});
Demo (try typing in the "unimportant" field, click somewhere else on the page, then close the window).
In short:
Hide the input
Trigger layout
Show the input
You can also change the value of the input, trigger layout, and change it back.
The one limitation here is that cleaning the input has to be done explicitly. In this case, it will be dirty until blur. This works well in my situation, and probably in many others, since the input will be protected from an accidental window close until something else on the page is manipulated (e.g. a link is clicked). You could choose to run this on keyup if you're willing to live with a flicker of the insertion point every time a key is pressed.
I'm open to cleaner solutions.
I found what I think is a pretty good solution to this problem. When I use AJAX to submit the form then I want the warning to suppress. This is accomplished with onbeforeunload.
window.onbeforeunload=function(e){}
But after I submit I might make additional changes and so I want the warning to show again. To do this I added a keyup handler to a form element.
$('txtarea').onkeyup=dirty;
What dirty does is checks is the input field has changed if it has then I set onbeforeunload to null.
function dirty(e){
if (e.srcElement.value != e.srcElement.defaultValue){
window.onbeforeunload=null;
}
}
I just found another solution to prevent Safari from displaying the "Are you sure you want to reload this page?" dialog when textareas have changed their content.
It turns out that setting the value through Javascript clears Safari's changed state:
$(document).on('blur', 'textarea', function() {
var value = $(this).val();
$(this).val('').val(value);
});
Clearing the value first is important, directly setting it to the content it already is does not work.
EDIT Apparently setting window.onbeforeunload to an empty function still works, however $(window).on('beforeunload', function() {}) does not.

Categories