views:

113

answers:

8

I have a large survey that I have made more usable with jQuery by arranging it into sections and using an accordian menu to flip through each section.

The trouble is, there is a noticable snap when $(document).ready() fires and condenses everything into an accordian menu. That is to say that before $(document).ready(), you can see the whole survey.

I did consider setting #surveyForm to display: none; in css and #surveyForm.active to display: block; but that creates a new problem:

Browsers without javascript enabled will never get to see #surveyForm.active and so they won't be able to use the survey.

Any ideas?

Cheers

-Iain

+1  A: 

I would stick with the css display:none solution. To fix the no javascript issue you might consider using this:

<script type="text/javascript">
   $(document).ready(function(){
      // fade in?
   });
</script>
<noscript>
   <div>foobar!</div>
</noscript>
jAndy
Assuming that what goes in the "foobar!" slot is the content you want shown would this not mean having two copies of the survey in the HTML or am I missing your intent here?
Chris
+2  A: 
Mike
Neat solution - obvious when you see it. Does it work?
belugabob
+2  A: 

It's not clean and unobtrusive like good Javascript should be, but you can just add a Javascript snippet directly after your accordian content to initialize the accordian and hide the pieces that need hiding. The net effect should completely eliminate the "snap" and keep the form accessable to non-JS clients.

Chris Heald
A: 

Could you try hiding everything at the top of your jquery block, and then showing it again after you do all the condensing?

$(document).ready
(
    function ()
    {
        $("#surveyForm").hide();
        ... MAGIC CONDENSING
        $("#surveyForm").show();
    }
);

That may reduce the impact of the "snap" you're seeing.

Jason
the problem happens because the survey is visible before document `ready` fires.
Anurag
Yes, but is the "snap" due to all the condensing that his script is doing? If so, hiding the whole thing first, then condensing and then showing might lessen or remove the "snap" effect.
Jason
@Jason - I think the snap is because the default html is rendered with the initial sizing but after applying the accordion on dom ready, the content sizing changes which causes the snap. Hiding it would still have that problem, as the survey is initially visible, then there will be a blink (hide/show) and the survey will be resized in an accordion when it comes back.
Anurag
+2  A: 

If you want to easily manage non-javascript browsers/users without the snap when JS is enabled, try the following snippet inside the head node of your page:

document.documentElement.className = 'has-js'
// or any other class name, use += and append it if you already have a class on your *html* tag

In your CSS write for the non-js scenario first and then set display to none or hide it any other way that fits you by prefixing your js-relevant css selector with .has-js.

I'll probably get downvoted for putting javascript in the head but keep in mind that from a performance standpoint (Yahoo et al) only javascript files (external) need to be loaded as late as possible.

A javascript tag itself will not make your page load longer except for the fact that it will block render while it is being parsed and executed, but in this case we want that, since you need the .has-js class before rendering starts to avoid flickering.

Denis 'Alpheus' Čahuk
+1  A: 

This is the progressive enhancement solution I use for situations like this.

Mitch R.
This works perfectly! Well done and thank you :)
Iain Fraser
A: 

Ways that I can think of to deal with this are:

  1. Use javascript to load the CSS file that does initial hiding.

  2. Put CSS in a noscript block that sets visibility to true after you've set it to false everywhere.

Both should work I think though I've not had a chance to test them properly.

Chris
A: 

You can place an inline Javascript statement which will hide the element immediately after it is rendered.

Basically...

  1. Scripts inside the <head> section are loaded
  2. HTML is rendered
  3. $(document).ready() fires

So to fix that, you can simply do this

<head>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
  $(document).ready(function() {
    $("#survey").accordion();
  }
</head>
<body>
    <div id="survey">....</div>
    <script type="text/javascript">
      $("#survey").hide();
    </script>
</body>
Marko