Set 'disabled' attribute of 'input' based on value of radio button?

D

David

Hi group,

I'm trying to add a very light sprinkling of JavaScript to a web form as
follows:

0. Of most importance, to me, at least, is that the form must not
_require_ JavaScript in order to function, so this little sprinking is
to be a 'progressive enhancement' only.

1. One input which the user must make on the form is to select 1 of 3
radio buttons to indicate a particular choice.

2. If a particular one of the radio buttons is *not* the selected button
(either at the time the form loads, having read in the user's existing
stored preference data, or as a result of the user selecting 1 of the
other 2 radio buttons), a text input field beneath the radio buttons
should be shown as 'disabled'.

(The "magic" button is the 2nd of 3 in the code below.)

2a. If the user has no existing stored data, then the "magic" radio
button clearly has not already been selected when the form loads, and
so the text field should be disabled. (This is just a further
clarification of rule 2)

3. If the user selects the "magic" radio button, then the text field
should be un-disabled.



So far, I have my form as follows:

[The code below is part of PHP code generating the form output, hence
some embedded variable names. The 'use_*' variables are either empty
or have the value 'checked="checked"', as appropriate.]

::::

<p>
Please choose which source of publications data to use:
</p>

<p>
<label>
<input id="publns_source_repo" name="publns_source"
type="radio" value="repo"

onchange="document.getElementById('publns_uri').disabled =
document.getElementById('publns_source_repo').checked;"

title="Use Publications Repository"
$use_repository />
Use Publications Repository
</label>


<br />
<label>
<input id="publns_source_web" name="publns_source"
type="radio" value="web"

onchange="document.getElementById('publns_uri').disabled =
!document.getElementById('publns_source_web').checked;"

title="Show link to a personal webpage containing
publications data"
$use_webpage />
Show link to a personal webpage containing publications data
</label>


<br />
<label>
<input id="publns_source_local" name="publns_source"
type="radio" value="local"

onchange="document.getElementById('publns_uri').disabled =
document.getElementById('publns_source_local').checked;"

title="Use existing publications database"
$use_localdata />
Use existing publications database
</label>
</p>


<p>
<label for="publns_uri">Web address of personal publications
page</label>
<br />
<span class="hint">
Complete only if you have chosen to display a link to your own
personal webpage of publications data
</span>
<br />
<input id="publns_uri" name="publns_uri"

onload="document.getElementById('publns_uri').disabled =
!document.getElementById('publns_source_web').checked;"

type="text" size="60" value="$publns_webpage_clean" />
</p>


::::

Everything seems to be working, except for when the page is initially
loaded (and when the text field should be enabled or disabled according
to the value of the 'publns_source_web' radio button at that time).

I thought that 'onload' was a valid JavaScript trigger. Does anybody
know where I'm going wrong with my code there?

(There's also the problem that IE and Opera/Win don't seem to ghost
disabled fields, only the *text* within the field, meaning that it's not
obvious that the field is disabled if there is no text in it, in those
cases. I suppose I could add my own custom CSS styles to make the state
of the field clearer..)


Disclaimer: I don't pretend to know any more than the absolute basics of
JavaScript, gleaned from hither and thither on the aethernet over time,
like pollen in the breeze (and so therefore probably out of date and/or
wrong in many ways); if I needed to make significant use of JavaScript,
I would certainly do some proper reading (I have just downloaded the
ECMAScript standard, but I don't really have time to read 258 pages
_just now_, although I am sure it will do me good in the long run), but
I just thought it would be nice to add a *tiny* little sprinkling to my
current project if it was easy to do so. Please turn your flames down
to a moderate heat. ;-)


Thanks for any help,

David.
 
D

Denis McMahon

I thought that 'onload' was a valid JavaScript trigger. Does anybody
know where I'm going wrong with my code there?

No, onload is an attribute used to specify an event handler.

I believe that it may only be applicable to the "body" html element, but
I'm a little hazy on that without checking.

However, it should be as easy for you to check as it is for me to check,
and may be more beneficial for you. If it's harder for you to check, then
you need practice in doing such checks. ;)

Rgds

Denis McMahon
 
R

RobG

Hi group,

I'm trying to add a very light sprinkling of JavaScript to a web form as
follows:

