utils.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. var config = require('./config'),
  2. attrs = config.attrs,
  3. toString = Object.prototype.toString,
  4. join = Array.prototype.join,
  5. console = window.console,
  6. ViewModel // late def
  7. /**
  8. * Create a prototype-less object
  9. * which is a better hash/map
  10. */
  11. function makeHash () {
  12. return Object.create(null)
  13. }
  14. var utils = module.exports = {
  15. hash: makeHash,
  16. // global storage for user-registered
  17. // vms, partials and transitions
  18. components : makeHash(),
  19. partials : makeHash(),
  20. transitions : makeHash(),
  21. /**
  22. * get an attribute and remove it.
  23. */
  24. attr: function (el, type, noRemove) {
  25. var attr = attrs[type],
  26. val = el.getAttribute(attr)
  27. if (!noRemove && val !== null) el.removeAttribute(attr)
  28. return val
  29. },
  30. /**
  31. * Define an ienumerable property
  32. * This avoids it being included in JSON.stringify
  33. * or for...in loops.
  34. */
  35. defProtected: function (obj, key, val, enumerable, configurable) {
  36. if (obj.hasOwnProperty(key)) return
  37. Object.defineProperty(obj, key, {
  38. value : val,
  39. enumerable : !!enumerable,
  40. configurable : !!configurable
  41. })
  42. },
  43. /**
  44. * Accurate type check
  45. * internal use only, so no need to check for NaN
  46. */
  47. typeOf: function (obj) {
  48. return toString.call(obj).slice(8, -1)
  49. },
  50. /**
  51. * Most simple bind
  52. * enough for the usecase and fast than native bind()
  53. */
  54. bind: function (fn, ctx) {
  55. return function (arg) {
  56. return fn.call(ctx, arg)
  57. }
  58. },
  59. /**
  60. * Make sure only strings and numbers are output to html
  61. * output empty string is value is not string or number
  62. */
  63. toText: function (value) {
  64. /* jshint eqeqeq: false */
  65. return (typeof value === 'string' ||
  66. typeof value === 'boolean' ||
  67. (typeof value === 'number' && value == value)) // deal with NaN
  68. ? value
  69. : ''
  70. },
  71. /**
  72. * simple extend
  73. */
  74. extend: function (obj, ext, protective) {
  75. for (var key in ext) {
  76. if (protective && obj[key]) continue
  77. obj[key] = ext[key]
  78. }
  79. },
  80. /**
  81. * filter an array with duplicates into uniques
  82. */
  83. unique: function (arr) {
  84. var hash = utils.hash(),
  85. i = arr.length,
  86. key, res = []
  87. while (i--) {
  88. key = arr[i]
  89. if (hash[key]) continue
  90. hash[key] = 1
  91. res.push(key)
  92. }
  93. return res
  94. },
  95. /**
  96. * Convert a string template to a dom fragment
  97. */
  98. toFragment: function (template) {
  99. if (typeof template !== 'string') {
  100. return template
  101. }
  102. if (template.charAt(0) === '#') {
  103. var templateNode = document.getElementById(template.slice(1))
  104. if (!templateNode) return
  105. template = templateNode.innerHTML
  106. }
  107. var node = document.createElement('div'),
  108. frag = document.createDocumentFragment(),
  109. child
  110. node.innerHTML = template.trim()
  111. /* jshint boss: true */
  112. while (child = node.firstChild) {
  113. frag.appendChild(child)
  114. }
  115. return frag
  116. },
  117. /**
  118. * Convert the object to a ViewModel constructor
  119. * if it is not already one
  120. */
  121. toConstructor: function (obj) {
  122. ViewModel = ViewModel || require('./viewmodel')
  123. return utils.typeOf(obj) === 'Object'
  124. ? ViewModel.extend(obj)
  125. : typeof obj === 'function'
  126. ? obj
  127. : null
  128. },
  129. /**
  130. * convert certain option values to the desired format.
  131. */
  132. processOptions: function (options) {
  133. var components = options.components,
  134. partials = options.partials,
  135. template = options.template,
  136. key
  137. if (components) {
  138. for (key in components) {
  139. components[key] = utils.toConstructor(components[key])
  140. }
  141. }
  142. if (partials) {
  143. for (key in partials) {
  144. partials[key] = utils.toFragment(partials[key])
  145. }
  146. }
  147. if (template) {
  148. options.template = utils.toFragment(template)
  149. }
  150. },
  151. /**
  152. * log for debugging
  153. */
  154. log: function () {
  155. if (config.debug && console) {
  156. console.log(join.call(arguments, ' '))
  157. }
  158. },
  159. /**
  160. * warnings, traces by default
  161. * can be suppressed by `silent` option.
  162. */
  163. warn: function() {
  164. if (!config.silent && console) {
  165. console.warn(join.call(arguments, ' '))
  166. }
  167. }
  168. }