0

I have a disabled element which I enable it only after value was entered to it's previous input, the problem is that change triggers before the input lost focus and the focus moved to the next not disabled element, so removing the disabled attribute then is no good.

HTML:

Fill this before you continue:      <input id="a" />
Fill this after the previous input: <input id="b" disabled="disabled" />​

jQuery:

$('#a').change(function(){
    if (this.value === "")
        $('#b').attr('disabled', 'disabled');
    else
        $('#b').removeAttr('disabled');
});​

Fiddle

I manged to overcome this problem by changing from disabled to readonly but then it's readonly and not disabled as I preferred, are there good and robust(mouse proof) ways to achieve it and using readonly?

Things to consider:

  • Subscribing to multiple events doesn't really seems right.
  • The user can paste text to the 1st input without using keyboard at all.
Community
  • 1
  • 1
gdoron
  • 147,333
  • 58
  • 291
  • 367
  • `change` doesn't trigger before the input has lost focus AFAIK. What browser are you using? – Asad Saeeduddin Jan 02 '13 at 17:17
  • 1
    @Asad, _"change- **The change event occurs when a control loses the input focus** and its value has been modified since gaining focus. This event is valid for INPUT, SELECT, and TEXTAREA. element."_ [Spec](http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-eventgroupings-htmlevents) – gdoron Jan 02 '13 at 17:21
  • just for suggestion: if you are building a form which takes email or password not a raw text then enable the other input when first input was validated successfully! there is no use of method you are using! people will add white-space only and unlock the other input ;) – Muhammad Talha Akbar Jan 02 '13 at 17:21
  • Yes, it occurs when the input loses focus, not before. – Asad Saeeduddin Jan 02 '13 at 17:21
  • In ES5 compatible browsers you can set a `watch` on the value property of the first input, which means regardless of how the value changes the second input's disabled attribute is adjusted appropriately. I can make a demo if you're interested. – Asad Saeeduddin Jan 02 '13 at 17:34
  • well, what about incompatible? add separate code for them? also detecting the browser whether it supports the watch attribute or not? – Muhammad Talha Akbar Jan 02 '13 at 17:35
  • @AspiringAqib There is a polyfill available that adds `watch` support cross browser. – Asad Saeeduddin Jan 02 '13 at 17:39
  • @Asad, yes I'm really interested. – gdoron Jan 02 '13 at 17:43
  • 1
    @AspiringAqib, I think paste with keyup will work, not with `change`. – gdoron Jan 02 '13 at 17:53
  • @gdoron Unfortunately, it appears the `value` property doesn't work well with `watch`. It would appear pasting and typing changes some internal property that `value` is a getter for. The best I could come up with is: http://jsfiddle.net/HmzYR/ – Asad Saeeduddin Jan 02 '13 at 17:54
  • well if you wanna add so many events then i should have answered a long ago! i thought my answer will be downvoted because you didn't wanted multiple events! – Muhammad Talha Akbar Jan 02 '13 at 17:56
  • @AspiringAqib, you're right, I commented to your comment with `change` + `paste`. please write an answer, I believe this is the best option we have. – gdoron Jan 02 '13 at 18:01
  • no, man just leave it, i don't wanna add answer! well, it's working as you want? – Muhammad Talha Akbar Jan 02 '13 at 18:03
  • @AspiringAqib, yes. I really wish I could delete the question it's a mess!!! – gdoron Jan 02 '13 at 18:03
  • well, i also think you need to do that :D i will tell truth that when i saw this question, i was laughing that a senior like you is asking this type of question! i know that my recent lines seems odd but that's the truth :D sorry bro well, no need of it, we all downvote your question and it will automatically closed :P – Muhammad Talha Akbar Jan 02 '13 at 18:06
  • @AspiringAqib, I wanted a way with one event so if the answer is _you can't..._ there is no purpose in the question... but if there was a way which I and you didn't know... then... I try to stay open minded. – gdoron Jan 02 '13 at 18:10
  • @gdoron yeah golden lines, well ok wanna remove so you can :D – Muhammad Talha Akbar Jan 02 '13 at 18:12
  • @AspiringAqib, after a question got answers only a mod can delete it... – gdoron Jan 02 '13 at 18:15
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/22072/discussion-between-aspiring-aqib-and-gdoron) – Muhammad Talha Akbar Jan 02 '13 at 18:16
  • @gdoron come in chat wanna ask you some questions ;) – Muhammad Talha Akbar Jan 02 '13 at 18:17

4 Answers4

2

You have said in your question that you don't want to subscribe to multiple events, but this is the only way I can think of to do this. The problem is that different ways of changing the value of the input all interface directly with the C/C++ DOM, but they do not do it through the JS API. See this question for more on this.

