logo

This is as this does

This is a handy keyword in JavaScript but only if you really understand what it means. Until recently I was confused. Then I read "this" and now I am feeling enlightened.

The article puts it quite simply:

In JavaScript this always refers to the "owner" of the function we're executing, or rather, to the object that a function is a method of.

Using this new knowledge I put it to use yesterday when I had to sort out problems with a web form. It was using a combination of the nasty "Refresh values on keyword change" field property, in conjunction with some hide when formulas to toggle the display of parts of the form. It worked but needed multiple round-trips to the server. In terms of usability it was a complete nightmare.

So I wrote a toggle function in JavaScript. The fields that previously used the refresh on change method now have a call to the toggle() function in their onclick event instead.

Here are some examples of if in use:

Test Toggle Fields
Would you consider yourself a JavaScript guru?

Yes No

It's raining. Did you bring the washing in?

Yes No

I confirm I read the whole of the EULA

Toggling areas of a form on and off, based on user input, is always useful. In this example it's merely text but could well be fields in the hidden bits.

I'm sharing the function I ended up writing as not only useful but a lesson in simplicity and versatile coding.

The function could have easily have looked something like:

function toggle(id, obj){
 if(obj[0].checked) {
        document.getElementById(id).style.display='';
 } else {
        document.getElementById(id).style.display='none';
 }
}

While this might work for the radio button where "Yes" is the desired on state and it happens to be the first option, what about the second example where we want choosing no to display a certain section?

A much better way is to take some of the logic out the function and place it in the call to the function. To call the function above we would have used:

<input type="radio" onclick="toggle('test1', this)" />

But we could just as well call a function like this:

<input type="radio" onclick="toggle('test1', this.value=='Yes')" />

Yes you can do that! You can have your own litle bits of code forming the arguments passed to the function itself.

The onclick event uses "this" in the call to the function, rather than the function itself, which gets round the issue of scope mentioned in the linked article above.

The second argument received by the function is then a boolean, rather than a string or object, which we can call "show" and use like so:

function toggle(id, show){
 if(show) {
        document.getElementById(id).style.display='';
 } else {
        document.getElementById(id).style.display='none';
 }
}

For a radio button where you want to display a section when no is selected you simply change the call, rather than the function itself, like so

<input type="radio" onclick="toggle('test2', this.value.toLowerCase()=='no')" />

For the checkbox the call is

<input type="radio" onclick="toggle('test3', this.checked)" />

Simple isn't it! We could go one step further and simplify the function to one line:

function toggle(id, show){
	document.getElementById(id).style.display={show)?'':'none';
}

With this function in your JS Header of a form you can simply add the following to the onclick event of a field:

Domino will then add the call to each individual radio button and this.value will refer to each individual button, so no need to work out which one is selected.

The same function can be used by any type of field — or buttons, images and links for that matter. You just need to make sure the second parameter works out to a boolean. I like this function as it's ultimately portable. In the past I've written JavaScript functions that will only ever work in that one scenario — throw-away functions if you will. As my understanding of the language improves I find myself trying not to and this is one example of that.

