I have taken a look around Stack Overflow on the topic of onblur but so far have not been able to locate an approach to solve what I want to do.
What I have is a simple two column tables with an unknown number of rows. Rows are created at render time based on the number of boxes being shipped. Each column has the following name and id for the input box:
For column 1: shipItems[ rowNum ].barcode
For column 2: shipItems[ rowNum ].trackingcode
Pretty straight forward. What I want to do is validate the trackingcode and if in error alert the user and re-focus the cursor on the column/row that caused the problem. Users will be using a scanner to scan in the information.
Every things works except that I can not get the cursor to go back to the column/input that caused the issue in the onBlur event.
My understanding is that when the onBlur event fires the element is losing focus and thus the focus is being transferred to the new/next element.
I have tried to playing around with the onfocus event, onkeypress events but still have not been successful.
I am open to any ideal to get this done, I have spend way to much time on it as it is. JQuery is not out of the questions or just plan old Javascript.
UPDATE
Here is a link to the script on jsFiddle:
After reviewing your code, best I can tell you are experiencing an unusual bug in jQuery. I have seen some quirky things happen when using focus() (like having to use setTimeout). But, in your case the $(this) is somehow not resolving correctly when calling focus().
At first I thought it was because the id is not following HTML-4 standards, but correcting the id did not help. $(this) still failed to focus, despite the fact it correctly refers to the <input> element. Then I tried identifying the id with jQuery as a string $("'#" + thisId + "'")...still did not work. But, a hard coded id did work...
So, here's how I modified your code and worked around the problem to get it to focus
if( null === $text.match(/\b(1Z ?[0-9A-Z]{3} ?[0-9A-Z]{3} ?[0-9A-Z]{2} ?[0-9A-Z]{4} ?[0-9A-Z]{3} ?[0-9A-Z]|[\dT]\d\d\d ?\d\d\d\d ?\d\d\d)\b/))
{
alert("No Match");
//$(this).focus();//don't use jquery $this
var thisId = $(this).attr('id');//get the id
//use the setTimeout workaround for firefox
setTimeout(function() {
document.getElementById(thisId).focus();//use javascript to set focus
},0);
$(this).css('background-color','Red');
}
Feel free to look at the fiddle (linked above). This approach does correct the focus problem.
I figured out the issue. It turns out that IE and FireFox have very different behavior when it comes to onBlur.
I was calling focus() during the execution of the blur(). since the blur has not completed it either ignored the focus command or executes and then completes the blur.
Some browsers the focus command can cause a blur to be triggered thus creating an infinite loop with the cursor bouncing between the two fields.
Using a timeout will cause the focus to trigger outside of the blur call back function.
Under IE I can make use of onBlur and have no issues, under FF the focus never got called event with a timeout, so it needs an onChange.
I have updated my script - it runs fine on IE - http://jsfiddle.net/boyd4715/3wbtQ/34/
Related
I've noticed a rather odd behavior when running a unit test which passed on PhantomJS but occasionally failed in Chrome, Firefox and IE. In a nutshell:
I set a focus listener for a DOM element.
I invoked element.focus(), yet the listener was not run.
Calling element.focus() for a second time actually ran the listener.
Unfortunately I couldn't reproduce this issue in a fiddle, but it can be done, for instance, in jQuery's website. I do the following steps on Chrome:
Open www.jquery.com and then open DevTools.
Run $("input[name=s]").on("focus", () => console.log("a"));.
Run $("input[name=s]").focus();. No output is generated.
Run $("input[name=s]").focus();. Now "a" is printed to the console for the first time!
What is causing this issue and how could I work around it?
Had a quick delve around the jquery source code, and it seems that focus actually uses focusin, and the code is trying to map to focusin. so if you try this:
$("input[name=s]").on("focusin", () => console.log("a"));
$("input[name=s]").focusin();
it will work. There is a difference between focus and focusin around bubbling:
http://api.jquery.com/focusin/
The focusin event is sent to an element when it, or any element inside
of it, gains focus. This is distinct from the focus event in that it
supports detecting the focus event on parent elements (in other words,
it supports event bubbling).
It seems like the behaviour is a hard to replicate bug, that must be caused by other bit of code somewhere (maybe a lib). Although the code above should help work around it.
I'm having difficulties with getting the .change() event in jQuery to trigger when I change the value of a select drop down. I've already searched for a possible solution though the ones I came across do not seem to work for me...
Basically I have an event on a site which is set as a variable product in WooCommerce, with different time slots. I have written a reasonably complex algorithm to detect whether the maximum number of people have taken that time slot in order to let the user know that the time and date they want is available or not. That part works, though I need to add a trigger on the time slot drop down in order to fire the check.
For debugging purposes I did this:
$('#time-slot').on('change', function() {
console.log("changed");
});
Where '#time-slot' is the ID of the select box. However, this does not seem to trigger the console.log text when I change the select. I even tried the following in my console:
$('#time-slot').trigger('change');
But the "changed" text did not appear in my console.
Then I changed my code so that it would trigger on a click instead. In my console now:
$('#time-slot').trigger('click');
And this time the text appeared in my console just fine - I even tried it with various other random events such as mouseup, mousedown and focus each time manually triggering the event and every other one worked - except change which is the one I really need.
Is change no longer supported? Or is it that I'm coding it incorrectly? The version of jQuery I am using is 1.11.3.
Hopefully there is a simple solution that maybe I'm just overlooking!
Thank you
Scenario: I'm trying to intercept paste events inside a textarea/input text, and filter the content being pasted.
Webkit/IE are handled rather well, as I can attach code to the onpaste event, and then read from the clipboard what is being pasted. Plenty of examples around.
Gecko is trickier, because as far as I know it isn't possible to read the clipboard content on Firefox (unless somebody knows a workaround for that?)
I just use the input swap trick for that.
Opera is being annoying tho. I can trap CTRL+V and SHIFT+INS, but there's no onpaste event.
Not to mention any sort of clipboard interaction, apparently.
So, my question is:
Can I detect if the user clicked on paste in the context menu on Opera? Is there any other way to detect the event?
EDIT:
Thanks everybody for the answers - they all add a good input, even if there's no definitive solution.
Having to choose, I'll pick the only one that tried to address the original question, and that would probably work if it wasn't too much of an hack to even try.
Notes for those that have my same problem (input filtering):
it is possible to capture content being dragged: mouseup + setTimeout does the trick everywhere almost perfectly.
without flash, there is probably no solution bar polling. Even with flash, it's not a completely solid solution either. Too much effort to support 100% of the cases.
I ran into this last year. In short, no.
I ended up using an onchange handler and filtering the content after it's already been pasted into the text box.
You can intercept the paste with jQuery using the bind('paste', function() {});, compare string before and after pasting and apply your formatting.
The following was tested in IE7/FF3.6/Chrome/Safari 5
$("#textarea").bind('paste', function(e){
// Do whatever you needed to do with the code here.
});
Live Example http://jsfiddle.net/VSrTg/2/
Edit An approach would be something like this:
$("#textarea").bind('paste', function(e){
var oldText = this.value;
setTimeout(function() {
// Compare oldText to $("#textarea").val() and format accordingly.
}, 1000);
});
Edit 2 Given your revisions to your original post, if you're worried about the giant market share that is Opera, you're going to have to monitor the value of your textbox with a setInterval() and compare it against itself for changes.
Ultimately there will always be a way around your script, even the above example is susceptible to simply dragging text from another text box (or the address bar) into it without triggering the paste event defined above.
I would like to point out DOJO menu widget that is creating context menus perfectly in different browsers. http://www.dojotoolkit.org/reference-guide/dijit/Menu.html#dijit-menu
What you can do is that detect paste event in browsers that are supporting it and override context menu in browsers that are not supporting this event like opera.
Once you create your own context menu then you can add copy paste menu item or create context menu similar to the default using css.
Edited
Some browsers might not allow us to fetch clipboard content, in this case we can always revert back to flash for borrowing some of its features that are cross browser. See couple of links I posted in comments.
Its complete implementation might have more issues than anticipated but it is possible and we can always give it a try (I will for sure).
The answer to the question is a simple no. The main browsers that have no paste event are recent versions of Opera and Firefox 2. Given that there is no paste event, you need to find an alternative event or set of events to detect a paste from the context menu as it actually happens. You can add handlers for every event there is (I've done this) and you simply get nothing in the relevant browsers when a paste is triggered from the context menu by the user.
This only leaves polling the text input's value regularly, which is not the same thing. You could keep track of keypresses and observe in your polling code that the text input's value has changed by some means other than keyboard input and do a diff, but that's hacky and unreliable.
I use the setTimeout for paste events. But for context menu select nothing seems to work(as stated above). I bind a mousemove to the input's form which fires the update function. Then unbind/bind so they don't stack up.
This handles the context menu select and dragging value to input field.
If your form is small, say with only one input field and the mouse will not land on it after selecting from context menu, bind to the form's parent or document. Sure, it has to wait until the mouse moves but that is the general user action after selecting from context menu.
Works fine.
Is there a cross-browser way to detect live changes to an input field?
By live, I mean not when the field loses focus, and not on the next keypress, and so on. Immediately or something like it.
Using combinations of jQuery and .change(), .keyup(), .bind('paste') and so on I can get working live change detection in some browsers, but not all. Using different combinations will make it work somewhat in other browsers.
The trickiest thing to get working is mouse manipulation of the input field - selecting text and moving it (which is essentially cut and paste), right-clicking and pasting or cutting, etc. For some reason even .mousedown() and .mouseup() don't seem to cut it.
The only cross-browser solution I can think of right now is to check the input field value every 100-or-so milliseconds and compare the value against a stored value. But this seems like overkill when the event-based solution comes so close.
Is there a jQuery plug-in that does this already? Or is there some other way to achieve this?
To complete your change and key handlers, you can add handlers for cut/copy/paste. They work in Firefox >=3, IE, Safari and Chrome (but not in Opera/Konqueror).
Would that cover everything for your use case?
Depending on the Browsers you need to support you might use HTML5's oninput.
It fires immediately when the monitored input changes. In jQuery you would just do:
$('#my-input').bind('input', function(e) {
console.log("#my-input's value changed");
});
Using jQuery, the following is not working in FF, but it is in IE
$(this).focus().select();
I looked around for this and found that you could use a timeout to get around this, but that is not something I want to do if I can avoid it. Does anyone know another way to do this and have it work in FF?
Metropolis
I've run into this before as well. I believe that the setTimeout() solution is the only way this will work in Firefox. The issue has to do with order of events processing, if I remember correctly: IE immediately changes control focus when the focus() method is invoked, but Firefox handles it by adding a focus event to the event queue, which doesn't resolve until after the current event processing has completed. The setTimeout() trick works because it adds the remainder of your code to another event to the event queue after the focus change event, causing it to resolve before your code continues processing.
Please try this code
setTimeout(function()
{
$(Selecter).focus();
}, 0);
i used
$('input').focus().select();
on
<input type="text" value="Some text" />
and it worked in firefox. maybe I dont understand what your problem exactly is.
A solution to this that I just found is to use the below code.
[elementHere].setSelectionRange(0, [elementHere].value.length);
According to the Mozilla Developer Network documentation, this selects the text but does not focus it. At least for me, this prevented issues with selecting text inside a focus event handler, since selecting the text does not cause the element containing it to be focused again.