Use Semantic UI for all HTML templates
[cacert-boardvoting.git] / static / semantic.js
1 /*
2 * # Semantic UI - 2.2.10
3 * https://github.com/Semantic-Org/Semantic-UI
4 * http://www.semantic-ui.com/
5 *
6 * Copyright 2014 Contributors
7 * Released under the MIT license
8 * http://opensource.org/licenses/MIT
9 *
10 */
11 /*!
12 * # Semantic UI 2.2.10 - Site
13 * http://github.com/semantic-org/semantic-ui/
14 *
15 *
16 * Released under the MIT license
17 * http://opensource.org/licenses/MIT
18 *
19 */
20
21 ;(function ($, window, document, undefined) {
22
23 $.site = $.fn.site = function(parameters) {
24 var
25 time = new Date().getTime(),
26 performance = [],
27
28 query = arguments[0],
29 methodInvoked = (typeof query == 'string'),
30 queryArguments = [].slice.call(arguments, 1),
31
32 settings = ( $.isPlainObject(parameters) )
33 ? $.extend(true, {}, $.site.settings, parameters)
34 : $.extend({}, $.site.settings),
35
36 namespace = settings.namespace,
37 error = settings.error,
38
39 eventNamespace = '.' + namespace,
40 moduleNamespace = 'module-' + namespace,
41
42 $document = $(document),
43 $module = $document,
44 element = this,
45 instance = $module.data(moduleNamespace),
46
47 module,
48 returnedValue
49 ;
50 module = {
51
52 initialize: function() {
53 module.instantiate();
54 },
55
56 instantiate: function() {
57 module.verbose('Storing instance of site', module);
58 instance = module;
59 $module
60 .data(moduleNamespace, module)
61 ;
62 },
63
64 normalize: function() {
65 module.fix.console();
66 module.fix.requestAnimationFrame();
67 },
68
69 fix: {
70 console: function() {
71 module.debug('Normalizing window.console');
72 if (console === undefined || console.log === undefined) {
73 module.verbose('Console not available, normalizing events');
74 module.disable.console();
75 }
76 if (typeof console.group == 'undefined' || typeof console.groupEnd == 'undefined' || typeof console.groupCollapsed == 'undefined') {
77 module.verbose('Console group not available, normalizing events');
78 window.console.group = function() {};
79 window.console.groupEnd = function() {};
80 window.console.groupCollapsed = function() {};
81 }
82 if (typeof console.markTimeline == 'undefined') {
83 module.verbose('Mark timeline not available, normalizing events');
84 window.console.markTimeline = function() {};
85 }
86 },
87 consoleClear: function() {
88 module.debug('Disabling programmatic console clearing');
89 window.console.clear = function() {};
90 },
91 requestAnimationFrame: function() {
92 module.debug('Normalizing requestAnimationFrame');
93 if(window.requestAnimationFrame === undefined) {
94 module.debug('RequestAnimationFrame not available, normalizing event');
95 window.requestAnimationFrame = window.requestAnimationFrame
96 || window.mozRequestAnimationFrame
97 || window.webkitRequestAnimationFrame
98 || window.msRequestAnimationFrame
99 || function(callback) { setTimeout(callback, 0); }
100 ;
101 }
102 }
103 },
104
105 moduleExists: function(name) {
106 return ($.fn[name] !== undefined && $.fn[name].settings !== undefined);
107 },
108
109 enabled: {
110 modules: function(modules) {
111 var
112 enabledModules = []
113 ;
114 modules = modules || settings.modules;
115 $.each(modules, function(index, name) {
116 if(module.moduleExists(name)) {
117 enabledModules.push(name);
118 }
119 });
120 return enabledModules;
121 }
122 },
123
124 disabled: {
125 modules: function(modules) {
126 var
127 disabledModules = []
128 ;
129 modules = modules || settings.modules;
130 $.each(modules, function(index, name) {
131 if(!module.moduleExists(name)) {
132 disabledModules.push(name);
133 }
134 });
135 return disabledModules;
136 }
137 },
138
139 change: {
140 setting: function(setting, value, modules, modifyExisting) {
141 modules = (typeof modules === 'string')
142 ? (modules === 'all')
143 ? settings.modules
144 : [modules]
145 : modules || settings.modules
146 ;
147 modifyExisting = (modifyExisting !== undefined)
148 ? modifyExisting
149 : true
150 ;
151 $.each(modules, function(index, name) {
152 var
153 namespace = (module.moduleExists(name))
154 ? $.fn[name].settings.namespace || false
155 : true,
156 $existingModules
157 ;
158 if(module.moduleExists(name)) {
159 module.verbose('Changing default setting', setting, value, name);
160 $.fn[name].settings[setting] = value;
161 if(modifyExisting && namespace) {
162 $existingModules = $(':data(module-' + namespace + ')');
163 if($existingModules.length > 0) {
164 module.verbose('Modifying existing settings', $existingModules);
165 $existingModules[name]('setting', setting, value);
166 }
167 }
168 }
169 });
170 },
171 settings: function(newSettings, modules, modifyExisting) {
172 modules = (typeof modules === 'string')
173 ? [modules]
174 : modules || settings.modules
175 ;
176 modifyExisting = (modifyExisting !== undefined)
177 ? modifyExisting
178 : true
179 ;
180 $.each(modules, function(index, name) {
181 var
182 $existingModules
183 ;
184 if(module.moduleExists(name)) {
185 module.verbose('Changing default setting', newSettings, name);
186 $.extend(true, $.fn[name].settings, newSettings);
187 if(modifyExisting && namespace) {
188 $existingModules = $(':data(module-' + namespace + ')');
189 if($existingModules.length > 0) {
190 module.verbose('Modifying existing settings', $existingModules);
191 $existingModules[name]('setting', newSettings);
192 }
193 }
194 }
195 });
196 }
197 },
198
199 enable: {
200 console: function() {
201 module.console(true);
202 },
203 debug: function(modules, modifyExisting) {
204 modules = modules || settings.modules;
205 module.debug('Enabling debug for modules', modules);
206 module.change.setting('debug', true, modules, modifyExisting);
207 },
208 verbose: function(modules, modifyExisting) {
209 modules = modules || settings.modules;
210 module.debug('Enabling verbose debug for modules', modules);
211 module.change.setting('verbose', true, modules, modifyExisting);
212 }
213 },
214 disable: {
215 console: function() {
216 module.console(false);
217 },
218 debug: function(modules, modifyExisting) {
219 modules = modules || settings.modules;
220 module.debug('Disabling debug for modules', modules);
221 module.change.setting('debug', false, modules, modifyExisting);
222 },
223 verbose: function(modules, modifyExisting) {
224 modules = modules || settings.modules;
225 module.debug('Disabling verbose debug for modules', modules);
226 module.change.setting('verbose', false, modules, modifyExisting);
227 }
228 },
229
230 console: function(enable) {
231 if(enable) {
232 if(instance.cache.console === undefined) {
233 module.error(error.console);
234 return;
235 }
236 module.debug('Restoring console function');
237 window.console = instance.cache.console;
238 }
239 else {
240 module.debug('Disabling console function');
241 instance.cache.console = window.console;
242 window.console = {
243 clear : function(){},
244 error : function(){},
245 group : function(){},
246 groupCollapsed : function(){},
247 groupEnd : function(){},
248 info : function(){},
249 log : function(){},
250 markTimeline : function(){},
251 warn : function(){}
252 };
253 }
254 },
255
256 destroy: function() {
257 module.verbose('Destroying previous site for', $module);
258 $module
259 .removeData(moduleNamespace)
260 ;
261 },
262
263 cache: {},
264
265 setting: function(name, value) {
266 if( $.isPlainObject(name) ) {
267 $.extend(true, settings, name);
268 }
269 else if(value !== undefined) {
270 settings[name] = value;
271 }
272 else {
273 return settings[name];
274 }
275 },
276 internal: function(name, value) {
277 if( $.isPlainObject(name) ) {
278 $.extend(true, module, name);
279 }
280 else if(value !== undefined) {
281 module[name] = value;
282 }
283 else {
284 return module[name];
285 }
286 },
287 debug: function() {
288 if(settings.debug) {
289 if(settings.performance) {
290 module.performance.log(arguments);
291 }
292 else {
293 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
294 module.debug.apply(console, arguments);
295 }
296 }
297 },
298 verbose: function() {
299 if(settings.verbose && settings.debug) {
300 if(settings.performance) {
301 module.performance.log(arguments);
302 }
303 else {
304 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
305 module.verbose.apply(console, arguments);
306 }
307 }
308 },
309 error: function() {
310 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
311 module.error.apply(console, arguments);
312 },
313 performance: {
314 log: function(message) {
315 var
316 currentTime,
317 executionTime,
318 previousTime
319 ;
320 if(settings.performance) {
321 currentTime = new Date().getTime();
322 previousTime = time || currentTime;
323 executionTime = currentTime - previousTime;
324 time = currentTime;
325 performance.push({
326 'Element' : element,
327 'Name' : message[0],
328 'Arguments' : [].slice.call(message, 1) || '',
329 'Execution Time' : executionTime
330 });
331 }
332 clearTimeout(module.performance.timer);
333 module.performance.timer = setTimeout(module.performance.display, 500);
334 },
335 display: function() {
336 var
337 title = settings.name + ':',
338 totalTime = 0
339 ;
340 time = false;
341 clearTimeout(module.performance.timer);
342 $.each(performance, function(index, data) {
343 totalTime += data['Execution Time'];
344 });
345 title += ' ' + totalTime + 'ms';
346 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
347 console.groupCollapsed(title);
348 if(console.table) {
349 console.table(performance);
350 }
351 else {
352 $.each(performance, function(index, data) {
353 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
354 });
355 }
356 console.groupEnd();
357 }
358 performance = [];
359 }
360 },
361 invoke: function(query, passedArguments, context) {
362 var
363 object = instance,
364 maxDepth,
365 found,
366 response
367 ;
368 passedArguments = passedArguments || queryArguments;
369 context = element || context;
370 if(typeof query == 'string' && object !== undefined) {
371 query = query.split(/[\. ]/);
372 maxDepth = query.length - 1;
373 $.each(query, function(depth, value) {
374 var camelCaseValue = (depth != maxDepth)
375 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
376 : query
377 ;
378 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
379 object = object[camelCaseValue];
380 }
381 else if( object[camelCaseValue] !== undefined ) {
382 found = object[camelCaseValue];
383 return false;
384 }
385 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
386 object = object[value];
387 }
388 else if( object[value] !== undefined ) {
389 found = object[value];
390 return false;
391 }
392 else {
393 module.error(error.method, query);
394 return false;
395 }
396 });
397 }
398 if ( $.isFunction( found ) ) {
399 response = found.apply(context, passedArguments);
400 }
401 else if(found !== undefined) {
402 response = found;
403 }
404 if($.isArray(returnedValue)) {
405 returnedValue.push(response);
406 }
407 else if(returnedValue !== undefined) {
408 returnedValue = [returnedValue, response];
409 }
410 else if(response !== undefined) {
411 returnedValue = response;
412 }
413 return found;
414 }
415 };
416
417 if(methodInvoked) {
418 if(instance === undefined) {
419 module.initialize();
420 }
421 module.invoke(query);
422 }
423 else {
424 if(instance !== undefined) {
425 module.destroy();
426 }
427 module.initialize();
428 }
429 return (returnedValue !== undefined)
430 ? returnedValue
431 : this
432 ;
433 };
434
435 $.site.settings = {
436
437 name : 'Site',
438 namespace : 'site',
439
440 error : {
441 console : 'Console cannot be restored, most likely it was overwritten outside of module',
442 method : 'The method you called is not defined.'
443 },
444
445 debug : false,
446 verbose : false,
447 performance : true,
448
449 modules: [
450 'accordion',
451 'api',
452 'checkbox',
453 'dimmer',
454 'dropdown',
455 'embed',
456 'form',
457 'modal',
458 'nag',
459 'popup',
460 'rating',
461 'shape',
462 'sidebar',
463 'state',
464 'sticky',
465 'tab',
466 'transition',
467 'visit',
468 'visibility'
469 ],
470
471 siteNamespace : 'site',
472 namespaceStub : {
473 cache : {},
474 config : {},
475 sections : {},
476 section : {},
477 utilities : {}
478 }
479
480 };
481
482 // allows for selection of elements with data attributes
483 $.extend($.expr[ ":" ], {
484 data: ($.expr.createPseudo)
485 ? $.expr.createPseudo(function(dataName) {
486 return function(elem) {
487 return !!$.data(elem, dataName);
488 };
489 })
490 : function(elem, i, match) {
491 // support: jQuery < 1.8
492 return !!$.data(elem, match[ 3 ]);
493 }
494 });
495
496
497 })( jQuery, window, document );
498
499 /*!
500 * # Semantic UI 2.2.10 - Form Validation
501 * http://github.com/semantic-org/semantic-ui/
502 *
503 *
504 * Released under the MIT license
505 * http://opensource.org/licenses/MIT
506 *
507 */
508
509 ;(function ($, window, document, undefined) {
510
511 "use strict";
512
513 window = (typeof window != 'undefined' && window.Math == Math)
514 ? window
515 : (typeof self != 'undefined' && self.Math == Math)
516 ? self
517 : Function('return this')()
518 ;
519
520 $.fn.form = function(parameters) {
521 var
522 $allModules = $(this),
523 moduleSelector = $allModules.selector || '',
524
525 time = new Date().getTime(),
526 performance = [],
527
528 query = arguments[0],
529 legacyParameters = arguments[1],
530 methodInvoked = (typeof query == 'string'),
531 queryArguments = [].slice.call(arguments, 1),
532 returnedValue
533 ;
534 $allModules
535 .each(function() {
536 var
537 $module = $(this),
538 element = this,
539
540 formErrors = [],
541 keyHeldDown = false,
542
543 // set at run-time
544 $field,
545 $group,
546 $message,
547 $prompt,
548 $submit,
549 $clear,
550 $reset,
551
552 settings,
553 validation,
554
555 metadata,
556 selector,
557 className,
558 regExp,
559 error,
560
561 namespace,
562 moduleNamespace,
563 eventNamespace,
564
565 instance,
566 module
567 ;
568
569 module = {
570
571 initialize: function() {
572
573 // settings grabbed at run time
574 module.get.settings();
575 if(methodInvoked) {
576 if(instance === undefined) {
577 module.instantiate();
578 }
579 module.invoke(query);
580 }
581 else {
582 if(instance !== undefined) {
583 instance.invoke('destroy');
584 }
585 module.verbose('Initializing form validation', $module, settings);
586 module.bindEvents();
587 module.set.defaults();
588 module.instantiate();
589 }
590 },
591
592 instantiate: function() {
593 module.verbose('Storing instance of module', module);
594 instance = module;
595 $module
596 .data(moduleNamespace, module)
597 ;
598 },
599
600 destroy: function() {
601 module.verbose('Destroying previous module', instance);
602 module.removeEvents();
603 $module
604 .removeData(moduleNamespace)
605 ;
606 },
607
608 refresh: function() {
609 module.verbose('Refreshing selector cache');
610 $field = $module.find(selector.field);
611 $group = $module.find(selector.group);
612 $message = $module.find(selector.message);
613 $prompt = $module.find(selector.prompt);
614
615 $submit = $module.find(selector.submit);
616 $clear = $module.find(selector.clear);
617 $reset = $module.find(selector.reset);
618 },
619
620 submit: function() {
621 module.verbose('Submitting form', $module);
622 $module
623 .submit()
624 ;
625 },
626
627 attachEvents: function(selector, action) {
628 action = action || 'submit';
629 $(selector)
630 .on('click' + eventNamespace, function(event) {
631 module[action]();
632 event.preventDefault();
633 })
634 ;
635 },
636
637 bindEvents: function() {
638 module.verbose('Attaching form events');
639 $module
640 .on('submit' + eventNamespace, module.validate.form)
641 .on('blur' + eventNamespace, selector.field, module.event.field.blur)
642 .on('click' + eventNamespace, selector.submit, module.submit)
643 .on('click' + eventNamespace, selector.reset, module.reset)
644 .on('click' + eventNamespace, selector.clear, module.clear)
645 ;
646 if(settings.keyboardShortcuts) {
647 $module
648 .on('keydown' + eventNamespace, selector.field, module.event.field.keydown)
649 ;
650 }
651 $field
652 .each(function() {
653 var
654 $input = $(this),
655 type = $input.prop('type'),
656 inputEvent = module.get.changeEvent(type, $input)
657 ;
658 $(this)
659 .on(inputEvent + eventNamespace, module.event.field.change)
660 ;
661 })
662 ;
663 },
664
665 clear: function() {
666 $field
667 .each(function () {
668 var
669 $field = $(this),
670 $element = $field.parent(),
671 $fieldGroup = $field.closest($group),
672 $prompt = $fieldGroup.find(selector.prompt),
673 defaultValue = $field.data(metadata.defaultValue) || '',
674 isCheckbox = $element.is(selector.uiCheckbox),
675 isDropdown = $element.is(selector.uiDropdown),
676 isErrored = $fieldGroup.hasClass(className.error)
677 ;
678 if(isErrored) {
679 module.verbose('Resetting error on field', $fieldGroup);
680 $fieldGroup.removeClass(className.error);
681 $prompt.remove();
682 }
683 if(isDropdown) {
684 module.verbose('Resetting dropdown value', $element, defaultValue);
685 $element.dropdown('clear');
686 }
687 else if(isCheckbox) {
688 $field.prop('checked', false);
689 }
690 else {
691 module.verbose('Resetting field value', $field, defaultValue);
692 $field.val('');
693 }
694 })
695 ;
696 },
697
698 reset: function() {
699 $field
700 .each(function () {
701 var
702 $field = $(this),
703 $element = $field.parent(),
704 $fieldGroup = $field.closest($group),
705 $prompt = $fieldGroup.find(selector.prompt),
706 defaultValue = $field.data(metadata.defaultValue),
707 isCheckbox = $element.is(selector.uiCheckbox),
708 isDropdown = $element.is(selector.uiDropdown),
709 isErrored = $fieldGroup.hasClass(className.error)
710 ;
711 if(defaultValue === undefined) {
712 return;
713 }
714 if(isErrored) {
715 module.verbose('Resetting error on field', $fieldGroup);
716 $fieldGroup.removeClass(className.error);
717 $prompt.remove();
718 }
719 if(isDropdown) {
720 module.verbose('Resetting dropdown value', $element, defaultValue);
721 $element.dropdown('restore defaults');
722 }
723 else if(isCheckbox) {
724 module.verbose('Resetting checkbox value', $element, defaultValue);
725 $field.prop('checked', defaultValue);
726 }
727 else {
728 module.verbose('Resetting field value', $field, defaultValue);
729 $field.val(defaultValue);
730 }
731 })
732 ;
733 },
734
735 determine: {
736 isValid: function() {
737 var
738 allValid = true
739 ;
740 $.each(validation, function(fieldName, field) {
741 if( !( module.validate.field(field, fieldName, true) ) ) {
742 allValid = false;
743 }
744 });
745 return allValid;
746 }
747 },
748
749 is: {
750 bracketedRule: function(rule) {
751 return (rule.type && rule.type.match(settings.regExp.bracket));
752 },
753 empty: function($field) {
754 if(!$field || $field.length === 0) {
755 return true;
756 }
757 else if($field.is('input[type="checkbox"]')) {
758 return !$field.is(':checked');
759 }
760 else {
761 return module.is.blank($field);
762 }
763 },
764 blank: function($field) {
765 return $.trim($field.val()) === '';
766 },
767 valid: function(field) {
768 var
769 allValid = true
770 ;
771 if(field) {
772 module.verbose('Checking if field is valid', field);
773 return module.validate.field(validation[field], field, false);
774 }
775 else {
776 module.verbose('Checking if form is valid');
777 $.each(validation, function(fieldName, field) {
778 if( !module.is.valid(fieldName) ) {
779 allValid = false;
780 }
781 });
782 return allValid;
783 }
784 }
785 },
786
787 removeEvents: function() {
788 $module
789 .off(eventNamespace)
790 ;
791 $field
792 .off(eventNamespace)
793 ;
794 $submit
795 .off(eventNamespace)
796 ;
797 $field
798 .off(eventNamespace)
799 ;
800 },
801
802 event: {
803 field: {
804 keydown: function(event) {
805 var
806 $field = $(this),
807 key = event.which,
808 isInput = $field.is(selector.input),
809 isCheckbox = $field.is(selector.checkbox),
810 isInDropdown = ($field.closest(selector.uiDropdown).length > 0),
811 keyCode = {
812 enter : 13,
813 escape : 27
814 }
815 ;
816 if( key == keyCode.escape) {
817 module.verbose('Escape key pressed blurring field');
818 $field
819 .blur()
820 ;
821 }
822 if(!event.ctrlKey && key == keyCode.enter && isInput && !isInDropdown && !isCheckbox) {
823 if(!keyHeldDown) {
824 $field
825 .one('keyup' + eventNamespace, module.event.field.keyup)
826 ;
827 module.submit();
828 module.debug('Enter pressed on input submitting form');
829 }
830 keyHeldDown = true;
831 }
832 },
833 keyup: function() {
834 keyHeldDown = false;
835 },
836 blur: function(event) {
837 var
838 $field = $(this),
839 $fieldGroup = $field.closest($group),
840 validationRules = module.get.validation($field)
841 ;
842 if( $fieldGroup.hasClass(className.error) ) {
843 module.debug('Revalidating field', $field, validationRules);
844 if(validationRules) {
845 module.validate.field( validationRules );
846 }
847 }
848 else if(settings.on == 'blur' || settings.on == 'change') {
849 if(validationRules) {
850 module.validate.field( validationRules );
851 }
852 }
853 },
854 change: function(event) {
855 var
856 $field = $(this),
857 $fieldGroup = $field.closest($group),
858 validationRules = module.get.validation($field)
859 ;
860 if(validationRules && (settings.on == 'change' || ( $fieldGroup.hasClass(className.error) && settings.revalidate) )) {
861 clearTimeout(module.timer);
862 module.timer = setTimeout(function() {
863 module.debug('Revalidating field', $field, module.get.validation($field));
864 module.validate.field( validationRules );
865 }, settings.delay);
866 }
867 }
868 }
869
870 },
871
872 get: {
873 ancillaryValue: function(rule) {
874 if(!rule.type || (!rule.value && !module.is.bracketedRule(rule))) {
875 return false;
876 }
877 return (rule.value !== undefined)
878 ? rule.value
879 : rule.type.match(settings.regExp.bracket)[1] + ''
880 ;
881 },
882 ruleName: function(rule) {
883 if( module.is.bracketedRule(rule) ) {
884 return rule.type.replace(rule.type.match(settings.regExp.bracket)[0], '');
885 }
886 return rule.type;
887 },
888 changeEvent: function(type, $input) {
889 if(type == 'checkbox' || type == 'radio' || type == 'hidden' || $input.is('select')) {
890 return 'change';
891 }
892 else {
893 return module.get.inputEvent();
894 }
895 },
896 inputEvent: function() {
897 return (document.createElement('input').oninput !== undefined)
898 ? 'input'
899 : (document.createElement('input').onpropertychange !== undefined)
900 ? 'propertychange'
901 : 'keyup'
902 ;
903 },
904 prompt: function(rule, field) {
905 var
906 ruleName = module.get.ruleName(rule),
907 ancillary = module.get.ancillaryValue(rule),
908 prompt = rule.prompt || settings.prompt[ruleName] || settings.text.unspecifiedRule,
909 requiresValue = (prompt.search('{value}') !== -1),
910 requiresName = (prompt.search('{name}') !== -1),
911 $label,
912 $field,
913 name
914 ;
915 if(requiresName || requiresValue) {
916 $field = module.get.field(field.identifier);
917 }
918 if(requiresValue) {
919 prompt = prompt.replace('{value}', $field.val());
920 }
921 if(requiresName) {
922 $label = $field.closest(selector.group).find('label').eq(0);
923 name = ($label.length == 1)
924 ? $label.text()
925 : $field.prop('placeholder') || settings.text.unspecifiedField
926 ;
927 prompt = prompt.replace('{name}', name);
928 }
929 prompt = prompt.replace('{identifier}', field.identifier);
930 prompt = prompt.replace('{ruleValue}', ancillary);
931 if(!rule.prompt) {
932 module.verbose('Using default validation prompt for type', prompt, ruleName);
933 }
934 return prompt;
935 },
936 settings: function() {
937 if($.isPlainObject(parameters)) {
938 var
939 keys = Object.keys(parameters),
940 isLegacySettings = (keys.length > 0)
941 ? (parameters[keys[0]].identifier !== undefined && parameters[keys[0]].rules !== undefined)
942 : false,
943 ruleKeys
944 ;
945 if(isLegacySettings) {
946 // 1.x (ducktyped)
947 settings = $.extend(true, {}, $.fn.form.settings, legacyParameters);
948 validation = $.extend({}, $.fn.form.settings.defaults, parameters);
949 module.error(settings.error.oldSyntax, element);
950 module.verbose('Extending settings from legacy parameters', validation, settings);
951 }
952 else {
953 // 2.x
954 if(parameters.fields) {
955 ruleKeys = Object.keys(parameters.fields);
956 if( typeof parameters.fields[ruleKeys[0]] == 'string' || $.isArray(parameters.fields[ruleKeys[0]]) ) {
957 $.each(parameters.fields, function(name, rules) {
958 if(typeof rules == 'string') {
959 rules = [rules];
960 }
961 parameters.fields[name] = {
962 rules: []
963 };
964 $.each(rules, function(index, rule) {
965 parameters.fields[name].rules.push({ type: rule });
966 });
967 });
968 }
969 }
970
971 settings = $.extend(true, {}, $.fn.form.settings, parameters);
972 validation = $.extend({}, $.fn.form.settings.defaults, settings.fields);
973 module.verbose('Extending settings', validation, settings);
974 }
975 }
976 else {
977 settings = $.fn.form.settings;
978 validation = $.fn.form.settings.defaults;
979 module.verbose('Using default form validation', validation, settings);
980 }
981
982 // shorthand
983 namespace = settings.namespace;
984 metadata = settings.metadata;
985 selector = settings.selector;
986 className = settings.className;
987 regExp = settings.regExp;
988 error = settings.error;
989 moduleNamespace = 'module-' + namespace;
990 eventNamespace = '.' + namespace;
991
992 // grab instance
993 instance = $module.data(moduleNamespace);
994
995 // refresh selector cache
996 module.refresh();
997 },
998 field: function(identifier) {
999 module.verbose('Finding field with identifier', identifier);
1000 identifier = module.escape.string(identifier);
1001 if($field.filter('#' + identifier).length > 0 ) {
1002 return $field.filter('#' + identifier);
1003 }
1004 else if( $field.filter('[name="' + identifier +'"]').length > 0 ) {
1005 return $field.filter('[name="' + identifier +'"]');
1006 }
1007 else if( $field.filter('[name="' + identifier +'[]"]').length > 0 ) {
1008 return $field.filter('[name="' + identifier +'[]"]');
1009 }
1010 else if( $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]').length > 0 ) {
1011 return $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]');
1012 }
1013 return $('<input/>');
1014 },
1015 fields: function(fields) {
1016 var
1017 $fields = $()
1018 ;
1019 $.each(fields, function(index, name) {
1020 $fields = $fields.add( module.get.field(name) );
1021 });
1022 return $fields;
1023 },
1024 validation: function($field) {
1025 var
1026 fieldValidation,
1027 identifier
1028 ;
1029 if(!validation) {
1030 return false;
1031 }
1032 $.each(validation, function(fieldName, field) {
1033 identifier = field.identifier || fieldName;
1034 if( module.get.field(identifier)[0] == $field[0] ) {
1035 field.identifier = identifier;
1036 fieldValidation = field;
1037 }
1038 });
1039 return fieldValidation || false;
1040 },
1041 value: function (field) {
1042 var
1043 fields = [],
1044 results
1045 ;
1046 fields.push(field);
1047 results = module.get.values.call(element, fields);
1048 return results[field];
1049 },
1050 values: function (fields) {
1051 var
1052 $fields = $.isArray(fields)
1053 ? module.get.fields(fields)
1054 : $field,
1055 values = {}
1056 ;
1057 $fields.each(function(index, field) {
1058 var
1059 $field = $(field),
1060 type = $field.prop('type'),
1061 name = $field.prop('name'),
1062 value = $field.val(),
1063 isCheckbox = $field.is(selector.checkbox),
1064 isRadio = $field.is(selector.radio),
1065 isMultiple = (name.indexOf('[]') !== -1),
1066 isChecked = (isCheckbox)
1067 ? $field.is(':checked')
1068 : false
1069 ;
1070 if(name) {
1071 if(isMultiple) {
1072 name = name.replace('[]', '');
1073 if(!values[name]) {
1074 values[name] = [];
1075 }
1076 if(isCheckbox) {
1077 if(isChecked) {
1078 values[name].push(value || true);
1079 }
1080 else {
1081 values[name].push(false);
1082 }
1083 }
1084 else {
1085 values[name].push(value);
1086 }
1087 }
1088 else {
1089 if(isRadio) {
1090 if(isChecked) {
1091 values[name] = value;
1092 }
1093 }
1094 else if(isCheckbox) {
1095 if(isChecked) {
1096 values[name] = value || true;
1097 }
1098 else {
1099 values[name] = false;
1100 }
1101 }
1102 else {
1103 values[name] = value;
1104 }
1105 }
1106 }
1107 });
1108 return values;
1109 }
1110 },
1111
1112 has: {
1113
1114 field: function(identifier) {
1115 module.verbose('Checking for existence of a field with identifier', identifier);
1116 identifier = module.escape.string(identifier);
1117 if(typeof identifier !== 'string') {
1118 module.error(error.identifier, identifier);
1119 }
1120 if($field.filter('#' + identifier).length > 0 ) {
1121 return true;
1122 }
1123 else if( $field.filter('[name="' + identifier +'"]').length > 0 ) {
1124 return true;
1125 }
1126 else if( $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]').length > 0 ) {
1127 return true;
1128 }
1129 return false;
1130 }
1131
1132 },
1133
1134 escape: {
1135 string: function(text) {
1136 text = String(text);
1137 return text.replace(regExp.escape, '\\$&');
1138 }
1139 },
1140
1141 add: {
1142 prompt: function(identifier, errors) {
1143 var
1144 $field = module.get.field(identifier),
1145 $fieldGroup = $field.closest($group),
1146 $prompt = $fieldGroup.children(selector.prompt),
1147 promptExists = ($prompt.length !== 0)
1148 ;
1149 errors = (typeof errors == 'string')
1150 ? [errors]
1151 : errors
1152 ;
1153 module.verbose('Adding field error state', identifier);
1154 $fieldGroup
1155 .addClass(className.error)
1156 ;
1157 if(settings.inline) {
1158 if(!promptExists) {
1159 $prompt = settings.templates.prompt(errors);
1160 $prompt
1161 .appendTo($fieldGroup)
1162 ;
1163 }
1164 $prompt
1165 .html(errors[0])
1166 ;
1167 if(!promptExists) {
1168 if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
1169 module.verbose('Displaying error with css transition', settings.transition);
1170 $prompt.transition(settings.transition + ' in', settings.duration);
1171 }
1172 else {
1173 module.verbose('Displaying error with fallback javascript animation');
1174 $prompt
1175 .fadeIn(settings.duration)
1176 ;
1177 }
1178 }
1179 else {
1180 module.verbose('Inline errors are disabled, no inline error added', identifier);
1181 }
1182 }
1183 },
1184 errors: function(errors) {
1185 module.debug('Adding form error messages', errors);
1186 module.set.error();
1187 $message
1188 .html( settings.templates.error(errors) )
1189 ;
1190 }
1191 },
1192
1193 remove: {
1194 prompt: function(identifier) {
1195 var
1196 $field = module.get.field(identifier),
1197 $fieldGroup = $field.closest($group),
1198 $prompt = $fieldGroup.children(selector.prompt)
1199 ;
1200 $fieldGroup
1201 .removeClass(className.error)
1202 ;
1203 if(settings.inline && $prompt.is(':visible')) {
1204 module.verbose('Removing prompt for field', identifier);
1205 if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
1206 $prompt.transition(settings.transition + ' out', settings.duration, function() {
1207 $prompt.remove();
1208 });
1209 }
1210 else {
1211 $prompt
1212 .fadeOut(settings.duration, function(){
1213 $prompt.remove();
1214 })
1215 ;
1216 }
1217 }
1218 }
1219 },
1220
1221 set: {
1222 success: function() {
1223 $module
1224 .removeClass(className.error)
1225 .addClass(className.success)
1226 ;
1227 },
1228 defaults: function () {
1229 $field
1230 .each(function () {
1231 var
1232 $field = $(this),
1233 isCheckbox = ($field.filter(selector.checkbox).length > 0),
1234 value = (isCheckbox)
1235 ? $field.is(':checked')
1236 : $field.val()
1237 ;
1238 $field.data(metadata.defaultValue, value);
1239 })
1240 ;
1241 },
1242 error: function() {
1243 $module
1244 .removeClass(className.success)
1245 .addClass(className.error)
1246 ;
1247 },
1248 value: function (field, value) {
1249 var
1250 fields = {}
1251 ;
1252 fields[field] = value;
1253 return module.set.values.call(element, fields);
1254 },
1255 values: function (fields) {
1256 if($.isEmptyObject(fields)) {
1257 return;
1258 }
1259 $.each(fields, function(key, value) {
1260 var
1261 $field = module.get.field(key),
1262 $element = $field.parent(),
1263 isMultiple = $.isArray(value),
1264 isCheckbox = $element.is(selector.uiCheckbox),
1265 isDropdown = $element.is(selector.uiDropdown),
1266 isRadio = ($field.is(selector.radio) && isCheckbox),
1267 fieldExists = ($field.length > 0),
1268 $multipleField
1269 ;
1270 if(fieldExists) {
1271 if(isMultiple && isCheckbox) {
1272 module.verbose('Selecting multiple', value, $field);
1273 $element.checkbox('uncheck');
1274 $.each(value, function(index, value) {
1275 $multipleField = $field.filter('[value="' + value + '"]');
1276 $element = $multipleField.parent();
1277 if($multipleField.length > 0) {
1278 $element.checkbox('check');
1279 }
1280 });
1281 }
1282 else if(isRadio) {
1283 module.verbose('Selecting radio value', value, $field);
1284 $field.filter('[value="' + value + '"]')
1285 .parent(selector.uiCheckbox)
1286 .checkbox('check')
1287 ;
1288 }
1289 else if(isCheckbox) {
1290 module.verbose('Setting checkbox value', value, $element);
1291 if(value === true) {
1292 $element.checkbox('check');
1293 }
1294 else {
1295 $element.checkbox('uncheck');
1296 }
1297 }
1298 else if(isDropdown) {
1299 module.verbose('Setting dropdown value', value, $element);
1300 $element.dropdown('set selected', value);
1301 }
1302 else {
1303 module.verbose('Setting field value', value, $field);
1304 $field.val(value);
1305 }
1306 }
1307 });
1308 }
1309 },
1310
1311 validate: {
1312
1313 form: function(event, ignoreCallbacks) {
1314 var
1315 values = module.get.values(),
1316 apiRequest
1317 ;
1318
1319 // input keydown event will fire submit repeatedly by browser default
1320 if(keyHeldDown) {
1321 return false;
1322 }
1323
1324 // reset errors
1325 formErrors = [];
1326 if( module.determine.isValid() ) {
1327 module.debug('Form has no validation errors, submitting');
1328 module.set.success();
1329 if(ignoreCallbacks !== true) {
1330 return settings.onSuccess.call(element, event, values);
1331 }
1332 }
1333 else {
1334 module.debug('Form has errors');
1335 module.set.error();
1336 if(!settings.inline) {
1337 module.add.errors(formErrors);
1338 }
1339 // prevent ajax submit
1340 if($module.data('moduleApi') !== undefined) {
1341 event.stopImmediatePropagation();
1342 }
1343 if(ignoreCallbacks !== true) {
1344 return settings.onFailure.call(element, formErrors, values);
1345 }
1346 }
1347 },
1348
1349 // takes a validation object and returns whether field passes validation
1350 field: function(field, fieldName, showErrors) {
1351 showErrors = (showErrors !== undefined)
1352 ? showErrors
1353 : true
1354 ;
1355 if(typeof field == 'string') {
1356 module.verbose('Validating field', field);
1357 fieldName = field;
1358 field = validation[field];
1359 }
1360 var
1361 identifier = field.identifier || fieldName,
1362 $field = module.get.field(identifier),
1363 $dependsField = (field.depends)
1364 ? module.get.field(field.depends)
1365 : false,
1366 fieldValid = true,
1367 fieldErrors = []
1368 ;
1369 if(!field.identifier) {
1370 module.debug('Using field name as identifier', identifier);
1371 field.identifier = identifier;
1372 }
1373 if($field.prop('disabled')) {
1374 module.debug('Field is disabled. Skipping', identifier);
1375 fieldValid = true;
1376 }
1377 else if(field.optional && module.is.blank($field)){
1378 module.debug('Field is optional and blank. Skipping', identifier);
1379 fieldValid = true;
1380 }
1381 else if(field.depends && module.is.empty($dependsField)) {
1382 module.debug('Field depends on another value that is not present or empty. Skipping', $dependsField);
1383 fieldValid = true;
1384 }
1385 else if(field.rules !== undefined) {
1386 $.each(field.rules, function(index, rule) {
1387 if( module.has.field(identifier) && !( module.validate.rule(field, rule) ) ) {
1388 module.debug('Field is invalid', identifier, rule.type);
1389 fieldErrors.push(module.get.prompt(rule, field));
1390 fieldValid = false;
1391 }
1392 });
1393 }
1394 if(fieldValid) {
1395 if(showErrors) {
1396 module.remove.prompt(identifier, fieldErrors);
1397 settings.onValid.call($field);
1398 }
1399 }
1400 else {
1401 if(showErrors) {
1402 formErrors = formErrors.concat(fieldErrors);
1403 module.add.prompt(identifier, fieldErrors);
1404 settings.onInvalid.call($field, fieldErrors);
1405 }
1406 return false;
1407 }
1408 return true;
1409 },
1410
1411 // takes validation rule and returns whether field passes rule
1412 rule: function(field, rule) {
1413 var
1414 $field = module.get.field(field.identifier),
1415 type = rule.type,
1416 value = $field.val(),
1417 isValid = true,
1418 ancillary = module.get.ancillaryValue(rule),
1419 ruleName = module.get.ruleName(rule),
1420 ruleFunction = settings.rules[ruleName]
1421 ;
1422 if( !$.isFunction(ruleFunction) ) {
1423 module.error(error.noRule, ruleName);
1424 return;
1425 }
1426 // cast to string avoiding encoding special values
1427 value = (value === undefined || value === '' || value === null)
1428 ? ''
1429 : $.trim(value + '')
1430 ;
1431 return ruleFunction.call($field, value, ancillary);
1432 }
1433 },
1434
1435 setting: function(name, value) {
1436 if( $.isPlainObject(name) ) {
1437 $.extend(true, settings, name);
1438 }
1439 else if(value !== undefined) {
1440 settings[name] = value;
1441 }
1442 else {
1443 return settings[name];
1444 }
1445 },
1446 internal: function(name, value) {
1447 if( $.isPlainObject(name) ) {
1448 $.extend(true, module, name);
1449 }
1450 else if(value !== undefined) {
1451 module[name] = value;
1452 }
1453 else {
1454 return module[name];
1455 }
1456 },
1457 debug: function() {
1458 if(!settings.silent && settings.debug) {
1459 if(settings.performance) {
1460 module.performance.log(arguments);
1461 }
1462 else {
1463 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
1464 module.debug.apply(console, arguments);
1465 }
1466 }
1467 },
1468 verbose: function() {
1469 if(!settings.silent && settings.verbose && settings.debug) {
1470 if(settings.performance) {
1471 module.performance.log(arguments);
1472 }
1473 else {
1474 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
1475 module.verbose.apply(console, arguments);
1476 }
1477 }
1478 },
1479 error: function() {
1480 if(!settings.silent) {
1481 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
1482 module.error.apply(console, arguments);
1483 }
1484 },
1485 performance: {
1486 log: function(message) {
1487 var
1488 currentTime,
1489 executionTime,
1490 previousTime
1491 ;
1492 if(settings.performance) {
1493 currentTime = new Date().getTime();
1494 previousTime = time || currentTime;
1495 executionTime = currentTime - previousTime;
1496 time = currentTime;
1497 performance.push({
1498 'Name' : message[0],
1499 'Arguments' : [].slice.call(message, 1) || '',
1500 'Element' : element,
1501 'Execution Time' : executionTime
1502 });
1503 }
1504 clearTimeout(module.performance.timer);
1505 module.performance.timer = setTimeout(module.performance.display, 500);
1506 },
1507 display: function() {
1508 var
1509 title = settings.name + ':',
1510 totalTime = 0
1511 ;
1512 time = false;
1513 clearTimeout(module.performance.timer);
1514 $.each(performance, function(index, data) {
1515 totalTime += data['Execution Time'];
1516 });
1517 title += ' ' + totalTime + 'ms';
1518 if(moduleSelector) {
1519 title += ' \'' + moduleSelector + '\'';
1520 }
1521 if($allModules.length > 1) {
1522 title += ' ' + '(' + $allModules.length + ')';
1523 }
1524 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
1525 console.groupCollapsed(title);
1526 if(console.table) {
1527 console.table(performance);
1528 }
1529 else {
1530 $.each(performance, function(index, data) {
1531 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
1532 });
1533 }
1534 console.groupEnd();
1535 }
1536 performance = [];
1537 }
1538 },
1539 invoke: function(query, passedArguments, context) {
1540 var
1541 object = instance,
1542 maxDepth,
1543 found,
1544 response
1545 ;
1546 passedArguments = passedArguments || queryArguments;
1547 context = element || context;
1548 if(typeof query == 'string' && object !== undefined) {
1549 query = query.split(/[\. ]/);
1550 maxDepth = query.length - 1;
1551 $.each(query, function(depth, value) {
1552 var camelCaseValue = (depth != maxDepth)
1553 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
1554 : query
1555 ;
1556 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
1557 object = object[camelCaseValue];
1558 }
1559 else if( object[camelCaseValue] !== undefined ) {
1560 found = object[camelCaseValue];
1561 return false;
1562 }
1563 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
1564 object = object[value];
1565 }
1566 else if( object[value] !== undefined ) {
1567 found = object[value];
1568 return false;
1569 }
1570 else {
1571 return false;
1572 }
1573 });
1574 }
1575 if( $.isFunction( found ) ) {
1576 response = found.apply(context, passedArguments);
1577 }
1578 else if(found !== undefined) {
1579 response = found;
1580 }
1581 if($.isArray(returnedValue)) {
1582 returnedValue.push(response);
1583 }
1584 else if(returnedValue !== undefined) {
1585 returnedValue = [returnedValue, response];
1586 }
1587 else if(response !== undefined) {
1588 returnedValue = response;
1589 }
1590 return found;
1591 }
1592 };
1593 module.initialize();
1594 })
1595 ;
1596
1597 return (returnedValue !== undefined)
1598 ? returnedValue
1599 : this
1600 ;
1601 };
1602
1603 $.fn.form.settings = {
1604
1605 name : 'Form',
1606 namespace : 'form',
1607
1608 debug : false,
1609 verbose : false,
1610 performance : true,
1611
1612 fields : false,
1613
1614 keyboardShortcuts : true,
1615 on : 'submit',
1616 inline : false,
1617
1618 delay : 200,
1619 revalidate : true,
1620
1621 transition : 'scale',
1622 duration : 200,
1623
1624 onValid : function() {},
1625 onInvalid : function() {},
1626 onSuccess : function() { return true; },
1627 onFailure : function() { return false; },
1628
1629 metadata : {
1630 defaultValue : 'default',
1631 validate : 'validate'
1632 },
1633
1634 regExp: {
1635 htmlID : /^[a-zA-Z][\w:.-]*$/g,
1636 bracket : /\[(.*)\]/i,
1637 decimal : /^\d+\.?\d*$/,
1638 email : /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i,
1639 escape : /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,
1640 flags : /^\/(.*)\/(.*)?/,
1641 integer : /^\-?\d+$/,
1642 number : /^\-?\d*(\.\d+)?$/,
1643 url : /(https?:\/\/(?:www\.|(?!www))[^\s\.]+\.[^\s]{2,}|www\.[^\s]+\.[^\s]{2,})/i
1644 },
1645
1646 text: {
1647 unspecifiedRule : 'Please enter a valid value',
1648 unspecifiedField : 'This field'
1649 },
1650
1651 prompt: {
1652 empty : '{name} must have a value',
1653 checked : '{name} must be checked',
1654 email : '{name} must be a valid e-mail',
1655 url : '{name} must be a valid url',
1656 regExp : '{name} is not formatted correctly',
1657 integer : '{name} must be an integer',
1658 decimal : '{name} must be a decimal number',
1659 number : '{name} must be set to a number',
1660 is : '{name} must be "{ruleValue}"',
1661 isExactly : '{name} must be exactly "{ruleValue}"',
1662 not : '{name} cannot be set to "{ruleValue}"',
1663 notExactly : '{name} cannot be set to exactly "{ruleValue}"',
1664 contain : '{name} cannot contain "{ruleValue}"',
1665 containExactly : '{name} cannot contain exactly "{ruleValue}"',
1666 doesntContain : '{name} must contain "{ruleValue}"',
1667 doesntContainExactly : '{name} must contain exactly "{ruleValue}"',
1668 minLength : '{name} must be at least {ruleValue} characters',
1669 length : '{name} must be at least {ruleValue} characters',
1670 exactLength : '{name} must be exactly {ruleValue} characters',
1671 maxLength : '{name} cannot be longer than {ruleValue} characters',
1672 match : '{name} must match {ruleValue} field',
1673 different : '{name} must have a different value than {ruleValue} field',
1674 creditCard : '{name} must be a valid credit card number',
1675 minCount : '{name} must have at least {ruleValue} choices',
1676 exactCount : '{name} must have exactly {ruleValue} choices',
1677 maxCount : '{name} must have {ruleValue} or less choices'
1678 },
1679
1680 selector : {
1681 checkbox : 'input[type="checkbox"], input[type="radio"]',
1682 clear : '.clear',
1683 field : 'input, textarea, select',
1684 group : '.field',
1685 input : 'input',
1686 message : '.error.message',
1687 prompt : '.prompt.label',
1688 radio : 'input[type="radio"]',
1689 reset : '.reset:not([type="reset"])',
1690 submit : '.submit:not([type="submit"])',
1691 uiCheckbox : '.ui.checkbox',
1692 uiDropdown : '.ui.dropdown'
1693 },
1694
1695 className : {
1696 error : 'error',
1697 label : 'ui prompt label',
1698 pressed : 'down',
1699 success : 'success'
1700 },
1701
1702 error: {
1703 identifier : 'You must specify a string identifier for each field',
1704 method : 'The method you called is not defined.',
1705 noRule : 'There is no rule matching the one you specified',
1706 oldSyntax : 'Starting in 2.0 forms now only take a single settings object. Validation settings converted to new syntax automatically.'
1707 },
1708
1709 templates: {
1710
1711 // template that produces error message
1712 error: function(errors) {
1713 var
1714 html = '<ul class="list">'
1715 ;
1716 $.each(errors, function(index, value) {
1717 html += '<li>' + value + '</li>';
1718 });
1719 html += '</ul>';
1720 return $(html);
1721 },
1722
1723 // template that produces label
1724 prompt: function(errors) {
1725 return $('<div/>')
1726 .addClass('ui basic red pointing prompt label')
1727 .html(errors[0])
1728 ;
1729 }
1730 },
1731
1732 rules: {
1733
1734 // is not empty or blank string
1735 empty: function(value) {
1736 return !(value === undefined || '' === value || $.isArray(value) && value.length === 0);
1737 },
1738
1739 // checkbox checked
1740 checked: function() {
1741 return ($(this).filter(':checked').length > 0);
1742 },
1743
1744 // is most likely an email
1745 email: function(value){
1746 return $.fn.form.settings.regExp.email.test(value);
1747 },
1748
1749 // value is most likely url
1750 url: function(value) {
1751 return $.fn.form.settings.regExp.url.test(value);
1752 },
1753
1754 // matches specified regExp
1755 regExp: function(value, regExp) {
1756 if(regExp instanceof RegExp) {
1757 return value.match(regExp);
1758 }
1759 var
1760 regExpParts = regExp.match($.fn.form.settings.regExp.flags),
1761 flags
1762 ;
1763 // regular expression specified as /baz/gi (flags)
1764 if(regExpParts) {
1765 regExp = (regExpParts.length >= 2)
1766 ? regExpParts[1]
1767 : regExp
1768 ;
1769 flags = (regExpParts.length >= 3)
1770 ? regExpParts[2]
1771 : ''
1772 ;
1773 }
1774 return value.match( new RegExp(regExp, flags) );
1775 },
1776
1777 // is valid integer or matches range
1778 integer: function(value, range) {
1779 var
1780 intRegExp = $.fn.form.settings.regExp.integer,
1781 min,
1782 max,
1783 parts
1784 ;
1785 if( !range || ['', '..'].indexOf(range) !== -1) {
1786 // do nothing
1787 }
1788 else if(range.indexOf('..') == -1) {
1789 if(intRegExp.test(range)) {
1790 min = max = range - 0;
1791 }
1792 }
1793 else {
1794 parts = range.split('..', 2);
1795 if(intRegExp.test(parts[0])) {
1796 min = parts[0] - 0;
1797 }
1798 if(intRegExp.test(parts[1])) {
1799 max = parts[1] - 0;
1800 }
1801 }
1802 return (
1803 intRegExp.test(value) &&
1804 (min === undefined || value >= min) &&
1805 (max === undefined || value <= max)
1806 );
1807 },
1808
1809 // is valid number (with decimal)
1810 decimal: function(value) {
1811 return $.fn.form.settings.regExp.decimal.test(value);
1812 },
1813
1814 // is valid number
1815 number: function(value) {
1816 return $.fn.form.settings.regExp.number.test(value);
1817 },
1818
1819 // is value (case insensitive)
1820 is: function(value, text) {
1821 text = (typeof text == 'string')
1822 ? text.toLowerCase()
1823 : text
1824 ;
1825 value = (typeof value == 'string')
1826 ? value.toLowerCase()
1827 : value
1828 ;
1829 return (value == text);
1830 },
1831
1832 // is value
1833 isExactly: function(value, text) {
1834 return (value == text);
1835 },
1836
1837 // value is not another value (case insensitive)
1838 not: function(value, notValue) {
1839 value = (typeof value == 'string')
1840 ? value.toLowerCase()
1841 : value
1842 ;
1843 notValue = (typeof notValue == 'string')
1844 ? notValue.toLowerCase()
1845 : notValue
1846 ;
1847 return (value != notValue);
1848 },
1849
1850 // value is not another value (case sensitive)
1851 notExactly: function(value, notValue) {
1852 return (value != notValue);
1853 },
1854
1855 // value contains text (insensitive)
1856 contains: function(value, text) {
1857 // escape regex characters
1858 text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
1859 return (value.search( new RegExp(text, 'i') ) !== -1);
1860 },
1861
1862 // value contains text (case sensitive)
1863 containsExactly: function(value, text) {
1864 // escape regex characters
1865 text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
1866 return (value.search( new RegExp(text) ) !== -1);
1867 },
1868
1869 // value contains text (insensitive)
1870 doesntContain: function(value, text) {
1871 // escape regex characters
1872 text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
1873 return (value.search( new RegExp(text, 'i') ) === -1);
1874 },
1875
1876 // value contains text (case sensitive)
1877 doesntContainExactly: function(value, text) {
1878 // escape regex characters
1879 text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
1880 return (value.search( new RegExp(text) ) === -1);
1881 },
1882
1883 // is at least string length
1884 minLength: function(value, requiredLength) {
1885 return (value !== undefined)
1886 ? (value.length >= requiredLength)
1887 : false
1888 ;
1889 },
1890
1891 // see rls notes for 2.0.6 (this is a duplicate of minLength)
1892 length: function(value, requiredLength) {
1893 return (value !== undefined)
1894 ? (value.length >= requiredLength)
1895 : false
1896 ;
1897 },
1898
1899 // is exactly length
1900 exactLength: function(value, requiredLength) {
1901 return (value !== undefined)
1902 ? (value.length == requiredLength)
1903 : false
1904 ;
1905 },
1906
1907 // is less than length
1908 maxLength: function(value, maxLength) {
1909 return (value !== undefined)
1910 ? (value.length <= maxLength)
1911 : false
1912 ;
1913 },
1914
1915 // matches another field
1916 match: function(value, identifier) {
1917 var
1918 $form = $(this),
1919 matchingValue
1920 ;
1921 if( $('[data-validate="'+ identifier +'"]').length > 0 ) {
1922 matchingValue = $('[data-validate="'+ identifier +'"]').val();
1923 }
1924 else if($('#' + identifier).length > 0) {
1925 matchingValue = $('#' + identifier).val();
1926 }
1927 else if($('[name="' + identifier +'"]').length > 0) {
1928 matchingValue = $('[name="' + identifier + '"]').val();
1929 }
1930 else if( $('[name="' + identifier +'[]"]').length > 0 ) {
1931 matchingValue = $('[name="' + identifier +'[]"]');
1932 }
1933 return (matchingValue !== undefined)
1934 ? ( value.toString() == matchingValue.toString() )
1935 : false
1936 ;
1937 },
1938
1939 // different than another field
1940 different: function(value, identifier) {
1941 // use either id or name of field
1942 var
1943 $form = $(this),
1944 matchingValue
1945 ;
1946 if( $('[data-validate="'+ identifier +'"]').length > 0 ) {
1947 matchingValue = $('[data-validate="'+ identifier +'"]').val();
1948 }
1949 else if($('#' + identifier).length > 0) {
1950 matchingValue = $('#' + identifier).val();
1951 }
1952 else if($('[name="' + identifier +'"]').length > 0) {
1953 matchingValue = $('[name="' + identifier + '"]').val();
1954 }
1955 else if( $('[name="' + identifier +'[]"]').length > 0 ) {
1956 matchingValue = $('[name="' + identifier +'[]"]');
1957 }
1958 return (matchingValue !== undefined)
1959 ? ( value.toString() !== matchingValue.toString() )
1960 : false
1961 ;
1962 },
1963
1964 creditCard: function(cardNumber, cardTypes) {
1965 var
1966 cards = {
1967 visa: {
1968 pattern : /^4/,
1969 length : [16]
1970 },
1971 amex: {
1972 pattern : /^3[47]/,
1973 length : [15]
1974 },
1975 mastercard: {
1976 pattern : /^5[1-5]/,
1977 length : [16]
1978 },
1979 discover: {
1980 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)/,
1981 length : [16]
1982 },
1983 unionPay: {
1984 pattern : /^(62|88)/,
1985 length : [16, 17, 18, 19]
1986 },
1987 jcb: {
1988 pattern : /^35(2[89]|[3-8][0-9])/,
1989 length : [16]
1990 },
1991 maestro: {
1992 pattern : /^(5018|5020|5038|6304|6759|676[1-3])/,
1993 length : [12, 13, 14, 15, 16, 17, 18, 19]
1994 },
1995 dinersClub: {
1996 pattern : /^(30[0-5]|^36)/,
1997 length : [14]
1998 },
1999 laser: {
2000 pattern : /^(6304|670[69]|6771)/,
2001 length : [16, 17, 18, 19]
2002 },
2003 visaElectron: {
2004 pattern : /^(4026|417500|4508|4844|491(3|7))/,
2005 length : [16]
2006 }
2007 },
2008 valid = {},
2009 validCard = false,
2010 requiredTypes = (typeof cardTypes == 'string')
2011 ? cardTypes.split(',')
2012 : false,
2013 unionPay,
2014 validation
2015 ;
2016
2017 if(typeof cardNumber !== 'string' || cardNumber.length === 0) {
2018 return;
2019 }
2020
2021 // allow dashes in card
2022 cardNumber = cardNumber.replace(/[\-]/g, '');
2023
2024 // verify card types
2025 if(requiredTypes) {
2026 $.each(requiredTypes, function(index, type){
2027 // verify each card type
2028 validation = cards[type];
2029 if(validation) {
2030 valid = {
2031 length : ($.inArray(cardNumber.length, validation.length) !== -1),
2032 pattern : (cardNumber.search(validation.pattern) !== -1)
2033 };
2034 if(valid.length && valid.pattern) {
2035 validCard = true;
2036 }
2037 }
2038 });
2039
2040 if(!validCard) {
2041 return false;
2042 }
2043 }
2044
2045 // skip luhn for UnionPay
2046 unionPay = {
2047 number : ($.inArray(cardNumber.length, cards.unionPay.length) !== -1),
2048 pattern : (cardNumber.search(cards.unionPay.pattern) !== -1)
2049 };
2050 if(unionPay.number && unionPay.pattern) {
2051 return true;
2052 }
2053
2054 // verify luhn, adapted from <https://gist.github.com/2134376>
2055 var
2056 length = cardNumber.length,
2057 multiple = 0,
2058 producedValue = [
2059 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
2060 [0, 2, 4, 6, 8, 1, 3, 5, 7, 9]
2061 ],
2062 sum = 0
2063 ;
2064 while (length--) {
2065 sum += producedValue[multiple][parseInt(cardNumber.charAt(length), 10)];
2066 multiple ^= 1;
2067 }
2068 return (sum % 10 === 0 && sum > 0);
2069 },
2070
2071 minCount: function(value, minCount) {
2072 if(minCount == 0) {
2073 return true;
2074 }
2075 if(minCount == 1) {
2076 return (value !== '');
2077 }
2078 return (value.split(',').length >= minCount);
2079 },
2080
2081 exactCount: function(value, exactCount) {
2082 if(exactCount == 0) {
2083 return (value === '');
2084 }
2085 if(exactCount == 1) {
2086 return (value !== '' && value.search(',') === -1);
2087 }
2088 return (value.split(',').length == exactCount);
2089 },
2090
2091 maxCount: function(value, maxCount) {
2092 if(maxCount == 0) {
2093 return false;
2094 }
2095 if(maxCount == 1) {
2096 return (value.search(',') === -1);
2097 }
2098 return (value.split(',').length <= maxCount);
2099 }
2100 }
2101
2102 };
2103
2104 })( jQuery, window, document );
2105
2106 /*!
2107 * # Semantic UI 2.2.10 - Checkbox
2108 * http://github.com/semantic-org/semantic-ui/
2109 *
2110 *
2111 * Released under the MIT license
2112 * http://opensource.org/licenses/MIT
2113 *
2114 */
2115
2116 ;(function ($, window, document, undefined) {
2117
2118 "use strict";
2119
2120 window = (typeof window != 'undefined' && window.Math == Math)
2121 ? window
2122 : (typeof self != 'undefined' && self.Math == Math)
2123 ? self
2124 : Function('return this')()
2125 ;
2126
2127 $.fn.checkbox = function(parameters) {
2128 var
2129 $allModules = $(this),
2130 moduleSelector = $allModules.selector || '',
2131
2132 time = new Date().getTime(),
2133 performance = [],
2134
2135 query = arguments[0],
2136 methodInvoked = (typeof query == 'string'),
2137 queryArguments = [].slice.call(arguments, 1),
2138 returnedValue
2139 ;
2140
2141 $allModules
2142 .each(function() {
2143 var
2144 settings = $.extend(true, {}, $.fn.checkbox.settings, parameters),
2145
2146 className = settings.className,
2147 namespace = settings.namespace,
2148 selector = settings.selector,
2149 error = settings.error,
2150
2151 eventNamespace = '.' + namespace,
2152 moduleNamespace = 'module-' + namespace,
2153
2154 $module = $(this),
2155 $label = $(this).children(selector.label),
2156 $input = $(this).children(selector.input),
2157 input = $input[0],
2158
2159 initialLoad = false,
2160 shortcutPressed = false,
2161 instance = $module.data(moduleNamespace),
2162
2163 observer,
2164 element = this,
2165 module
2166 ;
2167
2168 module = {
2169
2170 initialize: function() {
2171 module.verbose('Initializing checkbox', settings);
2172
2173 module.create.label();
2174 module.bind.events();
2175
2176 module.set.tabbable();
2177 module.hide.input();
2178
2179 module.observeChanges();
2180 module.instantiate();
2181 module.setup();
2182 },
2183
2184 instantiate: function() {
2185 module.verbose('Storing instance of module', module);
2186 instance = module;
2187 $module
2188 .data(moduleNamespace, module)
2189 ;
2190 },
2191
2192 destroy: function() {
2193 module.verbose('Destroying module');
2194 module.unbind.events();
2195 module.show.input();
2196 $module.removeData(moduleNamespace);
2197 },
2198
2199 fix: {
2200 reference: function() {
2201 if( $module.is(selector.input) ) {
2202 module.debug('Behavior called on <input> adjusting invoked element');
2203 $module = $module.closest(selector.checkbox);
2204 module.refresh();
2205 }
2206 }
2207 },
2208
2209 setup: function() {
2210 module.set.initialLoad();
2211 if( module.is.indeterminate() ) {
2212 module.debug('Initial value is indeterminate');
2213 module.indeterminate();
2214 }
2215 else if( module.is.checked() ) {
2216 module.debug('Initial value is checked');
2217 module.check();
2218 }
2219 else {
2220 module.debug('Initial value is unchecked');
2221 module.uncheck();
2222 }
2223 module.remove.initialLoad();
2224 },
2225
2226 refresh: function() {
2227 $label = $module.children(selector.label);
2228 $input = $module.children(selector.input);
2229 input = $input[0];
2230 },
2231
2232 hide: {
2233 input: function() {
2234 module.verbose('Modifying <input> z-index to be unselectable');
2235 $input.addClass(className.hidden);
2236 }
2237 },
2238 show: {
2239 input: function() {
2240 module.verbose('Modifying <input> z-index to be selectable');
2241 $input.removeClass(className.hidden);
2242 }
2243 },
2244
2245 observeChanges: function() {
2246 if('MutationObserver' in window) {
2247 observer = new MutationObserver(function(mutations) {
2248 module.debug('DOM tree modified, updating selector cache');
2249 module.refresh();
2250 });
2251 observer.observe(element, {
2252 childList : true,
2253 subtree : true
2254 });
2255 module.debug('Setting up mutation observer', observer);
2256 }
2257 },
2258
2259 attachEvents: function(selector, event) {
2260 var
2261 $element = $(selector)
2262 ;
2263 event = $.isFunction(module[event])
2264 ? module[event]
2265 : module.toggle
2266 ;
2267 if($element.length > 0) {
2268 module.debug('Attaching checkbox events to element', selector, event);
2269 $element
2270 .on('click' + eventNamespace, event)
2271 ;
2272 }
2273 else {
2274 module.error(error.notFound);
2275 }
2276 },
2277
2278 event: {
2279 click: function(event) {
2280 var
2281 $target = $(event.target)
2282 ;
2283 if( $target.is(selector.input) ) {
2284 module.verbose('Using default check action on initialized checkbox');
2285 return;
2286 }
2287 if( $target.is(selector.link) ) {
2288 module.debug('Clicking link inside checkbox, skipping toggle');
2289 return;
2290 }
2291 module.toggle();
2292 $input.focus();
2293 event.preventDefault();
2294 },
2295 keydown: function(event) {
2296 var
2297 key = event.which,
2298 keyCode = {
2299 enter : 13,
2300 space : 32,
2301 escape : 27
2302 }
2303 ;
2304 if(key == keyCode.escape) {
2305 module.verbose('Escape key pressed blurring field');
2306 $input.blur();
2307 shortcutPressed = true;
2308 }
2309 else if(!event.ctrlKey && ( key == keyCode.space || key == keyCode.enter) ) {
2310 module.verbose('Enter/space key pressed, toggling checkbox');
2311 module.toggle();
2312 shortcutPressed = true;
2313 }
2314 else {
2315 shortcutPressed = false;
2316 }
2317 },
2318 keyup: function(event) {
2319 if(shortcutPressed) {
2320 event.preventDefault();
2321 }
2322 }
2323 },
2324
2325 check: function() {
2326 if( !module.should.allowCheck() ) {
2327 return;
2328 }
2329 module.debug('Checking checkbox', $input);
2330 module.set.checked();
2331 if( !module.should.ignoreCallbacks() ) {
2332 settings.onChecked.call(input);
2333 settings.onChange.call(input);
2334 }
2335 },
2336
2337 uncheck: function() {
2338 if( !module.should.allowUncheck() ) {
2339 return;
2340 }
2341 module.debug('Unchecking checkbox');
2342 module.set.unchecked();
2343 if( !module.should.ignoreCallbacks() ) {
2344 settings.onUnchecked.call(input);
2345 settings.onChange.call(input);
2346 }
2347 },
2348
2349 indeterminate: function() {
2350 if( module.should.allowIndeterminate() ) {
2351 module.debug('Checkbox is already indeterminate');
2352 return;
2353 }
2354 module.debug('Making checkbox indeterminate');
2355 module.set.indeterminate();
2356 if( !module.should.ignoreCallbacks() ) {
2357 settings.onIndeterminate.call(input);
2358 settings.onChange.call(input);
2359 }
2360 },
2361
2362 determinate: function() {
2363 if( module.should.allowDeterminate() ) {
2364 module.debug('Checkbox is already determinate');
2365 return;
2366 }
2367 module.debug('Making checkbox determinate');
2368 module.set.determinate();
2369 if( !module.should.ignoreCallbacks() ) {
2370 settings.onDeterminate.call(input);
2371 settings.onChange.call(input);
2372 }
2373 },
2374
2375 enable: function() {
2376 if( module.is.enabled() ) {
2377 module.debug('Checkbox is already enabled');
2378 return;
2379 }
2380 module.debug('Enabling checkbox');
2381 module.set.enabled();
2382 settings.onEnable.call(input);
2383 // preserve legacy callbacks
2384 settings.onEnabled.call(input);
2385 },
2386
2387 disable: function() {
2388 if( module.is.disabled() ) {
2389 module.debug('Checkbox is already disabled');
2390 return;
2391 }
2392 module.debug('Disabling checkbox');
2393 module.set.disabled();
2394 settings.onDisable.call(input);
2395 // preserve legacy callbacks
2396 settings.onDisabled.call(input);
2397 },
2398
2399 get: {
2400 radios: function() {
2401 var
2402 name = module.get.name()
2403 ;
2404 return $('input[name="' + name + '"]').closest(selector.checkbox);
2405 },
2406 otherRadios: function() {
2407 return module.get.radios().not($module);
2408 },
2409 name: function() {
2410 return $input.attr('name');
2411 }
2412 },
2413
2414 is: {
2415 initialLoad: function() {
2416 return initialLoad;
2417 },
2418 radio: function() {
2419 return ($input.hasClass(className.radio) || $input.attr('type') == 'radio');
2420 },
2421 indeterminate: function() {
2422 return $input.prop('indeterminate') !== undefined && $input.prop('indeterminate');
2423 },
2424 checked: function() {
2425 return $input.prop('checked') !== undefined && $input.prop('checked');
2426 },
2427 disabled: function() {
2428 return $input.prop('disabled') !== undefined && $input.prop('disabled');
2429 },
2430 enabled: function() {
2431 return !module.is.disabled();
2432 },
2433 determinate: function() {
2434 return !module.is.indeterminate();
2435 },
2436 unchecked: function() {
2437 return !module.is.checked();
2438 }
2439 },
2440
2441 should: {
2442 allowCheck: function() {
2443 if(module.is.determinate() && module.is.checked() && !module.should.forceCallbacks() ) {
2444 module.debug('Should not allow check, checkbox is already checked');
2445 return false;
2446 }
2447 if(settings.beforeChecked.apply(input) === false) {
2448 module.debug('Should not allow check, beforeChecked cancelled');
2449 return false;
2450 }
2451 return true;
2452 },
2453 allowUncheck: function() {
2454 if(module.is.determinate() && module.is.unchecked() && !module.should.forceCallbacks() ) {
2455 module.debug('Should not allow uncheck, checkbox is already unchecked');
2456 return false;
2457 }
2458 if(settings.beforeUnchecked.apply(input) === false) {
2459 module.debug('Should not allow uncheck, beforeUnchecked cancelled');
2460 return false;
2461 }
2462 return true;
2463 },
2464 allowIndeterminate: function() {
2465 if(module.is.indeterminate() && !module.should.forceCallbacks() ) {
2466 module.debug('Should not allow indeterminate, checkbox is already indeterminate');
2467 return false;
2468 }
2469 if(settings.beforeIndeterminate.apply(input) === false) {
2470 module.debug('Should not allow indeterminate, beforeIndeterminate cancelled');
2471 return false;
2472 }
2473 return true;
2474 },
2475 allowDeterminate: function() {
2476 if(module.is.determinate() && !module.should.forceCallbacks() ) {
2477 module.debug('Should not allow determinate, checkbox is already determinate');
2478 return false;
2479 }
2480 if(settings.beforeDeterminate.apply(input) === false) {
2481 module.debug('Should not allow determinate, beforeDeterminate cancelled');
2482 return false;
2483 }
2484 return true;
2485 },
2486 forceCallbacks: function() {
2487 return (module.is.initialLoad() && settings.fireOnInit);
2488 },
2489 ignoreCallbacks: function() {
2490 return (initialLoad && !settings.fireOnInit);
2491 }
2492 },
2493
2494 can: {
2495 change: function() {
2496 return !( $module.hasClass(className.disabled) || $module.hasClass(className.readOnly) || $input.prop('disabled') || $input.prop('readonly') );
2497 },
2498 uncheck: function() {
2499 return (typeof settings.uncheckable === 'boolean')
2500 ? settings.uncheckable
2501 : !module.is.radio()
2502 ;
2503 }
2504 },
2505
2506 set: {
2507 initialLoad: function() {
2508 initialLoad = true;
2509 },
2510 checked: function() {
2511 module.verbose('Setting class to checked');
2512 $module
2513 .removeClass(className.indeterminate)
2514 .addClass(className.checked)
2515 ;
2516 if( module.is.radio() ) {
2517 module.uncheckOthers();
2518 }
2519 if(!module.is.indeterminate() && module.is.checked()) {
2520 module.debug('Input is already checked, skipping input property change');
2521 return;
2522 }
2523 module.verbose('Setting state to checked', input);
2524 $input
2525 .prop('indeterminate', false)
2526 .prop('checked', true)
2527 ;
2528 module.trigger.change();
2529 },
2530 unchecked: function() {
2531 module.verbose('Removing checked class');
2532 $module
2533 .removeClass(className.indeterminate)
2534 .removeClass(className.checked)
2535 ;
2536 if(!module.is.indeterminate() && module.is.unchecked() ) {
2537 module.debug('Input is already unchecked');
2538 return;
2539 }
2540 module.debug('Setting state to unchecked');
2541 $input
2542 .prop('indeterminate', false)
2543 .prop('checked', false)
2544 ;
2545 module.trigger.change();
2546 },
2547 indeterminate: function() {
2548 module.verbose('Setting class to indeterminate');
2549 $module
2550 .addClass(className.indeterminate)
2551 ;
2552 if( module.is.indeterminate() ) {
2553 module.debug('Input is already indeterminate, skipping input property change');
2554 return;
2555 }
2556 module.debug('Setting state to indeterminate');
2557 $input
2558 .prop('indeterminate', true)
2559 ;
2560 module.trigger.change();
2561 },
2562 determinate: function() {
2563 module.verbose('Removing indeterminate class');
2564 $module
2565 .removeClass(className.indeterminate)
2566 ;
2567 if( module.is.determinate() ) {
2568 module.debug('Input is already determinate, skipping input property change');
2569 return;
2570 }
2571 module.debug('Setting state to determinate');
2572 $input
2573 .prop('indeterminate', false)
2574 ;
2575 },
2576 disabled: function() {
2577 module.verbose('Setting class to disabled');
2578 $module
2579 .addClass(className.disabled)
2580 ;
2581 if( module.is.disabled() ) {
2582 module.debug('Input is already disabled, skipping input property change');
2583 return;
2584 }
2585 module.debug('Setting state to disabled');
2586 $input
2587 .prop('disabled', 'disabled')
2588 ;
2589 module.trigger.change();
2590 },
2591 enabled: function() {
2592 module.verbose('Removing disabled class');
2593 $module.removeClass(className.disabled);
2594 if( module.is.enabled() ) {
2595 module.debug('Input is already enabled, skipping input property change');
2596 return;
2597 }
2598 module.debug('Setting state to enabled');
2599 $input
2600 .prop('disabled', false)
2601 ;
2602 module.trigger.change();
2603 },
2604 tabbable: function() {
2605 module.verbose('Adding tabindex to checkbox');
2606 if( $input.attr('tabindex') === undefined) {
2607 $input.attr('tabindex', 0);
2608 }
2609 }
2610 },
2611
2612 remove: {
2613 initialLoad: function() {
2614 initialLoad = false;
2615 }
2616 },
2617
2618 trigger: {
2619 change: function() {
2620 var
2621 events = document.createEvent('HTMLEvents'),
2622 inputElement = $input[0]
2623 ;
2624 if(inputElement) {
2625 module.verbose('Triggering native change event');
2626 events.initEvent('change', true, false);
2627 inputElement.dispatchEvent(events);
2628 }
2629 }
2630 },
2631
2632
2633 create: {
2634 label: function() {
2635 if($input.prevAll(selector.label).length > 0) {
2636 $input.prev(selector.label).detach().insertAfter($input);
2637 module.debug('Moving existing label', $label);
2638 }
2639 else if( !module.has.label() ) {
2640 $label = $('<label>').insertAfter($input);
2641 module.debug('Creating label', $label);
2642 }
2643 }
2644 },
2645
2646 has: {
2647 label: function() {
2648 return ($label.length > 0);
2649 }
2650 },
2651
2652 bind: {
2653 events: function() {
2654 module.verbose('Attaching checkbox events');
2655 $module
2656 .on('click' + eventNamespace, module.event.click)
2657 .on('keydown' + eventNamespace, selector.input, module.event.keydown)
2658 .on('keyup' + eventNamespace, selector.input, module.event.keyup)
2659 ;
2660 }
2661 },
2662
2663 unbind: {
2664 events: function() {
2665 module.debug('Removing events');
2666 $module
2667 .off(eventNamespace)
2668 ;
2669 }
2670 },
2671
2672 uncheckOthers: function() {
2673 var
2674 $radios = module.get.otherRadios()
2675 ;
2676 module.debug('Unchecking other radios', $radios);
2677 $radios.removeClass(className.checked);
2678 },
2679
2680 toggle: function() {
2681 if( !module.can.change() ) {
2682 if(!module.is.radio()) {
2683 module.debug('Checkbox is read-only or disabled, ignoring toggle');
2684 }
2685 return;
2686 }
2687 if( module.is.indeterminate() || module.is.unchecked() ) {
2688 module.debug('Currently unchecked');
2689 module.check();
2690 }
2691 else if( module.is.checked() && module.can.uncheck() ) {
2692 module.debug('Currently checked');
2693 module.uncheck();
2694 }
2695 },
2696 setting: function(name, value) {
2697 module.debug('Changing setting', name, value);
2698 if( $.isPlainObject(name) ) {
2699 $.extend(true, settings, name);
2700 }
2701 else if(value !== undefined) {
2702 if($.isPlainObject(settings[name])) {
2703 $.extend(true, settings[name], value);
2704 }
2705 else {
2706 settings[name] = value;
2707 }
2708 }
2709 else {
2710 return settings[name];
2711 }
2712 },
2713 internal: function(name, value) {
2714 if( $.isPlainObject(name) ) {
2715 $.extend(true, module, name);
2716 }
2717 else if(value !== undefined) {
2718 module[name] = value;
2719 }
2720 else {
2721 return module[name];
2722 }
2723 },
2724 debug: function() {
2725 if(!settings.silent && settings.debug) {
2726 if(settings.performance) {
2727 module.performance.log(arguments);
2728 }
2729 else {
2730 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
2731 module.debug.apply(console, arguments);
2732 }
2733 }
2734 },
2735 verbose: function() {
2736 if(!settings.silent && settings.verbose && settings.debug) {
2737 if(settings.performance) {
2738 module.performance.log(arguments);
2739 }
2740 else {
2741 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
2742 module.verbose.apply(console, arguments);
2743 }
2744 }
2745 },
2746 error: function() {
2747 if(!settings.silent) {
2748 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
2749 module.error.apply(console, arguments);
2750 }
2751 },
2752 performance: {
2753 log: function(message) {
2754 var
2755 currentTime,
2756 executionTime,
2757 previousTime
2758 ;
2759 if(settings.performance) {
2760 currentTime = new Date().getTime();
2761 previousTime = time || currentTime;
2762 executionTime = currentTime - previousTime;
2763 time = currentTime;
2764 performance.push({
2765 'Name' : message[0],
2766 'Arguments' : [].slice.call(message, 1) || '',
2767 'Element' : element,
2768 'Execution Time' : executionTime
2769 });
2770 }
2771 clearTimeout(module.performance.timer);
2772 module.performance.timer = setTimeout(module.performance.display, 500);
2773 },
2774 display: function() {
2775 var
2776 title = settings.name + ':',
2777 totalTime = 0
2778 ;
2779 time = false;
2780 clearTimeout(module.performance.timer);
2781 $.each(performance, function(index, data) {
2782 totalTime += data['Execution Time'];
2783 });
2784 title += ' ' + totalTime + 'ms';
2785 if(moduleSelector) {
2786 title += ' \'' + moduleSelector + '\'';
2787 }
2788 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
2789 console.groupCollapsed(title);
2790 if(console.table) {
2791 console.table(performance);
2792 }
2793 else {
2794 $.each(performance, function(index, data) {
2795 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
2796 });
2797 }
2798 console.groupEnd();
2799 }
2800 performance = [];
2801 }
2802 },
2803 invoke: function(query, passedArguments, context) {
2804 var
2805 object = instance,
2806 maxDepth,
2807 found,
2808 response
2809 ;
2810 passedArguments = passedArguments || queryArguments;
2811 context = element || context;
2812 if(typeof query == 'string' && object !== undefined) {
2813 query = query.split(/[\. ]/);
2814 maxDepth = query.length - 1;
2815 $.each(query, function(depth, value) {
2816 var camelCaseValue = (depth != maxDepth)
2817 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
2818 : query
2819 ;
2820 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
2821 object = object[camelCaseValue];
2822 }
2823 else if( object[camelCaseValue] !== undefined ) {
2824 found = object[camelCaseValue];
2825 return false;
2826 }
2827 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
2828 object = object[value];
2829 }
2830 else if( object[value] !== undefined ) {
2831 found = object[value];
2832 return false;
2833 }
2834 else {
2835 module.error(error.method, query);
2836 return false;
2837 }
2838 });
2839 }
2840 if ( $.isFunction( found ) ) {
2841 response = found.apply(context, passedArguments);
2842 }
2843 else if(found !== undefined) {
2844 response = found;
2845 }
2846 if($.isArray(returnedValue)) {
2847 returnedValue.push(response);
2848 }
2849 else if(returnedValue !== undefined) {
2850 returnedValue = [returnedValue, response];
2851 }
2852 else if(response !== undefined) {
2853 returnedValue = response;
2854 }
2855 return found;
2856 }
2857 };
2858
2859 if(methodInvoked) {
2860 if(instance === undefined) {
2861 module.initialize();
2862 }
2863 module.invoke(query);
2864 }
2865 else {
2866 if(instance !== undefined) {
2867 instance.invoke('destroy');
2868 }
2869 module.initialize();
2870 }
2871 })
2872 ;
2873
2874 return (returnedValue !== undefined)
2875 ? returnedValue
2876 : this
2877 ;
2878 };
2879
2880 $.fn.checkbox.settings = {
2881
2882 name : 'Checkbox',
2883 namespace : 'checkbox',
2884
2885 silent : false,
2886 debug : false,
2887 verbose : true,
2888 performance : true,
2889
2890 // delegated event context
2891 uncheckable : 'auto',
2892 fireOnInit : false,
2893
2894 onChange : function(){},
2895
2896 beforeChecked : function(){},
2897 beforeUnchecked : function(){},
2898 beforeDeterminate : function(){},
2899 beforeIndeterminate : function(){},
2900
2901 onChecked : function(){},
2902 onUnchecked : function(){},
2903
2904 onDeterminate : function() {},
2905 onIndeterminate : function() {},
2906
2907 onEnable : function(){},
2908 onDisable : function(){},
2909
2910 // preserve misspelled callbacks (will be removed in 3.0)
2911 onEnabled : function(){},
2912 onDisabled : function(){},
2913
2914 className : {
2915 checked : 'checked',
2916 indeterminate : 'indeterminate',
2917 disabled : 'disabled',
2918 hidden : 'hidden',
2919 radio : 'radio',
2920 readOnly : 'read-only'
2921 },
2922
2923 error : {
2924 method : 'The method you called is not defined'
2925 },
2926
2927 selector : {
2928 checkbox : '.ui.checkbox',
2929 label : 'label, .box',
2930 input : 'input[type="checkbox"], input[type="radio"]',
2931 link : 'a[href]'
2932 }
2933
2934 };
2935
2936 })( jQuery, window, document );
2937
2938 /*!
2939 * # Semantic UI 2.2.10 - Dropdown
2940 * http://github.com/semantic-org/semantic-ui/
2941 *
2942 *
2943 * Released under the MIT license
2944 * http://opensource.org/licenses/MIT
2945 *
2946 */
2947
2948 ;(function ($, window, document, undefined) {
2949
2950 "use strict";
2951
2952 window = (typeof window != 'undefined' && window.Math == Math)
2953 ? window
2954 : (typeof self != 'undefined' && self.Math == Math)
2955 ? self
2956 : Function('return this')()
2957 ;
2958
2959 $.fn.dropdown = function(parameters) {
2960 var
2961 $allModules = $(this),
2962 $document = $(document),
2963
2964 moduleSelector = $allModules.selector || '',
2965
2966 hasTouch = ('ontouchstart' in document.documentElement),
2967 time = new Date().getTime(),
2968 performance = [],
2969
2970 query = arguments[0],
2971 methodInvoked = (typeof query == 'string'),
2972 queryArguments = [].slice.call(arguments, 1),
2973 returnedValue
2974 ;
2975
2976 $allModules
2977 .each(function(elementIndex) {
2978 var
2979 settings = ( $.isPlainObject(parameters) )
2980 ? $.extend(true, {}, $.fn.dropdown.settings, parameters)
2981 : $.extend({}, $.fn.dropdown.settings),
2982
2983 className = settings.className,
2984 message = settings.message,
2985 fields = settings.fields,
2986 keys = settings.keys,
2987 metadata = settings.metadata,
2988 namespace = settings.namespace,
2989 regExp = settings.regExp,
2990 selector = settings.selector,
2991 error = settings.error,
2992 templates = settings.templates,
2993
2994 eventNamespace = '.' + namespace,
2995 moduleNamespace = 'module-' + namespace,
2996
2997 $module = $(this),
2998 $context = $(settings.context),
2999 $text = $module.find(selector.text),
3000 $search = $module.find(selector.search),
3001 $sizer = $module.find(selector.sizer),
3002 $input = $module.find(selector.input),
3003 $icon = $module.find(selector.icon),
3004
3005 $combo = ($module.prev().find(selector.text).length > 0)
3006 ? $module.prev().find(selector.text)
3007 : $module.prev(),
3008
3009 $menu = $module.children(selector.menu),
3010 $item = $menu.find(selector.item),
3011
3012 activated = false,
3013 itemActivated = false,
3014 internalChange = false,
3015 element = this,
3016 instance = $module.data(moduleNamespace),
3017
3018 initialLoad,
3019 pageLostFocus,
3020 willRefocus,
3021 elementNamespace,
3022 id,
3023 selectObserver,
3024 menuObserver,
3025 module
3026 ;
3027
3028 module = {
3029
3030 initialize: function() {
3031 module.debug('Initializing dropdown', settings);
3032
3033 if( module.is.alreadySetup() ) {
3034 module.setup.reference();
3035 }
3036 else {
3037 module.setup.layout();
3038 module.refreshData();
3039
3040 module.save.defaults();
3041 module.restore.