0. Of most importance, to me, at least, is that the form must not
_require_ JavaScript in order to function, so this little sprinking is
to be a 'progressive enhancement' only.

1. One input which the user must make on the form is to select 1 of 3
radio buttons to indicate a particular choice.

2. If a particular one of the radio buttons is *not* the selected button
(either at the time the form loads, having read in the user's existing
stored preference data, or as a result of the user selecting 1 of the
other 2 radio buttons), a text input field beneath the radio buttons
should be shown as 'disabled'.

(The "magic" button is the 2nd of 3 in the code below.)

2a. If the user has no existing stored data, then the "magic" radio
button clearly has not already been selected when the form loads, and
so the text field should be disabled. (This is just a further
clarification of rule 2)

3. If the user selects the "magic" radio button, then the text field
should be un-disabled.

So far, I have my form as follows:

[The code below is part of PHP code generating the form output, hence
some embedded variable names. The 'use_*' variables are either empty
or have the value 'checked="checked"', as appropriate.]

::::

<p>
Please choose which source of publications data to use:
</p>

<p>
<label>
<input id="publns_source_repo" name="publns_source"
    type="radio" value="repo"

    onchange="document.getElementById('publns_uri').disabled =
        document.getElementById('publns_source_repo').checked;"

The change event is a little inconsistent on radio buttons. It is
supposed to fire when the control loses focus, i.e. onblur. Some
browsers wait for that, others don't. Better to use the click event.

You note that the elements are in a form, so you can use that to
reference other form controls and the element that the listener is on
can be referenced as *this*, so:

onclick="this.form['publns_uri'].disabled = this.checked;"

    title="Use Publications Repository"
    $use_repository />
Use Publications Repository
</label>

<br />
<label>
<input id="publns_source_web" name="publns_source"
    type="radio" value="web"

    onchange="document.getElementById('publns_uri').disabled =
        !document.getElementById('publns_source_web').checked;"

    title="Show link to a personal webpage containing
publications data"
    $use_webpage />
Show link to a personal webpage containing publications data
</label>

<br />
<label>
<input id="publns_source_local" name="publns_source"
    type="radio" value="local"

    onchange="document.getElementById('publns_uri').disabled =
        document.getElementById('publns_source_local').checked;"

    title="Use existing publications database"
    $use_localdata />
Use existing publications database
</label>
</p>

<p>
<label for="publns_uri">Web address of personal publications
page</label>
<br />
<span class="hint">
Complete only if you have chosen to display a link to your own
personal webpage of publications data
</span>
<br />
<input id="publns_uri" name="publns_uri"

    onload="document.getElementById('publns_uri').disabled =
        !document.getElementById('publns_source_web').checked;"

Input elements don't have an onload attribute. In HTML 4.01, an onload
attribute is specified for the body and iframe elements only, however
some other elements will dispatch them also (e.g. img).

HTML5 specifies that all HTML elements should dispatch load events,
however it will be awhile before all browsers support it.

You need to put the load listener on the body, so:

<body onload="..." ...>

However if the load is slow, the input may be disabled or enabled
after becoming visible. You might consider using a script element
immediately below the controls so they are updated as soon as they are
in the document.
    type="text" size="60" value="$publns_webpage_clean" />
</p>

::::

Everything seems to be working, except for when the page is initially
loaded (and when the text field should be enabled or disabled according
to the value of the 'publns_source_web' radio button at that time).

I thought that 'onload' was a valid JavaScript trigger. Does anybody
know where I'm going wrong with my code there?

See above.

(There's also the problem that IE and Opera/Win don't seem to ghost
disabled fields, only the *text* within the field, meaning that it's not
obvious that the field is disabled if there is no text in it, in those
cases. I suppose I could add my own custom CSS styles to make the state
of the field clearer..)

Yes, that would be a good idea. Though not sure if older versions of
IE support those types of pseudo class, you may need to add or remove
a class on the element.

