Reputation: 3082
I have a modal which I am using for alphabetical searching. Along the top, there is a horizontal bar with A-Z buttons. I want each of these buttons to scroll the div (with overflow:auto) to the appropriate letter.
Eg if the user clicks "G", it will scroll the div down to the G results.
I would like to set these onclicks with js or jquery. Here's what I have so far:
$('.search__strip__letter').each(function () {
var number = $(this).data('letter');
$(this).click(function () {
var target = '#search__results__letter--'+number;
$('.search-results').animate({scrollTop:$(target).position().top}, 200);
})
})
Why isn't this working...?
EDIT: Here's a fiddle.
Upvotes: 0
Views: 836
Reputation: 490
Added clearfix class on floated elements, updated jquery selector spelling Fixed here.
$('.search__strip__letter').each(function () {
var number = $(this).data('letter');
$(this).click(function () {
console.log('click');
var target = '#search__results__letter--' + number;
console.log(target,$('.search-results'));
$('.search-results').animate({
scrollTop: $(target).offset().top + 100
}, 200);
})
})
http://jsfiddle.net/Aerious/z17nyh2s/8/
Upvotes: 3
Reputation: 11725
UPDATE
You should be using $(target).offset().top
, it works independent of the style's position
property.
You must scrollTop
to 0
and subtract the .search-results
offset's top, also.
UPDATE II
If you want to animate for both sides, instead of scrollingTop to 0
, you must get the current scrollTop and sum it, take a look below:
[].forEach.call('ABCDEFGHIJKLMNOPQRSTUVWXYZ', function(l, i) {
var a = document.createElement('a');
a.textContent = l;
a.addEventListener('click', function(e) {
var target = '#search__results__letter--' + i;
var now = $('.search-results').scrollTop();
$('.search-results').animate({ scrollTop: $(target).offset().top - $('.search-results').offset().top + now }, 200);
});
document.getElementById('letters').appendChild(a);
var div = document.createElement('div');
div.id = 'search__results__letter--' + i;
div.textContent = 'Letter ' + l;
document.querySelector('.search-results').appendChild(div);
});
#letters a {
display: inline-block;
width: 25px;
height: 25px;
background-color: darkblue;
margin: 2px;
line-height: 25px;
text-align: center;
color: white;
font-family: Verdana;
cursor: pointer;
}
.search-results {
height: 120px;
overflow-y: auto;
}
.search-results div {
height: 100px;
background-color: aqua;
margin: 2px;
font-family: Verdana;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="letters">
</div>
<div class="search-results">
</div>
Upvotes: 0
Reputation: 78520
You need a couple modifications to your code to make it work as I understand it. First, you need to give the .search-results
element some context. You do this by adding position:relative
to that element. Now that it's the relative parent of your search__results__letter--*
elements, you can scroll to them with your animate snippet. However, you also need to calculate the scroll position relative to the offset scroll of the parent. Simple math will handle that part by first getting the scroll position of the search__results__letter--*
element and adding it to the scrollTop()
of .search-results
. You can see this method in the demo code below:
$('.search__strip__letter').each(function () {
var number = $(this).data('letter');
$(this).on('click', function () {
var target = '#search__results__letter--'+number;
var currentPosition = $('.search-results').scrollTop();
$('.search-results').animate({scrollTop:currentPosition + $(target).position().top}, 200);
})
})
.search-results {
border: 1px solid;
height: 100px;
overflow: auto;
position: relative;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li><a href="#" class="search__strip__letter" data-letter="A">A</a></li>
<li><a href="#" class="search__strip__letter" data-letter="B">B</a></li>
<li><a href="#" class="search__strip__letter" data-letter="C">C</a></li>
<li><a href="#" class="search__strip__letter" data-letter="D">D</a></li>
<li><a href="#" class="search__strip__letter" data-letter="E">E</a></li>
<li><a href="#" class="search__strip__letter" data-letter="F">F</a></li>
</ul>
<div class="search-results">
<p id="search__results__letter--A">Search Results A</p>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<p id="search__results__letter--B">Search Results B</p>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<p id="search__results__letter--C">Search Results C</p>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<p id="search__results__letter--D">Search Results D</p>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<p id="search__results__letter--E">Search Results E</p>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<p id="search__results__letter--F">Search Results F</p>
</div>
I've adapted the original poster's fiddle using my code. One addition I had to make was to force the .search__results__letter
back into flow by making a new block formatting context on that class. I did this by adding display:inline-block;width:100%;
Adding overflow:hidden;
or overflow:auto;
should also accomplish the same thing. Also, see MDN docs on block formatting context for other methods to force it.
https://jsfiddle.net/gLpvzgu5/
Upvotes: 0
Reputation: 1259
I suggest you use the jquery.scrollTo plugin. It's highly customizable, supports animations and is very easy to use. You just need to replace your animate
code with something like this:
$('.search-results').scrollTo($(target), 200);
Upvotes: 0