/** * humane.js * Humanized Messages for Notifications * @author Marc Harter (@wavded) * @example * humane.log('hello world'); * @license MIT * See more usage examples at: http://wavded.github.com/humane-js/ */ ;!function (name, context, definition) { if (typeof module !== 'undefined') module.exports = definition(name, context) else if (typeof define === 'function' && typeof define.amd === 'object') define(definition) else context[name] = definition(name, context) }('humane', this, function (name, context) { var win = window var doc = document var ENV = { on: function (el, type, cb) { 'addEventListener' in win ? el.addEventListener(type,cb,false) : el.attachEvent('on'+type,cb) }, off: function (el, type, cb) { 'removeEventListener' in win ? el.removeEventListener(type,cb,false) : el.detachEvent('on'+type,cb) }, bind: function (fn, ctx) { return function () { fn.apply(ctx,arguments) } }, isArray: Array.isArray || function (obj) { return Object.prototype.toString.call(obj) === '[object Array]' }, config: function (preferred, fallback) { return preferred != null ? preferred : fallback }, transSupport: false, useFilter: /msie [678]/i.test(navigator.userAgent), // sniff, sniff _checkTransition: function () { var el = doc.createElement('div') var vendors = { webkit: 'webkit', Moz: '', O: 'o', ms: 'MS' } for (var vendor in vendors) if (vendor + 'Transition' in el.style) { this.vendorPrefix = vendors[vendor] this.transSupport = true } } } ENV._checkTransition() var Humane = function (o) { o || (o = {}) this.queue = [] this.baseCls = o.baseCls || 'humane' this.addnCls = o.addnCls || '' this.timeout = 'timeout' in o ? o.timeout : 2500 this.waitForMove = o.waitForMove || false this.clickToClose = o.clickToClose || false this.timeoutAfterMove = o.timeoutAfterMove || false this.container = o.container try { this._setupEl() } // attempt to setup elements catch (e) { ENV.on(win,'load',ENV.bind(this._setupEl, this)) // dom wasn't ready, wait till ready } } Humane.prototype = { constructor: Humane, _setupEl: function () { var el = doc.createElement('div') el.style.display = 'none' if (!this.container){ if(doc.body) this.container = doc.body; else throw 'document.body is null' } this.container.appendChild(el) this.el = el this.removeEvent = ENV.bind(function(){ var timeoutAfterMove = ENV.config(this.currentMsg.timeoutAfterMove,this.timeoutAfterMove) if (!timeoutAfterMove){ this.remove() } else { setTimeout(ENV.bind(this.remove,this),timeoutAfterMove) } },this) this.transEvent = ENV.bind(this._afterAnimation,this) this._run() }, _afterTimeout: function () { if (!ENV.config(this.currentMsg.waitForMove,this.waitForMove)) this.remove() else if (!this.removeEventsSet) { ENV.on(doc.body,'mousemove',this.removeEvent) ENV.on(doc.body,'click',this.removeEvent) ENV.on(doc.body,'keypress',this.removeEvent) ENV.on(doc.body,'touchstart',this.removeEvent) this.removeEventsSet = true } }, _run: function () { if (this._animating || !this.queue.length || !this.el) return this._animating = true if (this.currentTimer) { clearTimeout(this.currentTimer) this.currentTimer = null } var msg = this.queue.shift() var clickToClose = ENV.config(msg.clickToClose,this.clickToClose) if (clickToClose) { ENV.on(this.el,'click',this.removeEvent) ENV.on(this.el,'touchstart',this.removeEvent) } var timeout = ENV.config(msg.timeout,this.timeout) if (timeout > 0) this.currentTimer = setTimeout(ENV.bind(this._afterTimeout,this), timeout) if (ENV.isArray(msg.html)) msg.html = '' this.el.innerHTML = msg.html this.currentMsg = msg this.el.className = this.baseCls if (ENV.transSupport) { this.el.style.display = 'block' setTimeout(ENV.bind(this._showMsg,this),50) } else { this._showMsg() } }, _setOpacity: function (opacity) { if (ENV.useFilter){ try{ this.el.filters.item('DXImageTransform.Microsoft.Alpha').Opacity = opacity*100 } catch(err){} } else { this.el.style.opacity = String(opacity) } }, _showMsg: function () { var addnCls = ENV.config(this.currentMsg.addnCls,this.addnCls) if (ENV.transSupport) { this.el.className = this.baseCls+' '+addnCls+' '+this.baseCls+'-animate' } else { var opacity = 0 this.el.className = this.baseCls+' '+addnCls+' '+this.baseCls+'-js-animate' this._setOpacity(0) // reset value so hover states work this.el.style.display = 'block' var self = this var interval = setInterval(function(){ if (opacity < 1) { opacity += 0.1 if (opacity > 1) opacity = 1 self._setOpacity(opacity) } else clearInterval(interval) }, 30) } }, _hideMsg: function () { var addnCls = ENV.config(this.currentMsg.addnCls,this.addnCls) if (ENV.transSupport) { this.el.className = this.baseCls+' '+addnCls ENV.on(this.el,ENV.vendorPrefix ? ENV.vendorPrefix+'TransitionEnd' : 'transitionend',this.transEvent) } else { var opacity = 1 var self = this var interval = setInterval(function(){ if(opacity > 0) { opacity -= 0.1 if (opacity < 0) opacity = 0 self._setOpacity(opacity); } else { self.el.className = self.baseCls+' '+addnCls clearInterval(interval) self._afterAnimation() } }, 30) } }, _afterAnimation: function () { if (ENV.transSupport) ENV.off(this.el,ENV.vendorPrefix ? ENV.vendorPrefix+'TransitionEnd' : 'transitionend',this.transEvent) if (this.currentMsg.cb) this.currentMsg.cb() this.el.style.display = 'none' this._animating = false this._run() }, remove: function (e) { var cb = typeof e == 'function' ? e : null ENV.off(doc.body,'mousemove',this.removeEvent) ENV.off(doc.body,'click',this.removeEvent) ENV.off(doc.body,'keypress',this.removeEvent) ENV.off(doc.body,'touchstart',this.removeEvent) ENV.off(this.el,'click',this.removeEvent) ENV.off(this.el,'touchstart',this.removeEvent) this.removeEventsSet = false if (cb && this.currentMsg) this.currentMsg.cb = cb if (this._animating) this._hideMsg() else if (cb) cb() }, log: function (html, o, cb, defaults) { var msg = {} if (defaults) for (var opt in defaults) msg[opt] = defaults[opt] if (typeof o == 'function') cb = o else if (o) for (var opt in o) msg[opt] = o[opt] msg.html = html if (cb) msg.cb = cb this.queue.push(msg) this._run() return this }, spawn: function (defaults) { var self = this return function (html, o, cb) { self.log.call(self,html,o,cb,defaults) return self } }, create: function (o) { return new Humane(o) } } return new Humane() });