-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathmodules-LazyImageLoader.js
111 lines (95 loc) · 3.1 KB
/
modules-LazyImageLoader.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
(function () {
/**
* window.LazyImageLoader()
*
* After instanciation there is two way to use it:
* `lazyImageLoader.add(url, cb)` for each image and then `lazyImageLoader.start()`
* or just
* `lazyImageLoader.load(url, cb)` for each image
* each image's load callback is called with one argument: the image object
*
* Rq: The `url` parameter may also be a function, that takes the target image object as parameter; this custom method have to trigger the image's onload method
*/
var STATUS = {
NOT_STARTED: 0,
LOADING: 1,
LOADED: 2
};
var LazyImageLoader = function(options) {
options = options || {};
var or = window.force.modules.helpers.or;
// params
this.maxParallel = or(options.maxParallel , 10); // maximum number of images we want to load in parallel, for asynchronous only
this.delayBetweenLoad = or(options.delayBetweenLoad , 10); // ms delay between 2 img load, to let the code live, like for animating a progress bar
// internals
this._list = []; // images to load
this._imgLoading = []; // images currently loading (indexes of this._list)
};
window.force.expose('window.LazyImageLoader', LazyImageLoader);
LazyImageLoader.prototype.add = function(url, cb) {
this._list.push({
url : url,
cb : cb,
status : STATUS.NOT_STARTED,
index : this._list.length
});
};
LazyImageLoader.prototype.start = function(url, cb) {
if (this._imgLoading.length < this.maxParallel) {
this._loadNext();
}
};
LazyImageLoader.prototype.load = function(url, cb) {
this.add(url, cb);
this.start();
};
LazyImageLoader.prototype.clear = function() {
this._list = [];
this._imgLoading = [];
};
var notStartedFilter = function(entry) {
return entry.status === STATUS.NOT_STARTED;
};
var notLoadedFilter = function(entry) {
return entry.status !== STATUS.LOADED;
};
LazyImageLoader.prototype._loadNext = function() {
if (this._imgLoading.length < this.maxParallel) {
var that = this;
var notLoadedYet = this._list.filter(notStartedFilter);
if (notLoadedYet.length > 0) {
var i = notLoadedYet[0].index;
this._list[i].status = STATUS.LOADING;
this._imgLoading.push(i);
var img = new Image();
img.onload = function() {
if (that._list[i].cb) {
that._list[i].cb(this);
}
that._list[i].cb = null;
that._list[i].status = STATUS.LOADED;
that._imgLoading.splice(that._imgLoading.indexOf(i), 1);
if (that._imgLoading.length < that.maxParallel) {
if (!that.delayBetweenLoad) {
that._loadNext();
} else {
setTimeout(function() {
that._loadNext();
}, that.delayBetweenLoad);
}
}
};
if (typeof this._list[i].url === 'string') {
img.src = this._list[i].url;
} else if (typeof this._list[i].url === 'function') {
this._list[i].url(img);
}
} else {
var notLoaded = this._list.filter(notLoadedFilter);
if (notLoaded.length === 0) {
this.clear();
}
}
}
}
})();