+3  A: 

I would recommend using a css selector for hiding your answers. In order to do so you would have to add a class attribute to your answer.

<div class="questions_main_box">
   <h2>common questions:</h2>
   <ul>
      <li>
         <h3 id="question1">question number 1</h3>
     <div id="answer1" class="answer">answer number 1</div>
      </li>
      <li>
         <h3 id="question2">question number 2</h3>
     <div id="answer2" class="answer">answer number 2</div>
      </li>
      etc etc...
   </ul>
</div>

Then using jquery you could hide all answers using this

$('.answer').hide();

So, put together with your other question JQuery if then else using URL parser plugin, there must be a more elegant solution! it would be:

var match = jQuery.url.attr('anchor').match(/^question([0-9]+)$/);
if (match && match.length > 0) {
    $('.answer').hide();
    $('#answer' + match[1] ).show();
}

Or on a single line like this.

 $('.answer').hide().is('#answer' + match[1]).show();
bendewey
Correct me if I'm wrong, but i would appear that having the $('.answer').hide(); after show would also hide the matching answer.
Jose Basilio
I thought that. Also neither of the answers from the previous question work correctly with both methods of showing the hidden answers. Tagging a hide class on to that code wouldn't help I don't think. I was hiding everything using:$('.questions_main_box ul li div').hide(); and then revealing things as and when I needed, but this struck me as inefficient because I'd effectively be hiding a div and then showing it again. At least with my current code everything is tested before an action is carried out.
i0n
@Jose you are correct, good catch, I changed the order.
bendewey
+1  A: 

To fix your Firefox issue, you could try using jQuery to scroll to your anchor after unhiding it. It's a little bit hackish, I suppose, but it should work.

The 'Interface' plugin for jQuery includes a scrollTo method. Link

Example usage. jQuery Smooth Scroll to Anchor Links

To solve the elegance problem, here's one idea:

var targetDiv = $('#'+($.url.attr('anchor'))).next().attr('id');
$("div[id!='"+targetDiv+"'][id^='answer']").hide();
$("div[id='"+targetDiv+"']").show();
$.scrollTo('#'+($.url.attr('anchor')));
Steven Richards
That's a really good idea. I was already using the localScroll plugin so this was easy to implement and adds that extra security that the browser window will be scrolled to the correct place!
i0n
+1  A: 

My suggestion would be to not use jQuery to hide answers initially, because doing so dynamically seems likely to confuse the browser about how long the page is.

Instead, I would use a class and CSS to hide them, e.g.

<li>
  <h3 id="question1">Foo?</h3>
  <div id="answer1" class="answer">Bar!</div>
</li>

and add .answers { display: none; } to the page's style so the browser is aware that those will not appear when the page first renders. Then, adding the $('#answer1').show() will show the appropriate.

Of course, this only works if your users have Javascript enabled, which might be a valid assumption. If they might not, then you need to dynamically add this CSS to the top of the page before the page fully renders. This is done by adding a <script> to the top of the body that adds the style:

<body>
  <script type="text/javascript">
    var style = document.createElement('style');
    style.type = 'text/css';
    style.innerHTML = '.answers { display: none; }';
    document.getElementsByTagName('head')[0].appendChild(style);
  </script>
  ...

This will ensure that people without Javascript will see all the answers.

In my tests, doing it this way ensures that the page is properly scrolled to the right question, at least in FF3.

tghw
-1 how will writing a <script type="text/javascript"> help if people don't have javascript?
bendewey
Think about it. If you just use CSS, anyone without JS will have all the answers hidden. If you add the CSS with JS, then you will not hide the answers from people without JS, which is what you want, since they have no way of showing it.
tghw
Thanks for your suggestion but this will make the content inaccessible to people without JavaScript enabled so it's a no go I'm afraid. Also I for one hat writing script directly into my HTML pages...
i0n
Is no one understanding what's going on here?If JS => Answers hiddenElse => Answers not hidden
tghw
I understand what you are suggesting. What I was pointing out was that in order to accomplish this without inline JavaScript containing CSS rules in the HTML page (Yuch!) I would have to add the rule to the stylesheet. This would make things inaccessible for users without JavaScript enabled. The point is moot now anyway as I have resolved the Firefox bug. So the only question that remains is a way of writing my if then else loop more elegantly without breaking functionality when an anchor tag is not present!
i0n
+1  A: 

You should add a class, it would be alot cleaner to hide them all with css. But using your existing html ...

$("div.questions_main_box div").hide();

In the abscence of an anchor, it looks like you wanted the first question to show so ...

var question = jQuery.url.attr('anchor') | "question1";
var match = question.match(/^question([0-9]+)$/);
if (match && match.length > 0) {
    $('#answer' + match[1] ).show().scrollTo();
}

I aam not sure what .scrollTO is in your code, but I assume it is a plugin, and $.scrollTo(selector) should be the same as $(selector).scrollTo()

Since you are using anchors, you should use the browser built in scrolling mechanism with anchors and forget about jQuery scrolling. Add a corresponding anchor tag to each question like:

<li>
    <a name="question1" />
Chad Grant
A: 
$('.questions_main_box h3').addClass('js_main_box');

$('.questions_main_box h3').bind('mousenter mouseleave',function(){
    $(this).toggleClass('js_main_box_highlight');
});

$('.questions_main_box h3').click(function(){
    var answer = $(this).parent().find("div");
    if (answer.is(':visible')) {
      answer.hide('fast');
      return;
    }
    answer.show('fast');
});
Chad Grant
Trying to change the state of the headings this way creates unexpected and unwanted results. Better the way I had it. I'm pretty happy with this section of the code, it's really only the if then else loop that I think needs refinement. Hiding everything and then showing items afterwards seems to be slower than what I have now so what I'm really looking for is a way of testing for a URL anchor and then hiding the rest of the divs inside the ul.
i0n
I could wrap it up in a few mins if you could post the source somewhere. thnx
Chad Grant
A: 

OK, so I'm going to answer my own question! This solution fixes the Firefox scrolling bug using scrollTo and the code is much more elegant and scalable. It's still not perfect but I have managed to condense the if loop down to this:

if 
  ($.url.segment(1) == 'questions.html'||'terms.html') {
    $('.questions_main_box ul li div').hide();
    $('#'+($.url.attr('anchor'))).next().show();
    $.scrollTo('#'+($.url.attr('anchor')));
};

Pros:

  • Code is much more elegant/condensed/DRYer
  • URL anchors will now work regardless of what they are called
  • Not dependant on matching question and answer id's
  • Will scale to any number of entries

Cons:

  • All divs are hidden before URL parsing is used to reveal any match. This is slightly less efficient than finding a way to test and only hide the necessary divs.

That's it! I hope this helps someone with a similar conundrum rattling around in their brain! If anyone can think of a way to improve this code to remove the final con then I'd be really interested to see your solution.

Finally thanks to Steven Richards for solving the Firefox bug problem by suggesting the use of scrollTo. A painless and simple solution, I thank you! http://stackoverflow.com/users/96089/steven-richards

i0n