jQuery's .on blur function executes incorrectly in Firefox - javascript

The client wants a form in which entered numbers behave like Excel in certain ways. In particular, the data saved and the data displayed can be different, as it can in Excel. For example, the data saved could be 32425.537342 and the data displayed could be $32,425.54.
The approach we have taken to accomplish this is by using input pairs, one of type='text' and one of type='number'. The number input, which is by default hidden, stores the data to be sent and the text input displays it to the user. The number input is only displayed when the corresponding text input is focused, at which time such text input is hidden.
This following code behaves as expected in Chrome.
HTML:
<input type="text">
<input type="number">
<br>
<input type="text">
<input type="number">
jQuery:
$(document).ready(function(){
$("[type='number']").hide();
$("[type='text']").on("focus",function(){
$(this).next().show().focus();
$(this).hide();
});
$("[type='number']").on('blur',function(){
$(this).prev().show();
$(this).hide();
});
});
Fiddle. However, in Firefox (version 33.1.1) for Mac OS, the same is not working at all. When the text input is focused on, it disappears completely, without the number input ever being displayed.
In trying to ascertain where the problem is, I cut the code back to this:
$(document).ready(function(){
$("[type='number']").hide();
$("[type='text']").on("focus",function(){
$(this).next().show().focus();
$(this).hide();
});
});
Fiddle. This actually works as expected in both Chrome and Firefox; on focus, the text input is permanently hidden and the number input is permanently displayed.
So it seems that the issue is in the second half of the code. If you take out the $(this).hide();, the code behaves consistently in Chrome and Firefox (although not in a way that's particularly useful):
$(document).ready(function(){
$("[type='number']").hide();
$("[type='text']").on("focus",function(){
$(this).next().show().focus();
$(this).hide();
});
$("[type='number']").on('blur',function(){
$(this).prev().show();
/* $(this).hide(); */
});
});
Fiddle. Likewise, if you remove only $(this).prev().show();, it also behaves the same in Chrome and Firefox: everything ultimately ends up hidden.
$(document).ready(function(){
$("[type='number']").hide();
$("[type='text']").on("focus",function(){
$(this).next().show().focus();
$(this).hide();
});
$("[type='number']").on('blur',function(){
/* $(this).prev().show(); */
$(this).hide();
});
});
Fiddle. The divergence in behavior only occurs when both lines are in there; Chrome hides one input and shows the other, whereas Firefox causes everything to disappear as soon as you focus on the text input.
I thought this might be related to the Firefox focus/blur issue that makes it behave strangely in iframes (example), but taking it out of JSFiddle's iframes didn't have any effect. Fiddle in full screen here.
So how do I make the behavior in Firefox match the behavior in Chrome?

This answer provided JavaScript that did the trick, and using that I was able to put together the equivalent in jQuery:
$(document).ready(function(){
$('[type="number"]').hide();
$('[type="text"]').on('focus',function(){
$(this).next().show().focus();
$(this).hide();
});
$('[type="number"]').on('blur',function(){
var $this = $(this);
setTimeout(function() {
if(!$(document.activeElement).is($this)){
$($this).hide();
$($this).prev().show();
}
}, 0);
});
});
Fiddle.
To quote from that answer as to why this is necessary:
[T]he issue is that different browsers choose to call event
handlers in different orders. One solution is to give the other events
a chance to fire by setting a timer for 0 milliseconds, and then
checking the fields to see which (if any) is focused.

Related

Keeping an iPad keyboard up between inputs

Right now I'm using a bit of jQuery to hide the iPad keyboard when an input loses focus.
jQuery(function($) {
$(document).on('touchend', function(e) {
document.activeElement.blur();
});
});
However during a process like the checkout when a user clicks from input to input the keyboard disappears and the reappears every time the input is changed. Is there any way to change the above jquery code to where it only blurs the active element if the place on the document that is touched does NOT have an input type of text?
Well, I haven't tried this with iPad before, so I'm not sure that it will work, but you can check the type of document.activeElement to determine if it is a text or textarea field. If it isn't, then perform your blur(). The code would be like this:
jQuery(function($) {
$(document).on('touchend', function(e) {
setTimeout(function() {
var currentElement = document.activeElement;
if ($(currentElement).not("textarea, :text").length > 0) {
currentElement.blur();
}
}, 100);
});
});
The setTimeout is needed to make sure that the focus has transferred to the next element, before checking what the current element is (doing it immediately, will return the <body> as the activeElement).
This general approach (i.e., identifying what type the current activeElement is) works in a desktop browser environment, and it SHOULD work on an iPad, but, like I said earlier, I've not had a chance to test it there, so this is more of a "possible solution" than an actual "answer", until you give it a try and se if it works for you. :D

Internet Explorer 8 get value of Radiobutton

I've been googling for about 2 hours to fix the following problem (other Stackoverflow Questions included):
<script type="text/javascript">
jQuery(document).ready(function() {
jQuery('input[type="radio"]').unbind('click.preset')
.bind('click.preset', function() {
doingStuffWith(jQuery(this).val());
});
});
</script>
<input type="radio" name="lightType" value="led" />
<input type="radio" name="lightType" value="tube" />
As you can see, I'm just trying to retrieve the current value of the radio button group "lightType" to work with it. This is working like a charm in Firefox / Safari / Chrome, but IE8 is giving me a hard time by just returning an empty string.
I've already tried several hacks from other questions like binding the change event to the radio buttons und forcing IE8 to fire it by blurring the clicked radio button etc. Maybe I'm
just suffering from blindness right now.
I'm working with the latest jQuery version and I've made sure that no other binded events interfere. Interestingly though, adding an alert() before retrieving the value and IE returns the current value:
....
// DOES WORK
alert();
alert(jQuery(this).val()); // alerts e.g. "tube"
// DOESN'T WORK
alert(jQuery(this).val()); // alerts ""
I thought it could be a timing problem, but trying to delay my single alert call with setTimeout didn't help.
Thanks in advance guys, I hope I'm just blind and didn't find another ugly behaviour in IE8.
I would use the latest jQuery and on() and the :checked selector in the callback:
jQuery(document).ready(function() {
jQuery('input[type="radio"]').on(function('change blur mousedown click') {
alert(jQuery('input[type="radio"]:checked').val());
});
});
Actually this is a little bit tricky, you can not fetch the selected radio button with "this" in the callback you have to use an other selector:
How can I know which radio button is selected via jQuery?
Thank you for your answers, but none worked. I'm not sure if this is a bug in jQuery or is just a problem I've hit in my particular case. It seems like jQuery is forcing IE8 to fire the change event before the field really changes.
I've finally solved it by binding to the blur event and combining it with powtacs :checked solution like this:
<script type="text/javascript">
jQuery(document).ready(function() {
jQuery('input[type="radio"]').unbind('click.preset')
.bind('click.preset', function() {
jQuery(this).blur();
}
jQuery('input[type="radio"]').unbind('blur.preset')
.bind('blur.preset', function() {
doingStuffWith(jQuery('input[type="radio"]:checked').val());
});
});
</script>
A fair option for IE8 is creating a class (!) in each radio option and use it to selected the checked option. Semantically it is a little weird, but it worked perfectly to me:
HTML
<input type="radio" name="example" class="example_class" value="1"/>#1
<input type="radio" name="example" class="example_class" value="2"/>#2
<input type="radio" name="example" class="example_class" value="3"/>#3
JS
var exampleValue = $('.example_class:checked').val();

How to deslect highlighted text in textbox if already highlighted?

So I have this very simple JS function that selects all the text in the ASP.NET texbox (input):
function selectAllText(textbox) {
textbox.focus();
textbox.select();
}
..and it gets called like this on the click event:
$("#<%=Textbox1.ClientID %>").click(function () { selectAllText(jQuery(this)) });
The problem is no matter how many times a user clicks in the text box all of the text is always selected. I understand why this is occuring (based on the way my code above is), but it doesn't work well when the user tries to click in the middle of a word to get the cursor back to make a modification to the text.
How do I modify this JS to tell if the text is already highlighted and then deselect the text? This was on subsiquient click, the user can get the single cursor on a precise clicked location to make a modification.
I am trying to get the documentation on the .select() method to see if I could do if(!textbox.select()), but I am having a hard time finding it, so post any doc links as well if you have them.
EDIT: This problem and need for a workaround seems to be for IE (I am using IE9). In Chrome the behavior by default is what I need, but this is for an intranet application that runs on IE, so it appears I need an explicit workaround.
Thanks!
Is it necessary to do the .focus() in this function? You could instead attach a simple .select(); to the onfocus event (.bind('focus', function(){..})): http://jsfiddle.net/EGHzj/
Try this
$(document).ready(function(){
$('input').bind('click',function(){
if($(this).hasClass('selected')){
$(this).toggleClass('selected');
}else{
this.focus();
this.select();
$(this).toggleClass('selected');
}
});
});
This should work in IE also,
http://jsfiddle.net/rAqgw/7/
function selectAllText(textbox) {
// if there isn't selected text.
if (textbox[0].selectionEnd) {
textbox.focus();
textbox.select();
}
}
$('#txt').click(function() {
selectAllText($(this));
});
Live DEMO
​

<textarea>'s text gets erased in Safari when using jQuery keyup

Safari on iPad does not support contenteditable and I don't have control over the generated HTMl. It's for a blog and the default area to insert text is a div with contenteditable attribute. I use jQuery to find this div, hide it, append a textarea and on keyup event for the new textarea put the text into the hidden div and then I can click the Save button and everything gets inserted properly.
The script below works fine in IE, Chrome and FireFox but not in Safari (iPad or PC), why is that and what is the solution?
$(document).ready(function () {
$('#defaultBox').parent().hide();
$('.ms-standardheader').each(function () {
var test = $(this).html();
if (test.indexOf("Body") != -1) {
$(this).parent().parent().after('<tr><td></td><td><textarea id="newBox" style="width:98%; height: 100%;"></textarea></td></tr>');
}
});
$('#newBox').keyup(function () {
var text = $(this).val();
$('#defaultBox').text(text);
});
});
Edit: what is happening in Safari is that as soon as I stop typing, the text immediately gets erased in the textarea I type in. The text does not get deleted from the div but it's hard to see what you wrote since it's hidden.
simple fiddle that works in Safari
http://jsfiddle.net/Va4L2/
I tried with keydown but no difference.
Thanks in advance.

How to re-focus to a text field when focus is lost on a HTML form?

There is only one text field on a HTML form. Users input some text, press Enter, submit the form, and the form is reloaded. The main use is barcode reading. I use the following code to set the focus to the text field:
<script language="javascript">
<!--
document.getElementById("#{id}").focus()
//-->
</script>
It works most of the time (if nobody touches the screen/mouse/keyboard).
However, when the user click somewhere outside the field within the browser window (the white empty space), the cursor is gone. One a single field HTML form, how can I prevent the cursor from getting lost? Or, how to re-focus the cursor inside the field after the cursor is lost? thx!
Darin's answer is right, but doesn't work in Firefox. If you want to steal focus back in Firefox too, you have to delay it until after the event:
<input onblur="var that= this; setTimeout(function() { that.focus(); }, 0);">
Or, better, assigned from JavaScript:
<script type="text/javascript">
var element= document.getElementById('foo');
element.focus();
element.onblur= function() {
setTimeout(function() {
element.focus();
}, 0);
};
</script>
But, I would strongly advise you not to do this. Clicking outside a text box to remove focus from that text box is perfectly normal browser behaviour, which can be of legitimate use (eg. to set search point for ctrl-F, or start a drag-selection, etc). There's very unlikely to be a good reason to mess with this expected behaviour.
<input type="text" name="barcode" onblur="this.focus();" />
You can hook the blur event and refocus the field again. There are very few use cases for doing this, but it sounds like yours may be one of them. Note that you'll probably have to schedule the re-focus via setTimeout or similar, you won't be able to do it within the blur handler itself.
When doing this without affecting the markup, this is easiest if you use a library like Prototype, jQuery, Closure, etc., but you can do it without them (of course), you just have to handle browser differences yourself. For instance, using Prototype:
document.observe("dom:loaded", function() {
var elm = $('thingy');
elm.focus();
elm.observe('blur', function() {
refocus.defer(elm);
});
function refocus(elm) {
elm.focus();
}
});
If you don't mind affecting the markup, you can use the onblur attribute. For instance, this works on IE, Firefox, and Chrome at least (probably others):
HTML:
<input type='text' id='thingy' onblur="refocus(this);">
Script:
function refocus(elm) {
setTimeout(go, 0);
function go() {
elm.focus();
}
}

Categories