Disclaimer: I don't pretend to know any more than the absolute basics of
JavaScript, gleaned from hither and thither on the aethernet over time,
like pollen in the breeze (and so therefore probably out of date and/or
wrong in many ways); if I needed to make significant use of JavaScript,
I would certainly do some proper reading (I have just downloaded the
ECMAScript standard, but I don't really have time to read 258 pages
_just now_, although I am sure it will do me good in the long run), but
I just thought it would be nice to add a *tiny* little sprinkling to my
current project if it was easy to do so. Please turn your flames down
to a moderate heat. ;-)

The ECMAScript spec is not the place resource from which to learn
javascript. :)

Use it as a reference for the language itself, use the W3C, Mozilla,
MS and other documentation for javascript (i.e. ECMAScript as
implemented in browsers). There are some resources listed in the faq,
I'd link to them but it is down (yet again).

<URL: http://www.jibberint.com/faq/ >

There is a chached copy here that seems Ok:

<URL:
http://webcache.googleusercontent.c...=au&client=firefox-a&source=www.google.com.au
 
S

Scott Sauyet

David said:
I'm trying to add a very light sprinkling of JavaScript to a web form as
follows:

0. Of most importance, to me, at least, is that the form must not
_require_ JavaScript in order to function, so this little sprinking is
to be a 'progressive enhancement' only.

Ok, I'll buy that.

[snipped: very clear, but very long explanation that one text box
should be enabled only if a particular radio button is selected.]

This of course means that the form will have slightly different
behavior in user agents with Javascript turned on. I assume that this
is ok for you.

So far, I have my form as follows:

[The code below is part of PHP code generating the form output, hence
some embedded variable names. The 'use_*' variables are either empty
or have the value 'checked="checked"', as appropriate.]

In the future it would be better to share only the output of running
this PHP. This group focuses on JS and might or might not understand
your PHP placeholders.

I've elided most of the code, as the examples to which I link below
all have copies of it included.
<input id="publns_uri" name="publns_uri"

onload="document.getElementById('publns_uri').disabled =
!document.getElementById('publns_source_web').checked;"

type="text" size="60" value="$publns_webpage_clean" />
</p>

Everything seems to be working, except for when the page is initially
loaded (and when the text field should be enabled or disabled according
to the value of the 'publns_source_web' radio button at that time).

I thought that 'onload' was a valid JavaScript trigger. Does anybody
know where I'm going wrong with my code there?

`onload` is appropriate for the body element and for some others, but
is not used on arbitrary form elements. So although that attribute
might be valid here (depending upon your document type), it's not
going to do anything.

A page with this code included, and the PHP variables stripped out, is
at

<http://scott.sauyet.com/Javascript/Demo/2011-07-28a/>

======================================================================

One way to fix this problem is by adding an `onload` handler to the
body tag:

<http://scott.sauyet.com/Javascript/Demo/2011-07-28b/>


<script type="text/javascript">
var checkStatus = function() {
document.getElementById('publns_uri').disabled =
!document.getElementById('publns_source_web').checked
};
</script>
...
<body onload="checkStatus()">


======================================================================

But now that we've written that function, we can reuse it in the
`onchange` handlers of the radio buttons:

<http://scott.sauyet.com/Javascript/Demo/2011-07-28c/>

so that our radio button markup is simpler:

<label>
<input id="publns_source_repo" name="publns_source" type="radio"
value="repo" onchange="checkStatus()"
title="Use Publications Repository"/>
Use Publications Repository
</label>

======================================================================


A different method for making this function run at load is to include
the script just before the close tag for the body element:

<http://scott.sauyet.com/Javascript/Demo/2011-07-28d/>

That has become perhaps the most prevalent technique for running
something later, and many experts swear by it for reasons of quick
loading.

======================================================================


Although these techniques work, there are some outstanding issues
involved. First of all, we often prefer not to let our JS hooks
intrude into the markup if we can prevent it reasonably easily. Here
it's no problem:

<http://scott.sauyet.com/Javascript/Demo/2011-07-28e/>

In that example, I pulled the JS to a separate file, and dynamically
assigned `onchange` handlers to the radio buttons pointing to the new
function.

var
publnsUri = document.getElementById('publns_uri'),
publnsSourceWeb = document.getElementById('publns_source_web'),

checkStatus = function() {
publnsUri.disabled = !publnsSourceWeb.checked
},

radioIds = ["publns_source_repo", "publns_source_web",
"publns_source_local"], i, len = radioIds.length;

for (i = 0; i < len; i++) {
document.getElementById(radioIds).onchange = checkStatus;
}

checkStatus();

======================================================================

This code, though, introduces to the globabl scope five separate
variables. That can be a serious problem in a larger project, and is
simply a bad habit to get in.

Javascript (at least versions so far included in popular browsers)
does not support any sort of block level scoping. Scopes are function-
based, so we can use an immediately invoked function expression to
greatly reduce the visibility of these variables:

<http://scott.sauyet.com/Javascript/Demo/2011-07-28f/>


(function() {
var
publnsUri = document.getElementById('publns_uri'),
publnsSourceWeb = document.getElementById('publns_source_web'),

checkStatus = function() {
publnsUri.disabled = !publnsSourceWeb.checked
},

radioIds = ["publns_source_repo", "publns_source_web",
"publns_source_local"], i, len = radioIds.length;

for (i = 0; i < len; i++) {
document.getElementById(radioIds).onchange = checkStatus;
}

checkStatus();
}());

======================================================================

This is relatively clean code, and I would be more than happy to leave
it there. But something needs to be said about some of the libraries
that can simplify some of these tasks. Such general-purpose libraries
do not garner much respect around these parts, but they are a
substantial part of the modern JS environment.

Currently, the most popular one is jQuery. I would never recommend
including it just to handle the small amount of work we've just done.
But if your project had numerous small or large DOM manipulations per
page, you might at least consider how such tools could help.

A version rewritten to use jQuery is at

<http://scott.sauyet.com/Javascript/Demo/2011-07-28g/>

The code is shorter, and perhaps more readable:

$(document).ready(function() {
var publnsUri = document.getElementById('publns_uri'),
publnsSourceWeb =
document.getElementById('publns_source_web');

$("input[name=publns_source]").change(function() {
publnsUri.disabled = !publnsSourceWeb.checked
}).first().trigger("change");
});

For more details of how this works, you can look up the jQuery API
online.

======================================================================

Finally, you should recognize some bad advice you nught get from the
library fanclubs. That last version could be written in a manner more
in tune with the jQuery way. I would not recommend ever swallowing
this much of the Kool-Aid:

<http://scott.sauyet.com/Javascript/Demo/2011-07-28h/> DON'T DO
THIS!

$(document).ready(function() {
var $publnsUri = $('#publns_uri'), $publnsSourceWeb = $
('#publns_source_web');

$("input[name=publns_source]").change(function() {
$publnsUri.attr("disabled", !$publnsSourceWeb.is(":checked"));
}).first().trigger("change");
});

Essentially, all the changes between the previous version and this one
are likely to be bad ideas. If you want to know why, go ahead and
ask, but for now, remember the fact that a library has a certain
facility never means that you actually have to use it!

======================================================================

(There's also the problem that IE and Opera/Win don't seem to ghost
disabled fields, only the *text* within the field, meaning that it's not
obvious that the field is disabled if there is no text in it, in those
cases. I suppose I could add my own custom CSS styles to make the state
of the field clearer..)

Yes, this can be handled relatively easily with CSS.

Disclaimer: I don't pretend to know any more than the absolute basics of
JavaScript, gleaned from hither and thither on the aethernet over time,
like pollen in the breeze (and so therefore probably out of date and/or
wrong in many ways); if I needed to make significant use of JavaScript,
I would certainly do some proper reading (I have just downloaded the
ECMAScript standard, but I don't really have time to read 258 pages
_just now_, although I am sure it will do me good in the long run), but
I just thought it would be nice to add a *tiny* little sprinkling to my
current project if it was easy to do so. Please turn your flames down
to a moderate heat. ;-)

A light charring all right with you? :)

I applaud you for trying.

As to reading material, the ECMAScript standard is probably not the
place to _start_! Douglas Crockford's _Javascript: The Good Parts_ is
opinionated and in a few places, I believe, downright wrong, but it's
a good overview of the useful features of the language. David
Flanagan's, _Javascript: The Definitive Guide_ is a comprehensive
overview of the language. (The sixth edition just came out and is
huge!) A number of people also speak very highly of Marijn
Haverbeke's online _Eloquent JavaScript: A Modern Introduction to
Programming_, although I haven't read it thoroughly myself.

