not really known
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

240 lines
8.1 KiB

  1. /**
  2. * humane.js
  3. * Humanized Messages for Notifications
  4. * @author Marc Harter (@wavded)
  5. * @example
  6. * humane.log('hello world');
  7. * @license MIT
  8. * See more usage examples at: http://wavded.github.com/humane-js/
  9. */
  10. ;!function (name, context, definition) {
  11. // HACK: Force loading with define to avoid loading issue in Electron
  12. //if (typeof module !== 'undefined') module.exports = definition(name, context)
  13. //else if (typeof define === 'function' && typeof define.amd === 'object') define(definition)
  14. //else context[name] = definition(name, context)
  15. define(definition);
  16. }('humane', this, function (name, context) {
  17. var win = window
  18. var doc = document
  19. var ENV = {
  20. on: function (el, type, cb) {
  21. 'addEventListener' in win ? el.addEventListener(type,cb,false) : el.attachEvent('on'+type,cb)
  22. },
  23. off: function (el, type, cb) {
  24. 'removeEventListener' in win ? el.removeEventListener(type,cb,false) : el.detachEvent('on'+type,cb)
  25. },
  26. bind: function (fn, ctx) {
  27. return function () { fn.apply(ctx,arguments) }
  28. },
  29. isArray: Array.isArray || function (obj) { return Object.prototype.toString.call(obj) === '[object Array]' },
  30. config: function (preferred, fallback) {
  31. return preferred != null ? preferred : fallback
  32. },
  33. transSupport: false,
  34. useFilter: /msie [678]/i.test(navigator.userAgent), // sniff, sniff
  35. _checkTransition: function () {
  36. var el = doc.createElement('div')
  37. var vendors = { webkit: 'webkit', Moz: '', O: 'o', ms: 'MS' }
  38. for (var vendor in vendors)
  39. if (vendor + 'Transition' in el.style) {
  40. this.vendorPrefix = vendors[vendor]
  41. this.transSupport = true
  42. }
  43. }
  44. }
  45. ENV._checkTransition()
  46. var Humane = function (o) {
  47. o || (o = {})
  48. this.queue = []
  49. this.baseCls = o.baseCls || 'humane'
  50. this.addnCls = o.addnCls || ''
  51. this.timeout = 'timeout' in o ? o.timeout : 2500
  52. this.waitForMove = o.waitForMove || false
  53. this.clickToClose = o.clickToClose || false
  54. this.timeoutAfterMove = o.timeoutAfterMove || false
  55. this.container = o.container
  56. try { this._setupEl() } // attempt to setup elements
  57. catch (e) {
  58. ENV.on(win,'load',ENV.bind(this._setupEl, this)) // dom wasn't ready, wait till ready
  59. }
  60. }
  61. Humane.prototype = {
  62. constructor: Humane,
  63. _setupEl: function () {
  64. var el = doc.createElement('div')
  65. el.style.display = 'none'
  66. if (!this.container){
  67. if(doc.body) this.container = doc.body;
  68. else throw 'document.body is null'
  69. }
  70. this.container.appendChild(el)
  71. this.el = el
  72. this.removeEvent = ENV.bind(function(){
  73. var timeoutAfterMove = ENV.config(this.currentMsg.timeoutAfterMove,this.timeoutAfterMove)
  74. if (!timeoutAfterMove){
  75. this.remove()
  76. } else {
  77. setTimeout(ENV.bind(this.remove,this),timeoutAfterMove)
  78. }
  79. },this)
  80. this.transEvent = ENV.bind(this._afterAnimation,this)
  81. this._run()
  82. },
  83. _afterTimeout: function () {
  84. if (!ENV.config(this.currentMsg.waitForMove,this.waitForMove)) this.remove()
  85. else if (!this.removeEventsSet) {
  86. ENV.on(doc.body,'mousemove',this.removeEvent)
  87. ENV.on(doc.body,'click',this.removeEvent)
  88. ENV.on(doc.body,'keypress',this.removeEvent)
  89. ENV.on(doc.body,'touchstart',this.removeEvent)
  90. this.removeEventsSet = true
  91. }
  92. },
  93. _run: function () {
  94. if (this._animating || !this.queue.length || !this.el) return
  95. this._animating = true
  96. if (this.currentTimer) {
  97. clearTimeout(this.currentTimer)
  98. this.currentTimer = null
  99. }
  100. var msg = this.queue.shift()
  101. var clickToClose = ENV.config(msg.clickToClose,this.clickToClose)
  102. if (clickToClose) {
  103. ENV.on(this.el,'click',this.removeEvent)
  104. ENV.on(this.el,'touchstart',this.removeEvent)
  105. }
  106. var timeout = ENV.config(msg.timeout,this.timeout)
  107. if (timeout > 0)
  108. this.currentTimer = setTimeout(ENV.bind(this._afterTimeout,this), timeout)
  109. if (ENV.isArray(msg.html)) msg.html = '<ul><li>'+msg.html.join('<li>')+'</ul>'
  110. this.el.innerHTML = msg.html
  111. this.currentMsg = msg
  112. this.el.className = this.baseCls
  113. if (ENV.transSupport) {
  114. this.el.style.display = 'block'
  115. setTimeout(ENV.bind(this._showMsg,this),50)
  116. } else {
  117. this._showMsg()
  118. }
  119. },
  120. _setOpacity: function (opacity) {
  121. if (ENV.useFilter){
  122. try{
  123. this.el.filters.item('DXImageTransform.Microsoft.Alpha').Opacity = opacity*100
  124. } catch(err){}
  125. } else {
  126. this.el.style.opacity = String(opacity)
  127. }
  128. },
  129. _showMsg: function () {
  130. var addnCls = ENV.config(this.currentMsg.addnCls,this.addnCls)
  131. if (ENV.transSupport) {
  132. this.el.className = this.baseCls+' '+addnCls+' '+this.baseCls+'-animate'
  133. }
  134. else {
  135. var opacity = 0
  136. this.el.className = this.baseCls+' '+addnCls+' '+this.baseCls+'-js-animate'
  137. this._setOpacity(0) // reset value so hover states work
  138. this.el.style.display = 'block'
  139. var self = this
  140. var interval = setInterval(function(){
  141. if (opacity < 1) {
  142. opacity += 0.1
  143. if (opacity > 1) opacity = 1
  144. self._setOpacity(opacity)
  145. }
  146. else clearInterval(interval)
  147. }, 30)
  148. }
  149. },
  150. _hideMsg: function () {
  151. var addnCls = ENV.config(this.currentMsg.addnCls,this.addnCls)
  152. if (ENV.transSupport) {
  153. this.el.className = this.baseCls+' '+addnCls
  154. ENV.on(this.el,ENV.vendorPrefix ? ENV.vendorPrefix+'TransitionEnd' : 'transitionend',this.transEvent)
  155. }
  156. else {
  157. var opacity = 1
  158. var self = this
  159. var interval = setInterval(function(){
  160. if(opacity > 0) {
  161. opacity -= 0.1
  162. if (opacity < 0) opacity = 0
  163. self._setOpacity(opacity);
  164. }
  165. else {
  166. self.el.className = self.baseCls+' '+addnCls
  167. clearInterval(interval)
  168. self._afterAnimation()
  169. }
  170. }, 30)
  171. }
  172. },
  173. _afterAnimation: function () {
  174. if (ENV.transSupport) ENV.off(this.el,ENV.vendorPrefix ? ENV.vendorPrefix+'TransitionEnd' : 'transitionend',this.transEvent)
  175. if (this.currentMsg.cb) this.currentMsg.cb()
  176. this.el.style.display = 'none'
  177. this._animating = false
  178. this._run()
  179. },
  180. remove: function (e) {
  181. var cb = typeof e == 'function' ? e : null
  182. ENV.off(doc.body,'mousemove',this.removeEvent)
  183. ENV.off(doc.body,'click',this.removeEvent)
  184. ENV.off(doc.body,'keypress',this.removeEvent)
  185. ENV.off(doc.body,'touchstart',this.removeEvent)
  186. ENV.off(this.el,'click',this.removeEvent)
  187. ENV.off(this.el,'touchstart',this.removeEvent)
  188. this.removeEventsSet = false
  189. if (cb && this.currentMsg) this.currentMsg.cb = cb
  190. if (this._animating) this._hideMsg()
  191. else if (cb) cb()
  192. },
  193. log: function (html, o, cb, defaults) {
  194. var msg = {}
  195. if (defaults)
  196. for (var opt in defaults)
  197. msg[opt] = defaults[opt]
  198. if (typeof o == 'function') cb = o
  199. else if (o)
  200. for (var opt in o) msg[opt] = o[opt]
  201. msg.html = html
  202. if (cb) msg.cb = cb
  203. this.queue.push(msg)
  204. this._run()
  205. return this
  206. },
  207. spawn: function (defaults) {
  208. var self = this
  209. return function (html, o, cb) {
  210. self.log.call(self,html,o,cb,defaults)
  211. return self
  212. }
  213. },
  214. create: function (o) { return new Humane(o) }
  215. }
  216. return new Humane()
  217. });