Scrollbar & jQuery – event handling using waypoints

Scrollbar & jQuery – event handling using waypoints

13 56405
Scrollbar & jQuery

How to handle scrolling with jQuery. Today we continue jQuery reviews, and our article will about event handling of scrollbar. Possible you saw such feature as ajaxy loading of new information when we scroll to end of page. As example here: http://www.dzone.com/links/index.html, or in your facebook page and other websites. Interesting feature isn’t it? Or, also will possible to stick some elements when our scroll moving out necessary positions. Or, we can handle events when scroller reach defined element at our page (and, as example – load some extra content on this event). Today I will show you how to do this.

We will use new jQuery plugin – Waypoints. This small jQuery plugin allow us to perform different actions whenever we using scroller. As example – scrollint to some defined element. Firstly – lets check our prepared demo

Here are sample and downloadable package:

Live Demo

Ok, download the example files and lets start coding !


Step 1. HTML

As usual, we start with the HTML.

This is our main page code.

index.html

<link rel="stylesheet" href="css/main.css" type="text/css" media="all" />
<script src="js/jquery-1.4.4.min.js" type="text/javascript"></script>
<script src="js/waypoints.min.js" type="text/javascript"></script>
<script src="js/main.js" type="text/javascript"></script>
<div class="example">
<div id="nav-holder">
<nav id="nav">
<ul>
<li>Menu 1</li>
<li>Menu 2</li>
<li>Menu 3</li>
<li>Menu 4</li>
<li>Menu 5</li>
</ul>
</nav>
</div>
<section id="container">
<div class="post">
<h1>Post number 1</h1>
<p>A man bribes a rabbit with wicked dentures to run away with him in a sailboat via an ambulance. Bribing Koalas to remain illegally in one place. Trees anchor me in place. / Your mom drives the ambulance, but the city is farther than it appears. A man bribes a rabbit with wicked dentures to run away with him in a sailboat via an ambulance. Bribing Koalas to remain illegally in one place. Trees anchor me in place. / Your mom drives the ambulance, but the city is farther than it appears. A man bribes a rabbit with wicked dentures to run away with him in a sailboat via an ambulance. Bribing Koalas to remain illegally in one place. Trees anchor me in place. / Your mom drives the ambulance, but the city is farther than it appears.</p>
</div>
<div class="post">
<h1>Post number 2</h1>
<p>A man bribes a rabbit with wicked dentures to run away with him in a sailboat via an ambulance. Bribing Koalas to remain illegally in one place. Trees anchor me in place. / Your mom drives the ambulance, but the city is farther than it appears. A man bribes a rabbit with wicked dentures to run away with him in a sailboat via an ambulance. Bribing Koalas to remain illegally in one place. Trees anchor me in place. / Your mom drives the ambulance, but the city is farther than it appears. A man bribes a rabbit with wicked dentures to run away with him in a sailboat via an ambulance. Bribing Koalas to remain illegally in one place. Trees anchor me in place. / Your mom drives the ambulance, but the city is farther than it appears.</p>
</div>
<div class="post">
<h1>Post number 3</h1>
<p>A man bribes a rabbit with wicked dentures to run away with him in a sailboat via an ambulance. Bribing Koalas to remain illegally in one place. Trees anchor me in place. / Your mom drives the ambulance, but the city is farther than it appears. A man bribes a rabbit with wicked dentures to run away with him in a sailboat via an ambulance. Bribing Koalas to remain illegally in one place. Trees anchor me in place. / Your mom drives the ambulance, but the city is farther than it appears. A man bribes a rabbit with wicked dentures to run away with him in a sailboat via an ambulance. Bribing Koalas to remain illegally in one place. Trees anchor me in place. / Your mom drives the ambulance, but the city is farther than it appears.</p>
</div>
<div class="post" id="post4">
<h1>Post number 4</h1>
<p>A man bribes a rabbit with wicked dentures to run away with him in a sailboat via an ambulance. Bribing Koalas to remain illegally in one place. Trees anchor me in place. / Your mom drives the ambulance, but the city is farther than it appears. A man bribes a rabbit with wicked dentures to run away with him in a sailboat via an ambulance. Bribing Koalas to remain illegally in one place. Trees anchor me in place. / Your mom drives the ambulance, but the city is farther than it appears. A man bribes a rabbit with wicked dentures to run away with him in a sailboat via an ambulance. Bribing Koalas to remain illegally in one place. Trees anchor me in place. / Your mom drives the ambulance, but the city is farther than it appears.</p>
</div>
<div class="post">
<h1>Post number 5</h1>
<p>A man bribes a rabbit with wicked dentures to run away with him in a sailboat via an ambulance. Bribing Koalas to remain illegally in one place. Trees anchor me in place. / Your mom drives the ambulance, but the city is farther than it appears. A man bribes a rabbit with wicked dentures to run away with him in a sailboat via an ambulance. Bribing Koalas to remain illegally in one place. Trees anchor me in place. / Your mom drives the ambulance, but the city is farther than it appears. A man bribes a rabbit with wicked dentures to run away with him in a sailboat via an ambulance. Bribing Koalas to remain illegally in one place. Trees anchor me in place. / Your mom drives the ambulance, but the city is farther than it appears.</p>
</div>
</section>
<footer>
<ul>
<li class="more"><a href="other.php?step=1" title="Traditional navigation link">Next Page</a></li>
</ul>
<ul>
<li><a class="top" href="#" title="Back to top">Top</a></li>
</ul>
</footer>
</div>

