0

Assuming the following code (current state can be viewed here):

function scrollTopFromEvent(evt) {
    return $(evt.target).scrollTop();
}

function scrollDirection(evt) {
    return -evt.originalEvent.wheelDelta / 120 || evt.originalEvent.detail / 3;
}

function pageNumber(previous, next) {
    return previous + next;
}

function scrollToPage(pageNumber) {
    var container = $('.parallax');
    TweenLite.to(container, 1, {
        scrollTop: container.height() * (pageNumber)
    });
}

function inRange(pageNumber) {
    var totalPages = $('.parallax').find('div[id^="group"]').length;
    return pageNumber >= 0 || pageNumber <= totalPages;
}
var scroll = $('.parallax')
    .asEventStream('mousewheel DOMMouseScroll')
    .doAction('.preventDefault').flatMap(scrollDirection);

var page = scroll
    .scan(0, pageNumber)
    .filter(inRange)
    .log()
    .onValue(scrollToPage);

I want to be able to limit the values emitted by the page stream from 0 to n, n being the totalPages (defined in the inRange method). In that particular case, there are 7 groups, so the range would be from 0 to 7

If a user scroll down to '7', and continues scrolling, no values would be emitted from the scroll stream.

Ideas?

Thanks

Olivier Clément
  • 732
  • 1
  • 7
  • 26
  • I don't understand what does not work. Why would no more values be emitted from `scroll`? There shouldn't be no more values in `page`, though. – Bergi Sep 10 '14 at 00:29

2 Answers2

2

I think what you actually want is to limit the value of scroll.scan(0, pageNumber) to a certain range, not to maintain a "virtual" scroll position and display that only when it currently is in the range.

Try

var totalPages = $('.parallax').find('div[id^=group]').length; // static, right?

function pageNumber(previous, next) {
    return Math.max(0, Math.min(totalPages, previous + next));
}

scroll.scan(0, pageNumber).onValue(scrollToPage);
Olivier Clément
  • 732
  • 1
  • 7
  • 26
Bergi
  • 513,640
  • 108
  • 821
  • 1,164
  • Thanks, definitely work (I edited your answer to inverse min and max, otherwise it would return only either -1 or +1) – Olivier Clément Sep 10 '14 at 01:53
  • Total page is indeed static, but I was wondering, what if it were not and the value would need to be dynamic? Could it be converted to a stream and use that? What would the solution look like in that case, if it's not too much to ask? – Olivier Clément Sep 10 '14 at 01:54
  • 1
    Quick guess: You'd need to do `sampleBy` and then `combine` it with the `scroll` stream, so that you get the `totalPages` as a part of `next`. – Bergi Sep 10 '14 at 02:00
  • Thanks, will try to keep that in mind - just starting playing with Bacon – Olivier Clément Sep 10 '14 at 03:03
0

These are the changes I made:

In your pageNumber function:

return previous + next >= $('.parallax__group').length ? previous : previous + next;

And in your inRange function:

return pageNumber >= 0 && pageNumber < totalPages;

Here is a fiddle containing your code with my changes.

bowheart
  • 4,340
  • 1
  • 21
  • 23
  • Thanks, your solution partially works for me. The values are indeed limited to the range, but for some reason, if you scroll up twice from 0, you'd need to scroll down three time for the value to get to 1. Accepted @bergi's solution above as it worked properly for this particular need. Thanks for your contribution! – Olivier Clément Sep 10 '14 at 01:57