Collapsible Content?

C

clintonG

Can somebody direct me to documents or source that supports the use of
collapsible content that is collapsed by default when the page is loaded?
The secondary objective would of course be cross-browser support.for IE
(5-6) and browsers derived from Mozilla (varies). Thank you...

<%= Clinton Gallagher
 
R

RobG

clintonG said:
Can somebody direct me to documents or source that supports the use of
collapsible content that is collapsed by default when the page is loaded?
The secondary objective would of course be cross-browser support.for IE
(5-6) and browsers derived from Mozilla (varies). Thank you...

Doing what you ask is fairly easy, however to do it properly
will requires a bit of thought.

Making content "collapsed by default" can be achieved two ways -
the simple way is to make the display property of the collapsed
bits 'none', then use JavaScript to set it to '', but this
approach is flawed.

If content is to be revealed by JS, then a better idea is to
have content visible by default, then hide it with JavaScript
when the page loads. That way, if the user's JavaScript is
disabled or their browser doesn't support it, they can still use
your page.

You can make the initial hide function run onload, however if
there is a fair bit of content to load in your page before
the onload runs, the user will see the divs displayed, then
hidden. So put it just after the divs to collapse.

Sample below.

<html><head><title>play</title>
</head><body>
<style type="text/css">
.outer {border: 1px solid blue; background-color: #7777dd;
color: #000066; padding: 5px;}
.inner {border: 1px solid blue; background-color: #eeeeff;
color: #333366;}
</style>
<script type="text/javascript">
function toggleDisplay(x) {
if (x.style) {
if (x.style.display == '') {
x.style.display='none'
} else {
x.style.display='';
}
}
}
</script>
</head><body>

<div class="outer"><span onclick="
toggleDisplay(this.nextSibling);">Click to display/hide
content</span><div class="inner">Here is the content
Here is the content Here is the content Here is the content
Here is the content Here is the content Here is the content
Here is the content Here is the content Here is the content
Here is the content Here is the content Here is the content
Here is the content Here is the content Here is the content
Here is the content Here is the content Here is the content
</div></div>

<script type="text/javascript">
if (document.getElementsByTagName){
var divs = document.getElementsByTagName('div');
} else if (document.all) {
var divs = document.all.tags('DIV');
}
for (var i=0, len=divs.length; i<len; i++){
if (divs.style && divs.className == 'inner') {
divs.style.display = 'none';
}
}
</script>
</body></html>
 
C

clintonG

RobG said:
clintonG said:
Can somebody direct me to documents or source that supports the use of
collapsible content that is collapsed by default when the page is loaded?
The secondary objective would of course be cross-browser support.for IE
(5-6) and browsers derived from Mozilla (varies). Thank you...

Doing what you ask is fairly easy, however to do it properly
will requires a bit of thought.

Making content "collapsed by default" can be achieved two ways -
the simple way is to make the display property of the collapsed
bits 'none', then use JavaScript to set it to '', but this
approach is flawed.

If content is to be revealed by JS, then a better idea is to
have content visible by default, then hide it with JavaScript
when the page loads. That way, if the user's JavaScript is
disabled or their browser doesn't support it, they can still use
your page.

You can make the initial hide function run onload, however if
there is a fair bit of content to load in your page before
the onload runs, the user will see the divs displayed, then
hidden. So put it just after the divs to collapse.

Sample below.

<html><head><title>play</title> /* REDUNDANT ELEMENTS */
</head><body> /* REDUNDANT ELEMENTS */
<style type="text/css">
.outer {border: 1px solid blue; background-color: #7777dd;
color: #000066; padding: 5px;}
.inner {border: 1px solid blue; background-color: #eeeeff;
color: #333366;}
</style>
<script type="text/javascript">
function toggleDisplay(x) {
if (x.style) {
if (x.style.display == '') {
x.style.display='none'
} else {
x.style.display='';
}
}
}
</script>
</head><body>

<div class="outer"><span onclick="
toggleDisplay(this.nextSibling);">Click to display/hide
content</span><div class="inner">Here is the content
Here is the content Here is the content Here is the content
Here is the content Here is the content Here is the content
Here is the content Here is the content Here is the content
Here is the content Here is the content Here is the content
Here is the content Here is the content Here is the content
Here is the content Here is the content Here is the content
</div></div>

<script type="text/javascript">
if (document.getElementsByTagName){
var divs = document.getElementsByTagName('div');
} else if (document.all) {
var divs = document.all.tags('DIV');
}
for (var i=0, len=divs.length; i<len; i++){
if (divs.style && divs.className == 'inner') {
divs.style.display = 'none';
}
}
</script>
</body></html>


Thank you Rob.

Note the code as shown includes redundant </head> and <body> tags
which I delineate as shown above.

The code does not function in FF or NS (Mozilla browsers) but it is very
impressive when used with IE and nearly exactly what I want (especially
the nice touch with the .outer and .inner classes so thank you again.

I am going to spend some time with it to determine what methods may
need to be modified to enable the script to function with Mozilla DNA
(FF/NS browsers) which has been a real pain so far.

I also need to use an iFrame within the div the inner class which will load
a server-side page (aspx) to run wizards for account logins and such and
then will need to determine how to collapse this.nextSibling once the
server-side .aspx process has completed. Comments appreciated.

I also just recalled reading that the use of the 'this' keyword is what may
be problematic with Mozilla's event handlers. I'll try to verify that later
this
evening and hope to return with results.

<%= Clinton Gallagher
 
R

RobG

clintonG wrote:
[...]
Thank you Rob.

Note the code as shown includes redundant </head> and <body> tags
which I delineate as shown above.

Err... copy/paste error. I
The code does not function in FF or NS (Mozilla browsers) but it is very

It should, I develop using Firefox and then test in IE. Even
with the errant head and body tags, it works for me in all
browsers I have.
impressive when used with IE and nearly exactly what I want (especially
the nice touch with the .outer and .inner classes so thank you again.

I am going to spend some time with it to determine what methods may
need to be modified to enable the script to function with Mozilla DNA
(FF/NS browsers) which has been a real pain so far.

If you use MS documentation and IE for development, that will be
the case. Use Firefox/Mozilla/etc. and w3c specs and you'll
have fewer issues, though you need a few tricks here and there
to support older IE browsers and maybe Netscape 4 & 6.
I also need to use an iFrame within the div the inner class which will load
a server-side page (aspx) to run wizards for account logins and such and
then will need to determine how to collapse this.nextSibling once the
server-side .aspx process has completed. Comments appreciated.

I used nextSibling as a convenience, rather than a
getElementById or Tag method. You need to design the structure
of your HTML to fit your model for creating dynamic content on
the page.

The idea is to create a link between the element that will be
clicked on with the one that will be collapsed. This can be
done with IDs or the relationship of the elements (e.g.
nextSibling).

Using ID requires some parsing either at the server or on the
client to ensure the link points at the right element and all
IDs remain unique in the page. e.g. your headings could all have
enumerated ids: id="header-01" ..."header-02", etc. and the
content to collapse: id="content-01" ..."content-02" etc.

When the header is clicked on, if it's id="header-01" then
collapse/expand element with id="content-01" (see sample below)

Using element relationships restricts page layout options -
change the layout and your relationship model may break. But
it's not dependent on the generation of unique IDs, so you can
just plonk the content on the page.
I also just recalled reading that the use of the 'this' keyword is what may
be problematic with Mozilla's event handlers. I'll try to verify that later
this
evening and hope to return with results.

As far as I know, 'this' works fine in Mozilla. The event
models in IE and the 'zillas are quite different, but that
should not cause you any issues in this case.

You can avoid using 'this' completely if you like and just pass
"event" - see toggleDisplay0() below. If you want to get really
fancy, you can add toggleDisplay() to all spans with
id="header-" using JS when the page loads to save some coding -
keeps the HTML clean.


<html><head><title>play</title>
<style type="text/css">
.outer {border: 1px solid blue; background-color: #7777dd;
color: #000066; padding: 5px;}
.inner {border: 1px solid blue; background-color: #eeeeff;
color: #333366; padding: 5px;}
</style>
<script type="text/javascript">

// Expects the element reference to be passed to it
function toggleDisplay(i) {
var cont = i.id.split('-')[1];
var x = document.getElementById('content-' + cont);
if (x.style) {
if (x.style.display == '') {
x.style.display='none'
} else {
x.style.display='';
}
}
}

// Uses the event to find the element clicked on
function toggleDisplay0(e) {

e = e || window.event;
var y = e.target || e.srcElement;
var n = y.id.split('-')[1];

if (document.getElementById) {
var x = document.getElementById('content-' + n);
} else if (document.al) {
var x = document.all('content-' + n);
}

if (x.style) {
if (x.style.display == '') {
x.style.display='none'
} else {
x.style.display='';
}
}
}
</script>
</head><body>

<div class="outer"><span id="header-01" onclick="
toggleDisplay(this);">Click to display/hide
content 1</span><div class="inner" id="content-01">
Here is the content 1 Here is the content 1
Here is the content 1 Here is the content 1
Here is the content 1 Here is the content 1
Here is the content 1 Here is the content 1
Here is the content 1 Here is the content 1
</div></div>

<div class="outer"><span id="header-02" onclick="
toggleDisplay0(event);">Click to display/hide
content 2</span><div class="inner" id="content-02">
Here is the content 2 Here is the content 2
Here is the content 2 Here is the content 2
Here is the content 2 Here is the content 2
Here is the content 2 Here is the content 2
Here is the content 2 Here is the content 2
</div></div>

<script type="text/javascript">
if (document.getElementsByTagName){
var divs = document.getElementsByTagName('div');
} else if (document.all) {
var divs = document.all.tags('DIV');
}
for (var i=0, len=divs.length; i<len; i++){
if (divs.style && divs.className == 'inner') {
divs.style.display = 'none';
}
}
</script>
</body></html>
 
C

clintonG

RobG said:
clintonG wrote:
[...]
Thank you Rob.

Note the code as shown includes redundant </head> and <body> tags
which I delineate as shown above.

Err... copy/paste error. I
The code does not function in FF or NS (Mozilla browsers) but it is very

It should, I develop using Firefox and then test in IE. Even
with the errant head and body tags, it works for me in all
browsers I have.
impressive when used with IE and nearly exactly what I want (especially
the nice touch with the .outer and .inner classes so thank you again.

I am going to spend some time with it to determine what methods may
need to be modified to enable the script to function with Mozilla DNA
(FF/NS browsers) which has been a real pain so far.

If you use MS documentation and IE for development, that will be
the case. Use Firefox/Mozilla/etc. and w3c specs and you'll
have fewer issues, though you need a few tricks here and there
to support older IE browsers and maybe Netscape 4 & 6.
I also need to use an iFrame within the div the inner class which will load
a server-side page (aspx) to run wizards for account logins and such and
then will need to determine how to collapse this.nextSibling once the
server-side .aspx process has completed. Comments appreciated.

I used nextSibling as a convenience, rather than a
getElementById or Tag method. You need to design the structure
of your HTML to fit your model for creating dynamic content on
the page.

The idea is to create a link between the element that will be
clicked on with the one that will be collapsed. This can be
done with IDs or the relationship of the elements (e.g.
nextSibling).

Using ID requires some parsing either at the server or on the
client to ensure the link points at the right element and all
IDs remain unique in the page. e.g. your headings could all have
enumerated ids: id="header-01" ..."header-02", etc. and the
content to collapse: id="content-01" ..."content-02" etc.

When the header is clicked on, if it's id="header-01" then
collapse/expand element with id="content-01" (see sample below)

Using element relationships restricts page layout options -
change the layout and your relationship model may break. But
it's not dependent on the generation of unique IDs, so you can
just plonk the content on the page.
I also just recalled reading that the use of the 'this' keyword is what may
be problematic with Mozilla's event handlers. I'll try to verify that later
this
evening and hope to return with results.

As far as I know, 'this' works fine in Mozilla. The event
models in IE and the 'zillas are quite different, but that
should not cause you any issues in this case.

You can avoid using 'this' completely if you like and just pass
"event" - see toggleDisplay0() below. If you want to get really
fancy, you can add toggleDisplay() to all spans with
id="header-" using JS when the page loads to save some coding -
keeps the HTML clean.


<html><head><title>play</title>
<style type="text/css">
.outer {border: 1px solid blue; background-color: #7777dd;
color: #000066; padding: 5px;}
.inner {border: 1px solid blue; background-color: #eeeeff;
color: #333366; padding: 5px;}
</style>
<script type="text/javascript">

// Expects the element reference to be passed to it
function toggleDisplay(i) {
var cont = i.id.split('-')[1];
var x = document.getElementById('content-' + cont);
if (x.style) {
if (x.style.display == '') {
x.style.display='none'
} else {
x.style.display='';
}
}
}

// Uses the event to find the element clicked on
function toggleDisplay0(e) {

e = e || window.event;
var y = e.target || e.srcElement;
var n = y.id.split('-')[1];

if (document.getElementById) {
var x = document.getElementById('content-' + n);
} else if (document.al) {
var x = document.all('content-' + n);
}

if (x.style) {
if (x.style.display == '') {
x.style.display='none'
} else {
x.style.display='';
}
}
}
</script>
</head><body>

<div class="outer"><span id="header-01" onclick="
toggleDisplay(this);">Click to display/hide
content 1</span><div class="inner" id="content-01">
Here is the content 1 Here is the content 1
Here is the content 1 Here is the content 1
Here is the content 1 Here is the content 1
Here is the content 1 Here is the content 1
Here is the content 1 Here is the content 1
</div></div>

<div class="outer"><span id="header-02" onclick="
toggleDisplay0(event);">Click to display/hide
content 2</span><div class="inner" id="content-02">
Here is the content 2 Here is the content 2
Here is the content 2 Here is the content 2
Here is the content 2 Here is the content 2
Here is the content 2 Here is the content 2
Here is the content 2 Here is the content 2
</div></div>

<script type="text/javascript">
if (document.getElementsByTagName){
var divs = document.getElementsByTagName('div');
} else if (document.all) {
var divs = document.all.tags('DIV');
}
for (var i=0, len=divs.length; i<len; i++){
if (divs.style && divs.className == 'inner') {
divs.style.display = 'none';
}
}
</script>
</body></html>


Your 2nd build does in fact function in IE and FF Rob. Thank you. It is also
very helpful in the sense that I will be using similar header-01, header-02
ids because the split will give me a value I can reuse to declare a src
property for the file I want to load in the iFrame.

FF oddity:
<!-- will not display the hand onMouseOver but will with IE -->
<span id="header-02" onclick="toggleDisplay0(event);"
style="cursor:hand;">Click to display/hide content 2</span>

IE and FF oddity:
<!-- Attempting to replace span with semantic markup results in FF error:
event is not defined -->
<a id="header-02" href="javascript:toggleDisplay0(event);">Click to
display/hide content 2</a>

Your advice to use FF and W3 DOM for development is noted and and is in
progress.

<%= Clinton
 
R

RobG

clintonG wrote:
[...]
Your 2nd build does in fact function in IE and FF Rob. Thank you. It is also
very helpful in the sense that I will be using similar header-01, header-02
ids because the split will give me a value I can reuse to declare a src
property for the file I want to load in the iFrame.

FF oddity:
<!-- will not display the hand onMouseOver but will with IE -->
<span id="header-02" onclick="toggleDisplay0(event);"
style="cursor:hand;">Click to display/hide content 2</span>

Maybe an HTML or CSS group can answer that.
IE and FF oddity:
<!-- Attempting to replace span with semantic markup results in FF error:
event is not defined -->
<a id="header-02" href="javascript:toggleDisplay0(event);">Click to
display/hide content 2</a>

This is considered an abuse of <a href...>. The onclick event
can be added to (almost) any element, so there is no need to
subvert an <a> tag. The "correct" way to achieve events when
clicking on an <a> is:

<a href="usefulLink.html"
onclick="doSomething(); return false;" ... >

That way if JS is disabled, the user goes somewhere useful. If
JS is enabled, the onclick runs and "return false" stops the
link being followed. If there really is no link, href="#" works
OK but it causes most browsers to scroll to the top of the page
if the event isn't canceled (i.e. if JS disabled or you don't
return false).

Considering the purpose is to open/close content, better to add
visual cues such as a "+" to the header when closed and "-" when
open to indicate that clicking on the text will display more
content. Maybe add a title attribute such as
"Click to expand..."

<a href="usefulLink.html"
onclick="doSomething(); return false;"
title="Click to expand..."> ... </a>
 
R

RobB

RobG said:
clintonG wrote:
[...]
Your 2nd build does in fact function in IE and FF Rob. Thank you. It is also
very helpful in the sense that I will be using similar header-01, header-02
ids because the split will give me a value I can reuse to declare a src
property for the file I want to load in the iFrame.

FF oddity:
<!-- will not display the hand onMouseOver but will with IE -->
<span id="header-02" onclick="toggleDisplay0(event);"
style="cursor:hand;">Click to display/hide content 2</span>

Maybe an HTML or CSS group can answer that.

.....style="cursor:pointer;"> (IE, not FF, oddity).
This is considered an abuse of <a href...>. The onclick event
can be added to (almost) any element, so there is no need to
subvert an <a> tag. The "correct" way to achieve events when
clicking on an <a> is:

<a href="usefulLink.html"
onclick="doSomething(); return false;" ... >

That way if JS is disabled, the user goes somewhere useful. If
JS is enabled, the onclick runs and "return false" stops the
link being followed. If there really is no link, href="#" works
OK but it causes most browsers to scroll to the top of the page
if the event isn't canceled (i.e. if JS disabled or you don't
return false).

(snip)

As well, you can't pick up the (moz) Event object that way, as it's
passed into the HTML event handler - in this case, Link.onclick - as
the local variable 'event'. That javascript: url will execute with
global scope, leaving 'event' undefined, as you observed.
 
M

Martin Honnen

clintonG wrote:

FF oddity:
<!-- will not display the hand onMouseOver but will with IE -->
<span id="header-02" onclick="toggleDisplay0(event);"
style="cursor:hand;">Click to display/hide content 2</span>

Well your CSS knowledge is the oddity, the value you probably want as
defined in CSS 2 is pointer, see
<http://www.w3.org/TR/CSS2/ui.html#cursor-props>
so
cursor: pointer;
will do in browsers like Mozilla, Firefox or Opera implementing W3C
standards. It also works in IE 6 but not earlier versions of IE on Win
at least, there you would need what you have (hand).
So use
cursor: pointer;
or check the archives of this group or CSS groups, in the right sequence
(either cursor: pointer; cursor: hand; or cursor: hand; cursor:
pointer;) you can make both IE 5/5.5 and the other browsers happy.
IE and FF oddity:
<!-- Attempting to replace span with semantic markup results in FF error:
event is not defined -->
<a id="header-02" href="javascript:toggleDisplay0(event);">Click to
display/hide content 2</a>

Event handlers are onclick, onmousedown etc, if you put script in the
href attribute in the form of a javascript: URL then there is no event
object. You likely want
<a href="#"
onclick="toggleDislay0(event); return false;">
 
C

clintonG

Martin Honnen said:
clintonG wrote:



Well your CSS knowledge is the oddity, the value you probably want as
defined in CSS 2 is pointer, see
<http://www.w3.org/TR/CSS2/ui.html#cursor-props>
so
cursor: pointer;
will do in browsers like Mozilla, Firefox or Opera implementing W3C
standards. It also works in IE 6 but not earlier versions of IE on Win
at least, there you would need what you have (hand).
So use
cursor: pointer;
or check the archives of this group or CSS groups, in the right sequence
(either cursor: pointer; cursor: hand; or cursor: hand; cursor:
pointer;) you can make both IE 5/5.5 and the other browsers happy.


Event handlers are onclick, onmousedown etc, if you put script in the
href attribute in the form of a javascript: URL then there is no event
object. You likely want
<a href="#"
onclick="toggleDislay0(event); return false;">

Thank you for bringing the updated CSS pointer attribute value to my
attention.

<%= Clinton Gallagher
 
C

clintonG

This is considered an abuse of <a href...>. The onclick event
can be added to (almost) any element, so there is no need to
subvert an <a> tag. The "correct" way to achieve events when
clicking on an <a> is:

<a href="usefulLink.html"
onclick="doSomething(); return false;" ... >

That way if JS is disabled, the user goes somewhere useful. If
JS is enabled, the onclick runs and "return false" stops the
link being followed. If there really is no link, href="#" works
OK but it causes most browsers to scroll to the top of the page
if the event isn't canceled (i.e. if JS disabled or you don't
return false).

Considering the purpose is to open/close content, better to add
visual cues such as a "+" to the header when closed and "-" when
open to indicate that clicking on the text will display more
content. Maybe add a title attribute such as
"Click to expand..."

<a href="usefulLink.html"
onclick="doSomething(); return false;"
title="Click to expand..."> ... </a>

Ah. I actually learned the proper way to call a scripted function from
within an anchored element some time ago but forgot and got sloppy. You're
right, it is the best solution and calling toggleDisplay0(event) as follows
now functions as desired.

<a id="header-02" href="BrowserRequirements.aspx"
onClick="toggleDisplay0(event); return false;">

RobB brings up the point regarding the Mozilla event handling model. I found
the forum discussion which discussed issues related to the use of the 'this'
keyword with interesting statements regarding the Mozilla event handling
model.

That discussion topic was about naming conventions [1] but as it so often
happens the discussion moved OT when 'georgias' broaches the subject of the
use of the keyword with immediate conjecture from 'asqueella' and a cogent
response from 'Mook' who speaks to the fundamental issue of the keyword in
the context RobB reminds us is fundamental.

<Mook>
* If called as object.function( ) then this is the object
* If called on an event handler, this is the element that triggered the
event
* If called via a reference to the function (in my case, passed it to
XPCOM), this is the function itself

All of this, of course, is evaluated when the function is executed, so if
you call it differently then the same variable in the function resolves to
different kinds of things...
</Mook>

BTW - MikeFoster (cross-browser.com) has implemented a demo [2] which models
the functionality we are all discussing.

Obviously there are many champions that advocate the use of DHTML to achieve
a rich user interface and I am grateful to all.

<%= Clinton Gallagher

[1] http://forums.mozillazine.org/viewtopic.php?t=129485
[2] http://cross-browser.com/toys/toolbars.html
 
C

clintonG

As well, you can't pick up the (moz) Event object that way, as it's
passed into the HTML event handler - in this case, Link.onclick - as
the local variable 'event'. That javascript: url will execute with
global scope, leaving 'event' undefined, as you observed.

Thank you for bringing this to the attention of this discussion Rob.
My reply to RobG includes discussion and references you may want
to respond to.

<%= Clinton Gallagher
 

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

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top