Make attention that here we draw our navigation menu, five posts and in footer we prepared 2 elements: link to next page: other.php?step=1 and another element which will allow us to jump to top of page. By default that element will invisible (CSS).

Step 2. CSS

Here are used CSS styles.

css/main.css

body{background:#eee;font-family:Verdana, Helvetica, Arial, sans-serif;margin:0;padding:0}
.example{position:relative;background:#FFF;width:600px;border:1px #000 solid;margin:20px auto;padding:20px;-moz-border-radius:3px;-webkit-border-radius:3px}
ol, ul {
list-style: none outside none;
}
#nav-holder {
height:30px;
}
#nav ul {
width:500px;
margin:0 auto;
padding:0;
height:30px;
line-height:30px;
text-align:center;
font-size:14px;
background:#333;
color:#ddd;
}
#nav li {
display:inline;
padding:0 10px;
border-left:1px solid #555;
}
#nav li:first-child {
border-left:0;
}
.sticky #nav {
position:fixed;
top:0;
left:0;
width:100%;
}
.sticky #nav ul {
margin:0 auto;
opacity:0.8;
}
#container {
margin-bottom:16px;
}
.loading {
left:0;
bottom:0;
width:100%;
height:34px;
line-height:34px;
margin-top:-34px;
background:#222;
color:#fff;
}
.loading p {
margin:0;
text-align:center;
-webkit-animation:pulse 2s infinite;
font-weight:bold;
text-transform:uppercase;
}
.top {
position:fixed;
right:15px;
bottom:15px;
width:50px;
height:25px;
padding-top:25px;
line-height:25px;
background:#333;
color:#888;
display:block;
text-transform:uppercase;
text-decoration:none;
text-align:center;
font-size:14px;
-webkit-border-radius:10px;
-moz-border-radius:10px;
border-radius:10px;
behavior:url(../PIE.htc);
opacity:1;
-webkit-transition:opacity 700ms linear;
-moz-transition:opacity 700ms linear;
transition:opacity 700ms linear;
}
.top:before {
position:absolute;
top:11px;
left:14px;
content:"";
border-bottom:11px solid #888;
border-left:11px solid transparent;
border-right:11px solid transparent;
}
.top:hover {
color:#eee;
}
.top:hover:before {
border-bottom-color:#eee;
}
.top.hidden {
opacity:0;
}

Step 3. JS

Here are all used JS files. This is of course jQuery library itself + our new plugin:

js/jquery-1.4.4.min.js and js/waypoints.min.js

js/main.js

$(document).ready(function() {
// Blink fast when we reached this element (post number 4)
$('#post4').waypoint(function() {
$(this).fadeOut(300).fadeIn(300);
}, {
offset: '50%',  // middle of the page
triggerOnce: true
});
// ajaxy content
var $loading = $("<div class='loading'><p>Loading more items ...</p></div>"),
$footer = $('footer'),
opts = {
offset: '100%'
};
$footer.waypoint(function(event, direction) {
$footer.waypoint('remove');
$('.example').append($loading);
$.get($('.more a').attr('href'), function(data) {
var $data = $(data);
$('#container').append($data.find('.post'));
$loading.detach();
if ($data.find('.more').length) {
$('.more').replaceWith($data.find('.more'));
$footer.waypoint(opts);
} else {
$('.more').parent().remove();
}
});
}, opts);
// nav menu
$('#nav-holder').waypoint(function(event, direction) {
$(this).parent().toggleClass('sticky', direction === "down");
event.stopPropagation();
});
// goto 'Top' button
$('.top').addClass('hidden');
$.waypoints.settings.scrollThrottle = 25;
$('.example').waypoint(function(event, direction) {
$('.top').toggleClass('hidden', direction === "up");
}, {
offset: '-100%'
});
});

This is most interesting and important part of our project. Firstly I should to show you format of initialization of waypoints plugin. By default this is:

$('some_element').waypoint([handler], [options]);

Both params – optional, here are from documentation:

  • handler — function, optional param, – callback function called when the user scrolls past the element. The function signature is function(event, direction), where ‘event’ is a usual jQuery event object and ‘direction’ is a string, either ‘down’ or ‘up’ indicating which direction the user is scrolling.
  • options — object, optional param, – map of options to apply to this set of waypoints, including where on the browser window the waypoint is triggered.

Now lets look to our most easy sample – where we will blink post (once) when the we scrolls to this element (at middle of page):

$('#post4').waypoint(function() {
$(this).fadeOut(300).fadeIn(300);
}, {
offset: '50%',  // middle of the page
triggerOnce: true
});

So, I created waypoint to element ‘#post4’, and handling event – scrolling to this element when it located at middle of page. This post should blink once (triggerOnce = true).

Another one sample – loading new posts when we reach end of page:

var $loading = $("<div class='loading'><p>Loading more items ...</p></div>"),
$footer = $('footer'),
opts = {
offset: '100%'
};
$footer.waypoint(function(event, direction) {
$footer.waypoint('remove');
$('.example').append($loading);
$.get($('.more a').attr('href'), function(data) {
var $data = $(data);
$('#container').append($data.find('.post'));
$loading.detach();
if ($data.find('.more').length) {
$('.more').replaceWith($data.find('.more'));
$footer.waypoint(opts);
} else {
$('.more').parent().remove();
}
});
}, opts);

As you can see, firstly I defined new loading element, options for waypoint. And, when we reached the bottom of the page I removing current waypoint, draw loading element, loading via $.get new content from my other.php, adding new posts, removing loading element, updating link to More, and, re-create waypoint again (for new positions). So, now its time to check our other.php file

Step 4. PHP

other.php

