vapid 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (433) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.gitmodules +6 -0
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +133 -0
  6. data/.travis.yml +5 -0
  7. data/Gemfile +10 -0
  8. data/README.md +37 -0
  9. data/Rakefile +6 -0
  10. data/bin/console +14 -0
  11. data/bin/setup +8 -0
  12. data/exe/vapid +7 -0
  13. data/lib/vapid.rb +24 -0
  14. data/lib/vapid/assets/javascripts/vapid/admin.coffee +2 -0
  15. data/lib/vapid/assets/stylesheets/vapid/admin.scss +72 -0
  16. data/lib/vapid/builder.rb +70 -0
  17. data/lib/vapid/cli.rb +96 -0
  18. data/lib/vapid/controllers/admin_controller.rb +282 -0
  19. data/lib/vapid/controllers/project_controller.rb +41 -0
  20. data/lib/vapid/db/migrate/20170202182310_create_groups.rb +12 -0
  21. data/lib/vapid/db/migrate/20170202183017_create_records.rb +11 -0
  22. data/lib/vapid/db/migrate/20170202185150_create_users.rb +11 -0
  23. data/lib/vapid/directive.rb +168 -0
  24. data/lib/vapid/directives.rb +30 -0
  25. data/lib/vapid/directives/audio.rb +27 -0
  26. data/lib/vapid/directives/group.rb +71 -0
  27. data/lib/vapid/directives/hide.rb +11 -0
  28. data/lib/vapid/directives/href.rb +11 -0
  29. data/lib/vapid/directives/image.rb +14 -0
  30. data/lib/vapid/directives/richtext.rb +15 -0
  31. data/lib/vapid/directives/show.rb +11 -0
  32. data/lib/vapid/directives/text.rb +24 -0
  33. data/lib/vapid/directives/video.rb +28 -0
  34. data/lib/vapid/generator_template/.gitignore +21 -0
  35. data/lib/vapid/generator_template/Gemfile.tt +13 -0
  36. data/lib/vapid/generator_template/README.md +0 -0
  37. data/lib/vapid/generator_template/assets/favicon.ico +0 -0
  38. data/lib/vapid/generator_template/assets/images/.keep +0 -0
  39. data/lib/vapid/generator_template/assets/javascripts/.keep +0 -0
  40. data/lib/vapid/generator_template/assets/stylesheets/.keep +0 -0
  41. data/lib/vapid/generator_template/assets/stylesheets/application.css +120 -0
  42. data/lib/vapid/generator_template/config.ru +3 -0
  43. data/lib/vapid/generator_template/config/database.yml +12 -0
  44. data/lib/vapid/generator_template/config/settings.yml.tt +11 -0
  45. data/lib/vapid/generator_template/templates/index.html.erb +25 -0
  46. data/lib/vapid/generator_template/templates/layouts/default.html.erb +22 -0
  47. data/lib/vapid/models.rb +18 -0
  48. data/lib/vapid/models/group.rb +36 -0
  49. data/lib/vapid/models/record.rb +30 -0
  50. data/lib/vapid/models/user.rb +16 -0
  51. data/lib/vapid/server.rb +93 -0
  52. data/lib/vapid/settings.rb +13 -0
  53. data/lib/vapid/template.rb +79 -0
  54. data/lib/vapid/template/node.rb +91 -0
  55. data/lib/vapid/template/parser.rb +50 -0
  56. data/lib/vapid/vendor/semantic-ui/.versions +4 -0
  57. data/lib/vapid/vendor/semantic-ui/LICENSE +22 -0
  58. data/lib/vapid/vendor/semantic-ui/README.md +7 -0
  59. data/lib/vapid/vendor/semantic-ui/components/accordion.css +252 -0
  60. data/lib/vapid/vendor/semantic-ui/components/accordion.js +610 -0
  61. data/lib/vapid/vendor/semantic-ui/components/accordion.min.css +9 -0
  62. data/lib/vapid/vendor/semantic-ui/components/accordion.min.js +10 -0
  63. data/lib/vapid/vendor/semantic-ui/components/ad.css +275 -0
  64. data/lib/vapid/vendor/semantic-ui/components/ad.min.css +10 -0
  65. data/lib/vapid/vendor/semantic-ui/components/api.js +1167 -0
  66. data/lib/vapid/vendor/semantic-ui/components/api.min.js +10 -0
  67. data/lib/vapid/vendor/semantic-ui/components/breadcrumb.css +124 -0
  68. data/lib/vapid/vendor/semantic-ui/components/breadcrumb.min.css +9 -0
  69. data/lib/vapid/vendor/semantic-ui/components/button.css +3450 -0
  70. data/lib/vapid/vendor/semantic-ui/components/button.min.css +9 -0
  71. data/lib/vapid/vendor/semantic-ui/components/card.css +964 -0
  72. data/lib/vapid/vendor/semantic-ui/components/card.min.css +9 -0
  73. data/lib/vapid/vendor/semantic-ui/components/checkbox.css +625 -0
  74. data/lib/vapid/vendor/semantic-ui/components/checkbox.js +831 -0
  75. data/lib/vapid/vendor/semantic-ui/components/checkbox.min.css +9 -0
  76. data/lib/vapid/vendor/semantic-ui/components/checkbox.min.js +10 -0
  77. data/lib/vapid/vendor/semantic-ui/components/colorize.js +274 -0
  78. data/lib/vapid/vendor/semantic-ui/components/colorize.min.js +11 -0
  79. data/lib/vapid/vendor/semantic-ui/components/comment.css +270 -0
  80. data/lib/vapid/vendor/semantic-ui/components/comment.min.css +9 -0
  81. data/lib/vapid/vendor/semantic-ui/components/container.css +147 -0
  82. data/lib/vapid/vendor/semantic-ui/components/container.min.css +9 -0
  83. data/lib/vapid/vendor/semantic-ui/components/dimmer.css +200 -0
  84. data/lib/vapid/vendor/semantic-ui/components/dimmer.js +708 -0
  85. data/lib/vapid/vendor/semantic-ui/components/dimmer.min.css +9 -0
  86. data/lib/vapid/vendor/semantic-ui/components/dimmer.min.js +10 -0
  87. data/lib/vapid/vendor/semantic-ui/components/divider.css +260 -0
  88. data/lib/vapid/vendor/semantic-ui/components/divider.min.css +9 -0
  89. data/lib/vapid/vendor/semantic-ui/components/dropdown.css +1442 -0
  90. data/lib/vapid/vendor/semantic-ui/components/dropdown.js +3767 -0
  91. data/lib/vapid/vendor/semantic-ui/components/dropdown.min.css +9 -0
  92. data/lib/vapid/vendor/semantic-ui/components/dropdown.min.js +11 -0
  93. data/lib/vapid/vendor/semantic-ui/components/embed.css +166 -0
  94. data/lib/vapid/vendor/semantic-ui/components/embed.js +696 -0
  95. data/lib/vapid/vendor/semantic-ui/components/embed.min.css +9 -0
  96. data/lib/vapid/vendor/semantic-ui/components/embed.min.js +10 -0
  97. data/lib/vapid/vendor/semantic-ui/components/feed.css +296 -0
  98. data/lib/vapid/vendor/semantic-ui/components/feed.min.css +9 -0
  99. data/lib/vapid/vendor/semantic-ui/components/flag.css +1031 -0
  100. data/lib/vapid/vendor/semantic-ui/components/flag.min.css +9 -0
  101. data/lib/vapid/vendor/semantic-ui/components/form.css +1067 -0
  102. data/lib/vapid/vendor/semantic-ui/components/form.js +1603 -0
  103. data/lib/vapid/vendor/semantic-ui/components/form.min.css +9 -0
  104. data/lib/vapid/vendor/semantic-ui/components/form.min.js +10 -0
  105. data/lib/vapid/vendor/semantic-ui/components/grid.css +2002 -0
  106. data/lib/vapid/vendor/semantic-ui/components/grid.min.css +9 -0
  107. data/lib/vapid/vendor/semantic-ui/components/header.css +721 -0
  108. data/lib/vapid/vendor/semantic-ui/components/header.min.css +9 -0
  109. data/lib/vapid/vendor/semantic-ui/components/icon.css +3292 -0
  110. data/lib/vapid/vendor/semantic-ui/components/icon.min.css +9 -0
  111. data/lib/vapid/vendor/semantic-ui/components/image.css +306 -0
  112. data/lib/vapid/vendor/semantic-ui/components/image.min.css +9 -0
  113. data/lib/vapid/vendor/semantic-ui/components/input.css +510 -0
  114. data/lib/vapid/vendor/semantic-ui/components/input.min.css +9 -0
  115. data/lib/vapid/vendor/semantic-ui/components/item.css +486 -0
  116. data/lib/vapid/vendor/semantic-ui/components/item.min.css +9 -0
  117. data/lib/vapid/vendor/semantic-ui/components/label.css +1307 -0
  118. data/lib/vapid/vendor/semantic-ui/components/label.min.css +9 -0
  119. data/lib/vapid/vendor/semantic-ui/components/list.css +951 -0
  120. data/lib/vapid/vendor/semantic-ui/components/list.min.css +9 -0
  121. data/lib/vapid/vendor/semantic-ui/components/loader.css +347 -0
  122. data/lib/vapid/vendor/semantic-ui/components/loader.min.css +9 -0
  123. data/lib/vapid/vendor/semantic-ui/components/menu.css +2002 -0
  124. data/lib/vapid/vendor/semantic-ui/components/menu.min.css +1 -0
  125. data/lib/vapid/vendor/semantic-ui/components/message.css +477 -0
  126. data/lib/vapid/vendor/semantic-ui/components/message.min.css +9 -0
  127. data/lib/vapid/vendor/semantic-ui/components/modal.css +502 -0
  128. data/lib/vapid/vendor/semantic-ui/components/modal.js +913 -0
  129. data/lib/vapid/vendor/semantic-ui/components/modal.min.css +9 -0
  130. data/lib/vapid/vendor/semantic-ui/components/modal.min.js +10 -0
  131. data/lib/vapid/vendor/semantic-ui/components/nag.css +147 -0
  132. data/lib/vapid/vendor/semantic-ui/components/nag.js +507 -0
  133. data/lib/vapid/vendor/semantic-ui/components/nag.min.css +9 -0
  134. data/lib/vapid/vendor/semantic-ui/components/nag.min.js +10 -0
  135. data/lib/vapid/vendor/semantic-ui/components/popup.css +733 -0
  136. data/lib/vapid/vendor/semantic-ui/components/popup.js +1475 -0
  137. data/lib/vapid/vendor/semantic-ui/components/popup.min.css +9 -0
  138. data/lib/vapid/vendor/semantic-ui/components/popup.min.js +10 -0
  139. data/lib/vapid/vendor/semantic-ui/components/progress.css +516 -0
  140. data/lib/vapid/vendor/semantic-ui/components/progress.js +931 -0
  141. data/lib/vapid/vendor/semantic-ui/components/progress.min.css +9 -0
  142. data/lib/vapid/vendor/semantic-ui/components/progress.min.js +10 -0
  143. data/lib/vapid/vendor/semantic-ui/components/rail.css +152 -0
  144. data/lib/vapid/vendor/semantic-ui/components/rail.min.css +9 -0
  145. data/lib/vapid/vendor/semantic-ui/components/rating.css +263 -0
  146. data/lib/vapid/vendor/semantic-ui/components/rating.js +508 -0
  147. data/lib/vapid/vendor/semantic-ui/components/rating.min.css +9 -0
  148. data/lib/vapid/vendor/semantic-ui/components/rating.min.js +10 -0
  149. data/lib/vapid/vendor/semantic-ui/components/reset.css +424 -0
  150. data/lib/vapid/vendor/semantic-ui/components/reset.min.css +9 -0
  151. data/lib/vapid/vendor/semantic-ui/components/reveal.css +284 -0
  152. data/lib/vapid/vendor/semantic-ui/components/reveal.min.css +9 -0
  153. data/lib/vapid/vendor/semantic-ui/components/search.css +408 -0
  154. data/lib/vapid/vendor/semantic-ui/components/search.js +1442 -0
  155. data/lib/vapid/vendor/semantic-ui/components/search.min.css +9 -0
  156. data/lib/vapid/vendor/semantic-ui/components/search.min.js +10 -0
  157. data/lib/vapid/vendor/semantic-ui/components/segment.css +798 -0
  158. data/lib/vapid/vendor/semantic-ui/components/segment.min.css +9 -0
  159. data/lib/vapid/vendor/semantic-ui/components/shape.css +157 -0
  160. data/lib/vapid/vendor/semantic-ui/components/shape.js +921 -0
  161. data/lib/vapid/vendor/semantic-ui/components/shape.min.css +9 -0
  162. data/lib/vapid/vendor/semantic-ui/components/shape.min.js +10 -0
  163. data/lib/vapid/vendor/semantic-ui/components/sidebar.css +634 -0
  164. data/lib/vapid/vendor/semantic-ui/components/sidebar.js +1036 -0
  165. data/lib/vapid/vendor/semantic-ui/components/sidebar.min.css +9 -0
  166. data/lib/vapid/vendor/semantic-ui/components/sidebar.min.js +10 -0
  167. data/lib/vapid/vendor/semantic-ui/components/site.css +160 -0
  168. data/lib/vapid/vendor/semantic-ui/components/site.js +487 -0
  169. data/lib/vapid/vendor/semantic-ui/components/site.min.css +9 -0
  170. data/lib/vapid/vendor/semantic-ui/components/site.min.js +10 -0
  171. data/lib/vapid/vendor/semantic-ui/components/state.js +708 -0
  172. data/lib/vapid/vendor/semantic-ui/components/state.min.js +10 -0
  173. data/lib/vapid/vendor/semantic-ui/components/statistic.css +569 -0
  174. data/lib/vapid/vendor/semantic-ui/components/statistic.min.css +9 -0
  175. data/lib/vapid/vendor/semantic-ui/components/step.css +623 -0
  176. data/lib/vapid/vendor/semantic-ui/components/step.min.css +9 -0
  177. data/lib/vapid/vendor/semantic-ui/components/sticky.css +78 -0
  178. data/lib/vapid/vendor/semantic-ui/components/sticky.js +942 -0
  179. data/lib/vapid/vendor/semantic-ui/components/sticky.min.css +9 -0
  180. data/lib/vapid/vendor/semantic-ui/components/sticky.min.js +10 -0
  181. data/lib/vapid/vendor/semantic-ui/components/tab.css +91 -0
  182. data/lib/vapid/vendor/semantic-ui/components/tab.js +952 -0
  183. data/lib/vapid/vendor/semantic-ui/components/tab.min.css +9 -0
  184. data/lib/vapid/vendor/semantic-ui/components/tab.min.js +10 -0
  185. data/lib/vapid/vendor/semantic-ui/components/table.css +1108 -0
  186. data/lib/vapid/vendor/semantic-ui/components/table.min.css +9 -0
  187. data/lib/vapid/vendor/semantic-ui/components/transition.css +1964 -0
  188. data/lib/vapid/vendor/semantic-ui/components/transition.js +1095 -0
  189. data/lib/vapid/vendor/semantic-ui/components/transition.min.css +9 -0
  190. data/lib/vapid/vendor/semantic-ui/components/transition.min.js +10 -0
  191. data/lib/vapid/vendor/semantic-ui/components/video.css +125 -0
  192. data/lib/vapid/vendor/semantic-ui/components/video.js +532 -0
  193. data/lib/vapid/vendor/semantic-ui/components/video.min.css +10 -0
  194. data/lib/vapid/vendor/semantic-ui/components/video.min.js +11 -0
  195. data/lib/vapid/vendor/semantic-ui/components/visibility.js +1288 -0
  196. data/lib/vapid/vendor/semantic-ui/components/visibility.min.js +10 -0
  197. data/lib/vapid/vendor/semantic-ui/components/visit.js +517 -0
  198. data/lib/vapid/vendor/semantic-ui/components/visit.min.js +11 -0
  199. data/lib/vapid/vendor/semantic-ui/package.js +34 -0
  200. data/lib/vapid/vendor/semantic-ui/package.json +20 -0
  201. data/lib/vapid/vendor/semantic-ui/semantic.css +36844 -0
  202. data/lib/vapid/vendor/semantic-ui/semantic.js +22617 -0
  203. data/lib/vapid/vendor/semantic-ui/semantic.min.css +364 -0
  204. data/lib/vapid/vendor/semantic-ui/semantic.min.js +19 -0
  205. data/lib/vapid/vendor/semantic-ui/themes/default/assets/fonts/icons.eot +0 -0
  206. data/lib/vapid/vendor/semantic-ui/themes/default/assets/fonts/icons.otf +0 -0
  207. data/lib/vapid/vendor/semantic-ui/themes/default/assets/fonts/icons.svg +2671 -0
  208. data/lib/vapid/vendor/semantic-ui/themes/default/assets/fonts/icons.ttf +0 -0
  209. data/lib/vapid/vendor/semantic-ui/themes/default/assets/fonts/icons.woff +0 -0
  210. data/lib/vapid/vendor/semantic-ui/themes/default/assets/fonts/icons.woff2 +0 -0
  211. data/lib/vapid/vendor/semantic-ui/themes/default/assets/images/flags.png +0 -0
  212. data/lib/vapid/vendor/trix/.blade.yml +45 -0
  213. data/lib/vapid/vendor/trix/.github/ISSUE_TEMPLATE.md +13 -0
  214. data/lib/vapid/vendor/trix/.gitignore +3 -0
  215. data/lib/vapid/vendor/trix/.ruby-version +1 -0
  216. data/lib/vapid/vendor/trix/.travis.yml +6 -0
  217. data/lib/vapid/vendor/trix/CONDUCT.md +79 -0
  218. data/lib/vapid/vendor/trix/Gemfile +17 -0
  219. data/lib/vapid/vendor/trix/Gemfile.lock +152 -0
  220. data/lib/vapid/vendor/trix/LICENSE +20 -0
  221. data/lib/vapid/vendor/trix/README.md +382 -0
  222. data/lib/vapid/vendor/trix/assets/index.html +55 -0
  223. data/lib/vapid/vendor/trix/assets/trix-core.coffee +2 -0
  224. data/lib/vapid/vendor/trix/assets/trix.coffee +3 -0
  225. data/lib/vapid/vendor/trix/assets/trix.scss +5 -0
  226. data/lib/vapid/vendor/trix/assets/trix/banner/index.coffee.erb +3 -0
  227. data/lib/vapid/vendor/trix/assets/trix/banner/index.scss.erb +3 -0
  228. data/lib/vapid/vendor/trix/assets/trix/banner/index.txt.erb +3 -0
  229. data/lib/vapid/vendor/trix/assets/trix/images/README.md +6 -0
  230. data/lib/vapid/vendor/trix/assets/trix/images/attach.svg +5 -0
  231. data/lib/vapid/vendor/trix/assets/trix/images/bold.svg +5 -0
  232. data/lib/vapid/vendor/trix/assets/trix/images/bullets.svg +5 -0
  233. data/lib/vapid/vendor/trix/assets/trix/images/code.svg +5 -0
  234. data/lib/vapid/vendor/trix/assets/trix/images/heading_1.svg +5 -0
  235. data/lib/vapid/vendor/trix/assets/trix/images/italic.svg +5 -0
  236. data/lib/vapid/vendor/trix/assets/trix/images/link.svg +6 -0
  237. data/lib/vapid/vendor/trix/assets/trix/images/nesting_level_decrease.svg +5 -0
  238. data/lib/vapid/vendor/trix/assets/trix/images/nesting_level_increase.svg +5 -0
  239. data/lib/vapid/vendor/trix/assets/trix/images/numbers.svg +5 -0
  240. data/lib/vapid/vendor/trix/assets/trix/images/quote.svg +5 -0
  241. data/lib/vapid/vendor/trix/assets/trix/images/redo.svg +5 -0
  242. data/lib/vapid/vendor/trix/assets/trix/images/remove.svg +4 -0
  243. data/lib/vapid/vendor/trix/assets/trix/images/strike.svg +6 -0
  244. data/lib/vapid/vendor/trix/assets/trix/images/trash.svg +5 -0
  245. data/lib/vapid/vendor/trix/assets/trix/images/undo.svg +5 -0
  246. data/lib/vapid/vendor/trix/assets/trix/stylesheets/attachments.scss +112 -0
  247. data/lib/vapid/vendor/trix/assets/trix/stylesheets/content.scss +88 -0
  248. data/lib/vapid/vendor/trix/assets/trix/stylesheets/editor.scss +8 -0
  249. data/lib/vapid/vendor/trix/assets/trix/stylesheets/icons.scss +14 -0
  250. data/lib/vapid/vendor/trix/assets/trix/stylesheets/media-queries.scss +7 -0
  251. data/lib/vapid/vendor/trix/assets/trix/stylesheets/toolbar.scss +194 -0
  252. data/lib/vapid/vendor/trix/bin/blade +16 -0
  253. data/lib/vapid/vendor/trix/bin/ci +21 -0
  254. data/lib/vapid/vendor/trix/bin/rackup +16 -0
  255. data/lib/vapid/vendor/trix/bin/rake +16 -0
  256. data/lib/vapid/vendor/trix/bin/release +139 -0
  257. data/lib/vapid/vendor/trix/bin/setup +69 -0
  258. data/lib/vapid/vendor/trix/bin/update-status-image +100 -0
  259. data/lib/vapid/vendor/trix/bower.json +34 -0
  260. data/lib/vapid/vendor/trix/config.ru +32 -0
  261. data/lib/vapid/vendor/trix/dist/trix-core.js +11 -0
  262. data/lib/vapid/vendor/trix/dist/trix.css +286 -0
  263. data/lib/vapid/vendor/trix/dist/trix.js +20 -0
  264. data/lib/vapid/vendor/trix/package.json +29 -0
  265. data/lib/vapid/vendor/trix/polyfills/polyfills.coffee +3 -0
  266. data/lib/vapid/vendor/trix/polyfills/set.coffee +24 -0
  267. data/lib/vapid/vendor/trix/polyfills/vendor/CustomElements.js +1029 -0
  268. data/lib/vapid/vendor/trix/polyfills/vendor/README.md +2 -0
  269. data/lib/vapid/vendor/trix/polyfills/vendor/promise.js +228 -0
  270. data/lib/vapid/vendor/trix/src/trix/VERSION +1 -0
  271. data/lib/vapid/vendor/trix/src/trix/config/block_attributes.coffee +37 -0
  272. data/lib/vapid/vendor/trix/src/trix/config/css.coffee +12 -0
  273. data/lib/vapid/vendor/trix/src/trix/config/file_size_formatting.coffee +22 -0
  274. data/lib/vapid/vendor/trix/src/trix/config/index.coffee +9 -0
  275. data/lib/vapid/vendor/trix/src/trix/config/lang.coffee +26 -0
  276. data/lib/vapid/vendor/trix/src/trix/config/selection_elements.coffee +26 -0
  277. data/lib/vapid/vendor/trix/src/trix/config/serialization.coffee +63 -0
  278. data/lib/vapid/vendor/trix/src/trix/config/text_attributes.coffee +25 -0
  279. data/lib/vapid/vendor/trix/src/trix/config/toolbar.coffee +41 -0
  280. data/lib/vapid/vendor/trix/src/trix/config/undo_interval.coffee +7 -0
  281. data/lib/vapid/vendor/trix/src/trix/controllers/attachment_editor_controller.coffee +104 -0
  282. data/lib/vapid/vendor/trix/src/trix/controllers/composition_controller.coffee +117 -0
  283. data/lib/vapid/vendor/trix/src/trix/controllers/controller.coffee +3 -0
  284. data/lib/vapid/vendor/trix/src/trix/controllers/editor_controller.coffee +369 -0
  285. data/lib/vapid/vendor/trix/src/trix/controllers/input/composition_input.coffee +57 -0
  286. data/lib/vapid/vendor/trix/src/trix/controllers/input_controller.coffee +473 -0
  287. data/lib/vapid/vendor/trix/src/trix/controllers/toolbar_controller.coffee +173 -0
  288. data/lib/vapid/vendor/trix/src/trix/core/basic_object.coffee +44 -0
  289. data/lib/vapid/vendor/trix/src/trix/core/collections/element_store.coffee +21 -0
  290. data/lib/vapid/vendor/trix/src/trix/core/collections/hash.coffee +98 -0
  291. data/lib/vapid/vendor/trix/src/trix/core/collections/index.coffee +4 -0
  292. data/lib/vapid/vendor/trix/src/trix/core/collections/object_group.coffee +37 -0
  293. data/lib/vapid/vendor/trix/src/trix/core/collections/object_map.coffee +10 -0
  294. data/lib/vapid/vendor/trix/src/trix/core/helpers/arrays.coffee +34 -0
  295. data/lib/vapid/vendor/trix/src/trix/core/helpers/config.coffee +23 -0
  296. data/lib/vapid/vendor/trix/src/trix/core/helpers/custom_elements.coffee +45 -0
  297. data/lib/vapid/vendor/trix/src/trix/core/helpers/dom.coffee +185 -0
  298. data/lib/vapid/vendor/trix/src/trix/core/helpers/extend.coffee +4 -0
  299. data/lib/vapid/vendor/trix/src/trix/core/helpers/functions.coffee +3 -0
  300. data/lib/vapid/vendor/trix/src/trix/core/helpers/global.coffee +23 -0
  301. data/lib/vapid/vendor/trix/src/trix/core/helpers/index.coffee +10 -0
  302. data/lib/vapid/vendor/trix/src/trix/core/helpers/objects.coffee +11 -0
  303. data/lib/vapid/vendor/trix/src/trix/core/helpers/ranges.coffee +33 -0
  304. data/lib/vapid/vendor/trix/src/trix/core/helpers/selection.coffee +25 -0
  305. data/lib/vapid/vendor/trix/src/trix/core/helpers/strings.coffee +46 -0
  306. data/lib/vapid/vendor/trix/src/trix/core/index.coffee +4 -0
  307. data/lib/vapid/vendor/trix/src/trix/core/object.coffee +33 -0
  308. data/lib/vapid/vendor/trix/src/trix/core/utilities/index.coffee +2 -0
  309. data/lib/vapid/vendor/trix/src/trix/core/utilities/operation.coffee +37 -0
  310. data/lib/vapid/vendor/trix/src/trix/core/utilities/utf16_string.coffee +93 -0
  311. data/lib/vapid/vendor/trix/src/trix/elements/trix_editor_element.coffee +166 -0
  312. data/lib/vapid/vendor/trix/src/trix/elements/trix_toolbar_element.coffee +28 -0
  313. data/lib/vapid/vendor/trix/src/trix/index.coffee.erb +14 -0
  314. data/lib/vapid/vendor/trix/src/trix/inspector/control_element.coffee +60 -0
  315. data/lib/vapid/vendor/trix/src/trix/inspector/debugger.coffee +104 -0
  316. data/lib/vapid/vendor/trix/src/trix/inspector/element.coffee +86 -0
  317. data/lib/vapid/vendor/trix/src/trix/inspector/index.coffee +17 -0
  318. data/lib/vapid/vendor/trix/src/trix/inspector/polyfills/vendor/details-element-polyfill.js +5 -0
  319. data/lib/vapid/vendor/trix/src/trix/inspector/templates/debug.jst.eco +17 -0
  320. data/lib/vapid/vendor/trix/src/trix/inspector/templates/document.jst.eco +33 -0
  321. data/lib/vapid/vendor/trix/src/trix/inspector/templates/performance.jst.eco +10 -0
  322. data/lib/vapid/vendor/trix/src/trix/inspector/templates/render.jst.eco +1 -0
  323. data/lib/vapid/vendor/trix/src/trix/inspector/templates/selection.jst.eco +5 -0
  324. data/lib/vapid/vendor/trix/src/trix/inspector/templates/undo.jst.eco +13 -0
  325. data/lib/vapid/vendor/trix/src/trix/inspector/view.coffee +58 -0
  326. data/lib/vapid/vendor/trix/src/trix/inspector/views/debug_view.coffee +33 -0
  327. data/lib/vapid/vendor/trix/src/trix/inspector/views/document_view.coffee +12 -0
  328. data/lib/vapid/vendor/trix/src/trix/inspector/views/performance_view.coffee +51 -0
  329. data/lib/vapid/vendor/trix/src/trix/inspector/views/render_view.coffee +21 -0
  330. data/lib/vapid/vendor/trix/src/trix/inspector/views/selection_view.coffee +33 -0
  331. data/lib/vapid/vendor/trix/src/trix/inspector/views/undo_view.coffee +12 -0
  332. data/lib/vapid/vendor/trix/src/trix/inspector/watchdog/deserializer.coffee +55 -0
  333. data/lib/vapid/vendor/trix/src/trix/inspector/watchdog/index.coffee +5 -0
  334. data/lib/vapid/vendor/trix/src/trix/inspector/watchdog/player.coffee +60 -0
  335. data/lib/vapid/vendor/trix/src/trix/inspector/watchdog/player_controller.coffee +43 -0
  336. data/lib/vapid/vendor/trix/src/trix/inspector/watchdog/player_element.coffee +32 -0
  337. data/lib/vapid/vendor/trix/src/trix/inspector/watchdog/player_view.coffee +133 -0
  338. data/lib/vapid/vendor/trix/src/trix/inspector/watchdog/recorder.coffee +82 -0
  339. data/lib/vapid/vendor/trix/src/trix/inspector/watchdog/recording.coffee +54 -0
  340. data/lib/vapid/vendor/trix/src/trix/inspector/watchdog/serializer.coffee +61 -0
  341. data/lib/vapid/vendor/trix/src/trix/models/attachment.coffee +157 -0
  342. data/lib/vapid/vendor/trix/src/trix/models/attachment_manager.coffee +24 -0
  343. data/lib/vapid/vendor/trix/src/trix/models/attachment_piece.coffee +47 -0
  344. data/lib/vapid/vendor/trix/src/trix/models/block.coffee +230 -0
  345. data/lib/vapid/vendor/trix/src/trix/models/composition.coffee +521 -0
  346. data/lib/vapid/vendor/trix/src/trix/models/document.coffee +538 -0
  347. data/lib/vapid/vendor/trix/src/trix/models/editor.coffee +141 -0
  348. data/lib/vapid/vendor/trix/src/trix/models/html_parser.coffee +335 -0
  349. data/lib/vapid/vendor/trix/src/trix/models/line_break_insertion.coffee +31 -0
  350. data/lib/vapid/vendor/trix/src/trix/models/location_mapper.coffee +156 -0
  351. data/lib/vapid/vendor/trix/src/trix/models/managed_attachment.coffee +28 -0
  352. data/lib/vapid/vendor/trix/src/trix/models/piece.coffee +95 -0
  353. data/lib/vapid/vendor/trix/src/trix/models/point_mapper.coffee +28 -0
  354. data/lib/vapid/vendor/trix/src/trix/models/selection_manager.coffee +129 -0
  355. data/lib/vapid/vendor/trix/src/trix/models/splittable_list.coffee +168 -0
  356. data/lib/vapid/vendor/trix/src/trix/models/string_piece.coffee +49 -0
  357. data/lib/vapid/vendor/trix/src/trix/models/text.coffee +168 -0
  358. data/lib/vapid/vendor/trix/src/trix/models/undo_manager.coffee +40 -0
  359. data/lib/vapid/vendor/trix/src/trix/observers/mutation_observer.coffee +131 -0
  360. data/lib/vapid/vendor/trix/src/trix/observers/selection_change_observer.coffee +56 -0
  361. data/lib/vapid/vendor/trix/src/trix/operations/file_verification_operation.coffee +15 -0
  362. data/lib/vapid/vendor/trix/src/trix/operations/image_preload_operation.coffee +15 -0
  363. data/lib/vapid/vendor/trix/src/trix/views/attachment_view.coffee +99 -0
  364. data/lib/vapid/vendor/trix/src/trix/views/block_view.coffee +37 -0
  365. data/lib/vapid/vendor/trix/src/trix/views/document_view.coffee +68 -0
  366. data/lib/vapid/vendor/trix/src/trix/views/object_group_view.coffee +23 -0
  367. data/lib/vapid/vendor/trix/src/trix/views/object_view.coffee +86 -0
  368. data/lib/vapid/vendor/trix/src/trix/views/piece_view.coffee +97 -0
  369. data/lib/vapid/vendor/trix/src/trix/views/previewable_attachment_view.coffee +49 -0
  370. data/lib/vapid/vendor/trix/src/trix/views/text_view.coffee +30 -0
  371. data/lib/vapid/vendor/trix/test/.gitignore +1 -0
  372. data/lib/vapid/vendor/trix/test/src/system/attachment_test.coffee +70 -0
  373. data/lib/vapid/vendor/trix/test/src/system/basic_input_test.coffee +68 -0
  374. data/lib/vapid/vendor/trix/test/src/system/block_formatting_test.coffee +602 -0
  375. data/lib/vapid/vendor/trix/test/src/system/caching_test.coffee +21 -0
  376. data/lib/vapid/vendor/trix/test/src/system/composition_input_test.coffee +138 -0
  377. data/lib/vapid/vendor/trix/test/src/system/cursor_movement_test.coffee +54 -0
  378. data/lib/vapid/vendor/trix/test/src/system/custom_element_test.coffee +314 -0
  379. data/lib/vapid/vendor/trix/test/src/system/html_loading_test.coffee +62 -0
  380. data/lib/vapid/vendor/trix/test/src/system/html_replacement_test.coffee +101 -0
  381. data/lib/vapid/vendor/trix/test/src/system/installation_process_test.coffee +59 -0
  382. data/lib/vapid/vendor/trix/test/src/system/list_formatting_test.coffee +70 -0
  383. data/lib/vapid/vendor/trix/test/src/system/mutation_input_test.coffee +73 -0
  384. data/lib/vapid/vendor/trix/test/src/system/pasting_test.coffee +215 -0
  385. data/lib/vapid/vendor/trix/test/src/system/text_formatting_test.coffee +151 -0
  386. data/lib/vapid/vendor/trix/test/src/system/undo_test.coffee +48 -0
  387. data/lib/vapid/vendor/trix/test/src/test.coffee +16 -0
  388. data/lib/vapid/vendor/trix/test/src/test_helpers/assertions.coffee +38 -0
  389. data/lib/vapid/vendor/trix/test/src/test_helpers/editor_helpers.coffee +37 -0
  390. data/lib/vapid/vendor/trix/test/src/test_helpers/fixtures/editor_empty.jst.eco +1 -0
  391. data/lib/vapid/vendor/trix/test/src/test_helpers/fixtures/editor_html.jst.eco +2 -0
  392. data/lib/vapid/vendor/trix/test/src/test_helpers/fixtures/editor_in_table.jst.eco +7 -0
  393. data/lib/vapid/vendor/trix/test/src/test_helpers/fixtures/editor_with_block_styles.jst.eco +6 -0
  394. data/lib/vapid/vendor/trix/test/src/test_helpers/fixtures/editor_with_bold_styles.jst.eco +7 -0
  395. data/lib/vapid/vendor/trix/test/src/test_helpers/fixtures/editor_with_image.jst.eco +2 -0
  396. data/lib/vapid/vendor/trix/test/src/test_helpers/fixtures/editor_with_styled_content.jst.eco +7 -0
  397. data/lib/vapid/vendor/trix/test/src/test_helpers/fixtures/editor_with_toolbar_and_input.jst.eco +5 -0
  398. data/lib/vapid/vendor/trix/test/src/test_helpers/fixtures/fixtures.coffee +536 -0
  399. data/lib/vapid/vendor/trix/test/src/test_helpers/fixtures/logo.png +0 -0
  400. data/lib/vapid/vendor/trix/test/src/test_helpers/index.coffee +18 -0
  401. data/lib/vapid/vendor/trix/test/src/test_helpers/input_helpers.coffee +183 -0
  402. data/lib/vapid/vendor/trix/test/src/test_helpers/selection_helpers.coffee +91 -0
  403. data/lib/vapid/vendor/trix/test/src/test_helpers/test_helpers.coffee +72 -0
  404. data/lib/vapid/vendor/trix/test/src/test_helpers/test_stubs.coffee +31 -0
  405. data/lib/vapid/vendor/trix/test/src/test_helpers/toolbar_helpers.coffee +45 -0
  406. data/lib/vapid/vendor/trix/test/src/unit/attachment_test.coffee +23 -0
  407. data/lib/vapid/vendor/trix/test/src/unit/block_test.coffee +22 -0
  408. data/lib/vapid/vendor/trix/test/src/unit/composition_test.coffee +13 -0
  409. data/lib/vapid/vendor/trix/test/src/unit/document_test.coffee +11 -0
  410. data/lib/vapid/vendor/trix/test/src/unit/document_view_test.coffee +6 -0
  411. data/lib/vapid/vendor/trix/test/src/unit/html_parser_test.coffee +162 -0
  412. data/lib/vapid/vendor/trix/test/src/unit/location_mapper_test.coffee +185 -0
  413. data/lib/vapid/vendor/trix/test/src/unit/mutation_observer_test.coffee +84 -0
  414. data/lib/vapid/vendor/trix/test/src/unit/serialization_test.coffee +7 -0
  415. data/lib/vapid/vendor/trix/test/src/unit/string_change_summary_test.coffee +57 -0
  416. data/lib/vapid/vendor/trix/test/src/unit/text_test.coffee +19 -0
  417. data/lib/vapid/vendor/trix/test/vendor/rangy-core.js +3845 -0
  418. data/lib/vapid/vendor/trix/test/vendor/rangy-textrange.js +1930 -0
  419. data/lib/vapid/version.rb +4 -0
  420. data/lib/vapid/views/admin/install.html.erb +19 -0
  421. data/lib/vapid/views/admin/login.html.erb +11 -0
  422. data/lib/vapid/views/admin/overview/index.html.erb +1 -0
  423. data/lib/vapid/views/admin/records/_form.erb +9 -0
  424. data/lib/vapid/views/admin/records/edit.html.erb +5 -0
  425. data/lib/vapid/views/admin/records/index.html.erb +38 -0
  426. data/lib/vapid/views/admin/records/new.html.erb +3 -0
  427. data/lib/vapid/views/errors/404.html.erb +1 -0
  428. data/lib/vapid/views/errors/500.html.erb +1 -0
  429. data/lib/vapid/views/layouts/admin.html.erb +41 -0
  430. data/lib/vapid/views/layouts/admin_form.html.erb +22 -0
  431. data/lib/vapid/views/layouts/error.html.erb +11 -0
  432. data/vapid.gemspec +48 -0
  433. metadata +811 -0
