processing-js
Version:
For the project website, visit http://processingjs.org
150 lines (131 loc) • 5.1 kB
JavaScript
/*
L A Z Y L O A D I N G F O R P R O C E S S I N G . J S
Part of the Processing.js project
License : MIT
Web Site : http://processingjs.org
Github Repo. : http://github.com/jeresig/processing-js
Bug Tracking : http://processing-js.lighthouseapp.com
*/
(function() {
/**
* Can we rely on there being a w3c DOM available?
*/
var isDOMPresent = ("document" in this) && !("fake" in this.document);
/**
* If there is no DOM, don't run.
*/
if (!isDOMPresent) {
throw("This browser does not support the w3c DOM interface, which this extension for Processing.js relies on.");
}
/**
* If there is no Processing.js, don't run.
*/
if (!Processing) {
throw("Please load Processing.js before loading the \"lazy loading\" extension.");
}
/**
* Prevent processing from running its init function
*/
Processing.disableInit();
// constructor
LazyLoading = this.LazyLoading = {};
/**
* This object will track every sketch that needs to be lazily loaded
*/
var sketches = {};
/**
* Get all canvas elements on the page, and if they indicate that
* they load processing sources, add them to our to-do collection/
*/
var setSketches = function() {
var elements = document.getElementsByTagName('canvas');
var _id = 0;
for (var e=0, end=elements.length; e<end; e++) {
var canvas = elements[e];
// make sure we only grab canvas elements that are associated with processing source files
if (canvas.getAttribute("data-processing-sources") || canvas.getAttribute("data-src") || canvas.getAttribute("datasrc")) {
if(!canvas.id) { canvas.id = "canvas"+(_id++); }
var sketch = {};
sketch.canvas = canvas;
sketches[canvas.id] = sketch;
}
}
};
/**
* This function sets the height values for the sketch's
* canvas's top and bottom.
* @param {sketch} sketch The sketch object for which the top/bottom values are set
*/
var setHeightValues = function(sketch) {
sketch.top = getElementPosition(sketch.canvas);
sketch.bottom = sketch.top + sketch.canvas.clientHeight;
};
/**
* General purpose "height of element on page" function.
* Code from http://www.quirksmode.org/js/findpos.html
* @param {HTMLElement} element The HTML element for which the height on the page is being checked
*/
var getElementPosition = function(obj) {
var curTop = 0;
if (obj.offsetParent) {
do {
curTop += obj.offsetTop;
} while (!!(obj = obj.offsetParent));
}
return curTop;
};
/**
* For each sketch in the to-do list, check whether it should be loaded
* based on whether or not the user can see any part of the canvas it
* is to be loaded in is visible on their screen.
*/
var checkPositions = LazyLoading.checkPositions = function() {
var top = 0, bottom = 0;
Object.keys(sketches).forEach(function(s) {
var sketch = sketches[s];
top = window.pageYOffset;
bottom = top + window.innerHeight;
setHeightValues(sketch);
if ((top <= sketch.top && sketch.top <= bottom) || (top <= sketch.bottom && sketch.bottom <= bottom)) {
LazyLoading.loadSketch(sketch);
delete sketches[s];
}
});
};
/**
* Load the sketch associated with a canvas, from source indicated by that canvas.
* @param {sketch} sketch An administrative sketch object
*/
var loadSketch = LazyLoading.loadSketch = function(sketch) {
if (sketch.canvas) {
// form an array of which files must be loaded for this sketch
var processingSources = sketch.canvas.getAttribute('data-processing-sources');
if(processingSources===null) { processingSources = sketch.canvas.getAttribute('data-src'); }
if(processingSources===null) { processingSources = sketch.canvas.getAttribute('datasrc'); }
var filenames = processingSources.split(' ');
for (var j = 0; j < filenames.length;) {
if (filenames[j]) { j++; }
else { filenames.splice(j, 1); }}
// make Processing.js load this sketch into its canvas
Processing.loadSketchFromSources(sketch.canvas, filenames);
}
};
/**
* In order for lazy-loading to do its work when it is started, it needs to first builds
* the to-do list for sketches that may eventually need loading, then check whether
* any of them need immediate loading, and finally, it needs to set up a scroll event
* listener so that every time a user scrolls the page (in whichever way), the lazy
* loader checks whether this resulted in one or more sketches needing to be loaded
* because they have become visible to the user.
*/
var init = function() {
setSketches();
checkPositions();
document.addEventListener("scroll", LazyLoading.checkPositions, false);
};
/**
* Finally, we kick-start the whole lazy loading process by making sure init() is called
* when the document signals it has finished building the page's DOM.
*/
document.addEventListener('DOMContentLoaded', init, false);
})();