#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2007
    Location
    NC, USA
    Posts
    15
    Rep Power
    0

    Expand/Collapse content, How to


    I'm making a few pages for my first real web page & it's going to have some poetry on it. Now, some poems are very short, like haiku, for example.

    What I'm looking for is a way to put several poems on a page with some sort of a contents, or perhaps list. The title of each poem, when clicked upon, would expand downward showing the actual poem.

    A good example of this is I'm sure you may have seen a "FAQs" section of a website, a list of questions. You click the question, it shows the answer beneath it, pushing the other questions down. Click it again, it hides the answer.

    I need it to validate XHTML 1.0 Strict, etc. & I have no server side scripting available, so. I am still a fair beginner to XHTML & CSS, so.

    Any ideas how one can go about accomplishing this? Is it possible with just XHTML & CSS?

    I'm really concerned about accessibility & validation, perhaps one could use a Listbox at the top of the DIV or something. If anyone has other ideas of how to display a lot of small content like this on a single page, I'm open to other ideas, too!
  2. #2
  3. CSS & JS/DOM Adept
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jul 2004
    Location
    USA (verifiably)
    Posts
    20,124
    Rep Power
    4309
    You would need unobtrusive JavaScript to do this. (In this case unobtrusive means that the content would only be hidden when JavaScript was available to make it visible.)

    This is close to what you want. Finding quality tutorials is difficult.

    After you read that, feel free to post your questions here.

    * Moved to the JavaScript Forum *

    P.S. Thanks for using a descriptive title.
    Spreading knowledge, one newbie at a time.

    Learn CSS. | PHP includes | HTML Validator | CSS validator

    Remember people spend most of their time on other people's sites (so don't violate web design conventions).
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2007
    Location
    NC, USA
    Posts
    15
    Rep Power
    0
    Yeah, thanks for the link gonna check it out. I tried googling for what I was looking for, but just as you said: finding something of quality, with at least some commentary, was difficult. Beyond that, nothing mentioned if it was cross-browser compatible.

    So, there's not really a possible way using the "display:hidden;" I guess...it probably wouldn't work the way I would want now that I think about it. It wouldn't "bounce back," I think.

    Unobtrusive javascript sounds good. I just hope it will work with IE6 & still validate.

    I worked out a test page, putting lists & anchors to practice. Hopefully I can make the page a little more interesting using some Javascript, then.

    Thank you for your help!
  6. #4
  7. garish grotesque gargoyle
    Devshed Beginner (1000 - 1499 posts)

    Join Date
    Mar 2006
    Location
    gracing gargantuan gothic gateways
    Posts
    1,323
    Rep Power
    0

    a quick, clean solution


    hi davosyn - I probably should have looked at kravvitz' link first, but this is something I've done several times and this is how I've done it:

    assume your content looks something like this:

    HTML Code:
    <div class="poem">
        <h4>The Poem Title</h4>
        <p>There once was a man from Nantucket...</p>
    </div>


    and so on for several poems on the page. of course you can replace the actual HTML tags with tags of your liking, and the concept should remain the same. Note that the title is not currently a link, and if loaded without JS the page should just contain a bunch of poems one after the other.

    now the unobtrusive JS - in a separate JS file create this function, and set it to run onload:

    Javascript Code:
    function hidePoems() {
      // grab your poem containers
      var poems = document.getElementsByTagName('div');
      for(var i=0;i<poems.length;i++) {
        if(poems[i].className.indexOf('poem') != -1) {
          // guess it actually is a poem, let's do some work...
          var title = poems[i].getElementsByTagName('h4')[0];
          var text = poems[i].getElementsByTagName('p')[0];
          text.style.display = 'none';
          var link = document.createElement('a');
          link.showText = text; // no id's or closures req'd!
          link.href='#';
          link.onclick = function() {
            // boy this logic should be familiar
            if(this.showText.style.display == 'none') {
              this.showText.style.display = 'block';
            } else {
              this.showText.style.display = 'none';
            }
            return false; // link shouldn't actually do anything
          }
          // great, but how do we attach it to the poem?
          link.appendChild(title);
          poems[i].insertBefore(link,text);
        }
      }
    }
    onload = hidePoems;


    basically you write a function that isolates the desired elements (in this case, 'div's with class 'poem', but could be 'li' or any other tag) and then use js to isolate the title and text portions (in this case 'h4' and 'p' -- but could just as easily be 'div' or 'span' or anything else; should be clear what I'm doing).

    once you have them, force display of the text off.

    Then create a link and give the link the text ele as a property (assigning a dom element as a property of another dom element? sure, why not?).

    Then replace the existing title with your link, including the link text as the old title. (I did this by appending the title as a child of the link, and inserting the link before the text in the poem div, but that cat can have its skin removed several ways -- feel free to figure out another solution!).

    Hope this is clear enough and helps you with what you wanted, and may represent another way of doing things than the other article. Plus, it gave me a chance to overuse parenthesis (which I love to do).

    HTH - derelict

    Comments on this post

    • Joseph Taylor agrees : Overuse parenthesis? Sounds suspiciously Lisp-user-ish to me.
  8. #5
  9. CSS & JS/DOM Adept
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jul 2004
    Location
    USA (verifiably)
    Posts
    20,124
    Rep Power
    4309
    Derelict, two things:

    1) It's best to avoid using display:none, so that screen readers won't ignore the content. The common alternative, called "offleft positioning", is to use position:absolute and left:-9999px.

    2) Headers, including <h4>s, may not be a child of an inline element, e.g <a> and <span>.

    Originally Posted by Davosyn
    Unobtrusive javascript sounds good. I just hope it will work with IE6 & still validate.
    You can do a lot of unobtrusive JavaScript in IE4 if you really want to and don't mind adding extra IE specific stuff to your code. When writing scripts with JavaScript/DOM supporting IE6 isn't a problem if you support IE7. IE5.x requires a little more work though.

    Unobtrusive JavaScript shouldn't cause any X/HTML validation issues.

    Comments on this post

    • execute agrees
    • derelict disagrees : man kravvitz - I'm a disagreeing fool today - notice my h4's were in a DIV, not an inline ele -- the offleft might be an interesting solution too, only a slight change -- an .offleft class might do the trick
    Spreading knowledge, one newbie at a time.

    Learn CSS. | PHP includes | HTML Validator | CSS validator

    Remember people spend most of their time on other people's sites (so don't violate web design conventions).
  10. #6
  11. c0der
    Devshed Novice (500 - 999 posts)

    Join Date
    Jun 2005
    Location
    Vancouver
    Posts
    664
    Rep Power
    159
    P.S. Thanks for using a descriptive title.
    Descriptive, yes, but it probably could have benefited from a question mark. Here I was thinking the OP was going to tell me how to expand/collapse content.

    P.S. Not really.
  12. #7
  13. c0der
    Devshed Novice (500 - 999 posts)

    Join Date
    Jun 2005
    Location
    Vancouver
    Posts
    664
    Rep Power
    159
    Originally Posted by derelict
    Code:
    if(poems[i].className.indexOf('poem') != -1)
    Hmm... So <div class="poem-container"></div> is actually a poem? How meta! How about <div class="totally-not-a-poem">Blarg bloog barm. Flabber flop.</div>? Granted, it's a fine example of alliteration... But poetic?

    Maybe this calls for a regular expression?

    Comments on this post

    • Kravvitz agrees
    • derelict agrees : helluva link
    Last edited by Joseph Taylor; January 30th, 2008 at 07:13 PM.
  14. #8
  15. garish grotesque gargoyle
    Devshed Beginner (1000 - 1499 posts)

    Join Date
    Mar 2006
    Location
    gracing gargantuan gothic gateways
    Posts
    1,323
    Rep Power
    0
    I see now -- I forgot I wrapped the h4 in a link

    so kravvitz - sorry, I apologize for that, you're right (as usual).

    I actually wouldn't recommend using header tags for that at all, unless you were already using h1-h3 for up-tree page headings; a classed span would probably be better. Also, it's fairly trivial to simply append the contents of the header to the link and then append the link to the header instead.

    to implement the offleft for screen readers, simply replace the style.display = 'none' with a className += ' offleft' and the style.display = 'block' with a className.replace(/ offleft/,'') and make an offleft class that's position:absolute; and left:-9999px or whatever.

    with the modifications, still an easy way to do unobtrusive JS -- my point really being that the initial HTML layout is practically irrelevant, as long as you have a way of isolating the elements to be changed. so really, you can take a finished page and concoct a script to add the desired functionality without having to design the page with the JS functionality in mind.

    HTH and sorry if I'm rubbing anyone the wrong way - just calling 'em as I see 'em.

    derelict

IMN logo majestic logo threadwatch logo seochat tools logo