volt-semantic-ui 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (155) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -0
  3. data/Gemfile +0 -0
  4. data/LICENSE.txt +0 -0
  5. data/README.md +0 -0
  6. data/Rakefile +0 -0
  7. data/app/semanticui/assets/css/semantic.min.css +3 -3
  8. data/app/semanticui/assets/css/themes/basic/assets/fonts/icons.eot +0 -0
  9. data/app/semanticui/assets/css/themes/basic/assets/fonts/icons.svg +0 -0
  10. data/app/semanticui/assets/css/themes/basic/assets/fonts/icons.ttf +0 -0
  11. data/app/semanticui/assets/css/themes/basic/assets/fonts/icons.woff +0 -0
  12. data/app/semanticui/assets/css/themes/default/assets/fonts/icons.eot +0 -0
  13. data/app/semanticui/assets/css/themes/default/assets/fonts/icons.otf +0 -0
  14. data/app/semanticui/assets/css/themes/default/assets/fonts/icons.svg +526 -465
  15. data/app/semanticui/assets/css/themes/default/assets/fonts/icons.ttf +0 -0
  16. data/app/semanticui/assets/css/themes/default/assets/fonts/icons.woff +0 -0
  17. data/app/semanticui/assets/css/themes/default/assets/fonts/icons.woff2 +0 -0
  18. data/app/semanticui/assets/css/themes/default/assets/images/flags.png +0 -0
  19. data/app/semanticui/assets/js/components/accordion.css +256 -0
  20. data/app/semanticui/assets/js/components/accordion.js +578 -0
  21. data/app/semanticui/assets/js/components/accordion.min.css +10 -0
  22. data/app/semanticui/assets/js/components/accordion.min.js +11 -0
  23. data/app/semanticui/assets/js/components/ad.css +276 -0
  24. data/app/semanticui/assets/js/components/ad.min.css +10 -0
  25. data/app/semanticui/assets/js/components/api.js +871 -0
  26. data/app/semanticui/assets/js/components/api.min.js +11 -0
  27. data/app/semanticui/assets/js/components/breadcrumb.css +124 -0
  28. data/app/semanticui/assets/js/components/breadcrumb.min.css +10 -0
  29. data/app/semanticui/assets/js/components/button.css +2391 -0
  30. data/app/semanticui/assets/js/components/button.min.css +10 -0
  31. data/app/semanticui/assets/js/components/card.css +909 -0
  32. data/app/semanticui/assets/js/components/card.min.css +10 -0
  33. data/app/semanticui/assets/js/components/checkbox.css +513 -0
  34. data/app/semanticui/assets/js/components/checkbox.js +509 -0
  35. data/app/semanticui/assets/js/components/checkbox.min.css +10 -0
  36. data/app/semanticui/assets/js/components/checkbox.min.js +11 -0
  37. data/app/semanticui/assets/js/components/comment.css +259 -0
  38. data/app/semanticui/assets/js/components/comment.min.css +10 -0
  39. data/app/semanticui/assets/js/components/dimmer.css +186 -0
  40. data/app/semanticui/assets/js/components/dimmer.js +669 -0
  41. data/app/semanticui/assets/js/components/dimmer.min.css +10 -0
  42. data/app/semanticui/assets/js/components/dimmer.min.js +11 -0
  43. data/app/semanticui/assets/js/components/divider.css +241 -0
  44. data/app/semanticui/assets/js/components/divider.min.css +10 -0
  45. data/app/semanticui/assets/js/components/dropdown.css +1103 -0
  46. data/app/semanticui/assets/js/components/dropdown.js +1795 -0
  47. data/app/semanticui/assets/js/components/dropdown.min.css +10 -0
  48. data/app/semanticui/assets/js/components/dropdown.min.js +11 -0
  49. data/app/semanticui/assets/js/components/feed.css +276 -0
  50. data/app/semanticui/assets/js/components/feed.min.css +10 -0
  51. data/app/semanticui/assets/js/components/flag.css +1024 -0
  52. data/app/semanticui/assets/js/components/flag.min.css +10 -0
  53. data/app/semanticui/assets/js/components/form.css +891 -0
  54. data/app/semanticui/assets/js/components/form.js +1118 -0
  55. data/app/semanticui/assets/js/components/form.min.css +10 -0
  56. data/app/semanticui/assets/js/components/form.min.js +11 -0
  57. data/app/semanticui/assets/js/components/grid.css +1871 -0
  58. data/app/semanticui/assets/js/components/grid.min.css +10 -0
  59. data/app/semanticui/assets/js/components/header.css +596 -0
  60. data/app/semanticui/assets/js/components/header.min.css +10 -0
  61. data/app/semanticui/assets/js/components/icon.css +2467 -0
  62. data/app/semanticui/assets/js/components/icon.min.css +10 -0
  63. data/app/semanticui/assets/js/components/image.css +288 -0
  64. data/app/semanticui/assets/js/components/image.min.css +10 -0
  65. data/app/semanticui/assets/js/components/input.css +439 -0
  66. data/app/semanticui/assets/js/components/input.min.css +10 -0
  67. data/app/semanticui/assets/js/components/item.css +456 -0
  68. data/app/semanticui/assets/js/components/item.min.css +10 -0
  69. data/app/semanticui/assets/js/components/label.css +963 -0
  70. data/app/semanticui/assets/js/components/label.min.css +10 -0
  71. data/app/semanticui/assets/js/components/list.css +878 -0
  72. data/app/semanticui/assets/js/components/list.min.css +10 -0
  73. data/app/semanticui/assets/js/components/loader.css +284 -0
  74. data/app/semanticui/assets/js/components/loader.min.css +10 -0
  75. data/app/semanticui/assets/js/components/menu.css +1608 -0
  76. data/app/semanticui/assets/js/components/menu.min.css +10 -0
  77. data/app/semanticui/assets/js/components/message.css +421 -0
  78. data/app/semanticui/assets/js/components/message.min.css +10 -0
  79. data/app/semanticui/assets/js/components/modal.css +432 -0
  80. data/app/semanticui/assets/js/components/modal.js +860 -0
  81. data/app/semanticui/assets/js/components/modal.min.css +10 -0
  82. data/app/semanticui/assets/js/components/modal.min.js +11 -0
  83. data/app/semanticui/assets/js/components/nag.css +148 -0
  84. data/app/semanticui/assets/js/components/nag.js +477 -0
  85. data/app/semanticui/assets/js/components/nag.min.css +10 -0
  86. data/app/semanticui/assets/js/components/nag.min.js +11 -0
  87. data/app/semanticui/assets/js/components/popup.css +293 -0
  88. data/app/semanticui/assets/js/components/popup.js +1224 -0
  89. data/app/semanticui/assets/js/components/popup.min.css +10 -0
  90. data/app/semanticui/assets/js/components/popup.min.js +11 -0
  91. data/app/semanticui/assets/js/components/progress.css +461 -0
  92. data/app/semanticui/assets/js/components/progress.js +785 -0
  93. data/app/semanticui/assets/js/components/progress.min.css +10 -0
  94. data/app/semanticui/assets/js/components/progress.min.js +11 -0
  95. data/app/semanticui/assets/js/components/rail.css +124 -0
  96. data/app/semanticui/assets/js/components/rail.min.css +10 -0
  97. data/app/semanticui/assets/js/components/rating.css +251 -0
  98. data/app/semanticui/assets/js/components/rating.js +451 -0
  99. data/app/semanticui/assets/js/components/rating.min.css +10 -0
  100. data/app/semanticui/assets/js/components/rating.min.js +11 -0
  101. data/app/semanticui/assets/js/components/reset.css +429 -0
  102. data/app/semanticui/assets/js/components/reset.min.css +10 -0
  103. data/app/semanticui/assets/js/components/reveal.css +293 -0
  104. data/app/semanticui/assets/js/components/reveal.min.css +10 -0
  105. data/app/semanticui/assets/js/components/search.css +329 -0
  106. data/app/semanticui/assets/js/components/search.js +1096 -0
  107. data/app/semanticui/assets/js/components/search.min.css +10 -0
  108. data/app/semanticui/assets/js/components/search.min.js +11 -0
  109. data/app/semanticui/assets/js/components/segment.css +635 -0
  110. data/app/semanticui/assets/js/components/segment.min.css +10 -0
  111. data/app/semanticui/assets/js/components/shape.css +154 -0
  112. data/app/semanticui/assets/js/components/shape.js +830 -0
  113. data/app/semanticui/assets/js/components/shape.min.css +10 -0
  114. data/app/semanticui/assets/js/components/shape.min.js +11 -0
  115. data/app/semanticui/assets/js/components/sidebar.css +625 -0
  116. data/app/semanticui/assets/js/components/sidebar.js +1089 -0
  117. data/app/semanticui/assets/js/components/sidebar.min.css +10 -0
  118. data/app/semanticui/assets/js/components/sidebar.min.js +11 -0
  119. data/app/semanticui/assets/js/components/site.css +160 -0
  120. data/app/semanticui/assets/js/components/site.js +487 -0
  121. data/app/semanticui/assets/js/components/site.min.css +10 -0
  122. data/app/semanticui/assets/js/components/site.min.js +11 -0
  123. data/app/semanticui/assets/js/components/state.js +695 -0
  124. data/app/semanticui/assets/js/components/state.min.js +11 -0
  125. data/app/semanticui/assets/js/components/statistic.css +409 -0
  126. data/app/semanticui/assets/js/components/statistic.min.css +10 -0
  127. data/app/semanticui/assets/js/components/step.css +432 -0
  128. data/app/semanticui/assets/js/components/step.min.css +10 -0
  129. data/app/semanticui/assets/js/components/sticky.css +79 -0
  130. data/app/semanticui/assets/js/components/sticky.js +792 -0
  131. data/app/semanticui/assets/js/components/sticky.min.css +10 -0
  132. data/app/semanticui/assets/js/components/sticky.min.js +11 -0
  133. data/app/semanticui/assets/js/components/tab.css +92 -0
  134. data/app/semanticui/assets/js/components/tab.js +802 -0
  135. data/app/semanticui/assets/js/components/tab.min.css +10 -0
  136. data/app/semanticui/assets/js/components/tab.min.js +11 -0
  137. data/app/semanticui/assets/js/components/table.css +1000 -0
  138. data/app/semanticui/assets/js/components/table.min.css +10 -0
  139. data/app/semanticui/assets/js/components/transition.css +1990 -0
  140. data/app/semanticui/assets/js/components/transition.js +1038 -0
  141. data/app/semanticui/assets/js/components/transition.min.css +10 -0
  142. data/app/semanticui/assets/js/components/transition.min.js +11 -0
  143. data/app/semanticui/assets/js/components/video.css +125 -0
  144. data/app/semanticui/assets/js/components/video.js +540 -0
  145. data/app/semanticui/assets/js/components/video.min.css +10 -0
  146. data/app/semanticui/assets/js/components/video.min.js +11 -0
  147. data/app/semanticui/assets/js/components/visibility.js +1032 -0
  148. data/app/semanticui/assets/js/components/visibility.min.js +11 -0
  149. data/app/semanticui/assets/js/semantic.min.js +9 -9
  150. data/lib/volt/semanticui.rb +0 -0
  151. data/lib/volt/semanticui/version.rb +1 -1
  152. data/volt-semantic-ui-0.0.1.gem +0 -0
  153. data/volt-semanticui-0.0.1.gem +0 -0
  154. data/volt-semanticui.gemspec +0 -0
  155. metadata +141 -10
@@ -0,0 +1,1118 @@
1
+ /*!
2
+ * # Semantic UI 1.11.4 - Form Validation
3
+ * http://github.com/semantic-org/semantic-ui/
4
+ *
5
+ *
6
+ * Copyright 2014 Contributors
7
+ * Released under the MIT license
8
+ * http://opensource.org/licenses/MIT
9
+ *
10
+ */
11
+
12
+ ;(function ( $, window, document, undefined ) {
13
+
14
+ "use strict";
15
+
16
+ $.fn.form = function(fields, parameters) {
17
+ var
18
+ $allModules = $(this),
19
+
20
+ settings = $.extend(true, {}, $.fn.form.settings, parameters),
21
+ validation = $.extend({}, $.fn.form.settings.defaults, fields),
22
+
23
+ namespace = settings.namespace,
24
+ metadata = settings.metadata,
25
+ selector = settings.selector,
26
+ className = settings.className,
27
+ error = settings.error,
28
+
29
+ eventNamespace = '.' + namespace,
30
+ moduleNamespace = 'module-' + namespace,
31
+
32
+ moduleSelector = $allModules.selector || '',
33
+
34
+ time = new Date().getTime(),
35
+ performance = [],
36
+
37
+ query = arguments[0],
38
+ methodInvoked = (typeof query == 'string'),
39
+ queryArguments = [].slice.call(arguments, 1),
40
+ returnedValue
41
+ ;
42
+ $allModules
43
+ .each(function() {
44
+ var
45
+ $module = $(this),
46
+ $field = $(this).find(selector.field),
47
+ $group = $(this).find(selector.group),
48
+ $message = $(this).find(selector.message),
49
+ $prompt = $(this).find(selector.prompt),
50
+
51
+ $submit = $(this).find(selector.submit),
52
+ $clear = $(this).find(selector.clear),
53
+ $reset = $(this).find(selector.reset),
54
+
55
+ formErrors = [],
56
+ keyHeldDown = false,
57
+
58
+ element = this,
59
+ instance = $module.data(moduleNamespace),
60
+ module
61
+ ;
62
+
63
+ module = {
64
+
65
+ initialize: function() {
66
+ module.verbose('Initializing form validation', $module, validation, settings);
67
+ module.bindEvents();
68
+ module.set.defaults();
69
+ module.instantiate();
70
+ },
71
+
72
+ instantiate: function() {
73
+ module.verbose('Storing instance of module', module);
74
+ instance = module;
75
+ $module
76
+ .data(moduleNamespace, module)
77
+ ;
78
+ },
79
+
80
+ destroy: function() {
81
+ module.verbose('Destroying previous module', instance);
82
+ module.removeEvents();
83
+ $module
84
+ .removeData(moduleNamespace)
85
+ ;
86
+ },
87
+
88
+ refresh: function() {
89
+ module.verbose('Refreshing selector cache');
90
+ $field = $module.find(selector.field);
91
+ },
92
+
93
+ submit: function() {
94
+ module.verbose('Submitting form', $module);
95
+ $module
96
+ .submit()
97
+ ;
98
+ },
99
+
100
+ attachEvents: function(selector, action) {
101
+ action = action || 'submit';
102
+ $(selector)
103
+ .on('click', function(event) {
104
+ module[action]();
105
+ event.preventDefault();
106
+ })
107
+ ;
108
+ },
109
+
110
+ bindEvents: function() {
111
+ if(settings.keyboardShortcuts) {
112
+ $field
113
+ .on('keydown' + eventNamespace, module.event.field.keydown)
114
+ ;
115
+ }
116
+ $module
117
+ .on('submit' + eventNamespace, module.validate.form)
118
+ ;
119
+ $field
120
+ .on('blur' + eventNamespace, module.event.field.blur)
121
+ ;
122
+
123
+ // attach events to common elements
124
+ module.attachEvents($submit, 'submit');
125
+ module.attachEvents($reset, 'reset');
126
+ module.attachEvents($clear, 'clear');
127
+
128
+ $field
129
+ .each(function() {
130
+ var
131
+ type = $(this).prop('type'),
132
+ inputEvent = module.get.changeEvent(type)
133
+ ;
134
+ $(this)
135
+ .on(inputEvent + eventNamespace, module.event.field.change)
136
+ ;
137
+ })
138
+ ;
139
+ },
140
+
141
+ clear: function() {
142
+ $field
143
+ .each(function () {
144
+ var
145
+ $field = $(this),
146
+ $element = $field.parent(),
147
+ $fieldGroup = $field.closest($group),
148
+ $prompt = $fieldGroup.find(selector.prompt),
149
+ defaultValue = $field.data(metadata.defaultValue) || '',
150
+ isCheckbox = $element.is(selector.uiCheckbox),
151
+ isDropdown = $element.is(selector.uiDropdown),
152
+ isErrored = $fieldGroup.hasClass(className.error)
153
+ ;
154
+ if(isErrored) {
155
+ module.verbose('Resetting error on field', $fieldGroup);
156
+ $fieldGroup.removeClass(className.error);
157
+ $prompt.remove();
158
+ }
159
+ if(isDropdown) {
160
+ module.verbose('Resetting dropdown value', $element, defaultValue);
161
+ $element.dropdown('clear');
162
+ }
163
+ else if(isCheckbox) {
164
+ $element.checkbox('uncheck');
165
+ }
166
+ else {
167
+ module.verbose('Resetting field value', $field, defaultValue);
168
+ $field.val('');
169
+ }
170
+ })
171
+ ;
172
+ },
173
+
174
+ reset: function() {
175
+ $field
176
+ .each(function () {
177
+ var
178
+ $field = $(this),
179
+ $element = $field.parent(),
180
+ $fieldGroup = $field.closest($group),
181
+ $prompt = $fieldGroup.find(selector.prompt),
182
+ defaultValue = $field.data(metadata.defaultValue) || '',
183
+ isCheckbox = $element.is(selector.uiCheckbox),
184
+ isDropdown = $element.is(selector.uiDropdown),
185
+ isErrored = $fieldGroup.hasClass(className.error)
186
+ ;
187
+ if(isErrored) {
188
+ module.verbose('Resetting error on field', $fieldGroup);
189
+ $fieldGroup.removeClass(className.error);
190
+ $prompt.remove();
191
+ }
192
+ if(isDropdown) {
193
+ module.verbose('Resetting dropdown value', $element, defaultValue);
194
+ $element.dropdown('restore defaults');
195
+ }
196
+ else if(isCheckbox) {
197
+ module.verbose('Resetting checkbox value', $element, defaultValue);
198
+ if(defaultValue === true) {
199
+ $element.checkbox('check');
200
+ }
201
+ else {
202
+ $element.checkbox('uncheck');
203
+ }
204
+ }
205
+ else {
206
+ module.verbose('Resetting field value', $field, defaultValue);
207
+ $field.val(defaultValue);
208
+ }
209
+ })
210
+ ;
211
+ },
212
+
213
+ removeEvents: function() {
214
+ $module
215
+ .off(eventNamespace)
216
+ ;
217
+ $field
218
+ .off(eventNamespace)
219
+ ;
220
+ $submit
221
+ .off(eventNamespace)
222
+ ;
223
+ $field
224
+ .off(eventNamespace)
225
+ ;
226
+ },
227
+
228
+ event: {
229
+ field: {
230
+ keydown: function(event) {
231
+ var
232
+ $field = $(this),
233
+ key = event.which,
234
+ keyCode = {
235
+ enter : 13,
236
+ escape : 27
237
+ }
238
+ ;
239
+ if( key == keyCode.escape) {
240
+ module.verbose('Escape key pressed blurring field');
241
+ $field
242
+ .blur()
243
+ ;
244
+ }
245
+ if(!event.ctrlKey && key == keyCode.enter && $field.is(selector.input) && $field.not(selector.checkbox).length > 0 ) {
246
+ $submit
247
+ .addClass(className.pressed)
248
+ ;
249
+ if(!keyHeldDown) {
250
+ $field
251
+ .one('keyup' + eventNamespace, module.event.field.keyup)
252
+ ;
253
+ module.submit();
254
+ module.debug('Enter pressed on input submitting form');
255
+ }
256
+ keyHeldDown = true;
257
+ }
258
+ },
259
+ keyup: function() {
260
+ keyHeldDown = false;
261
+ $submit.removeClass(className.pressed);
262
+ },
263
+ blur: function() {
264
+ var
265
+ $field = $(this),
266
+ $fieldGroup = $field.closest($group)
267
+ ;
268
+ if( $fieldGroup.hasClass(className.error) ) {
269
+ module.debug('Revalidating field', $field, module.get.validation($field));
270
+ module.validate.field( module.get.validation($field) );
271
+ }
272
+ else if(settings.on == 'blur' || settings.on == 'change') {
273
+ module.validate.field( module.get.validation($field) );
274
+ }
275
+ },
276
+ change: function() {
277
+ var
278
+ $field = $(this),
279
+ $fieldGroup = $field.closest($group)
280
+ ;
281
+ if(settings.on == 'change' || ( $fieldGroup.hasClass(className.error) && settings.revalidate) ) {
282
+ clearTimeout(module.timer);
283
+ module.timer = setTimeout(function() {
284
+ module.debug('Revalidating field', $field, module.get.validation($field));
285
+ module.validate.field( module.get.validation($field) );
286
+ }, settings.delay);
287
+ }
288
+ }
289
+ }
290
+
291
+ },
292
+
293
+ get: {
294
+ changeEvent: function(type) {
295
+ if(type == 'checkbox' || type == 'radio' || type == 'hidden') {
296
+ return 'change';
297
+ }
298
+ else {
299
+ return module.get.inputEvent();
300
+ }
301
+ },
302
+ inputEvent: function() {
303
+ return (document.createElement('input').oninput !== undefined)
304
+ ? 'input'
305
+ : (document.createElement('input').onpropertychange !== undefined)
306
+ ? 'propertychange'
307
+ : 'keyup'
308
+ ;
309
+ },
310
+ field: function(identifier) {
311
+ module.verbose('Finding field with identifier', identifier);
312
+ if( $field.filter('#' + identifier).length > 0 ) {
313
+ return $field.filter('#' + identifier);
314
+ }
315
+ else if( $field.filter('[name="' + identifier +'"]').length > 0 ) {
316
+ return $field.filter('[name="' + identifier +'"]');
317
+ }
318
+ else if( $field.filter('[name="' + identifier +'[]"]').length > 0 ) {
319
+ return $field.filter('[name="' + identifier +'[]"]');
320
+ }
321
+ else if( $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]').length > 0 ) {
322
+ return $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]');
323
+ }
324
+ return $('<input/>');
325
+ },
326
+ fields: function(fields) {
327
+ var
328
+ $fields = $()
329
+ ;
330
+ $.each(fields, function(index, name) {
331
+ $fields = $fields.add( module.get.field(name) );
332
+ });
333
+ return $fields;
334
+ },
335
+ validation: function($field) {
336
+ var
337
+ rules
338
+ ;
339
+ $.each(validation, function(fieldName, field) {
340
+ if( module.get.field(field.identifier).get(0) == $field.get(0) ) {
341
+ rules = field;
342
+ }
343
+ });
344
+ return rules || false;
345
+ },
346
+ value: function (field) {
347
+ var
348
+ fields = [],
349
+ results
350
+ ;
351
+ fields.push(field);
352
+ results = module.get.values.call(element, fields);
353
+ return results[field];
354
+ },
355
+ values: function (fields) {
356
+ var
357
+ $fields = $.isArray(fields)
358
+ ? module.get.fields(fields)
359
+ : $field,
360
+ values = {}
361
+ ;
362
+ $fields.each(function(index, field) {
363
+ var
364
+ $field = $(field),
365
+ type = $field.prop('type'),
366
+ name = $field.prop('name'),
367
+ value = $field.val(),
368
+ isCheckbox = $field.is(selector.checkbox),
369
+ isRadio = $field.is(selector.radio),
370
+ isMultiple = (name.indexOf('[]') !== -1),
371
+ isChecked = (isCheckbox)
372
+ ? $field.is(':checked')
373
+ : false
374
+ ;
375
+ if(name) {
376
+ if(isMultiple) {
377
+ name = name.replace('[]', '');
378
+ if(!values[name]) {
379
+ values[name] = [];
380
+ }
381
+ if(isCheckbox) {
382
+ if(isChecked) {
383
+ values[name].push(value)
384
+ }
385
+ else {
386
+ module.debug('Omitted unchecked checkbox', $field);
387
+ return true;
388
+ }
389
+ }
390
+ else {
391
+ values[name].push(value);
392
+ }
393
+ }
394
+ else {
395
+ if(isRadio) {
396
+ if(isChecked) {
397
+ values[name] = value;
398
+ }
399
+ }
400
+ else if(isCheckbox) {
401
+ if(isChecked) {
402
+ values[name] = true;
403
+ }
404
+ else {
405
+ module.debug('Omitted unchecked checkbox', $field);
406
+ return true;
407
+ }
408
+ }
409
+ else {
410
+ values[name] = value;
411
+ }
412
+ }
413
+ }
414
+ });
415
+ return values;
416
+ }
417
+ },
418
+
419
+ has: {
420
+
421
+ field: function(identifier) {
422
+ module.verbose('Checking for existence of a field with identifier', identifier);
423
+ if( $field.filter('#' + identifier).length > 0 ) {
424
+ return true;
425
+ }
426
+ else if( $field.filter('[name="' + identifier +'"]').length > 0 ) {
427
+ return true;
428
+ }
429
+ else if( $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]').length > 0 ) {
430
+ return true;
431
+ }
432
+ return false;
433
+ }
434
+
435
+ },
436
+
437
+ add: {
438
+ prompt: function(identifier, errors) {
439
+ var
440
+ $field = module.get.field(identifier),
441
+ $fieldGroup = $field.closest($group),
442
+ $prompt = $fieldGroup.children(selector.prompt),
443
+ promptExists = ($prompt.length !== 0)
444
+ ;
445
+ errors = (typeof errors == 'string')
446
+ ? [errors]
447
+ : errors
448
+ ;
449
+ module.verbose('Adding field error state', identifier);
450
+ $fieldGroup
451
+ .addClass(className.error)
452
+ ;
453
+ if(settings.inline) {
454
+ if(!promptExists) {
455
+ $prompt = settings.templates.prompt(errors);
456
+ $prompt
457
+ .appendTo($fieldGroup)
458
+ ;
459
+ }
460
+ $prompt
461
+ .html(errors[0])
462
+ ;
463
+ if(!promptExists) {
464
+ if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
465
+ module.verbose('Displaying error with css transition', settings.transition);
466
+ $prompt.transition(settings.transition + ' in', settings.duration);
467
+ }
468
+ else {
469
+ module.verbose('Displaying error with fallback javascript animation');
470
+ $prompt
471
+ .fadeIn(settings.duration)
472
+ ;
473
+ }
474
+ }
475
+ else {
476
+ module.verbose('Inline errors are disabled, no inline error added', identifier);
477
+ }
478
+ }
479
+ },
480
+ errors: function(errors) {
481
+ module.debug('Adding form error messages', errors);
482
+ $message
483
+ .html( settings.templates.error(errors) )
484
+ ;
485
+ }
486
+ },
487
+
488
+ remove: {
489
+ prompt: function(field) {
490
+ var
491
+ $field = module.get.field(field.identifier),
492
+ $fieldGroup = $field.closest($group),
493
+ $prompt = $fieldGroup.children(selector.prompt)
494
+ ;
495
+ $fieldGroup
496
+ .removeClass(className.error)
497
+ ;
498
+ if(settings.inline && $prompt.is(':visible')) {
499
+ module.verbose('Removing prompt for field', field);
500
+ if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
501
+ $prompt.transition(settings.transition + ' out', settings.duration, function() {
502
+ $prompt.remove();
503
+ });
504
+ }
505
+ else {
506
+ $prompt
507
+ .fadeOut(settings.duration, function(){
508
+ $prompt.remove();
509
+ })
510
+ ;
511
+ }
512
+ }
513
+ }
514
+ },
515
+
516
+ set: {
517
+ success: function() {
518
+ $module
519
+ .removeClass(className.error)
520
+ .addClass(className.success)
521
+ ;
522
+ },
523
+ defaults: function () {
524
+ $field
525
+ .each(function () {
526
+ var
527
+ $field = $(this),
528
+ isCheckbox = ($field.filter(selector.checkbox).length > 0),
529
+ value = (isCheckbox)
530
+ ? $field.is(':checked')
531
+ : $field.val()
532
+ ;
533
+ $field.data(metadata.defaultValue, value);
534
+ })
535
+ ;
536
+ },
537
+ error: function() {
538
+ $module
539
+ .removeClass(className.success)
540
+ .addClass(className.error)
541
+ ;
542
+ },
543
+ value: function (field, value) {
544
+ var
545
+ fields = {}
546
+ ;
547
+ fields[field] = value;
548
+ return module.set.values.call(element, fields);
549
+ },
550
+ values: function (fields) {
551
+ if($.isEmptyObject(fields)) {
552
+ return;
553
+ }
554
+ $.each(fields, function(key, value) {
555
+ var
556
+ $field = module.get.field(key),
557
+ $element = $field.parent(),
558
+ isMultiple = $.isArray(value),
559
+ isCheckbox = $element.is(selector.uiCheckbox),
560
+ isDropdown = $element.is(selector.uiDropdown),
561
+ isRadio = ($field.is(selector.radio) && isCheckbox),
562
+ fieldExists = ($field.length > 0),
563
+ $multipleField
564
+ ;
565
+ if(fieldExists) {
566
+ if(isMultiple && isCheckbox) {
567
+ module.verbose('Selecting multiple', value, $field);
568
+ $element.checkbox('uncheck');
569
+ $.each(value, function(index, value) {
570
+ $multipleField = $field.filter('[value="' + value + '"]');
571
+ $element = $multipleField.parent();
572
+ if($multipleField.length > 0) {
573
+ $element.checkbox('check');
574
+ }
575
+ });
576
+ }
577
+ else if(isRadio) {
578
+ module.verbose('Selecting radio value', value, $field);
579
+ $field.filter('[value="' + value + '"]')
580
+ .parent(selector.uiCheckbox)
581
+ .checkbox('check')
582
+ ;
583
+ }
584
+ else if(isCheckbox) {
585
+ module.verbose('Setting checkbox value', value, $element);
586
+ if(value === true) {
587
+ $element.checkbox('check');
588
+ }
589
+ else {
590
+ $element.checkbox('uncheck');
591
+ }
592
+ }
593
+ else if(isDropdown) {
594
+ module.verbose('Setting dropdown value', value, $element);
595
+ $element.dropdown('set selected', value);
596
+ }
597
+ else {
598
+ module.verbose('Setting field value', value, $field);
599
+ $field.val(value);
600
+ }
601
+ }
602
+ });
603
+ module.validate.form();
604
+ }
605
+ },
606
+
607
+ validate: {
608
+
609
+ form: function(event) {
610
+ var
611
+ allValid = true,
612
+ apiRequest
613
+ ;
614
+
615
+ // input keydown event will fire submit repeatedly by browser default
616
+ if(keyHeldDown) {
617
+ return false;
618
+ }
619
+
620
+ // reset errors
621
+ formErrors = [];
622
+ $.each(validation, function(fieldName, field) {
623
+ if( !( module.validate.field(field) ) ) {
624
+ allValid = false;
625
+ }
626
+ });
627
+ if(allValid) {
628
+ module.debug('Form has no validation errors, submitting');
629
+ module.set.success();
630
+ return settings.onSuccess.call(element, event);
631
+ }
632
+ else {
633
+ module.debug('Form has errors');
634
+ module.set.error();
635
+ if(!settings.inline) {
636
+ module.add.errors(formErrors);
637
+ }
638
+ // prevent ajax submit
639
+ if($module.data('moduleApi') !== undefined) {
640
+ event.stopImmediatePropagation();
641
+ }
642
+ return settings.onFailure.call(element, formErrors);
643
+ }
644
+ },
645
+
646
+ // takes a validation object and returns whether field passes validation
647
+ field: function(field) {
648
+ var
649
+ $field = module.get.field(field.identifier),
650
+ fieldValid = true,
651
+ fieldErrors = []
652
+ ;
653
+ if($field.prop('disabled')) {
654
+ module.debug('Field is disabled. Skipping', field.identifier);
655
+ fieldValid = true;
656
+ }
657
+ else if(field.optional && $.trim($field.val()) === ''){
658
+ module.debug('Field is optional and empty. Skipping', field.identifier);
659
+ fieldValid = true;
660
+ }
661
+ else if(field.rules !== undefined) {
662
+ $.each(field.rules, function(index, rule) {
663
+ if( module.has.field(field.identifier) && !( module.validate.rule(field, rule) ) ) {
664
+ module.debug('Field is invalid', field.identifier, rule.type);
665
+ fieldErrors.push(rule.prompt);
666
+ fieldValid = false;
667
+ }
668
+ });
669
+ }
670
+ if(fieldValid) {
671
+ module.remove.prompt(field, fieldErrors);
672
+ settings.onValid.call($field);
673
+ }
674
+ else {
675
+ formErrors = formErrors.concat(fieldErrors);
676
+ module.add.prompt(field.identifier, fieldErrors);
677
+ settings.onInvalid.call($field, fieldErrors);
678
+ return false;
679
+ }
680
+ return true;
681
+ },
682
+
683
+ // takes validation rule and returns whether field passes rule
684
+ rule: function(field, validation) {
685
+ var
686
+ $field = module.get.field(field.identifier),
687
+ type = validation.type,
688
+ value = $.trim($field.val() + ''),
689
+
690
+ bracketRegExp = /\[(.*)\]/i,
691
+ bracket = bracketRegExp.exec(type),
692
+ isValid = true,
693
+ ancillary,
694
+ functionType
695
+ ;
696
+ // if bracket notation is used, pass in extra parameters
697
+ if(bracket !== undefined && bracket !== null) {
698
+ ancillary = '' + bracket[1];
699
+ functionType = type.replace(bracket[0], '');
700
+ isValid = settings.rules[functionType].call(element, value, ancillary);
701
+ }
702
+ // normal notation
703
+ else {
704
+ isValid = settings.rules[type].call($field, value);
705
+ }
706
+ return isValid;
707
+ }
708
+ },
709
+
710
+ setting: function(name, value) {
711
+ if( $.isPlainObject(name) ) {
712
+ $.extend(true, settings, name);
713
+ }
714
+ else if(value !== undefined) {
715
+ settings[name] = value;
716
+ }
717
+ else {
718
+ return settings[name];
719
+ }
720
+ },
721
+ internal: function(name, value) {
722
+ if( $.isPlainObject(name) ) {
723
+ $.extend(true, module, name);
724
+ }
725
+ else if(value !== undefined) {
726
+ module[name] = value;
727
+ }
728
+ else {
729
+ return module[name];
730
+ }
731
+ },
732
+ debug: function() {
733
+ if(settings.debug) {
734
+ if(settings.performance) {
735
+ module.performance.log(arguments);
736
+ }
737
+ else {
738
+ module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
739
+ module.debug.apply(console, arguments);
740
+ }
741
+ }
742
+ },
743
+ verbose: function() {
744
+ if(settings.verbose && settings.debug) {
745
+ if(settings.performance) {
746
+ module.performance.log(arguments);
747
+ }
748
+ else {
749
+ module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
750
+ module.verbose.apply(console, arguments);
751
+ }
752
+ }
753
+ },
754
+ error: function() {
755
+ module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
756
+ module.error.apply(console, arguments);
757
+ },
758
+ performance: {
759
+ log: function(message) {
760
+ var
761
+ currentTime,
762
+ executionTime,
763
+ previousTime
764
+ ;
765
+ if(settings.performance) {
766
+ currentTime = new Date().getTime();
767
+ previousTime = time || currentTime;
768
+ executionTime = currentTime - previousTime;
769
+ time = currentTime;
770
+ performance.push({
771
+ 'Name' : message[0],
772
+ 'Arguments' : [].slice.call(message, 1) || '',
773
+ 'Element' : element,
774
+ 'Execution Time' : executionTime
775
+ });
776
+ }
777
+ clearTimeout(module.performance.timer);
778
+ module.performance.timer = setTimeout(module.performance.display, 100);
779
+ },
780
+ display: function() {
781
+ var
782
+ title = settings.name + ':',
783
+ totalTime = 0
784
+ ;
785
+ time = false;
786
+ clearTimeout(module.performance.timer);
787
+ $.each(performance, function(index, data) {
788
+ totalTime += data['Execution Time'];
789
+ });
790
+ title += ' ' + totalTime + 'ms';
791
+ if(moduleSelector) {
792
+ title += ' \'' + moduleSelector + '\'';
793
+ }
794
+ if($allModules.length > 1) {
795
+ title += ' ' + '(' + $allModules.length + ')';
796
+ }
797
+ if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
798
+ console.groupCollapsed(title);
799
+ if(console.table) {
800
+ console.table(performance);
801
+ }
802
+ else {
803
+ $.each(performance, function(index, data) {
804
+ console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
805
+ });
806
+ }
807
+ console.groupEnd();
808
+ }
809
+ performance = [];
810
+ }
811
+ },
812
+ invoke: function(query, passedArguments, context) {
813
+ var
814
+ object = instance,
815
+ maxDepth,
816
+ found,
817
+ response
818
+ ;
819
+ passedArguments = passedArguments || queryArguments;
820
+ context = element || context;
821
+ if(typeof query == 'string' && object !== undefined) {
822
+ query = query.split(/[\. ]/);
823
+ maxDepth = query.length - 1;
824
+ $.each(query, function(depth, value) {
825
+ var camelCaseValue = (depth != maxDepth)
826
+ ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
827
+ : query
828
+ ;
829
+ if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
830
+ object = object[camelCaseValue];
831
+ }
832
+ else if( object[camelCaseValue] !== undefined ) {
833
+ found = object[camelCaseValue];
834
+ return false;
835
+ }
836
+ else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
837
+ object = object[value];
838
+ }
839
+ else if( object[value] !== undefined ) {
840
+ found = object[value];
841
+ return false;
842
+ }
843
+ else {
844
+ return false;
845
+ }
846
+ });
847
+ }
848
+ if( $.isFunction( found ) ) {
849
+ response = found.apply(context, passedArguments);
850
+ }
851
+ else if(found !== undefined) {
852
+ response = found;
853
+ }
854
+ if($.isArray(returnedValue)) {
855
+ returnedValue.push(response);
856
+ }
857
+ else if(returnedValue !== undefined) {
858
+ returnedValue = [returnedValue, response];
859
+ }
860
+ else if(response !== undefined) {
861
+ returnedValue = response;
862
+ }
863
+ return found;
864
+ }
865
+ };
866
+ if(methodInvoked) {
867
+ if(instance === undefined) {
868
+ module.initialize();
869
+ }
870
+ module.invoke(query);
871
+ }
872
+ else {
873
+ if(instance !== undefined) {
874
+ instance.invoke('destroy');
875
+ }
876
+ module.initialize();
877
+ }
878
+
879
+ })
880
+ ;
881
+
882
+ return (returnedValue !== undefined)
883
+ ? returnedValue
884
+ : this
885
+ ;
886
+ };
887
+
888
+ $.fn.form.settings = {
889
+
890
+ name : 'Form',
891
+ namespace : 'form',
892
+
893
+ debug : false,
894
+ verbose : true,
895
+ performance : true,
896
+
897
+
898
+ keyboardShortcuts : true,
899
+ on : 'submit',
900
+ inline : false,
901
+
902
+ delay : 200,
903
+ revalidate : true,
904
+
905
+ transition : 'scale',
906
+ duration : 200,
907
+
908
+ onValid : function() {},
909
+ onInvalid : function() {},
910
+ onSuccess : function() { return true; },
911
+ onFailure : function() { return false; },
912
+
913
+ metadata : {
914
+ defaultValue : 'default',
915
+ validate : 'validate'
916
+ },
917
+
918
+ selector : {
919
+ checkbox : 'input[type="checkbox"], input[type="radio"]',
920
+ clear : '.clear',
921
+ field : 'input, textarea, select',
922
+ group : '.field',
923
+ input : 'input',
924
+ message : '.error.message',
925
+ prompt : '.prompt.label',
926
+ radio : 'input[type="radio"]',
927
+ reset : '.reset',
928
+ submit : '.submit',
929
+ uiCheckbox : '.ui.checkbox',
930
+ uiDropdown : '.ui.dropdown'
931
+ },
932
+
933
+ className : {
934
+ error : 'error',
935
+ label : 'ui prompt label',
936
+ pressed : 'down',
937
+ success : 'success'
938
+ },
939
+
940
+ error: {
941
+ method : 'The method you called is not defined.'
942
+ },
943
+
944
+ templates: {
945
+
946
+ // template that produces error message
947
+ error: function(errors) {
948
+ var
949
+ html = '<ul class="list">'
950
+ ;
951
+ $.each(errors, function(index, value) {
952
+ html += '<li>' + value + '</li>';
953
+ });
954
+ html += '</ul>';
955
+ return $(html);
956
+ },
957
+
958
+ // template that produces label
959
+ prompt: function(errors) {
960
+ return $('<div/>')
961
+ .addClass('ui red pointing prompt label')
962
+ .html(errors[0])
963
+ ;
964
+ }
965
+ },
966
+
967
+ rules: {
968
+
969
+ // checkbox checked
970
+ checked: function() {
971
+ return ($(this).filter(':checked').length > 0);
972
+ },
973
+
974
+ // value contains text (insensitive)
975
+ contains: function(value, text) {
976
+ // escape regex characters
977
+ text = text.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
978
+ return (value.search( new RegExp(text, 'i') ) !== -1);
979
+ },
980
+
981
+ // value contains text (case sensitive)
982
+ containsExactly: function(value, text) {
983
+ // escape regex characters
984
+ text = text.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
985
+ return (value.search( new RegExp(text) ) !== -1);
986
+ },
987
+
988
+ // is most likely an email
989
+ email: function(value){
990
+ var
991
+ emailRegExp = new RegExp("[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", "i")
992
+ ;
993
+ return emailRegExp.test(value);
994
+ },
995
+
996
+ // is not empty or blank string
997
+ empty: function(value) {
998
+ return !(value === undefined || '' === value);
999
+ },
1000
+
1001
+ // is valid integer
1002
+ integer: function(value, range) {
1003
+ var
1004
+ intRegExp = /^\-?\d+$/,
1005
+ min,
1006
+ max,
1007
+ parts
1008
+ ;
1009
+ if(range === undefined || range === '' || range === '..') {
1010
+ // do nothing
1011
+ }
1012
+ else if(range.indexOf('..') == -1) {
1013
+ if(intRegExp.test(range)) {
1014
+ min = max = range - 0;
1015
+ }
1016
+ }
1017
+ else {
1018
+ parts = range.split('..', 2);
1019
+ if(intRegExp.test(parts[0])) {
1020
+ min = parts[0] - 0;
1021
+ }
1022
+ if(intRegExp.test(parts[1])) {
1023
+ max = parts[1] - 0;
1024
+ }
1025
+ }
1026
+ return (
1027
+ intRegExp.test(value) &&
1028
+ (min === undefined || value >= min) &&
1029
+ (max === undefined || value <= max)
1030
+ );
1031
+ },
1032
+
1033
+ // is value (case insensitive)
1034
+ is: function(value, text) {
1035
+ text = (typeof text == 'string')
1036
+ ? text.toLowerCase()
1037
+ : text
1038
+ ;
1039
+ value = (typeof value == 'string')
1040
+ ? value.toLowerCase()
1041
+ : value
1042
+ ;
1043
+ return (value == text);
1044
+ },
1045
+
1046
+ // is value
1047
+ isExactly: function(value, text) {
1048
+ return (value == text);
1049
+ },
1050
+
1051
+ // is at least string length
1052
+ length: function(value, requiredLength) {
1053
+ return (value !== undefined)
1054
+ ? (value.length >= requiredLength)
1055
+ : false
1056
+ ;
1057
+ },
1058
+
1059
+ // matches another field
1060
+ match: function(value, fieldIdentifier) {
1061
+ // use either id or name of field
1062
+ var
1063
+ $form = $(this),
1064
+ matchingValue
1065
+ ;
1066
+ if($form.find('#' + fieldIdentifier).length > 0) {
1067
+ matchingValue = $form.find('#' + fieldIdentifier).val();
1068
+ }
1069
+ else if($form.find('[name="' + fieldIdentifier +'"]').length > 0) {
1070
+ matchingValue = $form.find('[name="' + fieldIdentifier + '"]').val();
1071
+ }
1072
+ else if( $form.find('[data-validate="'+ fieldIdentifier +'"]').length > 0 ) {
1073
+ matchingValue = $form.find('[data-validate="'+ fieldIdentifier +'"]').val();
1074
+ }
1075
+ return (matchingValue !== undefined)
1076
+ ? ( value.toString() == matchingValue.toString() )
1077
+ : false
1078
+ ;
1079
+ },
1080
+
1081
+ // string length is less than max length
1082
+ maxLength: function(value, maxLength) {
1083
+ return (value !== undefined)
1084
+ ? (value.length <= maxLength)
1085
+ : false
1086
+ ;
1087
+ },
1088
+
1089
+ // value is not value (case insensitive)
1090
+ not: function(value, notValue) {
1091
+ value = (typeof value == 'string')
1092
+ ? value.toLowerCase()
1093
+ : value
1094
+ ;
1095
+ notValue = (typeof notValue == 'string')
1096
+ ? notValue.toLowerCase()
1097
+ : notValue
1098
+ ;
1099
+ return (value != notValue);
1100
+ },
1101
+
1102
+ // value is not value (case sensitive)
1103
+ notExactly: function(value, notValue) {
1104
+ return (value != notValue);
1105
+ },
1106
+
1107
+ // value is most likely url
1108
+ url: function(value) {
1109
+ var
1110
+ urlRegExp = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/
1111
+ ;
1112
+ return urlRegExp.test(value);
1113
+ }
1114
+ }
1115
+
1116
+ };
1117
+
1118
+ })( jQuery, window , document );