This is my second question about this topic, the original question can be found here: JQuery if then else using URL parser plugin, there must be a more elegant solution!
If you are sitting comfortably I shall begin!
I have built a web page which contains a list of questions. Each question has an answer contained in a Div after it. The HTML looks like this:
<div class="questions_main_box">
<h2>common questions:</h2>
<ul>
<li>
<h3 id="question1">question number 1</h3>
<div id="answer1"> answer number 1</div>
</li>
<li>
<h3 id="question2">question number 2</h3>
<div id="answer2"> answer number 2</div>
</li>
etc etc...
</ul>
</div>
I have written some code using jQuery to adjust the way this list behaves. The idea is that all the answer Divs are hidden by jQuery, they are then revealed in one of two ways:
Either the user clicks the relevant h3 header
or
The user clicks on a link to one of the questions from another page.
If the user is coming from another page, the question that they clicked should be displayed and all the others hidden.
I've made this work but my code is rather inefficient. I was furnished with an answer in my previous go at explaining this issue, but the answers I received had an undesirable side effect: They stopped the menu from displaying any answers unless there was an anchor link in the URL. So for instance:
http://mydomain.com/questions.html would not work
but
http://mydomain.com/questions.html#question1 would work!
I need for both to work! As I said my version does work in both ways but is pretty clunky and I'm sure there must be a better way of expressing it. Here's the code that could be more efficient:
if
($.url.attr('anchor') == 'question1'){
$('#answer2, #answer3, #answer4, #answer5, #answer6, #answer7, #answer8').hide();
$.scrollTo('#question1');
}
else if
($.url.attr('anchor') == 'question2'){
$('#answer1, #answer3, #answer4, #answer5, #answer6, #answer7, #answer8').hide();
$.scrollTo('#question2');
}
else if
($.url.attr('anchor') == 'question3'){
$('#answer1, #answer2, #answer4, #answer5, #answer6, #answer7, #answer8').hide();
$.scrollTo('#question3');
}
else if
($.url.attr('anchor') == 'question4'){
$('#answer1, #answer2, #answer3, #answer5, #answer6, #answer7, #answer8').hide();
$.scrollTo('#question4');
}
else if
($.url.attr('anchor') == 'question5'){
$('#answer1, #answer2, #answer3, #answer4, #answer6, #answer7, #answer8').hide();
$.scrollTo('#question5');
}
else if
($.url.attr('anchor') == 'question6'){
$('#answer1, #answer2, #answer3, #answer4, #answer5, #answer7, #answer8').hide();
$.scrollTo('#question6');
}
else if
($.url.attr('anchor') == 'question7'){
$('#answer1, #answer2, #answer3, #answer4, #answer5, #answer6, #answer8').hide();
$.scrollTo('#question7');
}
else if
($.url.attr('anchor') == 'question8'){
$('#answer1, #answer2, #answer3, #answer4, #answer5, #answer6, #answer7').hide();
$.scrollTo('#question8');
}
else if
($.url.attr('anchor') != 'question1, question2, question3, question4, question5, question6, question7, question8'){
$('.questions_main_box ul li div').hide();
};
It works fine but is quite clunky, in it's current incarnation it also means that if I want to add more questions and answers I have to add them explicitly to the list(s) of ID's. It would be far better not to have to do this!
Just so you have the whole pi
-
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();
Jose Basilio : Correct me if I'm wrong, but i would appear that having the $('.answer').hide(); after show would also hide the matching answer.i0n : 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.bendewey : @Jose you are correct, good catch, I changed the order. -
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')));
i0n : 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! -
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.
bendewey : -1 how will writing a