Skip to content
Ben Boyle edited this page Feb 26, 2014 · 9 revisions

Only ask for an email address when the users asks for a reply

<ol class="questions">
    ...
    <li>
        <fieldset>
            <legend>
                <span class="label">Would you like a reply?</span>
                <abbr title="(required)">*</abbr>
            </legend>
            <ul class="choices">
               <li><input type="radio" name="replyRequested" id="reply-requested-yes" value="yes" /><label for="reply-requested-yes">Yes</label></li>
               <li><input type="radio" name="replyRequested" id="reply-requested-no" value="no" /><label for="reply-requested-no">No</label></li>
            </ul>
        </fieldset>
    </li>
    <li>
        <label for="email">
            <span class="label">Email</span>
            <abbr title="(required)">
        </label>
        <input type="email" id="customer-email" name="emailField" required="required" size="40" />
    </li>
    ...
</ol>
var emailField = $( '#customer-email' ),

    toggleEmailRelevance = function() {
        // is a reply requested?
        var isRelevant = $( '#reply-requested-yes' ).is( ':checked' );
        // set relevance of the email question
        emailField.relevance( 'relevant', isRelevant );
    }
;

// check relevance whenever the radio buttons are clicked
$( ':radio[name=replyRequested]' ).bind( 'click', toggleEmailRelevance );

// set the initial relevance when the form is loaded/refreshed
toggleEmailRelevance();

Example 1 on codepen

Not quite there…

You will notice that relevance is being toggled on #customer-email. This is the text field for the email address, but does not include the label. If we leave it like this, the text box will be shown and hidden but the label will always be visible.

We really want to show/hide the entire "question"—that is, the <li> element that wraps the label and the input.

There are 2 ways to solve this.

1. Intercept events

You can intercept the relevant and irrelevant events and run the show and hide functions on the <li> wrapper.

// show/hide entire 'question' when fields become irrelevant
$( '.questions > li' )
	.bind( 'relevant', function( event ) {
		$( this ).relevance( 'show' );
		event.stopImmediatePropagation();
	})
	.bind( 'irrelevant', function( event ) {
		$( this ).relevance( 'hide' );
		event.stopImmediatePropagation();
	})
;

Example 2 on codepen

2. Toggle relevant on the wrapper, instead of the field

In the original code, emailField is $( '#customer-email' ) which is just the textbox. It is a simple matter of making this jquery object the wrapper instead, like so:

var emailField = $( '#customer-email' ).closest( 'li' ),

    toggleEmailRelevance = function() {
        // is a reply requested?
        var isRelevant = $( '#reply-requested-yes' ).is( ':checked' );
        // set relevance of the email question
        emailField.relevance( 'relevant', isRelevant );
    }
;

// check relevance whenever the radio buttons are clicked
$( ':radio[name=replyRequested]' ).bind( 'click', toggleEmailRelevance );

// set the initial relevance when the form is loaded/refreshed
toggleEmailRelevance();

Example 3 on codepen

Summary

Option 2 is probably easier for most situations, but the choice is yours! Often when scripting with forms, you are already accessing and/or modifying the actual input elements and it’s easier to just toggle relevance on those existing objects. In this case, the code shown in Option 1 needs only be included once and can be used across an entire website to handle this situation.

You can use both if you like.