Reputation: 736
I am using the excellent accordion menu provided by Ian Flynn of RocketMill: http://www.rocketmill.co.uk/create-accordian-boxes-with-a-rotating-arrow-using-css-jquery
This has worked well for me in the past, but I have a new client that leans towards the verbose. This presents a problem when the user attempts to click on their next desired accordion link. The accordion works correctly, but the hyperbolic amount of content shoots off of the page, presenting an obvious usability issue.
What I want to do is to reconcile the top of the active (just clicked on) "menuTitle" div with the top of its parent, the "content" div.
<div id="content">
<div class="menuTitle">
<strong>Title 1…</strong>
</div>
<div class="menuContent"> <!-- Sliding content box -->
<h5>Sub-title 1</h5>
<p>Content</p>
</div> <!-- End of div class="menuContent" -->
<!-- THE ABOVE SEVEN LINES REPEAT FOR EACH FOLD OF THE ACCORDION -->
</div> <!-- End of div id="content" -->
I have been working on this for about three days and have consulted many, many sites, jQuery guides, and whisky. I am not a jQuery expert. Please help!
Oh… I made a jsFiddle. My first: http://jsfiddle.net/Parapluie/CRXX8/
Upvotes: 0
Views: 1026
Reputation: 1547
well, if i understand what you want..
$(document).ready(function() {
$('#content .menuTitle').on('click',function() {
$('#content .menuTitle').removeClass('on'); // "closes" the closing menu arrow
$('#content .menuContent').slideUp('normal'); // slide-closes the closing div
if($(this).next().is(':hidden') == true) {
$(this).addClass('on'); // "opens" the opening menu arrow
$(this).next().slideDown('normal',function(){
$('html,body').animate({scrollTop:$(this).prev().offset().top}, {queue: false,duration:250, easing: 'swing'}); // on complete slidedown, scroll the clicked .menuTitle to top of page
});// slide-opens the opening div
}
}); // end of click event
}); // end of ready
UPDATE:
As your called elements are wraped in a div called '#focusWide'
, you dont have to scrollTop html,body
, you have to scrollTop the wraper div '#focusWide'
and use position().top
istead of offset().top
. And i add more '11px'
(half of wraper div padding).
$('#focusWide').animate({scrollTop:$(this).prev().position().top + 11 + 'px'}, {queue: false,duration:250, easing: 'swing'});
Upvotes: 2
Reputation: 18051
I use the function shown below, which works great in most cases. Just make sure the container/wrapper is scrollable (using overflow-y:auto
). See fiddle
function scrollIntoView(oElement, sContainer, fnCallback) {
var oContainer, nContainerTop, nContainerBottom, nElemHeight, nElemTop, nElemBottom;
if (!oElement || oElement.length <= 0) {
return;
}
oContainer = (typeof sContainer == "object" ? sContainer : $(sContainer));
nContainerTop = oContainer.scrollTop();
nContainerBottom = nContainerTop + oContainer.height();
nElemHeight = oElement.height() || 25;
nElemTop = oElement[0].offsetTop - 50;
nElemBottom = nElemTop + nElemHeight + 100;
if ((nElemTop < nContainerTop) || (nElemHeight >= $(sContainer).height())) {
oContainer.animate({ scrollTop: nElemTop }, { duration: "fast", complete: fnCallback });
}
else if (nElemBottom > nContainerBottom) {
oContainer.animate({ scrollTop: (nElemBottom - $(sContainer).height()) }, { duration: "fast", complete: fnCallback });
}
else if (fnCallback) {
fnCallback();
}
}
Upvotes: 0