In any case, I hope this helped. Good luck with your project,

-- Scott
 
E

Evertjan.

RobG wrote on 28 jul 2011 in comp.lang.javascript:
You need to put the load listener on the body, so:

<body onload="..." ...>

However if the load is slow, the input may be disabled or enabled
after becoming visible. You might consider using a script element
immediately below the controls so they are updated as soon as they are
in the document.

There is no need for an onload testing of input element values.

You can set or clear input elemants at will by html
to get the on start of the page you want,
without any onload listener or inbody javascript.
 
S

Scott Sauyet

[I apologize if this is a duplicate. It hasn't shown up locally five
hours after I posted it.]
I'm trying to add a very light sprinkling of JavaScript to a web form as
follows:

0. Of most importance, to me, at least, is that the form must not
_require_ JavaScript in order to function, so this little sprinking is
to be a 'progressive enhancement' only.

Ok, I'll buy that.

[snipped: very clear, but very long explanation that one text box
should be enabled only if a particular radio button is selected.]

This of course means that the form will have slightly different
behavior in user agents with Javascript turned on. I assume that this
is ok for you.

So far, I have my form as follows:

[The code below is part of PHP code generating the form output, hence
some embedded variable names. The 'use_*' variables are either empty
or have the value 'checked="checked"', as appropriate.]

In the future it would be better to share only the output of running
this PHP. This group focuses on JS and might or might not understand
your PHP placeholders.

I've elided most of the code, as the examples to which I link below
all have copies of it included.
<input id="publns_uri" name="publns_uri"

onload="document.getElementById('publns_uri').disabled =
!document.getElementById('publns_source_web').checked;"

type="text" size="60" value="$publns_webpage_clean" />
</p>

Everything seems to be working, except for when the page is initially
loaded (and when the text field should be enabled or disabled according
to the value of the 'publns_source_web' radio button at that time).

I thought that 'onload' was a valid JavaScript trigger. Does anybody
know where I'm going wrong with my code there?

`onload` is appropriate for the body element and for some others, but
is not used on arbitrary form elements. So although that attribute
might be valid here (depending upon your document type), it's not
going to do anything.

A page with this code included, and the PHP variables stripped out, is
at

<http://scott.sauyet.com/Javascript/Demo/2011-07-28a/>

======================================================================

One way to fix this problem is by adding an `onload` handler to the
body tag:

<http://scott.sauyet.com/Javascript/Demo/2011-07-28b/>


<script type="text/javascript">
var checkStatus = function() {
document.getElementById('publns_uri').disabled =
!document.getElementById('publns_source_web').checked
};
</script>
...
<body onload="checkStatus()">


======================================================================

But now that we've written that function, we can reuse it in the
`onchange` handlers of the radio buttons:

<http://scott.sauyet.com/Javascript/Demo/2011-07-28c/>

so that our radio button markup is simpler:

<label>
<input id="publns_source_repo" name="publns_source" type="radio"
value="repo" onchange="checkStatus()"
title="Use Publications Repository"/>
Use Publications Repository
</label>

======================================================================


A different method for making this function run at load is to include
the script just before the close tag for the body element:

<http://scott.sauyet.com/Javascript/Demo/2011-07-28d/>

That has become perhaps the most prevalent technique for running
something later, and many experts swear by it for reasons of quick
loading.

======================================================================


Although these techniques work, there are some outstanding issues
involved. First of all, we often prefer not to let our JS hooks
intrude into the markup if we can prevent it reasonably easily. Here
it's no problem:

<http://scott.sauyet.com/Javascript/Demo/2011-07-28e/>

In that example, I pulled the JS to a separate file, and dynamically
assigned `onchange` handlers to the radio buttons pointing to the new
function.

var
publnsUri = document.getElementById('publns_uri'),
publnsSourceWeb = document.getElementById('publns_source_web'),

checkStatus = function() {
publnsUri.disabled = !publnsSourceWeb.checked
},

radioIds = ["publns_source_repo", "publns_source_web",
"publns_source_local"], i, len = radioIds.length;

for (i = 0; i < len; i++) {
document.getElementById(radioIds).onchange = checkStatus;
}

