views:

3928

answers:

9

I am testing a site build with a slow connection and I noticed the jQuery Accordion stays expanded for a long time, until the rest of the site is loaded, and then finally collapses. Not very pretty. I was wondering how I could keep it collapsed through the loading process and only expand when clicked.

I am working with the standalone 1.6 version of the accordion plugin.

The basic structure :

<div class="sidebar">

<ul id="navigation" class="ui-accordion-container">
<li><a class="head" href="#">1</a>
     <ul class="sub">
     <li><a href="#">1a</a></li>
     <li><a href="#">2a</a></li>
     </ul> 
 </li>
</ul>
</div>

and the script

jQuery().ready(function(){
jQuery('#navigation').accordion({ 
active: 'false', 
header: '.head', 
navigation: true,
animated: 'easeslide',
collapsible: true
});  
});

I tried to hide the elements in the CSS to keep them from appearing while loading but all that achieved is in having them always hidden.

Maybe the problem is in the CSS I have a background image in each of the sub menus:

#navigation{
margin:0px;
margin-left: 10px;
padding:0px;
text-indent:0px;
font-size: 1.1em;
width:200px;
text-transform: uppercase;
padding-bottom: 30px;
} 
#navigation ul{
border-width:0px;
margin:0px;
padding:0px;
text-indent:0px;
}
#navigation li{
list-style:none outside none;
}
#navigation li ul{
height:185px; overflow:auto;
}
#navigation li ul.sub{
background:url('../images/sub.jpg') no-repeat;
dispaly: block;
}
#navigation li li a{
color:#000000;
display:block;
text-indent:20px;
text-decoration: none;
padding: 6px 0;
}
#navigation li li a:hover{
background-color:#FFFF99;
color:#FF0000;
}

Thanks in advance for any advice on how to have this thing run a little smoother and having the accordion always collapsed.

-edit - I forgot to mention that I am also hoping for a solution that will allow the nav to still be accessible for those without javscript.

A: 

I haven't used UI accordion, but I have built accordions with jQuery. The only thing the script does is to alternate the visibility of the accordion panels. So if one panel is visible when the page loads, then perhaps you should try using a CSS rule such as:

ul.sub{
  visiblity:hidden;
  display:none;
}
picardo
Yes as I mentioned I did try that but then sub menu was always hidden. It is not one panel but all of them that are expaned out while the page loads.
zac
A: 

I tried to hide the elements in the CSS to keep them from appearing while loading but all that achieved is in having them always hidden.

Why don't you try making it hidden in the css, and then do this:

jQuery('#navigation').show().accordian...

aquinas
Thanks for the response.. that would work but as I failed to mention in my original post.. I am trying to find a solution that allows the menu to still be used if javascript is off
zac
+2  A: 

Code inside jQuery.ready() doesn't run until the DOM is ready — so it's normal for elements that will eventually be hidden to stay visible for a while. Accordion is set up this way partly for ease of use and partly for the sake of graceful degredation: content won't be missing (hidden) if JavaScript is disabled.

If you're willing to risk a page that breaks without JavaScript, go ahead and set your elements to be hidden. Then, immediately before .accordion(), show() them.


Here's an idea to maintain compatibility. It has been minimally-tested and is open to comment.

Leave your CSS alone, but add this to the top of your JavaScript (outside jQuery.ready()):

document.styleSheets[0].addRule(".yourclass", "display:none");

That way, as the page is being constructed, a CSS rule will be set up to hide your hidden elements. Then, inside jQuery.ready(), call $(".yourclass").show() to bring them back before initializing the accordion.

Sidnicious
ahh yes that was what i meant to add to my question, if there was a way to do it and still have the navigation accessible for those without javascript.. guess not ?
zac
zac, I added some code to my post that might work. I just came up with the idea, so it could use some testing, but it's getting the job done on my end.
Sidnicious
Hmmm.. that sounds like a good solution.. i will give it a go in a bit and let you know what happens.
zac
A: 

Do your .accordion binding directly in a <script> just below the accordion elements instead of waiting for document ready.

They'll then activate as soon as possible, rather than waiting until the page is ‘ready’ (which can take a long time especially on IE, which doesn't support the DOMContentLoaded event, so jQuery has to wait for onload, which only fires after all the images and everything are loaded).

You could set the accordion parent element to ‘visibility: hidden’, and then restore it to ‘visible’ manually when the script initialises. But then browsers with JavaScript off won't see the content at all, which isn't ideal.

bobince
+8  A: 

I do this first thing with all my sites: Right after the body tag, put a script tag with this javascript:

jQuery('body').addClass('js');

This gives you a style hook for any elements that will look different in some way when Javascript enabled, and it happens immediately.

There are good solutions to the rest of your problems in the other answers. You'll just need two "base" styles instead of one:

#navigation ul li { /*open styles for no javascript*/ }
body.js #navigation ul li { /*closed styles for pre dom.ready*/ }

... and then re-open before applying the accordion on dom.ready.

EDIT: If you're loading jQuery at the end of the page (or aren't using jQuery), you can use this straight javascript version:

<script type="text/javascript">
    var b = document.getElementsByTagName('body')[0];
    b.className+=b.className?' js':'js';
</script>
Jerph
oh that is great! thanks for sharing... that will solve a lot of my concerns about degredation
zac
+1  A: 

I faced this very problem a week ago. I set the container to display:none and then used jQuery to make it show up at the appropriate time:

$(".accordion").show();
$(".accordion").accordion();
A: 

I have hundreds of jQuery elements (tabs, sliders & accordions) across many portal sites. Setting hide/show styles for each isn't a realistic option.

Simple solution, hide the body until jQuery is ready and has built the elements, then show the body.

In my master stylesheet:

body {
  display: none; 
}

In my master javascript file, at the bottom of jQuery.ready():

$(document).ready(function() { 
   $("body").show(); 
}
Tim
A: 

I have been using css solutions like the one Tim suggested, but these would mean to hide content for people with javascript disable (or devices with no javascript support). I much prefer the solution provided by Jerph, thanks for sharing.

AJweb
A: 

be careful using this with regard to accessibility:

body { display: none; }

If for whatever reason javascript is turned off, then nothing will be displayed ;)

Stryder