Comments

    • avatar
    • Richard Shergold
    • Thu 1 Mar 2007 06:20 AM

    Thanks Jake, that's a handy tip!

  1. Excelent! I love these functions (and all your explanation) that are simple and reusable :)

    Thanks Jake

    • avatar
    • Mark
    • Thu 1 Mar 2007 09:21 AM

    Kewl. There is really still much to come from JavaScript in the future.

    At the moment I am digging with an agent to produce JSON. Although the task is simple I needed much time just to know what I actually want to get. Combined with Prototype or YUI.EXT or so it is terrific how easy some things can be if you do it the right way...

    • avatar
    • Mark
    • Thu 1 Mar 2007 09:25 AM

    one thing I forgot to mention: For a non-mandatory radio button it is a good practice to add a function to the onDblClick event which resets the button to an empty selection

  2. Just a suggestion really: switch className instead of toggling styles whenever possible.

    {Link}

    function toggle(id, show){

    if(show) {

    document.getElementById(id).clasName = "active";

    } else {

    document.getElementById(id).className = "inactive";

    }

    }

    Now, you can use CSS specific to the tag and className to get some pretty great results:

    ul#tabbednavigation li {

    border: 1px solid #999;

    padding: 4px;

    text-align: center;

    cursor: pointer;

    }

    ul#tabbednavigation li.inactive {

    border-bottom: 1px solid #999;

    background-color: #cfcfcf;

    font-size: 8pt;

    }

    ul#tabbednavigation li.inactive {

    border-bottom: none;

    background-color: #fff;

    font-size: 9pt;

    }

    form#contact fieldset {

    border: none;

    width: 500px;

    }

    form#contact fieldset.inactive {

    display: none;

    }

    form#contact fieldset.active {

    display: block;

    }

    Now, you could very easily build a tabbed-based navigation "engine" that will allow a tab to trigger the conditional display on a given section in a form:

    function toggle(id, show){

    var idcontainer = id + "_container";

    if(show) {

    document.getElementById(id).clasName = "active";

    document.getElementById(idcontainer).clasName = "active";

    } else {

    document.getElementById(id).className = "inactive";

    document.getElementById(idcontainer).className = "inactive";

    }

    }

    .. I'm being lazy here and not writing the looping through like-elements to grab the other tabs and making sure they're inactive (as well as their correlating fieldsets)... but you get the idea...

    Sorry to babble on... good stuff Jake!

  3. Proper form now, no empty quotes.

    {Link}

    9.2.4 The 'display' property

    'display'

    Value: inline | block | list-item | run-in | inline-block | table | inline-table | table-row-group | table-header-group | table-footer-group | table-row | table-column-group | table-column | table-cell | table-caption | none | inherit

    Initial: inline

    Applies to: all elements

    Inherited: no

    Percentages: N/A

    Media: all

    • avatar
    • Brian Miller
    • Thu 1 Mar 2007 12:22 PM

    @Michael:

    Careful, now - not every element defaults to display: inline. Setting the display to a null string uses the browser default for the type of element. This is especially thorny when you're dealing with table parts.

    @Jake:

    One best-practice you might want to start getting into is avoiding cluttering the global (window) namespace. Every time you do a

    function blap (foo) { alert( "Your code here." ) };

    you're actually attaching that function to the window object. Better might be something like this:

    var Codestore = {

    toggle: function(foo,bar) { ... },

    waffle: function(baz) { ... },

    baffle: function(bling) { ... }

    };

    You would call this by using Codestore.toggle("b0rp", true);

    Besides slightly better memory performance, you also get a little bit of organization. And, you don't have to worry about some other programmer hogging the global name "toggle" on you.

  4. Thanks Jake. It's handy Tip.

    If you're using Protoype v1.5, the toggle() function is available to us. Just call it from the OnClick event, like below:

    if(this.value == 'Pink') $('underneath').toggle()

  5. Ext.Get('underneath').toggle()

    ;P

    • avatar
    • YiMing
    • Sat 3 Mar 2007 07:05 AM

    There's many JS frameworks you can use, like YUI and Prototype, but your code give me some inspiration, thanks.

    • avatar
    • Jake Howlett
    • Sat 3 Mar 2007 01:40 PM

    Rich. That's framework-dependent and has no logic to it, so wouldn't really work for what I've described.

Your Comments

Name:
E-mail:
(optional)
Website:
(optional)
Comment:


About This Page

Written by Jake Howlett on Thu 1 Mar 2007

Share This Page

# ( ) '

Comments

The most recent comments added:

Skip to the comments or add your own.

You can subscribe to an individual RSS feed of comments on this entry.

Let's Get Social


About This Website

CodeStore is all about web development. Concentrating on Lotus Domino, ASP.NET, Flex, SharePoint and all things internet.

Your host is Jake Howlett who runs his own web development company called Rockall Design and is always on the lookout for new and interesting work to do.

You can find me on Twitter and on Linked In.

Read more about this site »

More Content