A reasonably bulletproof way of doing it while subscribing to multiple events would be:

$('#a').on('keyup paste propertychange input', function() {
    if (this.value === "") $('#b').prop('disabled', true);
    else $('#b').removeAttr('disabled');
});

Here is a demonstration: http://jsfiddle.net/HmzYR/

Community
  • 1
  • 1
Asad Saeeduddin
  • 46,193
  • 6
  • 90
  • 139
1

Have you considered adding an event on onkeydown or onkeyup?

If the users just needs to enter something you can add an event on onkeyup that does validation and sets the disabled property of the other input element.

I'm not sure about the order of events but onkeyup also fires after the focus has moved I would assume. But this shouldn't be much of problem in this case. One case I can think of is the following sequence of keys: "a" backspace tab. I suppose the perfect solution would be to use onkeydown and inspect the key before it's pressed, but it's hard to predict the effect of non-readable keys like backspace and arrowdown.


Another suggestion: attach an onkeydown listener and look for the tab key. Validate the value and enable the next input field.


In essence: you either need to catch all input events, or all events that change focus (like tab). And you must act before the events are completed.

Halcyon
  • 57,230
  • 10
  • 89
  • 128
  • The user can paste text without using keyboard, and subscribing to multiple events doesn't seem right for such a simple task. – gdoron Jan 02 '13 at 17:26
  • This is not a _simple_ task. You want to do live form generation, that's quite involved. Pasting is not a problem, you will see `ctrl "v" tab`. Validation after `"v"` should enable the next input element. – Halcyon Jan 02 '13 at 17:29
  • well, buddies don't fight and @gdoron please explain what do you exactly want? because i have tried your code and it's working! – Muhammad Talha Akbar Jan 02 '13 at 17:31
  • 1
    @FritsvanCampen It is possible to paste without using the keyboard. – Asad Saeeduddin Jan 02 '13 at 17:31
  • @AspiringAqib, I agree this thread became a mass, I wish I could delete it, but I can't do that now... – gdoron Jan 02 '13 at 17:33
  • i know you don't wanna add multiple events but just a suggestion though ^_^ http://jsfiddle.net/swubm/7/ – Muhammad Talha Akbar Jan 02 '13 at 17:49
0

Use prop and not attr:

$('#b').prop('disabled', true);

Also try hooking to the keyup event instead of the change event.

Here is a fiddle: http://jsfiddle.net/maniator/swubm/3/

For more explanations please see here: .prop() vs .attr()


Fiddle to handle cutting and pasting using mouseout: http://jsfiddle.net/maniator/swubm/4/ (based on comments below)

Community
  • 1
  • 1
Naftali
  • 144,921
  • 39
  • 244
  • 303
  • You have a typo and anyway I'm almost sure it won't help, but I'll give it a try. **UPDATE:** I tried it at jsFiddle, and it didn't work, not sure why did you think it would. – gdoron Jan 02 '13 at 17:17
  • @gdoron I added a fiddle demo for you ^_^ – Naftali Jan 02 '13 at 17:21
  • What about the mouse? it seems to be to complicated adding all those events. and the if you subscribe for the `keyup` then the `attr` will work just the same! – gdoron Jan 02 '13 at 17:23
  • @gdoron what about the mouse? – Naftali Jan 02 '13 at 17:23
  • Though it's your question there it doesn't seem like you know the difference between the two. – gdoron Jan 02 '13 at 17:24
  • @gdoron can you please explain what you mean by mouse? – Naftali Jan 02 '13 at 17:25
  • Pasting text with mouse doesn't trigger the `keyup` event. – gdoron Jan 02 '13 at 17:26
  • @gdoron so add `mouseout` if you really want to :-) http://jsfiddle.net/maniator/swubm/4/ – Naftali Jan 02 '13 at 17:28
  • @gdoron you want to do a lot of things. one event is not going to cut it. – Naftali Jan 02 '13 at 17:30
  • I admit it was I, and I thought I explained why, the `prop` has nothing to do here, so _"this answer is not helpful"_. – gdoron Jan 02 '13 at 17:41
  • @gdoron umm yes it was. It is not advisable to futz with attributes. Use it's properties and everything will be better and nicer ^_^ also it reduces everything to one line of code ^_^ – Naftali Jan 02 '13 at 17:42
-2

I updated my answer: http://jsfiddle.net/swubm/10/

Fill this before you continue:
<input id="a" />
<br>
<br>
Fill this after the previous input
<input id="b" disabled />​

JS:

$('#a').bind('input propertychange', function() {
    var value = $('#a').val();
    if (value == "")
        $('#b').attr('disabled', 'disabled');
    else
        $('#b').removeAttr('disabled');

});
phnkha
  • 7,782
  • 2
  • 24
  • 31