integral 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (761) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +105 -0
  4. data/Rakefile +22 -0
  5. data/app/assets/images/integral/backend/data-unavailable.png +0 -0
  6. data/app/assets/images/integral/backend/logo.png +0 -0
  7. data/app/assets/images/integral/defaults/no_image_available.jpg +0 -0
  8. data/app/assets/images/integral/defaults/user_avatar.jpg +0 -0
  9. data/app/assets/images/integral/image-not-set.png +0 -0
  10. data/app/assets/images/integral/posts-hero-banner.jpg +0 -0
  11. data/app/assets/javascripts/ckeditor/loader.js.erb +6 -0
  12. data/app/assets/javascripts/ckeditor/my_config.js.erb +154 -0
  13. data/app/assets/javascripts/ckeditor/my_contents.sass +22 -0
  14. data/app/assets/javascripts/ckeditor/my_javascript.js +12 -0
  15. data/app/assets/javascripts/ckeditor/my_styles.js +5 -0
  16. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/az.js +8 -0
  17. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/bg.js +8 -0
  18. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/ca.js +8 -0
  19. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/cs.js +8 -0
  20. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/da.js +8 -0
  21. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/de-ch.js +8 -0
  22. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/de.js +8 -0
  23. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/el.js +8 -0
  24. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/en-au.js +8 -0
  25. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/en.js +8 -0
  26. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/eo.js +8 -0
  27. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/es-mx.js +8 -0
  28. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/es.js +8 -0
  29. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/eu.js +8 -0
  30. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/fr.js +8 -0
  31. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/gl.js +8 -0
  32. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/hr.js +8 -0
  33. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/hu.js +8 -0
  34. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/it.js +8 -0
  35. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/ja.js +8 -0
  36. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/km.js +8 -0
  37. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/ko.js +8 -0
  38. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/ku.js +8 -0
  39. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/mk.js +8 -0
  40. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/nb.js +8 -0
  41. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/nl.js +8 -0
  42. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/oc.js +8 -0
  43. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/pl.js +8 -0
  44. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/pt-br.js +8 -0
  45. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/pt.js +8 -0
  46. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/ro.js +8 -0
  47. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/ru.js +8 -0
  48. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/sk.js +8 -0
  49. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/sq.js +8 -0
  50. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/sv.js +8 -0
  51. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/tr.js +8 -0
  52. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/ug.js +8 -0
  53. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/uk.js +8 -0
  54. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/vi.js +8 -0
  55. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/zh-cn.js +8 -0
  56. data/app/assets/javascripts/ckeditor/plugins/autoembed/lang/zh.js +8 -0
  57. data/app/assets/javascripts/ckeditor/plugins/autoembed/plugin.js +218 -0
  58. data/app/assets/javascripts/ckeditor/plugins/autogrow/plugin.js +232 -0
  59. data/app/assets/javascripts/ckeditor/plugins/autogrow/samples/autogrow.html +102 -0
  60. data/app/assets/javascripts/ckeditor/plugins/autolink/plugin.js +69 -0
  61. data/app/assets/javascripts/ckeditor/plugins/codemirror/css/codemirror.min.css +1 -0
  62. data/app/assets/javascripts/ckeditor/plugins/codemirror/icons/autocomplete.png +0 -0
  63. data/app/assets/javascripts/ckeditor/plugins/codemirror/icons/autoformat.png +0 -0
  64. data/app/assets/javascripts/ckeditor/plugins/codemirror/icons/commentselectedrange.png +0 -0
  65. data/app/assets/javascripts/ckeditor/plugins/codemirror/icons/searchcode.png +0 -0
  66. data/app/assets/javascripts/ckeditor/plugins/codemirror/icons/uncommentselectedrange.png +0 -0
  67. data/app/assets/javascripts/ckeditor/plugins/codemirror/js/beautify.min.js +2 -0
  68. data/app/assets/javascripts/ckeditor/plugins/codemirror/js/codemirror.addons.min.js +2 -0
  69. data/app/assets/javascripts/ckeditor/plugins/codemirror/js/codemirror.addons.search.min.js +1 -0
  70. data/app/assets/javascripts/ckeditor/plugins/codemirror/js/codemirror.min.js +6 -0
  71. data/app/assets/javascripts/ckeditor/plugins/codemirror/js/codemirror.mode.bbcode.min.js +1 -0
  72. data/app/assets/javascripts/ckeditor/plugins/codemirror/js/codemirror.mode.bbcodemixed.min.js +1 -0
  73. data/app/assets/javascripts/ckeditor/plugins/codemirror/js/codemirror.mode.htmlmixed.min.js +2 -0
  74. data/app/assets/javascripts/ckeditor/plugins/codemirror/js/codemirror.mode.javascript.min.js +1 -0
  75. data/app/assets/javascripts/ckeditor/plugins/codemirror/js/codemirror.mode.php.min.js +3 -0
  76. data/app/assets/javascripts/ckeditor/plugins/codemirror/js/codemirror.mode.twig.min.js +1 -0
  77. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/af.js +12 -0
  78. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/ar.js +12 -0
  79. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/bg.js +12 -0
  80. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/bn.js +12 -0
  81. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/bs.js +12 -0
  82. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/ca.js +12 -0
  83. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/cs.js +12 -0
  84. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/cy.js +12 -0
  85. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/da.js +12 -0
  86. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/de.js +12 -0
  87. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/el.js +12 -0
  88. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/en-au.js +12 -0
  89. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/en-ca.js +12 -0
  90. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/en-gb.js +12 -0
  91. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/en.js +12 -0
  92. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/eo.js +12 -0
  93. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/es.js +12 -0
  94. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/et.js +12 -0
  95. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/eu.js +12 -0
  96. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/fa.js +12 -0
  97. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/fi.js +12 -0
  98. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/fo.js +12 -0
  99. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/fr-ca.js +12 -0
  100. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/fr.js +12 -0
  101. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/gl.js +12 -0
  102. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/gu.js +12 -0
  103. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/he.js +12 -0
  104. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/hi.js +12 -0
  105. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/hr.js +12 -0
  106. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/hu.js +12 -0
  107. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/is.js +12 -0
  108. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/it.js +12 -0
  109. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/ja.js +12 -0
  110. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/ka.js +12 -0
  111. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/km.js +12 -0
  112. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/ko.js +12 -0
  113. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/ku.js +12 -0
  114. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/lt.js +12 -0
  115. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/lv.js +12 -0
  116. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/mk.js +12 -0
  117. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/mn.js +12 -0
  118. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/ms.js +12 -0
  119. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/nb.js +12 -0
  120. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/nl.js +12 -0
  121. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/no.js +12 -0
  122. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/pl.js +12 -0
  123. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/pt-br.js +12 -0
  124. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/pt.js +12 -0
  125. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/ro.js +12 -0
  126. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/ru.js +12 -0
  127. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/sk.js +12 -0
  128. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/sl.js +12 -0
  129. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/sr-latn.js +12 -0
  130. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/sr.js +12 -0
  131. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/sv.js +12 -0
  132. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/th.js +12 -0
  133. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/tr.js +12 -0
  134. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/ug.js +12 -0
  135. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/uk.js +12 -0
  136. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/vi.js +12 -0
  137. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/zh-cn.js +12 -0
  138. data/app/assets/javascripts/ckeditor/plugins/codemirror/lang/zh.js +12 -0
  139. data/app/assets/javascripts/ckeditor/plugins/codemirror/plugin.js +1311 -0
  140. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/3024-day.css +41 -0
  141. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/3024-night.css +39 -0
  142. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/abcdef.css +32 -0
  143. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/ambiance-mobile.css +5 -0
  144. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/ambiance.css +74 -0
  145. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/base16-dark.css +38 -0
  146. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/base16-light.css +38 -0
  147. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/bespin.css +34 -0
  148. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/blackboard.css +32 -0
  149. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/cobalt.css +25 -0
  150. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/colorforth.css +33 -0
  151. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/dracula.css +40 -0
  152. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/duotone-dark.css +35 -0
  153. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/duotone-light.css +36 -0
  154. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/eclipse.css +23 -0
  155. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/elegant.css +13 -0
  156. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/erlang-dark.css +34 -0
  157. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/hopscotch.css +34 -0
  158. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/icecoder.css +43 -0
  159. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/isotope.css +34 -0
  160. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/lesser-dark.css +47 -0
  161. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/liquibyte.css +95 -0
  162. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/material.css +53 -0
  163. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/mbo.css +37 -0
  164. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/mdn-like.css +46 -0
  165. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/midnight.css +43 -0
  166. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/monokai.css +36 -0
  167. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/neat.css +12 -0
  168. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/neo.css +43 -0
  169. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/night.css +27 -0
  170. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/panda-syntax.css +85 -0
  171. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/paraiso-dark.css +38 -0
  172. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/paraiso-light.css +38 -0
  173. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/pastel-on-dark.css +52 -0
  174. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/railscasts.css +34 -0
  175. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/rubyblue.css +25 -0
  176. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/seti.css +44 -0
  177. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/solarized.css +168 -0
  178. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/the-matrix.css +30 -0
  179. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/tomorrow-night-bright.css +35 -0
  180. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/tomorrow-night-eighties.css +38 -0
  181. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/ttcn.css +64 -0
  182. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/twilight.css +32 -0
  183. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/vibrant-ink.css +34 -0
  184. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/xq-dark.css +53 -0
  185. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/xq-light.css +43 -0
  186. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/yeti.css +44 -0
  187. data/app/assets/javascripts/ckeditor/plugins/codemirror/theme/zenburn.css +37 -0
  188. data/app/assets/javascripts/ckeditor/plugins/embed/icons/embed.png +0 -0
  189. data/app/assets/javascripts/ckeditor/plugins/embed/icons/hidpi/embed.png +0 -0
  190. data/app/assets/javascripts/ckeditor/plugins/embed/plugin.js +105 -0
  191. data/app/assets/javascripts/ckeditor/plugins/embedbase/dialogs/embedbase.js +99 -0
  192. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/az.js +15 -0
  193. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/bg.js +15 -0
  194. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/ca.js +15 -0
  195. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/cs.js +15 -0
  196. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/da.js +15 -0
  197. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/de-ch.js +15 -0
  198. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/de.js +15 -0
  199. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/en-au.js +15 -0
  200. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/en.js +15 -0
  201. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/eo.js +15 -0
  202. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/es-mx.js +15 -0
  203. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/es.js +15 -0
  204. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/eu.js +15 -0
  205. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/fr.js +15 -0
  206. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/gl.js +15 -0
  207. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/hr.js +15 -0
  208. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/hu.js +15 -0
  209. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/id.js +15 -0
  210. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/it.js +15 -0
  211. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/ja.js +15 -0
  212. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/ko.js +15 -0
  213. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/ku.js +15 -0
  214. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/nb.js +15 -0
  215. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/nl.js +15 -0
  216. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/oc.js +15 -0
  217. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/pl.js +15 -0
  218. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/pt-br.js +15 -0
  219. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/pt.js +15 -0
  220. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/ro.js +15 -0
  221. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/ru.js +15 -0
  222. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/sk.js +15 -0
  223. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/sq.js +15 -0
  224. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/sv.js +15 -0
  225. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/tr.js +15 -0
  226. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/ug.js +15 -0
  227. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/uk.js +15 -0
  228. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/zh-cn.js +15 -0
  229. data/app/assets/javascripts/ckeditor/plugins/embedbase/lang/zh.js +15 -0
  230. data/app/assets/javascripts/ckeditor/plugins/embedbase/plugin.js +652 -0
  231. data/app/assets/javascripts/ckeditor/plugins/embedjs/plugin.js +110 -0
  232. data/app/assets/javascripts/ckeditor/plugins/lineutils/dev/dnd.html +172 -0
  233. data/app/assets/javascripts/ckeditor/plugins/lineutils/dev/magicfinger.html +285 -0
  234. data/app/assets/javascripts/ckeditor/plugins/lineutils/plugin.js +1018 -0
  235. data/app/assets/javascripts/ckeditor/plugins/notification/lang/cs.js +7 -0
  236. data/app/assets/javascripts/ckeditor/plugins/notification/lang/da.js +7 -0
  237. data/app/assets/javascripts/ckeditor/plugins/notification/lang/de-ch.js +7 -0
  238. data/app/assets/javascripts/ckeditor/plugins/notification/lang/de.js +7 -0
  239. data/app/assets/javascripts/ckeditor/plugins/notification/lang/en.js +7 -0
  240. data/app/assets/javascripts/ckeditor/plugins/notification/lang/eo.js +7 -0
  241. data/app/assets/javascripts/ckeditor/plugins/notification/lang/eu.js +7 -0
  242. data/app/assets/javascripts/ckeditor/plugins/notification/lang/fr.js +7 -0
  243. data/app/assets/javascripts/ckeditor/plugins/notification/lang/gl.js +7 -0
  244. data/app/assets/javascripts/ckeditor/plugins/notification/lang/id.js +7 -0
  245. data/app/assets/javascripts/ckeditor/plugins/notification/lang/it.js +7 -0
  246. data/app/assets/javascripts/ckeditor/plugins/notification/lang/km.js +7 -0
  247. data/app/assets/javascripts/ckeditor/plugins/notification/lang/ko.js +7 -0
  248. data/app/assets/javascripts/ckeditor/plugins/notification/lang/ku.js +7 -0
  249. data/app/assets/javascripts/ckeditor/plugins/notification/lang/nb.js +7 -0
  250. data/app/assets/javascripts/ckeditor/plugins/notification/lang/nl.js +7 -0
  251. data/app/assets/javascripts/ckeditor/plugins/notification/lang/pl.js +7 -0
  252. data/app/assets/javascripts/ckeditor/plugins/notification/lang/pt-br.js +7 -0
  253. data/app/assets/javascripts/ckeditor/plugins/notification/lang/pt.js +7 -0
  254. data/app/assets/javascripts/ckeditor/plugins/notification/lang/ru.js +7 -0
  255. data/app/assets/javascripts/ckeditor/plugins/notification/lang/sv.js +7 -0
  256. data/app/assets/javascripts/ckeditor/plugins/notification/lang/tr.js +7 -0
  257. data/app/assets/javascripts/ckeditor/plugins/notification/lang/ug.js +7 -0
  258. data/app/assets/javascripts/ckeditor/plugins/notification/lang/uk.js +7 -0
  259. data/app/assets/javascripts/ckeditor/plugins/notification/lang/zh-cn.js +7 -0
  260. data/app/assets/javascripts/ckeditor/plugins/notification/lang/zh.js +7 -0
  261. data/app/assets/javascripts/ckeditor/plugins/notification/plugin.js +923 -0
  262. data/app/assets/javascripts/ckeditor/plugins/notificationaggregator/plugin.js +548 -0
  263. data/app/assets/javascripts/ckeditor/plugins/placeholder/dev/placeholder.html +60 -0
  264. data/app/assets/javascripts/ckeditor/plugins/placeholder/dialogs/placeholder.js +49 -0
  265. data/app/assets/javascripts/ckeditor/plugins/placeholder/icons/hidpi/placeholder.png +0 -0
  266. data/app/assets/javascripts/ckeditor/plugins/placeholder/icons/placeholder.png +0 -0
  267. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/af.js +12 -0
  268. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/ar.js +12 -0
  269. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/az.js +12 -0
  270. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/bg.js +12 -0
  271. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/ca.js +12 -0
  272. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/cs.js +12 -0
  273. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/cy.js +12 -0
  274. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/da.js +12 -0
  275. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/de-ch.js +12 -0
  276. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/de.js +12 -0
  277. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/el.js +12 -0
  278. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/en-gb.js +12 -0
  279. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/en.js +12 -0
  280. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/eo.js +12 -0
  281. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/es-mx.js +12 -0
  282. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/es.js +12 -0
  283. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/et.js +12 -0
  284. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/eu.js +12 -0
  285. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/fa.js +12 -0
  286. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/fi.js +12 -0
  287. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/fr-ca.js +12 -0
  288. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/fr.js +12 -0
  289. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/gl.js +12 -0
  290. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/he.js +12 -0
  291. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/hr.js +12 -0
  292. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/hu.js +12 -0
  293. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/id.js +12 -0
  294. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/it.js +12 -0
  295. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/ja.js +12 -0
  296. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/km.js +12 -0
  297. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/ko.js +12 -0
  298. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/ku.js +12 -0
  299. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/lv.js +12 -0
  300. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/nb.js +12 -0
  301. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/nl.js +12 -0
  302. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/no.js +12 -0
  303. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/oc.js +12 -0
  304. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/pl.js +12 -0
  305. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/pt-br.js +12 -0
  306. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/pt.js +12 -0
  307. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/ru.js +12 -0
  308. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/si.js +12 -0
  309. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/sk.js +12 -0
  310. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/sl.js +12 -0
  311. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/sq.js +12 -0
  312. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/sv.js +12 -0
  313. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/th.js +12 -0
  314. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/tr.js +12 -0
  315. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/tt.js +12 -0
  316. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/ug.js +12 -0
  317. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/uk.js +12 -0
  318. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/vi.js +12 -0
  319. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/zh-cn.js +12 -0
  320. data/app/assets/javascripts/ckeditor/plugins/placeholder/lang/zh.js +12 -0
  321. data/app/assets/javascripts/ckeditor/plugins/placeholder/plugin.js +99 -0
  322. data/app/assets/javascripts/ckeditor/plugins/placeholder/samples/placeholder.html +75 -0
  323. data/app/assets/javascripts/ckeditor/plugins/strinsert/README.md +76 -0
  324. data/app/assets/javascripts/ckeditor/plugins/strinsert/bower.json +16 -0
  325. data/app/assets/javascripts/ckeditor/plugins/strinsert/plugin.js +107 -0
  326. data/app/assets/javascripts/ckeditor/plugins/widget/dev/assets/contents.css +23 -0
  327. data/app/assets/javascripts/ckeditor/plugins/widget/dev/assets/sample.jpg +0 -0
  328. data/app/assets/javascripts/ckeditor/plugins/widget/dev/assets/simplebox/contents.css +36 -0
  329. data/app/assets/javascripts/ckeditor/plugins/widget/dev/assets/simplebox/dialogs/simplebox.js +51 -0
  330. data/app/assets/javascripts/ckeditor/plugins/widget/dev/assets/simplebox/icons/simplebox.png +0 -0
  331. data/app/assets/javascripts/ckeditor/plugins/widget/dev/assets/simplebox/plugin.js +114 -0
  332. data/app/assets/javascripts/ckeditor/plugins/widget/dev/console.js +131 -0
  333. data/app/assets/javascripts/ckeditor/plugins/widget/dev/nestedwidgets.html +134 -0
  334. data/app/assets/javascripts/ckeditor/plugins/widget/dev/widgetstyles.html +144 -0
  335. data/app/assets/javascripts/ckeditor/plugins/widget/images/handle.png +0 -0
  336. data/app/assets/javascripts/ckeditor/plugins/widget/lang/af.js +8 -0
  337. data/app/assets/javascripts/ckeditor/plugins/widget/lang/ar.js +8 -0
  338. data/app/assets/javascripts/ckeditor/plugins/widget/lang/az.js +8 -0
  339. data/app/assets/javascripts/ckeditor/plugins/widget/lang/bg.js +8 -0
  340. data/app/assets/javascripts/ckeditor/plugins/widget/lang/ca.js +8 -0
  341. data/app/assets/javascripts/ckeditor/plugins/widget/lang/cs.js +8 -0
  342. data/app/assets/javascripts/ckeditor/plugins/widget/lang/cy.js +8 -0
  343. data/app/assets/javascripts/ckeditor/plugins/widget/lang/da.js +8 -0
  344. data/app/assets/javascripts/ckeditor/plugins/widget/lang/de-ch.js +8 -0
  345. data/app/assets/javascripts/ckeditor/plugins/widget/lang/de.js +8 -0
  346. data/app/assets/javascripts/ckeditor/plugins/widget/lang/el.js +8 -0
  347. data/app/assets/javascripts/ckeditor/plugins/widget/lang/en-gb.js +8 -0
  348. data/app/assets/javascripts/ckeditor/plugins/widget/lang/en.js +8 -0
  349. data/app/assets/javascripts/ckeditor/plugins/widget/lang/eo.js +8 -0
  350. data/app/assets/javascripts/ckeditor/plugins/widget/lang/es-mx.js +8 -0
  351. data/app/assets/javascripts/ckeditor/plugins/widget/lang/es.js +8 -0
  352. data/app/assets/javascripts/ckeditor/plugins/widget/lang/eu.js +8 -0
  353. data/app/assets/javascripts/ckeditor/plugins/widget/lang/fa.js +8 -0
  354. data/app/assets/javascripts/ckeditor/plugins/widget/lang/fi.js +8 -0
  355. data/app/assets/javascripts/ckeditor/plugins/widget/lang/fr.js +8 -0
  356. data/app/assets/javascripts/ckeditor/plugins/widget/lang/gl.js +8 -0
  357. data/app/assets/javascripts/ckeditor/plugins/widget/lang/he.js +8 -0
  358. data/app/assets/javascripts/ckeditor/plugins/widget/lang/hr.js +8 -0
  359. data/app/assets/javascripts/ckeditor/plugins/widget/lang/hu.js +8 -0
  360. data/app/assets/javascripts/ckeditor/plugins/widget/lang/id.js +8 -0
  361. data/app/assets/javascripts/ckeditor/plugins/widget/lang/it.js +8 -0
  362. data/app/assets/javascripts/ckeditor/plugins/widget/lang/ja.js +8 -0
  363. data/app/assets/javascripts/ckeditor/plugins/widget/lang/km.js +8 -0
  364. data/app/assets/javascripts/ckeditor/plugins/widget/lang/ko.js +8 -0
  365. data/app/assets/javascripts/ckeditor/plugins/widget/lang/ku.js +8 -0
  366. data/app/assets/javascripts/ckeditor/plugins/widget/lang/lv.js +8 -0
  367. data/app/assets/javascripts/ckeditor/plugins/widget/lang/nb.js +8 -0
  368. data/app/assets/javascripts/ckeditor/plugins/widget/lang/nl.js +8 -0
  369. data/app/assets/javascripts/ckeditor/plugins/widget/lang/no.js +8 -0
  370. data/app/assets/javascripts/ckeditor/plugins/widget/lang/oc.js +8 -0
  371. data/app/assets/javascripts/ckeditor/plugins/widget/lang/pl.js +8 -0
  372. data/app/assets/javascripts/ckeditor/plugins/widget/lang/pt-br.js +8 -0
  373. data/app/assets/javascripts/ckeditor/plugins/widget/lang/pt.js +8 -0
  374. data/app/assets/javascripts/ckeditor/plugins/widget/lang/ru.js +8 -0
  375. data/app/assets/javascripts/ckeditor/plugins/widget/lang/sk.js +8 -0
  376. data/app/assets/javascripts/ckeditor/plugins/widget/lang/sl.js +8 -0
  377. data/app/assets/javascripts/ckeditor/plugins/widget/lang/sq.js +8 -0
  378. data/app/assets/javascripts/ckeditor/plugins/widget/lang/sv.js +8 -0
  379. data/app/assets/javascripts/ckeditor/plugins/widget/lang/tr.js +8 -0
  380. data/app/assets/javascripts/ckeditor/plugins/widget/lang/tt.js +8 -0
  381. data/app/assets/javascripts/ckeditor/plugins/widget/lang/ug.js +8 -0
  382. data/app/assets/javascripts/ckeditor/plugins/widget/lang/uk.js +8 -0
  383. data/app/assets/javascripts/ckeditor/plugins/widget/lang/vi.js +8 -0
  384. data/app/assets/javascripts/ckeditor/plugins/widget/lang/zh-cn.js +8 -0
  385. data/app/assets/javascripts/ckeditor/plugins/widget/lang/zh.js +8 -0
  386. data/app/assets/javascripts/ckeditor/plugins/widget/plugin.js +4147 -0
  387. data/app/assets/javascripts/ckeditor/plugins/widgetselection/plugin.js +366 -0
  388. data/app/assets/javascripts/ckeditor/plugins/wordcount/css/wordcount.css +3 -0
  389. data/app/assets/javascripts/ckeditor/plugins/wordcount/lang/ar.js +11 -0
  390. data/app/assets/javascripts/ckeditor/plugins/wordcount/lang/ca.js +13 -0
  391. data/app/assets/javascripts/ckeditor/plugins/wordcount/lang/da.js +13 -0
  392. data/app/assets/javascripts/ckeditor/plugins/wordcount/lang/de.js +13 -0
  393. data/app/assets/javascripts/ckeditor/plugins/wordcount/lang/el.js +13 -0
  394. data/app/assets/javascripts/ckeditor/plugins/wordcount/lang/en.js +13 -0
  395. data/app/assets/javascripts/ckeditor/plugins/wordcount/lang/es.js +13 -0
  396. data/app/assets/javascripts/ckeditor/plugins/wordcount/lang/fi.js +14 -0
  397. data/app/assets/javascripts/ckeditor/plugins/wordcount/lang/fr.js +11 -0
  398. data/app/assets/javascripts/ckeditor/plugins/wordcount/lang/he.js +13 -0
  399. data/app/assets/javascripts/ckeditor/plugins/wordcount/lang/hr.js +13 -0
  400. data/app/assets/javascripts/ckeditor/plugins/wordcount/lang/it.js +14 -0
  401. data/app/assets/javascripts/ckeditor/plugins/wordcount/lang/ja.js +14 -0
  402. data/app/assets/javascripts/ckeditor/plugins/wordcount/lang/jp.js +13 -0
  403. data/app/assets/javascripts/ckeditor/plugins/wordcount/lang/nl.js +13 -0
  404. data/app/assets/javascripts/ckeditor/plugins/wordcount/lang/no.js +10 -0
  405. data/app/assets/javascripts/ckeditor/plugins/wordcount/lang/pl.js +13 -0
  406. data/app/assets/javascripts/ckeditor/plugins/wordcount/lang/pt-br.js +13 -0
  407. data/app/assets/javascripts/ckeditor/plugins/wordcount/lang/pt.js +9 -0
  408. data/app/assets/javascripts/ckeditor/plugins/wordcount/lang/ru.js +13 -0
  409. data/app/assets/javascripts/ckeditor/plugins/wordcount/lang/sv.js +13 -0
  410. data/app/assets/javascripts/ckeditor/plugins/wordcount/lang/tr.js +13 -0
  411. data/app/assets/javascripts/ckeditor/plugins/wordcount/lang/zh-cn.js +13 -0
  412. data/app/assets/javascripts/ckeditor/plugins/wordcount/plugin.js +407 -0
  413. data/app/assets/javascripts/ckeditor/plugins/wordcount/samples/wordcount.html +61 -0
  414. data/app/assets/javascripts/ckeditor/plugins/wordcount/samples/wordcountWithMaxCount.html +110 -0
  415. data/app/assets/javascripts/integral/backend.js +268 -0
  416. data/app/assets/javascripts/integral/backend/extensions.js +1 -0
  417. data/app/assets/javascripts/integral/backend/support/Chart.bundle.min.js +10 -0
  418. data/app/assets/javascripts/integral/frontend.js +60 -0
  419. data/app/assets/javascripts/integral/support/character_counter.js +67 -0
  420. data/app/assets/javascripts/integral/support/chart_manager.coffee +145 -0
  421. data/app/assets/javascripts/integral/support/click_to_copy.coffee +28 -0
  422. data/app/assets/javascripts/integral/support/confirm_modal.coffee +58 -0
  423. data/app/assets/javascripts/integral/support/date_picker.coffee +83 -0
  424. data/app/assets/javascripts/integral/support/date_picker/picker.date.js +1435 -0
  425. data/app/assets/javascripts/integral/support/date_picker/picker.js +1132 -0
  426. data/app/assets/javascripts/integral/support/gallery.coffee +82 -0
  427. data/app/assets/javascripts/integral/support/google_analytics.coffee +23 -0
  428. data/app/assets/javascripts/integral/support/grid.coffee +92 -0
  429. data/app/assets/javascripts/integral/support/header_anchors.coffee +22 -0
  430. data/app/assets/javascripts/integral/support/image-preview.coffee +14 -0
  431. data/app/assets/javascripts/integral/support/image_selector.coffee +43 -0
  432. data/app/assets/javascripts/integral/support/image_uploader.coffee +59 -0
  433. data/app/assets/javascripts/integral/support/lib/html.sortable.js +691 -0
  434. data/app/assets/javascripts/integral/support/lib/jquery.are-you-sure.js +231 -0
  435. data/app/assets/javascripts/integral/support/lib/jquery_form.js +11 -0
  436. data/app/assets/javascripts/integral/support/lib/js.cookie.js +165 -0
  437. data/app/assets/javascripts/integral/support/lib/materialize-tags.js +758 -0
  438. data/app/assets/javascripts/integral/support/lib/materialize.clockpicker.js +699 -0
  439. data/app/assets/javascripts/integral/support/lib/swiper.js +7719 -0
  440. data/app/assets/javascripts/integral/support/lib/typeahead.js +2451 -0
  441. data/app/assets/javascripts/integral/support/lib/underscore.js +6 -0
  442. data/app/assets/javascripts/integral/support/list.coffee +71 -0
  443. data/app/assets/javascripts/integral/support/list_item.coffee +249 -0
  444. data/app/assets/javascripts/integral/support/notification_manager.coffee +17 -0
  445. data/app/assets/javascripts/integral/support/record_selector.coffee +161 -0
  446. data/app/assets/javascripts/integral/support/remote_form.coffee +87 -0
  447. data/app/assets/javascripts/integral/support/responsive_swiper.coffee +26 -0
  448. data/app/assets/javascripts/integral/support/scroll_to_top.coffee +17 -0
  449. data/app/assets/javascripts/integral/support/slug_generator.coffee +49 -0
  450. data/app/assets/stylesheets/errors.css +1834 -0
  451. data/app/assets/stylesheets/integral/backend.sass +66 -0
  452. data/app/assets/stylesheets/integral/backend/_foundation_settings.scss +867 -0
  453. data/app/assets/stylesheets/integral/backend/dashboard-layout.scss +491 -0
  454. data/app/assets/stylesheets/integral/backend/devise.sass +40 -0
  455. data/app/assets/stylesheets/integral/backend/foundation_and_overrides.scss +56 -0
  456. data/app/assets/stylesheets/integral/backend/materialize-tags.sass +70 -0
  457. data/app/assets/stylesheets/integral/backend/notifications.sass +43 -0
  458. data/app/assets/stylesheets/integral/backend/overrides.sass +1 -0
  459. data/app/assets/stylesheets/integral/backend/shared.sass +770 -0
  460. data/app/assets/stylesheets/integral/emails.scss +19 -0
  461. data/app/assets/stylesheets/integral/emails/colors.sass +3 -0
  462. data/app/assets/stylesheets/integral/frontend.sass +26 -0
  463. data/app/assets/stylesheets/integral/frontend/_foundation_settings.scss +863 -0
  464. data/app/assets/stylesheets/integral/frontend/blog.sass +263 -0
  465. data/app/assets/stylesheets/integral/frontend/demo.sass +158 -0
  466. data/app/assets/stylesheets/integral/frontend/foundation_and_overrides.scss +56 -0
  467. data/app/assets/stylesheets/integral/frontend/layout.sass +66 -0
  468. data/app/assets/stylesheets/integral/frontend/overrides.sass +1 -0
  469. data/app/assets/stylesheets/integral/frontend/share_modal.sass +25 -0
  470. data/app/assets/stylesheets/integral/frontend/shared.sass +73 -0
  471. data/app/assets/stylesheets/integral/support/date-picker.scss +16 -0
  472. data/app/assets/stylesheets/integral/support/date_picker/_default.date.scss +452 -0
  473. data/app/assets/stylesheets/integral/support/date_picker/_default.scss +201 -0
  474. data/app/assets/stylesheets/integral/support/date_picker/_default.time.scss +125 -0
  475. data/app/assets/stylesheets/integral/support/date_picker/materialize_clockpicker.sass +220 -0
  476. data/app/assets/stylesheets/integral/support/gallery.sass +54 -0
  477. data/app/assets/stylesheets/integral/support/media-query-indicator.sass +25 -0
  478. data/app/assets/stylesheets/integral/support/mixins.sass +29 -0
  479. data/app/assets/stylesheets/integral/support/scroll-to-top.sass +19 -0
  480. data/app/assets/stylesheets/integral/support/swiper.css +618 -0
  481. data/app/assets/stylesheets/integral/wysiwyg.sass +13 -0
  482. data/app/controllers/integral/application_controller.rb +130 -0
  483. data/app/controllers/integral/backend/activities_controller.rb +55 -0
  484. data/app/controllers/integral/backend/base_controller.rb +123 -0
  485. data/app/controllers/integral/backend/images_controller.rb +120 -0
  486. data/app/controllers/integral/backend/lists_controller.rb +138 -0
  487. data/app/controllers/integral/backend/pages_controller.rb +142 -0
  488. data/app/controllers/integral/backend/posts_controller.rb +132 -0
  489. data/app/controllers/integral/backend/settings_controller.rb +53 -0
  490. data/app/controllers/integral/backend/static_pages_controller.rb +10 -0
  491. data/app/controllers/integral/backend/users_controller.rb +130 -0
  492. data/app/controllers/integral/blog_controller.rb +19 -0
  493. data/app/controllers/integral/contact_controller.rb +36 -0
  494. data/app/controllers/integral/pages_controller.rb +45 -0
  495. data/app/controllers/integral/posts_controller.rb +71 -0
  496. data/app/controllers/integral/tags_controller.rb +38 -0
  497. data/app/decorators/integral/image_decorator.rb +16 -0
  498. data/app/decorators/integral/list_decorator.rb +21 -0
  499. data/app/decorators/integral/page_decorator.rb +26 -0
  500. data/app/decorators/integral/post_decorator.rb +63 -0
  501. data/app/decorators/integral/user_decorator.rb +21 -0
  502. data/app/decorators/integral/version_decorator.rb +57 -0
  503. data/app/helpers/integral/application_helper.rb +52 -0
  504. data/app/helpers/integral/backend/base_helper.rb +72 -0
  505. data/app/helpers/integral/blog_helper.rb +26 -0
  506. data/app/helpers/integral/gallery_helper.rb +36 -0
  507. data/app/helpers/integral/mail_helper.rb +16 -0
  508. data/app/helpers/integral/social_helper.rb +123 -0
  509. data/app/helpers/integral/support_helper.rb +60 -0
  510. data/app/jobs/integral/application_job.rb +10 -0
  511. data/app/jobs/integral/newsletter_signup_job.rb +28 -0
  512. data/app/mailers/integral/contact_mailer.rb +56 -0
  513. data/app/models/ckeditor/asset.rb +8 -0
  514. data/app/models/ckeditor/attachment_file.rb +9 -0
  515. data/app/models/ckeditor/picture.rb +21 -0
  516. data/app/models/integral/application_record.rb +6 -0
  517. data/app/models/integral/basic.rb +11 -0
  518. data/app/models/integral/enquiry.rb +46 -0
  519. data/app/models/integral/image.rb +67 -0
  520. data/app/models/integral/image_version.rb +8 -0
  521. data/app/models/integral/link.rb +11 -0
  522. data/app/models/integral/list.rb +69 -0
  523. data/app/models/integral/list_item.rb +89 -0
  524. data/app/models/integral/list_version.rb +8 -0
  525. data/app/models/integral/newsletter_signup.rb +22 -0
  526. data/app/models/integral/object.rb +30 -0
  527. data/app/models/integral/page.rb +153 -0
  528. data/app/models/integral/page_version.rb +8 -0
  529. data/app/models/integral/post.rb +149 -0
  530. data/app/models/integral/post_version.rb +8 -0
  531. data/app/models/integral/post_viewing.rb +19 -0
  532. data/app/models/integral/role.rb +14 -0
  533. data/app/models/integral/role_assignment.rb +7 -0
  534. data/app/models/integral/settings.rb +5 -0
  535. data/app/models/integral/user.rb +59 -0
  536. data/app/models/integral/user_version.rb +8 -0
  537. data/app/models/integral/version.rb +31 -0
  538. data/app/models/paper_trail/version.rb +9 -0
  539. data/app/policies/integral/base_policy.rb +50 -0
  540. data/app/policies/integral/image_policy.rb +14 -0
  541. data/app/policies/integral/list_policy.rb +9 -0
  542. data/app/policies/integral/page_policy.rb +45 -0
  543. data/app/policies/integral/post_policy.rb +9 -0
  544. data/app/policies/integral/settings_policy.rb +17 -0
  545. data/app/policies/integral/user_policy.rb +17 -0
  546. data/app/policies/integral/version_policy.rb +19 -0
  547. data/app/uploaders/ckeditor_attachment_file_uploader.rb +34 -0
  548. data/app/uploaders/ckeditor_picture_uploader.rb +55 -0
  549. data/app/uploaders/integral/avatar_uploader.rb +9 -0
  550. data/app/uploaders/integral/image_uploader.rb +114 -0
  551. data/app/views/devise/invitations/edit.haml +17 -0
  552. data/app/views/devise/mailer/confirmation_instructions.html.erb +5 -0
  553. data/app/views/devise/mailer/invitation_instructions.html.erb +13 -0
  554. data/app/views/devise/mailer/invitation_instructions.text.erb +12 -0
  555. data/app/views/devise/mailer/reset_password_instructions.html.erb +8 -0
  556. data/app/views/devise/mailer/unlock_instructions.html.erb +7 -0
  557. data/app/views/devise/passwords/edit.haml +17 -0
  558. data/app/views/devise/passwords/new.haml +12 -0
  559. data/app/views/devise/sessions/new.haml +18 -0
  560. data/app/views/devise/shared/_links.html.erb +25 -0
  561. data/app/views/integral/backend/activities/_grid.haml +23 -0
  562. data/app/views/integral/backend/activities/index.haml +15 -0
  563. data/app/views/integral/backend/activities/shared/_grid.haml +20 -0
  564. data/app/views/integral/backend/activities/shared/_listing.haml +14 -0
  565. data/app/views/integral/backend/activities/shared/_log.haml +56 -0
  566. data/app/views/integral/backend/activities/show.haml +18 -0
  567. data/app/views/integral/backend/images/_create_modal.haml +17 -0
  568. data/app/views/integral/backend/images/_form.haml +41 -0
  569. data/app/views/integral/backend/images/_grid.haml +16 -0
  570. data/app/views/integral/backend/images/edit.haml +3 -0
  571. data/app/views/integral/backend/images/index.haml +18 -0
  572. data/app/views/integral/backend/images/new.haml +1 -0
  573. data/app/views/integral/backend/lists/_child_fields.haml +26 -0
  574. data/app/views/integral/backend/lists/_form.haml +25 -0
  575. data/app/views/integral/backend/lists/_grid.haml +16 -0
  576. data/app/views/integral/backend/lists/_item_container.haml +26 -0
  577. data/app/views/integral/backend/lists/_item_modal.haml +46 -0
  578. data/app/views/integral/backend/lists/_list_item_fields.haml +26 -0
  579. data/app/views/integral/backend/lists/_manager.haml +14 -0
  580. data/app/views/integral/backend/lists/edit.haml +2 -0
  581. data/app/views/integral/backend/lists/index.haml +18 -0
  582. data/app/views/integral/backend/lists/new.haml +1 -0
  583. data/app/views/integral/backend/lists/show.haml +26 -0
  584. data/app/views/integral/backend/pages/_form.haml +52 -0
  585. data/app/views/integral/backend/pages/_grid.haml +21 -0
  586. data/app/views/integral/backend/pages/activities.haml +2 -0
  587. data/app/views/integral/backend/pages/activity.haml +1 -0
  588. data/app/views/integral/backend/pages/edit.html.haml +15 -0
  589. data/app/views/integral/backend/pages/index.haml +22 -0
  590. data/app/views/integral/backend/pages/new.haml +2 -0
  591. data/app/views/integral/backend/posts/_form.haml +57 -0
  592. data/app/views/integral/backend/posts/_grid.haml +25 -0
  593. data/app/views/integral/backend/posts/activities.haml +3 -0
  594. data/app/views/integral/backend/posts/activity.haml +1 -0
  595. data/app/views/integral/backend/posts/edit.haml +16 -0
  596. data/app/views/integral/backend/posts/index.haml +20 -0
  597. data/app/views/integral/backend/posts/new.haml +2 -0
  598. data/app/views/integral/backend/settings/_input.haml +4 -0
  599. data/app/views/integral/backend/settings/_section.haml +11 -0
  600. data/app/views/integral/backend/settings/index.haml +10 -0
  601. data/app/views/integral/backend/settings/sections/_general.haml +12 -0
  602. data/app/views/integral/backend/settings/sections/_lists.haml +4 -0
  603. data/app/views/integral/backend/settings/sections/_seo.haml +8 -0
  604. data/app/views/integral/backend/settings/sections/_social.haml +16 -0
  605. data/app/views/integral/backend/shared/_breadcrumbs.haml +9 -0
  606. data/app/views/integral/backend/shared/_empty_grid.haml +7 -0
  607. data/app/views/integral/backend/shared/_grid.haml +18 -0
  608. data/app/views/integral/backend/shared/_image_preview.haml +23 -0
  609. data/app/views/integral/backend/shared/_image_selector.haml +4 -0
  610. data/app/views/integral/backend/shared/_pagination.haml +1 -0
  611. data/app/views/integral/backend/shared/cards/_at_a_glance.haml +5 -0
  612. data/app/views/integral/backend/shared/cards/_welcome.haml +29 -0
  613. data/app/views/integral/backend/shared/graphs/_donut.haml +5 -0
  614. data/app/views/integral/backend/shared/graphs/_line.haml +5 -0
  615. data/app/views/integral/backend/shared/graphs/_no_data_available.haml +2 -0
  616. data/app/views/integral/backend/shared/record_selector/_collection.haml +13 -0
  617. data/app/views/integral/backend/shared/record_selector/_modal.haml +42 -0
  618. data/app/views/integral/backend/shared/record_selector/_record.haml +6 -0
  619. data/app/views/integral/backend/static_pages/_card.haml +24 -0
  620. data/app/views/integral/backend/static_pages/dashboard.haml +20 -0
  621. data/app/views/integral/backend/users/_form.haml +58 -0
  622. data/app/views/integral/backend/users/_grid.haml +19 -0
  623. data/app/views/integral/backend/users/edit.haml +3 -0
  624. data/app/views/integral/backend/users/index.haml +18 -0
  625. data/app/views/integral/backend/users/new.haml +2 -0
  626. data/app/views/integral/backend/users/show.haml +36 -0
  627. data/app/views/integral/contact_mailer/auto_reply.html.haml +16 -0
  628. data/app/views/integral/contact_mailer/auto_reply.text.erb +15 -0
  629. data/app/views/integral/contact_mailer/forward_enquiry.haml +12 -0
  630. data/app/views/integral/contact_mailer/forward_enquiry.text.erb +9 -0
  631. data/app/views/integral/pages/_demo.haml +188 -0
  632. data/app/views/integral/pages/templates/default.haml +6 -0
  633. data/app/views/integral/posts/_item.haml +16 -0
  634. data/app/views/integral/posts/index.haml +6 -0
  635. data/app/views/integral/posts/templates/default.haml +38 -0
  636. data/app/views/integral/shared/_blog_layout.haml +15 -0
  637. data/app/views/integral/shared/_blog_sidebar.haml +49 -0
  638. data/app/views/integral/shared/_breadcrumbs.haml +5 -0
  639. data/app/views/integral/shared/_media_query_indicator.haml +2 -0
  640. data/app/views/integral/shared/_scroll_to_top.haml +3 -0
  641. data/app/views/integral/shared/_share_modal.haml +20 -0
  642. data/app/views/integral/shared/_social_list_items.haml +41 -0
  643. data/app/views/integral/shared/_swiper_layout.haml +20 -0
  644. data/app/views/integral/shared/gallery/_placeholder.haml +7 -0
  645. data/app/views/integral/shared/gallery/_slide.haml +5 -0
  646. data/app/views/integral/shared/gallery/_thumb_slide.haml +2 -0
  647. data/app/views/integral/shared/gallery/gallery.haml +7 -0
  648. data/app/views/integral/tags/index.haml +6 -0
  649. data/app/views/integral/tags/show.haml +6 -0
  650. data/app/views/layouts/error.haml +12 -0
  651. data/app/views/layouts/integral/backend.html.haml +93 -0
  652. data/app/views/layouts/integral/backend/_create_dropdown.haml +30 -0
  653. data/app/views/layouts/integral/backend/_head.html.haml +17 -0
  654. data/app/views/layouts/integral/backend/_main_menu_items.haml +91 -0
  655. data/app/views/layouts/integral/frontend.html.haml +36 -0
  656. data/app/views/layouts/integral/frontend/_admin_bar.haml +25 -0
  657. data/app/views/layouts/integral/frontend/_footer.haml +23 -0
  658. data/app/views/layouts/integral/frontend/_header.haml +12 -0
  659. data/app/views/layouts/integral/login.haml +8 -0
  660. data/app/views/layouts/integral/mailer.html.inky-haml +17 -0
  661. data/app/views/layouts/integral/mailer/_footer.html.inky-haml +11 -0
  662. data/app/views/layouts/integral/mailer/_header.html.inky-haml +7 -0
  663. data/config/initializers/acts_as_taggable_on.rb +6 -0
  664. data/config/initializers/ckeditor.rb +51 -0
  665. data/config/initializers/client_side_validations.rb +20 -0
  666. data/config/initializers/compression.rb +46 -0
  667. data/config/initializers/devise.rb +308 -0
  668. data/config/initializers/extensions/ckeditor.rb +31 -0
  669. data/config/initializers/friendly_id.rb +88 -0
  670. data/config/initializers/gaffe.rb +3 -0
  671. data/config/initializers/simple_form.rb +169 -0
  672. data/config/initializers/simple_form/length_component.rb +36 -0
  673. data/config/locales/devise.en.yml +60 -0
  674. data/config/locales/devise_invitable.en.yml +31 -0
  675. data/config/locales/en.yml +477 -0
  676. data/config/locales/simple_form.en.yml +31 -0
  677. data/config/routes.rb +3 -0
  678. data/db/migrate/20160129021044_devise_create_integral_users.rb +42 -0
  679. data/db/migrate/20160130051535_add_name_and_avatar_to_users.rb +6 -0
  680. data/db/migrate/20160201003936_add_roles.rb +13 -0
  681. data/db/migrate/20160302071241_create_integral_images.rb +13 -0
  682. data/db/migrate/20160311092506_create_ckeditor_assets.rb +26 -0
  683. data/db/migrate/20160318004136_create_integral_pages.rb +12 -0
  684. data/db/migrate/20160513033619_create_integral_posts.rb +12 -0
  685. data/db/migrate/20160514063048_add_slug_column_to_post.rb +6 -0
  686. data/db/migrate/20160516084702_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb +31 -0
  687. data/db/migrate/20160516084703_add_missing_unique_indices.acts_as_taggable_on_engine.rb +20 -0
  688. data/db/migrate/20160516084704_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb +15 -0
  689. data/db/migrate/20160516084705_add_missing_taggable_index.acts_as_taggable_on_engine.rb +10 -0
  690. data/db/migrate/20160516084706_change_collation_for_tag_names.acts_as_taggable_on_engine.rb +10 -0
  691. data/db/migrate/20160519005736_add_image_to_posts.rb +5 -0
  692. data/db/migrate/20160519053329_create_friendly_id_slugs.rb +15 -0
  693. data/db/migrate/20160610021858_add_view_count_to_posts.rb +5 -0
  694. data/db/migrate/20160613035508_add_drafting_to_posts.rb +6 -0
  695. data/db/migrate/20160628050006_create_integral_post_viewings.rb +10 -0
  696. data/db/migrate/20160718011218_add_locale_to_integral_users.rb +5 -0
  697. data/db/migrate/20160722100113_devise_invitable_add_to_integral_users.rb +23 -0
  698. data/db/migrate/20160809115906_add_drafting_to_pages.rb +5 -0
  699. data/db/migrate/20160909124940_add_deleted_at_to_objects.rb +15 -0
  700. data/db/migrate/20161014175823_create_lists.rb +31 -0
  701. data/db/migrate/20161102094859_create_settings.rb +18 -0
  702. data/db/migrate/20170215012231_add_templates_to_pages.rb +5 -0
  703. data/db/migrate/20170425091312_add_image_processing_fields.rb +7 -0
  704. data/db/migrate/20170516033523_add_timestamps_to_lists.rb +6 -0
  705. data/db/migrate/20170608131624_add_file_size_to_images.rb +5 -0
  706. data/db/migrate/20170801182434_add_parent_to_pages.rb +5 -0
  707. data/db/migrate/20170922201940_add_image_id_to_posts.rb +9 -0
  708. data/db/migrate/20171008193414_create_post_versions.rb +21 -0
  709. data/db/migrate/20171030215146_create_page_versions.rb +20 -0
  710. data/db/migrate/20171030215154_create_user_versions.rb +20 -0
  711. data/db/migrate/20171030215202_create_list_versions.rb +20 -0
  712. data/db/migrate/20171123155010_create_integral_enquiries.rb +13 -0
  713. data/db/migrate/20171127141132_add_deleted_at_to_lists.rb +6 -0
  714. data/db/migrate/20171230213848_add_image_to_pages.rb +6 -0
  715. data/db/migrate/20180202010010_add_lock_version_to_integral_objects.rb +9 -0
  716. data/db/migrate/20180202010020_create_image_versions.rb +20 -0
  717. data/db/migrate/20180207174914_add_fields_to_lists.rb +7 -0
  718. data/db/migrate/20180223232512_create_integral_newsletter_signups.rb +11 -0
  719. data/db/migrate/20180306204912_add_admin_to_integral_users.rb +5 -0
  720. data/db/migrate/20180326224500_add_processed_to_enquiries_and_newsletters.rb +6 -0
  721. data/db/migrate/20180509101917_add_context_to_enquiries.rb +6 -0
  722. data/db/migrate/20180920030236_update_posts_and_pages_null.rb +6 -0
  723. data/db/migrate/20181011234446_add_preview_image_to_posts.rb +6 -0
  724. data/db/seeds.rb +53 -0
  725. data/lib/generators/integral/install_generator.rb +19 -0
  726. data/lib/generators/templates/app.yml +24 -0
  727. data/lib/generators/templates/carrierwave.rb +35 -0
  728. data/lib/generators/templates/carrierwave_backgrounder.rb +11 -0
  729. data/lib/generators/templates/integral.rb +129 -0
  730. data/lib/generators/templates/sitemap.rb +41 -0
  731. data/lib/integral.rb +155 -0
  732. data/lib/integral/acts_as_listable.rb +45 -0
  733. data/lib/integral/button_link_renderer.rb +54 -0
  734. data/lib/integral/chart_renderer/base.rb +80 -0
  735. data/lib/integral/chart_renderer/donut.rb +21 -0
  736. data/lib/integral/chart_renderer/line.rb +24 -0
  737. data/lib/integral/content_renderer.rb +78 -0
  738. data/lib/integral/engine.rb +124 -0
  739. data/lib/integral/foundation_builder.rb +33 -0
  740. data/lib/integral/google_tag_manager.rb +33 -0
  741. data/lib/integral/grids/activities_grid.rb +37 -0
  742. data/lib/integral/grids/images_grid.rb +21 -0
  743. data/lib/integral/grids/lists_grid.rb +21 -0
  744. data/lib/integral/grids/pages_grid.rb +27 -0
  745. data/lib/integral/grids/posts_grid.rb +32 -0
  746. data/lib/integral/grids/users_grid.rb +22 -0
  747. data/lib/integral/list_item_renderer.rb +204 -0
  748. data/lib/integral/list_renderer.rb +91 -0
  749. data/lib/integral/middleware/page_router.rb +84 -0
  750. data/lib/integral/partial_list_item_renderer.rb +40 -0
  751. data/lib/integral/router.rb +106 -0
  752. data/lib/integral/slack_bot.rb +45 -0
  753. data/lib/integral/swiper_list_renderer.rb +30 -0
  754. data/lib/integral/version.rb +5 -0
  755. data/lib/integral/widgets/recent_posts.rb +41 -0
  756. data/lib/integral/widgets/swiper_list.rb +40 -0
  757. data/lib/tasks/integral_tasks.rake +57 -0
  758. data/lib/templates/erb/scaffold/_form.html.erb +13 -0
  759. data/spec/factories.rb +114 -0
  760. data/spec/support/image.jpg +0 -0
  761. metadata +1734 -0
@@ -0,0 +1,2451 @@
1
+ /*!
2
+ * typeahead.js 0.11.1
3
+ * https://github.com/twitter/typeahead.js
4
+ * Copyright 2013-2015 Twitter, Inc. and other contributors; Licensed MIT
5
+ */
6
+
7
+ (function(root, factory) {
8
+ if (typeof define === "function" && define.amd) {
9
+ define("bloodhound", [ "jquery" ], function(a0) {
10
+ return root["Bloodhound"] = factory(a0);
11
+ });
12
+ } else if (typeof exports === "object") {
13
+ module.exports = factory(require("jquery"));
14
+ } else {
15
+ root["Bloodhound"] = factory(jQuery);
16
+ }
17
+ })(this, function($) {
18
+ var _ = function() {
19
+ "use strict";
20
+ return {
21
+ isMsie: function() {
22
+ return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2] : false;
23
+ },
24
+ isBlankString: function(str) {
25
+ return !str || /^\s*$/.test(str);
26
+ },
27
+ escapeRegExChars: function(str) {
28
+ return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
29
+ },
30
+ isString: function(obj) {
31
+ return typeof obj === "string";
32
+ },
33
+ isNumber: function(obj) {
34
+ return typeof obj === "number";
35
+ },
36
+ isArray: $.isArray,
37
+ isFunction: $.isFunction,
38
+ isObject: $.isPlainObject,
39
+ isUndefined: function(obj) {
40
+ return typeof obj === "undefined";
41
+ },
42
+ isElement: function(obj) {
43
+ return !!(obj && obj.nodeType === 1);
44
+ },
45
+ isJQuery: function(obj) {
46
+ return obj instanceof $;
47
+ },
48
+ toStr: function toStr(s) {
49
+ return _.isUndefined(s) || s === null ? "" : s + "";
50
+ },
51
+ bind: $.proxy,
52
+ each: function(collection, cb) {
53
+ $.each(collection, reverseArgs);
54
+ function reverseArgs(index, value) {
55
+ return cb(value, index);
56
+ }
57
+ },
58
+ map: $.map,
59
+ filter: $.grep,
60
+ every: function(obj, test) {
61
+ var result = true;
62
+ if (!obj) {
63
+ return result;
64
+ }
65
+ $.each(obj, function(key, val) {
66
+ if (!(result = test.call(null, val, key, obj))) {
67
+ return false;
68
+ }
69
+ });
70
+ return !!result;
71
+ },
72
+ some: function(obj, test) {
73
+ var result = false;
74
+ if (!obj) {
75
+ return result;
76
+ }
77
+ $.each(obj, function(key, val) {
78
+ if (result = test.call(null, val, key, obj)) {
79
+ return false;
80
+ }
81
+ });
82
+ return !!result;
83
+ },
84
+ mixin: $.extend,
85
+ identity: function(x) {
86
+ return x;
87
+ },
88
+ clone: function(obj) {
89
+ return $.extend(true, {}, obj);
90
+ },
91
+ getIdGenerator: function() {
92
+ var counter = 0;
93
+ return function() {
94
+ return counter++;
95
+ };
96
+ },
97
+ templatify: function templatify(obj) {
98
+ return $.isFunction(obj) ? obj : template;
99
+ function template() {
100
+ return String(obj);
101
+ }
102
+ },
103
+ defer: function(fn) {
104
+ setTimeout(fn, 0);
105
+ },
106
+ debounce: function(func, wait, immediate) {
107
+ var timeout, result;
108
+ return function() {
109
+ var context = this, args = arguments, later, callNow;
110
+ later = function() {
111
+ timeout = null;
112
+ if (!immediate) {
113
+ result = func.apply(context, args);
114
+ }
115
+ };
116
+ callNow = immediate && !timeout;
117
+ clearTimeout(timeout);
118
+ timeout = setTimeout(later, wait);
119
+ if (callNow) {
120
+ result = func.apply(context, args);
121
+ }
122
+ return result;
123
+ };
124
+ },
125
+ throttle: function(func, wait) {
126
+ var context, args, timeout, result, previous, later;
127
+ previous = 0;
128
+ later = function() {
129
+ previous = new Date();
130
+ timeout = null;
131
+ result = func.apply(context, args);
132
+ };
133
+ return function() {
134
+ var now = new Date(), remaining = wait - (now - previous);
135
+ context = this;
136
+ args = arguments;
137
+ if (remaining <= 0) {
138
+ clearTimeout(timeout);
139
+ timeout = null;
140
+ previous = now;
141
+ result = func.apply(context, args);
142
+ } else if (!timeout) {
143
+ timeout = setTimeout(later, remaining);
144
+ }
145
+ return result;
146
+ };
147
+ },
148
+ stringify: function(val) {
149
+ return _.isString(val) ? val : JSON.stringify(val);
150
+ },
151
+ noop: function() {}
152
+ };
153
+ }();
154
+ var VERSION = "0.11.1";
155
+ var tokenizers = function() {
156
+ "use strict";
157
+ return {
158
+ nonword: nonword,
159
+ whitespace: whitespace,
160
+ obj: {
161
+ nonword: getObjTokenizer(nonword),
162
+ whitespace: getObjTokenizer(whitespace)
163
+ }
164
+ };
165
+ function whitespace(str) {
166
+ str = _.toStr(str);
167
+ return str ? str.split(/\s+/) : [];
168
+ }
169
+ function nonword(str) {
170
+ str = _.toStr(str);
171
+ return str ? str.split(/\W+/) : [];
172
+ }
173
+ function getObjTokenizer(tokenizer) {
174
+ return function setKey(keys) {
175
+ keys = _.isArray(keys) ? keys : [].slice.call(arguments, 0);
176
+ return function tokenize(o) {
177
+ var tokens = [];
178
+ _.each(keys, function(k) {
179
+ tokens = tokens.concat(tokenizer(_.toStr(o[k])));
180
+ });
181
+ return tokens;
182
+ };
183
+ };
184
+ }
185
+ }();
186
+ var LruCache = function() {
187
+ "use strict";
188
+ function LruCache(maxSize) {
189
+ this.maxSize = _.isNumber(maxSize) ? maxSize : 100;
190
+ this.reset();
191
+ if (this.maxSize <= 0) {
192
+ this.set = this.get = $.noop;
193
+ }
194
+ }
195
+ _.mixin(LruCache.prototype, {
196
+ set: function set(key, val) {
197
+ var tailItem = this.list.tail, node;
198
+ if (this.size >= this.maxSize) {
199
+ this.list.remove(tailItem);
200
+ delete this.hash[tailItem.key];
201
+ this.size--;
202
+ }
203
+ if (node = this.hash[key]) {
204
+ node.val = val;
205
+ this.list.moveToFront(node);
206
+ } else {
207
+ node = new Node(key, val);
208
+ this.list.add(node);
209
+ this.hash[key] = node;
210
+ this.size++;
211
+ }
212
+ },
213
+ get: function get(key) {
214
+ var node = this.hash[key];
215
+ if (node) {
216
+ this.list.moveToFront(node);
217
+ return node.val;
218
+ }
219
+ },
220
+ reset: function reset() {
221
+ this.size = 0;
222
+ this.hash = {};
223
+ this.list = new List();
224
+ }
225
+ });
226
+ function List() {
227
+ this.head = this.tail = null;
228
+ }
229
+ _.mixin(List.prototype, {
230
+ add: function add(node) {
231
+ if (this.head) {
232
+ node.next = this.head;
233
+ this.head.prev = node;
234
+ }
235
+ this.head = node;
236
+ this.tail = this.tail || node;
237
+ },
238
+ remove: function remove(node) {
239
+ node.prev ? node.prev.next = node.next : this.head = node.next;
240
+ node.next ? node.next.prev = node.prev : this.tail = node.prev;
241
+ },
242
+ moveToFront: function(node) {
243
+ this.remove(node);
244
+ this.add(node);
245
+ }
246
+ });
247
+ function Node(key, val) {
248
+ this.key = key;
249
+ this.val = val;
250
+ this.prev = this.next = null;
251
+ }
252
+ return LruCache;
253
+ }();
254
+ var PersistentStorage = function() {
255
+ "use strict";
256
+ var LOCAL_STORAGE;
257
+ try {
258
+ LOCAL_STORAGE = window.localStorage;
259
+ LOCAL_STORAGE.setItem("~~~", "!");
260
+ LOCAL_STORAGE.removeItem("~~~");
261
+ } catch (err) {
262
+ LOCAL_STORAGE = null;
263
+ }
264
+ function PersistentStorage(namespace, override) {
265
+ this.prefix = [ "__", namespace, "__" ].join("");
266
+ this.ttlKey = "__ttl__";
267
+ this.keyMatcher = new RegExp("^" + _.escapeRegExChars(this.prefix));
268
+ this.ls = override || LOCAL_STORAGE;
269
+ !this.ls && this._noop();
270
+ }
271
+ _.mixin(PersistentStorage.prototype, {
272
+ _prefix: function(key) {
273
+ return this.prefix + key;
274
+ },
275
+ _ttlKey: function(key) {
276
+ return this._prefix(key) + this.ttlKey;
277
+ },
278
+ _noop: function() {
279
+ this.get = this.set = this.remove = this.clear = this.isExpired = _.noop;
280
+ },
281
+ _safeSet: function(key, val) {
282
+ try {
283
+ this.ls.setItem(key, val);
284
+ } catch (err) {
285
+ if (err.name === "QuotaExceededError") {
286
+ this.clear();
287
+ this._noop();
288
+ }
289
+ }
290
+ },
291
+ get: function(key) {
292
+ if (this.isExpired(key)) {
293
+ this.remove(key);
294
+ }
295
+ return decode(this.ls.getItem(this._prefix(key)));
296
+ },
297
+ set: function(key, val, ttl) {
298
+ if (_.isNumber(ttl)) {
299
+ this._safeSet(this._ttlKey(key), encode(now() + ttl));
300
+ } else {
301
+ this.ls.removeItem(this._ttlKey(key));
302
+ }
303
+ return this._safeSet(this._prefix(key), encode(val));
304
+ },
305
+ remove: function(key) {
306
+ this.ls.removeItem(this._ttlKey(key));
307
+ this.ls.removeItem(this._prefix(key));
308
+ return this;
309
+ },
310
+ clear: function() {
311
+ var i, keys = gatherMatchingKeys(this.keyMatcher);
312
+ for (i = keys.length; i--; ) {
313
+ this.remove(keys[i]);
314
+ }
315
+ return this;
316
+ },
317
+ isExpired: function(key) {
318
+ var ttl = decode(this.ls.getItem(this._ttlKey(key)));
319
+ return _.isNumber(ttl) && now() > ttl ? true : false;
320
+ }
321
+ });
322
+ return PersistentStorage;
323
+ function now() {
324
+ return new Date().getTime();
325
+ }
326
+ function encode(val) {
327
+ return JSON.stringify(_.isUndefined(val) ? null : val);
328
+ }
329
+ function decode(val) {
330
+ return $.parseJSON(val);
331
+ }
332
+ function gatherMatchingKeys(keyMatcher) {
333
+ var i, key, keys = [], len = LOCAL_STORAGE.length;
334
+ for (i = 0; i < len; i++) {
335
+ if ((key = LOCAL_STORAGE.key(i)).match(keyMatcher)) {
336
+ keys.push(key.replace(keyMatcher, ""));
337
+ }
338
+ }
339
+ return keys;
340
+ }
341
+ }();
342
+ var Transport = function() {
343
+ "use strict";
344
+ var pendingRequestsCount = 0, pendingRequests = {}, maxPendingRequests = 6, sharedCache = new LruCache(10);
345
+ function Transport(o) {
346
+ o = o || {};
347
+ this.cancelled = false;
348
+ this.lastReq = null;
349
+ this._send = o.transport;
350
+ this._get = o.limiter ? o.limiter(this._get) : this._get;
351
+ this._cache = o.cache === false ? new LruCache(0) : sharedCache;
352
+ }
353
+ Transport.setMaxPendingRequests = function setMaxPendingRequests(num) {
354
+ maxPendingRequests = num;
355
+ };
356
+ Transport.resetCache = function resetCache() {
357
+ sharedCache.reset();
358
+ };
359
+ _.mixin(Transport.prototype, {
360
+ _fingerprint: function fingerprint(o) {
361
+ o = o || {};
362
+ return o.url + o.type + $.param(o.data || {});
363
+ },
364
+ _get: function(o, cb) {
365
+ var that = this, fingerprint, jqXhr;
366
+ fingerprint = this._fingerprint(o);
367
+ if (this.cancelled || fingerprint !== this.lastReq) {
368
+ return;
369
+ }
370
+ if (jqXhr = pendingRequests[fingerprint]) {
371
+ jqXhr.done(done).fail(fail);
372
+ } else if (pendingRequestsCount < maxPendingRequests) {
373
+ pendingRequestsCount++;
374
+ pendingRequests[fingerprint] = this._send(o).done(done).fail(fail).always(always);
375
+ } else {
376
+ this.onDeckRequestArgs = [].slice.call(arguments, 0);
377
+ }
378
+ function done(resp) {
379
+ cb(null, resp);
380
+ that._cache.set(fingerprint, resp);
381
+ }
382
+ function fail() {
383
+ cb(true);
384
+ }
385
+ function always() {
386
+ pendingRequestsCount--;
387
+ delete pendingRequests[fingerprint];
388
+ if (that.onDeckRequestArgs) {
389
+ that._get.apply(that, that.onDeckRequestArgs);
390
+ that.onDeckRequestArgs = null;
391
+ }
392
+ }
393
+ },
394
+ get: function(o, cb) {
395
+ var resp, fingerprint;
396
+ cb = cb || $.noop;
397
+ o = _.isString(o) ? {
398
+ url: o
399
+ } : o || {};
400
+ fingerprint = this._fingerprint(o);
401
+ this.cancelled = false;
402
+ this.lastReq = fingerprint;
403
+ if (resp = this._cache.get(fingerprint)) {
404
+ cb(null, resp);
405
+ } else {
406
+ this._get(o, cb);
407
+ }
408
+ },
409
+ cancel: function() {
410
+ this.cancelled = true;
411
+ }
412
+ });
413
+ return Transport;
414
+ }();
415
+ var SearchIndex = window.SearchIndex = function() {
416
+ "use strict";
417
+ var CHILDREN = "c", IDS = "i";
418
+ function SearchIndex(o) {
419
+ o = o || {};
420
+ if (!o.datumTokenizer || !o.queryTokenizer) {
421
+ $.error("datumTokenizer and queryTokenizer are both required");
422
+ }
423
+ this.identify = o.identify || _.stringify;
424
+ this.datumTokenizer = o.datumTokenizer;
425
+ this.queryTokenizer = o.queryTokenizer;
426
+ this.reset();
427
+ }
428
+ _.mixin(SearchIndex.prototype, {
429
+ bootstrap: function bootstrap(o) {
430
+ this.datums = o.datums;
431
+ this.trie = o.trie;
432
+ },
433
+ add: function(data) {
434
+ var that = this;
435
+ data = _.isArray(data) ? data : [ data ];
436
+ _.each(data, function(datum) {
437
+ var id, tokens;
438
+ that.datums[id = that.identify(datum)] = datum;
439
+ tokens = normalizeTokens(that.datumTokenizer(datum));
440
+ _.each(tokens, function(token) {
441
+ var node, chars, ch;
442
+ node = that.trie;
443
+ chars = token.split("");
444
+ while (ch = chars.shift()) {
445
+ node = node[CHILDREN][ch] || (node[CHILDREN][ch] = newNode());
446
+ node[IDS].push(id);
447
+ }
448
+ });
449
+ });
450
+ },
451
+ get: function get(ids) {
452
+ var that = this;
453
+ return _.map(ids, function(id) {
454
+ return that.datums[id];
455
+ });
456
+ },
457
+ search: function search(query) {
458
+ var that = this, tokens, matches;
459
+ tokens = normalizeTokens(this.queryTokenizer(query));
460
+ _.each(tokens, function(token) {
461
+ var node, chars, ch, ids;
462
+ if (matches && matches.length === 0) {
463
+ return false;
464
+ }
465
+ node = that.trie;
466
+ chars = token.split("");
467
+ while (node && (ch = chars.shift())) {
468
+ node = node[CHILDREN][ch];
469
+ }
470
+ if (node && chars.length === 0) {
471
+ ids = node[IDS].slice(0);
472
+ matches = matches ? getIntersection(matches, ids) : ids;
473
+ } else {
474
+ matches = [];
475
+ return false;
476
+ }
477
+ });
478
+ return matches ? _.map(unique(matches), function(id) {
479
+ return that.datums[id];
480
+ }) : [];
481
+ },
482
+ all: function all() {
483
+ var values = [];
484
+ for (var key in this.datums) {
485
+ values.push(this.datums[key]);
486
+ }
487
+ return values;
488
+ },
489
+ reset: function reset() {
490
+ this.datums = {};
491
+ this.trie = newNode();
492
+ },
493
+ serialize: function serialize() {
494
+ return {
495
+ datums: this.datums,
496
+ trie: this.trie
497
+ };
498
+ }
499
+ });
500
+ return SearchIndex;
501
+ function normalizeTokens(tokens) {
502
+ tokens = _.filter(tokens, function(token) {
503
+ return !!token;
504
+ });
505
+ tokens = _.map(tokens, function(token) {
506
+ return token.toLowerCase();
507
+ });
508
+ return tokens;
509
+ }
510
+ function newNode() {
511
+ var node = {};
512
+ node[IDS] = [];
513
+ node[CHILDREN] = {};
514
+ return node;
515
+ }
516
+ function unique(array) {
517
+ var seen = {}, uniques = [];
518
+ for (var i = 0, len = array.length; i < len; i++) {
519
+ if (!seen[array[i]]) {
520
+ seen[array[i]] = true;
521
+ uniques.push(array[i]);
522
+ }
523
+ }
524
+ return uniques;
525
+ }
526
+ function getIntersection(arrayA, arrayB) {
527
+ var ai = 0, bi = 0, intersection = [];
528
+ arrayA = arrayA.sort();
529
+ arrayB = arrayB.sort();
530
+ var lenArrayA = arrayA.length, lenArrayB = arrayB.length;
531
+ while (ai < lenArrayA && bi < lenArrayB) {
532
+ if (arrayA[ai] < arrayB[bi]) {
533
+ ai++;
534
+ } else if (arrayA[ai] > arrayB[bi]) {
535
+ bi++;
536
+ } else {
537
+ intersection.push(arrayA[ai]);
538
+ ai++;
539
+ bi++;
540
+ }
541
+ }
542
+ return intersection;
543
+ }
544
+ }();
545
+ var Prefetch = function() {
546
+ "use strict";
547
+ var keys;
548
+ keys = {
549
+ data: "data",
550
+ protocol: "protocol",
551
+ thumbprint: "thumbprint"
552
+ };
553
+ function Prefetch(o) {
554
+ this.url = o.url;
555
+ this.ttl = o.ttl;
556
+ this.cache = o.cache;
557
+ this.prepare = o.prepare;
558
+ this.transform = o.transform;
559
+ this.transport = o.transport;
560
+ this.thumbprint = o.thumbprint;
561
+ this.storage = new PersistentStorage(o.cacheKey);
562
+ }
563
+ _.mixin(Prefetch.prototype, {
564
+ _settings: function settings() {
565
+ return {
566
+ url: this.url,
567
+ type: "GET",
568
+ dataType: "json"
569
+ };
570
+ },
571
+ store: function store(data) {
572
+ if (!this.cache) {
573
+ return;
574
+ }
575
+ this.storage.set(keys.data, data, this.ttl);
576
+ this.storage.set(keys.protocol, location.protocol, this.ttl);
577
+ this.storage.set(keys.thumbprint, this.thumbprint, this.ttl);
578
+ },
579
+ fromCache: function fromCache() {
580
+ var stored = {}, isExpired;
581
+ if (!this.cache) {
582
+ return null;
583
+ }
584
+ stored.data = this.storage.get(keys.data);
585
+ stored.protocol = this.storage.get(keys.protocol);
586
+ stored.thumbprint = this.storage.get(keys.thumbprint);
587
+ isExpired = stored.thumbprint !== this.thumbprint || stored.protocol !== location.protocol;
588
+ return stored.data && !isExpired ? stored.data : null;
589
+ },
590
+ fromNetwork: function(cb) {
591
+ var that = this, settings;
592
+ if (!cb) {
593
+ return;
594
+ }
595
+ settings = this.prepare(this._settings());
596
+ this.transport(settings).fail(onError).done(onResponse);
597
+ function onError() {
598
+ cb(true);
599
+ }
600
+ function onResponse(resp) {
601
+ cb(null, that.transform(resp));
602
+ }
603
+ },
604
+ clear: function clear() {
605
+ this.storage.clear();
606
+ return this;
607
+ }
608
+ });
609
+ return Prefetch;
610
+ }();
611
+ var Remote = function() {
612
+ "use strict";
613
+ function Remote(o) {
614
+ this.url = o.url;
615
+ this.prepare = o.prepare;
616
+ this.transform = o.transform;
617
+ this.transport = new Transport({
618
+ cache: o.cache,
619
+ limiter: o.limiter,
620
+ transport: o.transport
621
+ });
622
+ }
623
+ _.mixin(Remote.prototype, {
624
+ _settings: function settings() {
625
+ return {
626
+ url: this.url,
627
+ type: "GET",
628
+ dataType: "json"
629
+ };
630
+ },
631
+ get: function get(query, cb) {
632
+ var that = this, settings;
633
+ if (!cb) {
634
+ return;
635
+ }
636
+ query = query || "";
637
+ settings = this.prepare(query, this._settings());
638
+ return this.transport.get(settings, onResponse);
639
+ function onResponse(err, resp) {
640
+ err ? cb([]) : cb(that.transform(resp));
641
+ }
642
+ },
643
+ cancelLastRequest: function cancelLastRequest() {
644
+ this.transport.cancel();
645
+ }
646
+ });
647
+ return Remote;
648
+ }();
649
+ var oParser = function() {
650
+ "use strict";
651
+ return function parse(o) {
652
+ var defaults, sorter;
653
+ defaults = {
654
+ initialize: true,
655
+ identify: _.stringify,
656
+ datumTokenizer: null,
657
+ queryTokenizer: null,
658
+ sufficient: 5,
659
+ sorter: null,
660
+ local: [],
661
+ prefetch: null,
662
+ remote: null
663
+ };
664
+ o = _.mixin(defaults, o || {});
665
+ !o.datumTokenizer && $.error("datumTokenizer is required");
666
+ !o.queryTokenizer && $.error("queryTokenizer is required");
667
+ sorter = o.sorter;
668
+ o.sorter = sorter ? function(x) {
669
+ return x.sort(sorter);
670
+ } : _.identity;
671
+ o.local = _.isFunction(o.local) ? o.local() : o.local;
672
+ o.prefetch = parsePrefetch(o.prefetch);
673
+ o.remote = parseRemote(o.remote);
674
+ return o;
675
+ };
676
+ function parsePrefetch(o) {
677
+ var defaults;
678
+ if (!o) {
679
+ return null;
680
+ }
681
+ defaults = {
682
+ url: null,
683
+ ttl: 24 * 60 * 60 * 1e3,
684
+ cache: true,
685
+ cacheKey: null,
686
+ thumbprint: "",
687
+ prepare: _.identity,
688
+ transform: _.identity,
689
+ transport: null
690
+ };
691
+ o = _.isString(o) ? {
692
+ url: o
693
+ } : o;
694
+ o = _.mixin(defaults, o);
695
+ !o.url && $.error("prefetch requires url to be set");
696
+ o.transform = o.filter || o.transform;
697
+ o.cacheKey = o.cacheKey || o.url;
698
+ o.thumbprint = VERSION + o.thumbprint;
699
+ o.transport = o.transport ? callbackToDeferred(o.transport) : $.ajax;
700
+ return o;
701
+ }
702
+ function parseRemote(o) {
703
+ var defaults;
704
+ if (!o) {
705
+ return;
706
+ }
707
+ defaults = {
708
+ url: null,
709
+ cache: true,
710
+ prepare: null,
711
+ replace: null,
712
+ wildcard: null,
713
+ limiter: null,
714
+ rateLimitBy: "debounce",
715
+ rateLimitWait: 300,
716
+ transform: _.identity,
717
+ transport: null
718
+ };
719
+ o = _.isString(o) ? {
720
+ url: o
721
+ } : o;
722
+ o = _.mixin(defaults, o);
723
+ !o.url && $.error("remote requires url to be set");
724
+ o.transform = o.filter || o.transform;
725
+ o.prepare = toRemotePrepare(o);
726
+ o.limiter = toLimiter(o);
727
+ o.transport = o.transport ? callbackToDeferred(o.transport) : $.ajax;
728
+ delete o.replace;
729
+ delete o.wildcard;
730
+ delete o.rateLimitBy;
731
+ delete o.rateLimitWait;
732
+ return o;
733
+ }
734
+ function toRemotePrepare(o) {
735
+ var prepare, replace, wildcard;
736
+ prepare = o.prepare;
737
+ replace = o.replace;
738
+ wildcard = o.wildcard;
739
+ if (prepare) {
740
+ return prepare;
741
+ }
742
+ if (replace) {
743
+ prepare = prepareByReplace;
744
+ } else if (o.wildcard) {
745
+ prepare = prepareByWildcard;
746
+ } else {
747
+ prepare = idenityPrepare;
748
+ }
749
+ return prepare;
750
+ function prepareByReplace(query, settings) {
751
+ settings.url = replace(settings.url, query);
752
+ return settings;
753
+ }
754
+ function prepareByWildcard(query, settings) {
755
+ settings.url = settings.url.replace(wildcard, encodeURIComponent(query));
756
+ return settings;
757
+ }
758
+ function idenityPrepare(query, settings) {
759
+ return settings;
760
+ }
761
+ }
762
+ function toLimiter(o) {
763
+ var limiter, method, wait;
764
+ limiter = o.limiter;
765
+ method = o.rateLimitBy;
766
+ wait = o.rateLimitWait;
767
+ if (!limiter) {
768
+ limiter = /^throttle$/i.test(method) ? throttle(wait) : debounce(wait);
769
+ }
770
+ return limiter;
771
+ function debounce(wait) {
772
+ return function debounce(fn) {
773
+ return _.debounce(fn, wait);
774
+ };
775
+ }
776
+ function throttle(wait) {
777
+ return function throttle(fn) {
778
+ return _.throttle(fn, wait);
779
+ };
780
+ }
781
+ }
782
+ function callbackToDeferred(fn) {
783
+ return function wrapper(o) {
784
+ var deferred = $.Deferred();
785
+ fn(o, onSuccess, onError);
786
+ return deferred;
787
+ function onSuccess(resp) {
788
+ _.defer(function() {
789
+ deferred.resolve(resp);
790
+ });
791
+ }
792
+ function onError(err) {
793
+ _.defer(function() {
794
+ deferred.reject(err);
795
+ });
796
+ }
797
+ };
798
+ }
799
+ }();
800
+ var Bloodhound = function() {
801
+ "use strict";
802
+ var old;
803
+ old = window && window.Bloodhound;
804
+ function Bloodhound(o) {
805
+ o = oParser(o);
806
+ this.sorter = o.sorter;
807
+ this.identify = o.identify;
808
+ this.sufficient = o.sufficient;
809
+ this.local = o.local;
810
+ this.remote = o.remote ? new Remote(o.remote) : null;
811
+ this.prefetch = o.prefetch ? new Prefetch(o.prefetch) : null;
812
+ this.index = new SearchIndex({
813
+ identify: this.identify,
814
+ datumTokenizer: o.datumTokenizer,
815
+ queryTokenizer: o.queryTokenizer
816
+ });
817
+ o.initialize !== false && this.initialize();
818
+ }
819
+ Bloodhound.noConflict = function noConflict() {
820
+ window && (window.Bloodhound = old);
821
+ return Bloodhound;
822
+ };
823
+ Bloodhound.tokenizers = tokenizers;
824
+ _.mixin(Bloodhound.prototype, {
825
+ __ttAdapter: function ttAdapter() {
826
+ var that = this;
827
+ return this.remote ? withAsync : withoutAsync;
828
+ function withAsync(query, sync, async) {
829
+ return that.search(query, sync, async);
830
+ }
831
+ function withoutAsync(query, sync) {
832
+ return that.search(query, sync);
833
+ }
834
+ },
835
+ _loadPrefetch: function loadPrefetch() {
836
+ var that = this, deferred, serialized;
837
+ deferred = $.Deferred();
838
+ if (!this.prefetch) {
839
+ deferred.resolve();
840
+ } else if (serialized = this.prefetch.fromCache()) {
841
+ this.index.bootstrap(serialized);
842
+ deferred.resolve();
843
+ } else {
844
+ this.prefetch.fromNetwork(done);
845
+ }
846
+ return deferred.promise();
847
+ function done(err, data) {
848
+ if (err) {
849
+ return deferred.reject();
850
+ }
851
+ that.add(data);
852
+ that.prefetch.store(that.index.serialize());
853
+ deferred.resolve();
854
+ }
855
+ },
856
+ _initialize: function initialize() {
857
+ var that = this, deferred;
858
+ this.clear();
859
+ (this.initPromise = this._loadPrefetch()).done(addLocalToIndex);
860
+ return this.initPromise;
861
+ function addLocalToIndex() {
862
+ that.add(that.local);
863
+ }
864
+ },
865
+ initialize: function initialize(force) {
866
+ return !this.initPromise || force ? this._initialize() : this.initPromise;
867
+ },
868
+ add: function add(data) {
869
+ this.index.add(data);
870
+ return this;
871
+ },
872
+ get: function get(ids) {
873
+ ids = _.isArray(ids) ? ids : [].slice.call(arguments);
874
+ return this.index.get(ids);
875
+ },
876
+ search: function search(query, sync, async) {
877
+ var that = this, local;
878
+ local = this.sorter(this.index.search(query));
879
+ sync(this.remote ? local.slice() : local);
880
+ if (this.remote && local.length < this.sufficient) {
881
+ this.remote.get(query, processRemote);
882
+ } else if (this.remote) {
883
+ this.remote.cancelLastRequest();
884
+ }
885
+ return this;
886
+ function processRemote(remote) {
887
+ var nonDuplicates = [];
888
+ _.each(remote, function(r) {
889
+ !_.some(local, function(l) {
890
+ return that.identify(r) === that.identify(l);
891
+ }) && nonDuplicates.push(r);
892
+ });
893
+ async && async(nonDuplicates);
894
+ }
895
+ },
896
+ all: function all() {
897
+ return this.index.all();
898
+ },
899
+ clear: function clear() {
900
+ this.index.reset();
901
+ return this;
902
+ },
903
+ clearPrefetchCache: function clearPrefetchCache() {
904
+ this.prefetch && this.prefetch.clear();
905
+ return this;
906
+ },
907
+ clearRemoteCache: function clearRemoteCache() {
908
+ Transport.resetCache();
909
+ return this;
910
+ },
911
+ ttAdapter: function ttAdapter() {
912
+ return this.__ttAdapter();
913
+ }
914
+ });
915
+ return Bloodhound;
916
+ }();
917
+ return Bloodhound;
918
+ });
919
+
920
+ (function(root, factory) {
921
+ if (typeof define === "function" && define.amd) {
922
+ define("typeahead.js", [ "jquery" ], function(a0) {
923
+ return factory(a0);
924
+ });
925
+ } else if (typeof exports === "object") {
926
+ module.exports = factory(require("jquery"));
927
+ } else {
928
+ factory(jQuery);
929
+ }
930
+ })(this, function($) {
931
+ var _ = function() {
932
+ "use strict";
933
+ return {
934
+ isMsie: function() {
935
+ return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2] : false;
936
+ },
937
+ isBlankString: function(str) {
938
+ return !str || /^\s*$/.test(str);
939
+ },
940
+ escapeRegExChars: function(str) {
941
+ return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
942
+ },
943
+ isString: function(obj) {
944
+ return typeof obj === "string";
945
+ },
946
+ isNumber: function(obj) {
947
+ return typeof obj === "number";
948
+ },
949
+ isArray: $.isArray,
950
+ isFunction: $.isFunction,
951
+ isObject: $.isPlainObject,
952
+ isUndefined: function(obj) {
953
+ return typeof obj === "undefined";
954
+ },
955
+ isElement: function(obj) {
956
+ return !!(obj && obj.nodeType === 1);
957
+ },
958
+ isJQuery: function(obj) {
959
+ return obj instanceof $;
960
+ },
961
+ toStr: function toStr(s) {
962
+ return _.isUndefined(s) || s === null ? "" : s + "";
963
+ },
964
+ bind: $.proxy,
965
+ each: function(collection, cb) {
966
+ $.each(collection, reverseArgs);
967
+ function reverseArgs(index, value) {
968
+ return cb(value, index);
969
+ }
970
+ },
971
+ map: $.map,
972
+ filter: $.grep,
973
+ every: function(obj, test) {
974
+ var result = true;
975
+ if (!obj) {
976
+ return result;
977
+ }
978
+ $.each(obj, function(key, val) {
979
+ if (!(result = test.call(null, val, key, obj))) {
980
+ return false;
981
+ }
982
+ });
983
+ return !!result;
984
+ },
985
+ some: function(obj, test) {
986
+ var result = false;
987
+ if (!obj) {
988
+ return result;
989
+ }
990
+ $.each(obj, function(key, val) {
991
+ if (result = test.call(null, val, key, obj)) {
992
+ return false;
993
+ }
994
+ });
995
+ return !!result;
996
+ },
997
+ mixin: $.extend,
998
+ identity: function(x) {
999
+ return x;
1000
+ },
1001
+ clone: function(obj) {
1002
+ return $.extend(true, {}, obj);
1003
+ },
1004
+ getIdGenerator: function() {
1005
+ var counter = 0;
1006
+ return function() {
1007
+ return counter++;
1008
+ };
1009
+ },
1010
+ templatify: function templatify(obj) {
1011
+ return $.isFunction(obj) ? obj : template;
1012
+ function template() {
1013
+ return String(obj);
1014
+ }
1015
+ },
1016
+ defer: function(fn) {
1017
+ setTimeout(fn, 0);
1018
+ },
1019
+ debounce: function(func, wait, immediate) {
1020
+ var timeout, result;
1021
+ return function() {
1022
+ var context = this, args = arguments, later, callNow;
1023
+ later = function() {
1024
+ timeout = null;
1025
+ if (!immediate) {
1026
+ result = func.apply(context, args);
1027
+ }
1028
+ };
1029
+ callNow = immediate && !timeout;
1030
+ clearTimeout(timeout);
1031
+ timeout = setTimeout(later, wait);
1032
+ if (callNow) {
1033
+ result = func.apply(context, args);
1034
+ }
1035
+ return result;
1036
+ };
1037
+ },
1038
+ throttle: function(func, wait) {
1039
+ var context, args, timeout, result, previous, later;
1040
+ previous = 0;
1041
+ later = function() {
1042
+ previous = new Date();
1043
+ timeout = null;
1044
+ result = func.apply(context, args);
1045
+ };
1046
+ return function() {
1047
+ var now = new Date(), remaining = wait - (now - previous);
1048
+ context = this;
1049
+ args = arguments;
1050
+ if (remaining <= 0) {
1051
+ clearTimeout(timeout);
1052
+ timeout = null;
1053
+ previous = now;
1054
+ result = func.apply(context, args);
1055
+ } else if (!timeout) {
1056
+ timeout = setTimeout(later, remaining);
1057
+ }
1058
+ return result;
1059
+ };
1060
+ },
1061
+ stringify: function(val) {
1062
+ return _.isString(val) ? val : JSON.stringify(val);
1063
+ },
1064
+ noop: function() {}
1065
+ };
1066
+ }();
1067
+ var WWW = function() {
1068
+ "use strict";
1069
+ var defaultClassNames = {
1070
+ wrapper: "twitter-typeahead",
1071
+ input: "tt-input",
1072
+ hint: "tt-hint",
1073
+ menu: "tt-menu",
1074
+ dataset: "tt-dataset",
1075
+ suggestion: "tt-suggestion",
1076
+ selectable: "tt-selectable",
1077
+ empty: "tt-empty",
1078
+ open: "tt-open",
1079
+ cursor: "tt-cursor",
1080
+ highlight: "tt-highlight"
1081
+ };
1082
+ return build;
1083
+ function build(o) {
1084
+ var www, classes;
1085
+ classes = _.mixin({}, defaultClassNames, o);
1086
+ www = {
1087
+ css: buildCss(),
1088
+ classes: classes,
1089
+ html: buildHtml(classes),
1090
+ selectors: buildSelectors(classes)
1091
+ };
1092
+ return {
1093
+ css: www.css,
1094
+ html: www.html,
1095
+ classes: www.classes,
1096
+ selectors: www.selectors,
1097
+ mixin: function(o) {
1098
+ _.mixin(o, www);
1099
+ }
1100
+ };
1101
+ }
1102
+ function buildHtml(c) {
1103
+ return {
1104
+ wrapper: '<span class="' + c.wrapper + '"></span>',
1105
+ menu: '<div class="' + c.menu + '"></div>'
1106
+ };
1107
+ }
1108
+ function buildSelectors(classes) {
1109
+ var selectors = {};
1110
+ _.each(classes, function(v, k) {
1111
+ selectors[k] = "." + v;
1112
+ });
1113
+ return selectors;
1114
+ }
1115
+ function buildCss() {
1116
+ var css = {
1117
+ wrapper: {
1118
+ position: "relative",
1119
+ display: "inline-block"
1120
+ },
1121
+ hint: {
1122
+ position: "absolute",
1123
+ top: "0",
1124
+ left: "0",
1125
+ borderColor: "transparent",
1126
+ boxShadow: "none",
1127
+ opacity: "1"
1128
+ },
1129
+ input: {
1130
+ position: "relative",
1131
+ verticalAlign: "top",
1132
+ backgroundColor: "transparent"
1133
+ },
1134
+ inputWithNoHint: {
1135
+ position: "relative",
1136
+ verticalAlign: "top"
1137
+ },
1138
+ menu: {
1139
+ position: "absolute",
1140
+ top: "100%",
1141
+ left: "0",
1142
+ zIndex: "100",
1143
+ display: "none"
1144
+ },
1145
+ ltr: {
1146
+ left: "0",
1147
+ right: "auto"
1148
+ },
1149
+ rtl: {
1150
+ left: "auto",
1151
+ right: " 0"
1152
+ }
1153
+ };
1154
+ if (_.isMsie()) {
1155
+ _.mixin(css.input, {
1156
+ backgroundImage: "url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)"
1157
+ });
1158
+ }
1159
+ return css;
1160
+ }
1161
+ }();
1162
+ var EventBus = function() {
1163
+ "use strict";
1164
+ var namespace, deprecationMap;
1165
+ namespace = "typeahead:";
1166
+ deprecationMap = {
1167
+ render: "rendered",
1168
+ cursorchange: "cursorchanged",
1169
+ select: "selected",
1170
+ autocomplete: "autocompleted"
1171
+ };
1172
+ function EventBus(o) {
1173
+ if (!o || !o.el) {
1174
+ $.error("EventBus initialized without el");
1175
+ }
1176
+ this.$el = $(o.el);
1177
+ }
1178
+ _.mixin(EventBus.prototype, {
1179
+ _trigger: function(type, args) {
1180
+ var $e;
1181
+ $e = $.Event(namespace + type);
1182
+ (args = args || []).unshift($e);
1183
+ this.$el.trigger.apply(this.$el, args);
1184
+ return $e;
1185
+ },
1186
+ before: function(type) {
1187
+ var args, $e;
1188
+ args = [].slice.call(arguments, 1);
1189
+ $e = this._trigger("before" + type, args);
1190
+ return $e.isDefaultPrevented();
1191
+ },
1192
+ trigger: function(type) {
1193
+ var deprecatedType;
1194
+ this._trigger(type, [].slice.call(arguments, 1));
1195
+ if (deprecatedType = deprecationMap[type]) {
1196
+ this._trigger(deprecatedType, [].slice.call(arguments, 1));
1197
+ }
1198
+ }
1199
+ });
1200
+ return EventBus;
1201
+ }();
1202
+ var EventEmitter = function() {
1203
+ "use strict";
1204
+ var splitter = /\s+/, nextTick = getNextTick();
1205
+ return {
1206
+ onSync: onSync,
1207
+ onAsync: onAsync,
1208
+ off: off,
1209
+ trigger: trigger
1210
+ };
1211
+ function on(method, types, cb, context) {
1212
+ var type;
1213
+ if (!cb) {
1214
+ return this;
1215
+ }
1216
+ types = types.split(splitter);
1217
+ cb = context ? bindContext(cb, context) : cb;
1218
+ this._callbacks = this._callbacks || {};
1219
+ while (type = types.shift()) {
1220
+ this._callbacks[type] = this._callbacks[type] || {
1221
+ sync: [],
1222
+ async: []
1223
+ };
1224
+ this._callbacks[type][method].push(cb);
1225
+ }
1226
+ return this;
1227
+ }
1228
+ function onAsync(types, cb, context) {
1229
+ return on.call(this, "async", types, cb, context);
1230
+ }
1231
+ function onSync(types, cb, context) {
1232
+ return on.call(this, "sync", types, cb, context);
1233
+ }
1234
+ function off(types) {
1235
+ var type;
1236
+ if (!this._callbacks) {
1237
+ return this;
1238
+ }
1239
+ types = types.split(splitter);
1240
+ while (type = types.shift()) {
1241
+ delete this._callbacks[type];
1242
+ }
1243
+ return this;
1244
+ }
1245
+ function trigger(types) {
1246
+ var type, callbacks, args, syncFlush, asyncFlush;
1247
+ if (!this._callbacks) {
1248
+ return this;
1249
+ }
1250
+ types = types.split(splitter);
1251
+ args = [].slice.call(arguments, 1);
1252
+ while ((type = types.shift()) && (callbacks = this._callbacks[type])) {
1253
+ syncFlush = getFlush(callbacks.sync, this, [ type ].concat(args));
1254
+ asyncFlush = getFlush(callbacks.async, this, [ type ].concat(args));
1255
+ syncFlush() && nextTick(asyncFlush);
1256
+ }
1257
+ return this;
1258
+ }
1259
+ function getFlush(callbacks, context, args) {
1260
+ return flush;
1261
+ function flush() {
1262
+ var cancelled;
1263
+ for (var i = 0, len = callbacks.length; !cancelled && i < len; i += 1) {
1264
+ cancelled = callbacks[i].apply(context, args) === false;
1265
+ }
1266
+ return !cancelled;
1267
+ }
1268
+ }
1269
+ function getNextTick() {
1270
+ var nextTickFn;
1271
+ if (window.setImmediate) {
1272
+ nextTickFn = function nextTickSetImmediate(fn) {
1273
+ setImmediate(function() {
1274
+ fn();
1275
+ });
1276
+ };
1277
+ } else {
1278
+ nextTickFn = function nextTickSetTimeout(fn) {
1279
+ setTimeout(function() {
1280
+ fn();
1281
+ }, 0);
1282
+ };
1283
+ }
1284
+ return nextTickFn;
1285
+ }
1286
+ function bindContext(fn, context) {
1287
+ return fn.bind ? fn.bind(context) : function() {
1288
+ fn.apply(context, [].slice.call(arguments, 0));
1289
+ };
1290
+ }
1291
+ }();
1292
+ var highlight = function(doc) {
1293
+ "use strict";
1294
+ var defaults = {
1295
+ node: null,
1296
+ pattern: null,
1297
+ tagName: "strong",
1298
+ className: null,
1299
+ wordsOnly: false,
1300
+ caseSensitive: false
1301
+ };
1302
+ return function hightlight(o) {
1303
+ var regex;
1304
+ o = _.mixin({}, defaults, o);
1305
+ if (!o.node || !o.pattern) {
1306
+ return;
1307
+ }
1308
+ o.pattern = _.isArray(o.pattern) ? o.pattern : [ o.pattern ];
1309
+ regex = getRegex(o.pattern, o.caseSensitive, o.wordsOnly);
1310
+ traverse(o.node, hightlightTextNode);
1311
+ function hightlightTextNode(textNode) {
1312
+ var match, patternNode, wrapperNode;
1313
+ if (match = regex.exec(textNode.data)) {
1314
+ wrapperNode = doc.createElement(o.tagName);
1315
+ o.className && (wrapperNode.className = o.className);
1316
+ patternNode = textNode.splitText(match.index);
1317
+ patternNode.splitText(match[0].length);
1318
+ wrapperNode.appendChild(patternNode.cloneNode(true));
1319
+ textNode.parentNode.replaceChild(wrapperNode, patternNode);
1320
+ }
1321
+ return !!match;
1322
+ }
1323
+ function traverse(el, hightlightTextNode) {
1324
+ var childNode, TEXT_NODE_TYPE = 3;
1325
+ for (var i = 0; i < el.childNodes.length; i++) {
1326
+ childNode = el.childNodes[i];
1327
+ if (childNode.nodeType === TEXT_NODE_TYPE) {
1328
+ i += hightlightTextNode(childNode) ? 1 : 0;
1329
+ } else {
1330
+ traverse(childNode, hightlightTextNode);
1331
+ }
1332
+ }
1333
+ }
1334
+ };
1335
+ function getRegex(patterns, caseSensitive, wordsOnly) {
1336
+ var escapedPatterns = [], regexStr;
1337
+ for (var i = 0, len = patterns.length; i < len; i++) {
1338
+ escapedPatterns.push(_.escapeRegExChars(patterns[i]));
1339
+ }
1340
+ regexStr = wordsOnly ? "\\b(" + escapedPatterns.join("|") + ")\\b" : "(" + escapedPatterns.join("|") + ")";
1341
+ return caseSensitive ? new RegExp(regexStr) : new RegExp(regexStr, "i");
1342
+ }
1343
+ }(window.document);
1344
+ var Input = function() {
1345
+ "use strict";
1346
+ var specialKeyCodeMap;
1347
+ specialKeyCodeMap = {
1348
+ 9: "tab",
1349
+ 27: "esc",
1350
+ 37: "left",
1351
+ 39: "right",
1352
+ 13: "enter",
1353
+ 38: "up",
1354
+ 40: "down"
1355
+ };
1356
+ function Input(o, www) {
1357
+ o = o || {};
1358
+ if (!o.input) {
1359
+ $.error("input is missing");
1360
+ }
1361
+ www.mixin(this);
1362
+ this.$hint = $(o.hint);
1363
+ this.$input = $(o.input);
1364
+ this.query = this.$input.val();
1365
+ this.queryWhenFocused = this.hasFocus() ? this.query : null;
1366
+ this.$overflowHelper = buildOverflowHelper(this.$input);
1367
+ this._checkLanguageDirection();
1368
+ if (this.$hint.length === 0) {
1369
+ this.setHint = this.getHint = this.clearHint = this.clearHintIfInvalid = _.noop;
1370
+ }
1371
+ }
1372
+ Input.normalizeQuery = function(str) {
1373
+ return _.toStr(str).replace(/^\s*/g, "").replace(/\s{2,}/g, " ");
1374
+ };
1375
+ _.mixin(Input.prototype, EventEmitter, {
1376
+ _onBlur: function onBlur() {
1377
+ this.resetInputValue();
1378
+ this.trigger("blurred");
1379
+ },
1380
+ _onFocus: function onFocus() {
1381
+ this.queryWhenFocused = this.query;
1382
+ this.trigger("focused");
1383
+ },
1384
+ _onKeydown: function onKeydown($e) {
1385
+ var keyName = specialKeyCodeMap[$e.which || $e.keyCode];
1386
+ this._managePreventDefault(keyName, $e);
1387
+ if (keyName && this._shouldTrigger(keyName, $e)) {
1388
+ this.trigger(keyName + "Keyed", $e);
1389
+ }
1390
+ },
1391
+ _onInput: function onInput() {
1392
+ this._setQuery(this.getInputValue());
1393
+ this.clearHintIfInvalid();
1394
+ this._checkLanguageDirection();
1395
+ },
1396
+ _managePreventDefault: function managePreventDefault(keyName, $e) {
1397
+ var preventDefault;
1398
+ switch (keyName) {
1399
+ case "up":
1400
+ case "down":
1401
+ preventDefault = !withModifier($e);
1402
+ break;
1403
+
1404
+ default:
1405
+ preventDefault = false;
1406
+ }
1407
+ preventDefault && $e.preventDefault();
1408
+ },
1409
+ _shouldTrigger: function shouldTrigger(keyName, $e) {
1410
+ var trigger;
1411
+ switch (keyName) {
1412
+ case "tab":
1413
+ trigger = !withModifier($e);
1414
+ break;
1415
+
1416
+ default:
1417
+ trigger = true;
1418
+ }
1419
+ return trigger;
1420
+ },
1421
+ _checkLanguageDirection: function checkLanguageDirection() {
1422
+ var dir = (this.$input.css("direction") || "ltr").toLowerCase();
1423
+ if (this.dir !== dir) {
1424
+ this.dir = dir;
1425
+ this.$hint.attr("dir", dir);
1426
+ this.trigger("langDirChanged", dir);
1427
+ }
1428
+ },
1429
+ _setQuery: function setQuery(val, silent) {
1430
+ var areEquivalent, hasDifferentWhitespace;
1431
+ areEquivalent = areQueriesEquivalent(val, this.query);
1432
+ hasDifferentWhitespace = areEquivalent ? this.query.length !== val.length : false;
1433
+ this.query = val;
1434
+ if (!silent && !areEquivalent) {
1435
+ this.trigger("queryChanged", this.query);
1436
+ } else if (!silent && hasDifferentWhitespace) {
1437
+ this.trigger("whitespaceChanged", this.query);
1438
+ }
1439
+ },
1440
+ bind: function() {
1441
+ var that = this, onBlur, onFocus, onKeydown, onInput;
1442
+ onBlur = _.bind(this._onBlur, this);
1443
+ onFocus = _.bind(this._onFocus, this);
1444
+ onKeydown = _.bind(this._onKeydown, this);
1445
+ onInput = _.bind(this._onInput, this);
1446
+ this.$input.on("blur.tt", onBlur).on("focus.tt", onFocus).on("keydown.tt", onKeydown);
1447
+ if (!_.isMsie() || _.isMsie() > 9) {
1448
+ this.$input.on("input.tt", onInput);
1449
+ } else {
1450
+ this.$input.on("keydown.tt keypress.tt cut.tt paste.tt", function($e) {
1451
+ if (specialKeyCodeMap[$e.which || $e.keyCode]) {
1452
+ return;
1453
+ }
1454
+ _.defer(_.bind(that._onInput, that, $e));
1455
+ });
1456
+ }
1457
+ return this;
1458
+ },
1459
+ focus: function focus() {
1460
+ this.$input.focus();
1461
+ },
1462
+ blur: function blur() {
1463
+ this.$input.blur();
1464
+ },
1465
+ getLangDir: function getLangDir() {
1466
+ return this.dir;
1467
+ },
1468
+ getQuery: function getQuery() {
1469
+ return this.query || "";
1470
+ },
1471
+ setQuery: function setQuery(val, silent) {
1472
+ this.setInputValue(val);
1473
+ this._setQuery(val, silent);
1474
+ },
1475
+ hasQueryChangedSinceLastFocus: function hasQueryChangedSinceLastFocus() {
1476
+ return this.query !== this.queryWhenFocused;
1477
+ },
1478
+ getInputValue: function getInputValue() {
1479
+ return this.$input.val();
1480
+ },
1481
+ setInputValue: function setInputValue(value) {
1482
+ this.$input.val(value);
1483
+ this.clearHintIfInvalid();
1484
+ this._checkLanguageDirection();
1485
+ },
1486
+ resetInputValue: function resetInputValue() {
1487
+ this.setInputValue(this.query);
1488
+ },
1489
+ getHint: function getHint() {
1490
+ return this.$hint.val();
1491
+ },
1492
+ setHint: function setHint(value) {
1493
+ this.$hint.val(value);
1494
+ },
1495
+ clearHint: function clearHint() {
1496
+ this.setHint("");
1497
+ },
1498
+ clearHintIfInvalid: function clearHintIfInvalid() {
1499
+ var val, hint, valIsPrefixOfHint, isValid;
1500
+ val = this.getInputValue();
1501
+ hint = this.getHint();
1502
+ valIsPrefixOfHint = val !== hint && hint.indexOf(val) === 0;
1503
+ isValid = val !== "" && valIsPrefixOfHint && !this.hasOverflow();
1504
+ !isValid && this.clearHint();
1505
+ },
1506
+ hasFocus: function hasFocus() {
1507
+ return this.$input.is(":focus");
1508
+ },
1509
+ hasOverflow: function hasOverflow() {
1510
+ var constraint = this.$input.width() - 2;
1511
+ this.$overflowHelper.text(this.getInputValue());
1512
+ return this.$overflowHelper.width() >= constraint;
1513
+ },
1514
+ isCursorAtEnd: function() {
1515
+ var valueLength, selectionStart, range;
1516
+ valueLength = this.$input.val().length;
1517
+ selectionStart = this.$input[0].selectionStart;
1518
+ if (_.isNumber(selectionStart)) {
1519
+ return selectionStart === valueLength;
1520
+ } else if (document.selection) {
1521
+ range = document.selection.createRange();
1522
+ range.moveStart("character", -valueLength);
1523
+ return valueLength === range.text.length;
1524
+ }
1525
+ return true;
1526
+ },
1527
+ destroy: function destroy() {
1528
+ this.$hint.off(".tt");
1529
+ this.$input.off(".tt");
1530
+ this.$overflowHelper.remove();
1531
+ this.$hint = this.$input = this.$overflowHelper = $("<div>");
1532
+ }
1533
+ });
1534
+ return Input;
1535
+ function buildOverflowHelper($input) {
1536
+ return $('<pre aria-hidden="true"></pre>').css({
1537
+ position: "absolute",
1538
+ visibility: "hidden",
1539
+ whiteSpace: "pre",
1540
+ fontFamily: $input.css("font-family"),
1541
+ fontSize: $input.css("font-size"),
1542
+ fontStyle: $input.css("font-style"),
1543
+ fontVariant: $input.css("font-variant"),
1544
+ fontWeight: $input.css("font-weight"),
1545
+ wordSpacing: $input.css("word-spacing"),
1546
+ letterSpacing: $input.css("letter-spacing"),
1547
+ textIndent: $input.css("text-indent"),
1548
+ textRendering: $input.css("text-rendering"),
1549
+ textTransform: $input.css("text-transform")
1550
+ }).insertAfter($input);
1551
+ }
1552
+ function areQueriesEquivalent(a, b) {
1553
+ return Input.normalizeQuery(a) === Input.normalizeQuery(b);
1554
+ }
1555
+ function withModifier($e) {
1556
+ return $e.altKey || $e.ctrlKey || $e.metaKey || $e.shiftKey;
1557
+ }
1558
+ }();
1559
+ var Dataset = function() {
1560
+ "use strict";
1561
+ var keys, nameGenerator;
1562
+ keys = {
1563
+ val: "tt-selectable-display",
1564
+ obj: "tt-selectable-object"
1565
+ };
1566
+ nameGenerator = _.getIdGenerator();
1567
+ function Dataset(o, www) {
1568
+ o = o || {};
1569
+ o.templates = o.templates || {};
1570
+ o.templates.notFound = o.templates.notFound || o.templates.empty;
1571
+ if (!o.source) {
1572
+ $.error("missing source");
1573
+ }
1574
+ if (!o.node) {
1575
+ $.error("missing node");
1576
+ }
1577
+ if (o.name && !isValidName(o.name)) {
1578
+ $.error("invalid dataset name: " + o.name);
1579
+ }
1580
+ www.mixin(this);
1581
+ this.highlight = !!o.highlight;
1582
+ this.name = o.name || nameGenerator();
1583
+ this.limit = o.limit || 5;
1584
+ this.displayFn = getDisplayFn(o.display || o.displayKey);
1585
+ this.templates = getTemplates(o.templates, this.displayFn);
1586
+ this.source = o.source.__ttAdapter ? o.source.__ttAdapter() : o.source;
1587
+ this.async = _.isUndefined(o.async) ? this.source.length > 2 : !!o.async;
1588
+ this._resetLastSuggestion();
1589
+ this.$el = $(o.node).addClass(this.classes.dataset).addClass(this.classes.dataset + "-" + this.name);
1590
+ }
1591
+ Dataset.extractData = function extractData(el) {
1592
+ var $el = $(el);
1593
+ if ($el.data(keys.obj)) {
1594
+ return {
1595
+ val: $el.data(keys.val) || "",
1596
+ obj: $el.data(keys.obj) || null
1597
+ };
1598
+ }
1599
+ return null;
1600
+ };
1601
+ _.mixin(Dataset.prototype, EventEmitter, {
1602
+ _overwrite: function overwrite(query, suggestions) {
1603
+ suggestions = suggestions || [];
1604
+ if (suggestions.length) {
1605
+ this._renderSuggestions(query, suggestions);
1606
+ } else if (this.async && this.templates.pending) {
1607
+ this._renderPending(query);
1608
+ } else if (!this.async && this.templates.notFound) {
1609
+ this._renderNotFound(query);
1610
+ } else {
1611
+ this._empty();
1612
+ }
1613
+ this.trigger("rendered", this.name, suggestions, false);
1614
+ },
1615
+ _append: function append(query, suggestions) {
1616
+ suggestions = suggestions || [];
1617
+ if (suggestions.length && this.$lastSuggestion.length) {
1618
+ this._appendSuggestions(query, suggestions);
1619
+ } else if (suggestions.length) {
1620
+ this._renderSuggestions(query, suggestions);
1621
+ } else if (!this.$lastSuggestion.length && this.templates.notFound) {
1622
+ this._renderNotFound(query);
1623
+ }
1624
+ this.trigger("rendered", this.name, suggestions, true);
1625
+ },
1626
+ _renderSuggestions: function renderSuggestions(query, suggestions) {
1627
+ var $fragment;
1628
+ $fragment = this._getSuggestionsFragment(query, suggestions);
1629
+ this.$lastSuggestion = $fragment.children().last();
1630
+ this.$el.html($fragment).prepend(this._getHeader(query, suggestions)).append(this._getFooter(query, suggestions));
1631
+ },
1632
+ _appendSuggestions: function appendSuggestions(query, suggestions) {
1633
+ var $fragment, $lastSuggestion;
1634
+ $fragment = this._getSuggestionsFragment(query, suggestions);
1635
+ $lastSuggestion = $fragment.children().last();
1636
+ this.$lastSuggestion.after($fragment);
1637
+ this.$lastSuggestion = $lastSuggestion;
1638
+ },
1639
+ _renderPending: function renderPending(query) {
1640
+ var template = this.templates.pending;
1641
+ this._resetLastSuggestion();
1642
+ template && this.$el.html(template({
1643
+ query: query,
1644
+ dataset: this.name
1645
+ }));
1646
+ },
1647
+ _renderNotFound: function renderNotFound(query) {
1648
+ var template = this.templates.notFound;
1649
+ this._resetLastSuggestion();
1650
+ template && this.$el.html(template({
1651
+ query: query,
1652
+ dataset: this.name
1653
+ }));
1654
+ },
1655
+ _empty: function empty() {
1656
+ this.$el.empty();
1657
+ this._resetLastSuggestion();
1658
+ },
1659
+ _getSuggestionsFragment: function getSuggestionsFragment(query, suggestions) {
1660
+ var that = this, fragment;
1661
+ fragment = document.createDocumentFragment();
1662
+ _.each(suggestions, function getSuggestionNode(suggestion) {
1663
+ var $el, context;
1664
+ context = that._injectQuery(query, suggestion);
1665
+ $el = $(that.templates.suggestion(context)).data(keys.obj, suggestion).data(keys.val, that.displayFn(suggestion)).addClass(that.classes.suggestion + " " + that.classes.selectable);
1666
+ fragment.appendChild($el[0]);
1667
+ });
1668
+ this.highlight && highlight({
1669
+ className: this.classes.highlight,
1670
+ node: fragment,
1671
+ pattern: query
1672
+ });
1673
+ return $(fragment);
1674
+ },
1675
+ _getFooter: function getFooter(query, suggestions) {
1676
+ return this.templates.footer ? this.templates.footer({
1677
+ query: query,
1678
+ suggestions: suggestions,
1679
+ dataset: this.name
1680
+ }) : null;
1681
+ },
1682
+ _getHeader: function getHeader(query, suggestions) {
1683
+ return this.templates.header ? this.templates.header({
1684
+ query: query,
1685
+ suggestions: suggestions,
1686
+ dataset: this.name
1687
+ }) : null;
1688
+ },
1689
+ _resetLastSuggestion: function resetLastSuggestion() {
1690
+ this.$lastSuggestion = $();
1691
+ },
1692
+ _injectQuery: function injectQuery(query, obj) {
1693
+ return _.isObject(obj) ? _.mixin({
1694
+ _query: query
1695
+ }, obj) : obj;
1696
+ },
1697
+ update: function update(query) {
1698
+ var that = this, canceled = false, syncCalled = false, rendered = 0;
1699
+ this.cancel();
1700
+ this.cancel = function cancel() {
1701
+ canceled = true;
1702
+ that.cancel = $.noop;
1703
+ that.async && that.trigger("asyncCanceled", query);
1704
+ };
1705
+ this.source(query, sync, async);
1706
+ !syncCalled && sync([]);
1707
+ function sync(suggestions) {
1708
+ if (syncCalled) {
1709
+ return;
1710
+ }
1711
+ syncCalled = true;
1712
+ suggestions = (suggestions || []).slice(0, that.limit);
1713
+ rendered = suggestions.length;
1714
+ that._overwrite(query, suggestions);
1715
+ if (rendered < that.limit && that.async) {
1716
+ that.trigger("asyncRequested", query);
1717
+ }
1718
+ }
1719
+ function async(suggestions) {
1720
+ suggestions = suggestions || [];
1721
+ if (!canceled && rendered < that.limit) {
1722
+ that.cancel = $.noop;
1723
+ rendered += suggestions.length;
1724
+ that._append(query, suggestions.slice(0, that.limit - rendered));
1725
+ that.async && that.trigger("asyncReceived", query);
1726
+ }
1727
+ }
1728
+ },
1729
+ cancel: $.noop,
1730
+ clear: function clear() {
1731
+ this._empty();
1732
+ this.cancel();
1733
+ this.trigger("cleared");
1734
+ },
1735
+ isEmpty: function isEmpty() {
1736
+ return this.$el.is(":empty");
1737
+ },
1738
+ destroy: function destroy() {
1739
+ this.$el = $("<div>");
1740
+ }
1741
+ });
1742
+ return Dataset;
1743
+ function getDisplayFn(display) {
1744
+ display = display || _.stringify;
1745
+ return _.isFunction(display) ? display : displayFn;
1746
+ function displayFn(obj) {
1747
+ return obj[display];
1748
+ }
1749
+ }
1750
+ function getTemplates(templates, displayFn) {
1751
+ return {
1752
+ notFound: templates.notFound && _.templatify(templates.notFound),
1753
+ pending: templates.pending && _.templatify(templates.pending),
1754
+ header: templates.header && _.templatify(templates.header),
1755
+ footer: templates.footer && _.templatify(templates.footer),
1756
+ suggestion: templates.suggestion || suggestionTemplate
1757
+ };
1758
+ function suggestionTemplate(context) {
1759
+ return $("<div>").text(displayFn(context));
1760
+ }
1761
+ }
1762
+ function isValidName(str) {
1763
+ return /^[_a-zA-Z0-9-]+$/.test(str);
1764
+ }
1765
+ }();
1766
+ var Menu = function() {
1767
+ "use strict";
1768
+ function Menu(o, www) {
1769
+ var that = this;
1770
+ o = o || {};
1771
+ if (!o.node) {
1772
+ $.error("node is required");
1773
+ }
1774
+ www.mixin(this);
1775
+ this.$node = $(o.node);
1776
+ this.query = null;
1777
+ this.datasets = _.map(o.datasets, initializeDataset);
1778
+ function initializeDataset(oDataset) {
1779
+ var node = that.$node.find(oDataset.node).first();
1780
+ oDataset.node = node.length ? node : $("<div>").appendTo(that.$node);
1781
+ return new Dataset(oDataset, www);
1782
+ }
1783
+ }
1784
+ _.mixin(Menu.prototype, EventEmitter, {
1785
+ _onSelectableClick: function onSelectableClick($e) {
1786
+ this.trigger("selectableClicked", $($e.currentTarget));
1787
+ },
1788
+ _onRendered: function onRendered(type, dataset, suggestions, async) {
1789
+ this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty());
1790
+ this.trigger("datasetRendered", dataset, suggestions, async);
1791
+ },
1792
+ _onCleared: function onCleared() {
1793
+ this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty());
1794
+ this.trigger("datasetCleared");
1795
+ },
1796
+ _propagate: function propagate() {
1797
+ this.trigger.apply(this, arguments);
1798
+ },
1799
+ _allDatasetsEmpty: function allDatasetsEmpty() {
1800
+ return _.every(this.datasets, isDatasetEmpty);
1801
+ function isDatasetEmpty(dataset) {
1802
+ return dataset.isEmpty();
1803
+ }
1804
+ },
1805
+ _getSelectables: function getSelectables() {
1806
+ return this.$node.find(this.selectors.selectable);
1807
+ },
1808
+ _removeCursor: function _removeCursor() {
1809
+ var $selectable = this.getActiveSelectable();
1810
+ $selectable && $selectable.removeClass(this.classes.cursor);
1811
+ },
1812
+ _ensureVisible: function ensureVisible($el) {
1813
+ var elTop, elBottom, nodeScrollTop, nodeHeight;
1814
+ elTop = $el.position().top;
1815
+ elBottom = elTop + $el.outerHeight(true);
1816
+ nodeScrollTop = this.$node.scrollTop();
1817
+ nodeHeight = this.$node.height() + parseInt(this.$node.css("paddingTop"), 10) + parseInt(this.$node.css("paddingBottom"), 10);
1818
+ if (elTop < 0) {
1819
+ this.$node.scrollTop(nodeScrollTop + elTop);
1820
+ } else if (nodeHeight < elBottom) {
1821
+ this.$node.scrollTop(nodeScrollTop + (elBottom - nodeHeight));
1822
+ }
1823
+ },
1824
+ bind: function() {
1825
+ var that = this, onSelectableClick;
1826
+ onSelectableClick = _.bind(this._onSelectableClick, this);
1827
+ this.$node.on("click.tt", this.selectors.selectable, onSelectableClick);
1828
+ _.each(this.datasets, function(dataset) {
1829
+ dataset.onSync("asyncRequested", that._propagate, that).onSync("asyncCanceled", that._propagate, that).onSync("asyncReceived", that._propagate, that).onSync("rendered", that._onRendered, that).onSync("cleared", that._onCleared, that);
1830
+ });
1831
+ return this;
1832
+ },
1833
+ isOpen: function isOpen() {
1834
+ return this.$node.hasClass(this.classes.open);
1835
+ },
1836
+ open: function open() {
1837
+ this.$node.addClass(this.classes.open);
1838
+ },
1839
+ close: function close() {
1840
+ this.$node.removeClass(this.classes.open);
1841
+ this._removeCursor();
1842
+ },
1843
+ setLanguageDirection: function setLanguageDirection(dir) {
1844
+ this.$node.attr("dir", dir);
1845
+ },
1846
+ selectableRelativeToCursor: function selectableRelativeToCursor(delta) {
1847
+ var $selectables, $oldCursor, oldIndex, newIndex;
1848
+ $oldCursor = this.getActiveSelectable();
1849
+ $selectables = this._getSelectables();
1850
+ oldIndex = $oldCursor ? $selectables.index($oldCursor) : -1;
1851
+ newIndex = oldIndex + delta;
1852
+ newIndex = (newIndex + 1) % ($selectables.length + 1) - 1;
1853
+ newIndex = newIndex < -1 ? $selectables.length - 1 : newIndex;
1854
+ return newIndex === -1 ? null : $selectables.eq(newIndex);
1855
+ },
1856
+ setCursor: function setCursor($selectable) {
1857
+ this._removeCursor();
1858
+ if ($selectable = $selectable && $selectable.first()) {
1859
+ $selectable.addClass(this.classes.cursor);
1860
+ this._ensureVisible($selectable);
1861
+ }
1862
+ },
1863
+ getSelectableData: function getSelectableData($el) {
1864
+ return $el && $el.length ? Dataset.extractData($el) : null;
1865
+ },
1866
+ getActiveSelectable: function getActiveSelectable() {
1867
+ var $selectable = this._getSelectables().filter(this.selectors.cursor).first();
1868
+ return $selectable.length ? $selectable : null;
1869
+ },
1870
+ getTopSelectable: function getTopSelectable() {
1871
+ var $selectable = this._getSelectables().first();
1872
+ return $selectable.length ? $selectable : null;
1873
+ },
1874
+ update: function update(query) {
1875
+ var isValidUpdate = query !== this.query;
1876
+ if (isValidUpdate) {
1877
+ this.query = query;
1878
+ _.each(this.datasets, updateDataset);
1879
+ }
1880
+ return isValidUpdate;
1881
+ function updateDataset(dataset) {
1882
+ dataset.update(query);
1883
+ }
1884
+ },
1885
+ empty: function empty() {
1886
+ _.each(this.datasets, clearDataset);
1887
+ this.query = null;
1888
+ this.$node.addClass(this.classes.empty);
1889
+ function clearDataset(dataset) {
1890
+ dataset.clear();
1891
+ }
1892
+ },
1893
+ destroy: function destroy() {
1894
+ this.$node.off(".tt");
1895
+ this.$node = $("<div>");
1896
+ _.each(this.datasets, destroyDataset);
1897
+ function destroyDataset(dataset) {
1898
+ dataset.destroy();
1899
+ }
1900
+ }
1901
+ });
1902
+ return Menu;
1903
+ }();
1904
+ var DefaultMenu = function() {
1905
+ "use strict";
1906
+ var s = Menu.prototype;
1907
+ function DefaultMenu() {
1908
+ Menu.apply(this, [].slice.call(arguments, 0));
1909
+ }
1910
+ _.mixin(DefaultMenu.prototype, Menu.prototype, {
1911
+ open: function open() {
1912
+ !this._allDatasetsEmpty() && this._show();
1913
+ return s.open.apply(this, [].slice.call(arguments, 0));
1914
+ },
1915
+ close: function close() {
1916
+ this._hide();
1917
+ return s.close.apply(this, [].slice.call(arguments, 0));
1918
+ },
1919
+ _onRendered: function onRendered() {
1920
+ if (this._allDatasetsEmpty()) {
1921
+ this._hide();
1922
+ } else {
1923
+ this.isOpen() && this._show();
1924
+ }
1925
+ return s._onRendered.apply(this, [].slice.call(arguments, 0));
1926
+ },
1927
+ _onCleared: function onCleared() {
1928
+ if (this._allDatasetsEmpty()) {
1929
+ this._hide();
1930
+ } else {
1931
+ this.isOpen() && this._show();
1932
+ }
1933
+ return s._onCleared.apply(this, [].slice.call(arguments, 0));
1934
+ },
1935
+ setLanguageDirection: function setLanguageDirection(dir) {
1936
+ this.$node.css(dir === "ltr" ? this.css.ltr : this.css.rtl);
1937
+ return s.setLanguageDirection.apply(this, [].slice.call(arguments, 0));
1938
+ },
1939
+ _hide: function hide() {
1940
+ this.$node.hide();
1941
+ },
1942
+ _show: function show() {
1943
+ this.$node.css("display", "block");
1944
+ }
1945
+ });
1946
+ return DefaultMenu;
1947
+ }();
1948
+ var Typeahead = function() {
1949
+ "use strict";
1950
+ function Typeahead(o, www) {
1951
+ var onFocused, onBlurred, onEnterKeyed, onTabKeyed, onEscKeyed, onUpKeyed, onDownKeyed, onLeftKeyed, onRightKeyed, onQueryChanged, onWhitespaceChanged;
1952
+ o = o || {};
1953
+ if (!o.input) {
1954
+ $.error("missing input");
1955
+ }
1956
+ if (!o.menu) {
1957
+ $.error("missing menu");
1958
+ }
1959
+ if (!o.eventBus) {
1960
+ $.error("missing event bus");
1961
+ }
1962
+ www.mixin(this);
1963
+ this.eventBus = o.eventBus;
1964
+ this.minLength = _.isNumber(o.minLength) ? o.minLength : 1;
1965
+ this.input = o.input;
1966
+ this.menu = o.menu;
1967
+ this.enabled = true;
1968
+ this.active = false;
1969
+ this.input.hasFocus() && this.activate();
1970
+ this.dir = this.input.getLangDir();
1971
+ this._hacks();
1972
+ this.menu.bind().onSync("selectableClicked", this._onSelectableClicked, this).onSync("asyncRequested", this._onAsyncRequested, this).onSync("asyncCanceled", this._onAsyncCanceled, this).onSync("asyncReceived", this._onAsyncReceived, this).onSync("datasetRendered", this._onDatasetRendered, this).onSync("datasetCleared", this._onDatasetCleared, this);
1973
+ onFocused = c(this, "activate", "open", "_onFocused");
1974
+ onBlurred = c(this, "deactivate", "_onBlurred");
1975
+ onEnterKeyed = c(this, "isActive", "isOpen", "_onEnterKeyed");
1976
+ onTabKeyed = c(this, "isActive", "isOpen", "_onTabKeyed");
1977
+ onEscKeyed = c(this, "isActive", "_onEscKeyed");
1978
+ onUpKeyed = c(this, "isActive", "open", "_onUpKeyed");
1979
+ onDownKeyed = c(this, "isActive", "open", "_onDownKeyed");
1980
+ onLeftKeyed = c(this, "isActive", "isOpen", "_onLeftKeyed");
1981
+ onRightKeyed = c(this, "isActive", "isOpen", "_onRightKeyed");
1982
+ onQueryChanged = c(this, "_openIfActive", "_onQueryChanged");
1983
+ onWhitespaceChanged = c(this, "_openIfActive", "_onWhitespaceChanged");
1984
+ this.input.bind().onSync("focused", onFocused, this).onSync("blurred", onBlurred, this).onSync("enterKeyed", onEnterKeyed, this).onSync("tabKeyed", onTabKeyed, this).onSync("escKeyed", onEscKeyed, this).onSync("upKeyed", onUpKeyed, this).onSync("downKeyed", onDownKeyed, this).onSync("leftKeyed", onLeftKeyed, this).onSync("rightKeyed", onRightKeyed, this).onSync("queryChanged", onQueryChanged, this).onSync("whitespaceChanged", onWhitespaceChanged, this).onSync("langDirChanged", this._onLangDirChanged, this);
1985
+ }
1986
+ _.mixin(Typeahead.prototype, {
1987
+ _hacks: function hacks() {
1988
+ var $input, $menu;
1989
+ $input = this.input.$input || $("<div>");
1990
+ $menu = this.menu.$node || $("<div>");
1991
+ $input.on("blur.tt", function($e) {
1992
+ var active, isActive, hasActive;
1993
+ active = document.activeElement;
1994
+ isActive = $menu.is(active);
1995
+ hasActive = $menu.has(active).length > 0;
1996
+ if (_.isMsie() && (isActive || hasActive)) {
1997
+ $e.preventDefault();
1998
+ $e.stopImmediatePropagation();
1999
+ _.defer(function() {
2000
+ $input.focus();
2001
+ });
2002
+ }
2003
+ });
2004
+ $menu.on("mousedown.tt", function($e) {
2005
+ $e.preventDefault();
2006
+ });
2007
+ },
2008
+ _onSelectableClicked: function onSelectableClicked(type, $el) {
2009
+ this.select($el);
2010
+ },
2011
+ _onDatasetCleared: function onDatasetCleared() {
2012
+ this._updateHint();
2013
+ },
2014
+ _onDatasetRendered: function onDatasetRendered(type, dataset, suggestions, async) {
2015
+ this._updateHint();
2016
+ this.eventBus.trigger("render", suggestions, async, dataset);
2017
+ },
2018
+ _onAsyncRequested: function onAsyncRequested(type, dataset, query) {
2019
+ this.eventBus.trigger("asyncrequest", query, dataset);
2020
+ },
2021
+ _onAsyncCanceled: function onAsyncCanceled(type, dataset, query) {
2022
+ this.eventBus.trigger("asynccancel", query, dataset);
2023
+ },
2024
+ _onAsyncReceived: function onAsyncReceived(type, dataset, query) {
2025
+ this.eventBus.trigger("asyncreceive", query, dataset);
2026
+ },
2027
+ _onFocused: function onFocused() {
2028
+ this._minLengthMet() && this.menu.update(this.input.getQuery());
2029
+ },
2030
+ _onBlurred: function onBlurred() {
2031
+ if (this.input.hasQueryChangedSinceLastFocus()) {
2032
+ this.eventBus.trigger("change", this.input.getQuery());
2033
+ }
2034
+ },
2035
+ _onEnterKeyed: function onEnterKeyed(type, $e) {
2036
+ var $selectable;
2037
+ if ($selectable = this.menu.getActiveSelectable()) {
2038
+ this.select($selectable) && $e.preventDefault();
2039
+ }
2040
+ },
2041
+ _onTabKeyed: function onTabKeyed(type, $e) {
2042
+ var $selectable;
2043
+ if ($selectable = this.menu.getActiveSelectable()) {
2044
+ this.select($selectable) && $e.preventDefault();
2045
+ } else if ($selectable = this.menu.getTopSelectable()) {
2046
+ this.autocomplete($selectable) && $e.preventDefault();
2047
+ }
2048
+ },
2049
+ _onEscKeyed: function onEscKeyed() {
2050
+ this.close();
2051
+ },
2052
+ _onUpKeyed: function onUpKeyed() {
2053
+ this.moveCursor(-1);
2054
+ },
2055
+ _onDownKeyed: function onDownKeyed() {
2056
+ this.moveCursor(+1);
2057
+ },
2058
+ _onLeftKeyed: function onLeftKeyed() {
2059
+ if (this.dir === "rtl" && this.input.isCursorAtEnd()) {
2060
+ this.autocomplete(this.menu.getTopSelectable());
2061
+ }
2062
+ },
2063
+ _onRightKeyed: function onRightKeyed() {
2064
+ if (this.dir === "ltr" && this.input.isCursorAtEnd()) {
2065
+ this.autocomplete(this.menu.getTopSelectable());
2066
+ }
2067
+ },
2068
+ _onQueryChanged: function onQueryChanged(e, query) {
2069
+ this._minLengthMet(query) ? this.menu.update(query) : this.menu.empty();
2070
+ },
2071
+ _onWhitespaceChanged: function onWhitespaceChanged() {
2072
+ this._updateHint();
2073
+ },
2074
+ _onLangDirChanged: function onLangDirChanged(e, dir) {
2075
+ if (this.dir !== dir) {
2076
+ this.dir = dir;
2077
+ this.menu.setLanguageDirection(dir);
2078
+ }
2079
+ },
2080
+ _openIfActive: function openIfActive() {
2081
+ this.isActive() && this.open();
2082
+ },
2083
+ _minLengthMet: function minLengthMet(query) {
2084
+ query = _.isString(query) ? query : this.input.getQuery() || "";
2085
+ return query.length >= this.minLength;
2086
+ },
2087
+ _updateHint: function updateHint() {
2088
+ var $selectable, data, val, query, escapedQuery, frontMatchRegEx, match;
2089
+ $selectable = this.menu.getTopSelectable();
2090
+ data = this.menu.getSelectableData($selectable);
2091
+ val = this.input.getInputValue();
2092
+ if (data && !_.isBlankString(val) && !this.input.hasOverflow()) {
2093
+ query = Input.normalizeQuery(val);
2094
+ escapedQuery = _.escapeRegExChars(query);
2095
+ frontMatchRegEx = new RegExp("^(?:" + escapedQuery + ")(.+$)", "i");
2096
+ match = frontMatchRegEx.exec(data.val);
2097
+ match && this.input.setHint(val + match[1]);
2098
+ } else {
2099
+ this.input.clearHint();
2100
+ }
2101
+ },
2102
+ isEnabled: function isEnabled() {
2103
+ return this.enabled;
2104
+ },
2105
+ enable: function enable() {
2106
+ this.enabled = true;
2107
+ },
2108
+ disable: function disable() {
2109
+ this.enabled = false;
2110
+ },
2111
+ isActive: function isActive() {
2112
+ return this.active;
2113
+ },
2114
+ activate: function activate() {
2115
+ if (this.isActive()) {
2116
+ return true;
2117
+ } else if (!this.isEnabled() || this.eventBus.before("active")) {
2118
+ return false;
2119
+ } else {
2120
+ this.active = true;
2121
+ this.eventBus.trigger("active");
2122
+ return true;
2123
+ }
2124
+ },
2125
+ deactivate: function deactivate() {
2126
+ if (!this.isActive()) {
2127
+ return true;
2128
+ } else if (this.eventBus.before("idle")) {
2129
+ return false;
2130
+ } else {
2131
+ this.active = false;
2132
+ this.close();
2133
+ this.eventBus.trigger("idle");
2134
+ return true;
2135
+ }
2136
+ },
2137
+ isOpen: function isOpen() {
2138
+ return this.menu.isOpen();
2139
+ },
2140
+ open: function open() {
2141
+ if (!this.isOpen() && !this.eventBus.before("open")) {
2142
+ this.menu.open();
2143
+ this._updateHint();
2144
+ this.eventBus.trigger("open");
2145
+ }
2146
+ return this.isOpen();
2147
+ },
2148
+ close: function close() {
2149
+ if (this.isOpen() && !this.eventBus.before("close")) {
2150
+ this.menu.close();
2151
+ this.input.clearHint();
2152
+ this.input.resetInputValue();
2153
+ this.eventBus.trigger("close");
2154
+ }
2155
+ return !this.isOpen();
2156
+ },
2157
+ setVal: function setVal(val) {
2158
+ this.input.setQuery(_.toStr(val));
2159
+ },
2160
+ getVal: function getVal() {
2161
+ return this.input.getQuery();
2162
+ },
2163
+ select: function select($selectable) {
2164
+ var data = this.menu.getSelectableData($selectable);
2165
+ if (data && !this.eventBus.before("select", data.obj)) {
2166
+ this.input.setQuery(data.val, true);
2167
+ this.eventBus.trigger("select", data.obj);
2168
+ this.close();
2169
+ return true;
2170
+ }
2171
+ return false;
2172
+ },
2173
+ autocomplete: function autocomplete($selectable) {
2174
+ var query, data, isValid;
2175
+ query = this.input.getQuery();
2176
+ data = this.menu.getSelectableData($selectable);
2177
+ isValid = data && query !== data.val;
2178
+ if (isValid && !this.eventBus.before("autocomplete", data.obj)) {
2179
+ this.input.setQuery(data.val);
2180
+ this.eventBus.trigger("autocomplete", data.obj);
2181
+ return true;
2182
+ }
2183
+ return false;
2184
+ },
2185
+ moveCursor: function moveCursor(delta) {
2186
+ var query, $candidate, data, payload, cancelMove;
2187
+ query = this.input.getQuery();
2188
+ $candidate = this.menu.selectableRelativeToCursor(delta);
2189
+ data = this.menu.getSelectableData($candidate);
2190
+ payload = data ? data.obj : null;
2191
+ cancelMove = this._minLengthMet() && this.menu.update(query);
2192
+ if (!cancelMove && !this.eventBus.before("cursorchange", payload)) {
2193
+ this.menu.setCursor($candidate);
2194
+ if (data) {
2195
+ this.input.setInputValue(data.val);
2196
+ } else {
2197
+ this.input.resetInputValue();
2198
+ this._updateHint();
2199
+ }
2200
+ this.eventBus.trigger("cursorchange", payload);
2201
+ return true;
2202
+ }
2203
+ return false;
2204
+ },
2205
+ destroy: function destroy() {
2206
+ this.input.destroy();
2207
+ this.menu.destroy();
2208
+ }
2209
+ });
2210
+ return Typeahead;
2211
+ function c(ctx) {
2212
+ var methods = [].slice.call(arguments, 1);
2213
+ return function() {
2214
+ var args = [].slice.call(arguments);
2215
+ _.each(methods, function(method) {
2216
+ return ctx[method].apply(ctx, args);
2217
+ });
2218
+ };
2219
+ }
2220
+ }();
2221
+ (function() {
2222
+ "use strict";
2223
+ var old, keys, methods;
2224
+ old = $.fn.typeahead;
2225
+ keys = {
2226
+ www: "tt-www",
2227
+ attrs: "tt-attrs",
2228
+ typeahead: "tt-typeahead"
2229
+ };
2230
+ methods = {
2231
+ initialize: function initialize(o, datasets) {
2232
+ var www;
2233
+ datasets = _.isArray(datasets) ? datasets : [].slice.call(arguments, 1);
2234
+ o = o || {};
2235
+ www = WWW(o.classNames);
2236
+ return this.each(attach);
2237
+ function attach() {
2238
+ var $input, $wrapper, $hint, $menu, defaultHint, defaultMenu, eventBus, input, menu, typeahead, MenuConstructor;
2239
+ _.each(datasets, function(d) {
2240
+ d.highlight = !!o.highlight;
2241
+ });
2242
+ $input = $(this);
2243
+ $wrapper = $(www.html.wrapper);
2244
+ $hint = $elOrNull(o.hint);
2245
+ $menu = $elOrNull(o.menu);
2246
+ defaultHint = o.hint !== false && !$hint;
2247
+ defaultMenu = o.menu !== false && !$menu;
2248
+ defaultHint && ($hint = buildHintFromInput($input, www));
2249
+ defaultMenu && ($menu = $(www.html.menu).css(www.css.menu));
2250
+ $hint && $hint.val("");
2251
+ $input = prepInput($input, www);
2252
+ if (defaultHint || defaultMenu) {
2253
+ $wrapper.css(www.css.wrapper);
2254
+ $input.css(defaultHint ? www.css.input : www.css.inputWithNoHint);
2255
+ $input.wrap($wrapper).parent().prepend(defaultHint ? $hint : null).append(defaultMenu ? $menu : null);
2256
+ }
2257
+ MenuConstructor = defaultMenu ? DefaultMenu : Menu;
2258
+ eventBus = new EventBus({
2259
+ el: $input
2260
+ });
2261
+ input = new Input({
2262
+ hint: $hint,
2263
+ input: $input
2264
+ }, www);
2265
+ menu = new MenuConstructor({
2266
+ node: $menu,
2267
+ datasets: datasets
2268
+ }, www);
2269
+ typeahead = new Typeahead({
2270
+ input: input,
2271
+ menu: menu,
2272
+ eventBus: eventBus,
2273
+ minLength: o.minLength
2274
+ }, www);
2275
+ $input.data(keys.www, www);
2276
+ $input.data(keys.typeahead, typeahead);
2277
+ }
2278
+ },
2279
+ isEnabled: function isEnabled() {
2280
+ var enabled;
2281
+ ttEach(this.first(), function(t) {
2282
+ enabled = t.isEnabled();
2283
+ });
2284
+ return enabled;
2285
+ },
2286
+ enable: function enable() {
2287
+ ttEach(this, function(t) {
2288
+ t.enable();
2289
+ });
2290
+ return this;
2291
+ },
2292
+ disable: function disable() {
2293
+ ttEach(this, function(t) {
2294
+ t.disable();
2295
+ });
2296
+ return this;
2297
+ },
2298
+ isActive: function isActive() {
2299
+ var active;
2300
+ ttEach(this.first(), function(t) {
2301
+ active = t.isActive();
2302
+ });
2303
+ return active;
2304
+ },
2305
+ activate: function activate() {
2306
+ ttEach(this, function(t) {
2307
+ t.activate();
2308
+ });
2309
+ return this;
2310
+ },
2311
+ deactivate: function deactivate() {
2312
+ ttEach(this, function(t) {
2313
+ t.deactivate();
2314
+ });
2315
+ return this;
2316
+ },
2317
+ isOpen: function isOpen() {
2318
+ var open;
2319
+ ttEach(this.first(), function(t) {
2320
+ open = t.isOpen();
2321
+ });
2322
+ return open;
2323
+ },
2324
+ open: function open() {
2325
+ ttEach(this, function(t) {
2326
+ t.open();
2327
+ });
2328
+ return this;
2329
+ },
2330
+ close: function close() {
2331
+ ttEach(this, function(t) {
2332
+ t.close();
2333
+ });
2334
+ return this;
2335
+ },
2336
+ select: function select(el) {
2337
+ var success = false, $el = $(el);
2338
+ ttEach(this.first(), function(t) {
2339
+ success = t.select($el);
2340
+ });
2341
+ return success;
2342
+ },
2343
+ autocomplete: function autocomplete(el) {
2344
+ var success = false, $el = $(el);
2345
+ ttEach(this.first(), function(t) {
2346
+ success = t.autocomplete($el);
2347
+ });
2348
+ return success;
2349
+ },
2350
+ moveCursor: function moveCursoe(delta) {
2351
+ var success = false;
2352
+ ttEach(this.first(), function(t) {
2353
+ success = t.moveCursor(delta);
2354
+ });
2355
+ return success;
2356
+ },
2357
+ val: function val(newVal) {
2358
+ var query;
2359
+ if (!arguments.length) {
2360
+ ttEach(this.first(), function(t) {
2361
+ query = t.getVal();
2362
+ });
2363
+ return query;
2364
+ } else {
2365
+ ttEach(this, function(t) {
2366
+ t.setVal(newVal);
2367
+ });
2368
+ return this;
2369
+ }
2370
+ },
2371
+ destroy: function destroy() {
2372
+ ttEach(this, function(typeahead, $input) {
2373
+ revert($input);
2374
+ typeahead.destroy();
2375
+ });
2376
+ return this;
2377
+ }
2378
+ };
2379
+ $.fn.typeahead = function(method) {
2380
+ if (methods[method]) {
2381
+ return methods[method].apply(this, [].slice.call(arguments, 1));
2382
+ } else {
2383
+ return methods.initialize.apply(this, arguments);
2384
+ }
2385
+ };
2386
+ $.fn.typeahead.noConflict = function noConflict() {
2387
+ $.fn.typeahead = old;
2388
+ return this;
2389
+ };
2390
+ function ttEach($els, fn) {
2391
+ $els.each(function() {
2392
+ var $input = $(this), typeahead;
2393
+ (typeahead = $input.data(keys.typeahead)) && fn(typeahead, $input);
2394
+ });
2395
+ }
2396
+ function buildHintFromInput($input, www) {
2397
+ return $input.clone().addClass(www.classes.hint).removeData().css(www.css.hint).css(getBackgroundStyles($input)).prop("readonly", true).removeAttr("id name placeholder required").attr({
2398
+ autocomplete: "off",
2399
+ spellcheck: "false",
2400
+ tabindex: -1
2401
+ });
2402
+ }
2403
+ function prepInput($input, www) {
2404
+ $input.data(keys.attrs, {
2405
+ dir: $input.attr("dir"),
2406
+ autocomplete: $input.attr("autocomplete"),
2407
+ spellcheck: $input.attr("spellcheck"),
2408
+ style: $input.attr("style")
2409
+ });
2410
+ $input.addClass(www.classes.input).attr({
2411
+ autocomplete: "off",
2412
+ spellcheck: false
2413
+ });
2414
+ try {
2415
+ !$input.attr("dir") && $input.attr("dir", "auto");
2416
+ } catch (e) {}
2417
+ return $input;
2418
+ }
2419
+ function getBackgroundStyles($el) {
2420
+ return {
2421
+ backgroundAttachment: $el.css("background-attachment"),
2422
+ backgroundClip: $el.css("background-clip"),
2423
+ backgroundColor: $el.css("background-color"),
2424
+ backgroundImage: $el.css("background-image"),
2425
+ backgroundOrigin: $el.css("background-origin"),
2426
+ backgroundPosition: $el.css("background-position"),
2427
+ backgroundRepeat: $el.css("background-repeat"),
2428
+ backgroundSize: $el.css("background-size")
2429
+ };
2430
+ }
2431
+ function revert($input) {
2432
+ var www, $wrapper;
2433
+ www = $input.data(keys.www);
2434
+ $wrapper = $input.parent().filter(www.selectors.wrapper);
2435
+ _.each($input.data(keys.attrs), function(val, key) {
2436
+ _.isUndefined(val) ? $input.removeAttr(key) : $input.attr(key, val);
2437
+ });
2438
+ $input.removeData(keys.typeahead).removeData(keys.www).removeData(keys.attr).removeClass(www.classes.input);
2439
+ if ($wrapper.length) {
2440
+ $input.detach().insertAfter($wrapper);
2441
+ $wrapper.remove();
2442
+ }
2443
+ }
2444
+ function $elOrNull(obj) {
2445
+ var isValid, $el;
2446
+ isValid = _.isJQuery(obj) || _.isElement(obj);
2447
+ $el = isValid ? $(obj).first() : [];
2448
+ return $el.length ? $el : null;
2449
+ }
2450
+ })();
2451
+ });