Endless scroll implementation
When there are many things to load it is best to always think about how to approach it and the best bet at how to do it right is to look at how others did it - big ones.
So Facebook, Twitter are just 2 of many where we can see endless scroll in action, however why did they do it?
Imagine if you were to log into Facebook and it was loading everything you missed since the last time you had logged in. If you have even a small number of friends, chances are that your scroll would become tiny and you would wait a ton of time for the page to finish loading.
So endless scroll comes into play and boom - everything is fast. The simple truth is that content within the "headline" or "above the fold" section is what matters right away, and everything else matters after it. So with endless scroll we decide what is the headline section and how much we want to show in it and then what is the lower importance content.
Once we know this we know how large the section that we want to break the things into will be.
Now while this is about the videos and how you can utilize index() function from our API the same approach can actually be used for all of the different things, regardless what they are, so lets dive in..
Decide which are important factors
Each project has these. We need to know what is the important factor and all of the ones that we have as knowing it as we start will help us finish the project faster and make it look more professional.
- how many videos will we load each time through index function?
- how many videos do we want to show on a page at single time?
- Will we be showing all of the videos or just some?
- how will we show the videos - one under the other, grid or just throw them there and see how it looks.
- will we do endless scroll automatically or have a button to load more manually, or add the button after some time as Google Images is made.
- What do we want to do while the videos are being retrieved and shown - show a progress bar of sorts, or just show the embeddings
- what happens when there are no more videos?
Build decision based on important factors
1. How many videos to load
We can easily load 100 videos from Ziggeo servers. This is fast and easy and while that is not the default value for the index() function we make just a slight change for this - this is also the maximum number of video details that we can grab at one time. We will however stick to 10 videos at a time to show how the requests are made.
2. How many videos to show at once
Now this is the important one. 5 videos seemed as a nice number, however during tests 10 like a nice count to actually create a scroll and make it load videos as we scroll down further, so for this post, we are picking 10 as our initial count and as every interval during which we show the videos.
This is preferred way for many reasons - we could add analytics to indicate that additional videos have been loaded, it would work if you have smaller number of videos in your account just as for larger, quicker load times and finally the person sitting in front of the screen will not start wondering why the scroll bar got so big all of a sudden.
3. Which videos will we show
If we want to get all videos, that is easy and default - however if we wanted to show some specific videos - such as those from some event for which we tagged our videos as "event2017", we could do that easily - just use tags. In our case, we will load all of the videos for simplicity reasons.
4. Presentation
It would be neat to make the videos fall in line, however for simplicity reasons, so that we show only relevant codes so it is easy to follow, lets just add them one after another.
5. automated vs manual endless scroll
Many people like when doors open before they come into the store, and the same can be applied with videos, it seems much nicer if videos got loaded as you scroll the page, so fully automated seems the best way to go. If you are interested in button implementation as well - well contact us and we can follow up with another article covering that approach as well ;)
6. Progress bar or not?
Progress bar is a great way to let person waiting know that something is being done. For us, that is not needed since we will load the required data upfront and just show the embeddings using the same when needed so for most people that would be quite fast. Still it is good to be considered for the best UX.
7. When we reach the end
We have multiple choices such as showing a message that there are no videos, or showing a recorder to make it easy to add new video, and for this approach lets just show the message in the console. Of course we can easily change this part to show the message on the page itself instead.
Into the build
The first function that we will use is the index() function of our JavaScript API. Lucky for you we have plenty more SDKs that of course, have the same functionality. You can check them all on our SKDs page.
ZiggeoApi.Videos.index(data, [callbacks])
For us, that will look like so:
ZiggeoApi.Videos.index( 'limit=10', {
success: function (args, data) {
console.log('This was the data that we got back when searching for ' +
args + ':' + JSON.stringify(data) );
},
failure: function (args, error) {
console.log('This was the error that we got back when searching for ' +
args + ':' + error);
}
});
OK, so at this time we have found index() function that will tell us info on the videos from our application at that one call. Now we need to add the code that will capture this data and show the videos based on the results.
To do that we will change the above to actually grab the data and to call the function that will do the endless scroll update for us
var last_video_index = 0; //we need to know what is the last index that we got,
// otherwise we would always get the same videos for
// our list..
var index_processing = false; //are we already loading new set of videos or not
function indexVideos() {
ZiggeoApi.Videos.index( 'limit=10&skip=' + last_video_index, {
success: function (args, data) {
if(data.length > 0) {
addVideosToPage(data);
//we now update the last_video_index to point to the number of videos
// that we got:
last_video_index += data.length;
index_processing = false;
}
else {
//no results
console.log('No videos found matching the requested:' + args);
}
},
failure: function (args, error) {
console.log('This was the error that we got back when searching for ' +
args + ':' + error);
}
});
}
Now the addVideosToPage() function will help us set the part of endless scroll where we add the data to page and for the endless scroll implementation it is not important that this follows any specific pattern - or to say it differently anything goes for it so design it to match your incoming data and desired output. As you can see in the code above, we pass it the data that we should go through to grab all of the video tokens, which is all we really need with Ziggeo.
In our case, this will look like this:
function addVideosToPage(videos_list) {
//we go through each of the videos in the list.
// In general it is always good to make a check here (again)
// so if you happen to call this from some new functions or
// events on your page, we still check if we have anything to work with.
if(videos_list && videos_list.length > 0) {
//now we know that all is good
//Now on the page we would need to know into which element
// we want to add new videos to, or if you are making another
// type of the endless scroll, what ever you would be adding
// would need to go to some element. Best would be to have
// that element marked with some ID, as IDs should be unique
// on the page, so lets grab the reference to it
var wall_of_videos = document.getElementById('wallOfVideos');
//in jQuery this would be $("#wallOfVideos"); for element such as <div id="wallOfVideos">
//so we will walk through each of the items on the list
for(i = 0; i < videos_list.length; i++) {
//This is where the biggest mistake can happen when
// implementing the endless scroll and we will cover it after the code sample
var video_element = document.createElement('div');
//if we want to specify something for our element,
// like class, id, etc we could do that now
video_element.className = "videos";
wall_of_videos.appendChild(video_element);
var player = new ZiggeoApi.V2.Player({
element: video_element,
attrs: {
width: 640,
height: 480,
video: videos_list[i].token
}
});
player.activate();
}
}
}
Now if you look above in the code, we mention a place in for() loop where the biggest mistake could be made for endless scroll implementation. Do you know what it is? Yes, of course you do, however sometimes it is easy to slip our mind - that is the ease of using innerHTML.
It is OK if we would to use it for the first time only when we create some element, however if we do it when a new video has been added to already existing list, that could potentially cause a lot of bugs later on. The key emphasis being events and DOM.
If you were to use the innerHTML after the data was already present, all of the events in there would have been recreated. So if your code had been running or depending on some event and values from the same, it is likely that there would be some strange things happening, and that is why we are always adding a new element to the list, attaching events only for it.
Another point here, and this depends on the specific endless scroll implementation is that you could very well be causing a lot of slowness to your page each time you do that. This would happen because at the same moment you would:
- break all events, so browsers will try to 'close' each of them down properly
- create a ton of new events (for elements that were there before and for new ones)
- if your elements do any type of loading of "out of page" resources, that would add to the time it is needed to be processed.
- of course by creating new elements and attaching them, you are successfully implementing everything without a need to worry for the above.
Now another part of the for() loop is that we can use a newer approach and write it like so (for those that like to feel adventurous):
for(i = 0; i < videos_list.length; i++) {
//instead of creating new element we use insertAdjacentHTML();
var video_template = '<ziggeoplayer ziggeo-width="640" ziggeo-height="480"' +
' ziggeo-video="' + videos_list[i].token + '"></ziggeoplayer>";
wall_of_videos.insertAdjacentHTML('beforeend', video_template);
}
As you can see this is a bit shorter method and allows you to add HTML so if you are using AJAX for example which returns HTML that you want to add to the page right away, this might be the best way to do it, while if you are going to be doing some processing or need to make your own changes on fly, the first approach would be recommended instead.
At this time we have set up the call to get the list of videos and the callback handler so that we capture the response and add all of the videos to the page. So far so good and now all we need is to add the callback for more videos per the scroll action.
Scroll detection
Here, it is important to pick which element is the one who's scroll and height you are interested in. For example, when we were adding this to our WordPress plugin, the point of interest was to see the scroll position based on the video wall template, not on the page itself. The reason for this is that video wall (a lot of videos one following another) can be just few percent of the entire page, so checking if someone went to the bottom of the page, might mean that someone was already way past the video wall and looking at something else.
So you need to find the actual element that is best for your implementation. For reference only, if you are making something like Facebook or Twitter, obvious choice would be the end of the page, while if this is for some sidebar, then `it` should be the focus.
The first thing to do is to attach an event that will tell us when scrolling happens:
(document.addEventListener) ? ( window.addEventListener('scroll', ourEndlessScroll, false) ) :
(window.attachEvent( 'onscroll', ourEndlessScroll) );
- This line checks if we should use addEventListener() which is used by all browsers, or if we should use attachEvent() instead, which is of course used by older IE browsers.
Of course we could add this to monitor specific elements as well, depending on the implementation. In our case, we are monitoring the scroll action on entire page, however basing our actions on the position of screen compared to the videos.
Now this scroll event will call ourEndlessScroll() function each time a scroll happens, so lets jump to the function that will do the actual work
function ourEndlessScroll() {
//we check if we are already processing new videos so that we do not call
// the same function multiple times.
if(index_processing === true) {
return false;
}
var wall_of_videos = document.getElementById('wallOfVideos');
//if there is no video wall for some reason, lets just stop
// listening to the scroll event - it is not needed any more
// in our case however removing this will make it work for you
// - if your implementation is like that so that this is interesting to you.
if(!wall_of_videos) {
(document.removeEventListener) ? (window.removeEventListener( 'scroll', ziggeo_endlessScroll )) :
(window.detachEvent( 'onscroll', ziggeo_endlessScroll));
return false;
}
//lets check where we are in terms of position
if(wall_of_videos.getBoundingClientRect().bottom <=
(wall_of_videos.getBoundingClientRect().height * 0.20 )) {
//we are checking if we are at the 80% of the total height of the video wall.
// The reason why we use 0.20 is the difference
index_processing = true; //make the lock
//now lets call the index function to grab new videos.
indexVideos();
}
}
And that is it, all done and ready. Of course this is just the basic implementation, you could add various things to it. In our WordPress plugin for example we are limiting how many videos we will show at one go, so we keep a cache of previously retrieved video tokens and check against that as well and your implementation might have some other logic applied next to it, however that is easy to add on top of the code above.
And how does the code run? Easy! You just add this last part to the same, after all the other code:
//Now we just initiate the indexing..
indexVideos();
Now we also have entire code on our blog post where you can grab it from.
Do you have some tips or tricks on how you implemented the same? Do contact us, we would love to hear all about it.
Tips:
- getBoundingClientRect() function gives access to different values like bottom, top, height, width, left, right and few other values of interest
- window.pageYOffset - while we did not use it, it is good if you are implementing the endless scroll for entire page
Please sign in to leave a comment.
Comments
0 comments