@@ -0,0 +1,1603 @@
1
+ /*!
2
+ * # Semantic UI 2.2.9 - Form Validation
3
+ * http://github.com/semantic-org/semantic-ui/
4
+ *
5
+ *
6
+ * Released under the MIT license
7
+ * http://opensource.org/licenses/MIT
8
+ *
9
+ */
10
+
11
+ ;(function ($, window, document, undefined) {
12
+
13
+ "use strict";
14
+
15
+ window = (typeof window != 'undefined' && window.Math == Math)
16
+ ? window
17
+ : (typeof self != 'undefined' && self.Math == Math)
18
+ ? self
19
+ : Function('return this')()
20
+ ;
21
+
22
+ $.fn.form = function(parameters) {
23
+ var
24
+ $allModules = $(this),
25
+ moduleSelector = $allModules.selector || '',
26
+
27
+ time = new Date().getTime(),
28
+ performance = [],
29
+
30
+ query = arguments[0],
31
+ legacyParameters = arguments[1],
32
+ methodInvoked = (typeof query == 'string'),
33
+ queryArguments = [].slice.call(arguments, 1),
34
+ returnedValue
35
+ ;
36
+ $allModules
37
+ .each(function() {
38
+ var
39
+ $module = $(this),
40
+ element = this,
41
+
42
+ formErrors = [],
43
+ keyHeldDown = false,
44
+
45
+ // set at run-time
46
+ $field,
47
+ $group,
48
+ $message,
49
+ $prompt,
50
+ $submit,
51
+ $clear,
52
+ $reset,
53
+
54
+ settings,
55
+ validation,
56
+
57
+ metadata,
58
+ selector,
59
+ className,
60
+ regExp,
61
+ error,
62
+
63
+ namespace,
64
+ moduleNamespace,
65
+ eventNamespace,
66
+
67
+ instance,
68
+ module
69
+ ;
70
+
71
+ module = {
72
+
73
+ initialize: function() {
74
+
75
+ // settings grabbed at run time
76
+ module.get.settings();
77
+ if(methodInvoked) {
78
+ if(instance === undefined) {
79
+ module.instantiate();
80
+ }
81
+ module.invoke(query);
82
+ }
83
+ else {
84
+ if(instance !== undefined) {
85
+ instance.invoke('destroy');
86
+ }
87
+ module.verbose('Initializing form validation', $module, settings);
88
+ module.bindEvents();
89
+ module.set.defaults();
90
+ module.instantiate();
91
+ }
92
+ },
93
+
94
+ instantiate: function() {
95
+ module.verbose('Storing instance of module', module);
96
+ instance = module;
97
+ $module
98
+ .data(moduleNamespace, module)
99
+ ;
100
+ },
101
+
102
+ destroy: function() {
103
+ module.verbose('Destroying previous module', instance);
104
+ module.removeEvents();
105
+ $module
106
+ .removeData(moduleNamespace)
107
+ ;
108
+ },
109
+
110
+ refresh: function() {
111
+ module.verbose('Refreshing selector cache');
112
+ $field = $module.find(selector.field);
113
+ $group = $module.find(selector.group);
114
+ $message = $module.find(selector.message);
115
+ $prompt = $module.find(selector.prompt);
116
+
117
+ $submit = $module.find(selector.submit);
118
+ $clear = $module.find(selector.clear);
119
+ $reset = $module.find(selector.reset);
120
+ },
121
+
122
+ submit: function() {
123
+ module.verbose('Submitting form', $module);
124
+ $module
125
+ .submit()
126
+ ;
127
+ },
128
+
129
+ attachEvents: function(selector, action) {
130
+ action = action || 'submit';
131
+ $(selector)
132
+ .on('click' + eventNamespace, function(event) {
133
+ module[action]();
134
+ event.preventDefault();
135
+ })
136
+ ;
137
+ },
138
+
139
+ bindEvents: function() {
140
+ module.verbose('Attaching form events');
141
+ $module
142
+ .on('submit' + eventNamespace, module.validate.form)
143
+ .on('blur' + eventNamespace, selector.field, module.event.field.blur)
144
+ .on('click' + eventNamespace, selector.submit, module.submit)
145
+ .on('click' + eventNamespace, selector.reset, module.reset)
146
+ .on('click' + eventNamespace, selector.clear, module.clear)
147
+ ;
148
+ if(settings.keyboardShortcuts) {
149
+ $module
150
+ .on('keydown' + eventNamespace, selector.field, module.event.field.keydown)
151
+ ;
152
+ }
153
+ $field
154
+ .each(function() {
155
+ var
156
+ $input = $(this),
157
+ type = $input.prop('type'),
158
+ inputEvent = module.get.changeEvent(type, $input)
159
+ ;
160
+ $(this)
161
+ .on(inputEvent + eventNamespace, module.event.field.change)
162
+ ;
163
+ })
164
+ ;
165
+ },
166
+
167
+ clear: function() {
168
+ $field
169
+ .each(function () {
170
+ var
171
+ $field = $(this),
172
+ $element = $field.parent(),
173
+ $fieldGroup = $field.closest($group),
174
+ $prompt = $fieldGroup.find(selector.prompt),
175
+ defaultValue = $field.data(metadata.defaultValue) || '',
176
+ isCheckbox = $element.is(selector.uiCheckbox),
177
+ isDropdown = $element.is(selector.uiDropdown),
178
+ isErrored = $fieldGroup.hasClass(className.error)
179
+ ;
180
+ if(isErrored) {
181
+ module.verbose('Resetting error on field', $fieldGroup);
182
+ $fieldGroup.removeClass(className.error);
183
+ $prompt.remove();
184
+ }
185
+ if(isDropdown) {
186
+ module.verbose('Resetting dropdown value', $element, defaultValue);
187
+ $element.dropdown('clear');
188
+ }
189
+ else if(isCheckbox) {
190
+ $field.prop('checked', false);
191
+ }
192
+ else {
193
+ module.verbose('Resetting field value', $field, defaultValue);
194
+ $field.val('');
195
+ }
196
+ })
197
+ ;
198
+ },
199
+
200
+ reset: function() {
201
+ $field
202
+ .each(function () {
203
+ var
204
+ $field = $(this),
205
+ $element = $field.parent(),
206
+ $fieldGroup = $field.closest($group),
207
+ $prompt = $fieldGroup.find(selector.prompt),
208
+ defaultValue = $field.data(metadata.defaultValue),
209
+ isCheckbox = $element.is(selector.uiCheckbox),
210
+ isDropdown = $element.is(selector.uiDropdown),
211
+ isErrored = $fieldGroup.hasClass(className.error)
212
+ ;
213
+ if(defaultValue === undefined) {
214
+ return;
215
+ }
216
+ if(isErrored) {
217
+ module.verbose('Resetting error on field', $fieldGroup);
218
+ $fieldGroup.removeClass(className.error);
219
+ $prompt.remove();
220
+ }
221
+ if(isDropdown) {
222
+ module.verbose('Resetting dropdown value', $element, defaultValue);
223
+ $element.dropdown('restore defaults');
224
+ }
225
+ else if(isCheckbox) {
226
+ module.verbose('Resetting checkbox value', $element, defaultValue);
227
+ $field.prop('checked', defaultValue);
228
+ }
229
+ else {
230
+ module.verbose('Resetting field value', $field, defaultValue);
231
+ $field.val(defaultValue);
232
+ }
233
+ })
234
+ ;
235
+ },
236
+
237
+ determine: {
238
+ isValid: function() {
239
+ var
240
+ allValid = true
241
+ ;
242
+ $.each(validation, function(fieldName, field) {
243
+ if( !( module.validate.field(field, fieldName, true) ) ) {
244
+ allValid = false;
245
+ }
246
+ });
247
+ return allValid;
248
+ }
249
+ },
250
+
251
+ is: {
252
+ bracketedRule: function(rule) {
253
+ return (rule.type && rule.type.match(settings.regExp.bracket));
254
+ },
255
+ empty: function($field) {
256
+ if(!$field || $field.length === 0) {
257
+ return true;
258
+ }
259
+ else if($field.is('input[type="checkbox"]')) {
260
+ return !$field.is(':checked');
261
+ }
262
+ else {
263
+ return module.is.blank($field);
264
+ }
265
+ },
266
+ blank: function($field) {
267
+ return $.trim($field.val()) === '';
268
+ },
269
+ valid: function(field) {
270
+ var
271
+ allValid = true
272
+ ;
273
+ if(field) {
274
+ module.verbose('Checking if field is valid', field);
275
+ return module.validate.field(validation[field], field, false);
276
+ }
277
+ else {
278
+ module.verbose('Checking if form is valid');
279
+ $.each(validation, function(fieldName, field) {
280
+ if( !module.is.valid(fieldName) ) {
281
+ allValid = false;
282
+ }
283
+ });
284
+ return allValid;
285
+ }
286
+ }
287
+ },
288
+
289
+ removeEvents: function() {
290
+ $module
291
+ .off(eventNamespace)
292
+ ;
293
+ $field
294
+ .off(eventNamespace)
295
+ ;
296
+ $submit
297
+ .off(eventNamespace)
298
+ ;
299
+ $field
300
+ .off(eventNamespace)
301
+ ;
302
+ },
303
+
304
+ event: {
305
+ field: {
306
+ keydown: function(event) {
307
+ var
308
+ $field = $(this),
309
+ key = event.which,
310
+ isInput = $field.is(selector.input),
311
+ isCheckbox = $field.is(selector.checkbox),
312
+ isInDropdown = ($field.closest(selector.uiDropdown).length > 0),
313
+ keyCode = {
314
+ enter : 13,
315
+ escape : 27
316
+ }
317
+ ;
318
+ if( key == keyCode.escape) {
319
+ module.verbose('Escape key pressed blurring field');
320
+ $field
321
+ .blur()
322
+ ;
323
+ }
324
+ if(!event.ctrlKey && key == keyCode.enter && isInput && !isInDropdown && !isCheckbox) {
325
+ if(!keyHeldDown) {
326
+ $field
327
+ .one('keyup' + eventNamespace, module.event.field.keyup)
328
+ ;
329
+ module.submit();
330
+ module.debug('Enter pressed on input submitting form');
331
+ }
332
+ keyHeldDown = true;
333
+ }
334
+ },
335
+ keyup: function() {
336
+ keyHeldDown = false;
337
+ },
338
+ blur: function(event) {
339
+ var
340
+ $field = $(this),
341
+ $fieldGroup = $field.closest($group),
342
+ validationRules = module.get.validation($field)
343
+ ;
344
+ if( $fieldGroup.hasClass(className.error) ) {
345
+ module.debug('Revalidating field', $field, validationRules);
346
+ if(validationRules) {
347
+ module.validate.field( validationRules );
348
+ }
349
+ }
350
+ else if(settings.on == 'blur' || settings.on == 'change') {
351
+ if(validationRules) {
352
+ module.validate.field( validationRules );
353
+ }
354
+ }
355
+ },
356
+ change: function(event) {
357
+ var
358
+ $field = $(this),
359
+ $fieldGroup = $field.closest($group),
360
+ validationRules = module.get.validation($field)
361
+ ;
362
+ if(validationRules && (settings.on == 'change' || ( $fieldGroup.hasClass(className.error) && settings.revalidate) )) {
363
+ clearTimeout(module.timer);
364
+ module.timer = setTimeout(function() {
365
+ module.debug('Revalidating field', $field, module.get.validation($field));
366
+ module.validate.field( validationRules );
367
+ }, settings.delay);
368
+ }
369
+ }
370
+ }
371
+
372
+ },
373
+
374
+ get: {
375
+ ancillaryValue: function(rule) {
376
+ if(!rule.type || (!rule.value && !module.is.bracketedRule(rule))) {
377
+ return false;
378
+ }
379
+ return (rule.value !== undefined)
380
+ ? rule.value
381
+ : rule.type.match(settings.regExp.bracket)[1] + ''
382
+ ;
383
+ },
384
+ ruleName: function(rule) {
385
+ if( module.is.bracketedRule(rule) ) {
386
+ return rule.type.replace(rule.type.match(settings.regExp.bracket)[0], '');
387
+ }
388
+ return rule.type;
389
+ },
390
+ changeEvent: function(type, $input) {
391
+ if(type == 'checkbox' || type == 'radio' || type == 'hidden' || $input.is('select')) {
392
+ return 'change';
393
+ }
394
+ else {
395
+ return module.get.inputEvent();
396
+ }
397
+ },
398
+ inputEvent: function() {
399
+ return (document.createElement('input').oninput !== undefined)
400
+ ? 'input'
401
+ : (document.createElement('input').onpropertychange !== undefined)
402
+ ? 'propertychange'
403
+ : 'keyup'
404
+ ;
405
+ },
406
+ prompt: function(rule, field) {
407
+ var
408
+ ruleName = module.get.ruleName(rule),
409
+ ancillary = module.get.ancillaryValue(rule),
410
+ prompt = rule.prompt || settings.prompt[ruleName] || settings.text.unspecifiedRule,
411
+ requiresValue = (prompt.search('{value}') !== -1),
412
+ requiresName = (prompt.search('{name}') !== -1),
413
+ $label,
414
+ $field,
415
+ name
416
+ ;
417
+ if(requiresName || requiresValue) {
418
+ $field = module.get.field(field.identifier);
419
+ }
420
+ if(requiresValue) {
421
+ prompt = prompt.replace('{value}', $field.val());
422
+ }
423
+ if(requiresName) {
424
+ $label = $field.closest(selector.group).find('label').eq(0);
425
+ name = ($label.length == 1)
426
+ ? $label.text()
427
+ : $field.prop('placeholder') || settings.text.unspecifiedField
428
+ ;
429
+ prompt = prompt.replace('{name}', name);
430
+ }
431
+ prompt = prompt.replace('{identifier}', field.identifier);
432
+ prompt = prompt.replace('{ruleValue}', ancillary);
433
+ if(!rule.prompt) {
434
+ module.verbose('Using default validation prompt for type', prompt, ruleName);
435
+ }
436
+ return prompt;
437
+ },
438
+ settings: function() {
439
+ if($.isPlainObject(parameters)) {
440
+ var
441
+ keys = Object.keys(parameters),
442
+ isLegacySettings = (keys.length > 0)
443
+ ? (parameters[keys[0]].identifier !== undefined && parameters[keys[0]].rules !== undefined)
444
+ : false,
445
+ ruleKeys
446
+ ;
447
+ if(isLegacySettings) {
448
+ // 1.x (ducktyped)
449
+ settings = $.extend(true, {}, $.fn.form.settings, legacyParameters);
450
+ validation = $.extend({}, $.fn.form.settings.defaults, parameters);
451
+ module.error(settings.error.oldSyntax, element);
452
+ module.verbose('Extending settings from legacy parameters', validation, settings);
453
+ }
454
+ else {
455
+ // 2.x
456
+ if(parameters.fields) {
457
+ ruleKeys = Object.keys(parameters.fields);
458
+ if( typeof parameters.fields[ruleKeys[0]] == 'string' || $.isArray(parameters.fields[ruleKeys[0]]) ) {
459
+ $.each(parameters.fields, function(name, rules) {
460
+ if(typeof rules == 'string') {
461
+ rules = [rules];
462
+ }
463
+ parameters.fields[name] = {
464
+ rules: []
465
+ };
466
+ $.each(rules, function(index, rule) {
467
+ parameters.fields[name].rules.push({ type: rule });
468
+ });
469
+ });
470
+ }
471
+ }
472
+
473
+ settings = $.extend(true, {}, $.fn.form.settings, parameters);
474
+ validation = $.extend({}, $.fn.form.settings.defaults, settings.fields);
475
+ module.verbose('Extending settings', validation, settings);
476
+ }
477
+ }
478
+ else {
479
+ settings = $.fn.form.settings;
480
+ validation = $.fn.form.settings.defaults;
481
+ module.verbose('Using default form validation', validation, settings);
482
+ }
483
+
484
+ // shorthand
485
+ namespace = settings.namespace;
486
+ metadata = settings.metadata;
487
+ selector = settings.selector;
488
+ className = settings.className;
489
+ regExp = settings.regExp;
490
+ error = settings.error;
491
+ moduleNamespace = 'module-' + namespace;
492
+ eventNamespace = '.' + namespace;
493
+
494
+ // grab instance
495
+ instance = $module.data(moduleNamespace);
496
+
497
+ // refresh selector cache
498
+ module.refresh();
499
+ },
500
+ field: function(identifier) {
501
+ module.verbose('Finding field with identifier', identifier);
502
+ identifier = module.escape.string(identifier);
503
+ if($field.filter('#' + identifier).length > 0 ) {
504
+ return $field.filter('#' + identifier);
505
+ }
506
+ else if( $field.filter('[name="' + identifier +'"]').length > 0 ) {
507
+ return $field.filter('[name="' + identifier +'"]');
508
+ }
509
+ else if( $field.filter('[name="' + identifier +'[]"]').length > 0 ) {
510
+ return $field.filter('[name="' + identifier +'[]"]');
511
+ }
512
+ else if( $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]').length > 0 ) {
513
+ return $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]');
514
+ }
515
+ return $('<input/>');
516
+ },
517
+ fields: function(fields) {
518
+ var
519
+ $fields = $()
520
+ ;
521
+ $.each(fields, function(index, name) {
522
+ $fields = $fields.add( module.get.field(name) );
523
+ });
524
+ return $fields;
525
+ },
526
+ validation: function($field) {
527
+ var
528
+ fieldValidation,
529
+ identifier
530
+ ;
531
+ if(!validation) {
532
+ return false;
533
+ }
534
+ $.each(validation, function(fieldName, field) {
535
+ identifier = field.identifier || fieldName;
536
+ if( module.get.field(identifier)[0] == $field[0] ) {
537
+ field.identifier = identifier;
538
+ fieldValidation = field;
539
+ }
540
+ });
541
+ return fieldValidation || false;
542
+ },
543
+ value: function (field) {
544
+ var
545
+ fields = [],
546
+ results
547
+ ;
548
+ fields.push(field);
549
+ results = module.get.values.call(element, fields);
550
+ return results[field];
551
+ },
552
+ values: function (fields) {
553
+ var
554
+ $fields = $.isArray(fields)
555
+ ? module.get.fields(fields)
556
+ : $field,
557
+ values = {}
558
+ ;
559
+ $fields.each(function(index, field) {
560
+ var
561
+ $field = $(field),
562
+ type = $field.prop('type'),
563
+ name = $field.prop('name'),
564
+ value = $field.val(),
565
+ isCheckbox = $field.is(selector.checkbox),
566
+ isRadio = $field.is(selector.radio),
567
+ isMultiple = (name.indexOf('[]') !== -1),
568
+ isChecked = (isCheckbox)
569
+ ? $field.is(':checked')
570
+ : false
571
+ ;
572
+ if(name) {
573
+ if(isMultiple) {
574
+ name = name.replace('[]', '');
575
+ if(!values[name]) {
576
+ values[name] = [];
577
+ }
578
+ if(isCheckbox) {
579
+ if(isChecked) {
580
+ values[name].push(value || true);
581
+ }
582
+ else {
583
+ values[name].push(false);
584
+ }
585
+ }
586
+ else {
587
+ values[name].push(value);
588
+ }
589
+ }
590
+ else {
591
+ if(isRadio) {
592
+ if(isChecked) {
593
+ values[name] = value;
594
+ }
595
+ }
596
+ else if(isCheckbox) {
597
+ if(isChecked) {
598
+ values[name] = value || true;
599
+ }
600
+ else {
601
+ values[name] = false;
602
+ }
603
+ }
604
+ else {
605
+ values[name] = value;
606
+ }
607
+ }
608
+ }
609
+ });
610
+ return values;
611
+ }
612
+ },
613
+
614
+ has: {
615
+
616
+ field: function(identifier) {
617
+ module.verbose('Checking for existence of a field with identifier', identifier);
618
+ identifier = module.escape.string(identifier);
619
+ if(typeof identifier !== 'string') {
620
+ module.error(error.identifier, identifier);
621
+ }
622
+ if($field.filter('#' + identifier).length > 0 ) {
623
+ return true;
624
+ }
625
+ else if( $field.filter('[name="' + identifier +'"]').length > 0 ) {
626
+ return true;
627
+ }
628
+ else if( $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]').length > 0 ) {
629
+ return true;
630
+ }
631
+ return false;
632
+ }
633
+
634
+ },
635
+
636
+ escape: {
637
+ string: function(text) {
638
+ text = String(text);
639
+ return text.replace(regExp.escape, '\\$&');
640
+ }
641
+ },
642
+
643
+ add: {
644
+ prompt: function(identifier, errors) {
645
+ var
646
+ $field = module.get.field(identifier),
647
+ $fieldGroup = $field.closest($group),
648
+ $prompt = $fieldGroup.children(selector.prompt),
649
+ promptExists = ($prompt.length !== 0)
650
+ ;
651
+ errors = (typeof errors == 'string')
652
+ ? [errors]
653
+ : errors
654
+ ;
655
+ module.verbose('Adding field error state', identifier);
656
+ $fieldGroup
657
+ .addClass(className.error)
658
+ ;
659
+ if(settings.inline) {
660
+ if(!promptExists) {
661
+ $prompt = settings.templates.prompt(errors);
662
+ $prompt
663
+ .appendTo($fieldGroup)
664
+ ;
665
+ }
666
+ $prompt
667
+ .html(errors[0])
668
+ ;
669
+ if(!promptExists) {
670
+ if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
671
+ module.verbose('Displaying error with css transition', settings.transition);
672
+ $prompt.transition(settings.transition + ' in', settings.duration);
673
+ }
674
+ else {
675
+ module.verbose('Displaying error with fallback javascript animation');
676
+ $prompt
677
+ .fadeIn(settings.duration)
678
+ ;
679
+ }
680
+ }
681
+ else {
682
+ module.verbose('Inline errors are disabled, no inline error added', identifier);
683
+ }
684
+ }
685
+ },
686
+ errors: function(errors) {
687
+ module.debug('Adding form error messages', errors);
688
+ module.set.error();
689
+ $message
690
+ .html( settings.templates.error(errors) )
691
+ ;
692
+ }
693
+ },
694
+
695
+ remove: {
696
+ prompt: function(identifier) {
697
+ var
698
+ $field = module.get.field(identifier),
699
+ $fieldGroup = $field.closest($group),
700
+ $prompt = $fieldGroup.children(selector.prompt)
701
+ ;
702
+ $fieldGroup
703
+ .removeClass(className.error)
704
+ ;
705
+ if(settings.inline && $prompt.is(':visible')) {
706
+ module.verbose('Removing prompt for field', identifier);
707
+ if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
708
+ $prompt.transition(settings.transition + ' out', settings.duration, function() {
709
+ $prompt.remove();
710
+ });
711
+ }
712
+ else {
713
+ $prompt
714
+ .fadeOut(settings.duration, function(){
715
+ $prompt.remove();
716
+ })
717
+ ;
718
+ }
719
+ }
720
+ }
721
+ },
722
+
723
+ set: {
724
+ success: function() {
725
+ $module
726
+ .removeClass(className.error)
727
+ .addClass(className.success)
728
+ ;
729
+ },
730
+ defaults: function () {
731
+ $field
732
+ .each(function () {
733
+ var
734
+ $field = $(this),
735
+ isCheckbox = ($field.filter(selector.checkbox).length > 0),
736
+ value = (isCheckbox)
737
+ ? $field.is(':checked')
738
+ : $field.val()
739
+ ;
740
+ $field.data(metadata.defaultValue, value);
741
+ })
742
+ ;
743
+ },
744
+ error: function() {
745
+ $module
746
+ .removeClass(className.success)
747
+ .addClass(className.error)
748
+ ;
749
+ },
750
+ value: function (field, value) {
751
+ var
752
+ fields = {}
753
+ ;
754
+ fields[field] = value;
755
+ return module.set.values.call(element, fields);
756
+ },
757
+ values: function (fields) {
758
+ if($.isEmptyObject(fields)) {
759
+ return;
760
+ }
761
+ $.each(fields, function(key, value) {
762
+ var
763
+ $field = module.get.field(key),
764
+ $element = $field.parent(),
765
+ isMultiple = $.isArray(value),
766
+ isCheckbox = $element.is(selector.uiCheckbox),
767
+ isDropdown = $element.is(selector.uiDropdown),
768
+ isRadio = ($field.is(selector.radio) && isCheckbox),
769
+ fieldExists = ($field.length > 0),
770
+ $multipleField
771
+ ;
772
+ if(fieldExists) {
773
+ if(isMultiple && isCheckbox) {
774
+ module.verbose('Selecting multiple', value, $field);
775
+ $element.checkbox('uncheck');
776
+ $.each(value, function(index, value) {
777
+ $multipleField = $field.filter('[value="' + value + '"]');
778
+ $element = $multipleField.parent();
779
+ if($multipleField.length > 0) {
780
+ $element.checkbox('check');
781
+ }
782
+ });
783
+ }
784
+ else if(isRadio) {
785
+ module.verbose('Selecting radio value', value, $field);
786
+ $field.filter('[value="' + value + '"]')
787
+ .parent(selector.uiCheckbox)
788
+ .checkbox('check')
789
+ ;
790
+ }
791
+ else if(isCheckbox) {
792
+ module.verbose('Setting checkbox value', value, $element);
793
+ if(value === true) {
794
+ $element.checkbox('check');
795
+ }
796
+ else {
797
+ $element.checkbox('uncheck');
798
+ }
799
+ }
800
+ else if(isDropdown) {
801
+ module.verbose('Setting dropdown value', value, $element);
802
+ $element.dropdown('set selected', value);
803
+ }
804
+ else {
805
+ module.verbose('Setting field value', value, $field);
806
+ $field.val(value);
807
+ }
808
+ }
809
+ });
810
+ }
811
+ },
812
+
813
+ validate: {
814
+
815
+ form: function(event, ignoreCallbacks) {
816
+ var
817
+ values = module.get.values(),
818
+ apiRequest
819
+ ;
820
+
821
+ // input keydown event will fire submit repeatedly by browser default
822
+ if(keyHeldDown) {
823
+ return false;
824
+ }
825
+
826
+ // reset errors
827
+ formErrors = [];
828
+ if( module.determine.isValid() ) {
829
+ module.debug('Form has no validation errors, submitting');
830
+ module.set.success();
831
+ if(ignoreCallbacks !== true) {
832
+ return settings.onSuccess.call(element, event, values);
833
+ }
834
+ }
835
+ else {
836
+ module.debug('Form has errors');
837
+ module.set.error();
838
+ if(!settings.inline) {
839
+ module.add.errors(formErrors);
840
+ }
841
+ // prevent ajax submit
842
+ if($module.data('moduleApi') !== undefined) {
843
+ event.stopImmediatePropagation();
844
+ }
845
+ if(ignoreCallbacks !== true) {
846
+ return settings.onFailure.call(element, formErrors, values);
847
+ }
848
+ }
849
+ },
850
+
851
+ // takes a validation object and returns whether field passes validation
852
+ field: function(field, fieldName, showErrors) {
853
+ showErrors = (showErrors !== undefined)
854
+ ? showErrors
855
+ : true
856
+ ;
857
+ if(typeof field == 'string') {
858
+ module.verbose('Validating field', field);
859
+ fieldName = field;
860
+ field = validation[field];
861
+ }
862
+ var
863
+ identifier = field.identifier || fieldName,
864
+ $field = module.get.field(identifier),
865
+ $dependsField = (field.depends)
866
+ ? module.get.field(field.depends)
867
+ : false,
868
+ fieldValid = true,
869
+ fieldErrors = []
870
+ ;
871
+ if(!field.identifier) {
872
+ module.debug('Using field name as identifier', identifier);
873
+ field.identifier = identifier;
874
+ }
875
+ if($field.prop('disabled')) {
876
+ module.debug('Field is disabled. Skipping', identifier);
877
+ fieldValid = true;
878
+ }
879
+ else if(field.optional && module.is.blank($field)){
880
+ module.debug('Field is optional and blank. Skipping', identifier);
881
+ fieldValid = true;
882
+ }
883
+ else if(field.depends && module.is.empty($dependsField)) {
884
+ module.debug('Field depends on another value that is not present or empty. Skipping', $dependsField);
885
+ fieldValid = true;
886
+ }
887
+ else if(field.rules !== undefined) {
888
+ $.each(field.rules, function(index, rule) {
889
+ if( module.has.field(identifier) && !( module.validate.rule(field, rule) ) ) {
890
+ module.debug('Field is invalid', identifier, rule.type);
891
+ fieldErrors.push(module.get.prompt(rule, field));
892
+ fieldValid = false;
893
+ }
894
+ });
895
+ }
896
+ if(fieldValid) {
897
+ if(showErrors) {
898
+ module.remove.prompt(identifier, fieldErrors);
899
+ settings.onValid.call($field);
900
+ }
901
+ }
902
+ else {
903
+ if(showErrors) {
904
+ formErrors = formErrors.concat(fieldErrors);
905
+ module.add.prompt(identifier, fieldErrors);
906
+ settings.onInvalid.call($field, fieldErrors);
907
+ }
908
+ return false;
909
+ }
910
+ return true;
911
+ },
912
+
913
+ // takes validation rule and returns whether field passes rule
914
+ rule: function(field, rule) {
915
+ var
916
+ $field = module.get.field(field.identifier),
917
+ type = rule.type,
918
+ value = $field.val(),
919
+ isValid = true,
920
+ ancillary = module.get.ancillaryValue(rule),
921
+ ruleName = module.get.ruleName(rule),
922
+ ruleFunction = settings.rules[ruleName]
923
+ ;
924
+ if( !$.isFunction(ruleFunction) ) {
925
+ module.error(error.noRule, ruleName);
926
+ return;
927
+ }
928
+ // cast to string avoiding encoding special values
929
+ value = (value === undefined || value === '' || value === null)
930
+ ? ''
931
+ : $.trim(value + '')
932
+ ;
933
+ return ruleFunction.call($field, value, ancillary);
934
+ }
935
+ },
936
+
937
+ setting: function(name, value) {
938
+ if( $.isPlainObject(name) ) {
939
+ $.extend(true, settings, name);
940
+ }
941
+ else if(value !== undefined) {
942
+ settings[name] = value;
943
+ }
944
+ else {
945
+ return settings[name];
946
+ }
947
+ },
948
+ internal: function(name, value) {
949
+ if( $.isPlainObject(name) ) {
950
+ $.extend(true, module, name);
951
+ }
952
+ else if(value !== undefined) {
953
+ module[name] = value;
954
+ }
955
+ else {
956
+ return module[name];
957
+ }
958
+ },
959
+ debug: function() {
960
+ if(!settings.silent && settings.debug) {
961
+ if(settings.performance) {
962
+ module.performance.log(arguments);
963
+ }
964
+ else {
965
+ module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
966
+ module.debug.apply(console, arguments);
967
+ }
968
+ }
969
+ },
970
+ verbose: function() {
971
+ if(!settings.silent && settings.verbose && settings.debug) {
972
+ if(settings.performance) {
973
+ module.performance.log(arguments);
974
+ }
975
+ else {
976
+ module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
977
+ module.verbose.apply(console, arguments);
978
+ }
979
+ }
980
+ },
981
+ error: function() {
982
+ if(!settings.silent) {
983
+ module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
984
+ module.error.apply(console, arguments);
985
+ }
986
+ },
987
+ performance: {
988
+ log: function(message) {
989
+ var
990
+ currentTime,
991
+ executionTime,
992
+ previousTime
993
+ ;
994
+ if(settings.performance) {
995
+ currentTime = new Date().getTime();
996
+ previousTime = time || currentTime;
997
+ executionTime = currentTime - previousTime;
998
+ time = currentTime;
999
+ performance.push({
1000
+ 'Name' : message[0],
1001
+ 'Arguments' : [].slice.call(message, 1) || '',
1002
+ 'Element' : element,
1003
+ 'Execution Time' : executionTime
1004
+ });
1005
+ }
1006
+ clearTimeout(module.performance.timer);
1007
+ module.performance.timer = setTimeout(module.performance.display, 500);
1008
+ },
1009
+ display: function() {
1010
+ var
1011
+ title = settings.name + ':',
1012
+ totalTime = 0
1013
+ ;
1014
+ time = false;
1015
+ clearTimeout(module.performance.timer);
1016
+ $.each(performance, function(index, data) {
1017
+ totalTime += data['Execution Time'];
1018
+ });
1019
+ title += ' ' + totalTime + 'ms';
1020
+ if(moduleSelector) {
1021
+ title += ' \'' + moduleSelector + '\'';
1022
+ }
1023
+ if($allModules.length > 1) {
1024
+ title += ' ' + '(' + $allModules.length + ')';
1025
+ }
1026
+ if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
1027
+ console.groupCollapsed(title);
1028
+ if(console.table) {
1029
+ console.table(performance);
1030
+ }
1031
+ else {
1032
+ $.each(performance, function(index, data) {
1033
+ console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
1034
+ });
1035
+ }
1036
+ console.groupEnd();
1037
+ }
1038
+ performance = [];
1039
+ }
1040
+ },
1041
+ invoke: function(query, passedArguments, context) {
1042
+ var
1043
+ object = instance,
1044
+ maxDepth,
1045
+ found,
1046
+ response
1047
+ ;
1048
+ passedArguments = passedArguments || queryArguments;
1049
+ context = element || context;
1050
+ if(typeof query == 'string' && object !== undefined) {
1051
+ query = query.split(/[\. ]/);
1052
+ maxDepth = query.length - 1;
1053
+ $.each(query, function(depth, value) {
1054
+ var camelCaseValue = (depth != maxDepth)
1055
+ ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
1056
+ : query
1057
+ ;
1058
+ if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
1059
+ object = object[camelCaseValue];
1060
+ }
1061
+ else if( object[camelCaseValue] !== undefined ) {
1062
+ found = object[camelCaseValue];
1063
+ return false;
1064
+ }
1065
+ else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
1066
+ object = object[value];
1067
+ }
1068
+ else if( object[value] !== undefined ) {
1069
+ found = object[value];
1070
+ return false;
1071
+ }
1072
+ else {
1073
+ return false;
1074
+ }
1075
+ });
1076
+ }
1077
+ if( $.isFunction( found ) ) {
1078
+ response = found.apply(context, passedArguments);
1079
+ }
1080
+ else if(found !== undefined) {
1081
+ response = found;
1082
+ }
1083
+ if($.isArray(returnedValue)) {
1084
+ returnedValue.push(response);
1085
+ }
1086
+ else if(returnedValue !== undefined) {
1087
+ returnedValue = [returnedValue, response];
1088
+ }
1089
+ else if(response !== undefined) {
1090
+ returnedValue = response;
1091
+ }
1092
+ return found;
1093
+ }
1094
+ };
1095
+ module.initialize();
1096
+ })
1097
+ ;
1098
+
1099
+ return (returnedValue !== undefined)
1100
+ ? returnedValue
1101
+ : this
1102
+ ;
1103
+ };
1104
+
1105
+ $.fn.form.settings = {
1106
+
1107
+ name : 'Form',
1108
+ namespace : 'form',
1109
+
1110
+ debug : false,
1111
+ verbose : false,
1112
+ performance : true,
1113
+
1114
+ fields : false,
1115
+
1116
+ keyboardShortcuts : true,
1117
+ on : 'submit',
1118
+ inline : false,
1119
+
1120
+ delay : 200,
1121
+ revalidate : true,
1122
+
1123
+ transition : 'scale',
1124
+ duration : 200,
1125
+
1126
+ onValid : function() {},
1127
+ onInvalid : function() {},
1128
+ onSuccess : function() { return true; },
1129
+ onFailure : function() { return false; },
1130
+
1131
+ metadata : {
1132
+ defaultValue : 'default',
1133
+ validate : 'validate'
1134
+ },
1135
+
1136
+ regExp: {
1137
+ htmlID : /^[a-zA-Z][\w:.-]*$/g,
1138
+ bracket : /\[(.*)\]/i,
1139
+ decimal : /^\d+\.?\d*$/,
1140
+ email : /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i,
1141
+ escape : /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,
1142
+ flags : /^\/(.*)\/(.*)?/,
1143
+ integer : /^\-?\d+$/,
1144
+ number : /^\-?\d*(\.\d+)?$/,
1145
+ url : /(https?:\/\/(?:www\.|(?!www))[^\s\.]+\.[^\s]{2,}|www\.[^\s]+\.[^\s]{2,})/i
1146
+ },
1147
+
1148
+ text: {
1149
+ unspecifiedRule : 'Please enter a valid value',
1150
+ unspecifiedField : 'This field'
1151
+ },
1152
+
1153
+ prompt: {
1154
+ empty : '{name} must have a value',
1155
+ checked : '{name} must be checked',
1156
+ email : '{name} must be a valid e-mail',
1157
+ url : '{name} must be a valid url',
1158
+ regExp : '{name} is not formatted correctly',
1159
+ integer : '{name} must be an integer',
1160
+ decimal : '{name} must be a decimal number',
1161
+ number : '{name} must be set to a number',
1162
+ is : '{name} must be "{ruleValue}"',
1163
+ isExactly : '{name} must be exactly "{ruleValue}"',
1164
+ not : '{name} cannot be set to "{ruleValue}"',
1165
+ notExactly : '{name} cannot be set to exactly "{ruleValue}"',
1166
+ contain : '{name} cannot contain "{ruleValue}"',
1167
+ containExactly : '{name} cannot contain exactly "{ruleValue}"',
1168
+ doesntContain : '{name} must contain "{ruleValue}"',
1169
+ doesntContainExactly : '{name} must contain exactly "{ruleValue}"',
1170
+ minLength : '{name} must be at least {ruleValue} characters',
1171
+ length : '{name} must be at least {ruleValue} characters',
1172
+ exactLength : '{name} must be exactly {ruleValue} characters',
1173
+ maxLength : '{name} cannot be longer than {ruleValue} characters',
1174
+ match : '{name} must match {ruleValue} field',
1175
+ different : '{name} must have a different value than {ruleValue} field',
1176
+ creditCard : '{name} must be a valid credit card number',
1177
+ minCount : '{name} must have at least {ruleValue} choices',
1178
+ exactCount : '{name} must have exactly {ruleValue} choices',
1179
+ maxCount : '{name} must have {ruleValue} or less choices'
1180
+ },
1181
+
1182
+ selector : {
1183
+ checkbox : 'input[type="checkbox"], input[type="radio"]',
1184
+ clear : '.clear',
1185
+ field : 'input, textarea, select',
1186
+ group : '.field',
1187
+ input : 'input',
1188
+ message : '.error.message',
1189
+ prompt : '.prompt.label',
1190
+ radio : 'input[type="radio"]',
1191
+ reset : '.reset:not([type="reset"])',
1192
+ submit : '.submit:not([type="submit"])',
1193
+ uiCheckbox : '.ui.checkbox',
1194
+ uiDropdown : '.ui.dropdown'
1195
+ },
1196
+
1197
+ className : {
1198
+ error : 'error',
1199
+ label : 'ui prompt label',
1200
+ pressed : 'down',
1201
+ success : 'success'
1202
+ },
1203
+
1204
+ error: {
1205
+ identifier : 'You must specify a string identifier for each field',
1206
+ method : 'The method you called is not defined.',
1207
+ noRule : 'There is no rule matching the one you specified',
1208
+ oldSyntax : 'Starting in 2.0 forms now only take a single settings object. Validation settings converted to new syntax automatically.'
1209
+ },
1210
+
1211
+ templates: {
1212
+
1213
+ // template that produces error message
1214
+ error: function(errors) {
1215
+ var
1216
+ html = '<ul class="list">'
1217
+ ;
1218
+ $.each(errors, function(index, value) {
1219
+ html += '<li>' + value + '</li>';
1220
+ });
1221
+ html += '</ul>';
1222
+ return $(html);
1223
+ },
1224
+
1225
+ // template that produces label
1226
+ prompt: function(errors) {
1227
+ return $('<div/>')
1228
+ .addClass('ui basic red pointing prompt label')
1229
+ .html(errors[0])
1230
+ ;
1231
+ }
1232
+ },
1233
+
1234
+ rules: {
1235
+
1236
+ // is not empty or blank string
1237
+ empty: function(value) {
1238
+ return !(value === undefined || '' === value || $.isArray(value) && value.length === 0);
1239
+ },
1240
+
1241
+ // checkbox checked
1242
+ checked: function() {
1243
+ return ($(this).filter(':checked').length > 0);
1244
+ },
1245
+
1246
+ // is most likely an email
1247
+ email: function(value){
1248
+ return $.fn.form.settings.regExp.email.test(value);
1249
+ },
1250
+
1251
+ // value is most likely url
1252
+ url: function(value) {
1253
+ return $.fn.form.settings.regExp.url.test(value);
1254
+ },
1255
+
1256
+ // matches specified regExp
1257
+ regExp: function(value, regExp) {
1258
+ if(regExp instanceof RegExp) {
1259
+ return value.match(regExp);
1260
+ }
1261
+ var
1262
+ regExpParts = regExp.match($.fn.form.settings.regExp.flags),
1263
+ flags
1264
+ ;
1265
+ // regular expression specified as /baz/gi (flags)
1266
+ if(regExpParts) {
1267
+ regExp = (regExpParts.length >= 2)
1268
+ ? regExpParts[1]
1269
+ : regExp
1270
+ ;
1271
+ flags = (regExpParts.length >= 3)
1272
+ ? regExpParts[2]
1273
+ : ''
1274
+ ;
1275
+ }
1276
+ return value.match( new RegExp(regExp, flags) );
1277
+ },
1278
+
1279
+ // is valid integer or matches range
1280
+ integer: function(value, range) {
1281
+ var
1282
+ intRegExp = $.fn.form.settings.regExp.integer,
1283
+ min,
1284
+ max,
1285
+ parts
1286
+ ;
1287
+ if( !range || ['', '..'].indexOf(range) !== -1) {
1288
+ // do nothing
1289
+ }
1290
+ else if(range.indexOf('..') == -1) {
1291
+ if(intRegExp.test(range)) {
1292
+ min = max = range - 0;
1293
+ }
1294
+ }
1295
+ else {
1296
+ parts = range.split('..', 2);
1297
+ if(intRegExp.test(parts[0])) {
1298
+ min = parts[0] - 0;
1299
+ }
1300
+ if(intRegExp.test(parts[1])) {
1301
+ max = parts[1] - 0;
1302
+ }
1303
+ }
1304
+ return (
1305
+ intRegExp.test(value) &&
1306
+ (min === undefined || value >= min) &&
1307
+ (max === undefined || value <= max)
1308
+ );
1309
+ },
1310
+
1311
+ // is valid number (with decimal)
1312
+ decimal: function(value) {
1313
+ return $.fn.form.settings.regExp.decimal.test(value);
1314
+ },
1315
+
1316
+ // is valid number
1317
+ number: function(value) {
1318
+ return $.fn.form.settings.regExp.number.test(value);
1319
+ },
1320
+
1321
+ // is value (case insensitive)
1322
+ is: function(value, text) {
1323
+ text = (typeof text == 'string')
1324
+ ? text.toLowerCase()
1325
+ : text
1326
+ ;
1327
+ value = (typeof value == 'string')
1328
+ ? value.toLowerCase()
1329
+ : value
1330
+ ;
1331
+ return (value == text);
1332
+ },
1333
+
1334
+ // is value
1335
+ isExactly: function(value, text) {
1336
+ return (value == text);
1337
+ },
1338
+
1339
+ // value is not another value (case insensitive)
1340
+ not: function(value, notValue) {
1341
+ value = (typeof value == 'string')
1342
+ ? value.toLowerCase()
1343
+ : value
1344
+ ;
1345
+ notValue = (typeof notValue == 'string')
1346
+ ? notValue.toLowerCase()
1347
+ : notValue
1348
+ ;
1349
+ return (value != notValue);
1350
+ },
1351
+
1352
+ // value is not another value (case sensitive)
1353
+ notExactly: function(value, notValue) {
1354
+ return (value != notValue);
1355
+ },
1356
+
1357
+ // value contains text (insensitive)
1358
+ contains: function(value, text) {
1359
+ // escape regex characters
1360
+ text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
1361
+ return (value.search( new RegExp(text, 'i') ) !== -1);
1362
+ },
1363
+
1364
+ // value contains text (case sensitive)
1365
+ containsExactly: function(value, text) {
1366
+ // escape regex characters
1367
+ text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
1368
+ return (value.search( new RegExp(text) ) !== -1);
1369
+ },
1370
+
1371
+ // value contains text (insensitive)
1372
+ doesntContain: function(value, text) {
1373
+ // escape regex characters
1374
+ text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
1375
+ return (value.search( new RegExp(text, 'i') ) === -1);
1376
+ },
1377
+
1378
+ // value contains text (case sensitive)
1379
+ doesntContainExactly: function(value, text) {
1380
+ // escape regex characters
1381
+ text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
1382
+ return (value.search( new RegExp(text) ) === -1);
1383
+ },
1384
+
1385
+ // is at least string length
1386
+ minLength: function(value, requiredLength) {
1387
+ return (value !== undefined)
1388
+ ? (value.length >= requiredLength)
1389
+ : false
1390
+ ;
1391
+ },
1392
+
1393
+ // see rls notes for 2.0.6 (this is a duplicate of minLength)
1394
+ length: function(value, requiredLength) {
1395
+ return (value !== undefined)
1396
+ ? (value.length >= requiredLength)
1397
+ : false
1398
+ ;
1399
+ },
1400
+
1401
+ // is exactly length
1402
+ exactLength: function(value, requiredLength) {
1403
+ return (value !== undefined)
1404
+ ? (value.length == requiredLength)
1405
+ : false
1406
+ ;
1407
+ },
1408
+
1409
+ // is less than length
1410
+ maxLength: function(value, maxLength) {
1411
+ return (value !== undefined)
1412
+ ? (value.length <= maxLength)
1413
+ : false
1414
+ ;
1415
+ },
1416
+
1417
+ // matches another field
1418
+ match: function(value, identifier) {
1419
+ var
1420
+ $form = $(this),
1421
+ matchingValue
1422
+ ;
1423
+ if( $('[data-validate="'+ identifier +'"]').length > 0 ) {
1424
+ matchingValue = $('[data-validate="'+ identifier +'"]').val();
1425
+ }
1426
+ else if($('#' + identifier).length > 0) {
1427
+ matchingValue = $('#' + identifier).val();
1428
+ }
1429
+ else if($('[name="' + identifier +'"]').length > 0) {
1430
+ matchingValue = $('[name="' + identifier + '"]').val();
1431
+ }
1432
+ else if( $('[name="' + identifier +'[]"]').length > 0 ) {
1433
+ matchingValue = $('[name="' + identifier +'[]"]');
1434
+ }
1435
+ return (matchingValue !== undefined)
1436
+ ? ( value.toString() == matchingValue.toString() )
1437
+ : false
1438
+ ;
1439
+ },
1440
+
1441
+ // different than another field
1442
+ different: function(value, identifier) {
1443
+ // use either id or name of field
1444
+ var
1445
+ $form = $(this),
1446
+ matchingValue
1447
+ ;
1448
+ if( $('[data-validate="'+ identifier +'"]').length > 0 ) {
1449
+ matchingValue = $('[data-validate="'+ identifier +'"]').val();
1450
+ }
1451
+ else if($('#' + identifier).length > 0) {
1452
+ matchingValue = $('#' + identifier).val();
1453
+ }
1454
+ else if($('[name="' + identifier +'"]').length > 0) {
1455
+ matchingValue = $('[name="' + identifier + '"]').val();
1456
+ }
1457
+ else if( $('[name="' + identifier +'[]"]').length > 0 ) {
1458
+ matchingValue = $('[name="' + identifier +'[]"]');
1459
+ }
1460
+ return (matchingValue !== undefined)
1461
+ ? ( value.toString() !== matchingValue.toString() )
1462
+ : false
1463
+ ;
1464
+ },
1465
+
1466
+ creditCard: function(cardNumber, cardTypes) {
1467
+ var
1468
+ cards = {
1469
+ visa: {
1470
+ pattern : /^4/,
1471
+ length : [16]
1472
+ },
1473
+ amex: {
1474
+ pattern : /^3[47]/,
1475
+ length : [15]
1476
+ },
1477
+ mastercard: {
1478
+ pattern : /^5[1-5]/,
1479
+ length : [16]
1480
+ },
1481
+ discover: {
1482
+ pattern : /^(6011|622(12[6-9]|1[3-9][0-9]|[2-8][0-9]{2}|9[0-1][0-9]|92[0-5]|64[4-9])|65)/,
1483
+ length : [16]
1484
+ },
1485
+ unionPay: {
1486
+ pattern : /^(62|88)/,
1487
+ length : [16, 17, 18, 19]
1488
+ },
1489
+ jcb: {
1490
+ pattern : /^35(2[89]|[3-8][0-9])/,
1491
+ length : [16]
1492
+ },
1493
+ maestro: {
1494
+ pattern : /^(5018|5020|5038|6304|6759|676[1-3])/,
1495
+ length : [12, 13, 14, 15, 16, 17, 18, 19]
1496
+ },
1497
+ dinersClub: {
1498
+ pattern : /^(30[0-5]|^36)/,
1499
+ length : [14]
1500
+ },
1501
+ laser: {
1502
+ pattern : /^(6304|670[69]|6771)/,
1503
+ length : [16, 17, 18, 19]
1504
+ },
1505
+ visaElectron: {
1506
+ pattern : /^(4026|417500|4508|4844|491(3|7))/,
1507
+ length : [16]
1508
+ }
1509
+ },
1510
+ valid = {},
1511
+ validCard = false,
1512
+ requiredTypes = (typeof cardTypes == 'string')
1513
+ ? cardTypes.split(',')
1514
+ : false,
1515
+ unionPay,
1516
+ validation
1517
+ ;
1518
+
1519
+ if(typeof cardNumber !== 'string' || cardNumber.length === 0) {
1520
+ return;
1521
+ }
1522
+
1523
+ // verify card types
1524
+ if(requiredTypes) {
1525
+ $.each(requiredTypes, function(index, type){
1526
+ // verify each card type
1527
+ validation = cards[type];
1528
+ if(validation) {
1529
+ valid = {
1530
+ length : ($.inArray(cardNumber.length, validation.length) !== -1),
1531
+ pattern : (cardNumber.search(validation.pattern) !== -1)
1532
+ };
1533
+ if(valid.length && valid.pattern) {
1534
+ validCard = true;
1535
+ }
1536
+ }
1537
+ });
1538
+
1539
+ if(!validCard) {
1540
+ return false;
1541
+ }
1542
+ }
1543
+
1544
+ // skip luhn for UnionPay
1545
+ unionPay = {
1546
+ number : ($.inArray(cardNumber.length, cards.unionPay.length) !== -1),
1547
+ pattern : (cardNumber.search(cards.unionPay.pattern) !== -1)
1548
+ };
1549
+ if(unionPay.number && unionPay.pattern) {
1550
+ return true;
1551
+ }
1552
+
1553
+ // verify luhn, adapted from <https://gist.github.com/2134376>
1554
+ var
1555
+ length = cardNumber.length,
1556
+ multiple = 0,
1557
+ producedValue = [
1558
+ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
1559
+ [0, 2, 4, 6, 8, 1, 3, 5, 7, 9]
1560
+ ],
1561
+ sum = 0
1562
+ ;
1563
+ while (length--) {
1564
+ sum += producedValue[multiple][parseInt(cardNumber.charAt(length), 10)];
1565
+ multiple ^= 1;
1566
+ }
1567
+ return (sum % 10 === 0 && sum > 0);
1568
+ },
1569
+
1570
+ minCount: function(value, minCount) {
1571
+ if(minCount == 0) {
1572
+ return true;
1573
+ }
1574
+ if(minCount == 1) {
1575
+ return (value !== '');
1576
+ }
1577
+ return (value.split(',').length >= minCount);
1578
+ },
1579
+
1580
+ exactCount: function(value, exactCount) {
1581
+ if(exactCount == 0) {
1582
+ return (value === '');
1583
+ }
1584
+ if(exactCount == 1) {
1585
+ return (value !== '' && value.search(',') === -1);
1586
+ }
1587
+ return (value.split(',').length == exactCount);
1588
+ },
1589
+
1590
+ maxCount: function(value, maxCount) {
1591
+ if(maxCount == 0) {
1592
+ return false;
1593
+ }
1594
+ if(maxCount == 1) {
1595
+ return (value.search(',') === -1);
1596
+ }
1597
+ return (value.split(',').length <= maxCount);
1598
+ }
1599
+ }
1600
+
1601
+ };
1602
+
1603
+ })( jQuery, window, document );