Last active
October 21, 2015 12:38
-
-
Save FuriouZz/fb7ee4e431e27bb7e7c1 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use strict" | |
/** | |
* | |
* Loader.js | |
* | |
* ------------------------------------------------------------ | |
* | |
* Available property: | |
* | |
* Loader.isLoading | |
* | |
* Available methods: | |
* | |
* Loader.load( String|Object|Array ) | |
* Loader.loadItem( Object ) | |
* Loader.loadUrl( String ) | |
* Loader.create() | |
* Loader.createAndLoad( String|Object|Array ) | |
* | |
* ------------------------------------------------------------ | |
* | |
* Events: | |
* | |
* oncomplete # Call when every item of the loop is loaded | |
* ondidload # Call when an item is loaded | |
* ondiderror # Call when an item loading failed | |
* | |
* ------------------------------------------------------------ | |
* | |
* Notes: | |
* | |
* Use load, loadItem or loadUrl if you want to load something in the main loop | |
* Use create, createAndLoad if you want to load something in a separate loop (for example a manifest) | |
* | |
* ------------------------------------------------------------ | |
* | |
* Examples: | |
* | |
* var url = 'my_image.jpg' | |
* Loader.load(url) | |
* Loader.on('onfileloaded', function(){ | |
* console.log('File loaded') | |
* }); | |
* | |
* var item = { type: 'audio', url: 'my_audio.mp3' } | |
* Loader.load(item, function(item){ | |
* if(item.loaded) { | |
* document.body.appendChild(item.element); | |
* } | |
* }); | |
* | |
* var items = ['image01.jpg', { type: 'video', 'my_video.mp4' }] | |
* Loader.load(items); | |
* | |
* var manifest = ['image02.jpg', { type: 'video', 'my_video01.mp4' }] | |
* var loader = Loader.createAndload(manifest); | |
* loader.on('oncomplete', function(){ | |
* console.log('oncomplete') | |
* }); | |
* | |
* // OR | |
* loader.oncomplete = function(){ | |
* console.log('oncomplete') | |
* } | |
* | |
* ------------------------------------------------------------ | |
* | |
*/ | |
import { EventEmitter } from 'events' | |
const typesRegExp = /(image|audio|video)/gi | |
const imageRegExp = /.(jpg|jpeg|png|gif)/gi | |
const videoRegExp = /.(mp4|webm)/gi | |
const audioRegExp = /.(mp3|ogg)/gi | |
class Loader extends EventEmitter { | |
constructor() { | |
super() | |
this.isLoading = false | |
this._queue = [] | |
this._current = null | |
this._bindEvents() | |
} | |
/** | |
* Add an url, an item or an array to the queue | |
* Params: | |
* => {String|Object|Array} urlOrItemOrArray | |
* Return | |
* => {Boolean} If it is loadable or not | |
*/ | |
load(urlOrItemOrArray) { | |
// Is an url | |
if (typeof urlOrItemOrArray === 'string') { | |
this.loadUrl(urlOrItemOrArray) | |
} | |
// Is an item | |
else if (urlOrItemOrArray.hasOwnProperty('type') | |
&& urlOrItemOrArray.hasOwnProperty('url')) { | |
this.loadItem(urlOrItemOrArray) | |
} | |
// Is an array | |
else if (typeof urlOrItemOrArray.length === 'number') { | |
urlOrItemOrArray.forEach((item) => { | |
this.load(item) | |
}) | |
} | |
else { | |
console.log("This content cannot be loaded") | |
return false | |
} | |
this._next() | |
return true | |
} | |
/** | |
* Add an item to the queue | |
* Params: | |
* => {Object} item | |
* type => {String} (image|audio|video) | |
* url => {String} | |
* Return | |
* => {Boolean} If it is loadable or not | |
*/ | |
loadItem(item) { | |
if (item.type && item.url && item.type.match(typesRegExp)) { | |
this._queue.push(item) | |
return true | |
} | |
console.log('This item cannot be loaded') | |
return false | |
} | |
/** | |
* Create an item from the url and add it to the queue | |
* Params: | |
* => {String} url | |
* => {Function} callback (default: null) | |
* Return | |
* => {Boolean} If it is loadable or not | |
*/ | |
loadUrl(url, callback = null) { | |
const item = { url: url, callback: callback } | |
if (url.match(imageRegExp)) { item.type = 'image' } | |
else if (url.match(videoRegExp)) { item.type = 'video' } | |
else if (url.match(audioRegExp)) { item.type = 'audio' } | |
else { console.log("This url cannot be loaded"); return false } | |
return this.loadItem(item) | |
} | |
/** | |
* Create a new loader | |
* Returns: | |
* {Object} Loader | |
*/ | |
create() { | |
return new Loader() | |
} | |
/** | |
* Create a new loader and load url, item, or array on this loader's scope | |
* Params: | |
* => {String|Object|Array} urlOrItemOrArray | |
* Returns: | |
* => {Object} Loader | |
*/ | |
createAndLoad(urlOrItemOrArray) { | |
const l = this.create() | |
l.load(urlOrItemOrArray) | |
return l | |
} | |
_bindEvents() { | |
this._onFileLoaded = this._onFileLoaded.bind(this) | |
this._onFileError = this._onFileError.bind(this) | |
} | |
_onLoad(item) { | |
switch (item.type) { | |
case 'image': { | |
let image | |
image = new Image() | |
image.onload = this._onFileLoaded | |
image.onerror = this._onFileError | |
image.src = item.url | |
item.element = image | |
break; | |
} | |
case 'audio': | |
case 'video': { | |
console.log('video or audio') | |
let media; | |
if (item.type === 'video') { media = document.createElement('video') } | |
else { media = document.createElement('audio') } | |
media.preload = 'auto' | |
media.addEventListener('loadedmetadata', this._onFileLoaded, false) | |
media.addEventListener('error', this._onFileError, false) | |
media.src = item.url | |
media.load() | |
item.element = media | |
break; | |
} | |
default: { | |
console.log('This item cannot be loaded', item) | |
return false; | |
} | |
} | |
this.isLoading = true | |
item.loaded = false | |
item.event = null | |
this._current = item | |
} | |
_onFileLoaded(e) { | |
this._current.event = e | |
this._current.loaded = true | |
this.emit('onfileloaded', this._current) | |
if (typeof this.onfileloaded === 'function') { | |
this.onfileloaded(this._current) | |
} | |
if (typeof this._current.callback === 'function') { | |
this._current.callback(this._current) | |
} | |
this._reset() | |
} | |
_onFileError(e) { | |
this._current.event = e | |
this._current.loaded = false | |
this.emit('onfileerror', this._current) | |
if (typeof this.onfileerror === 'function') { | |
this.onfileerror(this._current) | |
} | |
if (typeof this._current.callback === 'function') { | |
this._current.callback(this._current) | |
} | |
this._reset() | |
} | |
_onContentLoaded(){ | |
this.emit('oncomplete') | |
if (typeof this.oncomplete === 'function') { | |
this.oncomplete() | |
} | |
} | |
_reset() { | |
var item = this._current | |
this._current = null | |
if (item.type === 'video' || item.type === 'audio') { | |
item.element.removeEventListener('loadedmetadata', this._onFileLoaded, false) | |
item.element.removeEventListener('error', this._onFileError, false) | |
} | |
if (item.type === 'image') { | |
item.element.onload = null | |
item.element.onerror = null | |
} | |
this.isLoading = false | |
this._next() | |
} | |
_next() { | |
if (!this.isLoading && this._queue.length > 0) { | |
this._onLoad(this._queue.shift()) | |
} | |
if (!this.isLoading && this._queue.length === 0) { | |
this._onContentLoaded() | |
} | |
} | |
} | |
const _loader = new Loader() | |
export default _loader |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment