Skip to content

Commit

Permalink
Merge pull request #5 from wallacode/develop
Browse files Browse the repository at this point in the history
v2.0.0
  • Loading branch information
shotap committed May 8, 2016
2 parents 87029cf + a2d078c commit 1bd37fb
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 82 deletions.
15 changes: 11 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ var lazy = new Snorlax({
});
```

## Buckets
We work with the principles of [Bucket sort](https://en.wikipedia.org/wiki/Bucket_sort) that works in ```O(n)```.
We divide the screen into buckets according to the ```bucketSize``` param, in each iteration we show a specific bucket and the buffer buckets according to the ```bucketBuffer``` param.

## Callbacks
We have 2 kinds of callbacks: show callbacks ans scroll callbacks

Expand Down Expand Up @@ -93,21 +97,24 @@ var lazy = new Snorlax({
## Options
```javascript
var lazy = new Snorlax({
threshold: 100,
bucketSize: 400,
bucketBuffer: 1,
attrPrefix: 'data-snorlax',
cssClassPrefix: 'snorlax',
scrollDelta: 0,
event: 'scroll',
horizontal: true,
wrap: 'demo'
wrap: 'demo',
scrollCB: [],
showCB: []
});
```
Name | Default | Description
--------------------|----------------|-------------------
threshold | 400 | number of pixels to load the image
bucketSize | 400 | height of each bucket
bucketBuffer | 1 | buffer of how much buckets before and after we should load
attrPrefix | 'data-snorlax' | prefix for the attrs on the html
cssClassPrefix | 'snorlax' | prefix for the css classes
scrollDelta | 100 | (px) the interval for the scroll event, 0 for every scroll event
event | 'scroll' | which event will trigger the loading
horizontal | false | will set the lazy loader to work horizontaly
wrap | '' | ID of the wrapper of the horizontal scroll, in the most of the times it will be a UL ID
Expand Down
14 changes: 3 additions & 11 deletions demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,28 +24,20 @@
<div class="snorlax" data-snorlax-alt="bla" data-snorlax-src="http://www.walla.co.il/images/apple/common-color-2.png"></div>
<div class="snorlax" data-snorlax-alt="bla" data-snorlax-src="http://www.walla.co.il/images/apple/common-color-3.png"></div>
<div class="snorlax" data-snorlax-alt="bla" data-snorlax-src="http://www.walla.co.il/images/apple/common-color-4.png"></div>
<div class="snorlax" data-snorlax-cb="a" data-snorlax-alt="bla" data-snorlax-src="http://www.walla.co.il/images/apple/common-color-5.png"></div>
<div class="snorlax" data-snorlax-alt="bla" data-snorlax-src="http://www.walla.co.il/images/apple/common-color-5.png"></div>
<div class="snorlax" data-snorlax-alt="bla" data-snorlax-src="http://www.walla.co.il/images/apple/common-color-6.png"></div>
<div class="snorlax" data-snorlax-alt="bla" data-snorlax-src="http://www.walla.co.il/images/apple/common-color-7.png"></div>
<div class="snorlax" data-snorlax-alt="bla" data-snorlax-src="http://www.walla.co.il/images/apple/common-color-8.png"></div>
<div class="snorlax" data-snorlax-alt="bla" data-snorlax-src="http://www.walla.co.il/images/apple/common-color-9.png"></div>
<div class="snorlax" data-snorlax-alt="bla" data-snorlax-src="http://www.walla.co.il/images/apple/common-color-10.png"></div>
<div class="snorlax" data-snorlax-cb="b" data-snorlax-alt="bla" data-snorlax-src="http://www.walla.co.il/images/apple/common-color-11.png"></div>
<div class="snorlax" data-snorlax-alt="bla" data-snorlax-src="http://www.walla.co.il/images/apple/common-color-11.png"></div>
<div class="snorlax" data-snorlax-alt="bla" data-snorlax-src="http://www.walla.co.il/images/apple/common-color-12.png"></div>
<div class="snorlax" data-snorlax-alt="bla" data-snorlax-src="http://www.walla.co.il/images/apple/common-color-13.png"></div>
<!-- <div class="snorlax" data-snorlax-src="http://www.walla.co.il"></div> -->

<script src="../src/snorlax.js"></script>
<script>
var lazy = new Snorlax({
showCB: {
'a': function(){ alert('A'); },
'b': function(){ alert('B'); }
},
scrollCB: [
function(x){ console.log(x); }
]
});
var lazy = new Snorlax({});

document.getElementsByClassName('loadAll')[0].onclick = function(){
lazy.loadAll();
Expand Down
128 changes: 62 additions & 66 deletions src/snorlax.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,34 +23,35 @@
*/
q = [],

/**
* view buckets
* @type {Array}
*/
buckets = [],

/**
* default config
* @type {Object}
*/
config = {
threshold: 600,
bucketSize : 400,
bucketBuffer: 1,
attrPrefix: 'data-snorlax',
cssClassPrefix: 'snorlax',
scrollDelta: 600,
event: 'scroll',
horizontal: false,
wrap: '',
scrollCB: [],
showCB: []
},

/**
* current position of the HEAD in the search scope
* @type {number}
*/
HEAD = 0,

isOn = true
;
/**
* @constructor
*/
_.Snorlax = function(_config) {

// Custom config
if (_config){
this.refreshConfig(_config);
Expand All @@ -67,13 +68,15 @@
for (var i = 0; i < q.length; i++)
q[i] = __getObjectFromHTMLCollection(q[i]);

__bucketSortElements(q);

var lastScroll = __getDocumentBottomScroll();

var action = function() {
var t = __getDocumentBottomScroll();
__runCallbacks(config.scrollCB, {'current': t, 'prev': lastScroll});

if (Math.abs(t - lastScroll) >= config.scrollDelta) {
if (Math.abs(t - lastScroll) >= config.bucketSize * config.bucketBuffer) {
lastScroll = t;
__load();
}
Expand Down Expand Up @@ -104,9 +107,9 @@
* Load all the objects
*/
_.Snorlax.prototype.loadAll = function(){
for(;q.length;){
__show(q[0]);
q.shift();
for(;buckets.length;){
__showBucket(buckets[0]);
buckets.shift();
}
};

Expand Down Expand Up @@ -148,7 +151,7 @@
* abstract add cb
* @param cb the callbacl to add
* @param cbDestination the destination array
* @returns the final destination
* @returns * the final destination
* @private
*/
function __addCB(cb, cbDestination){
Expand All @@ -164,33 +167,21 @@
* @private
*/
function __load(scroll){
HEAD = HEAD || __findInitialHead();

for(;isOn && q.length;){
for(;isOn && buckets.length;){
if (!config.horizontal) {
var upperbound = __getDocumentTopScroll() - config.threshold;
var lowerbound = __getDocumentBottomScroll() + config.threshold;

__updateEdgePosition(HEAD);
__updateEdgePosition(HEAD-1);

if (q[HEAD].top > upperbound && q[HEAD].bottom < lowerbound) {
__show(q[HEAD]);
q.splice(HEAD,1);
var topBucket = Math.max(Math.floor(__getDocumentTopScroll() / config.bucketSize) - config.bucketBuffer,0);
var bottomBucket = Math.min(Math.ceil(__getDocumentBottomScroll() / config.bucketSize) + config.bucketBuffer,buckets.length-1);

if (HEAD > q.length - 1 ) {
HEAD--;
for (var i=topBucket; i<bottomBucket; i++) {
if (!buckets[i].loaded) {
__showBucket(buckets[i]);
}
} else if (HEAD > 0 && q[HEAD-1].top > upperbound && q[HEAD-1].bottom < lowerbound) {
__show(q[HEAD - 1]);
q.splice(HEAD - 1, 1);
HEAD--;
} else {
return;
}

return;
}
else {
__updateEdgePosition();
if (q[0].left - config.threshold < scroll) {
__show(q[0]);
q.shift();
Expand Down Expand Up @@ -288,7 +279,8 @@
src : HTMLitem.getAttribute(config.attrPrefix + '-src'),
alt : HTMLitem.getAttribute(config.attrPrefix + '-alt'),
cb : HTMLitem.getAttribute(config.attrPrefix + '-cb'),
type : /^https?:\/\/(?:[a-z\-]+\.)+[a-z]{2,6}(?:\/[^\/#?]+)+\.(?:jpe?g|gif|png)$/i.test(HTMLitem.getAttribute(config.attrPrefix + '-src')) ? 'img' : 'iframe'
type : /^https?:\/\/(?:[a-z\-]+\.)+[a-z]{2,6}(?:\/[^\/#?]+)+\.(?:jpe?g|gif|png)$/i.test(HTMLitem.getAttribute(config.attrPrefix + '-src')) ? 'img' : 'iframe',
loaded : false
};
}

Expand Down Expand Up @@ -372,42 +364,11 @@
};
}

/**
* update the position of the item in the i'th position
* @param i
* @private
*/
function __updateEdgePosition(i) {
i = i || HEAD;

if (q.length && i > -1 && q.length > i) {
q[i].top = q[i].el.getBoundingClientRect().top + __getDocumentTopScroll();
q[i].left = q[i].el.getBoundingClientRect().left;
}
}

/**
* calc the inital position of the HEAD
*
* @returns {number}
* @private
*/
function __findInitialHead(){
var t = __getDocumentTopScroll();

for (var i = 0; i < q.length; i++) {
if (q[i].top > t)
return i;
}
return q.length - 1;
}

/**
* run custom added callbacks.
*
* @param cb
* @param position
* @param lastScroll
* @param params
* @private
*/
function __runCallbacks(cb, params) {
Expand All @@ -429,4 +390,39 @@
}
}

function __bucketSortElements(q) {
var body = document.body,
html = document.documentElement;

var height = Math.max( body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight );

var numOfBuckets = Math.ceil(height / config.bucketSize);

for (var i=0; i<numOfBuckets; i++) {
buckets[i] = {
_id: i,
loaded : false,
elements : []
};
}

for (var i=0; i<q.length; i++) {
var startBucket = Math.floor(q[i].top / config.bucketSize);
var endBucket = Math.ceil((q[i].bottom - q[i].top) / config.bucketSize);
for (var j = startBucket; j < startBucket + endBucket; j++) {
buckets[j].elements.push(q[i]);
}
}
}

function __showBucket(bucket) {
for (var i=0; i<bucket.elements.length; i++) {
if (!bucket.elements[i].loaded) {
__show(bucket.elements[i]);
bucket.elements[i].loaded = true;
}
}
bucket.loaded = true;
}

}(window));
2 changes: 1 addition & 1 deletion src/snorlax.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 1bd37fb

Please sign in to comment.