ONLamp.com
oreilly.comSafari Books Online.Conferences.

advertisement


Advanced JavaScript II
Pages: 1, 2, 3

Note that each item calls the ShowImage JavaScript function when the onclick event is triggered. As we saw in the first example, this hides all the div sections except the one given as the argument to ShowImage. Thus we use it here to show the tab you have just clicked on and hide the rest. CSS or styles are used to actually draw the tabs properly. We have defined two classes: tab, and tab_selected. The former is general and applies to the whole tab bar, while the latter is applied only to the currently selected tab. The CSS looks like this:

ul.tab {
    margin: 0;
    padding: 3px 0;
    border-bottom: 1px solid #778;
    font-weight: bold;
}

ul.tab li {
    display: inline;
    padding: 3px 0.5em;
    margin-left: 3px;
    border-top: 1px solid #778;
    border-left: 1px solid #778;
    border-right: 1px solid #778;
    border-bottom: none;
    background: top repeat-x #89aac7;
    white-space: nowrap;
    color: white;
    cursor:pointer;
}

ul.tab li.tab_selected {
    background: #fff;
    border-bottom: 1px solid #fff;
    color: black;
}

The first section applies to the ul tag and thus the whole tab bar. It sets the margins and padding so it is forced all the way over to the left and a border is drawn along the bottom of the tab bar. The padding is needed for everything to line up properly. We also bold any text in the tab bar.

The next section is applied to all the li tags in the tab bar. display:inline is perhaps the most important, causing the list to go horizontally instead of vertically. Again padding and margins are used to make things line up and leave a pleasing space between the tabs. The border properties draw the top and sides of the tabs themselves (the bottom comes from the ul tag rememeber). Finally, we set the background and foreground colors and ensure text wrapping is disabled.

The final section is applied only to the currently selected tab, overriding any settings in the second section. This changes the background and foreground colors of the tab to make it stand out, as well as drawing a white bottom border to cover up the black bottom border from the ul tag. This gives the illusion that the tab has popped forward in front of the other tabs.

In this example, all the contents of all the tabs are loaded and stored with the page, so clicking on a tab produces the new information almost instantly and without any distracting reloading of the page. Using a very simple JavaScript function and a bit of CSS, we have achieved a very impressive effect indeed.

And Even More div Tricks

As a last example of a useful application of the tricks we have learned above, try the following example that can be used as a way of summarizing large sections of text or lists and allowing the user to open and look at only the lists that he/she is interested in:

Click to Expand Choice of four widget colors

And the source:

<div style="display:block;" id="colors1">
    <table style="background:#eeeebb">
        <tr>
            <td>
                <img src="/onlamp/2007/08/23/graphics/expand.jpg" style="cursor:pointer;"
                alt="Click to Expand" title="Click to Expand" onclick="ShowImage(2, 'colors');" />
            </td>
            <td>
                Choice of four widget colors
            </td>
        </tr>
    </table>
</div>
<div style="display:none;" id="colors2">
    <table style="background:#eeeebb">
        <tr valign="top">
            <td>
                <img src="/onlamp/2007/08/23/graphics/collapse.jpg" style="cursor:pointer;"
                alt="Click to Collapse" title="Click to Collapse" onclick="ShowImage(1, 'colors');" />
            </td>
            <td>
                <ul>
                    <li>blue</li>
                    <li>green</li>
                    <li>red</li>
                    <li>brown</li>
                </ul>
            </td>
        </tr>
    </table>
</div>

By now it should be pretty clear how this is accomplished. Again we have two div blocks, one with the collapsed version of the text and the expand button and one with the fully expanded version of the text and the collapse button. Initially, we show only the collapsed version (display:block) and we use the onclick callback of the image to trigger the swap between div blocks. The blocks are given id of colors1 and colors2 so that they can be easily switched by the ShowImage JavaScript function we wrote earlier.

Drag and Drop and Swap

Now that we have examined div tags ad nauseum, let us look at something a little different. In this example, we reveal a method to drag and drop text (or images) with the mouse. This could be used in making a little JavaScript game or have a more serious purpose, for example, allowing you to swap the order of images in a page of images. In the following example, try to drag and drop the three names on top of each other to swap their positions. Note how you can swap John and Jane with no trouble, but Bill will not swap with either one of them, as he is always the troublemaker.

John
Jane
Bill

This example requires more code than the others shown so far, but is still reasonably straightforward. Unlike the others, it uses global mouse events. Specifically, it depends on three callback functions that are triggered: whenever the mouse button is depressed; when the mouse moves; and when the mouse button is released. The disadvantage of using these sorts of global events is that, if you have multiple things going on at once, it can get pretty hairy quickly. So, you should minimize your use of these and try to have at most one or two per page. For this particular example, global events are pretty much necessary. Let's go through the code one section at a time:

// Set the callbacks
document.onmousedown = mousedown;
document.onmousemove = movemouse;
document.onmouseup   = mouseup;

var lastobj;  // Last draggable object we hovered over
var isdrag;   // True if dragging an object

Here we initialize the three callback functions. mousedown will be called whenever the user clicks a mouse button, movemouse will be called whenever the mouse moves, and mouseup will be triggered whenever the left mouse button is released. We need two global variables as well, the first to track the most recent object we hovered over and the second is a flag, true if we are currently dragging an object.

// This prevents browsers from highlighting the draggable text
// when you click on it.  The table containing all the draggable
// text has id drag_drop.

window.onload = function()
{
    var e = document.getElementById('drag_drop');
    if (e) {
        if (moz)
            e.onmousedown = function () { return false; } // mozilla
        else
            e.onselectstart = function () { return false; } // ie
    }
}

This little function is executed as soon as the page is loaded and ensures clicking on the draggable objects does not highlight the text, as would normally happen when clicking on text. This is achieved by overwriting the normally called function responsible for highlighting the text with an empty function.

// Checks to see if a swap is allowed between two objects based on their ids.
// Change this as you see fit to permit or forbid swapping each possible pair
// of draggable items.
function allowswap(a,b)
{
    if (a.id == "dragdropa" && b.id == "dragdropb" || a.id == "dragdropb" && b.id == "dragdropa")
        return true;
    return false;
}

// Returns true if an object is draggable - change this to suit your needs.
function isdraggable(obj)
{
    if (obj.id.substr(0,8) == "dragdrop")
        return true;
    return false;
}

There are two other utility functions we need; given two objects, allowswap returns true if the objects can be swapped, and false otherwise. Obviously, with some more sophisticated logic here, you can do some interesting things. isdraggable returns true if a given object is draggable. For the purposes of this example, we base this decision on the id of the object beginning with dragdrop, but you may, of course, change this to suit your needs. Draggability could be indicated in other ways, such as with a particular class, but this will do for the purposes of our example.

Pages: 1, 2, 3

Next Pagearrow





Sponsored by: