Adding onkeydown to onclick

I am using a JS accordion script to hide/show content on an FAQs page.

The original script used this code to toggle the content:

 // Assign onclick events to the accordion item headings
      for ( var i = 0; i < accordionItems.length; i++ ) {
        var h3 = getFirstChildWithTagName( accordionItems[i], 'H3' );
        h3.onclick = toggleItem;
      }

I wanted to make it keyboard-accessible, so I’ve added tabindex=“0” to the h3s to give focus, and the following code:

// Assign onkeypress events to the accordion item headings
      for ( var i = 0; i < accordionItems.length; i++ ) {
        var h3 = getFirstChildWithTagName( accordionItems[i], 'H3' );
        h3.onkeypress = toggleItem;
      }

That works fine, but I just wondered if that’s the best way to do it, or if there’s a way to combine onclick and onkeypress. I’ve Googled it, but with very little success.

This works (in newer browser versions because of the autofocus):


<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Demo</title>
</head>
<body>

    <form name="theForm">
        <input type="text" name="textField" autofocus>
    </form>

    <script>
        var textField = theForm.textField;
        textField.onclick = textField.onkeydown = function() {
            alert('Yep!');
            }
    </script>

</body>
</html>

So I would think it should work in your case, too?

I don’t have an input area, so (as far as I can see) autofocus is irrelevant, but

h3.onclick = h3.onkeypress = toggleItem

is what I was after and it works, thank you. :slight_smile:

I saw that, but I couldn’t get h3+onkeydown to work. And I still wanted to show you the principle of a = b = value. Glad it solved your problem.

It does if you add tabindex to give focus. :slight_smile: http://snook.ca/archives/accessibility_and_usability/elements_focusable_with_tabindex

Nice. Something to keep in mind. But I’m just wondering: how do your users know that they have to press a(n additional) key to hide/show the content? Shouldn’t it be so that when an h3 gets focus by means of the Tab key, its content is already shown and the other content is hidden?

If you navigate any site by keyboard, that’s how links function - you tab to the link to give it focus and then activate it by pressing “Enter”, so keyboarders will be familiar with that.

The only problem, if you can call it that, with the script as I have it, is that tabbing to the next question acts as “onkeypress” and opens the section you’re leaving. I’m sure there’s a way around this, but my JS skills are not up to finding it. And given that many sites with similar set-ups are not navigable by keyboard at all, it seems a pretty minor fault to me. (I spent some considerable time Googling for a keyboard-accessible accordion and couldn’t find one, hence I had to tweak this one.) It also displays everything if JS is off, rather than hides everything, which is another important consideration for me.

This is the full thing, if you have any suggestions for improvement.


<body onload="init()">

<div id="page">
		
<h2>Page Heading</h2>
	
	<div class="accordionItem">
		<h3 tabindex="0">First Question</h3>
	<div>
<p>
	Lorem ipsum dolor sit amet, consecteteur. Netus semper ve ante elit hymenaeos. Vitae dapibus, ultricies eu ullamcorper ut, cursus cum. Tortor vitae hendrerit rhoncus purus odio. Sapien. Vitae. Cras elit neque eros sem odio luctus fringilla nonummy. Taciti, luctus, urna sit. Dui sem consectetuer ut, lacus in erat, class.
</p>
	</div>
	</div>
	
	<div class="accordionItem">			
		<h3 tabindex="0">Second Question</h3>
	<div>
<p>
	Lorem ipsum dolor sit. Varius praesent ullamcorper interdum, cras mi nulla dui maecenas habitasse ut, penatibus. Vehicula placerat libero nunc ut cras. Suspendisse laoreet morbi duis platea, sapien, bibendum pede. Hac eu elit fusce, urna rutrum, dictum orci. Felis penatibus sit, malesuada lacus ac luctus aliquam egestas odio. Cras. Ultrices aliquam posuere odio feugiat vivamus. Mollis, hendrerit adipiscing nibh. Hymenaeos. Eros senectus etiam diam facilisi vestibulum gravida cum ante nibh.
</p>
	</div>
	</div>
	
	<div class="accordionItem">
		<h3 tabindex="0">Third Question</h3>
	<div>			
<p>
	Lorem ipsum dolor sit amet, consecteteur adipiscing elit elit. Porta at fames aenean. Sapien libero. Mauris hymenaeos ut, at ad risus nam platea.
</p>
	</div>
	</div>
				
	<div class="accordionItem">
		<h3 tabindex="0">Fourth Question</h3>
	<div>			
<p>
	Lorem ipsum dolor sit amet, consecteteur adipiscing elit. Mauris euismod semper nisi urna lacinia eu, auctor at, interdum nec, natoque a, mattis fames magna turpis rutrum. Consectetuer cubilia vitae. Velit lectus consectetuer fermentum aenean neque adipiscing odio morbi tristique blandit. Sit. Purus. Semper pede, viverra laoreet diam ultrices nunc. Facilisis ante duis quisque in, convallis nisi. Potenti nibh lobortis odio, sit. Turpis. Mi. Libero, id lectus fringilla faucibus aenean. Cursus amet, arcu erat. Purus facilisis aliquet ante maecenas curabitur. Suspendisse arcu, odio, luctus aliquam. Nisi rhoncus et.
</p>
<p>
	Pulvinar auctor curae condimentum pede. Nunc parturient curabitur morbi at consectetuer eget egestas. Sollicitudin integer, donec diam lorem, elementum dis. Duis odio. Porta potenti elit diam posuere convallis leo. Vel justo sociis diam gravida sit, vestibulum tortor, torquent aliquet fusce class. Elit non molestie. Et. Erat sollicitudin adipiscing cras. Sociis. Vel, eros. Ullamcorper. Diam, eu velit vitae duis feugiat.
</p>
	</div>
	</div>
	
	<div class="accordionItem">
		<h3 tabindex="0">Fifth Question</h3>
	<div>			
<p>Lorem ipsum dolor sit amet, consecteteur adipiscing elit vehicula. A. Lacus proin ornare vulputate rhoncus. Ac nunc nunc natoque et, sem at lobortis fusce duis potenti eu, tempor. Pretium, donec neque felis, accumsan. Ante placerat augue. Tellus. Euismod dui, in fringilla eget.</p>
	</div>
	</div>
					
	<div class="accordionItem">
		<h3 tabindex="0">Sixth Question</h3>
	<div>			
<p>
	Lorem ipsum dolor sit amet, consecteteur adipiscing elit. Integer, iaculis ultricies habitant auctor lectus fusce posuere ut. Dolor netus, interdum dignissim. Tellus neque scelerisque eu lectus. Arcu semper id dictum massa parturient suspendisse tortor ut class neque morbi. Quis risus gravida metus amet arcu vivamus. Fringilla etiam nunc iaculis. Tempor. Consectetuer feugiat, augue nunc imperdiet. Odio. In, ac congue sit aenean, ad id curae lobortis felis id tristique. Consectetuer facilisis curae eu platea pharetra dui aliquam sagittis quisque taciti purus.
</p>
	</div>
	</div>			
</div>
<script type="text/javascript">
    //<![CDATA[

    var accordionItems = new Array();

    function init() {

      // Grab the accordion items from the page
      var divs = document.getElementsByTagName( 'div' );
      for ( var i = 0; i < divs.length; i++ ) {
        if ( divs[i].className == 'accordionItem' ) accordionItems.push( divs[i] );
      }

      // Assign onclick and onkeypress events to the accordion item headings
      for ( var i = 0; i < accordionItems.length; i++ ) {
        var h3 = getFirstChildWithTagName( accordionItems[i], 'H3' );
        h3.onclick = h3.onkeypress = toggleItem;
      }

      // Hide all accordion item bodies except the first
      for ( var i = 1; i < accordionItems.length; i++ ) {
        accordionItems[i].className = 'accordionItem hide';
      }
    }

    function toggleItem() {
      var itemClass = this.parentNode.className;

      // Hide all items
      for ( var i = 0; i < accordionItems.length; i++ ) {
        accordionItems[i].className = 'accordionItem hide';
      }

      // Show this item if it was previously hidden
      if ( itemClass == 'accordionItem hide' ) {
        this.parentNode.className = 'accordionItem';
      }
    }

    function getFirstChildWithTagName( element, tagName ) {
      for ( var i = 0; i < element.childNodes.length; i++ ) {
        if ( element.childNodes[i].nodeName == tagName ) return element.childNodes[i];
      }
    }

     //]]>
    </script>			
</body>

body, h1, h2, h3, dl, dt, dd, ul, li, p {margin: 0; padding: 0;}

body {color: #333333;
	font-family: "Trebuchet MS",Helvetica,sans-serif;
	font-size: 100%;
	line-height: 1.4;
	background-color: #EDEDED;
	}

#page {width: 100%;
	max-width: 58em;
   margin: auto;
   background-color: #fff;
   }

p {padding: 0.5em 0;}

.accordionItem h3 {margin: 0;
	font-size: 1.1em;
	padding: 0.4em;
	color: #fff;
	background-color: #88F;
	border-bottom: 1px solid #66d;
	}
	
.accordionItem h3:hover { cursor: pointer; }
.accordionItem h3:focus {outline: 2px solid #0000FF;}

.accordionItem div {margin: 0;
	padding: 1em 0.4em;
	background-color: #fff;
	border-bottom: 1px solid #66d;
	}

.accordionItem.hide h3 {color: #000;
	background-color: #eef; }
	
.accordionItem.hide div { display: none; }

The original: http://www.elated.com/articles/javascript-accordion/

Of course. (Clearly, it’s been a decade since I’ve tried that even as a user.)

I would have, among other things to catch the Enter key press rather than any key press. But I’m quite busy today, so that will have to wait until tomorrow or Tuesday. But I’ll get to you back on it. One question for now: what’s your doctype?

I struggle a bit with a mouse, so I keyboard as much as possible - and all too often, that’s not very much at all. :frowning:

Thank you - I’d appreciate that. :slight_smile:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

Given Frank is busy I have had a blast at this.

As of IE8 you can use document.querySelectorAll with CSS2 type selectors, so for instance you can target headings like so var headings = document.querySelectorAll(‘.accordionItem h3’). A bit easier.

I have removed the hide class. Instead by default the divs containing the paragraphs have been set in CSS to display: none. We then toggle a ‘show’ class instead. That way with javascript switched off all should be hidden.

The javascript:

(function() {

    var headings = document.querySelectorAll('.accordionItem h3'),
        len = headings.length, i;

        toggleItem = function() {

            var root = this.parentNode, /* div accordionItem parentNode */
                div = root.querySelector('div'),
                divToHide = document.querySelector('.accordionItem div.show');

            div.classList.toggle('show');

            if(divToHide) { divToHide.classList.remove('show'); }

        };

    for (i = 0; i < len; i += 1) {

        headings[i].onclick = headings[i].onkeypress = toggleItem;

    }
}());

The full script:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Type of Test</title>
<style>
body, h1, h2, h3, dl, dt, dd, ul, li, p {margin: 0; padding: 0;}

body {color: #333333;
    font-family: "Trebuchet MS",Helvetica,sans-serif;
    font-size: 100%;
    line-height: 1.4;
    background-color: #EDEDED;
    }

#page {width: 100%;
    max-width: 58em;
   margin: auto;
   background-color: #fff;
   }

p {padding: 0.5em 0;}

.accordionItem h3 {
    margin: 0;
    font-size: 1.1em;
    padding: 0.4em;
    color: #fff;
    background-color: #88F;
    border-bottom: 1px solid #66d;
    /* prevent h3 being highlighted */
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}

.accordionItem h3:hover { cursor: pointer; }
.accordionItem h3:focus { outline: 2px solid #0000FF; }

.accordionItem div {
    margin: 0;
    padding: 1em 0.4em;
    background-color: #fff;
    border-bottom: 1px solid #66d;
    display: none; /* Initial State */
}

.accordionItem div.show { display: block; }

</style>
</head>
<body>

<div id="page">

<h2>Page Heading</h2>

    <div class="accordionItem">
        <h3 tabindex="0">First Question</h3>
        <div>
            <p>
            Lorem ipsum dolor sit amet, consecteteur. Netus semper ve ante elit hymenaeos. Vitae dapibus, ultricies eu ullamcorper ut, cursus cum. Tortor vitae hendrerit rhoncus purus odio. Sapien. Vitae. Cras elit neque eros sem odio luctus fringilla nonummy. Taciti, luctus, urna sit. Dui sem consectetuer ut, lacus in erat, class.
            </p>
        </div>
    </div>

    <div class="accordionItem">
        <h3 tabindex="0">Second Question</h3>
        <div>
             <p>
             Lorem ipsum dolor sit. Varius praesent ullamcorper interdum, cras mi nulla dui maecenas habitasse ut, penatibus. Vehicula placerat libero nunc ut cras. Suspendisse laoreet morbi duis platea, sapien, bibendum pede. Hac eu elit fusce, urna rutrum, dictum orci. Felis penatibus sit, malesuada lacus ac luctus aliquam egestas odio. Cras. Ultrices aliquam posuere odio feugiat vivamus. Mollis, hendrerit adipiscing nibh. Hymenaeos. Eros senectus etiam diam facilisi vestibulum gravida cum ante nibh.
             </p>
        </div>
    </div>

    <div class="accordionItem">
        <h3 tabindex="0">Third Question</h3>
        <div>
            <p>
            Lorem ipsum dolor sit amet, consecteteur adipiscing elit elit. Porta at fames aenean. Sapien libero. Mauris hymenaeos ut, at ad risus nam platea.
            </p>
        </div>
    </div>

    <div class="accordionItem">
        <h3 tabindex="0">Fourth Question</h3>
        <div>
            <p>
            Lorem ipsum dolor sit amet, consecteteur adipiscing elit. Mauris euismod semper nisi urna lacinia eu, auctor at, interdum nec, natoque a, mattis fames magna turpis rutrum. Consectetuer cubilia vitae. Velit lectus consectetuer fermentum aenean neque adipiscing odio morbi tristique blandit. Sit. Purus. Semper pede, viverra laoreet diam ultrices nunc. Facilisis ante duis quisque in, convallis nisi. Potenti nibh lobortis odio, sit. Turpis. Mi. Libero, id lectus fringilla faucibus aenean. Cursus amet, arcu erat. Purus facilisis aliquet ante maecenas curabitur. Suspendisse arcu, odio, luctus aliquam. Nisi rhoncus et.
            </p>
            <p>
            Pulvinar auctor curae condimentum pede. Nunc parturient curabitur morbi at consectetuer eget egestas. Sollicitudin integer, donec diam lorem, elementum dis. Duis odio. Porta potenti elit diam posuere convallis leo. Vel justo sociis diam gravida sit, vestibulum tortor, torquent aliquet fusce class. Elit non molestie. Et. Erat sollicitudin adipiscing cras. Sociis. Vel, eros. Ullamcorper. Diam, eu velit vitae duis feugiat.
            </p>
        </div>
    </div>

    <div class="accordionItem">
        <h3 tabindex="0">Fifth Question</h3>
        <div class='hide'>
            <p>Lorem ipsum dolor sit amet, consecteteur adipiscing elit vehicula. A. Lacus proin ornare vulputate rhoncus. Ac nunc nunc natoque et, sem at lobortis fusce duis potenti eu, tempor. Pretium, donec neque felis, accumsan. Ante placerat augue. Tellus. Euismod dui, in fringilla eget.</p>
        </div>
    </div>

    <div class="accordionItem">
        <h3 tabindex="0" unselectable="on">Sixth Question</h3>
        <div>
            <p>
            Lorem ipsum dolor sit amet, consecteteur adipiscing elit. Integer, iaculis ultricies habitant auctor lectus fusce posuere ut. Dolor netus, interdum dignissim. Tellus neque scelerisque eu lectus. Arcu semper id dictum massa parturient suspendisse tortor ut class neque morbi. Quis risus gravida metus amet arcu vivamus. Fringilla etiam nunc iaculis. Tempor. Consectetuer feugiat, augue nunc imperdiet. Odio. In, ac congue sit aenean, ad id curae lobortis felis id tristique. Consectetuer facilisis curae eu platea pharetra dui aliquam sagittis quisque taciti purus.
           </p>
        </div>
    </div>
</div>
<script type="text/javascript">
(function() {

    var headings = document.querySelectorAll('.accordionItem h3'),
        len = headings.length, i;

        toggleItem = function() {

            var root = this.parentNode, /* div accordionItem parentNode */
                div = root.querySelector('div'),
                divToHide = document.querySelector('.accordionItem div.show');

            div.classList.toggle('show');

            if(divToHide) { divToHide.classList.remove('show'); }

        };

    for (i = 0; i < len; i += 1) {

        headings[i].onclick = headings[i].onkeypress = toggleItem;

    }
}());
</script>
</body>
</html>

As I say will look at making a more backward compatible version, but hope this helps.

Thanks, that’s great, apart from

which is the opposite of what I want. :slight_smile:

Ha ha. Missed that

Still working on the backwards compatibility.

In the meantime

(function() {

    var headings = document.querySelectorAll('.accordionItem h3'),
        len = headings.length, i;

        toggleItem = function() {

            var root = this.parentNode, /* div accordionItem parentNode */
                div = root.querySelector('div'),
                divToHide = document.querySelector('.accordionItem div.show');

            div.classList.remove('hide'); div.classList.add('show');

            if(divToHide) { divToHide.classList.remove('show'); divToHide.classList.add('hide'); }

        };

    for (i = 0; i < len; i += 1) {

        headings[i].onclick = headings[i].onkeypress = toggleItem;
        headings[i].parentNode.querySelector('div').classList.add('hide');

    }
}());

change to css

.accordionItem div.show { display: block; }

.accordionItem div.hide { display: none; }

Now has a ‘hide’ class as well, which is initially added to all the divs in javascript. Switich off javascript and all paragraphs will be displayed.

It would be helpful to get some input on this. Firstly having issues with IE8 not consistently firing clicks. Specifically clicking too quickly one after another will not fire.

Regards the keypress and the ‘Tab’ key is it? Will look into that. You want it to do it’s default behaviour plus hide and show elements I presume.

Edit: onkeyup seems work better with ‘Tab’. Have edited code. Could still do with work.

Anyway should work ok in ie9+. You will need to amend the hide and show class as per previous post.

(function() {

    var addClass = function(el, clName) {
    
            if ((' '+el.className+' ').indexOf(' '+clName+' ') === -1) { el.className = el.className+' '+clName; }
    
        },
        
        replaceClass = function(el, clName, newClName) {
            
            var elClName = ' '+el.className+' ';

            while (elClName.indexOf(' '+clName+' ') !== -1) { elClName = elClName.replace(' '+clName+' ',' '+newClName+' '); }

            el.className = elClName.replace(/^\\s+|\\s+$/g, '');
        
        },

        addEvent = function(el, type, fn) {
        
            if(el.addEventListener) {
                
                el.addEventListener(type, fn, false);
                
                return fn;
                
            } else {
                // bind 'this' to element
                var callback = function(){ return fn.apply(el, arguments); }
                
                el.attachEvent('on'+type, callback);
                
                return callback;
            }
        },

        items = document.querySelectorAll('.accordionItem'),
        len = items.length, i;

        toggleItem = function(e) {
            
            var root = this,
                div = root.querySelector('div'),
                divToHide = document.querySelector('.accordionItem div.show');

            replaceClass(div, 'hide', 'show');

            if(divToHide) { replaceClass(divToHide, 'show', 'hide'); }

        };

    for (var i = 0; i < len; i += 1) {
    
        addEvent(items[i], 'click', toggleItem);
        addEvent(items[i], 'keyup', toggleItem);
        addClass(items[i].querySelector('div'), 'hide');
    }
}());

Thanks - I really appreciate the trouble you’re taking. Unfortunately, my audience for this is predominantly elderly and using fairly old systems. I know a number of them are still running XP, so I do have to support IE8. :frowning: Although it would be acceptable just to have the whole lot display in IE8, with no hide/show.

I’ve tried both the versions you gave above, and both of them still hide everything when JS is disabled. I’ve remembered to change the CSS, so I’m not sure where the problem is. :o

Ok, well some progress. Learning exercise for me too.

Swapping out ‘click’ for ‘mouseup’ seems to have fixed the ie8 issue and also works in the newer browsers I have tested.
Edit: Just to explain the problem with ‘click’ in IE8. If you click repeatedly and too quickly then a dblclick event gets fired instead of click.

I’ve tried both the versions you gave above, and both of them still hide everything when JS is disabled. I’ve remembered to change the CSS, so I’m not sure where the problem is

Probably best I give you the complete code then. If I switch off javascript in chrome, it displays all the paragraphs. In addition testing in IE offline obviously blocks javascript until you ok it. All content is displayed until I click ‘ok’.

Here you go. Hope it works for you.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Type of Test</title>
<style>
body, h1, h2, h3, dl, dt, dd, ul, li, p {margin: 0; padding: 0;}

body {color: #333333;
    font-family: "Trebuchet MS",Helvetica,sans-serif;
    font-size: 100%;
    line-height: 1.4;
    background-color: #EDEDED;
    }

#page {width: 100%;
    max-width: 58em;
   margin: auto;
   background-color: #fff;
   }

p {padding: 0.5em 0;}

.accordionItem h3 {
    margin: 0;
    font-size: 1.1em;
    padding: 0.4em;
    color: #fff;
    background-color: #88F;
    border-bottom: 1px solid #66d;
    /* prevent h3 being highlighted */
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}

.accordionItem h3:hover { cursor: pointer; }
.accordionItem h3:focus { outline: 2px solid #0000FF; }

.accordionItem div {
    margin: 0;
    padding: 1em 0.4em;
    background-color: #fff;
    border-bottom: 1px solid #66d;
    display: block;
}

.accordionItem div.show { display: block; }

.accordionItem div.hide { display: none; }

</style>
</head>
<body>

<div id="page">

<h2>Page Heading</h2>

    <div class="accordionItem">
        <h3 tabindex="0">First Question</h3>
        <div>
            <p>
            Lorem ipsum dolor sit amet, consecteteur. Netus semper ve ante elit hymenaeos. Vitae dapibus, ultricies eu ullamcorper ut, cursus cum. Tortor vitae hendrerit rhoncus purus odio. Sapien. Vitae. Cras elit neque eros sem odio luctus fringilla nonummy. Taciti, luctus, urna sit. Dui sem consectetuer ut, lacus in erat, class.
            </p>
        </div>
    </div>

    <div class="accordionItem">
        <h3 tabindex="0">Second Question</h3>
        <div>
             <p>
             Lorem ipsum dolor sit. Varius praesent ullamcorper interdum, cras mi nulla dui maecenas habitasse ut, penatibus. Vehicula placerat libero nunc ut cras. Suspendisse laoreet morbi duis platea, sapien, bibendum pede. Hac eu elit fusce, urna rutrum, dictum orci. Felis penatibus sit, malesuada lacus ac luctus aliquam egestas odio. Cras. Ultrices aliquam posuere odio feugiat vivamus. Mollis, hendrerit adipiscing nibh. Hymenaeos. Eros senectus etiam diam facilisi vestibulum gravida cum ante nibh.
             </p>
        </div>
    </div>

    <div class="accordionItem">
        <h3 tabindex="0">Third Question</h3>
        <div>
            <p>
            Lorem ipsum dolor sit amet, consecteteur adipiscing elit elit. Porta at fames aenean. Sapien libero. Mauris hymenaeos ut, at ad risus nam platea.
            </p>
        </div>
    </div>

    <div class="accordionItem">
        <h3 tabindex="0">Fourth Question</h3>
        <div>
            <p>
            Lorem ipsum dolor sit amet, consecteteur adipiscing elit. Mauris euismod semper nisi urna lacinia eu, auctor at, interdum nec, natoque a, mattis fames magna turpis rutrum. Consectetuer cubilia vitae. Velit lectus consectetuer fermentum aenean neque adipiscing odio morbi tristique blandit. Sit. Purus. Semper pede, viverra laoreet diam ultrices nunc. Facilisis ante duis quisque in, convallis nisi. Potenti nibh lobortis odio, sit. Turpis. Mi. Libero, id lectus fringilla faucibus aenean. Cursus amet, arcu erat. Purus facilisis aliquet ante maecenas curabitur. Suspendisse arcu, odio, luctus aliquam. Nisi rhoncus et.
            </p>
            <p>
            Pulvinar auctor curae condimentum pede. Nunc parturient curabitur morbi at consectetuer eget egestas. Sollicitudin integer, donec diam lorem, elementum dis. Duis odio. Porta potenti elit diam posuere convallis leo. Vel justo sociis diam gravida sit, vestibulum tortor, torquent aliquet fusce class. Elit non molestie. Et. Erat sollicitudin adipiscing cras. Sociis. Vel, eros. Ullamcorper. Diam, eu velit vitae duis feugiat.
            </p>
        </div>
    </div>

    <div class="accordionItem">
        <h3 tabindex="0">Fifth Question</h3>
        <div class='hide'>
            <p>Lorem ipsum dolor sit amet, consecteteur adipiscing elit vehicula. A. Lacus proin ornare vulputate rhoncus. Ac nunc nunc natoque et, sem at lobortis fusce duis potenti eu, tempor. Pretium, donec neque felis, accumsan. Ante placerat augue. Tellus. Euismod dui, in fringilla eget.</p>
        </div>
    </div>

    <div class="accordionItem">
        <h3 tabindex="0" unselectable="on">Sixth Question</h3>
        <div>
            <p>
            Lorem ipsum dolor sit amet, consecteteur adipiscing elit. Integer, iaculis ultricies habitant auctor lectus fusce posuere ut. Dolor netus, interdum dignissim. Tellus neque scelerisque eu lectus. Arcu semper id dictum massa parturient suspendisse tortor ut class neque morbi. Quis risus gravida metus amet arcu vivamus. Fringilla etiam nunc iaculis. Tempor. Consectetuer feugiat, augue nunc imperdiet. Odio. In, ac congue sit aenean, ad id curae lobortis felis id tristique. Consectetuer facilisis curae eu platea pharetra dui aliquam sagittis quisque taciti purus.
           </p>
        </div>
    </div>
</div>
<script type="text/javascript">
(function() {

    var addClass = function(el, clName) {
    
            if ((' '+el.className+' ').indexOf(' '+clName+' ') === -1) { el.className = el.className+' '+clName; }
    
        },
        
        replaceClass = function(el, clName, newClName) {
            
            var elClName = ' '+el.className+' ';

            while (elClName.indexOf(' '+clName+' ') !== -1) { elClName = elClName.replace(' '+clName+' ',' '+newClName+' '); }

            el.className = elClName.replace(/^\\s+|\\s+$/g, '');
        
        },

        addEvent = function(el, type, fn) {
        
            if(el.addEventListener) {
                
                el.addEventListener(type, fn, false);
                
                return fn;
                
            } else {
                // bind 'this' to element
                var callback = function(){ return fn.apply(el, arguments); }
                
                el.attachEvent('on'+type, callback);
                
                return callback;
            }
        },

        items = document.querySelectorAll('.accordionItem'),
        len = items.length, i;

        toggleItem = function(e) {
        
            var e = (e || window.event);
            
            if(e.preventDefault) { e.preventDefault() } 
            else (e.returnValue = false);
            
            var root = this,
                div = root.querySelector('div'),
                divToHide = document.querySelector('.accordionItem div.show');

            replaceClass(div, 'hide', 'show');

            if(divToHide) { replaceClass(divToHide, 'show', 'hide'); }

        };

    for (var i = 0; i < len; i += 1) {
    
        addEvent(items[i], 'mouseup', toggleItem);
        addEvent(items[i], 'keyup', toggleItem);
        addClass(items[i].querySelector('div'), 'hide');
    }
}());
</script>
</body>
</html>

It does indeed (after I removed the stray class=“hide” from the fifth item ;)). Many thanks for your time and effort - it’s much appreciated. :slight_smile:

No worries man, glad it worked.:tup:

Is the problem solved then? And in a way that you understand the inner working of the code? Because a working code is one thing, but the one who has to work with it should preferably understand its mechanism and syntax, too, I’d think. You offered a high-tech and possibly fully working solution, RLM, don’t get me wrong. But I wonder whether the Bear understands the inner working of the Javascript?

Also, I made a JSBin demo of the last posted code. In that demo, tabbing = opening, and clicking inside an opened content part = closing? Doesn’t the latter make it an oddly functioning web questionnaire?

To be honest, no. I’ve not had time to go through it and try to make sense of it yet. My JS knowledge is sadly lacking, or I wouldn’t be here asking about this. :slight_smile:

I’m not sure I understand your last point. The page is an FAQs page, rather than a questionnaire. (The existing page has a <ul> with the list of questions, each of which links down to the relevant place in a <dl> with the questions and answers. But it’s pretty long and unwieldy like that, and not easy to move about in, so I thought an accordion would help.)

Ideally, if I could write this myself, I’d have Tab move through each item and Enter open them, in the same way that tabbing through navigation links works. So that if I’m only interested in Question Five, I can tab down to it without each section opening on the way through. (The chances of anybody wanting to read every Q&A are pretty remote.) However, having them open when I land on them is definitely an improvement on having them open when I leave them, as was happening before.

One odd behaviour of the latest code which I’ve noticed just now is in using Shift + Tab to move back up the list. The item opens when tabbed to, but closes if the Shift key is released, which I think would be confusing. It does then open again with Enter, but my target audience consists largely of the kind of folk who feel they’ve done something wrong if things don’t function as expected. :slight_smile: