@tower1229/flow-ui
Version:
Highly customizable UI framework based Seajs/jQuery
466 lines (456 loc) • 12.5 kB
JavaScript
/*
* name: img-loaded.js
* version: v0.0.1
* update: build
* date: 2015-09-28
*/
(function() {
function EventEmitter() {}
var proto = EventEmitter.prototype;
var exports = this;
var originalGlobalValue = exports.EventEmitter;
function indexOfListener(listeners, listener) {
var i = listeners.length;
while (i--) {
if (listeners[i].listener === listener) {
return i
}
}
return -1
}
function alias(name) {
return function aliasClosure() {
return this[name].apply(this, arguments)
}
}
proto.getListeners = function getListeners(evt) {
var events = this._getEvents();
var response;
var key;
if (typeof evt === 'object') {
response = {};
for (key in events) {
if (events.hasOwnProperty(key) && evt.test(key)) {
response[key] = events[key]
}
}
} else {
response = events[evt] || (events[evt] = [])
}
return response
};
proto.flattenListeners = function flattenListeners(listeners) {
var flatListeners = [];
var i;
for (i = 0; i < listeners.length; i += 1) {
flatListeners.push(listeners[i].listener)
}
return flatListeners
};
proto.getListenersAsObject = function getListenersAsObject(evt) {
var listeners = this.getListeners(evt);
var response;
if (listeners instanceof Array) {
response = {};
response[evt] = listeners
}
return response || listeners
};
proto.addListener = function addListener(evt, listener) {
var listeners = this.getListenersAsObject(evt);
var listenerIsWrapped = typeof listener === 'object';
var key;
for (key in listeners) {
if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) {
listeners[key].push(listenerIsWrapped ? listener : {
listener: listener,
once: false
})
}
}
return this
};
proto.on = alias('addListener');
proto.addOnceListener = function addOnceListener(evt, listener) {
return this.addListener(evt, {
listener: listener,
once: true
})
};
proto.once = alias('addOnceListener');
proto.defineEvent = function defineEvent(evt) {
this.getListeners(evt);
return this
};
proto.defineEvents = function defineEvents(evts) {
for (var i = 0; i < evts.length; i += 1) {
this.defineEvent(evts[i])
}
return this
};
proto.removeListener = function removeListener(evt, listener) {
var listeners = this.getListenersAsObject(evt);
var index;
var key;
for (key in listeners) {
if (listeners.hasOwnProperty(key)) {
index = indexOfListener(listeners[key], listener);
if (index !== -1) {
listeners[key].splice(index, 1)
}
}
}
return this
};
proto.off = alias('removeListener');
proto.addListeners = function addListeners(evt, listeners) {
return this.manipulateListeners(false, evt, listeners)
};
proto.removeListeners = function removeListeners(evt, listeners) {
return this.manipulateListeners(true, evt, listeners)
};
proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) {
var i;
var value;
var single = remove ? this.removeListener : this.addListener;
var multiple = remove ? this.removeListeners : this.addListeners;
if (typeof evt === 'object' && !(evt instanceof RegExp)) {
for (i in evt) {
if (evt.hasOwnProperty(i) && (value = evt[i])) {
if (typeof value === 'function') {
single.call(this, i, value)
} else {
multiple.call(this, i, value)
}
}
}
} else {
i = listeners.length;
while (i--) {
single.call(this, evt, listeners[i])
}
}
return this
};
proto.removeEvent = function removeEvent(evt) {
var type = typeof evt;
var events = this._getEvents();
var key;
if (type === 'string') {
delete events[evt]
} else if (type === 'object') {
for (key in events) {
if (events.hasOwnProperty(key) && evt.test(key)) {
delete events[key]
}
}
} else {
delete this._events
}
return this
};
proto.removeAllListeners = alias('removeEvent');
proto.emitEvent = function emitEvent(evt, args) {
var listeners = this.getListenersAsObject(evt);
var listener;
var i;
var key;
var response;
for (key in listeners) {
if (listeners.hasOwnProperty(key)) {
i = listeners[key].length;
while (i--) {
listener = listeners[key][i];
if (listener.once === true) {
this.removeListener(evt, listener.listener)
}
response = listener.listener.apply(this, args || []);
if (response === this._getOnceReturnValue()) {
this.removeListener(evt, listener.listener)
}
}
}
}
return this
};
proto.trigger = alias('emitEvent');
proto.emit = function emit(evt) {
var args = Array.prototype.slice.call(arguments, 1);
return this.emitEvent(evt, args)
};
proto.setOnceReturnValue = function setOnceReturnValue(value) {
this._onceReturnValue = value;
return this
};
proto._getOnceReturnValue = function _getOnceReturnValue() {
if (this.hasOwnProperty('_onceReturnValue')) {
return this._onceReturnValue
} else {
return true
}
};
proto._getEvents = function _getEvents() {
return this._events || (this._events = {})
};
EventEmitter.noConflict = function noConflict() {
exports.EventEmitter = originalGlobalValue;
return EventEmitter
};
if (typeof define === 'function' && define.amd) {
define('eventEmitter/EventEmitter', [], function() {
return EventEmitter
})
} else if (typeof module === 'object' && module.exports) {
module.exports = EventEmitter
} else {
this.EventEmitter = EventEmitter
}
}.call(this));
(function(window) {
var docElem = document.documentElement;
var bind = function() {};
function getIEEvent(obj) {
var event = window.event;
event.target = event.target || event.srcElement || obj;
return event
}
if (docElem.addEventListener) {
bind = function(obj, type, fn) {
obj.addEventListener(type, fn, false)
}
} else if (docElem.attachEvent) {
bind = function(obj, type, fn) {
obj[type + fn] = fn.handleEvent ?
function() {
var event = getIEEvent(obj);
fn.handleEvent.call(fn, event)
} : function() {
var event = getIEEvent(obj);
fn.call(obj, event)
};
obj.attachEvent("on" + type, obj[type + fn])
}
}
var unbind = function() {};
if (docElem.removeEventListener) {
unbind = function(obj, type, fn) {
obj.removeEventListener(type, fn, false)
}
} else if (docElem.detachEvent) {
unbind = function(obj, type, fn) {
obj.detachEvent("on" + type, obj[type + fn]);
try {
delete obj[type + fn]
} catch (err) {
obj[type + fn] = undefined
}
}
}
var eventie = {
bind: bind,
unbind: unbind
};
if (typeof define === 'function' && define.amd) {
define('eventie/eventie', eventie)
} else {
window.eventie = eventie
}
})(this);
define('img-loaded', function(require, exports, module) {
var $ = window.$ || require('jquery');
var console = window.console;
var hasConsole = typeof console !== 'undefined';
function extend(a, b) {
for (var prop in b) {
a[prop] = b[prop]
}
return a
}
var objToString = Object.prototype.toString;
function isArray(obj) {
return objToString.call(obj) === '[object Array]'
}
function makeArray(obj) {
var ary = [];
if (isArray(obj)) {
ary = obj
} else if (typeof obj.length === 'number') {
for (var i = 0, len = obj.length; i < len; i++) {
ary.push(obj[i])
}
} else {
ary.push(obj)
}
return ary
}
function ImagesLoaded(elem, options, onAlways) {
if (!(this instanceof ImagesLoaded)) {
return new ImagesLoaded(elem, options)
}
if (typeof elem === 'string') {
elem = $(elem)
}
this.elements = makeArray(elem);
this.options = extend({}, this.options);
if (typeof options === 'function') {
onAlways = options
} else {
extend(this.options, options)
}
if (onAlways) {
this.on('always', onAlways)
}
this.getImages();
if ($) {
this.jqDeferred = new $.Deferred()
}
var _this = this;
setTimeout(function() {
_this.check()
})
}
ImagesLoaded.prototype = new EventEmitter();
ImagesLoaded.prototype.options = {};
ImagesLoaded.prototype.getImages = function() {
this.images = [];
for (var i = 0, len = this.elements.length; i < len; i++) {
var elem = this.elements[i];
if (elem.nodeName === 'IMG') {
this.addImage(elem)
}
var nodeType = elem.nodeType;
if (!nodeType || !(nodeType === 1 || nodeType === 9 || nodeType === 11)) {
continue
}
var childElems = $(elem).find('img');
for (var j = 0, jLen = childElems.length; j < jLen; j++) {
var img = childElems[j];
this.addImage(img)
}
}
};
ImagesLoaded.prototype.addImage = function(img) {
var loadingImage = new LoadingImage(img);
this.images.push(loadingImage)
};
ImagesLoaded.prototype.check = function() {
var _this = this;
var checkedCount = 0;
var length = this.images.length;
this.hasAnyBroken = false;
if (!length) {
this.complete();
return
}
function onConfirm(image, message) {
if (_this.options.debug && hasConsole) {
console.log('confirm', image, message)
}
_this.progress(image);
checkedCount++;
if (checkedCount === length) {
_this.complete()
}
return true
}
for (var i = 0; i < length; i++) {
var loadingImage = this.images[i];
loadingImage.on('confirm', onConfirm);
loadingImage.check()
}
};
ImagesLoaded.prototype.progress = function(image) {
this.hasAnyBroken = this.hasAnyBroken || !image.isLoaded;
var _this = this;
setTimeout(function() {
_this.emit('progress', _this, image);
if (_this.jqDeferred && _this.jqDeferred.notify) {
_this.jqDeferred.notify(_this, image)
}
})
};
ImagesLoaded.prototype.complete = function() {
var eventName = this.hasAnyBroken ? 'fail' : 'done';
this.isComplete = true;
var _this = this;
setTimeout(function() {
_this.emit(eventName, _this);
_this.emit('always', _this);
if (_this.jqDeferred) {
var jqMethod = _this.hasAnyBroken ? 'reject' : 'resolve';
_this.jqDeferred[jqMethod](_this)
}
})
};
if ($) {
$.fn.imagesLoaded = function(options, callback) {
var instance = new ImagesLoaded(this, options, callback);
return instance.jqDeferred.promise($(this))
}
}
function LoadingImage(img) {
this.img = img
}
LoadingImage.prototype = new EventEmitter();
LoadingImage.prototype.check = function() {
var resource = cache[this.img.src] || new Resource(this.img.src);
if (resource.isConfirmed) {
this.confirm(resource.isLoaded, 'cached was confirmed');
return
}
if (this.img.complete && this.img.naturalWidth !== undefined) {
this.confirm(this.img.naturalWidth !== 0, 'naturalWidth');
return
}
var _this = this;
resource.on('confirm', function(resrc, message) {
_this.confirm(resrc.isLoaded, message);
return true
});
resource.check()
};
LoadingImage.prototype.confirm = function(isLoaded, message) {
this.isLoaded = isLoaded;
this.emit('confirm', this, message)
};
var cache = {};
function Resource(src) {
this.src = src;
cache[src] = this
}
Resource.prototype = new EventEmitter();
Resource.prototype.check = function() {
if (this.isChecked) {
return
}
var proxyImage = new Image();
eventie.bind(proxyImage, 'load', this);
eventie.bind(proxyImage, 'error', this);
proxyImage.src = this.src;
this.isChecked = true
};
Resource.prototype.handleEvent = function(event) {
var method = 'on' + event.type;
if (this[method]) {
this[method](event)
}
};
Resource.prototype.onload = function(event) {
this.confirm(true, 'onload');
this.unbindProxyEvents(event)
};
Resource.prototype.onerror = function(event) {
this.confirm(false, 'onerror');
this.unbindProxyEvents(event)
};
Resource.prototype.confirm = function(isLoaded, message) {
this.isConfirmed = true;
this.isLoaded = isLoaded;
this.emit('confirm', this, message)
};
Resource.prototype.unbindProxyEvents = function(event) {
eventie.unbind(event.target, 'load', this);
eventie.unbind(event.target, 'error', this)
};
return ImagesLoaded
});