Ask your JavaScript questions! Pay money and get answers fast! (more info)

Scroll to clicked item in expandable/collapsible list in div JavaScript

  • REFUNDED

Hi,
I have a page layout that has a fixed header and a footer. The body contains two scrollable columns - a layout similar to www.cssplay.co.uk/layouts/body5.html. Within each scrollable columns, I am trying to incorporate a list such as that featured in jsfiddle.net/489Y2/6/.

In the first column, I want an expandable/collapsible list which allows more than one item to remain expanded and in the second column, I want only one item to be expanded at a time.
I have lifted the code from the fiddle, contained it inside a div, and placed it below my fixed header (which has a height of 200px), but when I click an item in the list it no longer scrolls to the top of the column as featured in the fiddle but instead it expands just below other expanded list as per normal
I am new to javascript, although I have read the scrollTop, offset and animate methods. I can't quite figure out how to make it work.
Could someone, please help me with my javascript? Thank you.


<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title> - jsFiddle demo</title>
<script type='text/javascript' src='http://code.jquery.com/jquery-1.11.0.js'></script>
<link rel="stylesheet" type="text/css" href="/css/result-light.css">

<style type='text/css'>
html {
height:100%;
max-height:100%;
padding:0;
margin:0;
border:0;
background:#fff;
/* hide overflow:hidden from IE5/Mac */
/* \*/
overflow: hidden;
/* */
}

body {height:100%;
max-height:100%;
overflow:hidden;
padding:0;
margin:0;
border:0;}

#head {position:absolute;
margin:0;
top:0;
left:0;
display:block;
width:100
height:200px;
background:url(fish.jpg) rgb(233,238,242);
background-repeat:no-repeat;
font-size:4em;
z-index:5;
color:#fff;}

#foot {position:absolute;
margin:0;
bottom:0;
left:0;
display:block;
width:100%;
height:50px;
background:rgb(233,238,242);
font-size:0.8em;
z-index:5;
text-align:right;
color:rgb(157,78,84);}

#stores, #abc {position:absolute;
left:0;
top:200px;
bottom:50px;
width:50%;
font-size:1em;
z-index:4;
overflow:auto;}

.details {
display: none;
}
</style>

<script type='text/javascript'>//<![CDATA[
$(window).load(function(){
$(".aro > .wrap").click(function () {
if (!$(this).parent().hasClass("active")) {

//$(".aro").removeClass("active");
$(this).parent().addClass("active");
$(this).parent().children(".details").slideDown("slow", function() {
$('html, body').animate({
scrollTop: $(this).parent().offset().top
}, 2000);
});
} else {
$(this).parent().removeClass("active");
$(this).parent().children(".details").slideUp("slow");
}
});
});//]]>

</script>
</head>
<body>
<div id="abc">
<div class="aro">
<div class="wrap">
<h2>Headline</h2>
</div>
<div class="details">
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
</div>
</div>
<div class="aro">
<div class="wrap">
<h2>Headline</h2>
</div>
<div class="details">
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
</div>
</div>
<div class="aro">
<div class="wrap">
<h2>Headline</h2>
</div>
<div class="details">
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
</div>
</div>
<div class="aro">
<div class="wrap">
<h2>Headline</h2>
</div>
<div class="details">
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
</div>
</div>
<div class="aro">
<div class="wrap">
<h2>Headline</h2>
</div>
<div class="details">
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
</div>
</div>
<div class="aro">
<div class="wrap">
<h2>Headline</h2>
</div>
<div class="details">
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
</div>
</div>
<div class="aro">
<div class="wrap">
<h2>Headline</h2>
</div>
<div class="details">
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
</div>
</div>
<div class="aro">
<div class="wrap">
<h2>Headline</h2>
</div>
<div class="details">
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
<p>Content</p>
</div>
</div>

</div>
</body>
</html>

Answers (2)

2014-10-28

Arnav Joy answers:

I think this problem is because of css not js , if you look this css line

#stores, #abc {position:absolute;

and remove position:absolute; then you will see scrolling effect works.


Jenova comments:

Hi Arnav,
Yes, if I remove the position: absolute, the scrolling effect works exactly as show in the fiddle I posted i.e. it scrolls all the way to the top of the browser window. But I need this div to be positioned in between a fixed header and fixed footer. How do I go about doing it? Thanks

2014-10-28

Rainner Lins answers:

Since you want both columns to behave differently, I converted the JS code into a jQuery plugin and made some changes to the HTML, it's on jsfiddle here: [[LINK href="http://jsfiddle.net/axrnawoh/2/"]]http://jsfiddle.net/axrnawoh/2/[[/LINK]]

You can see one column resets after you click on a header, and the other stays open, I think that is what you were asking for. This is jsfiddle, so won't be perfect, but can be improved on.

Edit: link.


Jenova comments:

Hi Rainner,
Firstly, I don't want both the #left and #right divs to be coupled together under the #content div. I wish to keep them separate as there is no relationship between them other than the fact, that when a user clicks on a link on the #right div, its corresponding description should be shown in the #left div.
Secondly, when I click the Headline in the #left div, it slides open its contents, however, the Headline and its contents does not scroll to the top of its column just like the #right div. Subsequent clicking scrolls to somewhere in the midst of the content region.
Thirdly, the scrolling on the #right div is working correctly.
Fourthly, how do I incorporate both divs in between a fixed header of height 200px and a fixed footer of height 50px and still achieve the intended scrolling effect? Thank you.


Jenova comments:

Hi,
I forgot to mention that I prefer a javascript or jquery code and not a jquery plugin. Reason being, I would like to learn javascript first before embarking on jquery plugins. But if it is not possible, I will be happy to accept any solution.
Thank you.


Rainner Lins comments:

Hi Jenova,

<blockquote>In the first column, I want an expandable/collapsible list which allows more than one item to remain expanded and in the second column, I want only one item to be expanded at a time.</blockquote>

I thought that was what you wanted. A jquery plugin is just like any other jquery code, similar to the one you were using, but it is wrapped inside a function that you can use against a set of matched elements. This is useful for applying similar functionality to different sets of elements on a page.

The way I setup the columns doesn't really matter, you can set them up any way you want as long as the list wrappers are correct (wrapper, header, contents, etc) for the javascript code to find what it needs.

Creating columns for your page content between the header and footer is not that hard, but if you want each column to stretch 100% and be scrollable, then it gets tricky. That's mostly CSS related, so I'll let you look into that. There should be some useful links on Google.

Here's an updated jsfiddle, now both columns scroll to the top but the body container is what scrolls, not the individual columns:

[[LINK href="http://jsfiddle.net/axrnawoh/4/"]]http://jsfiddle.net/axrnawoh/4/[[/LINK]]

Also, the comments I added in the JS code section should help.


Jenova comments:

Hi Rainner,
Thank you for the detailed explanation on jquery plugin. Your comments are indeed very helpful. My apologies for the misunderstanding.
Your first solution is exactly what I wanted i.e. i wanted 2 separate scrollable columns. The #right div is working as intended. However, the #left div does not scroll as expected. When you click on the first Headline, it expands its contents and moves to the top. When I scroll down and click on the second Headline, it expands its contents, but instead of scrolling the second Headline and its contents to the top of the column, it scrolls to somewhere in the middle of the contents section of the first Heading. And when you scroll further down and click on the third Headline, again it expands and scrolls somewhere to the contents section of the first Heading. This would mean, the user has to remember which heading they clicked on (since several panels may have been expanded) and then have to manually scroll to that particular heading and its contents. (which is what I am trying to avoid).

I don't want the body container to scroll. There are already several such examples on the web. But, I couldn't find an example that scrolls the clicked Heading and its contents to the top of a scrollable column which allows for more than one expanded panels to remain open.

Thank you.