checkStatus();

======================================================================

This code, though, introduces to the globabl scope five separate
variables. That can be a serious problem in a larger project, and is
simply a bad habit to get in.

Javascript (at least versions so far included in popular browsers)
does not support any sort of block level scoping. Scopes are function-
based, so we can use an immediately invoked function expression to
greatly reduce the visibility of these variables:

<http://scott.sauyet.com/Javascript/Demo/2011-07-28f/>


(function() {
var
publnsUri = document.getElementById('publns_uri'),
publnsSourceWeb = document.getElementById('publns_source_web'),

checkStatus = function() {
publnsUri.disabled = !publnsSourceWeb.checked
},

radioIds = ["publns_source_repo", "publns_source_web",
"publns_source_local"], i, len = radioIds.length;

for (i = 0; i < len; i++) {
document.getElementById(radioIds).onchange = checkStatus;
}

checkStatus();
}());

======================================================================

This is relatively clean code, and I would be more than happy to leave
it there. But something needs to be said about some of the libraries
that can simplify some of these tasks. Such general-purpose libraries
do not garner much respect around these parts, but they are a
substantial part of the modern JS environment.

Currently, the most popular one is jQuery. I would never recommend
including it just to handle the small amount of work we've just done.
But if your project had numerous small or large DOM manipulations per
page, you might at least consider how such tools could help.

A version rewritten to use jQuery is at

<http://scott.sauyet.com/Javascript/Demo/2011-07-28g/>

The code is shorter, and perhaps more readable:

$(document).ready(function() {
var publnsUri = document.getElementById('publns_uri'),
publnsSourceWeb =
document.getElementById('publns_source_web');

$("input[name=publns_source]").change(function() {
publnsUri.disabled = !publnsSourceWeb.checked
}).first().trigger("change");
});

For more details of how this works, you can look up the jQuery API
online.

======================================================================

Finally, you should recognize some bad advice you nught get from the
library fanclubs. That last version could be written in a manner more
in tune with the jQuery way. I would not recommend ever swallowing
this much of the Kool-Aid:

<http://scott.sauyet.com/Javascript/Demo/2011-07-28h/> DON'T DO
THIS!

$(document).ready(function() {
var $publnsUri = $('#publns_uri'), $publnsSourceWeb = $
('#publns_source_web');

$("input[name=publns_source]").change(function() {
$publnsUri.attr("disabled", !$publnsSourceWeb.is(":checked"));
}).first().trigger("change");
});

Essentially, all the changes between the previous version and this one
are likely to be bad ideas. If you want to know why, go ahead and
ask, but for now, remember the fact that a library has a certain
facility never means that you actually have to use it!

======================================================================

(There's also the problem that IE and Opera/Win don't seem to ghost
disabled fields, only the *text* within the field, meaning that it's not
obvious that the field is disabled if there is no text in it, in those
cases. I suppose I could add my own custom CSS styles to make the state
of the field clearer..)

Yes, this can be handled relatively easily with CSS.

Disclaimer: I don't pretend to know any more than the absolute basics of
JavaScript, gleaned from hither and thither on the aethernet over time,
like pollen in the breeze (and so therefore probably out of date and/or
wrong in many ways); if I needed to make significant use of JavaScript,
I would certainly do some proper reading (I have just downloaded the
ECMAScript standard, but I don't really have time to read 258 pages
_just now_, although I am sure it will do me good in the long run), but
I just thought it would be nice to add a *tiny* little sprinkling to my
current project if it was easy to do so. Please turn your flames down
to a moderate heat. ;-)

A light charring all right with you? :)

I applaud you for trying.

As to reading material, the ECMAScript standard is probably not the
place to _start_! Douglas Crockford's _Javascript: The Good Parts_ is
opinionated and in a few places, I believe, downright wrong, but it's
a good overview of the useful features of the language. David
Flanagan's, _Javascript: The Definitive Guide_ is a comprehensive
overview of the language. (The sixth edition just came out and is
huge!) A number of people also speak very highly of Marijn
Haverbeke's online _Eloquent JavaScript: A Modern Introduction to
Programming_, although I haven't read it thoroughly myself.

In any case, I hope this helped. Good luck with your project,

-- Scott
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top