Dynamic Form Settings with JQuery

One of the thing I like to do when creating HTML forms is to hide the input fields of features that users have not yet selected. It reduces the clutter on the screen, makes it easier for users to navigate the settings page, and for them to tell which features are currently enabled.

Typically, this is done by using a snippet of Javascript attached to the onclick attribute of a checkbox or radio button. When clicked, the code changes the CSS display property of the hidden fields from none to block (or inline):

<input type="checkbox" name="enable-scroll" 
       onclick="toggleDisplay('scroll-left'); 
                toggleDisplay('scroll-right')"/>

toggleDisplay is the following Javascript function:

function toggleDisplay(id) {
   var el = document.getElementById(id);
   if (el.style.display == 'block') {
      el.style.display = 'none';
   } else {
      el.style.display = 'block';
   }
}

This works very well, but there are two problems. First, it’s a pain to have to scatter snippets of Javascript throughout the form–even if it’s only to call a function. Second, you still have to add more code to initialize the visibility of the fields when the page is load.

Fortunately, there is a good solution to these problems–use the Javascript framework, JQuery.

The main advantage of using JQuery is that it’s extremely easy to attach event handlers to individual form fields. For this checkbox:

<input type="checkbox" id="enable-scroll" name="enable-scroll"/>

all you have to use is the following JQuery code:

$('#enable-scroll').click(function(event) {
   $('#scroll-left, #scroll-right').toggle(this.is(':checked'));
});

The code attaches a mouse click handler to the element with the id of #enable-scroll and sets the visibility of elements #scroll-left and #scroll-right depending on the checked state of #enable-scroll.

(Note: the name of the toggle function is a bit misleading since it sets the visibility state of the element depending on the boolean parameter it takes, so it doesn’t actually toggle the visibility of the element, but sets it according to the specified value.)

$.fn.showIfChecked

So far so good, but you don’t really want to have to write three lines of code for every field you want to toggle the visibility of, and you still have to write additional code to set the initial state correctly.

It would be much better to write one generic function to set the initial state and handle the mouse clicks–and so we end up with the function showIfChecked:

$.fn.showIfChecked = function(el) {
   // Set initial visibility state.
   $(el).toggle(this.is(':checked'));
   // Attach handler to update visibility state when clicked.
   this.click(function(event) {
      $(el).toggle($(this).is(':checked'));
   });
   // Return 'this' to allow standard JQuery chaining
   return this;
};

By declaring the function in the form $.fn.showIfChecked we’re actually extending the JQuery framework, allowing us to call the function directly on any element on the page, like this:

$('#enable-scroll').showIfChecked('#scroll-left, #scroll-right');

And there you have it, just one, very clear line of code to implement the behavior we are looking for. Here is an example of the code in action (click the checkbox):

One additional thing to remember is that you should set the initial CSS state of the fields you are toggling to display:none otherwise users may see them on the page for a second or two while the page is loading, before they disappear.  This can look a little messy.

(Note: calling toggle(true) on an element initially set to display:none in the CSS stylesheet will set display:block. So if you call this function on an element that is supposed to be display:inline, it may mess up the formatting. To solve this issue, I typically wrap the elements I want to hide in a div element and toggling that.)

$.fn.showIfOneChecked

Sometimes the test to see whether a settings field should be visible is a little more involved. Perhaps you want to display a setting when just one of two settings is selected. Well, the function for that case almost as simple as the previous case:

$.fn.showIfOneChecked = function(el) {
   $(el).toggle(this.filter(':checked').length > 0);
   var self = this;
   this.click(function(event) {
      $(el).toggle(self.filter(':checked').length > 0);
   });
   return this;
};

Here, instead of just testing the state of the checkbox the user has clicked, we check the states of all the selected checkboxes to see if any one of them is checked. So when calling this function, we include selectors for all the checkboxes we want to test:

$('#enable-scroll-mouse, #enable-scroll-keyboard')
        .showIfChecked('#scroll-left, #scroll-right');

Here is showIfOneChecked is action (click one of the checkboxes):

$.fn.showIfAllChecked

Finally, here is a version of the function that will only display settings fields when all of the selected checkboxes are checked:

$.fn.showIfAllChecked = function(el) {
   $(el).toggle(this.length == this.filter(':checked').length);
   var self = this;
   this.click(function(event) {
      $(el).toggle(self.length == self.filter(':checked').length);
   });
   return this;
};

This is how you would call this function:

$('#enable-mouse, #enable-keyboard')
        .showIfChecked('#show-input-method');

And here is a working example of showifAllChecked (you have to select both checkboxes before the other field is displayed).

So if you include these three little functions in your standard settings page script, you have a very concise and easy to use method for adding a little dynamic content to your settings pages.

This entry was posted in JQuery and tagged , , . Bookmark the permalink.

One Response to Dynamic Form Settings with JQuery

  1. Bella Petrelli says:

    CSS is designed primarily to enable the separation of document content (written in HTML or a similar markup language) from document presentation, including elements such as the layout, colors, and fonts.This separation can improve content accessibility, provide more flexibility and control in the specification of presentation characteristics, enable multiple pages to share formatting, and reduce complexity and repetition in the structural content (such as by allowing for tableless web design). ..”

    Latest write-up produced by our very own blog page
    <http://www.foodsupplementcenter.com