I dont know why the blur event does not trigger when I click outside the input text (on the paragraph in yellow). So the keyboard cant close. The only way I can trigger it is when I click on the body (in blue in the snippet).
I have put many console.log for debugging.
What is even more weird is that when I remove the event click on the document, the click on body dont work anymore!
The problem occurs on Safari IOS. I have tested on Iphone 6.
Any idea ?
Thanks for your help
<!DOCTYPE html>
<html lang="en" style="height:200px; background:blue">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Document</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
</head>
<body style="height:200px; background:gray">
<form action="" style="background:purple">
<input type="text" name="test" id="test">
</form>
<p style="height:50px; background:yellow" >Paragraph</p>
<script>
$(document).ready(function() {
$(document).on('click', function() {
console.log('document click')
});
$('input').click(function(event) {
console.log("input click");
});
$('input').blur(function(event) {
console.log('input blur');
});
$('input').focusout(function(event) {
console.log('input focustout')
});
$('body').on('click', function(event) {
console.log('body click');
console.log(event);
});
});
</script>
</body>
</html>
I found a hack for this:
document.body.firstElementChild.tabIndex = 1
This makes the first element in the body focusable thus when you click "outside" the input it loses focus. At the same time you don't see any visual glitches on that focused element because there is not style defined (unless your first body child element is something other than div)
A less hacky solution might be to call
document.activeElement.blur()
in the event listener that triggers on clicks outside the <input /> element. activeElement has great browser support.
You might also want to check in the event listener that the intended input currently has focus with something like
if (document.activeElement.id === 'foo') document.activeElement.blur()
or
if (document.activeElement.hasAttribute('bar')) document.activeElement.blur()
to ensure you're not randomly blurring some other active element whenever tapping outside your input field.
Update Dec 7, 2019
Turns out there's an even simpler solution. Unlike blur, the mouseleave event does fire on mobile Safari if you tap outside an input element. If you're using React, it's as simple as
<input onMouseLeave={e => e.target.blur()} />
Or, in plain JS:
const input = document.getElementById('foo')
input.addEventListener('mouseleave', e => e.target.blur())
event.currentTarget.blur() may be even safer than event.target (i.e. certain to be the intended input element) but I found both work fine.
Related
I'm currently using Angularjs (version 1.5.8) and I'm developing an application where a series of inputs are generated dynamically, and I want that when you focus an input and you take 5 seconds or more to start writing, appears a tooltip (the tooltip is the same for all inputs), currently I have a tooltip directive that supports trigger events ('click', 'mouseenter', 'focus').
I made a first version of what I want using the click trigger, but sometimes there are unwanted behaviors, any suggestions?
Use the mouseenter event (or focus) and set a timeout to add the title attribute to the input (or create an explicit tooltip component to appear). If the user has any keypress or just plain model input, then cancel the timeout ?
let input = document.getElementById('input');
input.onfocus = function(){
let a = 0;
setTimeout(function(){alert('Please, write something');}, 5000);
};
/* Replaces the function alert('Please ...') with the function that manages your tooltip */
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<input id="input" />
</body>
</html>
`
$scope.focus = function() {
setTimeout(function(){
alert("test"); }, 5000);`
you write tooltip code ...inside of function.
you write custom directive called element.on("focus")
I would like to access the event that caused a beforeunload event. Specifically, if I click on a link to another page, I would like to know what the link was in the beforeunload event handler.
In this way, I would be perform different actions in the beforeunload event handler according to what the URL was.
Eg 'http:' or 'https:' warn user about losing unsaved changes; 'mailto:' or 'skype:' don't warn user because page is not actually going to be unloaded.
I am trying to build a good solution to a problem like this:
mailto link (in chrome) is triggering window.onbeforeunload - can i prevent this?
I was all prepared to tell you this was impossible because the onbeforeunload event only reports to have been triggered by the window when you check out event.target, event.originaltarget, etc. If you override window.onclick, however, we can modify that method to register which element was last clicked on the page. Then, by providing code for window.onbeforeunload, we can specify new behavior that will check for the href of the element which was clicked last. Hooray, beer!
Here's code that will give you exactly the information you want though, in pure javascript and with no cruft to add inside your anchor tags. I've also thrown in the preventDefault() which will pop up the "This page is asking you to confirm that you want to leave - data you have entered may not be saved." confirm box. Hope this helps - you can figure out what to do from here.
<!DOCTYPE html>
<html lang="en">
<head>
<title>12065389</title>
<meta charset="utf-8">
<script type="text/javascript">
var last_clicked;
window.onclick = function(e) {
last_clicked = e.target;
return true;
}
window.onbeforeunload = function(e) {
var e = e || window.event;
if (last_clicked.href) {
alert(last_clicked.href);
e.preventDefault();
}
}
</script>
</head>
<body>
google
</body>
</html>
I would probably attach the event to all links on the page, rather than the beforeunload event.
Something like:
$("a").click(function(evt) {
if($(this).attr('href').indexOf('http') == 0) {
if(confirm("Are you sure?")) {
//continue
} else {
evt.preventDefault();
}
}
}
I try to show text box (#dimVal), when div(#CanvasArea) is clicked. And I want to make this text box disappear, when it loses its focus.
<head>
<script src="jquery-1.5.1.js" type="text/javascript"></script>
</head>
<body>
<div id = "CanvasArea", style = "width:50%; height:600px; border:2px; border-color:orange; border-style:solid; float:left">
<h3>Click Me</h3>
</div>
<input type="text", id="dimVal", value="111", style="position:absolute; display:none; left:300px; top:300px" />
<script type="text/javascript">
onMouseDown = function(e){
$("#dimVal").show();
$("#dimVal").focus();
$("#dimVal").focusout(onLostFocus);
}
onLostFocus = function(e){
$("#dimVal").hide();
$("#dimVal").unbind("focusout");
}
$("#CanvasArea").bind("mousedown", onMouseDown);
</script>
</body>
I wonder why "focusout" event fires right after mouseclick?
I was not able to get your code to work in its current form, so I rewrote it somewhat using the jQuery mouseup function and the newest version of jQuery:
$(document).ready(function() {
$("#CanvasArea").mouseup(function() {
$("#dimVal").show();
$("#dimVal").focus();
$("#dimVal").focusout(onLostFocus);
});
onLostFocus = function(e){
$("#dimVal").hide();
$("#dimVal").unbind("focusout");
}
});
this works as intended, shows up when canvas area is clicked and removes focus when the user clicks off the form.
That's because your mouse is over the CanvasArea at the time you give focus to the dimVal hence dimVal immediately loses focus after gaining it.
Change mousedown to click event because before click event mousedown event triggers and then your code is executed which sets the focus onto textbox, after the click event is triggered the focus is lost so the focusout event is triggered. Also make use of anonymous function instead of having global functions. Try this.
$("#CanvasArea").bind("click", function(e){
$("#dimVal").focusout(function(e){
$(this).hide().unbind("focusout");
}).show().focus();
});
I've tried $('#field').focus(), and any other method found on the internet. Nothing worked. I have a simple html that reproduces the problem.
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$('#field').focus();
});
</script>
</head>
<body>
<input type="text" id="field" name="field"/>
</body>
</html>
Please help!
Actually, the general javascript function "focus" is deactivated in the android browser. Hence, the jQuery focus function is deactivated since it's using the above.
if you bind it to another click event it will work. This works for me:
$(document).ready(function()
{
$('#field').click(function(e){ $(this).focus(); });
$('body').click(function(e)
{
$('#field').trigger('click');
})
})
Will pop up the software keyboard. trigger() will trigger any event you give it. In this case the default behaviour of clicking on the field == tap == focus == win! Note: this call is bound to another click event happening.
click() or focus() alone is not enough. You need to focus() then click(). Beware of endless loops if your script is triggered by an onclick() on a containing element. The script below is working for me on Chrome for android 58 and Safari mobile 602.1. Soft keyboard popping nicely.
var target = document.getElementsByTagName("input")[0];
if (event.target != target) {
target.focus();
target.click();
}
I want my (ExtJS) toolbar buttons not to grab the focus on the web page when they are clicked, but to do their "thing" while leaving the focus unchanged by the click. How do I do that?
Cancelling the default behavior of onmousedown prevents an element from getting the focus:
// Prevent capturing focus by the button.
$('button').on('mousedown',
/** #param {!jQuery.Event} event */
function(event) {
event.preventDefault();
}
);
document.activeElement stores the currently focussed element.
So on your toolbar, you can add a "mousedown" handler to this function :
function preventFocus() {
var ae = document.activeElement;
setTimeout(function() { ae.focus() }, 1);
}
Try this example :
<html>
<head>
<script>
function preventFocus() {
var ae = document.activeElement;
setTimeout(function() { ae.focus() }, 1);
}
</script>
</head>
<body>
<input type="text"/>
<input type="button" onmousedown="preventFocus()" onclick="alert('clicked')" value="Toolbar" />
</body>
</html>
This usually does the trick for me:
<button
tabindex="-1"
onclick="javascript:console.log('do your thing')"
>My Button</button>
From https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex:
A negative value (usually tabindex="-1") means that the element should be focusable, but should not be reachable via sequential keyboard navigation. It's mostly useful to create accessible widgets with JavaScript.
I don't think there's an easy way to do what you want to do because it's the browser's default behaviour.
You could of course blur() the button as soon as it is clicked, but that would simply unselect everything. To have the previously active object regain focus, you'd have to create a "memory" of sorts by adding a blur handler for every element to keep track of which element had/lost focus last (store the id of the element in a global and update it when an element loses focus).
The top-voted answer is technically correct, but depends on jQuery...
Here's a simpler example:
<span onclick="document.execCommand('bold', false);" onmousedown="event.preventDefault();"></span>
My solution is to replace <button /> with <div /> and style it as a button.
Looks like Div doesn't take a focus on it when you click it.
Because the toolbar buttons are just styled ordinary HTML button elements then this is an actual browser behavior, and you should think twice before changing it. But nevertheless...
You should be able to prevent the botton from receiving focus by just returning false from its onclick handler.
Maybe you should try to use stateful and state change properties for form fields or whatever to get focus back?
I would attach one blur event listener to all fields. This listener should save the field, that lost the focus, in a global variable.
Then all the toolbar button should get one focus event listener. This listener should focus the field, that was saved as described above.
This code should work, although it didn't test it
<script>
function focusor(){
document.getElementById('focus').focus;
}
document.onkeydown = focusor;
document.onclick = focusor;
</script>
<div style="width: 0px; height: 0px; overflow: hiddden;">
<button id="focus"></button>
</div>
What I have found, is you will have to make a dummy element, I found buttons to work best in this situation. put the button in a div and make the div 0px.
[do not make the div display none, some browsers will just ignore it]
Basically any click or button presses, it will focus on this dummy button.
I had a project very similar and whenever they pressed the down key it selected the first button on the page, this just focuses on the button over and over again.
Sort of jacked up, but it works.
All these answers are wack. Here's a very excellent trick that only uses CSS
<button type="submit" disabled>
<span>Submit</span> <!-- the <span> is the secret -->
</button>
Now in your css:
button[disabled] > * {
pointer-events: none;
}
The trick is the inner span has to be used, otherwise the button will still steal focus away from inputs.