6
  1. I have an <input type=text> with focusout event handler
  2. I have a <button> with click event handler

Focusout checks whether format in input box is correct. It does so by testing input value against a regular expression. If it fails it displays a message (a div fades-in and -out after some time) and refocuses my input by calling

window.setTimout(function() { $(this).focus(); }, 10);

since I can't refocus in focusout event handler. focusout event can't be cancelled either. Just FYI.

Click collects data from input elements and sends it using Ajax.

The problem

When user TABs their way through the form everything is fine. When a certain input box failes formatting check it gets refocused immediately after user presses TAB.

But when user doesn't use TAB but instead clicks on each individual input field everything works fine until they click the button. focusout fires and sets time-out for refocusing. Since time-out is so short focusing happens afterwards and then click event fires and issues an Ajax request.

Question

I have implemented my formatting check as an independent jQuery plugin that I want to keep that way. It uses .live() to attach focusout on all input fields with a particular attribute where format regular expression is defined.

Data submission is also generic and I don't want to make it dependant on formatting plugin. They should both stay independent.

How can I prevent click event from executing without making these two plugins dependant?

Example code I'm fiddling with

After some searching I've seen that all major browser support document.activeElement but I can't make it work in Chrome. FF and IE both report this being the active element, but Chrome always says it's BODY that is active even though click fired on the button element.

Check this code http://jsfiddle.net/Anp4b/1/ and click on the button. Test with Chrome and some other browser and see the difference.

Robert Koritnik
  • 103,639
  • 52
  • 277
  • 404
  • I'm not really sure I understand your question, but wouldn't disabling the `button` if there is an `input` that failed validation solve your problem? – mekwall Jan 07 '11 at 18:15
  • @mekwall: No. Because `click` already fired. It would fire even though `focusout` would disable the button. – Robert Koritnik Jan 07 '11 at 18:30
  • @Robert, alright. Could you throw this together into a test case on [jsFiddle](http://www.jsfiddle.net)? – mekwall Jan 07 '11 at 19:00
  • @mekwall: I've added additional info to my question. Including a link to jsfiddle. Check it out yourself. – Robert Koritnik Jan 07 '11 at 19:01
  • 1
    @Robert May I remark that his auto-focus feature is the most irritating thing that I experienced in a while. Professional web-sites offer some sort of notification if validation failed, but they **never** use such a brute-force approach. – Šime Vidas Jan 07 '11 at 19:09
  • @Šime Vidas: Are you talking about my code or Chrome or what? What are you referring by *his*... – Robert Koritnik Jan 07 '11 at 19:14
  • @Robert I meant "this" not "his"... I'm talking about your code. – Šime Vidas Jan 07 '11 at 19:17
  • 1
    @Robert You want form submission and validation to be independent? But form submission is by design dependent on validation: If it validates, submit, if not, don't. Submission **cannot** be independent off validation. – Šime Vidas Jan 07 '11 at 19:22
  • 1
    i dont know the context you intend to implement this code in, so i cant say, like Sime, that this is annoying, because it may be appropriate. although if the scenario is standard, then i suggest you think a little broader than the user filling out a form. most notably, try and focus on the address bar in firefox when the input box has focus and is empty. youll see that its impossible because ff returns focus to the form... that is frustrating! – davin Jan 07 '11 at 19:24
  • @Šime: Good point. Let me rethink this process all over again. Could you add another answer with the information about validation and submission being the same process? I'll accept it because it is the right answer to my question. – Robert Koritnik Jan 07 '11 at 19:25
  • @davin Yea, that's what I experienced. It hijacks the whole browser. But, as you said, this behavior may be appropriate in some scenarios... it depends on how the OP is using it. – Šime Vidas Jan 07 '11 at 19:30

2 Answers2

4

You could use a flag...

Live demo: http://jsfiddle.net/Anp4b/4/


So your question is:

How can I prevent click event from executing without making these two plugins dependent?

Well, you obviously cannot prevent the click event. If the user wants to click the button, he will, and the click event will trigger. There's nothing you can do about that.

So the answer to the above question is: You cannot.

Based on the current conditions, you have to - inside the click handler - retrieve the validation result, and based on that result, decide if form submission should or should not occur.

JS Code:

$("#Name").focusout(function(){    
    var that = this;    
    valid = this.value.length ? true : false;    
    !valid && window.setTimeout(function() {
        $(that).focus();
    }, 0);            
});


$("#Confirm").click(function(e) {    
    if ( !valid ) { return false; }    
    e.preventDefault();    
    alert('AJAX-TIME :)');    
 });

HTML Code:

<input type="text" id="Name">
<button id="Confirm">OK</button>
Demodave
  • 6,242
  • 6
  • 43
  • 58
Šime Vidas
  • 182,163
  • 62
  • 281
  • 385
  • In my question I've pointed out that both plugins (format check and auto submitting) should stay independent. This way they latter is depending on the first one to make it work. What if the first plugin wasn't loaded? What if someone else's done something similar but not using this global variable. Auto submission plugin would spectacularly fail with this check. – Robert Koritnik Jan 07 '11 at 19:23
  • while that solves the original issue, it still doesnt work 100% in chrome (for me). try click outside the input box and hold the click (i.e. hold down the mouse button) for say, hald a second. the input box "loses" focus. it regains it with a second click, although presumably thats undesirable behaviour – davin Jan 07 '11 at 19:27
  • @davin I don't have this issue in my Chrome browser. – Šime Vidas Jan 07 '11 at 19:36
  • But you can replace the current click handler with another one in `focusout` or `mousedown` and then let that handler rebind the original handler. It's not pretty, but it works as presented in the [second example](http://jsfiddle.net/mekwall/uS7en/3/) in my answer. – mekwall Jan 07 '11 at 20:22
  • @ŠimeVidas please see my problem at http://stackoverflow.com/questions/42874482/jquery-ajax-form-requires-two-clicks-to-submit going nuts trying to fix it... – DragonFire Mar 19 '17 at 11:50
0

Is there are reason you use .focusout instead of .blur?

Using a flag is a good idea, but I would rather use a class on the element. By using classes to determine the state you can also style it accordingly. Here's my example based on your fiddle.

Another solution that hopefully gives the result you are looking for.

1) Create a named click handler:

var clickHandler = function(e){ /** submit form or whatever you want to do**/ };
$("button").click(clickHandler);

2) Add the following to the focusout event when it's failing validation:

$("button").unbind("click", clickHandler).one("click", function(){ button.click(clickHandler); return false;});

You can find an example of this here.

mekwall
  • 28,614
  • 6
  • 75
  • 77