Element-swapping method comparison

C

Christopher Jeris

Please help me understand the differences, in semantics, browser
support and moral preferredness, between the following three methods
of swapping content in and out of a page via JavaScript. I would also
appreciate any general criticism you have to offer.

I don't know yet how to write the degradation-path code for browsers
that don't support the DOM methods I'm using, so there are some
commented-out paths below.

If the content contained form controls, then methods I and II would
cause hidden controls to be submitted, and method III would cause them
not to be submitted, correct?


Here is the page content. The upper area contains three buttons
that select which text is to be displayed in the lower area. Standard
HTML wrapper is omitted.

<!-- control area -->
<div id="control_area">
<button id="button_1" onclick="do_button(1);">1</button>
<button id="button_2" onclick="do_button(2);">2</button>
<button id="button_3" onclick="do_button(3);">3</button>
</div>

<!-- content area -->
<div id="content_area">
<div class="content" id="content_1">Content box 1.</div>
<div class="content" id="content_2">Content box 2.</div>
<div class="content" id="content_3">Content box 3.</div>
</div>


Method I. Class swapping. Define two CSS classes, one "hidden"
and one "non-hidden"; the event-handler changes the className of
each div.

<style type="text/css">
div.content { display: none; }
div.content_unhidden { display: block; }
</style>

<script type="text/javascript">
var content_boxes = new Array();
// get the div objects
if (document.getElementById) {
for (var i = 1; i <= 3; i++) {
content_boxes = document.getElementById("content_" + i);
}
} else {
; // do something else when we don't have document.getElementById
}

function do_button(n) {
for (var i = 1; i <= 3; i++) {
// if div.className is not provided by the browser's DOM,
// setting it should be harmless, right?
content_boxes.className = (i == n) ? "content_unhidden"
: "content";
}
}
</script>


Method II. Direct setting of the style.display property. Goodman
says this is DOM Level 2, not 1, and in particular setting
style.display to "block" is not supported by IE4, although "none"
is.

<script type="text/javascript">
var content_boxes = new Array();
// get the div objects
if (document.getElementById) {
for (var i = 1; i <= 3; i++) {
content_boxes = document.getElementById("content_" + i);
}
} else {
; // do something else when we don't have document.getElementById
}

// begin by hiding them all
if (content_boxes[1].style) {
for (var i = 1; i <= 3; i++) {
content_boxes.style.display = "none";
}
} else {
; // do something else when we don't have div.style
}

function do_button(n) {
if (content_boxes[1].style) {
for (var i = 1; i <= 3; i++) {
content_boxes.style.display = (i == n) ? "block"
: "none";
}
} else {
; // do something else when we don't have div.style
}
}
</script>


Method III. Moving of nodes in and out of the surrounding box by DOM
methods. I suppose it would be more efficient to wrap _all_ of this
in a check for DOM support, so that you don't have to check every
method?

<script type="text/javascript">
var bounding_box;
var content_boxes = new Array();
// get the div objects
bounding_box = document.getElementById("content_area");
for (var i = 1; i <= 3; i++) {
content_boxes = document.getElementById("content_" + i);
}

// begin by hiding them all
while (bounding_box.hasChildNodes()) {
bounding_box.removeChild(bounding_box.firstChild);
}

function do_button(n) {
// prune out all the elements:
while (bounding_box.hasChildNodes()) {
bounding_box.removeChild(bounding_box.firstChild);
}
// then add back in the one we want
bounding_box.appendChild(content_boxes[n]);
}
</script>


Thanks for your time,
 
Y

Yann-Erwan Perio

Christopher said:
Please help me understand the differences, in semantics, browser
support and moral preferredness, between the following three methods
of swapping content in and out of a page via JavaScript.

Changing DOM structure would be theoretically best in swapping content,
since you really want to reflect a document fragment change; you can of
course accompany the new fragments with CSS to have a good presentation.

Now, CSS being more supported across user agents than DOM methods, means
that you'll see it used more often to achieve the content swapping
(since the visual rendering would appear to be the same in the end).

Eventually, most designers will however question the need to have
content swapping when they can make separate pages:)
If the content contained form controls, then methods I and II would
cause hidden controls to be submitted, and method III would cause them
not to be submitted, correct?

I would tend to agree, provided the HTML is well-formed; now I don't
know why but I wouldn't be surprised to discover that with the buggy
version of browser X, elements with display set to none are not sent
along with the form submission:)
Method I. Class swapping. Define two CSS classes, one "hidden"
and one "non-hidden"; the event-handler changes the className of
each div.
div.content_unhidden { display: block; }

FYI underscores are not permitted in CSS identifiers.
// if div.className is not provided by the browser's DOM,
// setting it should be harmless, right?

Yes, but that doesn't mean your fallback mechanism will fire.


Method I is a good method, although the className property is not
supported in legacy browsers (Opera 6, Netscape 4, IE4 I think). However
changing the className can be quite resource-demanding when done frequently.
Method II. Direct setting of the style.display property. Goodman
says this is DOM Level 2, not 1, and in particular setting
style.display to "block" is not supported by IE4, although "none"
is.

A good method too, probably better supported by browsers than classNames
when you stick to "block" and "none"; certainly faster and the best
adapted to presentational swapping issue. Note that all display
properties are however far from being supported anywhere (e.g. table
layouts).
Method III. Moving of nodes in and out of the surrounding box by DOM
methods. I suppose it would be more efficient to wrap _all_ of this
in a check for DOM support, so that you don't have to check every
method?

Well it depends on your fallback solutions, whether you want to set a
general fallback solution or many ones... but yes. Feature detection is
a solid approach which however quickly burdens the code with numerous
checks. Doing the big part at some entry point can relieve other parts
of the code.

Method III is an excellent one when you truly want to swap content; it
tends to be quite supported since most user agents try now to respect
the W3C texts. Note that speed might also be an issue if you change
content in short intervals, since browsers may insert/remove nodes, or
working on orphaned nodes, at different speed.

As ever, the real problem you'll have to tackle will have its own
specificities, which may eventually force strange conceptions. Consider
filtering/sorting table elements; would it be better to change the
display or to remove nodes when filtering? What if you need to traverse
the filtered data frequently? If speed really matters would positioned
div be faster a table re-arranging?


Regards,
Yep.
 
Y

Yann-Erwan Perio

*chris spends a frantic half-hour reading specs*

Underscores are indeed forbidden by the original CSS 2 spec!
Fortunately for me, this was apparently changed in a 2001 erratum[1]
and the CSS 2.1 working draft[2] permits them.

*well it's high time for yep to read back some specs*

Thanks for the correction!
 

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

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top