text: /**
   * humane.js
   * Humanized Messages for Notifications
   * @author Marc Harter (@wavded)
   * @example
   *   humane.log('hello world');
   * 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 = o.timeout || 2500
        this.waitForMove = o.waitForMove || false
        this.clickToClose = o.clickToClose || false
        this.forceNew = o.forceNew || false
        this.container = o.container || doc.body
  
        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'
           this.container.appendChild(el)
           this.el = el
           this.removeEvent = ENV.bind(this.remove,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 = '<ul><li>'+msg.html.join('<li>')+'</ul>'
  
           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)
              this.el.filters.item('DXImageTransform.Microsoft.Alpha').Opacity = opacity*100
           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.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()
  })
  