<?
$iStep = (int)$_GET['step'];
$aPosts[] = <<<EOF
<div class="post">
<h1>Post number 6 (loaded ajaxy)</h1>
<p>A man bribes a rabbit with wicked dentures to run away with him in a sailboat via an ambulance. Bribing Koalas to remain illegally in one place. Trees anchor me in place. / Your mom drives the ambulance, but the city is farther than it appears.</p>
<p>A man bribes a rabbit with wicked dentures to run away with him in a sailboat via an ambulance. Bribing Koalas to remain illegally in one place. Trees anchor me in place. / Your mom drives the ambulance, but the city is farther than it appears.</p>
</div>
EOF;
$aPosts[] = <<<EOF
<div class="post">
<h1>Post number 7 (loaded ajaxy)</h1>
<p>A man bribes a rabbit with wicked dentures to run away with him in a sailboat via an ambulance. Bribing Koalas to remain illegally in one place. Trees anchor me in place. / Your mom drives the ambulance, but the city is farther than it appears.</p>
<p>A man bribes a rabbit with wicked dentures to run away with him in a sailboat via an ambulance. Bribing Koalas to remain illegally in one place. Trees anchor me in place. / Your mom drives the ambulance, but the city is farther than it appears.</p>
</div>
EOF;
$aPosts[] = <<<EOF
<div class="post">
<h1>Post number 8 (loaded ajaxy)</h1>
<p>A man bribes a rabbit with wicked dentures to run away with him in a sailboat via an ambulance. Bribing Koalas to remain illegally in one place. Trees anchor me in place. / Your mom drives the ambulance, but the city is farther than it appears.</p>
<p>A man bribes a rabbit with wicked dentures to run away with him in a sailboat via an ambulance. Bribing Koalas to remain illegally in one place. Trees anchor me in place. / Your mom drives the ambulance, but the city is farther than it appears.</p>
</div>
EOF;
$aPosts[] = <<<EOF
<div class="post">
<h1>Post number 9 (loaded ajaxy)</h1>
<p>A man bribes a rabbit with wicked dentures to run away with him in a sailboat via an ambulance. Bribing Koalas to remain illegally in one place. Trees anchor me in place. / Your mom drives the ambulance, but the city is farther than it appears.</p>
<p>A man bribes a rabbit with wicked dentures to run away with him in a sailboat via an ambulance. Bribing Koalas to remain illegally in one place. Trees anchor me in place. / Your mom drives the ambulance, but the city is farther than it appears.</p>
</div>
EOF;
$i = ($iStep > 0)  ? ($iStep-1) : 0;
if (count($aPosts) > $i) {
echo '<div class="results">';
echo $aPosts[$i];
if (count($aPosts) > $iStep) {
echo '<div class="more"><a href="other.php?step=' . ($iStep + 1) . '">Next Page</a></div>';
}
echo '</div>';
}
?>

In begining – I defined array of all posts (sure that in your project anything will in database). After, depends on accepted param ‘step’ we will draw necessary result, plus – link new updated link to another results (other.php?step=2, other.php?step=3 etc)


Here are continue of documentation. Functions and options of waypoint:

  • $(‘some_element’).waypoint(‘destroy’) – this function will fully unregister current waypoint, unbind all waypoint event handlers.
  • $(‘some_element’).waypoint(‘remove’) – this function will unregisters the elements as waypoints and wipes any custom options, but leaves the ‘waypoint.reached’ events bound. Calling ‘$(‘some_element’).waypoint’ again in the future would re-register the waypoint and the old handlers would continue to work.
  • $(‘some_element’).waypoint.defaults – default options of object that is extended when calling ‘.waypoint’. It have next properties:
    • offset — number | string | function (default: 0), – tell us how far the top of the element must be from the top of the browser window to trigger waypoint. It can be a number, which is taken as a number of pixels, a string representing a percentage of the viewport height, or a function that will return a number of pixels. Example – offset: ‘100%’
    • triggerOnce — boolean (default: false), – if true, the waypoint will be destroyed when triggered.

Also we can perform work with all created waypoints. All waypoints registered through $.waypoints(). Here are possible functions and options:

  • $.waypoints(‘refresh’) – that function will perform recalculation of all waypoint`s trigger point based on its offset value. By default this called automatically (whenever the window is resized, new waypoints are added, or a waypoint’s options are modified). If your project is changing the DOM structure or page layout without doing one of these things, you may want to manually call this refresh.
  • $.waypoints(‘viewportHeight’) – that function will return the height of the viewport, adjusting for inconsistencies that come with calling ‘$(window).height()’ in iOS. Recommended for use within any offset functions.
  • $.waypoints.settings – settings, which determine some of the plugin`s behavior:
    • continuous — boolean (default: true), – determines which waypoints to trigger events for if a single scroll change passes more than one waypoint. If false, only the last waypoint is triggered and the rest are ignored. If true, all waypoints between the previous scroll position and the new one are triggered in order.
    • resizeThrottle — number (default: 200), – the refresh performed during window resizes is throttled. This value is the rate-limit in milliseconds between resize refreshes.
    • scrollThrottle — number (default: 100), – checking for any crossed waypoints during the window scroll event is throttled. This value is the rate-limit in milliseconds between scroll checks. (You can notice that we already using ‘scrollThrottle’ in our sample)

Live Demo

Conclusion

Today we review new interesting jQuery plugin which can enhance user interface of your website. If is you were wondering – do not forget to thank. I would be grateful for your interesting comments. Good luck!

SIMILAR ARTICLES

jQuery Mobile Lesson 6

0 10
jQuery Mobile Lesson 5

0 170

13 COMMENTS

  1. Hello, thank you for your tutorial.
    Element Div “Back to Top”, show for one second
    when page loading. Please have you any advice?

    • Hello, you can modify our
      <a class="top" href="#" title="Back to top">Top</a>
      to
      <a class="top" href="#" title="Back to top" style="opacity:0">Top</a>
      as example.
      This hint will hide this element in time when page loading

  2. Hi, can you help me i wanna add offset on navigation:

    $(‘#nav-holder’).waypoint(function(event, direction) {
    $(this).parent().toggleClass(‘sticky’, direction === “down”);
    event.stopPropagation();
    });

    i don’t wanna navigation reach top of the screen, i wanna to stop about 70px till top

    • Hi Michael,
      Hum, you don’t need to change JS, but, try to customize CSS:
      .sticky #nav {
      left: 0;
      position: fixed;
      top: 70px;
      width: 100%;
      }

      as example

  3. Hello, thanks a lot for the excellent tutorial. May i use this plugin within a defined block? (Width:500px; height:600px;)
    And can you help me with my query? In php file i use like this query to select blocks, but should I save my data in array before showing ?

    f($f = $mysqli->prepare(” SELECT city, title, desc, date FROM articles”))
    { $f->execute();
    $f->bind_result( $city, $title, $desc, $date);
    while ($f->fetch())
    {
    echo ” {$city}…. “;
    // So I didn’t understand how to view selected data from DB

    }
    }

    So i coundn’t figured out how to do this. I would appreciate any pointers, I’m sure other people will find this useful as well.
    Thanks for any help. :)

    • Hello Refresh,
      It doesn’t matter where you use it, you can use it everywhere.
      And, it is not so necessary to use arrays in your case. Basically, you just have to echo your results (you also can wrap it (<div class="results">) and put link to next page).

  4. I did the query, thanks a lot , but i want do load data by ten. While i’m scrolling, it’s loading 1 article. So any suggestions ?

  5. Hello,
    I’m rather new to the web development environment, and I was wondering which part of the code is for the static navbar at the top. I’ve been trying to get something like this for quite a while and I’m kinda stumped.

    Thanks in advance!

  6. Hi
    I’m getting
    TypeError: event.stopPropagation is not a function
    when I run your demo locally (I’m runnign XAMPP). When the waypoint fires it only loads posts 8 and 9 . Post 8 ends with EOF; $aPosts[] = < 0) ? ($iStep-1) : 0; if (count($aPosts) > $i) { echo ”; } ?>

    I’d appreciate any thoughts.
    Regards

  7. By the way, I had to change
    $footer.waypoint(‘remove’);
    to
    $footer.waypoint(‘destroy’);
    because I was getting the error
    Error: The remove method does not exist in jQuery Waypoints.

    • Hi Mike,
      Did you try to update the version of libraries? I haven’t tested it with the most fresh versions, but at the time I developed it – it worked without any problems.

Leave a Reply