UNPKG

896 kBJavaScriptView Raw
1 /*
2 * # Fomantic UI - 2.7.2
3 * https://github.com/fomantic/Fomantic-UI
4 * http://fomantic-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.7.2 - 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$.isFunction = $.isFunction || function(obj) {
24 return typeof obj === "function" && typeof obj.nodeType !== "number";
25};
26
27$.site = $.fn.site = function(parameters) {
28 var
29 time = new Date().getTime(),
30 performance = [],
31
32 query = arguments[0],
33 methodInvoked = (typeof query == 'string'),
34 queryArguments = [].slice.call(arguments, 1),
35
36 settings = ( $.isPlainObject(parameters) )
37 ? $.extend(true, {}, $.site.settings, parameters)
38 : $.extend({}, $.site.settings),
39
40 namespace = settings.namespace,
41 error = settings.error,
42
43 eventNamespace = '.' + namespace,
44 moduleNamespace = 'module-' + namespace,
45
46 $document = $(document),
47 $module = $document,
48 element = this,
49 instance = $module.data(moduleNamespace),
50
51 module,
52 returnedValue
53 ;
54 module = {
55
56 initialize: function() {
57 module.instantiate();
58 },
59
60 instantiate: function() {
61 module.verbose('Storing instance of site', module);
62 instance = module;
63 $module
64 .data(moduleNamespace, module)
65 ;
66 },
67
68 normalize: function() {
69 module.fix.console();
70 module.fix.requestAnimationFrame();
71 },
72
73 fix: {
74 console: function() {
75 module.debug('Normalizing window.console');
76 if (console === undefined || console.log === undefined) {
77 module.verbose('Console not available, normalizing events');
78 module.disable.console();
79 }
80 if (typeof console.group == 'undefined' || typeof console.groupEnd == 'undefined' || typeof console.groupCollapsed == 'undefined') {
81 module.verbose('Console group not available, normalizing events');
82 window.console.group = function() {};
83 window.console.groupEnd = function() {};
84 window.console.groupCollapsed = function() {};
85 }
86 if (typeof console.markTimeline == 'undefined') {
87 module.verbose('Mark timeline not available, normalizing events');
88 window.console.markTimeline = function() {};
89 }
90 },
91 consoleClear: function() {
92 module.debug('Disabling programmatic console clearing');
93 window.console.clear = function() {};
94 },
95 requestAnimationFrame: function() {
96 module.debug('Normalizing requestAnimationFrame');
97 if(window.requestAnimationFrame === undefined) {
98 module.debug('RequestAnimationFrame not available, normalizing event');
99 window.requestAnimationFrame = window.requestAnimationFrame
100 || window.mozRequestAnimationFrame
101 || window.webkitRequestAnimationFrame
102 || window.msRequestAnimationFrame
103 || function(callback) { setTimeout(callback, 0); }
104 ;
105 }
106 }
107 },
108
109 moduleExists: function(name) {
110 return ($.fn[name] !== undefined && $.fn[name].settings !== undefined);
111 },
112
113 enabled: {
114 modules: function(modules) {
115 var
116 enabledModules = []
117 ;
118 modules = modules || settings.modules;
119 $.each(modules, function(index, name) {
120 if(module.moduleExists(name)) {
121 enabledModules.push(name);
122 }
123 });
124 return enabledModules;
125 }
126 },
127
128 disabled: {
129 modules: function(modules) {
130 var
131 disabledModules = []
132 ;
133 modules = modules || settings.modules;
134 $.each(modules, function(index, name) {
135 if(!module.moduleExists(name)) {
136 disabledModules.push(name);
137 }
138 });
139 return disabledModules;
140 }
141 },
142
143 change: {
144 setting: function(setting, value, modules, modifyExisting) {
145 modules = (typeof modules === 'string')
146 ? (modules === 'all')
147 ? settings.modules
148 : [modules]
149 : modules || settings.modules
150 ;
151 modifyExisting = (modifyExisting !== undefined)
152 ? modifyExisting
153 : true
154 ;
155 $.each(modules, function(index, name) {
156 var
157 namespace = (module.moduleExists(name))
158 ? $.fn[name].settings.namespace || false
159 : true,
160 $existingModules
161 ;
162 if(module.moduleExists(name)) {
163 module.verbose('Changing default setting', setting, value, name);
164 $.fn[name].settings[setting] = value;
165 if(modifyExisting && namespace) {
166 $existingModules = $(':data(module-' + namespace + ')');
167 if($existingModules.length > 0) {
168 module.verbose('Modifying existing settings', $existingModules);
169 $existingModules[name]('setting', setting, value);
170 }
171 }
172 }
173 });
174 },
175 settings: function(newSettings, modules, modifyExisting) {
176 modules = (typeof modules === 'string')
177 ? [modules]
178 : modules || settings.modules
179 ;
180 modifyExisting = (modifyExisting !== undefined)
181 ? modifyExisting
182 : true
183 ;
184 $.each(modules, function(index, name) {
185 var
186 $existingModules
187 ;
188 if(module.moduleExists(name)) {
189 module.verbose('Changing default setting', newSettings, name);
190 $.extend(true, $.fn[name].settings, newSettings);
191 if(modifyExisting && namespace) {
192 $existingModules = $(':data(module-' + namespace + ')');
193 if($existingModules.length > 0) {
194 module.verbose('Modifying existing settings', $existingModules);
195 $existingModules[name]('setting', newSettings);
196 }
197 }
198 }
199 });
200 }
201 },
202
203 enable: {
204 console: function() {
205 module.console(true);
206 },
207 debug: function(modules, modifyExisting) {
208 modules = modules || settings.modules;
209 module.debug('Enabling debug for modules', modules);
210 module.change.setting('debug', true, modules, modifyExisting);
211 },
212 verbose: function(modules, modifyExisting) {
213 modules = modules || settings.modules;
214 module.debug('Enabling verbose debug for modules', modules);
215 module.change.setting('verbose', true, modules, modifyExisting);
216 }
217 },
218 disable: {
219 console: function() {
220 module.console(false);
221 },
222 debug: function(modules, modifyExisting) {
223 modules = modules || settings.modules;
224 module.debug('Disabling debug for modules', modules);
225 module.change.setting('debug', false, modules, modifyExisting);
226 },
227 verbose: function(modules, modifyExisting) {
228 modules = modules || settings.modules;
229 module.debug('Disabling verbose debug for modules', modules);
230 module.change.setting('verbose', false, modules, modifyExisting);
231 }
232 },
233
234 console: function(enable) {
235 if(enable) {
236 if(instance.cache.console === undefined) {
237 module.error(error.console);
238 return;
239 }
240 module.debug('Restoring console function');
241 window.console = instance.cache.console;
242 }
243 else {
244 module.debug('Disabling console function');
245 instance.cache.console = window.console;
246 window.console = {
247 clear : function(){},
248 error : function(){},
249 group : function(){},
250 groupCollapsed : function(){},
251 groupEnd : function(){},
252 info : function(){},
253 log : function(){},
254 markTimeline : function(){},
255 warn : function(){}
256 };
257 }
258 },
259
260 destroy: function() {
261 module.verbose('Destroying previous site for', $module);
262 $module
263 .removeData(moduleNamespace)
264 ;
265 },
266
267 cache: {},
268
269 setting: function(name, value) {
270 if( $.isPlainObject(name) ) {
271 $.extend(true, settings, name);
272 }
273 else if(value !== undefined) {
274 settings[name] = value;
275 }
276 else {
277 return settings[name];
278 }
279 },
280 internal: function(name, value) {
281 if( $.isPlainObject(name) ) {
282 $.extend(true, module, name);
283 }
284 else if(value !== undefined) {
285 module[name] = value;
286 }
287 else {
288 return module[name];
289 }
290 },
291 debug: function() {
292 if(settings.debug) {
293 if(settings.performance) {
294 module.performance.log(arguments);
295 }
296 else {
297 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
298 module.debug.apply(console, arguments);
299 }
300 }
301 },
302 verbose: function() {
303 if(settings.verbose && settings.debug) {
304 if(settings.performance) {
305 module.performance.log(arguments);
306 }
307 else {
308 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
309 module.verbose.apply(console, arguments);
310 }
311 }
312 },
313 error: function() {
314 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
315 module.error.apply(console, arguments);
316 },
317 performance: {
318 log: function(message) {
319 var
320 currentTime,
321 executionTime,
322 previousTime
323 ;
324 if(settings.performance) {
325 currentTime = new Date().getTime();
326 previousTime = time || currentTime;
327 executionTime = currentTime - previousTime;
328 time = currentTime;
329 performance.push({
330 'Element' : element,
331 'Name' : message[0],
332 'Arguments' : [].slice.call(message, 1) || '',
333 'Execution Time' : executionTime
334 });
335 }
336 clearTimeout(module.performance.timer);
337 module.performance.timer = setTimeout(module.performance.display, 500);
338 },
339 display: function() {
340 var
341 title = settings.name + ':',
342 totalTime = 0
343 ;
344 time = false;
345 clearTimeout(module.performance.timer);
346 $.each(performance, function(index, data) {
347 totalTime += data['Execution Time'];
348 });
349 title += ' ' + totalTime + 'ms';
350 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
351 console.groupCollapsed(title);
352 if(console.table) {
353 console.table(performance);
354 }
355 else {
356 $.each(performance, function(index, data) {
357 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
358 });
359 }
360 console.groupEnd();
361 }
362 performance = [];
363 }
364 },
365 invoke: function(query, passedArguments, context) {
366 var
367 object = instance,
368 maxDepth,
369 found,
370 response
371 ;
372 passedArguments = passedArguments || queryArguments;
373 context = element || context;
374 if(typeof query == 'string' && object !== undefined) {
375 query = query.split(/[\. ]/);
376 maxDepth = query.length - 1;
377 $.each(query, function(depth, value) {
378 var camelCaseValue = (depth != maxDepth)
379 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
380 : query
381 ;
382 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
383 object = object[camelCaseValue];
384 }
385 else if( object[camelCaseValue] !== undefined ) {
386 found = object[camelCaseValue];
387 return false;
388 }
389 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
390 object = object[value];
391 }
392 else if( object[value] !== undefined ) {
393 found = object[value];
394 return false;
395 }
396 else {
397 module.error(error.method, query);
398 return false;
399 }
400 });
401 }
402 if ( $.isFunction( found ) ) {
403 response = found.apply(context, passedArguments);
404 }
405 else if(found !== undefined) {
406 response = found;
407 }
408 if(Array.isArray(returnedValue)) {
409 returnedValue.push(response);
410 }
411 else if(returnedValue !== undefined) {
412 returnedValue = [returnedValue, response];
413 }
414 else if(response !== undefined) {
415 returnedValue = response;
416 }
417 return found;
418 }
419 };
420
421 if(methodInvoked) {
422 if(instance === undefined) {
423 module.initialize();
424 }
425 module.invoke(query);
426 }
427 else {
428 if(instance !== undefined) {
429 module.destroy();
430 }
431 module.initialize();
432 }
433 return (returnedValue !== undefined)
434 ? returnedValue
435 : this
436 ;
437};
438
439$.site.settings = {
440
441 name : 'Site',
442 namespace : 'site',
443
444 error : {
445 console : 'Console cannot be restored, most likely it was overwritten outside of module',
446 method : 'The method you called is not defined.'
447 },
448
449 debug : false,
450 verbose : false,
451 performance : true,
452
453 modules: [
454 'accordion',
455 'api',
456 'calendar',
457 'checkbox',
458 'dimmer',
459 'dropdown',
460 'embed',
461 'form',
462 'modal',
463 'nag',
464 'popup',
465 'slider',
466 'rating',
467 'shape',
468 'sidebar',
469 'state',
470 'sticky',
471 'tab',
472 'toast',
473 'transition',
474 'visibility',
475 'visit'
476 ],
477
478 siteNamespace : 'site',
479 namespaceStub : {
480 cache : {},
481 config : {},
482 sections : {},
483 section : {},
484 utilities : {}
485 }
486
487};
488
489// allows for selection of elements with data attributes
490$.extend($.expr[ ":" ], {
491 data: ($.expr.createPseudo)
492 ? $.expr.createPseudo(function(dataName) {
493 return function(elem) {
494 return !!$.data(elem, dataName);
495 };
496 })
497 : function(elem, i, match) {
498 // support: jQuery < 1.8
499 return !!$.data(elem, match[ 3 ]);
500 }
501});
502
503
504})( jQuery, window, document );
505
506/*!
507 * # Semantic UI 2.7.2 - Form Validation
508 * http://github.com/semantic-org/semantic-ui/
509 *
510 *
511 * Released under the MIT license
512 * http://opensource.org/licenses/MIT
513 *
514 */
515
516;(function ($, window, document, undefined) {
517
518'use strict';
519
520$.isFunction = $.isFunction || function(obj) {
521 return typeof obj === "function" && typeof obj.nodeType !== "number";
522};
523
524window = (typeof window != 'undefined' && window.Math == Math)
525 ? window
526 : (typeof self != 'undefined' && self.Math == Math)
527 ? self
528 : Function('return this')()
529;
530
531$.fn.form = function(parameters) {
532 var
533 $allModules = $(this),
534 moduleSelector = $allModules.selector || '',
535
536 time = new Date().getTime(),
537 performance = [],
538
539 query = arguments[0],
540 legacyParameters = arguments[1],
541 methodInvoked = (typeof query == 'string'),
542 queryArguments = [].slice.call(arguments, 1),
543 returnedValue
544 ;
545 $allModules
546 .each(function() {
547 var
548 $module = $(this),
549 element = this,
550
551 formErrors = [],
552 keyHeldDown = false,
553
554 // set at run-time
555 $field,
556 $group,
557 $message,
558 $prompt,
559 $submit,
560 $clear,
561 $reset,
562
563 settings,
564 validation,
565
566 metadata,
567 selector,
568 className,
569 regExp,
570 error,
571
572 namespace,
573 moduleNamespace,
574 eventNamespace,
575
576 instance,
577 module
578 ;
579
580 module = {
581
582 initialize: function() {
583
584 // settings grabbed at run time
585 module.get.settings();
586 if(methodInvoked) {
587 if(instance === undefined) {
588 module.instantiate();
589 }
590 module.invoke(query);
591 }
592 else {
593 if(instance !== undefined) {
594 instance.invoke('destroy');
595 }
596 module.verbose('Initializing form validation', $module, settings);
597 module.bindEvents();
598 module.set.defaults();
599 module.instantiate();
600 }
601 },
602
603 instantiate: function() {
604 module.verbose('Storing instance of module', module);
605 instance = module;
606 $module
607 .data(moduleNamespace, module)
608 ;
609 },
610
611 destroy: function() {
612 module.verbose('Destroying previous module', instance);
613 module.removeEvents();
614 $module
615 .removeData(moduleNamespace)
616 ;
617 },
618
619 refresh: function() {
620 module.verbose('Refreshing selector cache');
621 $field = $module.find(selector.field);
622 $group = $module.find(selector.group);
623 $message = $module.find(selector.message);
624 $prompt = $module.find(selector.prompt);
625
626 $submit = $module.find(selector.submit);
627 $clear = $module.find(selector.clear);
628 $reset = $module.find(selector.reset);
629 },
630
631 submit: function() {
632 module.verbose('Submitting form', $module);
633 $module
634 .submit()
635 ;
636 },
637
638 attachEvents: function(selector, action) {
639 action = action || 'submit';
640 $(selector)
641 .on('click' + eventNamespace, function(event) {
642 module[action]();
643 event.preventDefault();
644 })
645 ;
646 },
647
648 bindEvents: function() {
649 module.verbose('Attaching form events');
650 $module
651 .on('submit' + eventNamespace, module.validate.form)
652 .on('blur' + eventNamespace, selector.field, module.event.field.blur)
653 .on('click' + eventNamespace, selector.submit, module.submit)
654 .on('click' + eventNamespace, selector.reset, module.reset)
655 .on('click' + eventNamespace, selector.clear, module.clear)
656 ;
657 if(settings.keyboardShortcuts) {
658 $module
659 .on('keydown' + eventNamespace, selector.field, module.event.field.keydown)
660 ;
661 }
662 $field
663 .each(function() {
664 var
665 $input = $(this),
666 type = $input.prop('type'),
667 inputEvent = module.get.changeEvent(type, $input)
668 ;
669 $(this)
670 .on(inputEvent + eventNamespace, module.event.field.change)
671 ;
672 })
673 ;
674 },
675
676 clear: function() {
677 $field
678 .each(function () {
679 var
680 $field = $(this),
681 $element = $field.parent(),
682 $fieldGroup = $field.closest($group),
683 $prompt = $fieldGroup.find(selector.prompt),
684 defaultValue = $field.data(metadata.defaultValue) || '',
685 isCheckbox = $element.is(selector.uiCheckbox),
686 isDropdown = $element.is(selector.uiDropdown),
687 isErrored = $fieldGroup.hasClass(className.error)
688 ;
689 if(isErrored) {
690 module.verbose('Resetting error on field', $fieldGroup);
691 $fieldGroup.removeClass(className.error);
692 $prompt.remove();
693 }
694 if(isDropdown) {
695 module.verbose('Resetting dropdown value', $element, defaultValue);
696 $element.dropdown('clear');
697 }
698 else if(isCheckbox) {
699 $field.prop('checked', false);
700 }
701 else {
702 module.verbose('Resetting field value', $field, defaultValue);
703 $field.val('');
704 }
705 })
706 ;
707 },
708
709 reset: function() {
710 $field
711 .each(function () {
712 var
713 $field = $(this),
714 $element = $field.parent(),
715 $fieldGroup = $field.closest($group),
716 $prompt = $fieldGroup.find(selector.prompt),
717 defaultValue = $field.data(metadata.defaultValue),
718 isCheckbox = $element.is(selector.uiCheckbox),
719 isDropdown = $element.is(selector.uiDropdown),
720 isErrored = $fieldGroup.hasClass(className.error)
721 ;
722 if(defaultValue === undefined) {
723 return;
724 }
725 if(isErrored) {
726 module.verbose('Resetting error on field', $fieldGroup);
727 $fieldGroup.removeClass(className.error);
728 $prompt.remove();
729 }
730 if(isDropdown) {
731 module.verbose('Resetting dropdown value', $element, defaultValue);
732 $element.dropdown('restore defaults');
733 }
734 else if(isCheckbox) {
735 module.verbose('Resetting checkbox value', $element, defaultValue);
736 $field.prop('checked', defaultValue);
737 }
738 else {
739 module.verbose('Resetting field value', $field, defaultValue);
740 $field.val(defaultValue);
741 }
742 })
743 ;
744 },
745
746 determine: {
747 isValid: function() {
748 var
749 allValid = true
750 ;
751 $.each(validation, function(fieldName, field) {
752 if( !( module.validate.field(field, fieldName, true) ) ) {
753 allValid = false;
754 }
755 });
756 return allValid;
757 }
758 },
759
760 is: {
761 bracketedRule: function(rule) {
762 return (rule.type && rule.type.match(settings.regExp.bracket));
763 },
764 shorthandFields: function(fields) {
765 var
766 fieldKeys = Object.keys(fields),
767 firstRule = fields[fieldKeys[0]]
768 ;
769 return module.is.shorthandRules(firstRule);
770 },
771 // duck type rule test
772 shorthandRules: function(rules) {
773 return (typeof rules == 'string' || Array.isArray(rules));
774 },
775 empty: function($field) {
776 if(!$field || $field.length === 0) {
777 return true;
778 }
779 else if($field.is(selector.checkbox)) {
780 return !$field.is(':checked');
781 }
782 else {
783 return module.is.blank($field);
784 }
785 },
786 blank: function($field) {
787 return $.trim($field.val()) === '';
788 },
789 valid: function(field) {
790 var
791 allValid = true
792 ;
793 if(field) {
794 module.verbose('Checking if field is valid', field);
795 return module.validate.field(validation[field], field, false);
796 }
797 else {
798 module.verbose('Checking if form is valid');
799 $.each(validation, function(fieldName, field) {
800 if( !module.is.valid(fieldName) ) {
801 allValid = false;
802 }
803 });
804 return allValid;
805 }
806 }
807 },
808
809 removeEvents: function() {
810 $module
811 .off(eventNamespace)
812 ;
813 $field
814 .off(eventNamespace)
815 ;
816 $submit
817 .off(eventNamespace)
818 ;
819 $field
820 .off(eventNamespace)
821 ;
822 },
823
824 event: {
825 field: {
826 keydown: function(event) {
827 var
828 $field = $(this),
829 key = event.which,
830 isInput = $field.is(selector.input),
831 isCheckbox = $field.is(selector.checkbox),
832 isInDropdown = ($field.closest(selector.uiDropdown).length > 0),
833 keyCode = {
834 enter : 13,
835 escape : 27
836 }
837 ;
838 if( key == keyCode.escape) {
839 module.verbose('Escape key pressed blurring field');
840 $field
841 .blur()
842 ;
843 }
844 if(!event.ctrlKey && key == keyCode.enter && isInput && !isInDropdown && !isCheckbox) {
845 if(!keyHeldDown) {
846 $field
847 .one('keyup' + eventNamespace, module.event.field.keyup)
848 ;
849 module.submit();
850 module.debug('Enter pressed on input submitting form');
851 }
852 keyHeldDown = true;
853 }
854 },
855 keyup: function() {
856 keyHeldDown = false;
857 },
858 blur: function(event) {
859 var
860 $field = $(this),
861 $fieldGroup = $field.closest($group),
862 validationRules = module.get.validation($field)
863 ;
864 if( $fieldGroup.hasClass(className.error) ) {
865 module.debug('Revalidating field', $field, validationRules);
866 if(validationRules) {
867 module.validate.field( validationRules );
868 }
869 }
870 else if(settings.on == 'blur') {
871 if(validationRules) {
872 module.validate.field( validationRules );
873 }
874 }
875 },
876 change: function(event) {
877 var
878 $field = $(this),
879 $fieldGroup = $field.closest($group),
880 validationRules = module.get.validation($field)
881 ;
882 if(validationRules && (settings.on == 'change' || ( $fieldGroup.hasClass(className.error) && settings.revalidate) )) {
883 clearTimeout(module.timer);
884 module.timer = setTimeout(function() {
885 module.debug('Revalidating field', $field, module.get.validation($field));
886 module.validate.field( validationRules );
887 }, settings.delay);
888 }
889 }
890 }
891
892 },
893
894 get: {
895 ancillaryValue: function(rule) {
896 if(!rule.type || (!rule.value && !module.is.bracketedRule(rule))) {
897 return false;
898 }
899 return (rule.value !== undefined)
900 ? rule.value
901 : rule.type.match(settings.regExp.bracket)[1] + ''
902 ;
903 },
904 ruleName: function(rule) {
905 if( module.is.bracketedRule(rule) ) {
906 return rule.type.replace(rule.type.match(settings.regExp.bracket)[0], '');
907 }
908 return rule.type;
909 },
910 changeEvent: function(type, $input) {
911 if(type == 'checkbox' || type == 'radio' || type == 'hidden' || $input.is('select')) {
912 return 'change';
913 }
914 else {
915 return module.get.inputEvent();
916 }
917 },
918 inputEvent: function() {
919 return (document.createElement('input').oninput !== undefined)
920 ? 'input'
921 : (document.createElement('input').onpropertychange !== undefined)
922 ? 'propertychange'
923 : 'keyup'
924 ;
925 },
926 fieldsFromShorthand: function(fields) {
927 var
928 fullFields = {}
929 ;
930 $.each(fields, function(name, rules) {
931 if(typeof rules == 'string') {
932 rules = [rules];
933 }
934 fullFields[name] = {
935 rules: []
936 };
937 $.each(rules, function(index, rule) {
938 fullFields[name].rules.push({ type: rule });
939 });
940 });
941 return fullFields;
942 },
943 prompt: function(rule, field) {
944 var
945 ruleName = module.get.ruleName(rule),
946 ancillary = module.get.ancillaryValue(rule),
947 $field = module.get.field(field.identifier),
948 value = $field.val(),
949 prompt = $.isFunction(rule.prompt)
950 ? rule.prompt(value)
951 : rule.prompt || settings.prompt[ruleName] || settings.text.unspecifiedRule,
952 requiresValue = (prompt.search('{value}') !== -1),
953 requiresName = (prompt.search('{name}') !== -1),
954 $label,
955 name
956 ;
957 if(requiresValue) {
958 prompt = prompt.replace('{value}', $field.val());
959 }
960 if(requiresName) {
961 $label = $field.closest(selector.group).find('label').eq(0);
962 name = ($label.length == 1)
963 ? $label.text()
964 : $field.prop('placeholder') || settings.text.unspecifiedField
965 ;
966 prompt = prompt.replace('{name}', name);
967 }
968 prompt = prompt.replace('{identifier}', field.identifier);
969 prompt = prompt.replace('{ruleValue}', ancillary);
970 if(!rule.prompt) {
971 module.verbose('Using default validation prompt for type', prompt, ruleName);
972 }
973 return prompt;
974 },
975 settings: function() {
976 if($.isPlainObject(parameters)) {
977 var
978 keys = Object.keys(parameters),
979 isLegacySettings = (keys.length > 0)
980 ? (parameters[keys[0]].identifier !== undefined && parameters[keys[0]].rules !== undefined)
981 : false,
982 ruleKeys
983 ;
984 if(isLegacySettings) {
985 // 1.x (ducktyped)
986 settings = $.extend(true, {}, $.fn.form.settings, legacyParameters);
987 validation = $.extend({}, $.fn.form.settings.defaults, parameters);
988 module.error(settings.error.oldSyntax, element);
989 module.verbose('Extending settings from legacy parameters', validation, settings);
990 }
991 else {
992 // 2.x
993 if(parameters.fields && module.is.shorthandFields(parameters.fields)) {
994 parameters.fields = module.get.fieldsFromShorthand(parameters.fields);
995 }
996 settings = $.extend(true, {}, $.fn.form.settings, parameters);
997 validation = $.extend({}, $.fn.form.settings.defaults, settings.fields);
998 module.verbose('Extending settings', validation, settings);
999 }
1000 }
1001 else {
1002 settings = $.fn.form.settings;
1003 validation = $.fn.form.settings.defaults;
1004 module.verbose('Using default form validation', validation, settings);
1005 }
1006
1007 // shorthand
1008 namespace = settings.namespace;
1009 metadata = settings.metadata;
1010 selector = settings.selector;
1011 className = settings.className;
1012 regExp = settings.regExp;
1013 error = settings.error;
1014 moduleNamespace = 'module-' + namespace;
1015 eventNamespace = '.' + namespace;
1016
1017 // grab instance
1018 instance = $module.data(moduleNamespace);
1019
1020 // refresh selector cache
1021 module.refresh();
1022 },
1023 field: function(identifier) {
1024 module.verbose('Finding field with identifier', identifier);
1025 identifier = module.escape.string(identifier);
1026 var t;
1027 if((t=$field.filter('#' + identifier)).length > 0 ) {
1028 return t;
1029 }
1030 if((t=$field.filter('[name="' + identifier +'"]')).length > 0 ) {
1031 return t;
1032 }
1033 if((t=$field.filter('[name="' + identifier +'[]"]')).length > 0 ) {
1034 return t;
1035 }
1036 if((t=$field.filter('[data-' + metadata.validate + '="'+ identifier +'"]')).length > 0 ) {
1037 return t;
1038 }
1039 return $('<input/>');
1040 },
1041 fields: function(fields) {
1042 var
1043 $fields = $()
1044 ;
1045 $.each(fields, function(index, name) {
1046 $fields = $fields.add( module.get.field(name) );
1047 });
1048 return $fields;
1049 },
1050 validation: function($field) {
1051 var
1052 fieldValidation,
1053 identifier
1054 ;
1055 if(!validation) {
1056 return false;
1057 }
1058 $.each(validation, function(fieldName, field) {
1059 identifier = field.identifier || fieldName;
1060 $.each(module.get.field(identifier), function(index, groupField) {
1061 if(groupField == $field[0]) {
1062 field.identifier = identifier;
1063 fieldValidation = field;
1064 return false;
1065 }
1066 });
1067 });
1068 return fieldValidation || false;
1069 },
1070 value: function (field) {
1071 var
1072 fields = [],
1073 results
1074 ;
1075 fields.push(field);
1076 results = module.get.values.call(element, fields);
1077 return results[field];
1078 },
1079 values: function (fields) {
1080 var
1081 $fields = Array.isArray(fields)
1082 ? module.get.fields(fields)
1083 : $field,
1084 values = {}
1085 ;
1086 $fields.each(function(index, field) {
1087 var
1088 $field = $(field),
1089 type = $field.prop('type'),
1090 name = $field.prop('name'),
1091 value = $field.val(),
1092 isCheckbox = $field.is(selector.checkbox),
1093 isRadio = $field.is(selector.radio),
1094 isMultiple = (name.indexOf('[]') !== -1),
1095 isChecked = (isCheckbox)
1096 ? $field.is(':checked')
1097 : false
1098 ;
1099 if(name) {
1100 if(isMultiple) {
1101 name = name.replace('[]', '');
1102 if(!values[name]) {
1103 values[name] = [];
1104 }
1105 if(isCheckbox) {
1106 if(isChecked) {
1107 values[name].push(value || true);
1108 }
1109 else {
1110 values[name].push(false);
1111 }
1112 }
1113 else {
1114 values[name].push(value);
1115 }
1116 }
1117 else {
1118 if(isRadio) {
1119 if(values[name] === undefined || values[name] == false) {
1120 values[name] = (isChecked)
1121 ? value || true
1122 : false
1123 ;
1124 }
1125 }
1126 else if(isCheckbox) {
1127 if(isChecked) {
1128 values[name] = value || true;
1129 }
1130 else {
1131 values[name] = false;
1132 }
1133 }
1134 else {
1135 values[name] = value;
1136 }
1137 }
1138 }
1139 });
1140 return values;
1141 }
1142 },
1143
1144 has: {
1145
1146 field: function(identifier) {
1147 module.verbose('Checking for existence of a field with identifier', identifier);
1148 identifier = module.escape.string(identifier);
1149 if(typeof identifier !== 'string') {
1150 module.error(error.identifier, identifier);
1151 }
1152 if($field.filter('#' + identifier).length > 0 ) {
1153 return true;
1154 }
1155 else if( $field.filter('[name="' + identifier +'"]').length > 0 ) {
1156 return true;
1157 }
1158 else if( $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]').length > 0 ) {
1159 return true;
1160 }
1161 return false;
1162 }
1163
1164 },
1165
1166 escape: {
1167 string: function(text) {
1168 text = String(text);
1169 return text.replace(regExp.escape, '\\$&');
1170 }
1171 },
1172
1173 add: {
1174 // alias
1175 rule: function(name, rules) {
1176 module.add.field(name, rules);
1177 },
1178 field: function(name, rules) {
1179 var
1180 newValidation = {}
1181 ;
1182 if(module.is.shorthandRules(rules)) {
1183 rules = Array.isArray(rules)
1184 ? rules
1185 : [rules]
1186 ;
1187 newValidation[name] = {
1188 rules: []
1189 };
1190 $.each(rules, function(index, rule) {
1191 newValidation[name].rules.push({ type: rule });
1192 });
1193 }
1194 else {
1195 newValidation[name] = rules;
1196 }
1197 validation = $.extend({}, validation, newValidation);
1198 module.debug('Adding rules', newValidation, validation);
1199 },
1200 fields: function(fields) {
1201 var
1202 newValidation
1203 ;
1204 if(fields && module.is.shorthandFields(fields)) {
1205 newValidation = module.get.fieldsFromShorthand(fields);
1206 }
1207 else {
1208 newValidation = fields;
1209 }
1210 validation = $.extend({}, validation, newValidation);
1211 },
1212 prompt: function(identifier, errors, internal) {
1213 var
1214 $field = module.get.field(identifier),
1215 $fieldGroup = $field.closest($group),
1216 $prompt = $fieldGroup.children(selector.prompt),
1217 promptExists = ($prompt.length !== 0)
1218 ;
1219 errors = (typeof errors == 'string')
1220 ? [errors]
1221 : errors
1222 ;
1223 module.verbose('Adding field error state', identifier);
1224 if(!internal) {
1225 $fieldGroup
1226 .addClass(className.error)
1227 ;
1228 }
1229 if(settings.inline) {
1230 if(!promptExists) {
1231 $prompt = settings.templates.prompt(errors);
1232 $prompt
1233 .appendTo($fieldGroup)
1234 ;
1235 }
1236 $prompt
1237 .html(errors[0])
1238 ;
1239 if(!promptExists) {
1240 if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
1241 module.verbose('Displaying error with css transition', settings.transition);
1242 $prompt.transition(settings.transition + ' in', settings.duration);
1243 }
1244 else {
1245 module.verbose('Displaying error with fallback javascript animation');
1246 $prompt
1247 .fadeIn(settings.duration)
1248 ;
1249 }
1250 }
1251 else {
1252 module.verbose('Inline errors are disabled, no inline error added', identifier);
1253 }
1254 }
1255 },
1256 errors: function(errors) {
1257 module.debug('Adding form error messages', errors);
1258 module.set.error();
1259 $message
1260 .html( settings.templates.error(errors) )
1261 ;
1262 }
1263 },
1264
1265 remove: {
1266 rule: function(field, rule) {
1267 var
1268 rules = Array.isArray(rule)
1269 ? rule
1270 : [rule]
1271 ;
1272 if(rule == undefined) {
1273 module.debug('Removed all rules');
1274 validation[field].rules = [];
1275 return;
1276 }
1277 if(validation[field] == undefined || !Array.isArray(validation[field].rules)) {
1278 return;
1279 }
1280 $.each(validation[field].rules, function(index, rule) {
1281 if(rules.indexOf(rule.type) !== -1) {
1282 module.debug('Removed rule', rule.type);
1283 validation[field].rules.splice(index, 1);
1284 }
1285 });
1286 },
1287 field: function(field) {
1288 var
1289 fields = Array.isArray(field)
1290 ? field
1291 : [field]
1292 ;
1293 $.each(fields, function(index, field) {
1294 module.remove.rule(field);
1295 });
1296 },
1297 // alias
1298 rules: function(field, rules) {
1299 if(Array.isArray(field)) {
1300 $.each(fields, function(index, field) {
1301 module.remove.rule(field, rules);
1302 });
1303 }
1304 else {
1305 module.remove.rule(field, rules);
1306 }
1307 },
1308 fields: function(fields) {
1309 module.remove.field(fields);
1310 },
1311 prompt: function(identifier) {
1312 var
1313 $field = module.get.field(identifier),
1314 $fieldGroup = $field.closest($group),
1315 $prompt = $fieldGroup.children(selector.prompt)
1316 ;
1317 $fieldGroup
1318 .removeClass(className.error)
1319 ;
1320 if(settings.inline && $prompt.is(':visible')) {
1321 module.verbose('Removing prompt for field', identifier);
1322 if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
1323 $prompt.transition(settings.transition + ' out', settings.duration, function() {
1324 $prompt.remove();
1325 });
1326 }
1327 else {
1328 $prompt
1329 .fadeOut(settings.duration, function(){
1330 $prompt.remove();
1331 })
1332 ;
1333 }
1334 }
1335 }
1336 },
1337
1338 set: {
1339 success: function() {
1340 $module
1341 .removeClass(className.error)
1342 .addClass(className.success)
1343 ;
1344 },
1345 defaults: function () {
1346 $field
1347 .each(function () {
1348 var
1349 $field = $(this),
1350 isCheckbox = ($field.filter(selector.checkbox).length > 0),
1351 value = (isCheckbox)
1352 ? $field.is(':checked')
1353 : $field.val()
1354 ;
1355 $field.data(metadata.defaultValue, value);
1356 })
1357 ;
1358 },
1359 error: function() {
1360 $module
1361 .removeClass(className.success)
1362 .addClass(className.error)
1363 ;
1364 },
1365 value: function (field, value) {
1366 var
1367 fields = {}
1368 ;
1369 fields[field] = value;
1370 return module.set.values.call(element, fields);
1371 },
1372 values: function (fields) {
1373 if($.isEmptyObject(fields)) {
1374 return;
1375 }
1376 $.each(fields, function(key, value) {
1377 var
1378 $field = module.get.field(key),
1379 $element = $field.parent(),
1380 isMultiple = Array.isArray(value),
1381 isCheckbox = $element.is(selector.uiCheckbox),
1382 isDropdown = $element.is(selector.uiDropdown),
1383 isRadio = ($field.is(selector.radio) && isCheckbox),
1384 fieldExists = ($field.length > 0),
1385 $multipleField
1386 ;
1387 if(fieldExists) {
1388 if(isMultiple && isCheckbox) {
1389 module.verbose('Selecting multiple', value, $field);
1390 $element.checkbox('uncheck');
1391 $.each(value, function(index, value) {
1392 $multipleField = $field.filter('[value="' + value + '"]');
1393 $element = $multipleField.parent();
1394 if($multipleField.length > 0) {
1395 $element.checkbox('check');
1396 }
1397 });
1398 }
1399 else if(isRadio) {
1400 module.verbose('Selecting radio value', value, $field);
1401 $field.filter('[value="' + value + '"]')
1402 .parent(selector.uiCheckbox)
1403 .checkbox('check')
1404 ;
1405 }
1406 else if(isCheckbox) {
1407 module.verbose('Setting checkbox value', value, $element);
1408 if(value === true) {
1409 $element.checkbox('check');
1410 }
1411 else {
1412 $element.checkbox('uncheck');
1413 }
1414 }
1415 else if(isDropdown) {
1416 module.verbose('Setting dropdown value', value, $element);
1417 $element.dropdown('set selected', value);
1418 }
1419 else {
1420 module.verbose('Setting field value', value, $field);
1421 $field.val(value);
1422 }
1423 }
1424 });
1425 }
1426 },
1427
1428 validate: {
1429
1430 form: function(event, ignoreCallbacks) {
1431 var
1432 values = module.get.values(),
1433 apiRequest
1434 ;
1435
1436 // input keydown event will fire submit repeatedly by browser default
1437 if(keyHeldDown) {
1438 return false;
1439 }
1440
1441 // reset errors
1442 formErrors = [];
1443 if( module.determine.isValid() ) {
1444 module.debug('Form has no validation errors, submitting');
1445 module.set.success();
1446 if(ignoreCallbacks !== true) {
1447 return settings.onSuccess.call(element, event, values);
1448 }
1449 }
1450 else {
1451 module.debug('Form has errors');
1452 module.set.error();
1453 if(!settings.inline) {
1454 module.add.errors(formErrors);
1455 }
1456 // prevent ajax submit
1457 if($module.data('moduleApi') !== undefined) {
1458 event.stopImmediatePropagation();
1459 }
1460 if(ignoreCallbacks !== true) {
1461 return settings.onFailure.call(element, formErrors, values);
1462 }
1463 }
1464 },
1465
1466 // takes a validation object and returns whether field passes validation
1467 field: function(field, fieldName, showErrors) {
1468 showErrors = (showErrors !== undefined)
1469 ? showErrors
1470 : true
1471 ;
1472 if(typeof field == 'string') {
1473 module.verbose('Validating field', field);
1474 fieldName = field;
1475 field = validation[field];
1476 }
1477 var
1478 identifier = field.identifier || fieldName,
1479 $field = module.get.field(identifier),
1480 $dependsField = (field.depends)
1481 ? module.get.field(field.depends)
1482 : false,
1483 fieldValid = true,
1484 fieldErrors = []
1485 ;
1486 if(!field.identifier) {
1487 module.debug('Using field name as identifier', identifier);
1488 field.identifier = identifier;
1489 }
1490 var isDisabled = true;
1491 $.each($field, function(){
1492 if(!$(this).prop('disabled')) {
1493 isDisabled = false;
1494 return false;
1495 }
1496 });
1497 if(isDisabled) {
1498 module.debug('Field is disabled. Skipping', identifier);
1499 }
1500 else if(field.optional && module.is.blank($field)){
1501 module.debug('Field is optional and blank. Skipping', identifier);
1502 }
1503 else if(field.depends && module.is.empty($dependsField)) {
1504 module.debug('Field depends on another value that is not present or empty. Skipping', $dependsField);
1505 }
1506 else if(field.rules !== undefined) {
1507 $field.closest($group).removeClass(className.error);
1508 $.each(field.rules, function(index, rule) {
1509 if( module.has.field(identifier)) {
1510 var invalidFields = module.validate.rule(field, rule,true) || [];
1511 if (invalidFields.length>0){
1512 module.debug('Field is invalid', identifier, rule.type);
1513 fieldErrors.push(module.get.prompt(rule, field));
1514 fieldValid = false;
1515 if(showErrors){
1516 $(invalidFields).closest($group).addClass(className.error);
1517 }
1518 }
1519 }
1520 });
1521 }
1522 if(fieldValid) {
1523 if(showErrors) {
1524 module.remove.prompt(identifier, fieldErrors);
1525 settings.onValid.call($field);
1526 }
1527 }
1528 else {
1529 if(showErrors) {
1530 formErrors = formErrors.concat(fieldErrors);
1531 module.add.prompt(identifier, fieldErrors, true);
1532 settings.onInvalid.call($field, fieldErrors);
1533 }
1534 return false;
1535 }
1536 return true;
1537 },
1538
1539 // takes validation rule and returns whether field passes rule
1540 rule: function(field, rule, internal) {
1541 var
1542 $field = module.get.field(field.identifier),
1543 type = rule.type,
1544 ancillary = module.get.ancillaryValue(rule),
1545 ruleName = module.get.ruleName(rule),
1546 ruleFunction = settings.rules[ruleName],
1547 invalidFields = [],
1548 isRadio = $field.is(selector.radio),
1549 isValid = function(field){
1550 var value = (isRadio ? $(field).filter(':checked').val() : $(field).val());
1551 // cast to string avoiding encoding special values
1552 value = (value === undefined || value === '' || value === null)
1553 ? ''
1554 : (settings.shouldTrim) ? $.trim(value + '') : String(value + '')
1555 ;
1556 return ruleFunction.call(field, value, ancillary);
1557 }
1558 ;
1559 if( !$.isFunction(ruleFunction) ) {
1560 module.error(error.noRule, ruleName);
1561 return;
1562 }
1563 if(isRadio) {
1564 if (!isValid($field)) {
1565 invalidFields = $field;
1566 }
1567 } else {
1568 $.each($field, function (index, field) {
1569 if (!isValid(field)) {
1570 invalidFields.push(field);
1571 }
1572 });
1573 }
1574 return internal ? invalidFields : !(invalidFields.length>0);
1575 }
1576 },
1577
1578 setting: function(name, value) {
1579 if( $.isPlainObject(name) ) {
1580 $.extend(true, settings, name);
1581 }
1582 else if(value !== undefined) {
1583 settings[name] = value;
1584 }
1585 else {
1586 return settings[name];
1587 }
1588 },
1589 internal: function(name, value) {
1590 if( $.isPlainObject(name) ) {
1591 $.extend(true, module, name);
1592 }
1593 else if(value !== undefined) {
1594 module[name] = value;
1595 }
1596 else {
1597 return module[name];
1598 }
1599 },
1600 debug: function() {
1601 if(!settings.silent && settings.debug) {
1602 if(settings.performance) {
1603 module.performance.log(arguments);
1604 }
1605 else {
1606 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
1607 module.debug.apply(console, arguments);
1608 }
1609 }
1610 },
1611 verbose: function() {
1612 if(!settings.silent && settings.verbose && settings.debug) {
1613 if(settings.performance) {
1614 module.performance.log(arguments);
1615 }
1616 else {
1617 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
1618 module.verbose.apply(console, arguments);
1619 }
1620 }
1621 },
1622 error: function() {
1623 if(!settings.silent) {
1624 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
1625 module.error.apply(console, arguments);
1626 }
1627 },
1628 performance: {
1629 log: function(message) {
1630 var
1631 currentTime,
1632 executionTime,
1633 previousTime
1634 ;
1635 if(settings.performance) {
1636 currentTime = new Date().getTime();
1637 previousTime = time || currentTime;
1638 executionTime = currentTime - previousTime;
1639 time = currentTime;
1640 performance.push({
1641 'Name' : message[0],
1642 'Arguments' : [].slice.call(message, 1) || '',
1643 'Element' : element,
1644 'Execution Time' : executionTime
1645 });
1646 }
1647 clearTimeout(module.performance.timer);
1648 module.performance.timer = setTimeout(module.performance.display, 500);
1649 },
1650 display: function() {
1651 var
1652 title = settings.name + ':',
1653 totalTime = 0
1654 ;
1655 time = false;
1656 clearTimeout(module.performance.timer);
1657 $.each(performance, function(index, data) {
1658 totalTime += data['Execution Time'];
1659 });
1660 title += ' ' + totalTime + 'ms';
1661 if(moduleSelector) {
1662 title += ' \'' + moduleSelector + '\'';
1663 }
1664 if($allModules.length > 1) {
1665 title += ' ' + '(' + $allModules.length + ')';
1666 }
1667 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
1668 console.groupCollapsed(title);
1669 if(console.table) {
1670 console.table(performance);
1671 }
1672 else {
1673 $.each(performance, function(index, data) {
1674 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
1675 });
1676 }
1677 console.groupEnd();
1678 }
1679 performance = [];
1680 }
1681 },
1682 invoke: function(query, passedArguments, context) {
1683 var
1684 object = instance,
1685 maxDepth,
1686 found,
1687 response
1688 ;
1689 passedArguments = passedArguments || queryArguments;
1690 context = element || context;
1691 if(typeof query == 'string' && object !== undefined) {
1692 query = query.split(/[\. ]/);
1693 maxDepth = query.length - 1;
1694 $.each(query, function(depth, value) {
1695 var camelCaseValue = (depth != maxDepth)
1696 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
1697 : query
1698 ;
1699 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
1700 object = object[camelCaseValue];
1701 }
1702 else if( object[camelCaseValue] !== undefined ) {
1703 found = object[camelCaseValue];
1704 return false;
1705 }
1706 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
1707 object = object[value];
1708 }
1709 else if( object[value] !== undefined ) {
1710 found = object[value];
1711 return false;
1712 }
1713 else {
1714 return false;
1715 }
1716 });
1717 }
1718 if( $.isFunction( found ) ) {
1719 response = found.apply(context, passedArguments);
1720 }
1721 else if(found !== undefined) {
1722 response = found;
1723 }
1724 if(Array.isArray(returnedValue)) {
1725 returnedValue.push(response);
1726 }
1727 else if(returnedValue !== undefined) {
1728 returnedValue = [returnedValue, response];
1729 }
1730 else if(response !== undefined) {
1731 returnedValue = response;
1732 }
1733 return found;
1734 }
1735 };
1736 module.initialize();
1737 })
1738 ;
1739
1740 return (returnedValue !== undefined)
1741 ? returnedValue
1742 : this
1743 ;
1744};
1745
1746$.fn.form.settings = {
1747
1748 name : 'Form',
1749 namespace : 'form',
1750
1751 debug : false,
1752 verbose : false,
1753 performance : true,
1754
1755 fields : false,
1756
1757 keyboardShortcuts : true,
1758 on : 'submit',
1759 inline : false,
1760
1761 delay : 200,
1762 revalidate : true,
1763 shouldTrim : true,
1764
1765 transition : 'scale',
1766 duration : 200,
1767
1768 onValid : function() {},
1769 onInvalid : function() {},
1770 onSuccess : function() { return true; },
1771 onFailure : function() { return false; },
1772
1773 metadata : {
1774 defaultValue : 'default',
1775 validate : 'validate'
1776 },
1777
1778 regExp: {
1779 htmlID : /^[a-zA-Z][\w:.-]*$/g,
1780 bracket : /\[(.*)\]/i,
1781 decimal : /^\d+\.?\d*$/,
1782 email : /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i,
1783 escape : /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|:,=@]/g,
1784 flags : /^\/(.*)\/(.*)?/,
1785 integer : /^\-?\d+$/,
1786 number : /^\-?\d*(\.\d+)?$/,
1787 url : /(https?:\/\/(?:www\.|(?!www))[^\s\.]+\.[^\s]{2,}|www\.[^\s]+\.[^\s]{2,})/i
1788 },
1789
1790 text: {
1791 unspecifiedRule : 'Please enter a valid value',
1792 unspecifiedField : 'This field'
1793 },
1794
1795 prompt: {
1796 empty : '{name} must have a value',
1797 checked : '{name} must be checked',
1798 email : '{name} must be a valid e-mail',
1799 url : '{name} must be a valid url',
1800 regExp : '{name} is not formatted correctly',
1801 integer : '{name} must be an integer',
1802 decimal : '{name} must be a decimal number',
1803 number : '{name} must be set to a number',
1804 is : '{name} must be "{ruleValue}"',
1805 isExactly : '{name} must be exactly "{ruleValue}"',
1806 not : '{name} cannot be set to "{ruleValue}"',
1807 notExactly : '{name} cannot be set to exactly "{ruleValue}"',
1808 contain : '{name} must contain "{ruleValue}"',
1809 containExactly : '{name} must contain exactly "{ruleValue}"',
1810 doesntContain : '{name} cannot contain "{ruleValue}"',
1811 doesntContainExactly : '{name} cannot contain exactly "{ruleValue}"',
1812 minLength : '{name} must be at least {ruleValue} characters',
1813 length : '{name} must be at least {ruleValue} characters',
1814 exactLength : '{name} must be exactly {ruleValue} characters',
1815 maxLength : '{name} cannot be longer than {ruleValue} characters',
1816 match : '{name} must match {ruleValue} field',
1817 different : '{name} must have a different value than {ruleValue} field',
1818 creditCard : '{name} must be a valid credit card number',
1819 minCount : '{name} must have at least {ruleValue} choices',
1820 exactCount : '{name} must have exactly {ruleValue} choices',
1821 maxCount : '{name} must have {ruleValue} or less choices'
1822 },
1823
1824 selector : {
1825 checkbox : 'input[type="checkbox"], input[type="radio"]',
1826 clear : '.clear',
1827 field : 'input, textarea, select',
1828 group : '.field',
1829 input : 'input',
1830 message : '.error.message',
1831 prompt : '.prompt.label',
1832 radio : 'input[type="radio"]',
1833 reset : '.reset:not([type="reset"])',
1834 submit : '.submit:not([type="submit"])',
1835 uiCheckbox : '.ui.checkbox',
1836 uiDropdown : '.ui.dropdown'
1837 },
1838
1839 className : {
1840 error : 'error',
1841 label : 'ui prompt label',
1842 pressed : 'down',
1843 success : 'success'
1844 },
1845
1846 error: {
1847 identifier : 'You must specify a string identifier for each field',
1848 method : 'The method you called is not defined.',
1849 noRule : 'There is no rule matching the one you specified',
1850 oldSyntax : 'Starting in 2.0 forms now only take a single settings object. Validation settings converted to new syntax automatically.'
1851 },
1852
1853 templates: {
1854
1855 // template that produces error message
1856 error: function(errors) {
1857 var
1858 html = '<ul class="list">'
1859 ;
1860 $.each(errors, function(index, value) {
1861 html += '<li>' + value + '</li>';
1862 });
1863 html += '</ul>';
1864 return $(html);
1865 },
1866
1867 // template that produces label
1868 prompt: function(errors) {
1869 return $('<div/>')
1870 .addClass('ui basic red pointing prompt label')
1871 .html(errors[0])
1872 ;
1873 }
1874 },
1875
1876 rules: {
1877
1878 // is not empty or blank string
1879 empty: function(value) {
1880 return !(value === undefined || '' === value || Array.isArray(value) && value.length === 0);
1881 },
1882
1883 // checkbox checked
1884 checked: function() {
1885 return ($(this).filter(':checked').length > 0);
1886 },
1887
1888 // is most likely an email
1889 email: function(value){
1890 return $.fn.form.settings.regExp.email.test(value);
1891 },
1892
1893 // value is most likely url
1894 url: function(value) {
1895 return $.fn.form.settings.regExp.url.test(value);
1896 },
1897
1898 // matches specified regExp
1899 regExp: function(value, regExp) {
1900 if(regExp instanceof RegExp) {
1901 return value.match(regExp);
1902 }
1903 var
1904 regExpParts = regExp.match($.fn.form.settings.regExp.flags),
1905 flags
1906 ;
1907 // regular expression specified as /baz/gi (flags)
1908 if(regExpParts) {
1909 regExp = (regExpParts.length >= 2)
1910 ? regExpParts[1]
1911 : regExp
1912 ;
1913 flags = (regExpParts.length >= 3)
1914 ? regExpParts[2]
1915 : ''
1916 ;
1917 }
1918 return value.match( new RegExp(regExp, flags) );
1919 },
1920
1921 // is valid integer or matches range
1922 integer: function(value, range) {
1923 var
1924 intRegExp = $.fn.form.settings.regExp.integer,
1925 min,
1926 max,
1927 parts
1928 ;
1929 if( !range || ['', '..'].indexOf(range) !== -1) {
1930 // do nothing
1931 }
1932 else if(range.indexOf('..') == -1) {
1933 if(intRegExp.test(range)) {
1934 min = max = range - 0;
1935 }
1936 }
1937 else {
1938 parts = range.split('..', 2);
1939 if(intRegExp.test(parts[0])) {
1940 min = parts[0] - 0;
1941 }
1942 if(intRegExp.test(parts[1])) {
1943 max = parts[1] - 0;
1944 }
1945 }
1946 return (
1947 intRegExp.test(value) &&
1948 (min === undefined || value >= min) &&
1949 (max === undefined || value <= max)
1950 );
1951 },
1952
1953 // is valid number (with decimal)
1954 decimal: function(value) {
1955 return $.fn.form.settings.regExp.decimal.test(value);
1956 },
1957
1958 // is valid number
1959 number: function(value) {
1960 return $.fn.form.settings.regExp.number.test(value);
1961 },
1962
1963 // is value (case insensitive)
1964 is: function(value, text) {
1965 text = (typeof text == 'string')
1966 ? text.toLowerCase()
1967 : text
1968 ;
1969 value = (typeof value == 'string')
1970 ? value.toLowerCase()
1971 : value
1972 ;
1973 return (value == text);
1974 },
1975
1976 // is value
1977 isExactly: function(value, text) {
1978 return (value == text);
1979 },
1980
1981 // value is not another value (case insensitive)
1982 not: function(value, notValue) {
1983 value = (typeof value == 'string')
1984 ? value.toLowerCase()
1985 : value
1986 ;
1987 notValue = (typeof notValue == 'string')
1988 ? notValue.toLowerCase()
1989 : notValue
1990 ;
1991 return (value != notValue);
1992 },
1993
1994 // value is not another value (case sensitive)
1995 notExactly: function(value, notValue) {
1996 return (value != notValue);
1997 },
1998
1999 // value contains text (insensitive)
2000 contains: function(value, text) {
2001 // escape regex characters
2002 text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
2003 return (value.search( new RegExp(text, 'i') ) !== -1);
2004 },
2005
2006 // value contains text (case sensitive)
2007 containsExactly: function(value, text) {
2008 // escape regex characters
2009 text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
2010 return (value.search( new RegExp(text) ) !== -1);
2011 },
2012
2013 // value contains text (insensitive)
2014 doesntContain: function(value, text) {
2015 // escape regex characters
2016 text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
2017 return (value.search( new RegExp(text, 'i') ) === -1);
2018 },
2019
2020 // value contains text (case sensitive)
2021 doesntContainExactly: function(value, text) {
2022 // escape regex characters
2023 text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
2024 return (value.search( new RegExp(text) ) === -1);
2025 },
2026
2027 // is at least string length
2028 minLength: function(value, requiredLength) {
2029 return (value !== undefined)
2030 ? (value.length >= requiredLength)
2031 : false
2032 ;
2033 },
2034
2035 // see rls notes for 2.0.6 (this is a duplicate of minLength)
2036 length: function(value, requiredLength) {
2037 return (value !== undefined)
2038 ? (value.length >= requiredLength)
2039 : false
2040 ;
2041 },
2042
2043 // is exactly length
2044 exactLength: function(value, requiredLength) {
2045 return (value !== undefined)
2046 ? (value.length == requiredLength)
2047 : false
2048 ;
2049 },
2050
2051 // is less than length
2052 maxLength: function(value, maxLength) {
2053 return (value !== undefined)
2054 ? (value.length <= maxLength)
2055 : false
2056 ;
2057 },
2058
2059 // matches another field
2060 match: function(value, identifier) {
2061 var
2062 $form = $(this),
2063 matchingValue
2064 ;
2065 if( $('[data-validate="'+ identifier +'"]').length > 0 ) {
2066 matchingValue = $('[data-validate="'+ identifier +'"]').val();
2067 }
2068 else if($('#' + identifier).length > 0) {
2069 matchingValue = $('#' + identifier).val();
2070 }
2071 else if($('[name="' + identifier +'"]').length > 0) {
2072 matchingValue = $('[name="' + identifier + '"]').val();
2073 }
2074 else if( $('[name="' + identifier +'[]"]').length > 0 ) {
2075 matchingValue = $('[name="' + identifier +'[]"]');
2076 }
2077 return (matchingValue !== undefined)
2078 ? ( value.toString() == matchingValue.toString() )
2079 : false
2080 ;
2081 },
2082
2083 // different than another field
2084 different: function(value, identifier) {
2085 // use either id or name of field
2086 var
2087 $form = $(this),
2088 matchingValue
2089 ;
2090 if( $('[data-validate="'+ identifier +'"]').length > 0 ) {
2091 matchingValue = $('[data-validate="'+ identifier +'"]').val();
2092 }
2093 else if($('#' + identifier).length > 0) {
2094 matchingValue = $('#' + identifier).val();
2095 }
2096 else if($('[name="' + identifier +'"]').length > 0) {
2097 matchingValue = $('[name="' + identifier + '"]').val();
2098 }
2099 else if( $('[name="' + identifier +'[]"]').length > 0 ) {
2100 matchingValue = $('[name="' + identifier +'[]"]');
2101 }
2102 return (matchingValue !== undefined)
2103 ? ( value.toString() !== matchingValue.toString() )
2104 : false
2105 ;
2106 },
2107
2108 creditCard: function(cardNumber, cardTypes) {
2109 var
2110 cards = {
2111 visa: {
2112 pattern : /^4/,
2113 length : [16]
2114 },
2115 amex: {
2116 pattern : /^3[47]/,
2117 length : [15]
2118 },
2119 mastercard: {
2120 pattern : /^5[1-5]/,
2121 length : [16]
2122 },
2123 discover: {
2124 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)/,
2125 length : [16]
2126 },
2127 unionPay: {
2128 pattern : /^(62|88)/,
2129 length : [16, 17, 18, 19]
2130 },
2131 jcb: {
2132 pattern : /^35(2[89]|[3-8][0-9])/,
2133 length : [16]
2134 },
2135 maestro: {
2136 pattern : /^(5018|5020|5038|6304|6759|676[1-3])/,
2137 length : [12, 13, 14, 15, 16, 17, 18, 19]
2138 },
2139 dinersClub: {
2140 pattern : /^(30[0-5]|^36)/,
2141 length : [14]
2142 },
2143 laser: {
2144 pattern : /^(6304|670[69]|6771)/,
2145 length : [16, 17, 18, 19]
2146 },
2147 visaElectron: {
2148 pattern : /^(4026|417500|4508|4844|491(3|7))/,
2149 length : [16]
2150 }
2151 },
2152 valid = {},
2153 validCard = false,
2154 requiredTypes = (typeof cardTypes == 'string')
2155 ? cardTypes.split(',')
2156 : false,
2157 unionPay,
2158 validation
2159 ;
2160
2161 if(typeof cardNumber !== 'string' || cardNumber.length === 0) {
2162 return;
2163 }
2164
2165 // allow dashes in card
2166 cardNumber = cardNumber.replace(/[\-]/g, '');
2167
2168 // verify card types
2169 if(requiredTypes) {
2170 $.each(requiredTypes, function(index, type){
2171 // verify each card type
2172 validation = cards[type];
2173 if(validation) {
2174 valid = {
2175 length : ($.inArray(cardNumber.length, validation.length) !== -1),
2176 pattern : (cardNumber.search(validation.pattern) !== -1)
2177 };
2178 if(valid.length && valid.pattern) {
2179 validCard = true;
2180 }
2181 }
2182 });
2183
2184 if(!validCard) {
2185 return false;
2186 }
2187 }
2188
2189 // skip luhn for UnionPay
2190 unionPay = {
2191 number : ($.inArray(cardNumber.length, cards.unionPay.length) !== -1),
2192 pattern : (cardNumber.search(cards.unionPay.pattern) !== -1)
2193 };
2194 if(unionPay.number && unionPay.pattern) {
2195 return true;
2196 }
2197
2198 // verify luhn, adapted from <https://gist.github.com/2134376>
2199 var
2200 length = cardNumber.length,
2201 multiple = 0,
2202 producedValue = [
2203 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
2204 [0, 2, 4, 6, 8, 1, 3, 5, 7, 9]
2205 ],
2206 sum = 0
2207 ;
2208 while (length--) {
2209 sum += producedValue[multiple][parseInt(cardNumber.charAt(length), 10)];
2210 multiple ^= 1;
2211 }
2212 return (sum % 10 === 0 && sum > 0);
2213 },
2214
2215 minCount: function(value, minCount) {
2216 if(minCount == 0) {
2217 return true;
2218 }
2219 if(minCount == 1) {
2220 return (value !== '');
2221 }
2222 return (value.split(',').length >= minCount);
2223 },
2224
2225 exactCount: function(value, exactCount) {
2226 if(exactCount == 0) {
2227 return (value === '');
2228 }
2229 if(exactCount == 1) {
2230 return (value !== '' && value.search(',') === -1);
2231 }
2232 return (value.split(',').length == exactCount);
2233 },
2234
2235 maxCount: function(value, maxCount) {
2236 if(maxCount == 0) {
2237 return false;
2238 }
2239 if(maxCount == 1) {
2240 return (value.search(',') === -1);
2241 }
2242 return (value.split(',').length <= maxCount);
2243 }
2244 }
2245
2246};
2247
2248})( jQuery, window, document );
2249
2250/*!
2251 * # Semantic UI 2.7.2 - Accordion
2252 * http://github.com/semantic-org/semantic-ui/
2253 *
2254 *
2255 * Released under the MIT license
2256 * http://opensource.org/licenses/MIT
2257 *
2258 */
2259
2260;(function ($, window, document, undefined) {
2261
2262'use strict';
2263
2264$.isFunction = $.isFunction || function(obj) {
2265 return typeof obj === "function" && typeof obj.nodeType !== "number";
2266};
2267
2268window = (typeof window != 'undefined' && window.Math == Math)
2269 ? window
2270 : (typeof self != 'undefined' && self.Math == Math)
2271 ? self
2272 : Function('return this')()
2273;
2274
2275$.fn.accordion = function(parameters) {
2276 var
2277 $allModules = $(this),
2278
2279 time = new Date().getTime(),
2280 performance = [],
2281
2282 query = arguments[0],
2283 methodInvoked = (typeof query == 'string'),
2284 queryArguments = [].slice.call(arguments, 1),
2285
2286 requestAnimationFrame = window.requestAnimationFrame
2287 || window.mozRequestAnimationFrame
2288 || window.webkitRequestAnimationFrame
2289 || window.msRequestAnimationFrame
2290 || function(callback) { setTimeout(callback, 0); },
2291
2292 returnedValue
2293 ;
2294 $allModules
2295 .each(function() {
2296 var
2297 settings = ( $.isPlainObject(parameters) )
2298 ? $.extend(true, {}, $.fn.accordion.settings, parameters)
2299 : $.extend({}, $.fn.accordion.settings),
2300
2301 className = settings.className,
2302 namespace = settings.namespace,
2303 selector = settings.selector,
2304 error = settings.error,
2305
2306 eventNamespace = '.' + namespace,
2307 moduleNamespace = 'module-' + namespace,
2308 moduleSelector = $allModules.selector || '',
2309
2310 $module = $(this),
2311 $title = $module.find(selector.title),
2312 $content = $module.find(selector.content),
2313
2314 element = this,
2315 instance = $module.data(moduleNamespace),
2316 observer,
2317 module
2318 ;
2319
2320 module = {
2321
2322 initialize: function() {
2323 module.debug('Initializing', $module);
2324 module.bind.events();
2325 if(settings.observeChanges) {
2326 module.observeChanges();
2327 }
2328 module.instantiate();
2329 },
2330
2331 instantiate: function() {
2332 instance = module;
2333 $module
2334 .data(moduleNamespace, module)
2335 ;
2336 },
2337
2338 destroy: function() {
2339 module.debug('Destroying previous instance', $module);
2340 $module
2341 .off(eventNamespace)
2342 .removeData(moduleNamespace)
2343 ;
2344 },
2345
2346 refresh: function() {
2347 $title = $module.find(selector.title);
2348 $content = $module.find(selector.content);
2349 },
2350
2351 observeChanges: function() {
2352 if('MutationObserver' in window) {
2353 observer = new MutationObserver(function(mutations) {
2354 module.debug('DOM tree modified, updating selector cache');
2355 module.refresh();
2356 });
2357 observer.observe(element, {
2358 childList : true,
2359 subtree : true
2360 });
2361 module.debug('Setting up mutation observer', observer);
2362 }
2363 },
2364
2365 bind: {
2366 events: function() {
2367 module.debug('Binding delegated events');
2368 $module
2369 .on(settings.on + eventNamespace, selector.trigger, module.event.click)
2370 ;
2371 }
2372 },
2373
2374 event: {
2375 click: function() {
2376 module.toggle.call(this);
2377 }
2378 },
2379
2380 toggle: function(query) {
2381 var
2382 $activeTitle = (query !== undefined)
2383 ? (typeof query === 'number')
2384 ? $title.eq(query)
2385 : $(query).closest(selector.title)
2386 : $(this).closest(selector.title),
2387 $activeContent = $activeTitle.next($content),
2388 isAnimating = $activeContent.hasClass(className.animating),
2389 isActive = $activeContent.hasClass(className.active),
2390 isOpen = (isActive && !isAnimating),
2391 isOpening = (!isActive && isAnimating)
2392 ;
2393 module.debug('Toggling visibility of content', $activeTitle);
2394 if(isOpen || isOpening) {
2395 if(settings.collapsible) {
2396 module.close.call($activeTitle);
2397 }
2398 else {
2399 module.debug('Cannot close accordion content collapsing is disabled');
2400 }
2401 }
2402 else {
2403 module.open.call($activeTitle);
2404 }
2405 },
2406
2407 open: function(query) {
2408 var
2409 $activeTitle = (query !== undefined)
2410 ? (typeof query === 'number')
2411 ? $title.eq(query)
2412 : $(query).closest(selector.title)
2413 : $(this).closest(selector.title),
2414 $activeContent = $activeTitle.next($content),
2415 isAnimating = $activeContent.hasClass(className.animating),
2416 isActive = $activeContent.hasClass(className.active),
2417 isOpen = (isActive || isAnimating)
2418 ;
2419 if(isOpen) {
2420 module.debug('Accordion already open, skipping', $activeContent);
2421 return;
2422 }
2423 module.debug('Opening accordion content', $activeTitle);
2424 settings.onOpening.call($activeContent);
2425 settings.onChanging.call($activeContent);
2426 if(settings.exclusive) {
2427 module.closeOthers.call($activeTitle);
2428 }
2429 $activeTitle
2430 .addClass(className.active)
2431 ;
2432 $activeContent
2433 .stop(true, true)
2434 .addClass(className.animating)
2435 ;
2436 if(settings.animateChildren) {
2437 if($.fn.transition !== undefined && $module.transition('is supported')) {
2438 $activeContent
2439 .children()
2440 .transition({
2441 animation : 'fade in',
2442 queue : false,
2443 useFailSafe : true,
2444 debug : settings.debug,
2445 verbose : settings.verbose,
2446 duration : settings.duration,
2447 skipInlineHidden : true
2448 })
2449 ;
2450 }
2451 else {
2452 $activeContent
2453 .children()
2454 .stop(true, true)
2455 .animate({
2456 opacity: 1
2457 }, settings.duration, module.resetOpacity)
2458 ;
2459 }
2460 }
2461 $activeContent
2462 .slideDown(settings.duration, settings.easing, function() {
2463 $activeContent
2464 .removeClass(className.animating)
2465 .addClass(className.active)
2466 ;
2467 module.reset.display.call(this);
2468 settings.onOpen.call(this);
2469 settings.onChange.call(this);
2470 })
2471 ;
2472 },
2473
2474 close: function(query) {
2475 var
2476 $activeTitle = (query !== undefined)
2477 ? (typeof query === 'number')
2478 ? $title.eq(query)
2479 : $(query).closest(selector.title)
2480 : $(this).closest(selector.title),
2481 $activeContent = $activeTitle.next($content),
2482 isAnimating = $activeContent.hasClass(className.animating),
2483 isActive = $activeContent.hasClass(className.active),
2484 isOpening = (!isActive && isAnimating),
2485 isClosing = (isActive && isAnimating)
2486 ;
2487 if((isActive || isOpening) && !isClosing) {
2488 module.debug('Closing accordion content', $activeContent);
2489 settings.onClosing.call($activeContent);
2490 settings.onChanging.call($activeContent);
2491 $activeTitle
2492 .removeClass(className.active)
2493 ;
2494 $activeContent
2495 .stop(true, true)
2496 .addClass(className.animating)
2497 ;
2498 if(settings.animateChildren) {
2499 if($.fn.transition !== undefined && $module.transition('is supported')) {
2500 $activeContent
2501 .children()
2502 .transition({
2503 animation : 'fade out',
2504 queue : false,
2505 useFailSafe : true,
2506 debug : settings.debug,
2507 verbose : settings.verbose,
2508 duration : settings.duration,
2509 skipInlineHidden : true
2510 })
2511 ;
2512 }
2513 else {
2514 $activeContent
2515 .children()
2516 .stop(true, true)
2517 .animate({
2518 opacity: 0
2519 }, settings.duration, module.resetOpacity)
2520 ;
2521 }
2522 }
2523 $activeContent
2524 .slideUp(settings.duration, settings.easing, function() {
2525 $activeContent
2526 .removeClass(className.animating)
2527 .removeClass(className.active)
2528 ;
2529 module.reset.display.call(this);
2530 settings.onClose.call(this);
2531 settings.onChange.call(this);
2532 })
2533 ;
2534 }
2535 },
2536
2537 closeOthers: function(index) {
2538 var
2539 $activeTitle = (index !== undefined)
2540 ? $title.eq(index)
2541 : $(this).closest(selector.title),
2542 $parentTitles = $activeTitle.parents(selector.content).prev(selector.title),
2543 $activeAccordion = $activeTitle.closest(selector.accordion),
2544 activeSelector = selector.title + '.' + className.active + ':visible',
2545 activeContent = selector.content + '.' + className.active + ':visible',
2546 $openTitles,
2547 $nestedTitles,
2548 $openContents
2549 ;
2550 if(settings.closeNested) {
2551 $openTitles = $activeAccordion.find(activeSelector).not($parentTitles);
2552 $openContents = $openTitles.next($content);
2553 }
2554 else {
2555 $openTitles = $activeAccordion.find(activeSelector).not($parentTitles);
2556 $nestedTitles = $activeAccordion.find(activeContent).find(activeSelector).not($parentTitles);
2557 $openTitles = $openTitles.not($nestedTitles);
2558 $openContents = $openTitles.next($content);
2559 }
2560 if( ($openTitles.length > 0) ) {
2561 module.debug('Exclusive enabled, closing other content', $openTitles);
2562 $openTitles
2563 .removeClass(className.active)
2564 ;
2565 $openContents
2566 .removeClass(className.animating)
2567 .stop(true, true)
2568 ;
2569 if(settings.animateChildren) {
2570 if($.fn.transition !== undefined && $module.transition('is supported')) {
2571 $openContents
2572 .children()
2573 .transition({
2574 animation : 'fade out',
2575 useFailSafe : true,
2576 debug : settings.debug,
2577 verbose : settings.verbose,
2578 duration : settings.duration,
2579 skipInlineHidden : true
2580 })
2581 ;
2582 }
2583 else {
2584 $openContents
2585 .children()
2586 .stop(true, true)
2587 .animate({
2588 opacity: 0
2589 }, settings.duration, module.resetOpacity)
2590 ;
2591 }
2592 }
2593 $openContents
2594 .slideUp(settings.duration , settings.easing, function() {
2595 $(this).removeClass(className.active);
2596 module.reset.display.call(this);
2597 })
2598 ;
2599 }
2600 },
2601
2602 reset: {
2603
2604 display: function() {
2605 module.verbose('Removing inline display from element', this);
2606 $(this).css('display', '');
2607 if( $(this).attr('style') === '') {
2608 $(this)
2609 .attr('style', '')
2610 .removeAttr('style')
2611 ;
2612 }
2613 },
2614
2615 opacity: function() {
2616 module.verbose('Removing inline opacity from element', this);
2617 $(this).css('opacity', '');
2618 if( $(this).attr('style') === '') {
2619 $(this)
2620 .attr('style', '')
2621 .removeAttr('style')
2622 ;
2623 }
2624 },
2625
2626 },
2627
2628 setting: function(name, value) {
2629 module.debug('Changing setting', name, value);
2630 if( $.isPlainObject(name) ) {
2631 $.extend(true, settings, name);
2632 }
2633 else if(value !== undefined) {
2634 if($.isPlainObject(settings[name])) {
2635 $.extend(true, settings[name], value);
2636 }
2637 else {
2638 settings[name] = value;
2639 }
2640 }
2641 else {
2642 return settings[name];
2643 }
2644 },
2645 internal: function(name, value) {
2646 module.debug('Changing internal', name, value);
2647 if(value !== undefined) {
2648 if( $.isPlainObject(name) ) {
2649 $.extend(true, module, name);
2650 }
2651 else {
2652 module[name] = value;
2653 }
2654 }
2655 else {
2656 return module[name];
2657 }
2658 },
2659 debug: function() {
2660 if(!settings.silent && settings.debug) {
2661 if(settings.performance) {
2662 module.performance.log(arguments);
2663 }
2664 else {
2665 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
2666 module.debug.apply(console, arguments);
2667 }
2668 }
2669 },
2670 verbose: function() {
2671 if(!settings.silent && settings.verbose && settings.debug) {
2672 if(settings.performance) {
2673 module.performance.log(arguments);
2674 }
2675 else {
2676 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
2677 module.verbose.apply(console, arguments);
2678 }
2679 }
2680 },
2681 error: function() {
2682 if(!settings.silent) {
2683 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
2684 module.error.apply(console, arguments);
2685 }
2686 },
2687 performance: {
2688 log: function(message) {
2689 var
2690 currentTime,
2691 executionTime,
2692 previousTime
2693 ;
2694 if(settings.performance) {
2695 currentTime = new Date().getTime();
2696 previousTime = time || currentTime;
2697 executionTime = currentTime - previousTime;
2698 time = currentTime;
2699 performance.push({
2700 'Name' : message[0],
2701 'Arguments' : [].slice.call(message, 1) || '',
2702 'Element' : element,
2703 'Execution Time' : executionTime
2704 });
2705 }
2706 clearTimeout(module.performance.timer);
2707 module.performance.timer = setTimeout(module.performance.display, 500);
2708 },
2709 display: function() {
2710 var
2711 title = settings.name + ':',
2712 totalTime = 0
2713 ;
2714 time = false;
2715 clearTimeout(module.performance.timer);
2716 $.each(performance, function(index, data) {
2717 totalTime += data['Execution Time'];
2718 });
2719 title += ' ' + totalTime + 'ms';
2720 if(moduleSelector) {
2721 title += ' \'' + moduleSelector + '\'';
2722 }
2723 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
2724 console.groupCollapsed(title);
2725 if(console.table) {
2726 console.table(performance);
2727 }
2728 else {
2729 $.each(performance, function(index, data) {
2730 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
2731 });
2732 }
2733 console.groupEnd();
2734 }
2735 performance = [];
2736 }
2737 },
2738 invoke: function(query, passedArguments, context) {
2739 var
2740 object = instance,
2741 maxDepth,
2742 found,
2743 response
2744 ;
2745 passedArguments = passedArguments || queryArguments;
2746 context = element || context;
2747 if(typeof query == 'string' && object !== undefined) {
2748 query = query.split(/[\. ]/);
2749 maxDepth = query.length - 1;
2750 $.each(query, function(depth, value) {
2751 var camelCaseValue = (depth != maxDepth)
2752 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
2753 : query
2754 ;
2755 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
2756 object = object[camelCaseValue];
2757 }
2758 else if( object[camelCaseValue] !== undefined ) {
2759 found = object[camelCaseValue];
2760 return false;
2761 }
2762 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
2763 object = object[value];
2764 }
2765 else if( object[value] !== undefined ) {
2766 found = object[value];
2767 return false;
2768 }
2769 else {
2770 module.error(error.method, query);
2771 return false;
2772 }
2773 });
2774 }
2775 if ( $.isFunction( found ) ) {
2776 response = found.apply(context, passedArguments);
2777 }
2778 else if(found !== undefined) {
2779 response = found;
2780 }
2781 if(Array.isArray(returnedValue)) {
2782 returnedValue.push(response);
2783 }
2784 else if(returnedValue !== undefined) {
2785 returnedValue = [returnedValue, response];
2786 }
2787 else if(response !== undefined) {
2788 returnedValue = response;
2789 }
2790 return found;
2791 }
2792 };
2793 if(methodInvoked) {
2794 if(instance === undefined) {
2795 module.initialize();
2796 }
2797 module.invoke(query);
2798 }
2799 else {
2800 if(instance !== undefined) {
2801 instance.invoke('destroy');
2802 }
2803 module.initialize();
2804 }
2805 })
2806 ;
2807 return (returnedValue !== undefined)
2808 ? returnedValue
2809 : this
2810 ;
2811};
2812
2813$.fn.accordion.settings = {
2814
2815 name : 'Accordion',
2816 namespace : 'accordion',
2817
2818 silent : false,
2819 debug : false,
2820 verbose : false,
2821 performance : true,
2822
2823 on : 'click', // event on title that opens accordion
2824
2825 observeChanges : true, // whether accordion should automatically refresh on DOM insertion
2826
2827 exclusive : true, // whether a single accordion content panel should be open at once
2828 collapsible : true, // whether accordion content can be closed
2829 closeNested : false, // whether nested content should be closed when a panel is closed
2830 animateChildren : true, // whether children opacity should be animated
2831
2832 duration : 350, // duration of animation
2833 easing : 'easeOutQuad', // easing equation for animation
2834
2835 onOpening : function(){}, // callback before open animation
2836 onClosing : function(){}, // callback before closing animation
2837 onChanging : function(){}, // callback before closing or opening animation
2838
2839 onOpen : function(){}, // callback after open animation
2840 onClose : function(){}, // callback after closing animation
2841 onChange : function(){}, // callback after closing or opening animation
2842
2843 error: {
2844 method : 'The method you called is not defined'
2845 },
2846
2847 className : {
2848 active : 'active',
2849 animating : 'animating'
2850 },
2851
2852 selector : {
2853 accordion : '.accordion',
2854 title : '.title',
2855 trigger : '.title',
2856 content : '.content'
2857 }
2858
2859};
2860
2861// Adds easing
2862$.extend( $.easing, {
2863 easeOutQuad: function (x, t, b, c, d) {
2864 return -c *(t/=d)*(t-2) + b;
2865 }
2866});
2867
2868})( jQuery, window, document );
2869
2870
2871/*!
2872 * # Semantic UI 2.7.2 - Calendar
2873 * http://github.com/semantic-org/semantic-ui/
2874 *
2875 *
2876 * Released under the MIT license
2877 * http://opensource.org/licenses/MIT
2878 *
2879 */
2880
2881;(function ($, window, document, undefined) {
2882
2883'use strict';
2884
2885$.isFunction = $.isFunction || function(obj) {
2886 return typeof obj === "function" && typeof obj.nodeType !== "number";
2887};
2888
2889window = (typeof window != 'undefined' && window.Math == Math)
2890 ? window
2891 : (typeof self != 'undefined' && self.Math == Math)
2892 ? self
2893 : Function('return this')()
2894;
2895
2896$.fn.calendar = function(parameters) {
2897 var
2898 $allModules = $(this),
2899
2900 moduleSelector = $allModules.selector || '',
2901
2902 time = new Date().getTime(),
2903 performance = [],
2904
2905 query = arguments[0],
2906 methodInvoked = (typeof query == 'string'),
2907 queryArguments = [].slice.call(arguments, 1),
2908 returnedValue,
2909 timeGapTable = {
2910 '5': {'row': 4, 'column': 3 },
2911 '10': {'row': 3, 'column': 2 },
2912 '15': {'row': 2, 'column': 2 },
2913 '20': {'row': 3, 'column': 1 },
2914 '30': {'row': 2, 'column': 1 }
2915 }
2916 ;
2917
2918 $allModules
2919 .each(function () {
2920 var
2921 settings = ( $.isPlainObject(parameters) )
2922 ? $.extend(true, {}, $.fn.calendar.settings, parameters)
2923 : $.extend({}, $.fn.calendar.settings),
2924
2925 className = settings.className,
2926 namespace = settings.namespace,
2927 selector = settings.selector,
2928 formatter = settings.formatter,
2929 parser = settings.parser,
2930 metadata = settings.metadata,
2931 timeGap = timeGapTable[settings.minTimeGap],
2932 error = settings.error,
2933
2934 eventNamespace = '.' + namespace,
2935 moduleNamespace = 'module-' + namespace,
2936
2937 $module = $(this),
2938 $input = $module.find(selector.input),
2939 $container = $module.find(selector.popup),
2940 $activator = $module.find(selector.activator),
2941
2942 element = this,
2943 instance = $module.data(moduleNamespace),
2944
2945 isTouch,
2946 isTouchDown = false,
2947 focusDateUsedForRange = false,
2948 module
2949 ;
2950
2951 module = {
2952
2953 initialize: function () {
2954 module.debug('Initializing calendar for', element, $module);
2955
2956 isTouch = module.get.isTouch();
2957 module.setup.config();
2958 module.setup.popup();
2959 module.setup.inline();
2960 module.setup.input();
2961 module.setup.date();
2962 module.create.calendar();
2963
2964 module.bind.events();
2965 module.instantiate();
2966 },
2967
2968 instantiate: function () {
2969 module.verbose('Storing instance of calendar');
2970 instance = module;
2971 $module.data(moduleNamespace, instance);
2972 },
2973
2974 destroy: function () {
2975 module.verbose('Destroying previous calendar for', element);
2976 $module.removeData(moduleNamespace);
2977 module.unbind.events();
2978 },
2979
2980 setup: {
2981 config: function () {
2982 if (module.get.minDate() !== null) {
2983 module.set.minDate($module.data(metadata.minDate));
2984 }
2985 if (module.get.maxDate() !== null) {
2986 module.set.maxDate($module.data(metadata.maxDate));
2987 }
2988 },
2989 popup: function () {
2990 if (settings.inline) {
2991 return;
2992 }
2993 if (!$activator.length) {
2994 $activator = $module.children().first();
2995 if (!$activator.length) {
2996 return;
2997 }
2998 }
2999 if ($.fn.popup === undefined) {
3000 module.error(error.popup);
3001 return;
3002 }
3003 if (!$container.length) {
3004 //prepend the popup element to the activator's parent so that it has less chance of messing with
3005 //the styling (eg input action button needs to be the last child to have correct border radius)
3006 $container = $('<div/>').addClass(className.popup).prependTo($activator.parent());
3007 }
3008 $container.addClass(className.calendar);
3009 var onVisible = settings.onVisible;
3010 var onHidden = settings.onHidden;
3011 if (!$input.length) {
3012 //no input, $container has to handle focus/blur
3013 $container.attr('tabindex', '0');
3014 onVisible = function () {
3015 module.focus();
3016 return settings.onVisible.apply($container, arguments);
3017 };
3018 onHidden = function () {
3019 module.blur();
3020 return settings.onHidden.apply($container, arguments);
3021 };
3022 }
3023 var onShow = function () {
3024 //reset the focus date onShow
3025 module.set.focusDate(module.get.date());
3026 module.set.mode(settings.startMode);
3027 return settings.onShow.apply($container, arguments);
3028 };
3029 var on = settings.on || ($input.length ? 'focus' : 'click');
3030 var options = $.extend({}, settings.popupOptions, {
3031 popup: $container,
3032 on: on,
3033 hoverable: on === 'hover',
3034 onShow: onShow,
3035 onVisible: onVisible,
3036 onHide: settings.onHide,
3037 onHidden: onHidden
3038 });
3039 module.popup(options);
3040 },
3041 inline: function () {
3042 if ($activator.length && !settings.inline) {
3043 return;
3044 }
3045 $container = $('<div/>').addClass(className.calendar).appendTo($module);
3046 if (!$input.length) {
3047 $container.attr('tabindex', '0');
3048 }
3049 },
3050 input: function () {
3051 if (settings.touchReadonly && $input.length && isTouch) {
3052 $input.prop('readonly', true);
3053 }
3054 },
3055 date: function () {
3056 if ($input.length) {
3057 var val = $input.val();
3058 var date = parser.date(val, settings);
3059 module.set.date(date, settings.formatInput, false);
3060 }
3061 }
3062 },
3063
3064 create: {
3065 calendar: function () {
3066 var i, r, c, p, row, cell, pageGrid;
3067
3068 var mode = module.get.mode();
3069 var today = new Date();
3070 var date = module.get.date();
3071 var focusDate = module.get.focusDate();
3072 var display = focusDate || date || settings.initialDate || today;
3073 display = module.helper.dateInRange(display);
3074
3075 if (!focusDate) {
3076 focusDate = display;
3077 module.set.focusDate(focusDate, false, false);
3078 }
3079
3080 var isYear = mode === 'year';
3081 var isMonth = mode === 'month';
3082 var isDay = mode === 'day';
3083 var isHour = mode === 'hour';
3084 var isMinute = mode === 'minute';
3085 var isTimeOnly = settings.type === 'time';
3086
3087 var multiMonth = Math.max(settings.multiMonth, 1);
3088 var monthOffset = !isDay ? 0 : module.get.monthOffset();
3089
3090 var minute = display.getMinutes();
3091 var hour = display.getHours();
3092 var day = display.getDate();
3093 var startMonth = display.getMonth() + monthOffset;
3094 var year = display.getFullYear();
3095
3096 var columns = isDay ? settings.showWeekNumbers ? 8 : 7 : isHour ? 4 : timeGap['column'];
3097 var rows = isDay || isHour ? 6 : timeGap['row'];
3098 var pages = isDay ? multiMonth : 1;
3099
3100 var container = $container;
3101 var tooltipPosition = container.hasClass("left") ? "right center" : "left center";
3102 container.empty();
3103 if (pages > 1) {
3104 pageGrid = $('<div/>').addClass(className.grid).appendTo(container);
3105 }
3106
3107 for (p = 0; p < pages; p++) {
3108 if (pages > 1) {
3109 var pageColumn = $('<div/>').addClass(className.column).appendTo(pageGrid);
3110 container = pageColumn;
3111 }
3112
3113 var month = startMonth + p;
3114 var firstMonthDayColumn = (new Date(year, month, 1).getDay() - settings.firstDayOfWeek % 7 + 7) % 7;
3115 if (!settings.constantHeight && isDay) {
3116 var requiredCells = new Date(year, month + 1, 0).getDate() + firstMonthDayColumn;
3117 rows = Math.ceil(requiredCells / 7);
3118 }
3119
3120 var yearChange = isYear ? 10 : isMonth ? 1 : 0;
3121 var monthChange = isDay ? 1 : 0;
3122 var dayChange = isHour || isMinute ? 1 : 0;
3123 var prevNextDay = isHour || isMinute ? day : 1;
3124 var prevDate = new Date(year - yearChange, month - monthChange, prevNextDay - dayChange, hour);
3125 var nextDate = new Date(year + yearChange, month + monthChange, prevNextDay + dayChange, hour);
3126
3127 var prevLast = isYear ? new Date(Math.ceil(year / 10) * 10 - 9, 0, 0) :
3128 isMonth ? new Date(year, 0, 0) : isDay ? new Date(year, month, 0) : new Date(year, month, day, -1);
3129 var nextFirst = isYear ? new Date(Math.ceil(year / 10) * 10 + 1, 0, 1) :
3130 isMonth ? new Date(year + 1, 0, 1) : isDay ? new Date(year, month + 1, 1) : new Date(year, month, day + 1);
3131
3132 var tempMode = mode;
3133 if (isDay && settings.showWeekNumbers){
3134 tempMode += ' andweek';
3135 }
3136 var table = $('<table/>').addClass(className.table).addClass(tempMode).appendTo(container);
3137 var textColumns = columns;
3138 //no header for time-only mode
3139 if (!isTimeOnly) {
3140 var thead = $('<thead/>').appendTo(table);
3141
3142 row = $('<tr/>').appendTo(thead);
3143 cell = $('<th/>').attr('colspan', '' + columns).appendTo(row);
3144
3145 var headerDate = isYear || isMonth ? new Date(year, 0, 1) :
3146 isDay ? new Date(year, month, 1) : new Date(year, month, day, hour, minute);
3147 var headerText = $('<span/>').addClass(className.link).appendTo(cell);
3148 headerText.text(formatter.header(headerDate, mode, settings));
3149 var newMode = isMonth ? (settings.disableYear ? 'day' : 'year') :
3150 isDay ? (settings.disableMonth ? 'year' : 'month') : 'day';
3151 headerText.data(metadata.mode, newMode);
3152
3153 if (p === 0) {
3154 var prev = $('<span/>').addClass(className.prev).appendTo(cell);
3155 prev.data(metadata.focusDate, prevDate);
3156 prev.toggleClass(className.disabledCell, !module.helper.isDateInRange(prevLast, mode));
3157 $('<i/>').addClass(className.prevIcon).appendTo(prev);
3158 }
3159
3160 if (p === pages - 1) {
3161 var next = $('<span/>').addClass(className.next).appendTo(cell);
3162 next.data(metadata.focusDate, nextDate);
3163 next.toggleClass(className.disabledCell, !module.helper.isDateInRange(nextFirst, mode));
3164 $('<i/>').addClass(className.nextIcon).appendTo(next);
3165 }
3166 if (isDay) {
3167 row = $('<tr/>').appendTo(thead);
3168 if(settings.showWeekNumbers) {
3169 cell = $('<th/>').appendTo(row);
3170 cell.text(settings.text.weekNo);
3171 cell.addClass(className.disabledCell);
3172 textColumns--;
3173 }
3174 for (i = 0; i < textColumns; i++) {
3175 cell = $('<th/>').appendTo(row);
3176 cell.text(formatter.dayColumnHeader((i + settings.firstDayOfWeek) % 7, settings));
3177 }
3178 }
3179 }
3180
3181 var tbody = $('<tbody/>').appendTo(table);
3182 i = isYear ? Math.ceil(year / 10) * 10 - 9 : isDay ? 1 - firstMonthDayColumn : 0;
3183 for (r = 0; r < rows; r++) {
3184 row = $('<tr/>').appendTo(tbody);
3185 if(isDay && settings.showWeekNumbers){
3186 cell = $('<th/>').appendTo(row);
3187 cell.text(module.get.weekOfYear(year,month,i+1-settings.firstDayOfWeek));
3188 cell.addClass(className.disabledCell);
3189 }
3190 for (c = 0; c < textColumns; c++, i++) {
3191 var cellDate = isYear ? new Date(i, month, 1, hour, minute) :
3192 isMonth ? new Date(year, i, 1, hour, minute) : isDay ? new Date(year, month, i, hour, minute) :
3193 isHour ? new Date(year, month, day, i) : new Date(year, month, day, hour, i * settings.minTimeGap);
3194 var cellText = isYear ? i :
3195 isMonth ? settings.text.monthsShort[i] : isDay ? cellDate.getDate() :
3196 formatter.time(cellDate, settings, true);
3197 cell = $('<td/>').addClass(className.cell).appendTo(row);
3198 cell.text(cellText);
3199 cell.data(metadata.date, cellDate);
3200 var adjacent = isDay && cellDate.getMonth() !== ((month + 12) % 12);
3201 var disabled = adjacent || !module.helper.isDateInRange(cellDate, mode) || settings.isDisabled(cellDate, mode) || module.helper.isDisabled(cellDate, mode);
3202 if (disabled) {
3203 var disabledReason = module.helper.disabledReason(cellDate, mode);
3204 if (disabledReason !== null) {
3205 cell.attr("data-tooltip", disabledReason[metadata.message]);
3206 cell.attr("data-position", tooltipPosition);
3207 }
3208 }
3209 var active = module.helper.dateEqual(cellDate, date, mode);
3210 var isToday = module.helper.dateEqual(cellDate, today, mode);
3211 cell.toggleClass(className.adjacentCell, adjacent);
3212 cell.toggleClass(className.disabledCell, disabled);
3213 cell.toggleClass(className.activeCell, active && !adjacent);
3214 if (!isHour && !isMinute) {
3215 cell.toggleClass(className.todayCell, !adjacent && isToday);
3216 }
3217
3218 // Allow for external modifications of each cell
3219 var cellOptions = {
3220 mode: mode,
3221 adjacent: adjacent,
3222 disabled: disabled,
3223 active: active,
3224 today: isToday
3225 };
3226 formatter.cell(cell, cellDate, cellOptions);
3227
3228 if (module.helper.dateEqual(cellDate, focusDate, mode)) {
3229 //ensure that the focus date is exactly equal to the cell date
3230 //so that, if selected, the correct value is set
3231 module.set.focusDate(cellDate, false, false);
3232 }
3233 }
3234 }
3235
3236 if (settings.today) {
3237 var todayRow = $('<tr/>').appendTo(tbody);
3238 var todayButton = $('<td/>').attr('colspan', '' + columns).addClass(className.today).appendTo(todayRow);
3239 todayButton.text(formatter.today(settings));
3240 todayButton.data(metadata.date, today);
3241 }
3242
3243 module.update.focus(false, table);
3244 }
3245 }
3246 },
3247
3248 update: {
3249 focus: function (updateRange, container) {
3250 container = container || $container;
3251 var mode = module.get.mode();
3252 var date = module.get.date();
3253 var focusDate = module.get.focusDate();
3254 var startDate = module.get.startDate();
3255 var endDate = module.get.endDate();
3256 var rangeDate = (updateRange ? focusDate : null) || date || (!isTouch ? focusDate : null);
3257
3258 container.find('td').each(function () {
3259 var cell = $(this);
3260 var cellDate = cell.data(metadata.date);
3261 if (!cellDate) {
3262 return;
3263 }
3264 var disabled = cell.hasClass(className.disabledCell);
3265 var active = cell.hasClass(className.activeCell);
3266 var adjacent = cell.hasClass(className.adjacentCell);
3267 var focused = module.helper.dateEqual(cellDate, focusDate, mode);
3268 var inRange = !rangeDate ? false :
3269 ((!!startDate && module.helper.isDateInRange(cellDate, mode, startDate, rangeDate)) ||
3270 (!!endDate && module.helper.isDateInRange(cellDate, mode, rangeDate, endDate)));
3271 cell.toggleClass(className.focusCell, focused && (!isTouch || isTouchDown) && !adjacent && !disabled);
3272 cell.toggleClass(className.rangeCell, inRange && !active && !disabled);
3273 });
3274 }
3275 },
3276
3277 refresh: function () {
3278 module.create.calendar();
3279 },
3280
3281 bind: {
3282 events: function () {
3283 module.debug('Binding events');
3284 $container.on('mousedown' + eventNamespace, module.event.mousedown);
3285 $container.on('touchstart' + eventNamespace, module.event.mousedown);
3286 $container.on('mouseup' + eventNamespace, module.event.mouseup);
3287 $container.on('touchend' + eventNamespace, module.event.mouseup);
3288 $container.on('mouseover' + eventNamespace, module.event.mouseover);
3289 if ($input.length) {
3290 $input.on('input' + eventNamespace, module.event.inputChange);
3291 $input.on('focus' + eventNamespace, module.event.inputFocus);
3292 $input.on('blur' + eventNamespace, module.event.inputBlur);
3293 $input.on('click' + eventNamespace, module.event.inputClick);
3294 $input.on('keydown' + eventNamespace, module.event.keydown);
3295 } else {
3296 $container.on('keydown' + eventNamespace, module.event.keydown);
3297 }
3298 }
3299 },
3300
3301 unbind: {
3302 events: function () {
3303 module.debug('Unbinding events');
3304 $container.off(eventNamespace);
3305 if ($input.length) {
3306 $input.off(eventNamespace);
3307 }
3308 }
3309 },
3310
3311 event: {
3312 mouseover: function (event) {
3313 var target = $(event.target);
3314 var date = target.data(metadata.date);
3315 var mousedown = event.buttons === 1;
3316 if (date) {
3317 module.set.focusDate(date, false, true, mousedown);
3318 }
3319 },
3320 mousedown: function (event) {
3321 if ($input.length) {
3322 //prevent the mousedown on the calendar causing the input to lose focus
3323 event.preventDefault();
3324 }
3325 isTouchDown = event.type.indexOf('touch') >= 0;
3326 var target = $(event.target);
3327 var date = target.data(metadata.date);
3328 if (date) {
3329 module.set.focusDate(date, false, true, true);
3330 }
3331 },
3332 mouseup: function (event) {
3333 //ensure input has focus so that it receives keydown events for calendar navigation
3334 module.focus();
3335 event.preventDefault();
3336 event.stopPropagation();
3337 isTouchDown = false;
3338 var target = $(event.target);
3339 if (target.hasClass("disabled")) {
3340 return;
3341 }
3342 var parent = target.parent();
3343 if (parent.data(metadata.date) || parent.data(metadata.focusDate) || parent.data(metadata.mode)) {
3344 //clicked on a child element, switch to parent (used when clicking directly on prev/next <i> icon element)
3345 target = parent;
3346 }
3347 var date = target.data(metadata.date);
3348 var focusDate = target.data(metadata.focusDate);
3349 var mode = target.data(metadata.mode);
3350 if (date) {
3351 var forceSet = target.hasClass(className.today);
3352 module.selectDate(date, forceSet);
3353 }
3354 else if (focusDate) {
3355 module.set.focusDate(focusDate);
3356 }
3357 else if (mode) {
3358 module.set.mode(mode);
3359 }
3360 },
3361 keydown: function (event) {
3362 if (event.keyCode === 27 || event.keyCode === 9) {
3363 //esc || tab
3364 module.popup('hide');
3365 }
3366
3367 if (module.popup('is visible')) {
3368 if (event.keyCode === 37 || event.keyCode === 38 || event.keyCode === 39 || event.keyCode === 40) {
3369 //arrow keys
3370 var mode = module.get.mode();
3371 var bigIncrement = mode === 'day' ? 7 : mode === 'hour' ? 4 : mode === 'minute' ? timeGap['column'] : 3;
3372 var increment = event.keyCode === 37 ? -1 : event.keyCode === 38 ? -bigIncrement : event.keyCode == 39 ? 1 : bigIncrement;
3373 increment *= mode === 'minute' ? settings.minTimeGap : 1;
3374 var focusDate = module.get.focusDate() || module.get.date() || new Date();
3375 var year = focusDate.getFullYear() + (mode === 'year' ? increment : 0);
3376 var month = focusDate.getMonth() + (mode === 'month' ? increment : 0);
3377 var day = focusDate.getDate() + (mode === 'day' ? increment : 0);
3378 var hour = focusDate.getHours() + (mode === 'hour' ? increment : 0);
3379 var minute = focusDate.getMinutes() + (mode === 'minute' ? increment : 0);
3380 var newFocusDate = new Date(year, month, day, hour, minute);
3381 if (settings.type === 'time') {
3382 newFocusDate = module.helper.mergeDateTime(focusDate, newFocusDate);
3383 }
3384 if (module.helper.isDateInRange(newFocusDate, mode)) {
3385 module.set.focusDate(newFocusDate);
3386 }
3387 } else if (event.keyCode === 13) {
3388 //enter
3389 var mode = module.get.mode();
3390 var date = module.get.focusDate();
3391 if (date && !settings.isDisabled(date, mode) && !module.helper.isDisabled(date, mode)) {
3392 module.selectDate(date);
3393 }
3394 //disable form submission:
3395 event.preventDefault();
3396 event.stopPropagation();
3397 }
3398 }
3399
3400 if (event.keyCode === 38 || event.keyCode === 40) {
3401 //arrow-up || arrow-down
3402 event.preventDefault(); //don't scroll
3403 module.popup('show');
3404 }
3405 },
3406 inputChange: function () {
3407 var val = $input.val();
3408 var date = parser.date(val, settings);
3409 module.set.date(date, false);
3410 },
3411 inputFocus: function () {
3412 $container.addClass(className.active);
3413 },
3414 inputBlur: function () {
3415 $container.removeClass(className.active);
3416 if (settings.formatInput) {
3417 var date = module.get.date();
3418 var text = formatter.datetime(date, settings);
3419 $input.val(text);
3420 }
3421 },
3422 inputClick: function () {
3423 module.popup('show');
3424 }
3425 },
3426
3427 get: {
3428 weekOfYear: function(weekYear,weekMonth,weekDay) {
3429 // adapted from http://www.merlyn.demon.co.uk/weekcalc.htm
3430 var ms1d = 864e5, // milliseconds in a day
3431 ms7d = 7 * ms1d; // milliseconds in a week
3432
3433 return function() { // return a closure so constants get calculated only once
3434 var DC3 = Date.UTC(weekYear, weekMonth, weekDay + 3) / ms1d, // an Absolute Day Number
3435 AWN = Math.floor(DC3 / 7), // an Absolute Week Number
3436 Wyr = new Date(AWN * ms7d).getUTCFullYear();
3437
3438 return AWN - Math.floor(Date.UTC(Wyr, 0, 7) / ms7d) + 1;
3439 }();
3440 },
3441 date: function () {
3442 return $module.data(metadata.date) || null;
3443 },
3444 focusDate: function () {
3445 return $module.data(metadata.focusDate) || null;
3446 },
3447 startDate: function () {
3448 var startModule = module.get.calendarModule(settings.startCalendar);
3449 return (startModule ? startModule.get.date() : $module.data(metadata.startDate)) || null;
3450 },
3451 endDate: function () {
3452 var endModule = module.get.calendarModule(settings.endCalendar);
3453 return (endModule ? endModule.get.date() : $module.data(metadata.endDate)) || null;
3454 },
3455 minDate: function() {
3456 return $module.data(metadata.minDate) || null;
3457 },
3458 maxDate: function() {
3459 return $module.data(metadata.maxDate) || null;
3460 },
3461 monthOffset: function () {
3462 return $module.data(metadata.monthOffset) || 0;
3463 },
3464 mode: function () {
3465 //only returns valid modes for the current settings
3466 var mode = $module.data(metadata.mode) || settings.startMode;
3467 var validModes = module.get.validModes();
3468 if ($.inArray(mode, validModes) >= 0) {
3469 return mode;
3470 }
3471 return settings.type === 'time' ? 'hour' :
3472 settings.type === 'month' ? 'month' :
3473 settings.type === 'year' ? 'year' : 'day';
3474 },
3475 validModes: function () {
3476 var validModes = [];
3477 if (settings.type !== 'time') {
3478 if (!settings.disableYear || settings.type === 'year') {
3479 validModes.push('year');
3480 }
3481 if (!(settings.disableMonth || settings.type === 'year') || settings.type === 'month') {
3482 validModes.push('month');
3483 }
3484 if (settings.type.indexOf('date') >= 0) {
3485 validModes.push('day');
3486 }
3487 }
3488 if (settings.type.indexOf('time') >= 0) {
3489 validModes.push('hour');
3490 if (!settings.disableMinute) {
3491 validModes.push('minute');
3492 }
3493 }
3494 return validModes;
3495 },
3496 isTouch: function () {
3497 try {
3498 document.createEvent('TouchEvent');
3499 return true;
3500 }
3501 catch (e) {
3502 return false;
3503 }
3504 },
3505 calendarModule: function (selector) {
3506 if (!selector) {
3507 return null;
3508 }
3509 if (!(selector instanceof $)) {
3510 selector = $module.parent().children(selector).first();
3511 }
3512 //assume range related calendars are using the same namespace
3513 return selector.data(moduleNamespace);
3514 }
3515 },
3516
3517 set: {
3518 date: function (date, updateInput, fireChange) {
3519 updateInput = updateInput !== false;
3520 fireChange = fireChange !== false;
3521 date = module.helper.sanitiseDate(date);
3522 date = module.helper.dateInRange(date);
3523
3524 var mode = module.get.mode();
3525 var text = formatter.datetime(date, settings);
3526 if (fireChange && settings.onChange.call(element, date, text, mode) === false) {
3527 return false;
3528 }
3529
3530 module.set.focusDate(date);
3531
3532 if (settings.isDisabled(date, mode)) {
3533 return false;
3534 }
3535
3536 var endDate = module.get.endDate();
3537 if (!!endDate && !!date && date > endDate) {
3538 //selected date is greater than end date in range, so clear end date
3539 module.set.endDate(undefined);
3540 }
3541 module.set.dataKeyValue(metadata.date, date);
3542
3543 if (updateInput && $input.length) {
3544 $input.val(text);
3545 }
3546 },
3547 startDate: function (date, refreshCalendar) {
3548 date = module.helper.sanitiseDate(date);
3549 var startModule = module.get.calendarModule(settings.startCalendar);
3550 if (startModule) {
3551 startModule.set.date(date);
3552 }
3553 module.set.dataKeyValue(metadata.startDate, date, refreshCalendar);
3554 },
3555 endDate: function (date, refreshCalendar) {
3556 date = module.helper.sanitiseDate(date);
3557 var endModule = module.get.calendarModule(settings.endCalendar);
3558 if (endModule) {
3559 endModule.set.date(date);
3560 }
3561 module.set.dataKeyValue(metadata.endDate, date, refreshCalendar);
3562 },
3563 focusDate: function (date, refreshCalendar, updateFocus, updateRange) {
3564 date = module.helper.sanitiseDate(date);
3565 date = module.helper.dateInRange(date);
3566 var isDay = module.get.mode() === 'day';
3567 var oldFocusDate = module.get.focusDate();
3568 if (isDay && date && oldFocusDate) {
3569 var yearDelta = date.getFullYear() - oldFocusDate.getFullYear();
3570 var monthDelta = yearDelta * 12 + date.getMonth() - oldFocusDate.getMonth();
3571 if (monthDelta) {
3572 var monthOffset = module.get.monthOffset() - monthDelta;
3573 module.set.monthOffset(monthOffset, false);
3574 }
3575 }
3576 var changed = module.set.dataKeyValue(metadata.focusDate, date, refreshCalendar);
3577 updateFocus = (updateFocus !== false && changed && refreshCalendar === false) || focusDateUsedForRange != updateRange;
3578 focusDateUsedForRange = updateRange;
3579 if (updateFocus) {
3580 module.update.focus(updateRange);
3581 }
3582 },
3583 minDate: function (date) {
3584 date = module.helper.sanitiseDate(date);
3585 if (settings.maxDate !== null && settings.maxDate <= date) {
3586 module.verbose('Unable to set minDate variable bigger that maxDate variable', date, settings.maxDate);
3587 } else {
3588 module.setting('minDate', date);
3589 module.set.dataKeyValue(metadata.minDate, date);
3590 }
3591 },
3592 maxDate: function (date) {
3593 date = module.helper.sanitiseDate(date);
3594 if (settings.minDate !== null && settings.minDate >= date) {
3595 module.verbose('Unable to set maxDate variable lower that minDate variable', date, settings.minDate);
3596 } else {
3597 module.setting('maxDate', date);
3598 module.set.dataKeyValue(metadata.maxDate, date);
3599 }
3600 },
3601 monthOffset: function (monthOffset, refreshCalendar) {
3602 var multiMonth = Math.max(settings.multiMonth, 1);
3603 monthOffset = Math.max(1 - multiMonth, Math.min(0, monthOffset));
3604 module.set.dataKeyValue(metadata.monthOffset, monthOffset, refreshCalendar);
3605 },
3606 mode: function (mode, refreshCalendar) {
3607 module.set.dataKeyValue(metadata.mode, mode, refreshCalendar);
3608 },
3609 dataKeyValue: function (key, value, refreshCalendar) {
3610 var oldValue = $module.data(key);
3611 var equal = oldValue === value || (oldValue <= value && oldValue >= value); //equality test for dates and string objects
3612 if (value) {
3613 $module.data(key, value);
3614 } else {
3615 $module.removeData(key);
3616 }
3617 refreshCalendar = refreshCalendar !== false && !equal;
3618 if (refreshCalendar) {
3619 module.refresh();
3620 }
3621 return !equal;
3622 }
3623 },
3624
3625 selectDate: function (date, forceSet) {
3626 module.verbose('New date selection', date)
3627 var mode = module.get.mode();
3628 var complete = forceSet || mode === 'minute' ||
3629 (settings.disableMinute && mode === 'hour') ||
3630 (settings.type === 'date' && mode === 'day') ||
3631 (settings.type === 'month' && mode === 'month') ||
3632 (settings.type === 'year' && mode === 'year');
3633 if (complete) {
3634 var canceled = module.set.date(date) === false;
3635 if (!canceled && settings.closable) {
3636 module.popup('hide');
3637 //if this is a range calendar, show the end date calendar popup and focus the input
3638 var endModule = module.get.calendarModule(settings.endCalendar);
3639 if (endModule) {
3640 endModule.popup('show');
3641 endModule.focus();
3642 }
3643 }
3644 } else {
3645 var newMode = mode === 'year' ? (!settings.disableMonth ? 'month' : 'day') :
3646 mode === 'month' ? 'day' : mode === 'day' ? 'hour' : 'minute';
3647 module.set.mode(newMode);
3648 if (mode === 'hour' || (mode === 'day' && module.get.date())) {
3649 //the user has chosen enough to consider a valid date/time has been chosen
3650 module.set.date(date);
3651 } else {
3652 module.set.focusDate(date);
3653 }
3654 }
3655 },
3656
3657 changeDate: function (date) {
3658 module.set.date(date);
3659 },
3660
3661 clear: function () {
3662 module.set.date(undefined);
3663 },
3664
3665 popup: function () {
3666 return $activator.popup.apply($activator, arguments);
3667 },
3668
3669 focus: function () {
3670 if ($input.length) {
3671 $input.focus();
3672 } else {
3673 $container.focus();
3674 }
3675 },
3676 blur: function () {
3677 if ($input.length) {
3678 $input.blur();
3679 } else {
3680 $container.blur();
3681 }
3682 },
3683
3684 helper: {
3685 isDisabled: function(date, mode) {
3686 return mode === 'day' && ((settings.disabledDaysOfWeek.indexOf(date.getDay()) !== -1) || settings.disabledDates.some(function(d){
3687 if (d instanceof Date) {
3688 return module.helper.dateEqual(date, d, mode);
3689 }
3690 if (d !== null && typeof d === 'object') {
3691 return module.helper.dateEqual(date, d[metadata.date], mode);
3692 }
3693 }));
3694 },
3695 disabledReason: function(date, mode) {
3696 if (mode === 'day') {
3697 for (var i = 0; i < settings.disabledDates.length; i++) {
3698 var d = settings.disabledDates[i];
3699 if (d !== null && typeof d === 'object' && module.helper.dateEqual(date, d[metadata.date], mode)) {
3700 var reason = {};
3701 reason[metadata.message] = d[metadata.message];
3702 return reason;
3703 }
3704 }
3705 }
3706 return null;
3707 },
3708 sanitiseDate: function (date) {
3709 if (!date) {
3710 return undefined;
3711 }
3712 if (!(date instanceof Date)) {
3713 date = parser.date('' + date, settings);
3714 }
3715 if (isNaN(date.getTime())) {
3716 return undefined;
3717 }
3718 return date;
3719 },
3720 dateDiff: function (date1, date2, mode) {
3721 mode = mode || 'day';
3722 var isTimeOnly = settings.type === 'time';
3723 var isYear = mode === 'year';
3724 var isYearOrMonth = isYear || mode === 'month';
3725 var isMinute = mode === 'minute';
3726 var isHourOrMinute = isMinute || mode === 'hour';
3727 //only care about a minute accuracy of settings.minTimeGap
3728 date1 = new Date(
3729 isTimeOnly ? 2000 : date1.getFullYear(),
3730 isTimeOnly ? 0 : isYear ? 0 : date1.getMonth(),
3731 isTimeOnly ? 1 : isYearOrMonth ? 1 : date1.getDate(),
3732 !isHourOrMinute ? 0 : date1.getHours(),
3733 !isMinute ? 0 : settings.minTimeGap * Math.floor(date1.getMinutes() / settings.minTimeGap));
3734 date2 = new Date(
3735 isTimeOnly ? 2000 : date2.getFullYear(),
3736 isTimeOnly ? 0 : isYear ? 0 : date2.getMonth(),
3737 isTimeOnly ? 1 : isYearOrMonth ? 1 : date2.getDate(),
3738 !isHourOrMinute ? 0 : date2.getHours(),
3739 !isMinute ? 0 : settings.minTimeGap * Math.floor(date2.getMinutes() / settings.minTimeGap));
3740 return date2.getTime() - date1.getTime();
3741 },
3742 dateEqual: function (date1, date2, mode) {
3743 return !!date1 && !!date2 && module.helper.dateDiff(date1, date2, mode) === 0;
3744 },
3745 isDateInRange: function (date, mode, minDate, maxDate) {
3746 if (!minDate && !maxDate) {
3747 var startDate = module.get.startDate();
3748 minDate = startDate && settings.minDate ? new Date(Math.max(startDate, settings.minDate)) : startDate || settings.minDate;
3749 maxDate = settings.maxDate;
3750 }
3751 minDate = minDate && new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate(), minDate.getHours(), settings.minTimeGap * Math.ceil(minDate.getMinutes() / settings.minTimeGap));
3752 return !(!date ||
3753 (minDate && module.helper.dateDiff(date, minDate, mode) > 0) ||
3754 (maxDate && module.helper.dateDiff(maxDate, date, mode) > 0));
3755 },
3756 dateInRange: function (date, minDate, maxDate) {
3757 if (!minDate && !maxDate) {
3758 var startDate = module.get.startDate();
3759 minDate = startDate && settings.minDate ? new Date(Math.max(startDate, settings.minDate)) : startDate || settings.minDate;
3760 maxDate = settings.maxDate;
3761 }
3762 minDate = minDate && new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate(), minDate.getHours(), settings.minTimeGap * Math.ceil(minDate.getMinutes() / settings.minTimeGap));
3763 var isTimeOnly = settings.type === 'time';
3764 return !date ? date :
3765 (minDate && module.helper.dateDiff(date, minDate, 'minute') > 0) ?
3766 (isTimeOnly ? module.helper.mergeDateTime(date, minDate) : minDate) :
3767 (maxDate && module.helper.dateDiff(maxDate, date, 'minute') > 0) ?
3768 (isTimeOnly ? module.helper.mergeDateTime(date, maxDate) : maxDate) :
3769 date;
3770 },
3771 mergeDateTime: function (date, time) {
3772 return (!date || !time) ? time :
3773 new Date(date.getFullYear(), date.getMonth(), date.getDate(), time.getHours(), time.getMinutes());
3774 }
3775 },
3776
3777 setting: function (name, value) {
3778 module.debug('Changing setting', name, value);
3779 if ($.isPlainObject(name)) {
3780 $.extend(true, settings, name);
3781 }
3782 else if (value !== undefined) {
3783 if ($.isPlainObject(settings[name])) {
3784 $.extend(true, settings[name], value);
3785 }
3786 else {
3787 settings[name] = value;
3788 }
3789 }
3790 else {
3791 return settings[name];
3792 }
3793 },
3794 internal: function (name, value) {
3795 if( $.isPlainObject(name) ) {
3796 $.extend(true, module, name);
3797 }
3798 else if(value !== undefined) {
3799 module[name] = value;
3800 }
3801 else {
3802 return module[name];
3803 }
3804 },
3805 debug: function () {
3806 if (!settings.silent && settings.debug) {
3807 if (settings.performance) {
3808 module.performance.log(arguments);
3809 }
3810 else {
3811 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
3812 module.debug.apply(console, arguments);
3813 }
3814 }
3815 },
3816 verbose: function () {
3817 if (!settings.silent && settings.verbose && settings.debug) {
3818 if (settings.performance) {
3819 module.performance.log(arguments);
3820 }
3821 else {
3822 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
3823 module.verbose.apply(console, arguments);
3824 }
3825 }
3826 },
3827 error: function () {
3828 if (!settings.silent) {
3829 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
3830 module.error.apply(console, arguments);
3831 }
3832 },
3833 performance: {
3834 log: function (message) {
3835 var
3836 currentTime,
3837 executionTime,
3838 previousTime
3839 ;
3840 if (settings.performance) {
3841 currentTime = new Date().getTime();
3842 previousTime = time || currentTime;
3843 executionTime = currentTime - previousTime;
3844 time = currentTime;
3845 performance.push({
3846 'Name': message[0],
3847 'Arguments': [].slice.call(message, 1) || '',
3848 'Element': element,
3849 'Execution Time': executionTime
3850 });
3851 }
3852 clearTimeout(module.performance.timer);
3853 module.performance.timer = setTimeout(module.performance.display, 500);
3854 },
3855 display: function () {
3856 var
3857 title = settings.name + ':',
3858 totalTime = 0
3859 ;
3860 time = false;
3861 clearTimeout(module.performance.timer);
3862 $.each(performance, function (index, data) {
3863 totalTime += data['Execution Time'];
3864 });
3865 title += ' ' + totalTime + 'ms';
3866 if (moduleSelector) {
3867 title += ' \'' + moduleSelector + '\'';
3868 }
3869 if ((console.group !== undefined || console.table !== undefined) && performance.length > 0) {
3870 console.groupCollapsed(title);
3871 if (console.table) {
3872 console.table(performance);
3873 }
3874 else {
3875 $.each(performance, function (index, data) {
3876 console.log(data['Name'] + ': ' + data['Execution Time'] + 'ms');
3877 });
3878 }
3879 console.groupEnd();
3880 }
3881 performance = [];
3882 }
3883 },
3884 invoke: function (query, passedArguments, context) {
3885 var
3886 object = instance,
3887 maxDepth,
3888 found,
3889 response
3890 ;
3891 passedArguments = passedArguments || queryArguments;
3892 context = element || context;
3893 if (typeof query == 'string' && object !== undefined) {
3894 query = query.split(/[\. ]/);
3895 maxDepth = query.length - 1;
3896 $.each(query, function (depth, value) {
3897 var camelCaseValue = (depth != maxDepth)
3898 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
3899 : query
3900 ;
3901 if ($.isPlainObject(object[camelCaseValue]) && (depth != maxDepth)) {
3902 object = object[camelCaseValue];
3903 }
3904 else if (object[camelCaseValue] !== undefined) {
3905 found = object[camelCaseValue];
3906 return false;
3907 }
3908 else if ($.isPlainObject(object[value]) && (depth != maxDepth)) {
3909 object = object[value];
3910 }
3911 else if (object[value] !== undefined) {
3912 found = object[value];
3913 return false;
3914 }
3915 else {
3916 module.error(error.method, query);
3917 return false;
3918 }
3919 });
3920 }
3921 if ($.isFunction(found)) {
3922 response = found.apply(context, passedArguments);
3923 }
3924 else if (found !== undefined) {
3925 response = found;
3926 }
3927 if (Array.isArray(returnedValue)) {
3928 returnedValue.push(response);
3929 }
3930 else if (returnedValue !== undefined) {
3931 returnedValue = [returnedValue, response];
3932 }
3933 else if (response !== undefined) {
3934 returnedValue = response;
3935 }
3936 return found;
3937 }
3938 };
3939
3940 if (methodInvoked) {
3941 if (instance === undefined) {
3942 module.initialize();
3943 }
3944 module.invoke(query);
3945 }
3946 else {
3947 if (instance !== undefined) {
3948 instance.invoke('destroy');
3949 }
3950 module.initialize();
3951 }
3952 })
3953 ;
3954 return (returnedValue !== undefined)
3955 ? returnedValue
3956 : this
3957 ;
3958};
3959
3960$.fn.calendar.settings = {
3961
3962 name : 'Calendar',
3963 namespace : 'calendar',
3964
3965 silent: false,
3966 debug: false,
3967 verbose: false,
3968 performance: false,
3969
3970 type : 'datetime', // picker type, can be 'datetime', 'date', 'time', 'month', or 'year'
3971 firstDayOfWeek : 0, // day for first day column (0 = Sunday)
3972 constantHeight : true, // add rows to shorter months to keep day calendar height consistent (6 rows)
3973 today : false, // show a 'today/now' button at the bottom of the calendar
3974 closable : true, // close the popup after selecting a date/time
3975 monthFirst : true, // month before day when parsing/converting date from/to text
3976 touchReadonly : true, // set input to readonly on touch devices
3977 inline : false, // create the calendar inline instead of inside a popup
3978 on : null, // when to show the popup (defaults to 'focus' for input, 'click' for others)
3979 initialDate : null, // date to display initially when no date is selected (null = now)
3980 startMode : false, // display mode to start in, can be 'year', 'month', 'day', 'hour', 'minute' (false = 'day')
3981 minDate : null, // minimum date/time that can be selected, dates/times before are disabled
3982 maxDate : null, // maximum date/time that can be selected, dates/times after are disabled
3983 ampm : true, // show am/pm in time mode
3984 disableYear : false, // disable year selection mode
3985 disableMonth : false, // disable month selection mode
3986 disableMinute : false, // disable minute selection mode
3987 formatInput : true, // format the input text upon input blur and module creation
3988 startCalendar : null, // jquery object or selector for another calendar that represents the start date of a date range
3989 endCalendar : null, // jquery object or selector for another calendar that represents the end date of a date range
3990 multiMonth : 1, // show multiple months when in 'day' mode
3991 minTimeGap : 5,
3992 showWeekNumbers : null, // show Number of Week at the very first column of a dayView
3993 disabledDates : [], // specific day(s) which won't be selectable and contain additional information.
3994 disabledDaysOfWeek : [], // day(s) which won't be selectable(s) (0 = Sunday)
3995 // popup options ('popup', 'on', 'hoverable', and show/hide callbacks are overridden)
3996 popupOptions: {
3997 position: 'bottom left',
3998 lastResort: 'bottom left',
3999 prefer: 'opposite',
4000 hideOnScroll: false
4001 },
4002
4003 text: {
4004 days: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
4005 months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
4006 monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
4007 today: 'Today',
4008 now: 'Now',
4009 am: 'AM',
4010 pm: 'PM',
4011 weekNo: 'Week'
4012 },
4013
4014 formatter: {
4015 header: function (date, mode, settings) {
4016 return mode === 'year' ? settings.formatter.yearHeader(date, settings) :
4017 mode === 'month' ? settings.formatter.monthHeader(date, settings) :
4018 mode === 'day' ? settings.formatter.dayHeader(date, settings) :
4019 mode === 'hour' ? settings.formatter.hourHeader(date, settings) :
4020 settings.formatter.minuteHeader(date, settings);
4021 },
4022 yearHeader: function (date, settings) {
4023 var decadeYear = Math.ceil(date.getFullYear() / 10) * 10;
4024 return (decadeYear - 9) + ' - ' + (decadeYear + 2);
4025 },
4026 monthHeader: function (date, settings) {
4027 return date.getFullYear();
4028 },
4029 dayHeader: function (date, settings) {
4030 var month = settings.text.months[date.getMonth()];
4031 var year = date.getFullYear();
4032 return month + ' ' + year;
4033 },
4034 hourHeader: function (date, settings) {
4035 return settings.formatter.date(date, settings);
4036 },
4037 minuteHeader: function (date, settings) {
4038 return settings.formatter.date(date, settings);
4039 },
4040 dayColumnHeader: function (day, settings) {
4041 return settings.text.days[day];
4042 },
4043 datetime: function (date, settings) {
4044 if (!date) {
4045 return '';
4046 }
4047 var day = settings.type === 'time' ? '' : settings.formatter.date(date, settings);
4048 var time = settings.type.indexOf('time') < 0 ? '' : settings.formatter.time(date, settings, false);
4049 var separator = settings.type === 'datetime' ? ' ' : '';
4050 return day + separator + time;
4051 },
4052 date: function (date, settings) {
4053 if (!date) {
4054 return '';
4055 }
4056 var day = date.getDate();
4057 var month = settings.text.months[date.getMonth()];
4058 var year = date.getFullYear();
4059 return settings.type === 'year' ? year :
4060 settings.type === 'month' ? month + ' ' + year :
4061 (settings.monthFirst ? month + ' ' + day : day + ' ' + month) + ', ' + year;
4062 },
4063 time: function (date, settings, forCalendar) {
4064 if (!date) {
4065 return '';
4066 }
4067 var hour = date.getHours();
4068 var minute = date.getMinutes();
4069 var ampm = '';
4070 if (settings.ampm) {
4071 ampm = ' ' + (hour < 12 ? settings.text.am : settings.text.pm);
4072 hour = hour === 0 ? 12 : hour > 12 ? hour - 12 : hour;
4073 }
4074 return hour + ':' + (minute < 10 ? '0' : '') + minute + ampm;
4075 },
4076 today: function (settings) {
4077 return settings.type === 'date' ? settings.text.today : settings.text.now;
4078 },
4079 cell: function (cell, date, cellOptions) {
4080 }
4081 },
4082
4083 parser: {
4084 date: function (text, settings) {
4085 if (!text) {
4086 return null;
4087 }
4088 text = ('' + text).trim().toLowerCase();
4089 if (text.length === 0) {
4090 return null;
4091 }
4092
4093 var i, j, k;
4094 var minute = -1, hour = -1, day = -1, month = -1, year = -1;
4095 var isAm = undefined;
4096
4097 var isTimeOnly = settings.type === 'time';
4098 var isDateOnly = settings.type.indexOf('time') < 0;
4099
4100 var words = text.split(settings.regExp.dateWords);
4101 var numbers = text.split(settings.regExp.dateNumbers);
4102
4103 if (!isDateOnly) {
4104 //am/pm
4105 isAm = $.inArray(settings.text.am.toLowerCase(), words) >= 0 ? true :
4106 $.inArray(settings.text.pm.toLowerCase(), words) >= 0 ? false : undefined;
4107
4108 //time with ':'
4109 for (i = 0; i < numbers.length; i++) {
4110 var number = numbers[i];
4111 if (number.indexOf(':') >= 0) {
4112 if (hour < 0 || minute < 0) {
4113 var parts = number.split(':');
4114 for (k = 0; k < Math.min(2, parts.length); k++) {
4115 j = parseInt(parts[k]);
4116 if (isNaN(j)) {
4117 j = 0;
4118 }
4119 if (k === 0) {
4120 hour = j % 24;
4121 } else {
4122 minute = j % 60;
4123 }
4124 }
4125 }
4126 numbers.splice(i, 1);
4127 }
4128 }
4129 }
4130
4131 if (!isTimeOnly) {
4132 //textual month
4133 for (i = 0; i < words.length; i++) {
4134 var word = words[i];
4135 if (word.length <= 0) {
4136 continue;
4137 }
4138 word = word.substring(0, Math.min(word.length, 3));
4139 for (j = 0; j < settings.text.months.length; j++) {
4140 var monthString = settings.text.months[j];
4141 monthString = monthString.substring(0, Math.min(word.length, Math.min(monthString.length, 3))).toLowerCase();
4142 if (monthString === word) {
4143 month = j + 1;
4144 break;
4145 }
4146 }
4147 if (month >= 0) {
4148 break;
4149 }
4150 }
4151
4152 //year > 59
4153 for (i = 0; i < numbers.length; i++) {
4154 j = parseInt(numbers[i]);
4155 if (isNaN(j)) {
4156 continue;
4157 }
4158 if (j > 59) {
4159 year = j;
4160 numbers.splice(i, 1);
4161 break;
4162 }
4163 }
4164
4165 //numeric month
4166 if (month < 0) {
4167 for (i = 0; i < numbers.length; i++) {
4168 k = i > 1 || settings.monthFirst ? i : i === 1 ? 0 : 1;
4169 j = parseInt(numbers[k]);
4170 if (isNaN(j)) {
4171 continue;
4172 }
4173 if (1 <= j && j <= 12) {
4174 month = j;
4175 numbers.splice(k, 1);
4176 break;
4177 }
4178 }
4179 }
4180
4181 //day
4182 for (i = 0; i < numbers.length; i++) {
4183 j = parseInt(numbers[i]);
4184 if (isNaN(j)) {
4185 continue;
4186 }
4187 if (1 <= j && j <= 31) {
4188 day = j;
4189 numbers.splice(i, 1);
4190 break;
4191 }
4192 }
4193
4194 //year <= 59
4195 if (year < 0) {
4196 for (i = numbers.length - 1; i >= 0; i--) {
4197 j = parseInt(numbers[i]);
4198 if (isNaN(j)) {
4199 continue;
4200 }
4201 if (j < 99) {
4202 j += 2000;
4203 }
4204 year = j;
4205 numbers.splice(i, 1);
4206 break;
4207 }
4208 }
4209 }
4210
4211 if (!isDateOnly) {
4212 //hour
4213 if (hour < 0) {
4214 for (i = 0; i < numbers.length; i++) {
4215 j = parseInt(numbers[i]);
4216 if (isNaN(j)) {
4217 continue;
4218 }
4219 if (0 <= j && j <= 23) {
4220 hour = j;
4221 numbers.splice(i, 1);
4222 break;
4223 }
4224 }
4225 }
4226
4227 //minute
4228 if (minute < 0) {
4229 for (i = 0; i < numbers.length; i++) {
4230 j = parseInt(numbers[i]);
4231 if (isNaN(j)) {
4232 continue;
4233 }
4234 if (0 <= j && j <= 59) {
4235 minute = j;
4236 numbers.splice(i, 1);
4237 break;
4238 }
4239 }
4240 }
4241 }
4242
4243 if (minute < 0 && hour < 0 && day < 0 && month < 0 && year < 0) {
4244 return null;
4245 }
4246
4247 if (minute < 0) {
4248 minute = 0;
4249 }
4250 if (hour < 0) {
4251 hour = 0;
4252 }
4253 if (day < 0) {
4254 day = 1;
4255 }
4256 if (month < 0) {
4257 month = 1;
4258 }
4259 if (year < 0) {
4260 year = new Date().getFullYear();
4261 }
4262
4263 if (isAm !== undefined) {
4264 if (isAm) {
4265 if (hour === 12) {
4266 hour = 0;
4267 }
4268 } else if (hour < 12) {
4269 hour += 12;
4270 }
4271 }
4272
4273 var date = new Date(year, month - 1, day, hour, minute);
4274 if (date.getMonth() !== month - 1 || date.getFullYear() !== year) {
4275 //month or year don't match up, switch to last day of the month
4276 date = new Date(year, month, 0, hour, minute);
4277 }
4278 return isNaN(date.getTime()) ? null : date;
4279 }
4280 },
4281
4282 // callback when date changes, return false to cancel the change
4283 onChange: function (date, text, mode) {
4284 return true;
4285 },
4286
4287 // callback before show animation, return false to prevent show
4288 onShow: function () {
4289 },
4290
4291 // callback after show animation
4292 onVisible: function () {
4293 },
4294
4295 // callback before hide animation, return false to prevent hide
4296 onHide: function () {
4297 },
4298
4299 // callback after hide animation
4300 onHidden: function () {
4301 },
4302
4303 // is the given date disabled?
4304 isDisabled: function (date, mode) {
4305 return false;
4306 },
4307
4308 selector: {
4309 popup: '.ui.popup',
4310 input: 'input',
4311 activator: 'input'
4312 },
4313
4314 regExp: {
4315 dateWords: /[^A-Za-z\u00C0-\u024F]+/g,
4316 dateNumbers: /[^\d:]+/g
4317 },
4318
4319 error: {
4320 popup: 'UI Popup, a required component is not included in this page',
4321 method: 'The method you called is not defined.'
4322 },
4323
4324 className: {
4325 calendar: 'calendar',
4326 active: 'active',
4327 popup: 'ui popup',
4328 grid: 'ui equal width grid',
4329 column: 'column',
4330 table: 'ui celled center aligned unstackable table',
4331 prev: 'prev link',
4332 next: 'next link',
4333 prevIcon: 'chevron left icon',
4334 nextIcon: 'chevron right icon',
4335 link: 'link',
4336 cell: 'link',
4337 disabledCell: 'disabled',
4338 adjacentCell: 'adjacent',
4339 activeCell: 'active',
4340 rangeCell: 'range',
4341 focusCell: 'focus',
4342 todayCell: 'today',
4343 today: 'today link'
4344 },
4345
4346 metadata: {
4347 date: 'date',
4348 focusDate: 'focusDate',
4349 startDate: 'startDate',
4350 endDate: 'endDate',
4351 minDate: 'minDate',
4352 maxDate: 'maxDate',
4353 mode: 'mode',
4354 monthOffset: 'monthOffset',
4355 message: 'message'
4356 }
4357};
4358
4359})(jQuery, window, document);
4360
4361/*!
4362 * # Semantic UI 2.7.2 - Checkbox
4363 * http://github.com/semantic-org/semantic-ui/
4364 *
4365 *
4366 * Released under the MIT license
4367 * http://opensource.org/licenses/MIT
4368 *
4369 */
4370
4371;(function ($, window, document, undefined) {
4372
4373'use strict';
4374
4375$.isFunction = $.isFunction || function(obj) {
4376 return typeof obj === "function" && typeof obj.nodeType !== "number";
4377};
4378
4379window = (typeof window != 'undefined' && window.Math == Math)
4380 ? window
4381 : (typeof self != 'undefined' && self.Math == Math)
4382 ? self
4383 : Function('return this')()
4384;
4385
4386$.fn.checkbox = function(parameters) {
4387 var
4388 $allModules = $(this),
4389 moduleSelector = $allModules.selector || '',
4390
4391 time = new Date().getTime(),
4392 performance = [],
4393
4394 query = arguments[0],
4395 methodInvoked = (typeof query == 'string'),
4396 queryArguments = [].slice.call(arguments, 1),
4397 returnedValue
4398 ;
4399
4400 $allModules
4401 .each(function() {
4402 var
4403 settings = $.extend(true, {}, $.fn.checkbox.settings, parameters),
4404
4405 className = settings.className,
4406 namespace = settings.namespace,
4407 selector = settings.selector,
4408 error = settings.error,
4409
4410 eventNamespace = '.' + namespace,
4411 moduleNamespace = 'module-' + namespace,
4412
4413 $module = $(this),
4414 $label = $(this).children(selector.label),
4415 $input = $(this).children(selector.input),
4416 input = $input[0],
4417
4418 initialLoad = false,
4419 shortcutPressed = false,
4420 instance = $module.data(moduleNamespace),
4421
4422 observer,
4423 element = this,
4424 module
4425 ;
4426
4427 module = {
4428
4429 initialize: function() {
4430 module.verbose('Initializing checkbox', settings);
4431
4432 module.create.label();
4433 module.bind.events();
4434
4435 module.set.tabbable();
4436 module.hide.input();
4437
4438 module.observeChanges();
4439 module.instantiate();
4440 module.setup();
4441 },
4442
4443 instantiate: function() {
4444 module.verbose('Storing instance of module', module);
4445 instance = module;
4446 $module
4447 .data(moduleNamespace, module)
4448 ;
4449 },
4450
4451 destroy: function() {
4452 module.verbose('Destroying module');
4453 module.unbind.events();
4454 module.show.input();
4455 $module.removeData(moduleNamespace);
4456 },
4457
4458 fix: {
4459 reference: function() {
4460 if( $module.is(selector.input) ) {
4461 module.debug('Behavior called on <input> adjusting invoked element');
4462 $module = $module.closest(selector.checkbox);
4463 module.refresh();
4464 }
4465 }
4466 },
4467
4468 setup: function() {
4469 module.set.initialLoad();
4470 if( module.is.indeterminate() ) {
4471 module.debug('Initial value is indeterminate');
4472 module.indeterminate();
4473 }
4474 else if( module.is.checked() ) {
4475 module.debug('Initial value is checked');
4476 module.check();
4477 }
4478 else {
4479 module.debug('Initial value is unchecked');
4480 module.uncheck();
4481 }
4482 module.remove.initialLoad();
4483 },
4484
4485 refresh: function() {
4486 $label = $module.children(selector.label);
4487 $input = $module.children(selector.input);
4488 input = $input[0];
4489 },
4490
4491 hide: {
4492 input: function() {
4493 module.verbose('Modifying <input> z-index to be unselectable');
4494 $input.addClass(className.hidden);
4495 }
4496 },
4497 show: {
4498 input: function() {
4499 module.verbose('Modifying <input> z-index to be selectable');
4500 $input.removeClass(className.hidden);
4501 }
4502 },
4503
4504 observeChanges: function() {
4505 if('MutationObserver' in window) {
4506 observer = new MutationObserver(function(mutations) {
4507 module.debug('DOM tree modified, updating selector cache');
4508 module.refresh();
4509 });
4510 observer.observe(element, {
4511 childList : true,
4512 subtree : true
4513 });
4514 module.debug('Setting up mutation observer', observer);
4515 }
4516 },
4517
4518 attachEvents: function(selector, event) {
4519 var
4520 $element = $(selector)
4521 ;
4522 event = $.isFunction(module[event])
4523 ? module[event]
4524 : module.toggle
4525 ;
4526 if($element.length > 0) {
4527 module.debug('Attaching checkbox events to element', selector, event);
4528 $element
4529 .on('click' + eventNamespace, event)
4530 ;
4531 }
4532 else {
4533 module.error(error.notFound);
4534 }
4535 },
4536
4537 event: {
4538 change: function(event) {
4539 if( !module.should.ignoreCallbacks() ) {
4540 settings.onChange.call(input);
4541 }
4542 },
4543 click: function(event) {
4544 var
4545 $target = $(event.target)
4546 ;
4547 if( $target.is(selector.input) ) {
4548 module.verbose('Using default check action on initialized checkbox');
4549 return;
4550 }
4551 if( $target.is(selector.link) ) {
4552 module.debug('Clicking link inside checkbox, skipping toggle');
4553 return;
4554 }
4555 module.toggle();
4556 $input.focus();
4557 event.preventDefault();
4558 },
4559 keydown: function(event) {
4560 var
4561 key = event.which,
4562 keyCode = {
4563 enter : 13,
4564 space : 32,
4565 escape : 27,
4566 left : 37,
4567 up : 38,
4568 right : 39,
4569 down : 40
4570 }
4571 ;
4572
4573 var r = module.get.radios(),
4574 rIndex = r.index($module),
4575 rLen = r.length,
4576 checkIndex = false;
4577
4578 if(key == keyCode.left || key == keyCode.up) {
4579 checkIndex = (rIndex === 0 ? rLen : rIndex) - 1;
4580 } else if(key == keyCode.right || key == keyCode.down) {
4581 checkIndex = rIndex === rLen-1 ? 0 : rIndex+1;
4582 }
4583
4584 if (!module.should.ignoreCallbacks() && checkIndex !== false) {
4585 if(settings.beforeUnchecked.apply(input)===false) {
4586 module.verbose('Option not allowed to be unchecked, cancelling key navigation');
4587 return false;
4588 }
4589 if (settings.beforeChecked.apply($(r[checkIndex]).children(selector.input)[0])===false) {
4590 module.verbose('Next option should not allow check, cancelling key navigation');
4591 return false;
4592 }
4593 }
4594
4595 if(key == keyCode.escape) {
4596 module.verbose('Escape key pressed blurring field');
4597 $input.blur();
4598 shortcutPressed = true;
4599 }
4600 else if(!event.ctrlKey && ( key == keyCode.space || key == keyCode.enter) ) {
4601 module.verbose('Enter/space key pressed, toggling checkbox');
4602 module.toggle();
4603 shortcutPressed = true;
4604 }
4605 else {
4606 shortcutPressed = false;
4607 }
4608 },
4609 keyup: function(event) {
4610 if(shortcutPressed) {
4611 event.preventDefault();
4612 }
4613 }
4614 },
4615
4616 check: function() {
4617 if( !module.should.allowCheck() ) {
4618 return;
4619 }
4620 module.debug('Checking checkbox', $input);
4621 module.set.checked();
4622 if( !module.should.ignoreCallbacks() ) {
4623 settings.onChecked.call(input);
4624 module.trigger.change();
4625 }
4626 },
4627
4628 uncheck: function() {
4629 if( !module.should.allowUncheck() ) {
4630 return;
4631 }
4632 module.debug('Unchecking checkbox');
4633 module.set.unchecked();
4634 if( !module.should.ignoreCallbacks() ) {
4635 settings.onUnchecked.call(input);
4636 module.trigger.change();
4637 }
4638 },
4639
4640 indeterminate: function() {
4641 if( module.should.allowIndeterminate() ) {
4642 module.debug('Checkbox is already indeterminate');
4643 return;
4644 }
4645 module.debug('Making checkbox indeterminate');
4646 module.set.indeterminate();
4647 if( !module.should.ignoreCallbacks() ) {
4648 settings.onIndeterminate.call(input);
4649 module.trigger.change();
4650 }
4651 },
4652
4653 determinate: function() {
4654 if( module.should.allowDeterminate() ) {
4655 module.debug('Checkbox is already determinate');
4656 return;
4657 }
4658 module.debug('Making checkbox determinate');
4659 module.set.determinate();
4660 if( !module.should.ignoreCallbacks() ) {
4661 settings.onDeterminate.call(input);
4662 module.trigger.change();
4663 }
4664 },
4665
4666 enable: function() {
4667 if( module.is.enabled() ) {
4668 module.debug('Checkbox is already enabled');
4669 return;
4670 }
4671 module.debug('Enabling checkbox');
4672 module.set.enabled();
4673 if( !module.should.ignoreCallbacks() ) {
4674 settings.onEnable.call(input);
4675 // preserve legacy callbacks
4676 settings.onEnabled.call(input);
4677 module.trigger.change();
4678 }
4679 },
4680
4681 disable: function() {
4682 if( module.is.disabled() ) {
4683 module.debug('Checkbox is already disabled');
4684 return;
4685 }
4686 module.debug('Disabling checkbox');
4687 module.set.disabled();
4688 if( !module.should.ignoreCallbacks() ) {
4689 settings.onDisable.call(input);
4690 // preserve legacy callbacks
4691 settings.onDisabled.call(input);
4692 module.trigger.change();
4693 }
4694 },
4695
4696 get: {
4697 radios: function() {
4698 var
4699 name = module.get.name()
4700 ;
4701 return $('input[name="' + name + '"]').closest(selector.checkbox);
4702 },
4703 otherRadios: function() {
4704 return module.get.radios().not($module);
4705 },
4706 name: function() {
4707 return $input.attr('name');
4708 }
4709 },
4710
4711 is: {
4712 initialLoad: function() {
4713 return initialLoad;
4714 },
4715 radio: function() {
4716 return ($input.hasClass(className.radio) || $input.attr('type') == 'radio');
4717 },
4718 indeterminate: function() {
4719 return $input.prop('indeterminate') !== undefined && $input.prop('indeterminate');
4720 },
4721 checked: function() {
4722 return $input.prop('checked') !== undefined && $input.prop('checked');
4723 },
4724 disabled: function() {
4725 return $input.prop('disabled') !== undefined && $input.prop('disabled');
4726 },
4727 enabled: function() {
4728 return !module.is.disabled();
4729 },
4730 determinate: function() {
4731 return !module.is.indeterminate();
4732 },
4733 unchecked: function() {
4734 return !module.is.checked();
4735 }
4736 },
4737
4738 should: {
4739 allowCheck: function() {
4740 if(module.is.determinate() && module.is.checked() && !module.is.initialLoad() ) {
4741 module.debug('Should not allow check, checkbox is already checked');
4742 return false;
4743 }
4744 if(!module.should.ignoreCallbacks() && settings.beforeChecked.apply(input) === false) {
4745 module.debug('Should not allow check, beforeChecked cancelled');
4746 return false;
4747 }
4748 return true;
4749 },
4750 allowUncheck: function() {
4751 if(module.is.determinate() && module.is.unchecked() && !module.is.initialLoad() ) {
4752 module.debug('Should not allow uncheck, checkbox is already unchecked');
4753 return false;
4754 }
4755 if(!module.should.ignoreCallbacks() && settings.beforeUnchecked.apply(input) === false) {
4756 module.debug('Should not allow uncheck, beforeUnchecked cancelled');
4757 return false;
4758 }
4759 return true;
4760 },
4761 allowIndeterminate: function() {
4762 if(module.is.indeterminate() && !module.is.initialLoad() ) {
4763 module.debug('Should not allow indeterminate, checkbox is already indeterminate');
4764 return false;
4765 }
4766 if(!module.should.ignoreCallbacks() && settings.beforeIndeterminate.apply(input) === false) {
4767 module.debug('Should not allow indeterminate, beforeIndeterminate cancelled');
4768 return false;
4769 }
4770 return true;
4771 },
4772 allowDeterminate: function() {
4773 if(module.is.determinate() && !module.is.initialLoad() ) {
4774 module.debug('Should not allow determinate, checkbox is already determinate');
4775 return false;
4776 }
4777 if(!module.should.ignoreCallbacks() && settings.beforeDeterminate.apply(input) === false) {
4778 module.debug('Should not allow determinate, beforeDeterminate cancelled');
4779 return false;
4780 }
4781 return true;
4782 },
4783 ignoreCallbacks: function() {
4784 return (initialLoad && !settings.fireOnInit);
4785 }
4786 },
4787
4788 can: {
4789 change: function() {
4790 return !( $module.hasClass(className.disabled) || $module.hasClass(className.readOnly) || $input.prop('disabled') || $input.prop('readonly') );
4791 },
4792 uncheck: function() {
4793 return (typeof settings.uncheckable === 'boolean')
4794 ? settings.uncheckable
4795 : !module.is.radio()
4796 ;
4797 }
4798 },
4799
4800 set: {
4801 initialLoad: function() {
4802 initialLoad = true;
4803 },
4804 checked: function() {
4805 module.verbose('Setting class to checked');
4806 $module
4807 .removeClass(className.indeterminate)
4808 .addClass(className.checked)
4809 ;
4810 if( module.is.radio() ) {
4811 module.uncheckOthers();
4812 }
4813 if(!module.is.indeterminate() && module.is.checked()) {
4814 module.debug('Input is already checked, skipping input property change');
4815 return;
4816 }
4817 module.verbose('Setting state to checked', input);
4818 $input
4819 .prop('indeterminate', false)
4820 .prop('checked', true)
4821 ;
4822 },
4823 unchecked: function() {
4824 module.verbose('Removing checked class');
4825 $module
4826 .removeClass(className.indeterminate)
4827 .removeClass(className.checked)
4828 ;
4829 if(!module.is.indeterminate() && module.is.unchecked() ) {
4830 module.debug('Input is already unchecked');
4831 return;
4832 }
4833 module.debug('Setting state to unchecked');
4834 $input
4835 .prop('indeterminate', false)
4836 .prop('checked', false)
4837 ;
4838 },
4839 indeterminate: function() {
4840 module.verbose('Setting class to indeterminate');
4841 $module
4842 .addClass(className.indeterminate)
4843 ;
4844 if( module.is.indeterminate() ) {
4845 module.debug('Input is already indeterminate, skipping input property change');
4846 return;
4847 }
4848 module.debug('Setting state to indeterminate');
4849 $input
4850 .prop('indeterminate', true)
4851 ;
4852 },
4853 determinate: function() {
4854 module.verbose('Removing indeterminate class');
4855 $module
4856 .removeClass(className.indeterminate)
4857 ;
4858 if( module.is.determinate() ) {
4859 module.debug('Input is already determinate, skipping input property change');
4860 return;
4861 }
4862 module.debug('Setting state to determinate');
4863 $input
4864 .prop('indeterminate', false)
4865 ;
4866 },
4867 disabled: function() {
4868 module.verbose('Setting class to disabled');
4869 $module
4870 .addClass(className.disabled)
4871 ;
4872 if( module.is.disabled() ) {
4873 module.debug('Input is already disabled, skipping input property change');
4874 return;
4875 }
4876 module.debug('Setting state to disabled');
4877 $input
4878 .prop('disabled', 'disabled')
4879 ;
4880 },
4881 enabled: function() {
4882 module.verbose('Removing disabled class');
4883 $module.removeClass(className.disabled);
4884 if( module.is.enabled() ) {
4885 module.debug('Input is already enabled, skipping input property change');
4886 return;
4887 }
4888 module.debug('Setting state to enabled');
4889 $input
4890 .prop('disabled', false)
4891 ;
4892 },
4893 tabbable: function() {
4894 module.verbose('Adding tabindex to checkbox');
4895 if( $input.attr('tabindex') === undefined) {
4896 $input.attr('tabindex', 0);
4897 }
4898 }
4899 },
4900
4901 remove: {
4902 initialLoad: function() {
4903 initialLoad = false;
4904 }
4905 },
4906
4907 trigger: {
4908 change: function() {
4909 var
4910 events = document.createEvent('HTMLEvents'),
4911 inputElement = $input[0]
4912 ;
4913 if(inputElement) {
4914 module.verbose('Triggering native change event');
4915 events.initEvent('change', true, false);
4916 inputElement.dispatchEvent(events);
4917 }
4918 }
4919 },
4920
4921
4922 create: {
4923 label: function() {
4924 if($input.prevAll(selector.label).length > 0) {
4925 $input.prev(selector.label).detach().insertAfter($input);
4926 module.debug('Moving existing label', $label);
4927 }
4928 else if( !module.has.label() ) {
4929 $label = $('<label>').insertAfter($input);
4930 module.debug('Creating label', $label);
4931 }
4932 }
4933 },
4934
4935 has: {
4936 label: function() {
4937 return ($label.length > 0);
4938 }
4939 },
4940
4941 bind: {
4942 events: function() {
4943 module.verbose('Attaching checkbox events');
4944 $module
4945 .on('click' + eventNamespace, module.event.click)
4946 .on('change' + eventNamespace, module.event.change)
4947 .on('keydown' + eventNamespace, selector.input, module.event.keydown)
4948 .on('keyup' + eventNamespace, selector.input, module.event.keyup)
4949 ;
4950 }
4951 },
4952
4953 unbind: {
4954 events: function() {
4955 module.debug('Removing events');
4956 $module
4957 .off(eventNamespace)
4958 ;
4959 }
4960 },
4961
4962 uncheckOthers: function() {
4963 var
4964 $radios = module.get.otherRadios()
4965 ;
4966 module.debug('Unchecking other radios', $radios);
4967 $radios.removeClass(className.checked);
4968 },
4969
4970 toggle: function() {
4971 if( !module.can.change() ) {
4972 if(!module.is.radio()) {
4973 module.debug('Checkbox is read-only or disabled, ignoring toggle');
4974 }
4975 return;
4976 }
4977 if( module.is.indeterminate() || module.is.unchecked() ) {
4978 module.debug('Currently unchecked');
4979 module.check();
4980 }
4981 else if( module.is.checked() && module.can.uncheck() ) {
4982 module.debug('Currently checked');
4983 module.uncheck();
4984 }
4985 },
4986 setting: function(name, value) {
4987 module.debug('Changing setting', name, value);
4988 if( $.isPlainObject(name) ) {
4989 $.extend(true, settings, name);
4990 }
4991 else if(value !== undefined) {
4992 if($.isPlainObject(settings[name])) {
4993 $.extend(true, settings[name], value);
4994 }
4995 else {
4996 settings[name] = value;
4997 }
4998 }
4999 else {
5000 return settings[name];
5001 }
5002 },
5003 internal: function(name, value) {
5004 if( $.isPlainObject(name) ) {
5005 $.extend(true, module, name);
5006 }
5007 else if(value !== undefined) {
5008 module[name] = value;
5009 }
5010 else {
5011 return module[name];
5012 }
5013 },
5014 debug: function() {
5015 if(!settings.silent && settings.debug) {
5016 if(settings.performance) {
5017 module.performance.log(arguments);
5018 }
5019 else {
5020 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
5021 module.debug.apply(console, arguments);
5022 }
5023 }
5024 },
5025 verbose: function() {
5026 if(!settings.silent && settings.verbose && settings.debug) {
5027 if(settings.performance) {
5028 module.performance.log(arguments);
5029 }
5030 else {
5031 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
5032 module.verbose.apply(console, arguments);
5033 }
5034 }
5035 },
5036 error: function() {
5037 if(!settings.silent) {
5038 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
5039 module.error.apply(console, arguments);
5040 }
5041 },
5042 performance: {
5043 log: function(message) {
5044 var
5045 currentTime,
5046 executionTime,
5047 previousTime
5048 ;
5049 if(settings.performance) {
5050 currentTime = new Date().getTime();
5051 previousTime = time || currentTime;
5052 executionTime = currentTime - previousTime;
5053 time = currentTime;
5054 performance.push({
5055 'Name' : message[0],
5056 'Arguments' : [].slice.call(message, 1) || '',
5057 'Element' : element,
5058 'Execution Time' : executionTime
5059 });
5060 }
5061 clearTimeout(module.performance.timer);
5062 module.performance.timer = setTimeout(module.performance.display, 500);
5063 },
5064 display: function() {
5065 var
5066 title = settings.name + ':',
5067 totalTime = 0
5068 ;
5069 time = false;
5070 clearTimeout(module.performance.timer);
5071 $.each(performance, function(index, data) {
5072 totalTime += data['Execution Time'];
5073 });
5074 title += ' ' + totalTime + 'ms';
5075 if(moduleSelector) {
5076 title += ' \'' + moduleSelector + '\'';
5077 }
5078 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
5079 console.groupCollapsed(title);
5080 if(console.table) {
5081 console.table(performance);
5082 }
5083 else {
5084 $.each(performance, function(index, data) {
5085 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
5086 });
5087 }
5088 console.groupEnd();
5089 }
5090 performance = [];
5091 }
5092 },
5093 invoke: function(query, passedArguments, context) {
5094 var
5095 object = instance,
5096 maxDepth,
5097 found,
5098 response
5099 ;
5100 passedArguments = passedArguments || queryArguments;
5101 context = element || context;
5102 if(typeof query == 'string' && object !== undefined) {
5103 query = query.split(/[\. ]/);
5104 maxDepth = query.length - 1;
5105 $.each(query, function(depth, value) {
5106 var camelCaseValue = (depth != maxDepth)
5107 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
5108 : query
5109 ;
5110 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
5111 object = object[camelCaseValue];
5112 }
5113 else if( object[camelCaseValue] !== undefined ) {
5114 found = object[camelCaseValue];
5115 return false;
5116 }
5117 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
5118 object = object[value];
5119 }
5120 else if( object[value] !== undefined ) {
5121 found = object[value];
5122 return false;
5123 }
5124 else {
5125 module.error(error.method, query);
5126 return false;
5127 }
5128 });
5129 }
5130 if ( $.isFunction( found ) ) {
5131 response = found.apply(context, passedArguments);
5132 }
5133 else if(found !== undefined) {
5134 response = found;
5135 }
5136 if(Array.isArray(returnedValue)) {
5137 returnedValue.push(response);
5138 }
5139 else if(returnedValue !== undefined) {
5140 returnedValue = [returnedValue, response];
5141 }
5142 else if(response !== undefined) {
5143 returnedValue = response;
5144 }
5145 return found;
5146 }
5147 };
5148
5149 if(methodInvoked) {
5150 if(instance === undefined) {
5151 module.initialize();
5152 }
5153 module.invoke(query);
5154 }
5155 else {
5156 if(instance !== undefined) {
5157 instance.invoke('destroy');
5158 }
5159 module.initialize();
5160 }
5161 })
5162 ;
5163
5164 return (returnedValue !== undefined)
5165 ? returnedValue
5166 : this
5167 ;
5168};
5169
5170$.fn.checkbox.settings = {
5171
5172 name : 'Checkbox',
5173 namespace : 'checkbox',
5174
5175 silent : false,
5176 debug : false,
5177 verbose : true,
5178 performance : true,
5179
5180 // delegated event context
5181 uncheckable : 'auto',
5182 fireOnInit : false,
5183
5184 onChange : function(){},
5185
5186 beforeChecked : function(){},
5187 beforeUnchecked : function(){},
5188 beforeDeterminate : function(){},
5189 beforeIndeterminate : function(){},
5190
5191 onChecked : function(){},
5192 onUnchecked : function(){},
5193
5194 onDeterminate : function() {},
5195 onIndeterminate : function() {},
5196
5197 onEnable : function(){},
5198 onDisable : function(){},
5199
5200 // preserve misspelled callbacks (will be removed in 3.0)
5201 onEnabled : function(){},
5202 onDisabled : function(){},
5203
5204 className : {
5205 checked : 'checked',
5206 indeterminate : 'indeterminate',
5207 disabled : 'disabled',
5208 hidden : 'hidden',
5209 radio : 'radio',
5210 readOnly : 'read-only'
5211 },
5212
5213 error : {
5214 method : 'The method you called is not defined'
5215 },
5216
5217 selector : {
5218 checkbox : '.ui.checkbox',
5219 label : 'label, .box',
5220 input : 'input[type="checkbox"], input[type="radio"]',
5221 link : 'a[href]'
5222 }
5223
5224};
5225
5226})( jQuery, window, document );
5227
5228/*!
5229 * # Semantic UI 2.7.2 - Dimmer
5230 * http://github.com/semantic-org/semantic-ui/
5231 *
5232 *
5233 * Released under the MIT license
5234 * http://opensource.org/licenses/MIT
5235 *
5236 */
5237
5238;(function ($, window, document, undefined) {
5239
5240'use strict';
5241
5242$.isFunction = $.isFunction || function(obj) {
5243 return typeof obj === "function" && typeof obj.nodeType !== "number";
5244};
5245
5246window = (typeof window != 'undefined' && window.Math == Math)
5247 ? window
5248 : (typeof self != 'undefined' && self.Math == Math)
5249 ? self
5250 : Function('return this')()
5251;
5252
5253$.fn.dimmer = function(parameters) {
5254 var
5255 $allModules = $(this),
5256
5257 time = new Date().getTime(),
5258 performance = [],
5259
5260 query = arguments[0],
5261 methodInvoked = (typeof query == 'string'),
5262 queryArguments = [].slice.call(arguments, 1),
5263
5264 returnedValue
5265 ;
5266
5267 $allModules
5268 .each(function() {
5269 var
5270 settings = ( $.isPlainObject(parameters) )
5271 ? $.extend(true, {}, $.fn.dimmer.settings, parameters)
5272 : $.extend({}, $.fn.dimmer.settings),
5273
5274 selector = settings.selector,
5275 namespace = settings.namespace,
5276 className = settings.className,
5277 error = settings.error,
5278
5279 eventNamespace = '.' + namespace,
5280 moduleNamespace = 'module-' + namespace,
5281 moduleSelector = $allModules.selector || '',
5282
5283 clickEvent = ('ontouchstart' in document.documentElement)
5284 ? 'touchstart'
5285 : 'click',
5286
5287 $module = $(this),
5288 $dimmer,
5289 $dimmable,
5290
5291 element = this,
5292 instance = $module.data(moduleNamespace),
5293 module
5294 ;
5295
5296 module = {
5297
5298 preinitialize: function() {
5299 if( module.is.dimmer() ) {
5300
5301 $dimmable = $module.parent();
5302 $dimmer = $module;
5303 }
5304 else {
5305 $dimmable = $module;
5306 if( module.has.dimmer() ) {
5307 if(settings.dimmerName) {
5308 $dimmer = $dimmable.find(selector.dimmer).filter('.' + settings.dimmerName);
5309 }
5310 else {
5311 $dimmer = $dimmable.find(selector.dimmer);
5312 }
5313 }
5314 else {
5315 $dimmer = module.create();
5316 }
5317 }
5318 },
5319
5320 initialize: function() {
5321 module.debug('Initializing dimmer', settings);
5322
5323 module.bind.events();
5324 module.set.dimmable();
5325 module.instantiate();
5326 },
5327
5328 instantiate: function() {
5329 module.verbose('Storing instance of module', module);
5330 instance = module;
5331 $module
5332 .data(moduleNamespace, instance)
5333 ;
5334 },
5335
5336 destroy: function() {
5337 module.verbose('Destroying previous module', $dimmer);
5338 module.unbind.events();
5339 module.remove.variation();
5340 $dimmable
5341 .off(eventNamespace)
5342 ;
5343 },
5344
5345 bind: {
5346 events: function() {
5347 if(settings.on == 'hover') {
5348 $dimmable
5349 .on('mouseenter' + eventNamespace, module.show)
5350 .on('mouseleave' + eventNamespace, module.hide)
5351 ;
5352 }
5353 else if(settings.on == 'click') {
5354 $dimmable
5355 .on(clickEvent + eventNamespace, module.toggle)
5356 ;
5357 }
5358 if( module.is.page() ) {
5359 module.debug('Setting as a page dimmer', $dimmable);
5360 module.set.pageDimmer();
5361 }
5362
5363 if( module.is.closable() ) {
5364 module.verbose('Adding dimmer close event', $dimmer);
5365 $dimmable
5366 .on(clickEvent + eventNamespace, selector.dimmer, module.event.click)
5367 ;
5368 }
5369 }
5370 },
5371
5372 unbind: {
5373 events: function() {
5374 $module
5375 .removeData(moduleNamespace)
5376 ;
5377 $dimmable
5378 .off(eventNamespace)
5379 ;
5380 }
5381 },
5382
5383 event: {
5384 click: function(event) {
5385 module.verbose('Determining if event occured on dimmer', event);
5386 if( $dimmer.find(event.target).length === 0 || $(event.target).is(selector.content) ) {
5387 module.hide();
5388 event.stopImmediatePropagation();
5389 }
5390 }
5391 },
5392
5393 addContent: function(element) {
5394 var
5395 $content = $(element)
5396 ;
5397 module.debug('Add content to dimmer', $content);
5398 if($content.parent()[0] !== $dimmer[0]) {
5399 $content.detach().appendTo($dimmer);
5400 }
5401 },
5402
5403 create: function() {
5404 var
5405 $element = $( settings.template.dimmer(settings) )
5406 ;
5407 if(settings.dimmerName) {
5408 module.debug('Creating named dimmer', settings.dimmerName);
5409 $element.addClass(settings.dimmerName);
5410 }
5411 $element
5412 .appendTo($dimmable)
5413 ;
5414 return $element;
5415 },
5416
5417 show: function(callback) {
5418 callback = $.isFunction(callback)
5419 ? callback
5420 : function(){}
5421 ;
5422 module.debug('Showing dimmer', $dimmer, settings);
5423 module.set.variation();
5424 if( (!module.is.dimmed() || module.is.animating()) && module.is.enabled() ) {
5425 module.animate.show(callback);
5426 settings.onShow.call(element);
5427 settings.onChange.call(element);
5428 }
5429 else {
5430 module.debug('Dimmer is already shown or disabled');
5431 }
5432 },
5433
5434 hide: function(callback) {
5435 callback = $.isFunction(callback)
5436 ? callback
5437 : function(){}
5438 ;
5439 if( module.is.dimmed() || module.is.animating() ) {
5440 module.debug('Hiding dimmer', $dimmer);
5441 module.animate.hide(callback);
5442 settings.onHide.call(element);
5443 settings.onChange.call(element);
5444 }
5445 else {
5446 module.debug('Dimmer is not visible');
5447 }
5448 },
5449
5450 toggle: function() {
5451 module.verbose('Toggling dimmer visibility', $dimmer);
5452 if( !module.is.dimmed() ) {
5453 module.show();
5454 }
5455 else {
5456 if ( module.is.closable() ) {
5457 module.hide();
5458 }
5459 }
5460 },
5461
5462 animate: {
5463 show: function(callback) {
5464 callback = $.isFunction(callback)
5465 ? callback
5466 : function(){}
5467 ;
5468 if(settings.useCSS && $.fn.transition !== undefined && $dimmer.transition('is supported')) {
5469 if(settings.useFlex) {
5470 module.debug('Using flex dimmer');
5471 module.remove.legacy();
5472 }
5473 else {
5474 module.debug('Using legacy non-flex dimmer');
5475 module.set.legacy();
5476 }
5477 if(settings.opacity !== 'auto') {
5478 module.set.opacity();
5479 }
5480 $dimmer
5481 .transition({
5482 displayType : settings.useFlex
5483 ? 'flex'
5484 : 'block',
5485 animation : settings.transition + ' in',
5486 queue : false,
5487 duration : module.get.duration(),
5488 useFailSafe : true,
5489 onStart : function() {
5490 module.set.dimmed();
5491 },
5492 onComplete : function() {
5493 module.set.active();
5494 callback();
5495 }
5496 })
5497 ;
5498 }
5499 else {
5500 module.verbose('Showing dimmer animation with javascript');
5501 module.set.dimmed();
5502 if(settings.opacity == 'auto') {
5503 settings.opacity = 0.8;
5504 }
5505 $dimmer
5506 .stop()
5507 .css({
5508 opacity : 0,
5509 width : '100%',
5510 height : '100%'
5511 })
5512 .fadeTo(module.get.duration(), settings.opacity, function() {
5513 $dimmer.removeAttr('style');
5514 module.set.active();
5515 callback();
5516 })
5517 ;
5518 }
5519 },
5520 hide: function(callback) {
5521 callback = $.isFunction(callback)
5522 ? callback
5523 : function(){}
5524 ;
5525 if(settings.useCSS && $.fn.transition !== undefined && $dimmer.transition('is supported')) {
5526 module.verbose('Hiding dimmer with css');
5527 $dimmer
5528 .transition({
5529 displayType : settings.useFlex
5530 ? 'flex'
5531 : 'block',
5532 animation : settings.transition + ' out',
5533 queue : false,
5534 duration : module.get.duration(),
5535 useFailSafe : true,
5536 onStart : function() {
5537 module.remove.dimmed();
5538 },
5539 onComplete : function() {
5540 module.remove.variation();
5541 module.remove.active();
5542 callback();
5543 }
5544 })
5545 ;
5546 }
5547 else {
5548 module.verbose('Hiding dimmer with javascript');
5549 module.remove.dimmed();
5550 $dimmer
5551 .stop()
5552 .fadeOut(module.get.duration(), function() {
5553 module.remove.active();
5554 $dimmer.removeAttr('style');
5555 callback();
5556 })
5557 ;
5558 }
5559 }
5560 },
5561
5562 get: {
5563 dimmer: function() {
5564 return $dimmer;
5565 },
5566 duration: function() {
5567 if(typeof settings.duration == 'object') {
5568 if( module.is.active() ) {
5569 return settings.duration.hide;
5570 }
5571 else {
5572 return settings.duration.show;
5573 }
5574 }
5575 return settings.duration;
5576 }
5577 },
5578
5579 has: {
5580 dimmer: function() {
5581 if(settings.dimmerName) {
5582 return ($module.find(selector.dimmer).filter('.' + settings.dimmerName).length > 0);
5583 }
5584 else {
5585 return ( $module.find(selector.dimmer).length > 0 );
5586 }
5587 }
5588 },
5589
5590 is: {
5591 active: function() {
5592 return $dimmer.hasClass(className.active);
5593 },
5594 animating: function() {
5595 return ( $dimmer.is(':animated') || $dimmer.hasClass(className.animating) );
5596 },
5597 closable: function() {
5598 if(settings.closable == 'auto') {
5599 if(settings.on == 'hover') {
5600 return false;
5601 }
5602 return true;
5603 }
5604 return settings.closable;
5605 },
5606 dimmer: function() {
5607 return $module.hasClass(className.dimmer);
5608 },
5609 dimmable: function() {
5610 return $module.hasClass(className.dimmable);
5611 },
5612 dimmed: function() {
5613 return $dimmable.hasClass(className.dimmed);
5614 },
5615 disabled: function() {
5616 return $dimmable.hasClass(className.disabled);
5617 },
5618 enabled: function() {
5619 return !module.is.disabled();
5620 },
5621 page: function () {
5622 return $dimmable.is('body');
5623 },
5624 pageDimmer: function() {
5625 return $dimmer.hasClass(className.pageDimmer);
5626 }
5627 },
5628
5629 can: {
5630 show: function() {
5631 return !$dimmer.hasClass(className.disabled);
5632 }
5633 },
5634
5635 set: {
5636 opacity: function(opacity) {
5637 var
5638 color = $dimmer.css('background-color'),
5639 colorArray = color.split(','),
5640 isRGB = (colorArray && colorArray.length == 3),
5641 isRGBA = (colorArray && colorArray.length == 4)
5642 ;
5643 opacity = settings.opacity === 0 ? 0 : settings.opacity || opacity;
5644 if(isRGB || isRGBA) {
5645 colorArray[3] = opacity + ')';
5646 color = colorArray.join(',');
5647 }
5648 else {
5649 color = 'rgba(0, 0, 0, ' + opacity + ')';
5650 }
5651 module.debug('Setting opacity to', opacity);
5652 $dimmer.css('background-color', color);
5653 },
5654 legacy: function() {
5655 $dimmer.addClass(className.legacy);
5656 },
5657 active: function() {
5658 $dimmer.addClass(className.active);
5659 },
5660 dimmable: function() {
5661 $dimmable.addClass(className.dimmable);
5662 },
5663 dimmed: function() {
5664 $dimmable.addClass(className.dimmed);
5665 },
5666 pageDimmer: function() {
5667 $dimmer.addClass(className.pageDimmer);
5668 },
5669 disabled: function() {
5670 $dimmer.addClass(className.disabled);
5671 },
5672 variation: function(variation) {
5673 variation = variation || settings.variation;
5674 if(variation) {
5675 $dimmer.addClass(variation);
5676 }
5677 }
5678 },
5679
5680 remove: {
5681 active: function() {
5682 $dimmer
5683 .removeClass(className.active)
5684 ;
5685 },
5686 legacy: function() {
5687 $dimmer.removeClass(className.legacy);
5688 },
5689 dimmed: function() {
5690 $dimmable.removeClass(className.dimmed);
5691 },
5692 disabled: function() {
5693 $dimmer.removeClass(className.disabled);
5694 },
5695 variation: function(variation) {
5696 variation = variation || settings.variation;
5697 if(variation) {
5698 $dimmer.removeClass(variation);
5699 }
5700 }
5701 },
5702
5703 setting: function(name, value) {
5704 module.debug('Changing setting', name, value);
5705 if( $.isPlainObject(name) ) {
5706 $.extend(true, settings, name);
5707 }
5708 else if(value !== undefined) {
5709 if($.isPlainObject(settings[name])) {
5710 $.extend(true, settings[name], value);
5711 }
5712 else {
5713 settings[name] = value;
5714 }
5715 }
5716 else {
5717 return settings[name];
5718 }
5719 },
5720 internal: function(name, value) {
5721 if( $.isPlainObject(name) ) {
5722 $.extend(true, module, name);
5723 }
5724 else if(value !== undefined) {
5725 module[name] = value;
5726 }
5727 else {
5728 return module[name];
5729 }
5730 },
5731 debug: function() {
5732 if(!settings.silent && settings.debug) {
5733 if(settings.performance) {
5734 module.performance.log(arguments);
5735 }
5736 else {
5737 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
5738 module.debug.apply(console, arguments);
5739 }
5740 }
5741 },
5742 verbose: function() {
5743 if(!settings.silent && settings.verbose && settings.debug) {
5744 if(settings.performance) {
5745 module.performance.log(arguments);
5746 }
5747 else {
5748 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
5749 module.verbose.apply(console, arguments);
5750 }
5751 }
5752 },
5753 error: function() {
5754 if(!settings.silent) {
5755 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
5756 module.error.apply(console, arguments);
5757 }
5758 },
5759 performance: {
5760 log: function(message) {
5761 var
5762 currentTime,
5763 executionTime,
5764 previousTime
5765 ;
5766 if(settings.performance) {
5767 currentTime = new Date().getTime();
5768 previousTime = time || currentTime;
5769 executionTime = currentTime - previousTime;
5770 time = currentTime;
5771 performance.push({
5772 'Name' : message[0],
5773 'Arguments' : [].slice.call(message, 1) || '',
5774 'Element' : element,
5775 'Execution Time' : executionTime
5776 });
5777 }
5778 clearTimeout(module.performance.timer);
5779 module.performance.timer = setTimeout(module.performance.display, 500);
5780 },
5781 display: function() {
5782 var
5783 title = settings.name + ':',
5784 totalTime = 0
5785 ;
5786 time = false;
5787 clearTimeout(module.performance.timer);
5788 $.each(performance, function(index, data) {
5789 totalTime += data['Execution Time'];
5790 });
5791 title += ' ' + totalTime + 'ms';
5792 if(moduleSelector) {
5793 title += ' \'' + moduleSelector + '\'';
5794 }
5795 if($allModules.length > 1) {
5796 title += ' ' + '(' + $allModules.length + ')';
5797 }
5798 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
5799 console.groupCollapsed(title);
5800 if(console.table) {
5801 console.table(performance);
5802 }
5803 else {
5804 $.each(performance, function(index, data) {
5805 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
5806 });
5807 }
5808 console.groupEnd();
5809 }
5810 performance = [];
5811 }
5812 },
5813 invoke: function(query, passedArguments, context) {
5814 var
5815 object = instance,
5816 maxDepth,
5817 found,
5818 response
5819 ;
5820 passedArguments = passedArguments || queryArguments;
5821 context = element || context;
5822 if(typeof query == 'string' && object !== undefined) {
5823 query = query.split(/[\. ]/);
5824 maxDepth = query.length - 1;
5825 $.each(query, function(depth, value) {
5826 var camelCaseValue = (depth != maxDepth)
5827 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
5828 : query
5829 ;
5830 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
5831 object = object[camelCaseValue];
5832 }
5833 else if( object[camelCaseValue] !== undefined ) {
5834 found = object[camelCaseValue];
5835 return false;
5836 }
5837 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
5838 object = object[value];
5839 }
5840 else if( object[value] !== undefined ) {
5841 found = object[value];
5842 return false;
5843 }
5844 else {
5845 module.error(error.method, query);
5846 return false;
5847 }
5848 });
5849 }
5850 if ( $.isFunction( found ) ) {
5851 response = found.apply(context, passedArguments);
5852 }
5853 else if(found !== undefined) {
5854 response = found;
5855 }
5856 if(Array.isArray(returnedValue)) {
5857 returnedValue.push(response);
5858 }
5859 else if(returnedValue !== undefined) {
5860 returnedValue = [returnedValue, response];
5861 }
5862 else if(response !== undefined) {
5863 returnedValue = response;
5864 }
5865 return found;
5866 }
5867 };
5868
5869 module.preinitialize();
5870
5871 if(methodInvoked) {
5872 if(instance === undefined) {
5873 module.initialize();
5874 }
5875 module.invoke(query);
5876 }
5877 else {
5878 if(instance !== undefined) {
5879 instance.invoke('destroy');
5880 }
5881 module.initialize();
5882 }
5883 })
5884 ;
5885
5886 return (returnedValue !== undefined)
5887 ? returnedValue
5888 : this
5889 ;
5890};
5891
5892$.fn.dimmer.settings = {
5893
5894 name : 'Dimmer',
5895 namespace : 'dimmer',
5896
5897 silent : false,
5898 debug : false,
5899 verbose : false,
5900 performance : true,
5901
5902 // whether should use flex layout
5903 useFlex : true,
5904
5905 // name to distinguish between multiple dimmers in context
5906 dimmerName : false,
5907
5908 // whether to add a variation type
5909 variation : false,
5910
5911 // whether to bind close events
5912 closable : 'auto',
5913
5914 // whether to use css animations
5915 useCSS : true,
5916
5917 // css animation to use
5918 transition : 'fade',
5919
5920 // event to bind to
5921 on : false,
5922
5923 // overriding opacity value
5924 opacity : 'auto',
5925
5926 // transition durations
5927 duration : {
5928 show : 500,
5929 hide : 500
5930 },
5931// whether the dynamically created dimmer should have a loader
5932 displayLoader: false,
5933 loaderText : false,
5934 loaderVariation : '',
5935
5936 onChange : function(){},
5937 onShow : function(){},
5938 onHide : function(){},
5939
5940 error : {
5941 method : 'The method you called is not defined.'
5942 },
5943
5944 className : {
5945 active : 'active',
5946 animating : 'animating',
5947 dimmable : 'dimmable',
5948 dimmed : 'dimmed',
5949 dimmer : 'dimmer',
5950 disabled : 'disabled',
5951 hide : 'hide',
5952 legacy : 'legacy',
5953 pageDimmer : 'page',
5954 show : 'show',
5955 loader : 'ui loader'
5956 },
5957
5958 selector: {
5959 dimmer : '> .ui.dimmer',
5960 content : '.ui.dimmer > .content, .ui.dimmer > .content > .center'
5961 },
5962
5963 template: {
5964 dimmer: function(settings) {
5965 var d = $('<div/>').addClass('ui dimmer'),l;
5966 if(settings.displayLoader) {
5967 l = $('<div/>')
5968 .addClass(settings.className.loader)
5969 .addClass(settings.loaderVariation);
5970 if(!!settings.loaderText){
5971 l.text(settings.loaderText);
5972 l.addClass('text');
5973 }
5974 d.append(l);
5975 }
5976 return d;
5977 }
5978 }
5979
5980};
5981
5982})( jQuery, window, document );
5983
5984/*!
5985 * # Semantic UI 2.7.2 - Dropdown
5986 * http://github.com/semantic-org/semantic-ui/
5987 *
5988 *
5989 * Released under the MIT license
5990 * http://opensource.org/licenses/MIT
5991 *
5992 */
5993
5994;(function ($, window, document, undefined) {
5995
5996'use strict';
5997
5998$.isFunction = $.isFunction || function(obj) {
5999 return typeof obj === "function" && typeof obj.nodeType !== "number";
6000};
6001
6002window = (typeof window != 'undefined' && window.Math == Math)
6003 ? window
6004 : (typeof self != 'undefined' && self.Math == Math)
6005 ? self
6006 : Function('return this')()
6007;
6008
6009$.fn.dropdown = function(parameters) {
6010 var
6011 $allModules = $(this),
6012 $document = $(document),
6013
6014 moduleSelector = $allModules.selector || '',
6015
6016 hasTouch = ('ontouchstart' in document.documentElement),
6017 time = new Date().getTime(),
6018 performance = [],
6019
6020 query = arguments[0],
6021 methodInvoked = (typeof query == 'string'),
6022 queryArguments = [].slice.call(arguments, 1),
6023 returnedValue
6024 ;
6025
6026 $allModules
6027 .each(function(elementIndex) {
6028 var
6029 settings = ( $.isPlainObject(parameters) )
6030 ? $.extend(true, {}, $.fn.dropdown.settings, parameters)
6031 : $.extend({}, $.fn.dropdown.settings),
6032
6033 className = settings.className,
6034 message = settings.message,
6035 fields = settings.fields,
6036 keys = settings.keys,
6037 metadata = settings.metadata,
6038 namespace = settings.namespace,
6039 regExp = settings.regExp,
6040 selector = settings.selector,
6041 error = settings.error,
6042 templates = settings.templates,
6043
6044 eventNamespace = '.' + namespace,
6045 moduleNamespace = 'module-' + namespace,
6046
6047 $module = $(this),
6048 $context = $(settings.context),
6049 $text = $module.find(selector.text),
6050 $search = $module.find(selector.search),
6051 $sizer = $module.find(selector.sizer),
6052 $input = $module.find(selector.input),
6053 $icon = $module.find(selector.icon),
6054 $clear = $module.find(selector.clearIcon),
6055
6056 $combo = ($module.prev().find(selector.text).length > 0)
6057 ? $module.prev().find(selector.text)
6058 : $module.prev(),
6059
6060 $menu = $module.children(selector.menu),
6061 $item = $menu.find(selector.item),
6062 $divider = settings.hideDividers ? $item.parent().children(selector.divider) : $(),
6063
6064 activated = false,
6065 itemActivated = false,
6066 internalChange = false,
6067 element = this,
6068 instance = $module.data(moduleNamespace),
6069
6070 initialLoad,
6071 pageLostFocus,
6072 willRefocus,
6073 elementNamespace,
6074 id,
6075 selectObserver,
6076 menuObserver,
6077 module
6078 ;
6079
6080 module = {
6081
6082 initialize: function() {
6083 module.debug('Initializing dropdown', settings);
6084
6085 if( module.is.alreadySetup() ) {
6086 module.setup.reference();
6087 }
6088 else {
6089 if (settings.ignoreDiacritics && !String.prototype.normalize) {
6090 settings.ignoreDiacritics = false;
6091 module.error(error.noNormalize, element);
6092 }
6093
6094 module.setup.layout();
6095
6096 if(settings.values) {
6097 module.change.values(settings.values);
6098 }
6099
6100 module.refreshData();
6101
6102 module.save.defaults();
6103 module.restore.selected();
6104
6105 module.create.id();
6106 module.bind.events();
6107
6108 module.observeChanges();
6109 module.instantiate();
6110 }
6111
6112 },
6113
6114 instantiate: function() {
6115 module.verbose('Storing instance of dropdown', module);
6116 instance = module;
6117 $module
6118 .data(moduleNamespace, module)
6119 ;
6120 },
6121
6122 destroy: function() {
6123 module.verbose('Destroying previous dropdown', $module);
6124 module.remove.tabbable();
6125 $module
6126 .off(eventNamespace)
6127 .removeData(moduleNamespace)
6128 ;
6129 $menu
6130 .off(eventNamespace)
6131 ;
6132 $document
6133 .off(elementNamespace)
6134 ;
6135 module.disconnect.menuObserver();
6136 module.disconnect.selectObserver();
6137 },
6138
6139 observeChanges: function() {
6140 if('MutationObserver' in window) {
6141 selectObserver = new MutationObserver(module.event.select.mutation);
6142 menuObserver = new MutationObserver(module.event.menu.mutation);
6143 module.debug('Setting up mutation observer', selectObserver, menuObserver);
6144 module.observe.select();
6145 module.observe.menu();
6146 }
6147 },
6148
6149 disconnect: {
6150 menuObserver: function() {
6151 if(menuObserver) {
6152 menuObserver.disconnect();
6153 }
6154 },
6155 selectObserver: function() {
6156 if(selectObserver) {
6157 selectObserver.disconnect();
6158 }
6159 }
6160 },
6161 observe: {
6162 select: function() {
6163 if(module.has.input()) {
6164 selectObserver.observe($module[0], {
6165 childList : true,
6166 subtree : true
6167 });
6168 }
6169 },
6170 menu: function() {
6171 if(module.has.menu()) {
6172 menuObserver.observe($menu[0], {
6173 childList : true,
6174 subtree : true
6175 });
6176 }
6177 }
6178 },
6179
6180 create: {
6181 id: function() {
6182 id = (Math.random().toString(16) + '000000000').substr(2, 8);
6183 elementNamespace = '.' + id;
6184 module.verbose('Creating unique id for element', id);
6185 },
6186 userChoice: function(values) {
6187 var
6188 $userChoices,
6189 $userChoice,
6190 isUserValue,
6191 html
6192 ;
6193 values = values || module.get.userValues();
6194 if(!values) {
6195 return false;
6196 }
6197 values = Array.isArray(values)
6198 ? values
6199 : [values]
6200 ;
6201 $.each(values, function(index, value) {
6202 if(module.get.item(value) === false) {
6203 html = settings.templates.addition( module.add.variables(message.addResult, value) );
6204 $userChoice = $('<div />')
6205 .html(html)
6206 .attr('data-' + metadata.value, value)
6207 .attr('data-' + metadata.text, value)
6208 .addClass(className.addition)
6209 .addClass(className.item)
6210 ;
6211 if(settings.hideAdditions) {
6212 $userChoice.addClass(className.hidden);
6213 }
6214 $userChoices = ($userChoices === undefined)
6215 ? $userChoice
6216 : $userChoices.add($userChoice)
6217 ;
6218 module.verbose('Creating user choices for value', value, $userChoice);
6219 }
6220 });
6221 return $userChoices;
6222 },
6223 userLabels: function(value) {
6224 var
6225 userValues = module.get.userValues()
6226 ;
6227 if(userValues) {
6228 module.debug('Adding user labels', userValues);
6229 $.each(userValues, function(index, value) {
6230 module.verbose('Adding custom user value');
6231 module.add.label(value, value);
6232 });
6233 }
6234 },
6235 menu: function() {
6236 $menu = $('<div />')
6237 .addClass(className.menu)
6238 .appendTo($module)
6239 ;
6240 },
6241 sizer: function() {
6242 $sizer = $('<span />')
6243 .addClass(className.sizer)
6244 .insertAfter($search)
6245 ;
6246 }
6247 },
6248
6249 search: function(query) {
6250 query = (query !== undefined)
6251 ? query
6252 : module.get.query()
6253 ;
6254 module.verbose('Searching for query', query);
6255 if(module.has.minCharacters(query)) {
6256 module.filter(query);
6257 }
6258 else {
6259 module.hide();
6260 }
6261 },
6262
6263 select: {
6264 firstUnfiltered: function() {
6265 module.verbose('Selecting first non-filtered element');
6266 module.remove.selectedItem();
6267 $item
6268 .not(selector.unselectable)
6269 .not(selector.addition + selector.hidden)
6270 .eq(0)
6271 .addClass(className.selected)
6272 ;
6273 },
6274 nextAvailable: function($selected) {
6275 $selected = $selected.eq(0);
6276 var
6277 $nextAvailable = $selected.nextAll(selector.item).not(selector.unselectable).eq(0),
6278 $prevAvailable = $selected.prevAll(selector.item).not(selector.unselectable).eq(0),
6279 hasNext = ($nextAvailable.length > 0)
6280 ;
6281 if(hasNext) {
6282 module.verbose('Moving selection to', $nextAvailable);
6283 $nextAvailable.addClass(className.selected);
6284 }
6285 else {
6286 module.verbose('Moving selection to', $prevAvailable);
6287 $prevAvailable.addClass(className.selected);
6288 }
6289 }
6290 },
6291
6292 setup: {
6293 api: function() {
6294 var
6295 apiSettings = {
6296 debug : settings.debug,
6297 urlData : {
6298 value : module.get.value(),
6299 query : module.get.query()
6300 },
6301 on : false
6302 }
6303 ;
6304 module.verbose('First request, initializing API');
6305 $module
6306 .api(apiSettings)
6307 ;
6308 },
6309 layout: function() {
6310 if( $module.is('select') ) {
6311 module.setup.select();
6312 module.setup.returnedObject();
6313 }
6314 if( !module.has.menu() ) {
6315 module.create.menu();
6316 }
6317 if ( module.is.selection() && module.is.clearable() && !module.has.clearItem() ) {
6318 module.verbose('Adding clear icon');
6319 $clear = $('<i />')
6320 .addClass('remove icon')
6321 .insertBefore($text)
6322 ;
6323 }
6324 if( module.is.search() && !module.has.search() ) {
6325 module.verbose('Adding search input');
6326 $search = $('<input />')
6327 .addClass(className.search)
6328 .prop('autocomplete', 'off')
6329 .insertBefore($text)
6330 ;
6331 }
6332 if( module.is.multiple() && module.is.searchSelection() && !module.has.sizer()) {
6333 module.create.sizer();
6334 }
6335 if(settings.allowTab) {
6336 module.set.tabbable();
6337 }
6338 },
6339 select: function() {
6340 var
6341 selectValues = module.get.selectValues()
6342 ;
6343 module.debug('Dropdown initialized on a select', selectValues);
6344 if( $module.is('select') ) {
6345 $input = $module;
6346 }
6347 // see if select is placed correctly already
6348 if($input.parent(selector.dropdown).length > 0) {
6349 module.debug('UI dropdown already exists. Creating dropdown menu only');
6350 $module = $input.closest(selector.dropdown);
6351 if( !module.has.menu() ) {
6352 module.create.menu();
6353 }
6354 $menu = $module.children(selector.menu);
6355 module.setup.menu(selectValues);
6356 }
6357 else {
6358 module.debug('Creating entire dropdown from select');
6359 $module = $('<div />')
6360 .attr('class', $input.attr('class') )
6361 .addClass(className.selection)
6362 .addClass(className.dropdown)
6363 .html( templates.dropdown(selectValues,settings.preserveHTML, settings.className) )
6364 .insertBefore($input)
6365 ;
6366 if($input.hasClass(className.multiple) && $input.prop('multiple') === false) {
6367 module.error(error.missingMultiple);
6368 $input.prop('multiple', true);
6369 }
6370 if($input.is('[multiple]')) {
6371 module.set.multiple();
6372 }
6373 if ($input.prop('disabled')) {
6374 module.debug('Disabling dropdown');
6375 $module.addClass(className.disabled);
6376 }
6377 $input
6378 .removeAttr('class')
6379 .detach()
6380 .prependTo($module)
6381 ;
6382 }
6383 module.refresh();
6384 },
6385 menu: function(values) {
6386 $menu.html( templates.menu(values, fields,settings.preserveHTML,settings.className));
6387 $item = $menu.find(selector.item);
6388 $divider = settings.hideDividers ? $item.parent().children(selector.divider) : $();
6389 },
6390 reference: function() {
6391 module.debug('Dropdown behavior was called on select, replacing with closest dropdown');
6392 // replace module reference
6393 $module = $module.parent(selector.dropdown);
6394 instance = $module.data(moduleNamespace);
6395 element = $module.get(0);
6396 module.refresh();
6397 module.setup.returnedObject();
6398 },
6399 returnedObject: function() {
6400 var
6401 $firstModules = $allModules.slice(0, elementIndex),
6402 $lastModules = $allModules.slice(elementIndex + 1)
6403 ;
6404 // adjust all modules to use correct reference
6405 $allModules = $firstModules.add($module).add($lastModules);
6406 }
6407 },
6408
6409 refresh: function() {
6410 module.refreshSelectors();
6411 module.refreshData();
6412 },
6413
6414 refreshItems: function() {
6415 $item = $menu.find(selector.item);
6416 $divider = settings.hideDividers ? $item.parent().children(selector.divider) : $();
6417 },
6418
6419 refreshSelectors: function() {
6420 module.verbose('Refreshing selector cache');
6421 $text = $module.find(selector.text);
6422 $search = $module.find(selector.search);
6423 $input = $module.find(selector.input);
6424 $icon = $module.find(selector.icon);
6425 $combo = ($module.prev().find(selector.text).length > 0)
6426 ? $module.prev().find(selector.text)
6427 : $module.prev()
6428 ;
6429 $menu = $module.children(selector.menu);
6430 $item = $menu.find(selector.item);
6431 $divider = settings.hideDividers ? $item.parent().children(selector.divider) : $();
6432 },
6433
6434 refreshData: function() {
6435 module.verbose('Refreshing cached metadata');
6436 $item
6437 .removeData(metadata.text)
6438 .removeData(metadata.value)
6439 ;
6440 },
6441
6442 clearData: function() {
6443 module.verbose('Clearing metadata');
6444 $item
6445 .removeData(metadata.text)
6446 .removeData(metadata.value)
6447 ;
6448 $module
6449 .removeData(metadata.defaultText)
6450 .removeData(metadata.defaultValue)
6451 .removeData(metadata.placeholderText)
6452 ;
6453 },
6454
6455 toggle: function() {
6456 module.verbose('Toggling menu visibility');
6457 if( !module.is.active() ) {
6458 module.show();
6459 }
6460 else {
6461 module.hide();
6462 }
6463 },
6464
6465 show: function(callback) {
6466 callback = $.isFunction(callback)
6467 ? callback
6468 : function(){}
6469 ;
6470 if(!module.can.show() && module.is.remote()) {
6471 module.debug('No API results retrieved, searching before show');
6472 module.queryRemote(module.get.query(), module.show);
6473 }
6474 if( module.can.show() && !module.is.active() ) {
6475 module.debug('Showing dropdown');
6476 if(module.has.message() && !(module.has.maxSelections() || module.has.allResultsFiltered()) ) {
6477 module.remove.message();
6478 }
6479 if(module.is.allFiltered()) {
6480 return true;
6481 }
6482 if(settings.onShow.call(element) !== false) {
6483 module.animate.show(function() {
6484 if( module.can.click() ) {
6485 module.bind.intent();
6486 }
6487 if(module.has.search()) {
6488 module.focusSearch();
6489 }
6490 module.set.visible();
6491 callback.call(element);
6492 });
6493 }
6494 }
6495 },
6496
6497 hide: function(callback) {
6498 callback = $.isFunction(callback)
6499 ? callback
6500 : function(){}
6501 ;
6502 if( module.is.active() && !module.is.animatingOutward() ) {
6503 module.debug('Hiding dropdown');
6504 if(settings.onHide.call(element) !== false) {
6505 module.animate.hide(function() {
6506 module.remove.visible();
6507 // hidding search focus
6508 if ( module.is.focusedOnSearch() ) {
6509 $search.blur();
6510 }
6511 callback.call(element);
6512 });
6513 }
6514 }
6515 },
6516
6517 hideOthers: function() {
6518 module.verbose('Finding other dropdowns to hide');
6519 $allModules
6520 .not($module)
6521 .has(selector.menu + '.' + className.visible)
6522 .dropdown('hide')
6523 ;
6524 },
6525
6526 hideMenu: function() {
6527 module.verbose('Hiding menu instantaneously');
6528 module.remove.active();
6529 module.remove.visible();
6530 $menu.transition('hide');
6531 },
6532
6533 hideSubMenus: function() {
6534 var
6535 $subMenus = $menu.children(selector.item).find(selector.menu)
6536 ;
6537 module.verbose('Hiding sub menus', $subMenus);
6538 $subMenus.transition('hide');
6539 },
6540
6541 bind: {
6542 events: function() {
6543 if(hasTouch) {
6544 module.bind.touchEvents();
6545 }
6546 module.bind.keyboardEvents();
6547 module.bind.inputEvents();
6548 module.bind.mouseEvents();
6549 },
6550 touchEvents: function() {
6551 module.debug('Touch device detected binding additional touch events');
6552 if( module.is.searchSelection() ) {
6553 // do nothing special yet
6554 }
6555 else if( module.is.single() ) {
6556 $module
6557 .on('touchstart' + eventNamespace, module.event.test.toggle)
6558 ;
6559 }
6560 $menu
6561 .on('touchstart' + eventNamespace, selector.item, module.event.item.mouseenter)
6562 ;
6563 },
6564 keyboardEvents: function() {
6565 module.verbose('Binding keyboard events');
6566 $module
6567 .on('keydown' + eventNamespace, module.event.keydown)
6568 ;
6569 if( module.has.search() ) {
6570 $module
6571 .on(module.get.inputEvent() + eventNamespace, selector.search, module.event.input)
6572 ;
6573 }
6574 if( module.is.multiple() ) {
6575 $document
6576 .on('keydown' + elementNamespace, module.event.document.keydown)
6577 ;
6578 }
6579 },
6580 inputEvents: function() {
6581 module.verbose('Binding input change events');
6582 $module
6583 .on('change' + eventNamespace, selector.input, module.event.change)
6584 ;
6585 },
6586 mouseEvents: function() {
6587 module.verbose('Binding mouse events');
6588 if(module.is.multiple()) {
6589 $module
6590 .on('click' + eventNamespace, selector.label, module.event.label.click)
6591 .on('click' + eventNamespace, selector.remove, module.event.remove.click)
6592 ;
6593 }
6594 if( module.is.searchSelection() ) {
6595 $module
6596 .on('mousedown' + eventNamespace, module.event.mousedown)
6597 .on('mouseup' + eventNamespace, module.event.mouseup)
6598 .on('mousedown' + eventNamespace, selector.menu, module.event.menu.mousedown)
6599 .on('mouseup' + eventNamespace, selector.menu, module.event.menu.mouseup)
6600 .on('click' + eventNamespace, selector.icon, module.event.icon.click)
6601 .on('click' + eventNamespace, selector.clearIcon, module.event.clearIcon.click)
6602 .on('focus' + eventNamespace, selector.search, module.event.search.focus)
6603 .on('click' + eventNamespace, selector.search, module.event.search.focus)
6604 .on('blur' + eventNamespace, selector.search, module.event.search.blur)
6605 .on('click' + eventNamespace, selector.text, module.event.text.focus)
6606 ;
6607 if(module.is.multiple()) {
6608 $module
6609 .on('click' + eventNamespace, module.event.click)
6610 ;
6611 }
6612 }
6613 else {
6614 if(settings.on == 'click') {
6615 $module
6616 .on('click' + eventNamespace, selector.icon, module.event.icon.click)
6617 .on('click' + eventNamespace, module.event.test.toggle)
6618 ;
6619 }
6620 else if(settings.on == 'hover') {
6621 $module
6622 .on('mouseenter' + eventNamespace, module.delay.show)
6623 .on('mouseleave' + eventNamespace, module.delay.hide)
6624 ;
6625 }
6626 else {
6627 $module
6628 .on(settings.on + eventNamespace, module.toggle)
6629 ;
6630 }
6631 $module
6632 .on('mousedown' + eventNamespace, module.event.mousedown)
6633 .on('mouseup' + eventNamespace, module.event.mouseup)
6634 .on('focus' + eventNamespace, module.event.focus)
6635 .on('click' + eventNamespace, selector.clearIcon, module.event.clearIcon.click)
6636 ;
6637 if(module.has.menuSearch() ) {
6638 $module
6639 .on('blur' + eventNamespace, selector.search, module.event.search.blur)
6640 ;
6641 }
6642 else {
6643 $module
6644 .on('blur' + eventNamespace, module.event.blur)
6645 ;
6646 }
6647 }
6648 $menu
6649 .on('mouseenter' + eventNamespace, selector.item, module.event.item.mouseenter)
6650 .on('mouseleave' + eventNamespace, selector.item, module.event.item.mouseleave)
6651 .on('click' + eventNamespace, selector.item, module.event.item.click)
6652 ;
6653 },
6654 intent: function() {
6655 module.verbose('Binding hide intent event to document');
6656 if(hasTouch) {
6657 $document
6658 .on('touchstart' + elementNamespace, module.event.test.touch)
6659 .on('touchmove' + elementNamespace, module.event.test.touch)
6660 ;
6661 }
6662 $document
6663 .on('click' + elementNamespace, module.event.test.hide)
6664 ;
6665 }
6666 },
6667
6668 unbind: {
6669 intent: function() {
6670 module.verbose('Removing hide intent event from document');
6671 if(hasTouch) {
6672 $document
6673 .off('touchstart' + elementNamespace)
6674 .off('touchmove' + elementNamespace)
6675 ;
6676 }
6677 $document
6678 .off('click' + elementNamespace)
6679 ;
6680 }
6681 },
6682
6683 filter: function(query) {
6684 var
6685 searchTerm = (query !== undefined)
6686 ? query
6687 : module.get.query(),
6688 afterFiltered = function() {
6689 if(module.is.multiple()) {
6690 module.filterActive();
6691 }
6692 if(query || (!query && module.get.activeItem().length == 0)) {
6693 module.select.firstUnfiltered();
6694 }
6695 if( module.has.allResultsFiltered() ) {
6696 if( settings.onNoResults.call(element, searchTerm) ) {
6697 if(settings.allowAdditions) {
6698 if(settings.hideAdditions) {
6699 module.verbose('User addition with no menu, setting empty style');
6700 module.set.empty();
6701 module.hideMenu();
6702 }
6703 }
6704 else {
6705 module.verbose('All items filtered, showing message', searchTerm);
6706 module.add.message(message.noResults);
6707 }
6708 }
6709 else {
6710 module.verbose('All items filtered, hiding dropdown', searchTerm);
6711 module.hideMenu();
6712 }
6713 }
6714 else {
6715 module.remove.empty();
6716 module.remove.message();
6717 }
6718 if(settings.allowAdditions) {
6719 module.add.userSuggestion(module.escape.htmlEntities(query));
6720 }
6721 if(module.is.searchSelection() && module.can.show() && module.is.focusedOnSearch() ) {
6722 module.show();
6723 }
6724 }
6725 ;
6726 if(settings.useLabels && module.has.maxSelections()) {
6727 return;
6728 }
6729 if(settings.apiSettings) {
6730 if( module.can.useAPI() ) {
6731 module.queryRemote(searchTerm, function() {
6732 if(settings.filterRemoteData) {
6733 module.filterItems(searchTerm);
6734 }
6735 var preSelected = $input.val();
6736 if(!Array.isArray(preSelected)) {
6737 preSelected = preSelected!=="" ? preSelected.split(settings.delimiter) : [];
6738 }
6739 $.each(preSelected,function(index,value){
6740 $item.filter('[data-value="'+value+'"]')
6741 .addClass(className.filtered)
6742 ;
6743 });
6744 afterFiltered();
6745 });
6746 }
6747 else {
6748 module.error(error.noAPI);
6749 }
6750 }
6751 else {
6752 module.filterItems(searchTerm);
6753 afterFiltered();
6754 }
6755 },
6756
6757 queryRemote: function(query, callback) {
6758 var
6759 apiSettings = {
6760 errorDuration : false,
6761 cache : 'local',
6762 throttle : settings.throttle,
6763 urlData : {
6764 query: query
6765 },
6766 onError: function() {
6767 module.add.message(message.serverError);
6768 callback();
6769 },
6770 onFailure: function() {
6771 module.add.message(message.serverError);
6772 callback();
6773 },
6774 onSuccess : function(response) {
6775 var
6776 values = response[fields.remoteValues]
6777 ;
6778 if (!Array.isArray(values)){
6779 values = [];
6780 }
6781 module.remove.message();
6782 module.setup.menu({
6783 values: values
6784 });
6785
6786 if(values.length===0 && !settings.allowAdditions) {
6787 module.add.message(message.noResults);
6788 }
6789 callback();
6790 }
6791 }
6792 ;
6793 if( !$module.api('get request') ) {
6794 module.setup.api();
6795 }
6796 apiSettings = $.extend(true, {}, apiSettings, settings.apiSettings);
6797 $module
6798 .api('setting', apiSettings)
6799 .api('query')
6800 ;
6801 },
6802
6803 filterItems: function(query) {
6804 var
6805 searchTerm = module.remove.diacritics(query !== undefined
6806 ? query
6807 : module.get.query()
6808 ),
6809 results = null,
6810 escapedTerm = module.escape.string(searchTerm),
6811 beginsWithRegExp = new RegExp('^' + escapedTerm, 'igm')
6812 ;
6813 // avoid loop if we're matching nothing
6814 if( module.has.query() ) {
6815 results = [];
6816
6817 module.verbose('Searching for matching values', searchTerm);
6818 $item
6819 .each(function(){
6820 var
6821 $choice = $(this),
6822 text,
6823 value
6824 ;
6825 if(settings.match === 'both' || settings.match === 'text') {
6826 text = module.remove.diacritics(String(module.get.choiceText($choice, false)));
6827 if(text.search(beginsWithRegExp) !== -1) {
6828 results.push(this);
6829 return true;
6830 }
6831 else if (settings.fullTextSearch === 'exact' && module.exactSearch(searchTerm, text)) {
6832 results.push(this);
6833 return true;
6834 }
6835 else if (settings.fullTextSearch === true && module.fuzzySearch(searchTerm, text)) {
6836 results.push(this);
6837 return true;
6838 }
6839 }
6840 if(settings.match === 'both' || settings.match === 'value') {
6841 value = module.remove.diacritics(String(module.get.choiceValue($choice, text)));
6842 if(value.search(beginsWithRegExp) !== -1) {
6843 results.push(this);
6844 return true;
6845 }
6846 else if (settings.fullTextSearch === 'exact' && module.exactSearch(searchTerm, value)) {
6847 results.push(this);
6848 return true;
6849 }
6850 else if (settings.fullTextSearch === true && module.fuzzySearch(searchTerm, value)) {
6851 results.push(this);
6852 return true;
6853 }
6854 }
6855 })
6856 ;
6857 }
6858 module.debug('Showing only matched items', searchTerm);
6859 module.remove.filteredItem();
6860 if(results) {
6861 $item
6862 .not(results)
6863 .addClass(className.filtered)
6864 ;
6865 }
6866
6867 if(!module.has.query()) {
6868 $divider
6869 .removeClass(className.hidden);
6870 } else if(settings.hideDividers === true) {
6871 $divider
6872 .addClass(className.hidden);
6873 } else if(settings.hideDividers === 'empty') {
6874 $divider
6875 .removeClass(className.hidden)
6876 .filter(function() {
6877 // First find the last divider in this divider group
6878 // Dividers which are direct siblings are considered a group
6879 var lastDivider = $(this).nextUntil(selector.item);
6880
6881 return (lastDivider.length ? lastDivider : $(this))
6882 // Count all non-filtered items until the next divider (or end of the dropdown)
6883 .nextUntil(selector.divider)
6884 .filter(selector.item + ":not(." + className.filtered + ")")
6885 // Hide divider if no items are found
6886 .length === 0;
6887 })
6888 .addClass(className.hidden);
6889 }
6890 },
6891
6892 fuzzySearch: function(query, term) {
6893 var
6894 termLength = term.length,
6895 queryLength = query.length
6896 ;
6897 query = query.toLowerCase();
6898 term = term.toLowerCase();
6899 if(queryLength > termLength) {
6900 return false;
6901 }
6902 if(queryLength === termLength) {
6903 return (query === term);
6904 }
6905 search: for (var characterIndex = 0, nextCharacterIndex = 0; characterIndex < queryLength; characterIndex++) {
6906 var
6907 queryCharacter = query.charCodeAt(characterIndex)
6908 ;
6909 while(nextCharacterIndex < termLength) {
6910 if(term.charCodeAt(nextCharacterIndex++) === queryCharacter) {
6911 continue search;
6912 }
6913 }
6914 return false;
6915 }
6916 return true;
6917 },
6918 exactSearch: function (query, term) {
6919 query = query.toLowerCase();
6920 term = term.toLowerCase();
6921 return term.indexOf(query) > -1;
6922
6923 },
6924 filterActive: function() {
6925 if(settings.useLabels) {
6926 $item.filter('.' + className.active)
6927 .addClass(className.filtered)
6928 ;
6929 }
6930 },
6931
6932 focusSearch: function(skipHandler) {
6933 if( module.has.search() && !module.is.focusedOnSearch() ) {
6934 if(skipHandler) {
6935 $module.off('focus' + eventNamespace, selector.search);
6936 $search.focus();
6937 $module.on('focus' + eventNamespace, selector.search, module.event.search.focus);
6938 }
6939 else {
6940 $search.focus();
6941 }
6942 }
6943 },
6944
6945 blurSearch: function() {
6946 if( module.has.search() ) {
6947 $search.blur();
6948 }
6949 },
6950
6951 forceSelection: function() {
6952 var
6953 $currentlySelected = $item.not(className.filtered).filter('.' + className.selected).eq(0),
6954 $activeItem = $item.not(className.filtered).filter('.' + className.active).eq(0),
6955 $selectedItem = ($currentlySelected.length > 0)
6956 ? $currentlySelected
6957 : $activeItem,
6958 hasSelected = ($selectedItem.length > 0)
6959 ;
6960 if(hasSelected && !module.is.multiple()) {
6961 module.debug('Forcing partial selection to selected item', $selectedItem);
6962 module.event.item.click.call($selectedItem, {}, true);
6963 }
6964 else {
6965 if(settings.allowAdditions) {
6966 module.set.selected(module.get.query());
6967 module.remove.searchTerm();
6968 }
6969 else {
6970 module.remove.searchTerm();
6971 }
6972 }
6973 },
6974
6975 change: {
6976 values: function(values) {
6977 if(!settings.allowAdditions) {
6978 module.clear();
6979 }
6980 module.debug('Creating dropdown with specified values', values);
6981 module.setup.menu({values: values});
6982 $.each(values, function(index, item) {
6983 if(item.selected == true) {
6984 module.debug('Setting initial selection to', item[fields.value]);
6985 module.set.selected(item[fields.value]);
6986 if(!module.is.multiple()) {
6987 return false;
6988 }
6989 }
6990 });
6991 }
6992 },
6993
6994 event: {
6995 change: function() {
6996 if(!internalChange) {
6997 module.debug('Input changed, updating selection');
6998 module.set.selected();
6999 }
7000 },
7001 focus: function() {
7002 if(settings.showOnFocus && !activated && module.is.hidden() && !pageLostFocus) {
7003 module.show();
7004 }
7005 },
7006 blur: function(event) {
7007 pageLostFocus = (document.activeElement === this);
7008 if(!activated && !pageLostFocus) {
7009 module.remove.activeLabel();
7010 module.hide();
7011 }
7012 },
7013 mousedown: function() {
7014 if(module.is.searchSelection()) {
7015 // prevent menu hiding on immediate re-focus
7016 willRefocus = true;
7017 }
7018 else {
7019 // prevents focus callback from occurring on mousedown
7020 activated = true;
7021 }
7022 },
7023 mouseup: function() {
7024 if(module.is.searchSelection()) {
7025 // prevent menu hiding on immediate re-focus
7026 willRefocus = false;
7027 }
7028 else {
7029 activated = false;
7030 }
7031 },
7032 click: function(event) {
7033 var
7034 $target = $(event.target)
7035 ;
7036 // focus search
7037 if($target.is($module)) {
7038 if(!module.is.focusedOnSearch()) {
7039 module.focusSearch();
7040 }
7041 else {
7042 module.show();
7043 }
7044 }
7045 },
7046 search: {
7047 focus: function() {
7048 activated = true;
7049 if(module.is.multiple()) {
7050 module.remove.activeLabel();
7051 }
7052 if(settings.showOnFocus || event.type !== 'focus') {
7053 module.search();
7054 }
7055 },
7056 blur: function(event) {
7057 pageLostFocus = (document.activeElement === this);
7058 if(module.is.searchSelection() && !willRefocus) {
7059 if(!itemActivated && !pageLostFocus) {
7060 if(settings.forceSelection) {
7061 module.forceSelection();
7062 }
7063 module.hide();
7064 }
7065 }
7066 willRefocus = false;
7067 }
7068 },
7069 clearIcon: {
7070 click: function(event) {
7071 module.clear();
7072 if(module.is.searchSelection()) {
7073 module.remove.searchTerm();
7074 }
7075 module.hide();
7076 event.stopPropagation();
7077 }
7078 },
7079 icon: {
7080 click: function(event) {
7081 if(module.has.search()) {
7082 if(!module.is.active()) {
7083 if(settings.showOnFocus){
7084 module.focusSearch();
7085 } else {
7086 module.toggle();
7087 }
7088 } else {
7089 module.blurSearch();
7090 }
7091 } else {
7092 module.toggle();
7093 }
7094 }
7095 },
7096 text: {
7097 focus: function(event) {
7098 activated = true;
7099 module.focusSearch();
7100 }
7101 },
7102 input: function(event) {
7103 if(module.is.multiple() || module.is.searchSelection()) {
7104 module.set.filtered();
7105 }
7106 clearTimeout(module.timer);
7107 module.timer = setTimeout(module.search, settings.delay.search);
7108 },
7109 label: {
7110 click: function(event) {
7111 var
7112 $label = $(this),
7113 $labels = $module.find(selector.label),
7114 $activeLabels = $labels.filter('.' + className.active),
7115 $nextActive = $label.nextAll('.' + className.active),
7116 $prevActive = $label.prevAll('.' + className.active),
7117 $range = ($nextActive.length > 0)
7118 ? $label.nextUntil($nextActive).add($activeLabels).add($label)
7119 : $label.prevUntil($prevActive).add($activeLabels).add($label)
7120 ;
7121 if(event.shiftKey) {
7122 $activeLabels.removeClass(className.active);
7123 $range.addClass(className.active);
7124 }
7125 else if(event.ctrlKey) {
7126 $label.toggleClass(className.active);
7127 }
7128 else {
7129 $activeLabels.removeClass(className.active);
7130 $label.addClass(className.active);
7131 }
7132 settings.onLabelSelect.apply(this, $labels.filter('.' + className.active));
7133 }
7134 },
7135 remove: {
7136 click: function() {
7137 var
7138 $label = $(this).parent()
7139 ;
7140 if( $label.hasClass(className.active) ) {
7141 // remove all selected labels
7142 module.remove.activeLabels();
7143 }
7144 else {
7145 // remove this label only
7146 module.remove.activeLabels( $label );
7147 }
7148 }
7149 },
7150 test: {
7151 toggle: function(event) {
7152 var
7153 toggleBehavior = (module.is.multiple())
7154 ? module.show
7155 : module.toggle
7156 ;
7157 if(module.is.bubbledLabelClick(event) || module.is.bubbledIconClick(event)) {
7158 return;
7159 }
7160 if( module.determine.eventOnElement(event, toggleBehavior) ) {
7161 event.preventDefault();
7162 }
7163 },
7164 touch: function(event) {
7165 module.determine.eventOnElement(event, function() {
7166 if(event.type == 'touchstart') {
7167 module.timer = setTimeout(function() {
7168 module.hide();
7169 }, settings.delay.touch);
7170 }
7171 else if(event.type == 'touchmove') {
7172 clearTimeout(module.timer);
7173 }
7174 });
7175 event.stopPropagation();
7176 },
7177 hide: function(event) {
7178 if(module.determine.eventInModule(event, module.hide)){
7179 event.preventDefault();
7180 }
7181 }
7182 },
7183 select: {
7184 mutation: function(mutations) {
7185 module.debug('<select> modified, recreating menu');
7186 if(module.is.selectMutation(mutations)) {
7187 module.disconnect.selectObserver();
7188 module.refresh();
7189 module.setup.select();
7190 module.set.selected();
7191 module.observe.select();
7192 }
7193 }
7194 },
7195 menu: {
7196 mutation: function(mutations) {
7197 var
7198 mutation = mutations[0],
7199 $addedNode = mutation.addedNodes
7200 ? $(mutation.addedNodes[0])
7201 : $(false),
7202 $removedNode = mutation.removedNodes
7203 ? $(mutation.removedNodes[0])
7204 : $(false),
7205 $changedNodes = $addedNode.add($removedNode),
7206 isUserAddition = $changedNodes.is(selector.addition) || $changedNodes.closest(selector.addition).length > 0,
7207 isMessage = $changedNodes.is(selector.message) || $changedNodes.closest(selector.message).length > 0
7208 ;
7209 if(isUserAddition || isMessage) {
7210 module.debug('Updating item selector cache');
7211 module.refreshItems();
7212 }
7213 else {
7214 module.debug('Menu modified, updating selector cache');
7215 module.refresh();
7216 }
7217 },
7218 mousedown: function() {
7219 itemActivated = true;
7220 },
7221 mouseup: function() {
7222 itemActivated = false;
7223 }
7224 },
7225 item: {
7226 mouseenter: function(event) {
7227 var
7228 $target = $(event.target),
7229 $item = $(this),
7230 $subMenu = $item.children(selector.menu),
7231 $otherMenus = $item.siblings(selector.item).children(selector.menu),
7232 hasSubMenu = ($subMenu.length > 0),
7233 isBubbledEvent = ($subMenu.find($target).length > 0)
7234 ;
7235 if( !isBubbledEvent && hasSubMenu ) {
7236 clearTimeout(module.itemTimer);
7237 module.itemTimer = setTimeout(function() {
7238 module.verbose('Showing sub-menu', $subMenu);
7239 $.each($otherMenus, function() {
7240 module.animate.hide(false, $(this));
7241 });
7242 module.animate.show(false, $subMenu);
7243 }, settings.delay.show);
7244 event.preventDefault();
7245 }
7246 },
7247 mouseleave: function(event) {
7248 var
7249 $subMenu = $(this).children(selector.menu)
7250 ;
7251 if($subMenu.length > 0) {
7252 clearTimeout(module.itemTimer);
7253 module.itemTimer = setTimeout(function() {
7254 module.verbose('Hiding sub-menu', $subMenu);
7255 module.animate.hide(false, $subMenu);
7256 }, settings.delay.hide);
7257 }
7258 },
7259 click: function (event, skipRefocus) {
7260 var
7261 $choice = $(this),
7262 $target = (event)
7263 ? $(event.target)
7264 : $(''),
7265 $subMenu = $choice.find(selector.menu),
7266 text = module.get.choiceText($choice),
7267 value = module.get.choiceValue($choice, text),
7268 hasSubMenu = ($subMenu.length > 0),
7269 isBubbledEvent = ($subMenu.find($target).length > 0)
7270 ;
7271 // prevents IE11 bug where menu receives focus even though `tabindex=-1`
7272 if (!module.has.search() || !document.activeElement.isEqualNode($search[0])) {
7273 $(document.activeElement).blur();
7274 }
7275 if(!isBubbledEvent && (!hasSubMenu || settings.allowCategorySelection)) {
7276 if(module.is.searchSelection()) {
7277 if(settings.allowAdditions) {
7278 module.remove.userAddition();
7279 }
7280 module.remove.searchTerm();
7281 if(!module.is.focusedOnSearch() && !(skipRefocus == true)) {
7282 module.focusSearch(true);
7283 }
7284 }
7285 if(!settings.useLabels) {
7286 module.remove.filteredItem();
7287 module.set.scrollPosition($choice);
7288 }
7289 module.determine.selectAction.call(this, text, value);
7290 }
7291 }
7292 },
7293
7294 document: {
7295 // label selection should occur even when element has no focus
7296 keydown: function(event) {
7297 var
7298 pressedKey = event.which,
7299 isShortcutKey = module.is.inObject(pressedKey, keys)
7300 ;
7301 if(isShortcutKey) {
7302 var
7303 $label = $module.find(selector.label),
7304 $activeLabel = $label.filter('.' + className.active),
7305 activeValue = $activeLabel.data(metadata.value),
7306 labelIndex = $label.index($activeLabel),
7307 labelCount = $label.length,
7308 hasActiveLabel = ($activeLabel.length > 0),
7309 hasMultipleActive = ($activeLabel.length > 1),
7310 isFirstLabel = (labelIndex === 0),
7311 isLastLabel = (labelIndex + 1 == labelCount),
7312 isSearch = module.is.searchSelection(),
7313 isFocusedOnSearch = module.is.focusedOnSearch(),
7314 isFocused = module.is.focused(),
7315 caretAtStart = (isFocusedOnSearch && module.get.caretPosition(false) === 0),
7316 isSelectedSearch = (caretAtStart && module.get.caretPosition(true) !== 0),
7317 $nextLabel
7318 ;
7319 if(isSearch && !hasActiveLabel && !isFocusedOnSearch) {
7320 return;
7321 }
7322
7323 if(pressedKey == keys.leftArrow) {
7324 // activate previous label
7325 if((isFocused || caretAtStart) && !hasActiveLabel) {
7326 module.verbose('Selecting previous label');
7327 $label.last().addClass(className.active);
7328 }
7329 else if(hasActiveLabel) {
7330 if(!event.shiftKey) {
7331 module.verbose('Selecting previous label');
7332 $label.removeClass(className.active);
7333 }
7334 else {
7335 module.verbose('Adding previous label to selection');
7336 }
7337 if(isFirstLabel && !hasMultipleActive) {
7338 $activeLabel.addClass(className.active);
7339 }
7340 else {
7341 $activeLabel.prev(selector.siblingLabel)
7342 .addClass(className.active)
7343 .end()
7344 ;
7345 }
7346 event.preventDefault();
7347 }
7348 }
7349 else if(pressedKey == keys.rightArrow) {
7350 // activate first label
7351 if(isFocused && !hasActiveLabel) {
7352 $label.first().addClass(className.active);
7353 }
7354 // activate next label
7355 if(hasActiveLabel) {
7356 if(!event.shiftKey) {
7357 module.verbose('Selecting next label');
7358 $label.removeClass(className.active);
7359 }
7360 else {
7361 module.verbose('Adding next label to selection');
7362 }
7363 if(isLastLabel) {
7364 if(isSearch) {
7365 if(!isFocusedOnSearch) {
7366 module.focusSearch();
7367 }
7368 else {
7369 $label.removeClass(className.active);
7370 }
7371 }
7372 else if(hasMultipleActive) {
7373 $activeLabel.next(selector.siblingLabel).addClass(className.active);
7374 }
7375 else {
7376 $activeLabel.addClass(className.active);
7377 }
7378 }
7379 else {
7380 $activeLabel.next(selector.siblingLabel).addClass(className.active);
7381 }
7382 event.preventDefault();
7383 }
7384 }
7385 else if(pressedKey == keys.deleteKey || pressedKey == keys.backspace) {
7386 if(hasActiveLabel) {
7387 module.verbose('Removing active labels');
7388 if(isLastLabel) {
7389 if(isSearch && !isFocusedOnSearch) {
7390 module.focusSearch();
7391 }
7392 }
7393 $activeLabel.last().next(selector.siblingLabel).addClass(className.active);
7394 module.remove.activeLabels($activeLabel);
7395 event.preventDefault();
7396 }
7397 else if(caretAtStart && !isSelectedSearch && !hasActiveLabel && pressedKey == keys.backspace) {
7398 module.verbose('Removing last label on input backspace');
7399 $activeLabel = $label.last().addClass(className.active);
7400 module.remove.activeLabels($activeLabel);
7401 }
7402 }
7403 else {
7404 $activeLabel.removeClass(className.active);
7405 }
7406 }
7407 }
7408 },
7409
7410 keydown: function(event) {
7411 var
7412 pressedKey = event.which,
7413 isShortcutKey = module.is.inObject(pressedKey, keys)
7414 ;
7415 if(isShortcutKey) {
7416 var
7417 $currentlySelected = $item.not(selector.unselectable).filter('.' + className.selected).eq(0),
7418 $activeItem = $menu.children('.' + className.active).eq(0),
7419 $selectedItem = ($currentlySelected.length > 0)
7420 ? $currentlySelected
7421 : $activeItem,
7422 $visibleItems = ($selectedItem.length > 0)
7423 ? $selectedItem.siblings(':not(.' + className.filtered +')').addBack()
7424 : $menu.children(':not(.' + className.filtered +')'),
7425 $subMenu = $selectedItem.children(selector.menu),
7426 $parentMenu = $selectedItem.closest(selector.menu),
7427 inVisibleMenu = ($parentMenu.hasClass(className.visible) || $parentMenu.hasClass(className.animating) || $parentMenu.parent(selector.menu).length > 0),
7428 hasSubMenu = ($subMenu.length> 0),
7429 hasSelectedItem = ($selectedItem.length > 0),
7430 selectedIsSelectable = ($selectedItem.not(selector.unselectable).length > 0),
7431 delimiterPressed = (pressedKey == keys.delimiter && settings.allowAdditions && module.is.multiple()),
7432 isAdditionWithoutMenu = (settings.allowAdditions && settings.hideAdditions && (pressedKey == keys.enter || delimiterPressed) && selectedIsSelectable),
7433 $nextItem,
7434 isSubMenuItem,
7435 newIndex
7436 ;
7437 // allow selection with menu closed
7438 if(isAdditionWithoutMenu) {
7439 module.verbose('Selecting item from keyboard shortcut', $selectedItem);
7440 module.event.item.click.call($selectedItem, event);
7441 if(module.is.searchSelection()) {
7442 module.remove.searchTerm();
7443 }
7444 if(module.is.multiple()){
7445 event.preventDefault();
7446 }
7447 }
7448
7449 // visible menu keyboard shortcuts
7450 if( module.is.visible() ) {
7451
7452 // enter (select or open sub-menu)
7453 if(pressedKey == keys.enter || delimiterPressed) {
7454 if(pressedKey == keys.enter && hasSelectedItem && hasSubMenu && !settings.allowCategorySelection) {
7455 module.verbose('Pressed enter on unselectable category, opening sub menu');
7456 pressedKey = keys.rightArrow;
7457 }
7458 else if(selectedIsSelectable) {
7459 module.verbose('Selecting item from keyboard shortcut', $selectedItem);
7460 module.event.item.click.call($selectedItem, event);
7461 if(module.is.searchSelection()) {
7462 module.remove.searchTerm();
7463 if(module.is.multiple()) {
7464 $search.focus();
7465 }
7466 }
7467 }
7468 event.preventDefault();
7469 }
7470
7471 // sub-menu actions
7472 if(hasSelectedItem) {
7473
7474 if(pressedKey == keys.leftArrow) {
7475
7476 isSubMenuItem = ($parentMenu[0] !== $menu[0]);
7477
7478 if(isSubMenuItem) {
7479 module.verbose('Left key pressed, closing sub-menu');
7480 module.animate.hide(false, $parentMenu);
7481 $selectedItem
7482 .removeClass(className.selected)
7483 ;
7484 $parentMenu
7485 .closest(selector.item)
7486 .addClass(className.selected)
7487 ;
7488 event.preventDefault();
7489 }
7490 }
7491
7492 // right arrow (show sub-menu)
7493 if(pressedKey == keys.rightArrow) {
7494 if(hasSubMenu) {
7495 module.verbose('Right key pressed, opening sub-menu');
7496 module.animate.show(false, $subMenu);
7497 $selectedItem
7498 .removeClass(className.selected)
7499 ;
7500 $subMenu
7501 .find(selector.item).eq(0)
7502 .addClass(className.selected)
7503 ;
7504 event.preventDefault();
7505 }
7506 }
7507 }
7508
7509 // up arrow (traverse menu up)
7510 if(pressedKey == keys.upArrow) {
7511 $nextItem = (hasSelectedItem && inVisibleMenu)
7512 ? $selectedItem.prevAll(selector.item + ':not(' + selector.unselectable + ')').eq(0)
7513 : $item.eq(0)
7514 ;
7515 if($visibleItems.index( $nextItem ) < 0) {
7516 module.verbose('Up key pressed but reached top of current menu');
7517 event.preventDefault();
7518 return;
7519 }
7520 else {
7521 module.verbose('Up key pressed, changing active item');
7522 $selectedItem
7523 .removeClass(className.selected)
7524 ;
7525 $nextItem
7526 .addClass(className.selected)
7527 ;
7528 module.set.scrollPosition($nextItem);
7529 if(settings.selectOnKeydown && module.is.single()) {
7530 module.set.selectedItem($nextItem);
7531 }
7532 }
7533 event.preventDefault();
7534 }
7535
7536 // down arrow (traverse menu down)
7537 if(pressedKey == keys.downArrow) {
7538 $nextItem = (hasSelectedItem && inVisibleMenu)
7539 ? $nextItem = $selectedItem.nextAll(selector.item + ':not(' + selector.unselectable + ')').eq(0)
7540 : $item.eq(0)
7541 ;
7542 if($nextItem.length === 0) {
7543 module.verbose('Down key pressed but reached bottom of current menu');
7544 event.preventDefault();
7545 return;
7546 }
7547 else {
7548 module.verbose('Down key pressed, changing active item');
7549 $item
7550 .removeClass(className.selected)
7551 ;
7552 $nextItem
7553 .addClass(className.selected)
7554 ;
7555 module.set.scrollPosition($nextItem);
7556 if(settings.selectOnKeydown && module.is.single()) {
7557 module.set.selectedItem($nextItem);
7558 }
7559 }
7560 event.preventDefault();
7561 }
7562
7563 // page down (show next page)
7564 if(pressedKey == keys.pageUp) {
7565 module.scrollPage('up');
7566 event.preventDefault();
7567 }
7568 if(pressedKey == keys.pageDown) {
7569 module.scrollPage('down');
7570 event.preventDefault();
7571 }
7572
7573 // escape (close menu)
7574 if(pressedKey == keys.escape) {
7575 module.verbose('Escape key pressed, closing dropdown');
7576 module.hide();
7577 }
7578
7579 }
7580 else {
7581 // delimiter key
7582 if(delimiterPressed) {
7583 event.preventDefault();
7584 }
7585 // down arrow (open menu)
7586 if(pressedKey == keys.downArrow && !module.is.visible()) {
7587 module.verbose('Down key pressed, showing dropdown');
7588 module.show();
7589 event.preventDefault();
7590 }
7591 }
7592 }
7593 else {
7594 if( !module.has.search() ) {
7595 module.set.selectedLetter( String.fromCharCode(pressedKey) );
7596 }
7597 }
7598 }
7599 },
7600
7601 trigger: {
7602 change: function() {
7603 var
7604 events = document.createEvent('HTMLEvents'),
7605 inputElement = $input[0]
7606 ;
7607 if(inputElement) {
7608 module.verbose('Triggering native change event');
7609 events.initEvent('change', true, false);
7610 inputElement.dispatchEvent(events);
7611 }
7612 }
7613 },
7614
7615 determine: {
7616 selectAction: function(text, value) {
7617 module.verbose('Determining action', settings.action);
7618 if( $.isFunction( module.action[settings.action] ) ) {
7619 module.verbose('Triggering preset action', settings.action, text, value);
7620 module.action[ settings.action ].call(element, text, value, this);
7621 }
7622 else if( $.isFunction(settings.action) ) {
7623 module.verbose('Triggering user action', settings.action, text, value);
7624 settings.action.call(element, text, value, this);
7625 }
7626 else {
7627 module.error(error.action, settings.action);
7628 }
7629 },
7630 eventInModule: function(event, callback) {
7631 var
7632 $target = $(event.target),
7633 inDocument = ($target.closest(document.documentElement).length > 0),
7634 inModule = ($target.closest($module).length > 0)
7635 ;
7636 callback = $.isFunction(callback)
7637 ? callback
7638 : function(){}
7639 ;
7640 if(inDocument && !inModule) {
7641 module.verbose('Triggering event', callback);
7642 callback();
7643 return true;
7644 }
7645 else {
7646 module.verbose('Event occurred in dropdown, canceling callback');
7647 return false;
7648 }
7649 },
7650 eventOnElement: function(event, callback) {
7651 var
7652 $target = $(event.target),
7653 $label = $target.closest(selector.siblingLabel),
7654 inVisibleDOM = document.body.contains(event.target),
7655 notOnLabel = ($module.find($label).length === 0),
7656 notInMenu = ($target.closest($menu).length === 0)
7657 ;
7658 callback = $.isFunction(callback)
7659 ? callback
7660 : function(){}
7661 ;
7662 if(inVisibleDOM && notOnLabel && notInMenu) {
7663 module.verbose('Triggering event', callback);
7664 callback();
7665 return true;
7666 }
7667 else {
7668 module.verbose('Event occurred in dropdown menu, canceling callback');
7669 return false;
7670 }
7671 }
7672 },
7673
7674 action: {
7675
7676 nothing: function() {},
7677
7678 activate: function(text, value, element) {
7679 value = (value !== undefined)
7680 ? value
7681 : text
7682 ;
7683 if( module.can.activate( $(element) ) ) {
7684 module.set.selected(value, $(element));
7685 if(!module.is.multiple()) {
7686 module.hideAndClear();
7687 }
7688 }
7689 },
7690
7691 select: function(text, value, element) {
7692 value = (value !== undefined)
7693 ? value
7694 : text
7695 ;
7696 if( module.can.activate( $(element) ) ) {
7697 module.set.value(value, text, $(element));
7698 if(!module.is.multiple()) {
7699 module.hideAndClear();
7700 }
7701 }
7702 },
7703
7704 combo: function(text, value, element) {
7705 value = (value !== undefined)
7706 ? value
7707 : text
7708 ;
7709 module.set.selected(value, $(element));
7710 module.hideAndClear();
7711 },
7712
7713 hide: function(text, value, element) {
7714 module.set.value(value, text, $(element));
7715 module.hideAndClear();
7716 }
7717
7718 },
7719
7720 get: {
7721 id: function() {
7722 return id;
7723 },
7724 defaultText: function() {
7725 return $module.data(metadata.defaultText);
7726 },
7727 defaultValue: function() {
7728 return $module.data(metadata.defaultValue);
7729 },
7730 placeholderText: function() {
7731 if(settings.placeholder != 'auto' && typeof settings.placeholder == 'string') {
7732 return settings.placeholder;
7733 }
7734 return $module.data(metadata.placeholderText) || '';
7735 },
7736 text: function() {
7737 return $text.text();
7738 },
7739 query: function() {
7740 return $.trim($search.val());
7741 },
7742 searchWidth: function(value) {
7743 value = (value !== undefined)
7744 ? value
7745 : $search.val()
7746 ;
7747 $sizer.text(value);
7748 // prevent rounding issues
7749 return Math.ceil( $sizer.width() + 1);
7750 },
7751 selectionCount: function() {
7752 var
7753 values = module.get.values(),
7754 count
7755 ;
7756 count = ( module.is.multiple() )
7757 ? Array.isArray(values)
7758 ? values.length
7759 : 0
7760 : (module.get.value() !== '')
7761 ? 1
7762 : 0
7763 ;
7764 return count;
7765 },
7766 transition: function($subMenu) {
7767 return (settings.transition == 'auto')
7768 ? module.is.upward($subMenu)
7769 ? 'slide up'
7770 : 'slide down'
7771 : settings.transition
7772 ;
7773 },
7774 userValues: function() {
7775 var
7776 values = module.get.values()
7777 ;
7778 if(!values) {
7779 return false;
7780 }
7781 values = Array.isArray(values)
7782 ? values
7783 : [values]
7784 ;
7785 return $.grep(values, function(value) {
7786 return (module.get.item(value) === false);
7787 });
7788 },
7789 uniqueArray: function(array) {
7790 return $.grep(array, function (value, index) {
7791 return $.inArray(value, array) === index;
7792 });
7793 },
7794 caretPosition: function(returnEndPos) {
7795 var
7796 input = $search.get(0),
7797 range,
7798 rangeLength
7799 ;
7800 if(returnEndPos && 'selectionEnd' in input){
7801 return input.selectionEnd;
7802 }
7803 else if(!returnEndPos && 'selectionStart' in input) {
7804 return input.selectionStart;
7805 }
7806 if (document.selection) {
7807 input.focus();
7808 range = document.selection.createRange();
7809 rangeLength = range.text.length;
7810 if(returnEndPos) {
7811 return rangeLength;
7812 }
7813 range.moveStart('character', -input.value.length);
7814 return range.text.length - rangeLength;
7815 }
7816 },
7817 value: function() {
7818 var
7819 value = ($input.length > 0)
7820 ? $input.val()
7821 : $module.data(metadata.value),
7822 isEmptyMultiselect = (Array.isArray(value) && value.length === 1 && value[0] === '')
7823 ;
7824 // prevents placeholder element from being selected when multiple
7825 return (value === undefined || isEmptyMultiselect)
7826 ? ''
7827 : value
7828 ;
7829 },
7830 values: function() {
7831 var
7832 value = module.get.value()
7833 ;
7834 if(value === '') {
7835 return '';
7836 }
7837 return ( !module.has.selectInput() && module.is.multiple() )
7838 ? (typeof value == 'string') // delimited string
7839 ? value.split(settings.delimiter)
7840 : ''
7841 : value
7842 ;
7843 },
7844 remoteValues: function() {
7845 var
7846 values = module.get.values(),
7847 remoteValues = false
7848 ;
7849 if(values) {
7850 if(typeof values == 'string') {
7851 values = [values];
7852 }
7853 $.each(values, function(index, value) {
7854 var
7855 name = module.read.remoteData(value)
7856 ;
7857 module.verbose('Restoring value from session data', name, value);
7858 if(name) {
7859 if(!remoteValues) {
7860 remoteValues = {};
7861 }
7862 remoteValues[value] = name;
7863 }
7864 });
7865 }
7866 return remoteValues;
7867 },
7868 choiceText: function($choice, preserveHTML) {
7869 preserveHTML = (preserveHTML !== undefined)
7870 ? preserveHTML
7871 : settings.preserveHTML
7872 ;
7873 if($choice) {
7874 if($choice.find(selector.menu).length > 0) {
7875 module.verbose('Retrieving text of element with sub-menu');
7876 $choice = $choice.clone();
7877 $choice.find(selector.menu).remove();
7878 $choice.find(selector.menuIcon).remove();
7879 }
7880 return ($choice.data(metadata.text) !== undefined)
7881 ? $choice.data(metadata.text)
7882 : (preserveHTML)
7883 ? $.trim($choice.html())
7884 : $.trim($choice.text())
7885 ;
7886 }
7887 },
7888 choiceValue: function($choice, choiceText) {
7889 choiceText = choiceText || module.get.choiceText($choice);
7890 if(!$choice) {
7891 return false;
7892 }
7893 return ($choice.data(metadata.value) !== undefined)
7894 ? String( $choice.data(metadata.value) )
7895 : (typeof choiceText === 'string')
7896 ? $.trim(choiceText.toLowerCase())
7897 : String(choiceText)
7898 ;
7899 },
7900 inputEvent: function() {
7901 var
7902 input = $search[0]
7903 ;
7904 if(input) {
7905 return (input.oninput !== undefined)
7906 ? 'input'
7907 : (input.onpropertychange !== undefined)
7908 ? 'propertychange'
7909 : 'keyup'
7910 ;
7911 }
7912 return false;
7913 },
7914 selectValues: function() {
7915 var
7916 select = {}
7917 ;
7918 select.values = [];
7919 $module
7920 .find('option')
7921 .each(function() {
7922 var
7923 $option = $(this),
7924 name = $option.html(),
7925 disabled = $option.attr('disabled'),
7926 value = ( $option.attr('value') !== undefined )
7927 ? $option.attr('value')
7928 : name
7929 ;
7930 if(settings.placeholder === 'auto' && value === '') {
7931 select.placeholder = name;
7932 }
7933 else {
7934 select.values.push({
7935 name : name,
7936 value : value,
7937 disabled : disabled
7938 });
7939 }
7940 })
7941 ;
7942 if(settings.placeholder && settings.placeholder !== 'auto') {
7943 module.debug('Setting placeholder value to', settings.placeholder);
7944 select.placeholder = settings.placeholder;
7945 }
7946 if(settings.sortSelect) {
7947 if(settings.sortSelect === true) {
7948 select.values.sort(function(a, b) {
7949 return a.name.localeCompare(b.name);
7950 });
7951 } else if(settings.sortSelect === 'natural') {
7952 select.values.sort(function(a, b) {
7953 return (a.name.toLowerCase().localeCompare(b.name.toLowerCase()));
7954 });
7955 } else if($.isFunction(settings.sortSelect)) {
7956 select.values.sort(settings.sortSelect);
7957 }
7958 module.debug('Retrieved and sorted values from select', select);
7959 }
7960 else {
7961 module.debug('Retrieved values from select', select);
7962 }
7963 return select;
7964 },
7965 activeItem: function() {
7966 return $item.filter('.' + className.active);
7967 },
7968 selectedItem: function() {
7969 var
7970 $selectedItem = $item.not(selector.unselectable).filter('.' + className.selected)
7971 ;
7972 return ($selectedItem.length > 0)
7973 ? $selectedItem
7974 : $item.eq(0)
7975 ;
7976 },
7977 itemWithAdditions: function(value) {
7978 var
7979 $items = module.get.item(value),
7980 $userItems = module.create.userChoice(value),
7981 hasUserItems = ($userItems && $userItems.length > 0)
7982 ;
7983 if(hasUserItems) {
7984 $items = ($items.length > 0)
7985 ? $items.add($userItems)
7986 : $userItems
7987 ;
7988 }
7989 return $items;
7990 },
7991 item: function(value, strict) {
7992 var
7993 $selectedItem = false,
7994 shouldSearch,
7995 isMultiple
7996 ;
7997 value = (value !== undefined)
7998 ? value
7999 : ( module.get.values() !== undefined)
8000 ? module.get.values()
8001 : module.get.text()
8002 ;
8003 shouldSearch = (isMultiple)
8004 ? (value.length > 0)
8005 : (value !== undefined && value !== null)
8006 ;
8007 isMultiple = (module.is.multiple() && Array.isArray(value));
8008 strict = (value === '' || value === false || value === true)
8009 ? true
8010 : strict || false
8011 ;
8012 if(shouldSearch) {
8013 $item
8014 .each(function() {
8015 var
8016 $choice = $(this),
8017 optionText = module.get.choiceText($choice),
8018 optionValue = module.get.choiceValue($choice, optionText)
8019 ;
8020 // safe early exit
8021 if(optionValue === null || optionValue === undefined) {
8022 return;
8023 }
8024 if(isMultiple) {
8025 if($.inArray( String(optionValue), value) !== -1) {
8026 $selectedItem = ($selectedItem)
8027 ? $selectedItem.add($choice)
8028 : $choice
8029 ;
8030 }
8031 }
8032 else if(strict) {
8033 module.verbose('Ambiguous dropdown value using strict type check', $choice, value);
8034 if( optionValue === value) {
8035 $selectedItem = $choice;
8036 return true;
8037 }
8038 }
8039 else {
8040 if( String(optionValue) == String(value)) {
8041 module.verbose('Found select item by value', optionValue, value);
8042 $selectedItem = $choice;
8043 return true;
8044 }
8045 }
8046 })
8047 ;
8048 }
8049 return $selectedItem;
8050 }
8051 },
8052
8053 check: {
8054 maxSelections: function(selectionCount) {
8055 if(settings.maxSelections) {
8056 selectionCount = (selectionCount !== undefined)
8057 ? selectionCount
8058 : module.get.selectionCount()
8059 ;
8060 if(selectionCount >= settings.maxSelections) {
8061 module.debug('Maximum selection count reached');
8062 if(settings.useLabels) {
8063 $item.addClass(className.filtered);
8064 module.add.message(message.maxSelections);
8065 }
8066 return true;
8067 }
8068 else {
8069 module.verbose('No longer at maximum selection count');
8070 module.remove.message();
8071 module.remove.filteredItem();
8072 if(module.is.searchSelection()) {
8073 module.filterItems();
8074 }
8075 return false;
8076 }
8077 }
8078 return true;
8079 }
8080 },
8081
8082 restore: {
8083 defaults: function() {
8084 module.clear();
8085 module.restore.defaultText();
8086 module.restore.defaultValue();
8087 },
8088 defaultText: function() {
8089 var
8090 defaultText = module.get.defaultText(),
8091 placeholderText = module.get.placeholderText
8092 ;
8093 if(defaultText === placeholderText) {
8094 module.debug('Restoring default placeholder text', defaultText);
8095 module.set.placeholderText(defaultText);
8096 }
8097 else {
8098 module.debug('Restoring default text', defaultText);
8099 module.set.text(defaultText);
8100 }
8101 },
8102 placeholderText: function() {
8103 module.set.placeholderText();
8104 },
8105 defaultValue: function() {
8106 var
8107 defaultValue = module.get.defaultValue()
8108 ;
8109 if(defaultValue !== undefined) {
8110 module.debug('Restoring default value', defaultValue);
8111 if(defaultValue !== '') {
8112 module.set.value(defaultValue);
8113 module.set.selected();
8114 }
8115 else {
8116 module.remove.activeItem();
8117 module.remove.selectedItem();
8118 }
8119 }
8120 },
8121 labels: function() {
8122 if(settings.allowAdditions) {
8123 if(!settings.useLabels) {
8124 module.error(error.labels);
8125 settings.useLabels = true;
8126 }
8127 module.debug('Restoring selected values');
8128 module.create.userLabels();
8129 }
8130 module.check.maxSelections();
8131 },
8132 selected: function() {
8133 module.restore.values();
8134 if(module.is.multiple()) {
8135 module.debug('Restoring previously selected values and labels');
8136 module.restore.labels();
8137 }
8138 else {
8139 module.debug('Restoring previously selected values');
8140 }
8141 },
8142 values: function() {
8143 // prevents callbacks from occurring on initial load
8144 module.set.initialLoad();
8145 if(settings.apiSettings && settings.saveRemoteData && module.get.remoteValues()) {
8146 module.restore.remoteValues();
8147 }
8148 else {
8149 module.set.selected();
8150 }
8151 if(module.get.item()) {
8152 $input.removeClass(className.noselection);
8153 } else {
8154 $input.addClass(className.noselection);
8155 }
8156 module.remove.initialLoad();
8157 },
8158 remoteValues: function() {
8159 var
8160 values = module.get.remoteValues()
8161 ;
8162 module.debug('Recreating selected from session data', values);
8163 if(values) {
8164 if( module.is.single() ) {
8165 $.each(values, function(value, name) {
8166 module.set.text(name);
8167 });
8168 }
8169 else {
8170 $.each(values, function(value, name) {
8171 module.add.label(value, name);
8172 });
8173 }
8174 }
8175 }
8176 },
8177
8178 read: {
8179 remoteData: function(value) {
8180 var
8181 name
8182 ;
8183 if(window.Storage === undefined) {
8184 module.error(error.noStorage);
8185 return;
8186 }
8187 name = sessionStorage.getItem(value);
8188 return (name !== undefined)
8189 ? name
8190 : false
8191 ;
8192 }
8193 },
8194
8195 save: {
8196 defaults: function() {
8197 module.save.defaultText();
8198 module.save.placeholderText();
8199 module.save.defaultValue();
8200 },
8201 defaultValue: function() {
8202 var
8203 value = module.get.value()
8204 ;
8205 module.verbose('Saving default value as', value);
8206 $module.data(metadata.defaultValue, value);
8207 },
8208 defaultText: function() {
8209 var
8210 text = module.get.text()
8211 ;
8212 module.verbose('Saving default text as', text);
8213 $module.data(metadata.defaultText, text);
8214 },
8215 placeholderText: function() {
8216 var
8217 text
8218 ;
8219 if(settings.placeholder !== false && $text.hasClass(className.placeholder)) {
8220 text = module.get.text();
8221 module.verbose('Saving placeholder text as', text);
8222 $module.data(metadata.placeholderText, text);
8223 }
8224 },
8225 remoteData: function(name, value) {
8226 if(window.Storage === undefined) {
8227 module.error(error.noStorage);
8228 return;
8229 }
8230 module.verbose('Saving remote data to session storage', value, name);
8231 sessionStorage.setItem(value, name);
8232 }
8233 },
8234
8235 clear: function() {
8236 if(module.is.multiple() && settings.useLabels) {
8237 module.remove.labels();
8238 }
8239 else {
8240 module.remove.activeItem();
8241 module.remove.selectedItem();
8242 module.remove.filteredItem();
8243 }
8244 module.set.placeholderText();
8245 module.clearValue();
8246 },
8247
8248 clearValue: function() {
8249 module.set.value('');
8250 },
8251
8252 scrollPage: function(direction, $selectedItem) {
8253 var
8254 $currentItem = $selectedItem || module.get.selectedItem(),
8255 $menu = $currentItem.closest(selector.menu),
8256 menuHeight = $menu.outerHeight(),
8257 currentScroll = $menu.scrollTop(),
8258 itemHeight = $item.eq(0).outerHeight(),
8259 itemsPerPage = Math.floor(menuHeight / itemHeight),
8260 maxScroll = $menu.prop('scrollHeight'),
8261 newScroll = (direction == 'up')
8262 ? currentScroll - (itemHeight * itemsPerPage)
8263 : currentScroll + (itemHeight * itemsPerPage),
8264 $selectableItem = $item.not(selector.unselectable),
8265 isWithinRange,
8266 $nextSelectedItem,
8267 elementIndex
8268 ;
8269 elementIndex = (direction == 'up')
8270 ? $selectableItem.index($currentItem) - itemsPerPage
8271 : $selectableItem.index($currentItem) + itemsPerPage
8272 ;
8273 isWithinRange = (direction == 'up')
8274 ? (elementIndex >= 0)
8275 : (elementIndex < $selectableItem.length)
8276 ;
8277 $nextSelectedItem = (isWithinRange)
8278 ? $selectableItem.eq(elementIndex)
8279 : (direction == 'up')
8280 ? $selectableItem.first()
8281 : $selectableItem.last()
8282 ;
8283 if($nextSelectedItem.length > 0) {
8284 module.debug('Scrolling page', direction, $nextSelectedItem);
8285 $currentItem
8286 .removeClass(className.selected)
8287 ;
8288 $nextSelectedItem
8289 .addClass(className.selected)
8290 ;
8291 if(settings.selectOnKeydown && module.is.single()) {
8292 module.set.selectedItem($nextSelectedItem);
8293 }
8294 $menu
8295 .scrollTop(newScroll)
8296 ;
8297 }
8298 },
8299
8300 set: {
8301 filtered: function() {
8302 var
8303 isMultiple = module.is.multiple(),
8304 isSearch = module.is.searchSelection(),
8305 isSearchMultiple = (isMultiple && isSearch),
8306 searchValue = (isSearch)
8307 ? module.get.query()
8308 : '',
8309 hasSearchValue = (typeof searchValue === 'string' && searchValue.length > 0),
8310 searchWidth = module.get.searchWidth(),
8311 valueIsSet = searchValue !== ''
8312 ;
8313 if(isMultiple && hasSearchValue) {
8314 module.verbose('Adjusting input width', searchWidth, settings.glyphWidth);
8315 $search.css('width', searchWidth);
8316 }
8317 if(hasSearchValue || (isSearchMultiple && valueIsSet)) {
8318 module.verbose('Hiding placeholder text');
8319 $text.addClass(className.filtered);
8320 }
8321 else if(!isMultiple || (isSearchMultiple && !valueIsSet)) {
8322 module.verbose('Showing placeholder text');
8323 $text.removeClass(className.filtered);
8324 }
8325 },
8326 empty: function() {
8327 $module.addClass(className.empty);
8328 },
8329 loading: function() {
8330 $module.addClass(className.loading);
8331 },
8332 placeholderText: function(text) {
8333 text = text || module.get.placeholderText();
8334 module.debug('Setting placeholder text', text);
8335 module.set.text(text);
8336 $text.addClass(className.placeholder);
8337 },
8338 tabbable: function() {
8339 if( module.is.searchSelection() ) {
8340 module.debug('Added tabindex to searchable dropdown');
8341 $search
8342 .val('')
8343 .attr('tabindex', 0)
8344 ;
8345 $menu
8346 .attr('tabindex', -1)
8347 ;
8348 }
8349 else {
8350 module.debug('Added tabindex to dropdown');
8351 if( $module.attr('tabindex') === undefined) {
8352 $module
8353 .attr('tabindex', 0)
8354 ;
8355 $menu
8356 .attr('tabindex', -1)
8357 ;
8358 }
8359 }
8360 },
8361 initialLoad: function() {
8362 module.verbose('Setting initial load');
8363 initialLoad = true;
8364 },
8365 activeItem: function($item) {
8366 if( settings.allowAdditions && $item.filter(selector.addition).length > 0 ) {
8367 $item.addClass(className.filtered);
8368 }
8369 else {
8370 $item.addClass(className.active);
8371 }
8372 },
8373 partialSearch: function(text) {
8374 var
8375 length = module.get.query().length
8376 ;
8377 $search.val( text.substr(0, length));
8378 },
8379 scrollPosition: function($item, forceScroll) {
8380 var
8381 edgeTolerance = 5,
8382 $menu,
8383 hasActive,
8384 offset,
8385 itemHeight,
8386 itemOffset,
8387 menuOffset,
8388 menuScroll,
8389 menuHeight,
8390 abovePage,
8391 belowPage
8392 ;
8393
8394 $item = $item || module.get.selectedItem();
8395 $menu = $item.closest(selector.menu);
8396 hasActive = ($item && $item.length > 0);
8397 forceScroll = (forceScroll !== undefined)
8398 ? forceScroll
8399 : false
8400 ;
8401 if($item && $menu.length > 0 && hasActive) {
8402 itemOffset = $item.position().top;
8403
8404 $menu.addClass(className.loading);
8405 menuScroll = $menu.scrollTop();
8406 menuOffset = $menu.offset().top;
8407 itemOffset = $item.offset().top;
8408 offset = menuScroll - menuOffset + itemOffset;
8409 if(!forceScroll) {
8410 menuHeight = $menu.height();
8411 belowPage = menuScroll + menuHeight < (offset + edgeTolerance);
8412 abovePage = ((offset - edgeTolerance) < menuScroll);
8413 }
8414 module.debug('Scrolling to active item', offset);
8415 if(forceScroll || abovePage || belowPage) {
8416 $menu.scrollTop(offset);
8417 }
8418 $menu.removeClass(className.loading);
8419 }
8420 },
8421 text: function(text) {
8422 if(settings.action === 'combo') {
8423 module.debug('Changing combo button text', text, $combo);
8424 if(settings.preserveHTML) {
8425 $combo.html(text);
8426 }
8427 else {
8428 $combo.text(text);
8429 }
8430 }
8431 else if(settings.action === 'activate') {
8432 if(text !== module.get.placeholderText()) {
8433 $text.removeClass(className.placeholder);
8434 }
8435 module.debug('Changing text', text, $text);
8436 $text
8437 .removeClass(className.filtered)
8438 ;
8439 if(settings.preserveHTML) {
8440 $text.html(text);
8441 }
8442 else {
8443 $text.text(text);
8444 }
8445 }
8446 },
8447 selectedItem: function($item) {
8448 var
8449 value = module.get.choiceValue($item),
8450 searchText = module.get.choiceText($item, false),
8451 text = module.get.choiceText($item, true)
8452 ;
8453 module.debug('Setting user selection to item', $item);
8454 module.remove.activeItem();
8455 module.set.partialSearch(searchText);
8456 module.set.activeItem($item);
8457 module.set.selected(value, $item);
8458 module.set.text(text);
8459 },
8460 selectedLetter: function(letter) {
8461 var
8462 $selectedItem = $item.filter('.' + className.selected),
8463 alreadySelectedLetter = $selectedItem.length > 0 && module.has.firstLetter($selectedItem, letter),
8464 $nextValue = false,
8465 $nextItem
8466 ;
8467 // check next of same letter
8468 if(alreadySelectedLetter) {
8469 $nextItem = $selectedItem.nextAll($item).eq(0);
8470 if( module.has.firstLetter($nextItem, letter) ) {
8471 $nextValue = $nextItem;
8472 }
8473 }
8474 // check all values
8475 if(!$nextValue) {
8476 $item
8477 .each(function(){
8478 if(module.has.firstLetter($(this), letter)) {
8479 $nextValue = $(this);
8480 return false;
8481 }
8482 })
8483 ;
8484 }
8485 // set next value
8486 if($nextValue) {
8487 module.verbose('Scrolling to next value with letter', letter);
8488 module.set.scrollPosition($nextValue);
8489 $selectedItem.removeClass(className.selected);
8490 $nextValue.addClass(className.selected);
8491 if(settings.selectOnKeydown && module.is.single()) {
8492 module.set.selectedItem($nextValue);
8493 }
8494 }
8495 },
8496 direction: function($menu) {
8497 if(settings.direction == 'auto') {
8498 // reset position, remove upward if it's base menu
8499 if (!$menu) {
8500 module.remove.upward();
8501 } else if (module.is.upward($menu)) {
8502 //we need make sure when make assertion openDownward for $menu, $menu does not have upward class
8503 module.remove.upward($menu);
8504 }
8505
8506 if(module.can.openDownward($menu)) {
8507 module.remove.upward($menu);
8508 }
8509 else {
8510 module.set.upward($menu);
8511 }
8512 if(!module.is.leftward($menu) && !module.can.openRightward($menu)) {
8513 module.set.leftward($menu);
8514 }
8515 }
8516 else if(settings.direction == 'upward') {
8517 module.set.upward($menu);
8518 }
8519 },
8520 upward: function($currentMenu) {
8521 var $element = $currentMenu || $module;
8522 $element.addClass(className.upward);
8523 },
8524 leftward: function($currentMenu) {
8525 var $element = $currentMenu || $menu;
8526 $element.addClass(className.leftward);
8527 },
8528 value: function(value, text, $selected) {
8529 if(value !== undefined && value !== '' && !(Array.isArray(value) && value.length === 0)) {
8530 $input.removeClass(className.noselection);
8531 } else {
8532 $input.addClass(className.noselection);
8533 }
8534 var
8535 escapedValue = module.escape.value(value),
8536 hasInput = ($input.length > 0),
8537 currentValue = module.get.values(),
8538 stringValue = (value !== undefined)
8539 ? String(value)
8540 : value,
8541 newValue
8542 ;
8543 if(hasInput) {
8544 if(!settings.allowReselection && stringValue == currentValue) {
8545 module.verbose('Skipping value update already same value', value, currentValue);
8546 if(!module.is.initialLoad()) {
8547 return;
8548 }
8549 }
8550
8551 if( module.is.single() && module.has.selectInput() && module.can.extendSelect() ) {
8552 module.debug('Adding user option', value);
8553 module.add.optionValue(value);
8554 }
8555 module.debug('Updating input value', escapedValue, currentValue);
8556 internalChange = true;
8557 $input
8558 .val(escapedValue)
8559 ;
8560 if(settings.fireOnInit === false && module.is.initialLoad()) {
8561 module.debug('Input native change event ignored on initial load');
8562 }
8563 else {
8564 module.trigger.change();
8565 }
8566 internalChange = false;
8567 }
8568 else {
8569 module.verbose('Storing value in metadata', escapedValue, $input);
8570 if(escapedValue !== currentValue) {
8571 $module.data(metadata.value, stringValue);
8572 }
8573 }
8574 if(settings.fireOnInit === false && module.is.initialLoad()) {
8575 module.verbose('No callback on initial load', settings.onChange);
8576 }
8577 else {
8578 settings.onChange.call(element, value, text, $selected);
8579 }
8580 },
8581 active: function() {
8582 $module
8583 .addClass(className.active)
8584 ;
8585 },
8586 multiple: function() {
8587 $module.addClass(className.multiple);
8588 },
8589 visible: function() {
8590 $module.addClass(className.visible);
8591 },
8592 exactly: function(value, $selectedItem) {
8593 module.debug('Setting selected to exact values');
8594 module.clear();
8595 module.set.selected(value, $selectedItem);
8596 },
8597 selected: function(value, $selectedItem) {
8598 var
8599 isMultiple = module.is.multiple(),
8600 $userSelectedItem
8601 ;
8602 $selectedItem = (settings.allowAdditions)
8603 ? $selectedItem || module.get.itemWithAdditions(value)
8604 : $selectedItem || module.get.item(value)
8605 ;
8606 if(!$selectedItem) {
8607 return;
8608 }
8609 module.debug('Setting selected menu item to', $selectedItem);
8610 if(module.is.multiple()) {
8611 module.remove.searchWidth();
8612 }
8613 if(module.is.single()) {
8614 module.remove.activeItem();
8615 module.remove.selectedItem();
8616 }
8617 else if(settings.useLabels) {
8618 module.remove.selectedItem();
8619 }
8620 // select each item
8621 $selectedItem
8622 .each(function() {
8623 var
8624 $selected = $(this),
8625 selectedText = module.get.choiceText($selected),
8626 selectedValue = module.get.choiceValue($selected, selectedText),
8627
8628 isFiltered = $selected.hasClass(className.filtered),
8629 isActive = $selected.hasClass(className.active),
8630 isUserValue = $selected.hasClass(className.addition),
8631 shouldAnimate = (isMultiple && $selectedItem.length == 1)
8632 ;
8633 if(isMultiple) {
8634 if(!isActive || isUserValue) {
8635 if(settings.apiSettings && settings.saveRemoteData) {
8636 module.save.remoteData(selectedText, selectedValue);
8637 }
8638 if(settings.useLabels) {
8639 module.add.label(selectedValue, selectedText, shouldAnimate);
8640 module.add.value(selectedValue, selectedText, $selected);
8641 module.set.activeItem($selected);
8642 module.filterActive();
8643 module.select.nextAvailable($selectedItem);
8644 }
8645 else {
8646 module.add.value(selectedValue, selectedText, $selected);
8647 module.set.text(module.add.variables(message.count));
8648 module.set.activeItem($selected);
8649 }
8650 }
8651 else if(!isFiltered) {
8652 module.debug('Selected active value, removing label');
8653 module.remove.selected(selectedValue);
8654 }
8655 }
8656 else {
8657 if(settings.apiSettings && settings.saveRemoteData) {
8658 module.save.remoteData(selectedText, selectedValue);
8659 }
8660 module.set.text(selectedText);
8661 module.set.value(selectedValue, selectedText, $selected);
8662 $selected
8663 .addClass(className.active)
8664 .addClass(className.selected)
8665 ;
8666 }
8667 })
8668 ;
8669 },
8670 },
8671
8672 add: {
8673 label: function(value, text, shouldAnimate) {
8674 var
8675 $next = module.is.searchSelection()
8676 ? $search
8677 : $text,
8678 escapedValue = module.escape.value(value),
8679 $label
8680 ;
8681 if(settings.ignoreCase) {
8682 escapedValue = escapedValue.toLowerCase();
8683 }
8684 $label = $('<a />')
8685 .addClass(className.label)
8686 .attr('data-' + metadata.value, escapedValue)
8687 .html(templates.label(escapedValue, text, settings.preserveHTML, settings.className))
8688 ;
8689 $label = settings.onLabelCreate.call($label, escapedValue, text);
8690
8691 if(module.has.label(value)) {
8692 module.debug('User selection already exists, skipping', escapedValue);
8693 return;
8694 }
8695 if(settings.label.variation) {
8696 $label.addClass(settings.label.variation);
8697 }
8698 if(shouldAnimate === true) {
8699 module.debug('Animating in label', $label);
8700 $label
8701 .addClass(className.hidden)
8702 .insertBefore($next)
8703 .transition(settings.label.transition, settings.label.duration)
8704 ;
8705 }
8706 else {
8707 module.debug('Adding selection label', $label);
8708 $label
8709 .insertBefore($next)
8710 ;
8711 }
8712 },
8713 message: function(message) {
8714 var
8715 $message = $menu.children(selector.message),
8716 html = settings.templates.message(module.add.variables(message))
8717 ;
8718 if($message.length > 0) {
8719 $message
8720 .html(html)
8721 ;
8722 }
8723 else {
8724 $message = $('<div/>')
8725 .html(html)
8726 .addClass(className.message)
8727 .appendTo($menu)
8728 ;
8729 }
8730 },
8731 optionValue: function(value) {
8732 var
8733 escapedValue = module.escape.value(value),
8734 $option = $input.find('option[value="' + module.escape.string(escapedValue) + '"]'),
8735 hasOption = ($option.length > 0)
8736 ;
8737 if(hasOption) {
8738 return;
8739 }
8740 // temporarily disconnect observer
8741 module.disconnect.selectObserver();
8742 if( module.is.single() ) {
8743 module.verbose('Removing previous user addition');
8744 $input.find('option.' + className.addition).remove();
8745 }
8746 $('<option/>')
8747 .prop('value', escapedValue)
8748 .addClass(className.addition)
8749 .html(value)
8750 .appendTo($input)
8751 ;
8752 module.verbose('Adding user addition as an <option>', value);
8753 module.observe.select();
8754 },
8755 userSuggestion: function(value) {
8756 var
8757 $addition = $menu.children(selector.addition),
8758 $existingItem = module.get.item(value),
8759 alreadyHasValue = $existingItem && $existingItem.not(selector.addition).length,
8760 hasUserSuggestion = $addition.length > 0,
8761 html
8762 ;
8763 if(settings.useLabels && module.has.maxSelections()) {
8764 return;
8765 }
8766 if(value === '' || alreadyHasValue) {
8767 $addition.remove();
8768 return;
8769 }
8770 if(hasUserSuggestion) {
8771 $addition
8772 .data(metadata.value, value)
8773 .data(metadata.text, value)
8774 .attr('data-' + metadata.value, value)
8775 .attr('data-' + metadata.text, value)
8776 .removeClass(className.filtered)
8777 ;
8778 if(!settings.hideAdditions) {
8779 html = settings.templates.addition( module.add.variables(message.addResult, value) );
8780 $addition
8781 .html(html)
8782 ;
8783 }
8784 module.verbose('Replacing user suggestion with new value', $addition);
8785 }
8786 else {
8787 $addition = module.create.userChoice(value);
8788 $addition
8789 .prependTo($menu)
8790 ;
8791 module.verbose('Adding item choice to menu corresponding with user choice addition', $addition);
8792 }
8793 if(!settings.hideAdditions || module.is.allFiltered()) {
8794 $addition
8795 .addClass(className.selected)
8796 .siblings()
8797 .removeClass(className.selected)
8798 ;
8799 }
8800 module.refreshItems();
8801 },
8802 variables: function(message, term) {
8803 var
8804 hasCount = (message.search('{count}') !== -1),
8805 hasMaxCount = (message.search('{maxCount}') !== -1),
8806 hasTerm = (message.search('{term}') !== -1),
8807 values,
8808 count,
8809 query
8810 ;
8811 module.verbose('Adding templated variables to message', message);
8812 if(hasCount) {
8813 count = module.get.selectionCount();
8814 message = message.replace('{count}', count);
8815 }
8816 if(hasMaxCount) {
8817 count = module.get.selectionCount();
8818 message = message.replace('{maxCount}', settings.maxSelections);
8819 }
8820 if(hasTerm) {
8821 query = term || module.get.query();
8822 message = message.replace('{term}', query);
8823 }
8824 return message;
8825 },
8826 value: function(addedValue, addedText, $selectedItem) {
8827 var
8828 currentValue = module.get.values(),
8829 newValue
8830 ;
8831 if(module.has.value(addedValue)) {
8832 module.debug('Value already selected');
8833 return;
8834 }
8835 if(addedValue === '') {
8836 module.debug('Cannot select blank values from multiselect');
8837 return;
8838 }
8839 // extend current array
8840 if(Array.isArray(currentValue)) {
8841 newValue = currentValue.concat([addedValue]);
8842 newValue = module.get.uniqueArray(newValue);
8843 }
8844 else {
8845 newValue = [addedValue];
8846 }
8847 // add values
8848 if( module.has.selectInput() ) {
8849 if(module.can.extendSelect()) {
8850 module.debug('Adding value to select', addedValue, newValue, $input);
8851 module.add.optionValue(addedValue);
8852 }
8853 }
8854 else {
8855 newValue = newValue.join(settings.delimiter);
8856 module.debug('Setting hidden input to delimited value', newValue, $input);
8857 }
8858
8859 if(settings.fireOnInit === false && module.is.initialLoad()) {
8860 module.verbose('Skipping onadd callback on initial load', settings.onAdd);
8861 }
8862 else {
8863 settings.onAdd.call(element, addedValue, addedText, $selectedItem);
8864 }
8865 module.set.value(newValue, addedValue, addedText, $selectedItem);
8866 module.check.maxSelections();
8867 },
8868 },
8869
8870 remove: {
8871 active: function() {
8872 $module.removeClass(className.active);
8873 },
8874 activeLabel: function() {
8875 $module.find(selector.label).removeClass(className.active);
8876 },
8877 empty: function() {
8878 $module.removeClass(className.empty);
8879 },
8880 loading: function() {
8881 $module.removeClass(className.loading);
8882 },
8883 initialLoad: function() {
8884 initialLoad = false;
8885 },
8886 upward: function($currentMenu) {
8887 var $element = $currentMenu || $module;
8888 $element.removeClass(className.upward);
8889 },
8890 leftward: function($currentMenu) {
8891 var $element = $currentMenu || $menu;
8892 $element.removeClass(className.leftward);
8893 },
8894 visible: function() {
8895 $module.removeClass(className.visible);
8896 },
8897 activeItem: function() {
8898 $item.removeClass(className.active);
8899 },
8900 filteredItem: function() {
8901 if(settings.useLabels && module.has.maxSelections() ) {
8902 return;
8903 }
8904 if(settings.useLabels && module.is.multiple()) {
8905 $item.not('.' + className.active).removeClass(className.filtered);
8906 }
8907 else {
8908 $item.removeClass(className.filtered);
8909 }
8910 if(settings.hideDividers) {
8911 $divider.removeClass(className.hidden);
8912 }
8913 module.remove.empty();
8914 },
8915 optionValue: function(value) {
8916 var
8917 escapedValue = module.escape.value(value),
8918 $option = $input.find('option[value="' + module.escape.string(escapedValue) + '"]'),
8919 hasOption = ($option.length > 0)
8920 ;
8921 if(!hasOption || !$option.hasClass(className.addition)) {
8922 return;
8923 }
8924 // temporarily disconnect observer
8925 if(selectObserver) {
8926 selectObserver.disconnect();
8927 module.verbose('Temporarily disconnecting mutation observer');
8928 }
8929 $option.remove();
8930 module.verbose('Removing user addition as an <option>', escapedValue);
8931 if(selectObserver) {
8932 selectObserver.observe($input[0], {
8933 childList : true,
8934 subtree : true
8935 });
8936 }
8937 },
8938 message: function() {
8939 $menu.children(selector.message).remove();
8940 },
8941 searchWidth: function() {
8942 $search.css('width', '');
8943 },
8944 searchTerm: function() {
8945 module.verbose('Cleared search term');
8946 $search.val('');
8947 module.set.filtered();
8948 },
8949 userAddition: function() {
8950 $item.filter(selector.addition).remove();
8951 },
8952 selected: function(value, $selectedItem) {
8953 $selectedItem = (settings.allowAdditions)
8954 ? $selectedItem || module.get.itemWithAdditions(value)
8955 : $selectedItem || module.get.item(value)
8956 ;
8957
8958 if(!$selectedItem) {
8959 return false;
8960 }
8961
8962 $selectedItem
8963 .each(function() {
8964 var
8965 $selected = $(this),
8966 selectedText = module.get.choiceText($selected),
8967 selectedValue = module.get.choiceValue($selected, selectedText)
8968 ;
8969 if(module.is.multiple()) {
8970 if(settings.useLabels) {
8971 module.remove.value(selectedValue, selectedText, $selected);
8972 module.remove.label(selectedValue);
8973 }
8974 else {
8975 module.remove.value(selectedValue, selectedText, $selected);
8976 if(module.get.selectionCount() === 0) {
8977 module.set.placeholderText();
8978 }
8979 else {
8980 module.set.text(module.add.variables(message.count));
8981 }
8982 }
8983 }
8984 else {
8985 module.remove.value(selectedValue, selectedText, $selected);
8986 }
8987 $selected
8988 .removeClass(className.filtered)
8989 .removeClass(className.active)
8990 ;
8991 if(settings.useLabels) {
8992 $selected.removeClass(className.selected);
8993 }
8994 })
8995 ;
8996 },
8997 selectedItem: function() {
8998 $item.removeClass(className.selected);
8999 },
9000 value: function(removedValue, removedText, $removedItem) {
9001 var
9002 values = module.get.values(),
9003 newValue
9004 ;
9005 if( module.has.selectInput() ) {
9006 module.verbose('Input is <select> removing selected option', removedValue);
9007 newValue = module.remove.arrayValue(removedValue, values);
9008 module.remove.optionValue(removedValue);
9009 }
9010 else {
9011 module.verbose('Removing from delimited values', removedValue);
9012 newValue = module.remove.arrayValue(removedValue, values);
9013 newValue = newValue.join(settings.delimiter);
9014 }
9015 if(settings.fireOnInit === false && module.is.initialLoad()) {
9016 module.verbose('No callback on initial load', settings.onRemove);
9017 }
9018 else {
9019 settings.onRemove.call(element, removedValue, removedText, $removedItem);
9020 }
9021 module.set.value(newValue, removedText, $removedItem);
9022 module.check.maxSelections();
9023 },
9024 arrayValue: function(removedValue, values) {
9025 if( !Array.isArray(values) ) {
9026 values = [values];
9027 }
9028 values = $.grep(values, function(value){
9029 return (removedValue != value);
9030 });
9031 module.verbose('Removed value from delimited string', removedValue, values);
9032 return values;
9033 },
9034 label: function(value, shouldAnimate) {
9035 var
9036 $labels = $module.find(selector.label),
9037 $removedLabel = $labels.filter('[data-' + metadata.value + '="' + module.escape.string(value) +'"]')
9038 ;
9039 module.verbose('Removing label', $removedLabel);
9040 $removedLabel.remove();
9041 },
9042 activeLabels: function($activeLabels) {
9043 $activeLabels = $activeLabels || $module.find(selector.label).filter('.' + className.active);
9044 module.verbose('Removing active label selections', $activeLabels);
9045 module.remove.labels($activeLabels);
9046 },
9047 labels: function($labels) {
9048 $labels = $labels || $module.find(selector.label);
9049 module.verbose('Removing labels', $labels);
9050 $labels
9051 .each(function(){
9052 var
9053 $label = $(this),
9054 value = $label.data(metadata.value),
9055 stringValue = (value !== undefined)
9056 ? String(value)
9057 : value,
9058 isUserValue = module.is.userValue(stringValue)
9059 ;
9060 if(settings.onLabelRemove.call($label, value) === false) {
9061 module.debug('Label remove callback cancelled removal');
9062 return;
9063 }
9064 module.remove.message();
9065 if(isUserValue) {
9066 module.remove.value(stringValue);
9067 module.remove.label(stringValue);
9068 }
9069 else {
9070 // selected will also remove label
9071 module.remove.selected(stringValue);
9072 }
9073 })
9074 ;
9075 },
9076 tabbable: function() {
9077 if( module.is.searchSelection() ) {
9078 module.debug('Searchable dropdown initialized');
9079 $search
9080 .removeAttr('tabindex')
9081 ;
9082 $menu
9083 .removeAttr('tabindex')
9084 ;
9085 }
9086 else {
9087 module.debug('Simple selection dropdown initialized');
9088 $module
9089 .removeAttr('tabindex')
9090 ;
9091 $menu
9092 .removeAttr('tabindex')
9093 ;
9094 }
9095 },
9096 diacritics: function(text) {
9097 return settings.ignoreDiacritics ? text.normalize('NFD').replace(/[\u0300-\u036f]/g, '') : text;
9098 }
9099 },
9100
9101 has: {
9102 menuSearch: function() {
9103 return (module.has.search() && $search.closest($menu).length > 0);
9104 },
9105 clearItem: function() {
9106 return ($clear.length > 0);
9107 },
9108 search: function() {
9109 return ($search.length > 0);
9110 },
9111 sizer: function() {
9112 return ($sizer.length > 0);
9113 },
9114 selectInput: function() {
9115 return ( $input.is('select') );
9116 },
9117 minCharacters: function(searchTerm) {
9118 if(settings.minCharacters) {
9119 searchTerm = (searchTerm !== undefined)
9120 ? String(searchTerm)
9121 : String(module.get.query())
9122 ;
9123 return (searchTerm.length >= settings.minCharacters);
9124 }
9125 return true;
9126 },
9127 firstLetter: function($item, letter) {
9128 var
9129 text,
9130 firstLetter
9131 ;
9132 if(!$item || $item.length === 0 || typeof letter !== 'string') {
9133 return false;
9134 }
9135 text = module.get.choiceText($item, false);
9136 letter = letter.toLowerCase();
9137 firstLetter = String(text).charAt(0).toLowerCase();
9138 return (letter == firstLetter);
9139 },
9140 input: function() {
9141 return ($input.length > 0);
9142 },
9143 items: function() {
9144 return ($item.length > 0);
9145 },
9146 menu: function() {
9147 return ($menu.length > 0);
9148 },
9149 message: function() {
9150 return ($menu.children(selector.message).length !== 0);
9151 },
9152 label: function(value) {
9153 var
9154 escapedValue = module.escape.value(value),
9155 $labels = $module.find(selector.label)
9156 ;
9157 if(settings.ignoreCase) {
9158 escapedValue = escapedValue.toLowerCase();
9159 }
9160 return ($labels.filter('[data-' + metadata.value + '="' + module.escape.string(escapedValue) +'"]').length > 0);
9161 },
9162 maxSelections: function() {
9163 return (settings.maxSelections && module.get.selectionCount() >= settings.maxSelections);
9164 },
9165 allResultsFiltered: function() {
9166 var
9167 $normalResults = $item.not(selector.addition)
9168 ;
9169 return ($normalResults.filter(selector.unselectable).length === $normalResults.length);
9170 },
9171 userSuggestion: function() {
9172 return ($menu.children(selector.addition).length > 0);
9173 },
9174 query: function() {
9175 return (module.get.query() !== '');
9176 },
9177 value: function(value) {
9178 return (settings.ignoreCase)
9179 ? module.has.valueIgnoringCase(value)
9180 : module.has.valueMatchingCase(value)
9181 ;
9182 },
9183 valueMatchingCase: function(value) {
9184 var
9185 values = module.get.values(),
9186 hasValue = Array.isArray(values)
9187 ? values && ($.inArray(value, values) !== -1)
9188 : (values == value)
9189 ;
9190 return (hasValue)
9191 ? true
9192 : false
9193 ;
9194 },
9195 valueIgnoringCase: function(value) {
9196 var
9197 values = module.get.values(),
9198 hasValue = false
9199 ;
9200 if(!Array.isArray(values)) {
9201 values = [values];
9202 }
9203 $.each(values, function(index, existingValue) {
9204 if(String(value).toLowerCase() == String(existingValue).toLowerCase()) {
9205 hasValue = true;
9206 return false;
9207 }
9208 });
9209 return hasValue;
9210 }
9211 },
9212
9213 is: {
9214 active: function() {
9215 return $module.hasClass(className.active);
9216 },
9217 animatingInward: function() {
9218 return $menu.transition('is inward');
9219 },
9220 animatingOutward: function() {
9221 return $menu.transition('is outward');
9222 },
9223 bubbledLabelClick: function(event) {
9224 return $(event.target).is('select, input') && $module.closest('label').length > 0;
9225 },
9226 bubbledIconClick: function(event) {
9227 return $(event.target).closest($icon).length > 0;
9228 },
9229 alreadySetup: function() {
9230 return ($module.is('select') && $module.parent(selector.dropdown).data(moduleNamespace) !== undefined && $module.prev().length === 0);
9231 },
9232 animating: function($subMenu) {
9233 return ($subMenu)
9234 ? $subMenu.transition && $subMenu.transition('is animating')
9235 : $menu.transition && $menu.transition('is animating')
9236 ;
9237 },
9238 leftward: function($subMenu) {
9239 var $selectedMenu = $subMenu || $menu;
9240 return $selectedMenu.hasClass(className.leftward);
9241 },
9242 clearable: function() {
9243 return ($module.hasClass(className.clearable) || settings.clearable);
9244 },
9245 disabled: function() {
9246 return $module.hasClass(className.disabled);
9247 },
9248 focused: function() {
9249 return (document.activeElement === $module[0]);
9250 },
9251 focusedOnSearch: function() {
9252 return (document.activeElement === $search[0]);
9253 },
9254 allFiltered: function() {
9255 return( (module.is.multiple() || module.has.search()) && !(settings.hideAdditions == false && module.has.userSuggestion()) && !module.has.message() && module.has.allResultsFiltered() );
9256 },
9257 hidden: function($subMenu) {
9258 return !module.is.visible($subMenu);
9259 },
9260 initialLoad: function() {
9261 return initialLoad;
9262 },
9263 inObject: function(needle, object) {
9264 var
9265 found = false
9266 ;
9267 $.each(object, function(index, property) {
9268 if(property == needle) {
9269 found = true;
9270 return true;
9271 }
9272 });
9273 return found;
9274 },
9275 multiple: function() {
9276 return $module.hasClass(className.multiple);
9277 },
9278 remote: function() {
9279 return settings.apiSettings && module.can.useAPI();
9280 },
9281 single: function() {
9282 return !module.is.multiple();
9283 },
9284 selectMutation: function(mutations) {
9285 var
9286 selectChanged = false
9287 ;
9288 $.each(mutations, function(index, mutation) {
9289 if($(mutation.target).is('select') || $(mutation.addedNodes).is('select')) {
9290 selectChanged = true;
9291 return false;
9292 }
9293 });
9294 return selectChanged;
9295 },
9296 search: function() {
9297 return $module.hasClass(className.search);
9298 },
9299 searchSelection: function() {
9300 return ( module.has.search() && $search.parent(selector.dropdown).length === 1 );
9301 },
9302 selection: function() {
9303 return $module.hasClass(className.selection);
9304 },
9305 userValue: function(value) {
9306 return ($.inArray(value, module.get.userValues()) !== -1);
9307 },
9308 upward: function($menu) {
9309 var $element = $menu || $module;
9310 return $element.hasClass(className.upward);
9311 },
9312 visible: function($subMenu) {
9313 return ($subMenu)
9314 ? $subMenu.hasClass(className.visible)
9315 : $menu.hasClass(className.visible)
9316 ;
9317 },
9318 verticallyScrollableContext: function() {
9319 var
9320 overflowY = ($context.get(0) !== window)
9321 ? $context.css('overflow-y')
9322 : false
9323 ;
9324 return (overflowY == 'auto' || overflowY == 'scroll');
9325 },
9326 horizontallyScrollableContext: function() {
9327 var
9328 overflowX = ($context.get(0) !== window)
9329 ? $context.css('overflow-X')
9330 : false
9331 ;
9332 return (overflowX == 'auto' || overflowX == 'scroll');
9333 }
9334 },
9335
9336 can: {
9337 activate: function($item) {
9338 if(settings.useLabels) {
9339 return true;
9340 }
9341 if(!module.has.maxSelections()) {
9342 return true;
9343 }
9344 if(module.has.maxSelections() && $item.hasClass(className.active)) {
9345 return true;
9346 }
9347 return false;
9348 },
9349 openDownward: function($subMenu) {
9350 var
9351 $currentMenu = $subMenu || $menu,
9352 canOpenDownward = true,
9353 onScreen = {},
9354 calculations
9355 ;
9356 $currentMenu
9357 .addClass(className.loading)
9358 ;
9359 calculations = {
9360 context: {
9361 offset : ($context.get(0) === window)
9362 ? { top: 0, left: 0}
9363 : $context.offset(),
9364 scrollTop : $context.scrollTop(),
9365 height : $context.outerHeight()
9366 },
9367 menu : {
9368 offset: $currentMenu.offset(),
9369 height: $currentMenu.outerHeight()
9370 }
9371 };
9372 if(module.is.verticallyScrollableContext()) {
9373 calculations.menu.offset.top += calculations.context.scrollTop;
9374 }
9375 onScreen = {
9376 above : (calculations.context.scrollTop) <= calculations.menu.offset.top - calculations.context.offset.top - calculations.menu.height,
9377 below : (calculations.context.scrollTop + calculations.context.height) >= calculations.menu.offset.top - calculations.context.offset.top + calculations.menu.height
9378 };
9379 if(onScreen.below) {
9380 module.verbose('Dropdown can fit in context downward', onScreen);
9381 canOpenDownward = true;
9382 }
9383 else if(!onScreen.below && !onScreen.above) {
9384 module.verbose('Dropdown cannot fit in either direction, favoring downward', onScreen);
9385 canOpenDownward = true;
9386 }
9387 else {
9388 module.verbose('Dropdown cannot fit below, opening upward', onScreen);
9389 canOpenDownward = false;
9390 }
9391 $currentMenu.removeClass(className.loading);
9392 return canOpenDownward;
9393 },
9394 openRightward: function($subMenu) {
9395 var
9396 $currentMenu = $subMenu || $menu,
9397 canOpenRightward = true,
9398 isOffscreenRight = false,
9399 calculations
9400 ;
9401 $currentMenu
9402 .addClass(className.loading)
9403 ;
9404 calculations = {
9405 context: {
9406 offset : ($context.get(0) === window)
9407 ? { top: 0, left: 0}
9408 : $context.offset(),
9409 scrollLeft : $context.scrollLeft(),
9410 width : $context.outerWidth()
9411 },
9412 menu: {
9413 offset : $currentMenu.offset(),
9414 width : $currentMenu.outerWidth()
9415 }
9416 };
9417 if(module.is.horizontallyScrollableContext()) {
9418 calculations.menu.offset.left += calculations.context.scrollLeft;
9419 }
9420 isOffscreenRight = (calculations.menu.offset.left - calculations.context.offset.left + calculations.menu.width >= calculations.context.scrollLeft + calculations.context.width);
9421 if(isOffscreenRight) {
9422 module.verbose('Dropdown cannot fit in context rightward', isOffscreenRight);
9423 canOpenRightward = false;
9424 }
9425 $currentMenu.removeClass(className.loading);
9426 return canOpenRightward;
9427 },
9428 click: function() {
9429 return (hasTouch || settings.on == 'click');
9430 },
9431 extendSelect: function() {
9432 return settings.allowAdditions || settings.apiSettings;
9433 },
9434 show: function() {
9435 return !module.is.disabled() && (module.has.items() || module.has.message());
9436 },
9437 useAPI: function() {
9438 return $.fn.api !== undefined;
9439 }
9440 },
9441
9442 animate: {
9443 show: function(callback, $subMenu) {
9444 var
9445 $currentMenu = $subMenu || $menu,
9446 start = ($subMenu)
9447 ? function() {}
9448 : function() {
9449 module.hideSubMenus();
9450 module.hideOthers();
9451 module.set.active();
9452 },
9453 transition
9454 ;
9455 callback = $.isFunction(callback)
9456 ? callback
9457 : function(){}
9458 ;
9459 module.verbose('Doing menu show animation', $currentMenu);
9460 module.set.direction($subMenu);
9461 transition = module.get.transition($subMenu);
9462 if( module.is.selection() ) {
9463 module.set.scrollPosition(module.get.selectedItem(), true);
9464 }
9465 if( module.is.hidden($currentMenu) || module.is.animating($currentMenu) ) {
9466 if(transition == 'none') {
9467 start();
9468 $currentMenu.transition('show');
9469 callback.call(element);
9470 }
9471 else if($.fn.transition !== undefined && $module.transition('is supported')) {
9472 $currentMenu
9473 .transition({
9474 animation : transition + ' in',
9475 debug : settings.debug,
9476 verbose : settings.verbose,
9477 duration : settings.duration,
9478 queue : true,
9479 onStart : start,
9480 onComplete : function() {
9481 callback.call(element);
9482 }
9483 })
9484 ;
9485 }
9486 else {
9487 module.error(error.noTransition, transition);
9488 }
9489 }
9490 },
9491 hide: function(callback, $subMenu) {
9492 var
9493 $currentMenu = $subMenu || $menu,
9494 duration = ($subMenu)
9495 ? (settings.duration * 0.9)
9496 : settings.duration,
9497 start = ($subMenu)
9498 ? function() {}
9499 : function() {
9500 if( module.can.click() ) {
9501 module.unbind.intent();
9502 }
9503 module.remove.active();
9504 },
9505 transition = module.get.transition($subMenu)
9506 ;
9507 callback = $.isFunction(callback)
9508 ? callback
9509 : function(){}
9510 ;
9511 if( module.is.visible($currentMenu) || module.is.animating($currentMenu) ) {
9512 module.verbose('Doing menu hide animation', $currentMenu);
9513
9514 if(transition == 'none') {
9515 start();
9516 $currentMenu.transition('hide');
9517 callback.call(element);
9518 }
9519 else if($.fn.transition !== undefined && $module.transition('is supported')) {
9520 $currentMenu
9521 .transition({
9522 animation : transition + ' out',
9523 duration : settings.duration,
9524 debug : settings.debug,
9525 verbose : settings.verbose,
9526 queue : false,
9527 onStart : start,
9528 onComplete : function() {
9529 callback.call(element);
9530 }
9531 })
9532 ;
9533 }
9534 else {
9535 module.error(error.transition);
9536 }
9537 }
9538 }
9539 },
9540
9541 hideAndClear: function() {
9542 module.remove.searchTerm();
9543 if( module.has.maxSelections() ) {
9544 return;
9545 }
9546 if(module.has.search()) {
9547 module.hide(function() {
9548 module.remove.filteredItem();
9549 });
9550 }
9551 else {
9552 module.hide();
9553 }
9554 },
9555
9556 delay: {
9557 show: function() {
9558 module.verbose('Delaying show event to ensure user intent');
9559 clearTimeout(module.timer);
9560 module.timer = setTimeout(module.show, settings.delay.show);
9561 },
9562 hide: function() {
9563 module.verbose('Delaying hide event to ensure user intent');
9564 clearTimeout(module.timer);
9565 module.timer = setTimeout(module.hide, settings.delay.hide);
9566 }
9567 },
9568
9569 escape: {
9570 value: function(value) {
9571 var
9572 multipleValues = Array.isArray(value),
9573 stringValue = (typeof value === 'string'),
9574 isUnparsable = (!stringValue && !multipleValues),
9575 hasQuotes = (stringValue && value.search(regExp.quote) !== -1),
9576 values = []
9577 ;
9578 if(isUnparsable || !hasQuotes) {
9579 return value;
9580 }
9581 module.debug('Encoding quote values for use in select', value);
9582 if(multipleValues) {
9583 $.each(value, function(index, value){
9584 values.push(value.replace(regExp.quote, '&quot;'));
9585 });
9586 return values;
9587 }
9588 return value.replace(regExp.quote, '&quot;');
9589 },
9590 string: function(text) {
9591 text = String(text);
9592 return text.replace(regExp.escape, '\\$&');
9593 },
9594 htmlEntities: function(string) {
9595 var
9596 badChars = /[&<>"'`]/g,
9597 shouldEscape = /[&<>"'`]/,
9598 escape = {
9599 "&": "&amp;",
9600 "<": "&lt;",
9601 ">": "&gt;",
9602 '"': "&quot;",
9603 "'": "&#x27;",
9604 "`": "&#x60;"
9605 },
9606 escapedChar = function(chr) {
9607 return escape[chr];
9608 }
9609 ;
9610 if(shouldEscape.test(string)) {
9611 return string.replace(badChars, escapedChar);
9612 }
9613 return string;
9614 }
9615 },
9616
9617 setting: function(name, value) {
9618 module.debug('Changing setting', name, value);
9619 if( $.isPlainObject(name) ) {
9620 $.extend(true, settings, name);
9621 }
9622 else if(value !== undefined) {
9623 if($.isPlainObject(settings[name])) {
9624 $.extend(true, settings[name], value);
9625 }
9626 else {
9627 settings[name] = value;
9628 }
9629 }
9630 else {
9631 return settings[name];
9632 }
9633 },
9634 internal: function(name, value) {
9635 if( $.isPlainObject(name) ) {
9636 $.extend(true, module, name);
9637 }
9638 else if(value !== undefined) {
9639 module[name] = value;
9640 }
9641 else {
9642 return module[name];
9643 }
9644 },
9645 debug: function() {
9646 if(!settings.silent && settings.debug) {
9647 if(settings.performance) {
9648 module.performance.log(arguments);
9649 }
9650 else {
9651 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
9652 module.debug.apply(console, arguments);
9653 }
9654 }
9655 },
9656 verbose: function() {
9657 if(!settings.silent && settings.verbose && settings.debug) {
9658 if(settings.performance) {
9659 module.performance.log(arguments);
9660 }
9661 else {
9662 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
9663 module.verbose.apply(console, arguments);
9664 }
9665 }
9666 },
9667 error: function() {
9668 if(!settings.silent) {
9669 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
9670 module.error.apply(console, arguments);
9671 }
9672 },
9673 performance: {
9674 log: function(message) {
9675 var
9676 currentTime,
9677 executionTime,
9678 previousTime
9679 ;
9680 if(settings.performance) {
9681 currentTime = new Date().getTime();
9682 previousTime = time || currentTime;
9683 executionTime = currentTime - previousTime;
9684 time = currentTime;
9685 performance.push({
9686 'Name' : message[0],
9687 'Arguments' : [].slice.call(message, 1) || '',
9688 'Element' : element,
9689 'Execution Time' : executionTime
9690 });
9691 }
9692 clearTimeout(module.performance.timer);
9693 module.performance.timer = setTimeout(module.performance.display, 500);
9694 },
9695 display: function() {
9696 var
9697 title = settings.name + ':',
9698 totalTime = 0
9699 ;
9700 time = false;
9701 clearTimeout(module.performance.timer);
9702 $.each(performance, function(index, data) {
9703 totalTime += data['Execution Time'];
9704 });
9705 title += ' ' + totalTime + 'ms';
9706 if(moduleSelector) {
9707 title += ' \'' + moduleSelector + '\'';
9708 }
9709 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
9710 console.groupCollapsed(title);
9711 if(console.table) {
9712 console.table(performance);
9713 }
9714 else {
9715 $.each(performance, function(index, data) {
9716 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
9717 });
9718 }
9719 console.groupEnd();
9720 }
9721 performance = [];
9722 }
9723 },
9724 invoke: function(query, passedArguments, context) {
9725 var
9726 object = instance,
9727 maxDepth,
9728 found,
9729 response
9730 ;
9731 passedArguments = passedArguments || queryArguments;
9732 context = element || context;
9733 if(typeof query == 'string' && object !== undefined) {
9734 query = query.split(/[\. ]/);
9735 maxDepth = query.length - 1;
9736 $.each(query, function(depth, value) {
9737 var camelCaseValue = (depth != maxDepth)
9738 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
9739 : query
9740 ;
9741 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
9742 object = object[camelCaseValue];
9743 }
9744 else if( object[camelCaseValue] !== undefined ) {
9745 found = object[camelCaseValue];
9746 return false;
9747 }
9748 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
9749 object = object[value];
9750 }
9751 else if( object[value] !== undefined ) {
9752 found = object[value];
9753 return false;
9754 }
9755 else {
9756 module.error(error.method, query);
9757 return false;
9758 }
9759 });
9760 }
9761 if ( $.isFunction( found ) ) {
9762 response = found.apply(context, passedArguments);
9763 }
9764 else if(found !== undefined) {
9765 response = found;
9766 }
9767 if(Array.isArray(returnedValue)) {
9768 returnedValue.push(response);
9769 }
9770 else if(returnedValue !== undefined) {
9771 returnedValue = [returnedValue, response];
9772 }
9773 else if(response !== undefined) {
9774 returnedValue = response;
9775 }
9776 return found;
9777 }
9778 };
9779
9780 if(methodInvoked) {
9781 if(instance === undefined) {
9782 module.initialize();
9783 }
9784 module.invoke(query);
9785 }
9786 else {
9787 if(instance !== undefined) {
9788 instance.invoke('destroy');
9789 }
9790 module.initialize();
9791 }
9792 })
9793 ;
9794 return (returnedValue !== undefined)
9795 ? returnedValue
9796 : $allModules
9797 ;
9798};
9799
9800$.fn.dropdown.settings = {
9801
9802 silent : false,
9803 debug : false,
9804 verbose : false,
9805 performance : true,
9806
9807 on : 'click', // what event should show menu action on item selection
9808 action : 'activate', // action on item selection (nothing, activate, select, combo, hide, function(){})
9809
9810 values : false, // specify values to use for dropdown
9811
9812 clearable : false, // whether the value of the dropdown can be cleared
9813
9814 apiSettings : false,
9815 selectOnKeydown : true, // Whether selection should occur automatically when keyboard shortcuts used
9816 minCharacters : 0, // Minimum characters required to trigger API call
9817
9818 filterRemoteData : false, // Whether API results should be filtered after being returned for query term
9819 saveRemoteData : true, // Whether remote name/value pairs should be stored in sessionStorage to allow remote data to be restored on page refresh
9820
9821 throttle : 200, // How long to wait after last user input to search remotely
9822
9823 context : window, // Context to use when determining if on screen
9824 direction : 'auto', // Whether dropdown should always open in one direction
9825 keepOnScreen : true, // Whether dropdown should check whether it is on screen before showing
9826
9827 match : 'both', // what to match against with search selection (both, text, or label)
9828 fullTextSearch : false, // search anywhere in value (set to 'exact' to require exact matches)
9829 ignoreDiacritics : false, // match results also if they contain diacritics of the same base character (for example searching for "a" will also match "á" or "â" or "à", etc...)
9830 hideDividers : false, // Whether to hide any divider elements (specified in selector.divider) that are sibling to any items when searched (set to true will hide all dividers, set to 'empty' will hide them when they are not followed by a visible item)
9831
9832 placeholder : 'auto', // whether to convert blank <select> values to placeholder text
9833 preserveHTML : true, // preserve html when selecting value
9834 sortSelect : false, // sort selection on init
9835
9836 forceSelection : true, // force a choice on blur with search selection
9837
9838 allowAdditions : false, // whether multiple select should allow user added values
9839 ignoreCase : false, // whether to consider values not matching in case to be the same
9840 hideAdditions : true, // whether or not to hide special message prompting a user they can enter a value
9841
9842 maxSelections : false, // When set to a number limits the number of selections to this count
9843 useLabels : true, // whether multiple select should filter currently active selections from choices
9844 delimiter : ',', // when multiselect uses normal <input> the values will be delimited with this character
9845
9846 showOnFocus : true, // show menu on focus
9847 allowReselection : false, // whether current value should trigger callbacks when reselected
9848 allowTab : true, // add tabindex to element
9849 allowCategorySelection : false, // allow elements with sub-menus to be selected
9850
9851 fireOnInit : false, // Whether callbacks should fire when initializing dropdown values
9852
9853 transition : 'auto', // auto transition will slide down or up based on direction
9854 duration : 200, // duration of transition
9855
9856 glyphWidth : 1.037, // widest glyph width in em (W is 1.037 em) used to calculate multiselect input width
9857
9858 // label settings on multi-select
9859 label: {
9860 transition : 'scale',
9861 duration : 200,
9862 variation : false
9863 },
9864
9865 // delay before event
9866 delay : {
9867 hide : 300,
9868 show : 200,
9869 search : 20,
9870 touch : 50
9871 },
9872
9873 /* Callbacks */
9874 onChange : function(value, text, $selected){},
9875 onAdd : function(value, text, $selected){},
9876 onRemove : function(value, text, $selected){},
9877
9878 onLabelSelect : function($selectedLabels){},
9879 onLabelCreate : function(value, text) { return $(this); },
9880 onLabelRemove : function(value) { return true; },
9881 onNoResults : function(searchTerm) { return true; },
9882 onShow : function(){},
9883 onHide : function(){},
9884
9885 /* Component */
9886 name : 'Dropdown',
9887 namespace : 'dropdown',
9888
9889 message: {
9890 addResult : 'Add <b>{term}</b>',
9891 count : '{count} selected',
9892 maxSelections : 'Max {maxCount} selections',
9893 noResults : 'No results found.',
9894 serverError : 'There was an error contacting the server'
9895 },
9896
9897 error : {
9898 action : 'You called a dropdown action that was not defined',
9899 alreadySetup : 'Once a select has been initialized behaviors must be called on the created ui dropdown',
9900 labels : 'Allowing user additions currently requires the use of labels.',
9901 missingMultiple : '<select> requires multiple property to be set to correctly preserve multiple values',
9902 method : 'The method you called is not defined.',
9903 noAPI : 'The API module is required to load resources remotely',
9904 noStorage : 'Saving remote data requires session storage',
9905 noTransition : 'This module requires ui transitions <https://github.com/Semantic-Org/UI-Transition>',
9906 noNormalize : '"ignoreDiacritics" setting will be ignored. Browser does not support String().normalize(). You may consider including <https://cdn.jsdelivr.net/npm/unorm@1.4.1/lib/unorm.min.js> as a polyfill.'
9907 },
9908
9909 regExp : {
9910 escape : /[-[\]{}()*+?.,\\^$|#\s:=@]/g,
9911 quote : /"/g
9912 },
9913
9914 metadata : {
9915 defaultText : 'defaultText',
9916 defaultValue : 'defaultValue',
9917 placeholderText : 'placeholder',
9918 text : 'text',
9919 value : 'value'
9920 },
9921
9922 // property names for remote query
9923 fields: {
9924 remoteValues : 'results', // grouping for api results
9925 values : 'values', // grouping for all dropdown values
9926 disabled : 'disabled', // whether value should be disabled
9927 name : 'name', // displayed dropdown text
9928 value : 'value', // actual dropdown value
9929 text : 'text', // displayed text when selected
9930 type : 'type' // type of dropdown element
9931 },
9932
9933 keys : {
9934 backspace : 8,
9935 delimiter : 188, // comma
9936 deleteKey : 46,
9937 enter : 13,
9938 escape : 27,
9939 pageUp : 33,
9940 pageDown : 34,
9941 leftArrow : 37,
9942 upArrow : 38,
9943 rightArrow : 39,
9944 downArrow : 40
9945 },
9946
9947 selector : {
9948 addition : '.addition',
9949 divider : '.divider, .header',
9950 dropdown : '.ui.dropdown',
9951 hidden : '.hidden',
9952 icon : '> .dropdown.icon',
9953 input : '> input[type="hidden"], > select',
9954 item : '.item',
9955 label : '> .label',
9956 remove : '> .label > .delete.icon',
9957 siblingLabel : '.label',
9958 menu : '.menu',
9959 message : '.message',
9960 menuIcon : '.dropdown.icon',
9961 search : 'input.search, .menu > .search > input, .menu input.search',
9962 sizer : '> input.sizer',
9963 text : '> .text:not(.icon)',
9964 unselectable : '.disabled, .filtered',
9965 clearIcon : '> .remove.icon'
9966 },
9967
9968 className : {
9969 active : 'active',
9970 addition : 'addition',
9971 animating : 'animating',
9972 disabled : 'disabled',
9973 empty : 'empty',
9974 dropdown : 'ui dropdown',
9975 filtered : 'filtered',
9976 hidden : 'hidden transition',
9977 item : 'item',
9978 label : 'ui label',
9979 loading : 'loading',
9980 menu : 'menu',
9981 message : 'message',
9982 multiple : 'multiple',
9983 placeholder : 'default',
9984 sizer : 'sizer',
9985 search : 'search',
9986 selected : 'selected',
9987 selection : 'selection',
9988 upward : 'upward',
9989 leftward : 'left',
9990 visible : 'visible',
9991 clearable : 'clearable',
9992 noselection : 'noselection',
9993 delete : 'delete'
9994 }
9995
9996};
9997
9998/* Templates */
9999$.fn.dropdown.settings.templates = {
10000 escape: function(string, preserveHTML) {
10001 if (preserveHTML){
10002 return string;
10003 }
10004 var
10005 badChars = /[&<>"'`]/g,
10006 shouldEscape = /[&<>"'`]/,
10007 escape = {
10008 "&": "&amp;",
10009 "<": "&lt;",
10010 ">": "&gt;",
10011 '"': "&quot;",
10012 "'": "&#x27;",
10013 "`": "&#x60;"
10014 },
10015 escapedChar = function(chr) {
10016 return escape[chr];
10017 }
10018 ;
10019 if(shouldEscape.test(string)) {
10020 return string.replace(badChars, escapedChar);
10021 }
10022 return string;
10023 },
10024 // generates dropdown from select values
10025 dropdown: function(select, preserveHTML, className) {
10026 var
10027 placeholder = select.placeholder || false,
10028 values = select.values || [],
10029 html = '',
10030 escape = $.fn.dropdown.settings.templates.escape
10031 ;
10032 html += '<i class="dropdown icon"></i>';
10033 if(placeholder) {
10034 html += '<div class="default text">' + escape(placeholder,preserveHTML) + '</div>';
10035 }
10036 else {
10037 html += '<div class="text"></div>';
10038 }
10039 html += '<div class="'+className.menu+'">';
10040 $.each(values, function(index, option) {
10041 html += '<div class="'+(option.disabled ? className.disabled+' ':'')+className.item+'" data-value="' + String(option.value).replace(/"/g,"") + '">' + escape(option.name,preserveHTML) + '</div>';
10042 });
10043 html += '</div>';
10044 return html;
10045 },
10046
10047 // generates just menu from select
10048 menu: function(response, fields, preserveHTML, className) {
10049 var
10050 values = response[fields.values] || [],
10051 html = '',
10052 escape = $.fn.dropdown.settings.templates.escape
10053 ;
10054 $.each(values, function(index, option) {
10055 var
10056 itemType = (option[fields.type])
10057 ? option[fields.type]
10058 : 'item'
10059 ;
10060
10061 if( itemType === 'item' ) {
10062 var
10063 maybeText = (option[fields.text])
10064 ? ' data-text="' + String(option[fields.text]).replace(/"/g,"") + '"'
10065 : '',
10066 maybeDisabled = (option[fields.disabled])
10067 ? className.disabled+' '
10068 : ''
10069 ;
10070 html += '<div class="'+ maybeDisabled + className.item+'" data-value="' + String(option[fields.value]).replace(/"/g,"") + '"' + maybeText + '>';
10071 html += escape(option[fields.name],preserveHTML);
10072 html += '</div>';
10073 } else if (itemType === 'header') {
10074 html += '<div class="header">';
10075 html += escape(option[fields.name],preserveHTML);
10076 html += '</div>';
10077 }
10078 });
10079 return html;
10080 },
10081
10082 // generates label for multiselect
10083 label: function(value, text, preserveHTML, className) {
10084 var
10085 escape = $.fn.dropdown.settings.templates.escape;
10086 return escape(text,preserveHTML) + '<i class="'+className.delete+' icon"></i>';
10087 },
10088
10089
10090 // generates messages like "No results"
10091 message: function(message) {
10092 return message;
10093 },
10094
10095 // generates user addition to selection menu
10096 addition: function(choice) {
10097 return choice;
10098 }
10099
10100};
10101
10102})( jQuery, window, document );
10103
10104/*!
10105 * # Semantic UI 2.7.2 - Embed
10106 * http://github.com/semantic-org/semantic-ui/
10107 *
10108 *
10109 * Released under the MIT license
10110 * http://opensource.org/licenses/MIT
10111 *
10112 */
10113
10114;(function ($, window, document, undefined) {
10115
10116"use strict";
10117
10118$.isFunction = $.isFunction || function(obj) {
10119 return typeof obj === "function" && typeof obj.nodeType !== "number";
10120};
10121
10122window = (typeof window != 'undefined' && window.Math == Math)
10123 ? window
10124 : (typeof self != 'undefined' && self.Math == Math)
10125 ? self
10126 : Function('return this')()
10127;
10128
10129$.fn.embed = function(parameters) {
10130
10131 var
10132 $allModules = $(this),
10133
10134 moduleSelector = $allModules.selector || '',
10135
10136 time = new Date().getTime(),
10137 performance = [],
10138
10139 query = arguments[0],
10140 methodInvoked = (typeof query == 'string'),
10141 queryArguments = [].slice.call(arguments, 1),
10142
10143 returnedValue
10144 ;
10145
10146 $allModules
10147 .each(function() {
10148 var
10149 settings = ( $.isPlainObject(parameters) )
10150 ? $.extend(true, {}, $.fn.embed.settings, parameters)
10151 : $.extend({}, $.fn.embed.settings),
10152
10153 selector = settings.selector,
10154 className = settings.className,
10155 sources = settings.sources,
10156 error = settings.error,
10157 metadata = settings.metadata,
10158 namespace = settings.namespace,
10159 templates = settings.templates,
10160
10161 eventNamespace = '.' + namespace,
10162 moduleNamespace = 'module-' + namespace,
10163
10164 $window = $(window),
10165 $module = $(this),
10166 $placeholder = $module.find(selector.placeholder),
10167 $icon = $module.find(selector.icon),
10168 $embed = $module.find(selector.embed),
10169
10170 element = this,
10171 instance = $module.data(moduleNamespace),
10172 module
10173 ;
10174
10175 module = {
10176
10177 initialize: function() {
10178 module.debug('Initializing embed');
10179 module.determine.autoplay();
10180 module.create();
10181 module.bind.events();
10182 module.instantiate();
10183 },
10184
10185 instantiate: function() {
10186 module.verbose('Storing instance of module', module);
10187 instance = module;
10188 $module
10189 .data(moduleNamespace, module)
10190 ;
10191 },
10192
10193 destroy: function() {
10194 module.verbose('Destroying previous instance of embed');
10195 module.reset();
10196 $module
10197 .removeData(moduleNamespace)
10198 .off(eventNamespace)
10199 ;
10200 },
10201
10202 refresh: function() {
10203 module.verbose('Refreshing selector cache');
10204 $placeholder = $module.find(selector.placeholder);
10205 $icon = $module.find(selector.icon);
10206 $embed = $module.find(selector.embed);
10207 },
10208
10209 bind: {
10210 events: function() {
10211 if( module.has.placeholder() ) {
10212 module.debug('Adding placeholder events');
10213 $module
10214 .on('click' + eventNamespace, selector.placeholder, module.createAndShow)
10215 .on('click' + eventNamespace, selector.icon, module.createAndShow)
10216 ;
10217 }
10218 }
10219 },
10220
10221 create: function() {
10222 var
10223 placeholder = module.get.placeholder()
10224 ;
10225 if(placeholder) {
10226 module.createPlaceholder();
10227 }
10228 else {
10229 module.createAndShow();
10230 }
10231 },
10232
10233 createPlaceholder: function(placeholder) {
10234 var
10235 icon = module.get.icon(),
10236 url = module.get.url(),
10237 embed = module.generate.embed(url)
10238 ;
10239 placeholder = placeholder || module.get.placeholder();
10240 $module.html( templates.placeholder(placeholder, icon) );
10241 module.debug('Creating placeholder for embed', placeholder, icon);
10242 },
10243
10244 createEmbed: function(url) {
10245 module.refresh();
10246 url = url || module.get.url();
10247 $embed = $('<div/>')
10248 .addClass(className.embed)
10249 .html( module.generate.embed(url) )
10250 .appendTo($module)
10251 ;
10252 settings.onCreate.call(element, url);
10253 module.debug('Creating embed object', $embed);
10254 },
10255
10256 changeEmbed: function(url) {
10257 $embed
10258 .html( module.generate.embed(url) )
10259 ;
10260 },
10261
10262 createAndShow: function() {
10263 module.createEmbed();
10264 module.show();
10265 },
10266
10267 // sets new embed
10268 change: function(source, id, url) {
10269 module.debug('Changing video to ', source, id, url);
10270 $module
10271 .data(metadata.source, source)
10272 .data(metadata.id, id)
10273 ;
10274 if(url) {
10275 $module.data(metadata.url, url);
10276 }
10277 else {
10278 $module.removeData(metadata.url);
10279 }
10280 if(module.has.embed()) {
10281 module.changeEmbed();
10282 }
10283 else {
10284 module.create();
10285 }
10286 },
10287
10288 // clears embed
10289 reset: function() {
10290 module.debug('Clearing embed and showing placeholder');
10291 module.remove.data();
10292 module.remove.active();
10293 module.remove.embed();
10294 module.showPlaceholder();
10295 settings.onReset.call(element);
10296 },
10297
10298 // shows current embed
10299 show: function() {
10300 module.debug('Showing embed');
10301 module.set.active();
10302 settings.onDisplay.call(element);
10303 },
10304
10305 hide: function() {
10306 module.debug('Hiding embed');
10307 module.showPlaceholder();
10308 },
10309
10310 showPlaceholder: function() {
10311 module.debug('Showing placeholder image');
10312 module.remove.active();
10313 settings.onPlaceholderDisplay.call(element);
10314 },
10315
10316 get: {
10317 id: function() {
10318 return settings.id || $module.data(metadata.id);
10319 },
10320 placeholder: function() {
10321 return settings.placeholder || $module.data(metadata.placeholder);
10322 },
10323 icon: function() {
10324 return (settings.icon)
10325 ? settings.icon
10326 : ($module.data(metadata.icon) !== undefined)
10327 ? $module.data(metadata.icon)
10328 : module.determine.icon()
10329 ;
10330 },
10331 source: function(url) {
10332 return (settings.source)
10333 ? settings.source
10334 : ($module.data(metadata.source) !== undefined)
10335 ? $module.data(metadata.source)
10336 : module.determine.source()
10337 ;
10338 },
10339 type: function() {
10340 var source = module.get.source();
10341 return (sources[source] !== undefined)
10342 ? sources[source].type
10343 : false
10344 ;
10345 },
10346 url: function() {
10347 return (settings.url)
10348 ? settings.url
10349 : ($module.data(metadata.url) !== undefined)
10350 ? $module.data(metadata.url)
10351 : module.determine.url()
10352 ;
10353 }
10354 },
10355
10356 determine: {
10357 autoplay: function() {
10358 if(module.should.autoplay()) {
10359 settings.autoplay = true;
10360 }
10361 },
10362 source: function(url) {
10363 var
10364 matchedSource = false
10365 ;
10366 url = url || module.get.url();
10367 if(url) {
10368 $.each(sources, function(name, source) {
10369 if(url.search(source.domain) !== -1) {
10370 matchedSource = name;
10371 return false;
10372 }
10373 });
10374 }
10375 return matchedSource;
10376 },
10377 icon: function() {
10378 var
10379 source = module.get.source()
10380 ;
10381 return (sources[source] !== undefined)
10382 ? sources[source].icon
10383 : false
10384 ;
10385 },
10386 url: function() {
10387 var
10388 id = settings.id || $module.data(metadata.id),
10389 source = settings.source || $module.data(metadata.source),
10390 url
10391 ;
10392 url = (sources[source] !== undefined)
10393 ? sources[source].url.replace('{id}', id)
10394 : false
10395 ;
10396 if(url) {
10397 $module.data(metadata.url, url);
10398 }
10399 return url;
10400 }
10401 },
10402
10403
10404 set: {
10405 active: function() {
10406 $module.addClass(className.active);
10407 }
10408 },
10409
10410 remove: {
10411 data: function() {
10412 $module
10413 .removeData(metadata.id)
10414 .removeData(metadata.icon)
10415 .removeData(metadata.placeholder)
10416 .removeData(metadata.source)
10417 .removeData(metadata.url)
10418 ;
10419 },
10420 active: function() {
10421 $module.removeClass(className.active);
10422 },
10423 embed: function() {
10424 $embed.empty();
10425 }
10426 },
10427
10428 encode: {
10429 parameters: function(parameters) {
10430 var
10431 urlString = [],
10432 index
10433 ;
10434 for (index in parameters) {
10435 urlString.push( encodeURIComponent(index) + '=' + encodeURIComponent( parameters[index] ) );
10436 }
10437 return urlString.join('&amp;');
10438 }
10439 },
10440
10441 generate: {
10442 embed: function(url) {
10443 module.debug('Generating embed html');
10444 var
10445 source = module.get.source(),
10446 html,
10447 parameters
10448 ;
10449 url = module.get.url(url);
10450 if(url) {
10451 parameters = module.generate.parameters(source);
10452 html = templates.iframe(url, parameters);
10453 }
10454 else {
10455 module.error(error.noURL, $module);
10456 }
10457 return html;
10458 },
10459 parameters: function(source, extraParameters) {
10460 var
10461 parameters = (sources[source] && sources[source].parameters !== undefined)
10462 ? sources[source].parameters(settings)
10463 : {}
10464 ;
10465 extraParameters = extraParameters || settings.parameters;
10466 if(extraParameters) {
10467 parameters = $.extend({}, parameters, extraParameters);
10468 }
10469 parameters = settings.onEmbed(parameters);
10470 return module.encode.parameters(parameters);
10471 }
10472 },
10473
10474 has: {
10475 embed: function() {
10476 return ($embed.length > 0);
10477 },
10478 placeholder: function() {
10479 return settings.placeholder || $module.data(metadata.placeholder);
10480 }
10481 },
10482
10483 should: {
10484 autoplay: function() {
10485 return (settings.autoplay === 'auto')
10486 ? (settings.placeholder || $module.data(metadata.placeholder) !== undefined)
10487 : settings.autoplay
10488 ;
10489 }
10490 },
10491
10492 is: {
10493 video: function() {
10494 return module.get.type() == 'video';
10495 }
10496 },
10497
10498 setting: function(name, value) {
10499 module.debug('Changing setting', name, value);
10500 if( $.isPlainObject(name) ) {
10501 $.extend(true, settings, name);
10502 }
10503 else if(value !== undefined) {
10504 if($.isPlainObject(settings[name])) {
10505 $.extend(true, settings[name], value);
10506 }
10507 else {
10508 settings[name] = value;
10509 }
10510 }
10511 else {
10512 return settings[name];
10513 }
10514 },
10515 internal: function(name, value) {
10516 if( $.isPlainObject(name) ) {
10517 $.extend(true, module, name);
10518 }
10519 else if(value !== undefined) {
10520 module[name] = value;
10521 }
10522 else {
10523 return module[name];
10524 }
10525 },
10526 debug: function() {
10527 if(!settings.silent && settings.debug) {
10528 if(settings.performance) {
10529 module.performance.log(arguments);
10530 }
10531 else {
10532 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
10533 module.debug.apply(console, arguments);
10534 }
10535 }
10536 },
10537 verbose: function() {
10538 if(!settings.silent && settings.verbose && settings.debug) {
10539 if(settings.performance) {
10540 module.performance.log(arguments);
10541 }
10542 else {
10543 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
10544 module.verbose.apply(console, arguments);
10545 }
10546 }
10547 },
10548 error: function() {
10549 if(!settings.silent) {
10550 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
10551 module.error.apply(console, arguments);
10552 }
10553 },
10554 performance: {
10555 log: function(message) {
10556 var
10557 currentTime,
10558 executionTime,
10559 previousTime
10560 ;
10561 if(settings.performance) {
10562 currentTime = new Date().getTime();
10563 previousTime = time || currentTime;
10564 executionTime = currentTime - previousTime;
10565 time = currentTime;
10566 performance.push({
10567 'Name' : message[0],
10568 'Arguments' : [].slice.call(message, 1) || '',
10569 'Element' : element,
10570 'Execution Time' : executionTime
10571 });
10572 }
10573 clearTimeout(module.performance.timer);
10574 module.performance.timer = setTimeout(module.performance.display, 500);
10575 },
10576 display: function() {
10577 var
10578 title = settings.name + ':',
10579 totalTime = 0
10580 ;
10581 time = false;
10582 clearTimeout(module.performance.timer);
10583 $.each(performance, function(index, data) {
10584 totalTime += data['Execution Time'];
10585 });
10586 title += ' ' + totalTime + 'ms';
10587 if(moduleSelector) {
10588 title += ' \'' + moduleSelector + '\'';
10589 }
10590 if($allModules.length > 1) {
10591 title += ' ' + '(' + $allModules.length + ')';
10592 }
10593 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
10594 console.groupCollapsed(title);
10595 if(console.table) {
10596 console.table(performance);
10597 }
10598 else {
10599 $.each(performance, function(index, data) {
10600 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
10601 });
10602 }
10603 console.groupEnd();
10604 }
10605 performance = [];
10606 }
10607 },
10608 invoke: function(query, passedArguments, context) {
10609 var
10610 object = instance,
10611 maxDepth,
10612 found,
10613 response
10614 ;
10615 passedArguments = passedArguments || queryArguments;
10616 context = element || context;
10617 if(typeof query == 'string' && object !== undefined) {
10618 query = query.split(/[\. ]/);
10619 maxDepth = query.length - 1;
10620 $.each(query, function(depth, value) {
10621 var camelCaseValue = (depth != maxDepth)
10622 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
10623 : query
10624 ;
10625 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
10626 object = object[camelCaseValue];
10627 }
10628 else if( object[camelCaseValue] !== undefined ) {
10629 found = object[camelCaseValue];
10630 return false;
10631 }
10632 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
10633 object = object[value];
10634 }
10635 else if( object[value] !== undefined ) {
10636 found = object[value];
10637 return false;
10638 }
10639 else {
10640 module.error(error.method, query);
10641 return false;
10642 }
10643 });
10644 }
10645 if ( $.isFunction( found ) ) {
10646 response = found.apply(context, passedArguments);
10647 }
10648 else if(found !== undefined) {
10649 response = found;
10650 }
10651 if(Array.isArray(returnedValue)) {
10652 returnedValue.push(response);
10653 }
10654 else if(returnedValue !== undefined) {
10655 returnedValue = [returnedValue, response];
10656 }
10657 else if(response !== undefined) {
10658 returnedValue = response;
10659 }
10660 return found;
10661 }
10662 };
10663
10664 if(methodInvoked) {
10665 if(instance === undefined) {
10666 module.initialize();
10667 }
10668 module.invoke(query);
10669 }
10670 else {
10671 if(instance !== undefined) {
10672 instance.invoke('destroy');
10673 }
10674 module.initialize();
10675 }
10676 })
10677 ;
10678 return (returnedValue !== undefined)
10679 ? returnedValue
10680 : this
10681 ;
10682};
10683
10684$.fn.embed.settings = {
10685
10686 name : 'Embed',
10687 namespace : 'embed',
10688
10689 silent : false,
10690 debug : false,
10691 verbose : false,
10692 performance : true,
10693
10694 icon : false,
10695 source : false,
10696 url : false,
10697 id : false,
10698
10699 // standard video settings
10700 autoplay : 'auto',
10701 color : '#444444',
10702 hd : true,
10703 brandedUI : false,
10704
10705 // additional parameters to include with the embed
10706 parameters: false,
10707
10708 onDisplay : function() {},
10709 onPlaceholderDisplay : function() {},
10710 onReset : function() {},
10711 onCreate : function(url) {},
10712 onEmbed : function(parameters) {
10713 return parameters;
10714 },
10715
10716 metadata : {
10717 id : 'id',
10718 icon : 'icon',
10719 placeholder : 'placeholder',
10720 source : 'source',
10721 url : 'url'
10722 },
10723
10724 error : {
10725 noURL : 'No URL specified',
10726 method : 'The method you called is not defined'
10727 },
10728
10729 className : {
10730 active : 'active',
10731 embed : 'embed'
10732 },
10733
10734 selector : {
10735 embed : '.embed',
10736 placeholder : '.placeholder',
10737 icon : '.icon'
10738 },
10739
10740 sources: {
10741 youtube: {
10742 name : 'youtube',
10743 type : 'video',
10744 icon : 'video play',
10745 domain : 'youtube.com',
10746 url : '//www.youtube.com/embed/{id}',
10747 parameters: function(settings) {
10748 return {
10749 autohide : !settings.brandedUI,
10750 autoplay : settings.autoplay,
10751 color : settings.color || undefined,
10752 hq : settings.hd,
10753 jsapi : settings.api,
10754 modestbranding : !settings.brandedUI
10755 };
10756 }
10757 },
10758 vimeo: {
10759 name : 'vimeo',
10760 type : 'video',
10761 icon : 'video play',
10762 domain : 'vimeo.com',
10763 url : '//player.vimeo.com/video/{id}',
10764 parameters: function(settings) {
10765 return {
10766 api : settings.api,
10767 autoplay : settings.autoplay,
10768 byline : settings.brandedUI,
10769 color : settings.color || undefined,
10770 portrait : settings.brandedUI,
10771 title : settings.brandedUI
10772 };
10773 }
10774 }
10775 },
10776
10777 templates: {
10778 iframe : function(url, parameters) {
10779 var src = url;
10780 if (parameters) {
10781 src += '?' + parameters;
10782 }
10783 return ''
10784 + '<iframe src="' + src + '"'
10785 + ' width="100%" height="100%"'
10786 + ' frameborder="0" scrolling="no" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>'
10787 ;
10788 },
10789 placeholder : function(image, icon) {
10790 var
10791 html = ''
10792 ;
10793 if(icon) {
10794 html += '<i class="' + icon + ' icon"></i>';
10795 }
10796 if(image) {
10797 html += '<img class="placeholder" src="' + image + '">';
10798 }
10799 return html;
10800 }
10801 },
10802
10803 // NOT YET IMPLEMENTED
10804 api : false,
10805 onPause : function() {},
10806 onPlay : function() {},
10807 onStop : function() {}
10808
10809};
10810
10811
10812
10813})( jQuery, window, document );
10814
10815/*!
10816 * # Semantic UI 2.7.2 - Modal
10817 * http://github.com/semantic-org/semantic-ui/
10818 *
10819 *
10820 * Released under the MIT license
10821 * http://opensource.org/licenses/MIT
10822 *
10823 */
10824
10825;(function ($, window, document, undefined) {
10826
10827'use strict';
10828
10829$.isFunction = $.isFunction || function(obj) {
10830 return typeof obj === "function" && typeof obj.nodeType !== "number";
10831};
10832
10833window = (typeof window != 'undefined' && window.Math == Math)
10834 ? window
10835 : (typeof self != 'undefined' && self.Math == Math)
10836 ? self
10837 : Function('return this')()
10838;
10839
10840$.fn.modal = function(parameters) {
10841 var
10842 $allModules = $(this),
10843 $window = $(window),
10844 $document = $(document),
10845 $body = $('body'),
10846
10847 moduleSelector = $allModules.selector || '',
10848
10849 time = new Date().getTime(),
10850 performance = [],
10851
10852 query = arguments[0],
10853 methodInvoked = (typeof query == 'string'),
10854 queryArguments = [].slice.call(arguments, 1),
10855
10856 requestAnimationFrame = window.requestAnimationFrame
10857 || window.mozRequestAnimationFrame
10858 || window.webkitRequestAnimationFrame
10859 || window.msRequestAnimationFrame
10860 || function(callback) { setTimeout(callback, 0); },
10861
10862 returnedValue
10863 ;
10864
10865 $allModules
10866 .each(function() {
10867 var
10868 settings = ( $.isPlainObject(parameters) )
10869 ? $.extend(true, {}, $.fn.modal.settings, parameters)
10870 : $.extend({}, $.fn.modal.settings),
10871
10872 selector = settings.selector,
10873 className = settings.className,
10874 namespace = settings.namespace,
10875 error = settings.error,
10876
10877 eventNamespace = '.' + namespace,
10878 moduleNamespace = 'module-' + namespace,
10879
10880 $module = $(this),
10881 $context = $(settings.context),
10882 $close = $module.find(selector.close),
10883
10884 $allModals,
10885 $otherModals,
10886 $focusedElement,
10887 $dimmable,
10888 $dimmer,
10889
10890 element = this,
10891 instance = $module.data(moduleNamespace),
10892
10893 ignoreRepeatedEvents = false,
10894
10895 initialMouseDownInModal,
10896 initialMouseDownInScrollbar,
10897
10898 elementEventNamespace,
10899 id,
10900 observer,
10901 module
10902 ;
10903 module = {
10904
10905 initialize: function() {
10906 module.verbose('Initializing dimmer', $context);
10907
10908 module.create.id();
10909 module.create.dimmer();
10910
10911 if ( settings.allowMultiple ) {
10912 module.create.innerDimmer();
10913 }
10914
10915 module.refreshModals();
10916
10917 module.bind.events();
10918 if(settings.observeChanges) {
10919 module.observeChanges();
10920 }
10921 module.instantiate();
10922 },
10923
10924 instantiate: function() {
10925 module.verbose('Storing instance of modal');
10926 instance = module;
10927 $module
10928 .data(moduleNamespace, instance)
10929 ;
10930 },
10931
10932 create: {
10933 dimmer: function() {
10934 var
10935 defaultSettings = {
10936 debug : settings.debug,
10937 variation : settings.centered
10938 ? false
10939 : 'top aligned',
10940 dimmerName : 'modals'
10941 },
10942 dimmerSettings = $.extend(true, defaultSettings, settings.dimmerSettings)
10943 ;
10944 if($.fn.dimmer === undefined) {
10945 module.error(error.dimmer);
10946 return;
10947 }
10948 module.debug('Creating dimmer');
10949 $dimmable = $context.dimmer(dimmerSettings);
10950 if(settings.detachable) {
10951 module.verbose('Modal is detachable, moving content into dimmer');
10952 $dimmable.dimmer('add content', $module);
10953 }
10954 else {
10955 module.set.undetached();
10956 }
10957 $dimmer = $dimmable.dimmer('get dimmer');
10958 },
10959 id: function() {
10960 id = (Math.random().toString(16) + '000000000').substr(2, 8);
10961 elementEventNamespace = '.' + id;
10962 module.verbose('Creating unique id for element', id);
10963 },
10964 innerDimmer: function() {
10965 if ( $module.find(selector.dimmer).length == 0 ) {
10966 $module.prepend('<div class="ui inverted dimmer"></div>');
10967 }
10968 }
10969 },
10970
10971 destroy: function() {
10972 module.verbose('Destroying previous modal');
10973 $module
10974 .removeData(moduleNamespace)
10975 .off(eventNamespace)
10976 ;
10977 $window.off(elementEventNamespace);
10978 $dimmer.off(elementEventNamespace);
10979 $close.off(eventNamespace);
10980 $context.dimmer('destroy');
10981 },
10982
10983 observeChanges: function() {
10984 if('MutationObserver' in window) {
10985 observer = new MutationObserver(function(mutations) {
10986 module.debug('DOM tree modified, refreshing');
10987 module.refresh();
10988 });
10989 observer.observe(element, {
10990 childList : true,
10991 subtree : true
10992 });
10993 module.debug('Setting up mutation observer', observer);
10994 }
10995 },
10996
10997 refresh: function() {
10998 module.remove.scrolling();
10999 module.cacheSizes();
11000 if(!module.can.useFlex()) {
11001 module.set.modalOffset();
11002 }
11003 module.set.screenHeight();
11004 module.set.type();
11005 },
11006
11007 refreshModals: function() {
11008 $otherModals = $module.siblings(selector.modal);
11009 $allModals = $otherModals.add($module);
11010 },
11011
11012 attachEvents: function(selector, event) {
11013 var
11014 $toggle = $(selector)
11015 ;
11016 event = $.isFunction(module[event])
11017 ? module[event]
11018 : module.toggle
11019 ;
11020 if($toggle.length > 0) {
11021 module.debug('Attaching modal events to element', selector, event);
11022 $toggle
11023 .off(eventNamespace)
11024 .on('click' + eventNamespace, event)
11025 ;
11026 }
11027 else {
11028 module.error(error.notFound, selector);
11029 }
11030 },
11031
11032 bind: {
11033 events: function() {
11034 module.verbose('Attaching events');
11035 $module
11036 .on('click' + eventNamespace, selector.close, module.event.close)
11037 .on('click' + eventNamespace, selector.approve, module.event.approve)
11038 .on('click' + eventNamespace, selector.deny, module.event.deny)
11039 ;
11040 $window
11041 .on('resize' + elementEventNamespace, module.event.resize)
11042 ;
11043 },
11044 scrollLock: function() {
11045 // touch events default to passive, due to changes in chrome to optimize mobile perf
11046 $dimmable.get(0).addEventListener('touchmove', module.event.preventScroll, { passive: false });
11047 }
11048 },
11049
11050 unbind: {
11051 scrollLock: function() {
11052 $dimmable.get(0).removeEventListener('touchmove', module.event.preventScroll, { passive: false });
11053 }
11054 },
11055
11056 get: {
11057 id: function() {
11058 return (Math.random().toString(16) + '000000000').substr(2, 8);
11059 }
11060 },
11061
11062 event: {
11063 approve: function() {
11064 if(ignoreRepeatedEvents || settings.onApprove.call(element, $(this)) === false) {
11065 module.verbose('Approve callback returned false cancelling hide');
11066 return;
11067 }
11068 ignoreRepeatedEvents = true;
11069 module.hide(function() {
11070 ignoreRepeatedEvents = false;
11071 });
11072 },
11073 preventScroll: function(event) {
11074 if(event.target.className.indexOf('dimmer') !== -1) {
11075 event.preventDefault();
11076 }
11077 },
11078 deny: function() {
11079 if(ignoreRepeatedEvents || settings.onDeny.call(element, $(this)) === false) {
11080 module.verbose('Deny callback returned false cancelling hide');
11081 return;
11082 }
11083 ignoreRepeatedEvents = true;
11084 module.hide(function() {
11085 ignoreRepeatedEvents = false;
11086 });
11087 },
11088 close: function() {
11089 module.hide();
11090 },
11091 mousedown: function(event) {
11092 var
11093 $target = $(event.target)
11094 ;
11095 initialMouseDownInModal = ($target.closest(selector.modal).length > 0);
11096 if(initialMouseDownInModal) {
11097 module.verbose('Mouse down event registered inside the modal');
11098 }
11099 initialMouseDownInScrollbar = module.is.scrolling() && $(window).outerWidth() - settings.scrollbarWidth <= event.clientX;
11100 if(initialMouseDownInScrollbar) {
11101 module.verbose('Mouse down event registered inside the scrollbar');
11102 }
11103 },
11104 mouseup: function(event) {
11105 if(!settings.closable) {
11106 module.verbose('Dimmer clicked but closable setting is disabled');
11107 return;
11108 }
11109 if(initialMouseDownInModal) {
11110 module.debug('Dimmer clicked but mouse down was initially registered inside the modal');
11111 return;
11112 }
11113 if(initialMouseDownInScrollbar){
11114 module.debug('Dimmer clicked but mouse down was initially registered inside the scrollbar');
11115 return;
11116 }
11117 var
11118 $target = $(event.target),
11119 isInModal = ($target.closest(selector.modal).length > 0),
11120 isInDOM = $.contains(document.documentElement, event.target)
11121 ;
11122 if(!isInModal && isInDOM && module.is.active() && $module.hasClass(className.top) ) {
11123 module.debug('Dimmer clicked, hiding all modals');
11124 if(settings.allowMultiple) {
11125 if(!module.hideAll()) {
11126 return;
11127 }
11128 }
11129 else if(!module.hide()){
11130 return;
11131 }
11132 module.remove.clickaway();
11133 }
11134 },
11135 debounce: function(method, delay) {
11136 clearTimeout(module.timer);
11137 module.timer = setTimeout(method, delay);
11138 },
11139 keyboard: function(event) {
11140 var
11141 keyCode = event.which,
11142 escapeKey = 27
11143 ;
11144 if(keyCode == escapeKey) {
11145 if(settings.closable) {
11146 module.debug('Escape key pressed hiding modal');
11147 if ( $module.hasClass(className.top) ) {
11148 module.hide();
11149 }
11150 }
11151 else {
11152 module.debug('Escape key pressed, but closable is set to false');
11153 }
11154 event.preventDefault();
11155 }
11156 },
11157 resize: function() {
11158 if( $dimmable.dimmer('is active') && ( module.is.animating() || module.is.active() ) ) {
11159 requestAnimationFrame(module.refresh);
11160 }
11161 }
11162 },
11163
11164 toggle: function() {
11165 if( module.is.active() || module.is.animating() ) {
11166 module.hide();
11167 }
11168 else {
11169 module.show();
11170 }
11171 },
11172
11173 show: function(callback) {
11174 callback = $.isFunction(callback)
11175 ? callback
11176 : function(){}
11177 ;
11178 module.refreshModals();
11179 module.set.dimmerSettings();
11180 module.set.dimmerStyles();
11181
11182 module.showModal(callback);
11183 },
11184
11185 hide: function(callback) {
11186 callback = $.isFunction(callback)
11187 ? callback
11188 : function(){}
11189 ;
11190 module.refreshModals();
11191 return module.hideModal(callback);
11192 },
11193
11194 showModal: function(callback) {
11195 callback = $.isFunction(callback)
11196 ? callback
11197 : function(){}
11198 ;
11199 if( module.is.animating() || !module.is.active() ) {
11200 module.showDimmer();
11201 module.cacheSizes();
11202 if(module.can.useFlex()) {
11203 module.remove.legacy();
11204 }
11205 else {
11206 module.set.legacy();
11207 module.set.modalOffset();
11208 module.debug('Using non-flex legacy modal positioning.');
11209 }
11210 module.set.screenHeight();
11211 module.set.type();
11212 module.set.clickaway();
11213
11214 if( !settings.allowMultiple && module.others.active() ) {
11215 module.hideOthers(module.showModal);
11216 }
11217 else {
11218 if( settings.allowMultiple ) {
11219 if ( module.others.active() ) {
11220 $otherModals.filter('.' + className.active).find(selector.dimmer).addClass('active');
11221 }
11222
11223 if ( settings.detachable ) {
11224 $module.detach().appendTo($dimmer);
11225 }
11226 }
11227 settings.onShow.call(element);
11228 if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
11229 module.debug('Showing modal with css animations');
11230 $module
11231 .transition({
11232 debug : settings.debug,
11233 animation : settings.transition + ' in',
11234 queue : settings.queue,
11235 duration : settings.duration,
11236 useFailSafe : true,
11237 onComplete : function() {
11238 settings.onVisible.apply(element);
11239 if(settings.keyboardShortcuts) {
11240 module.add.keyboardShortcuts();
11241 }
11242 module.save.focus();
11243 module.set.active();
11244 if(settings.autofocus) {
11245 module.set.autofocus();
11246 }
11247 callback();
11248 }
11249 })
11250 ;
11251 }
11252 else {
11253 module.error(error.noTransition);
11254 }
11255 }
11256 }
11257 else {
11258 module.debug('Modal is already visible');
11259 }
11260 },
11261
11262 hideModal: function(callback, keepDimmed, hideOthersToo) {
11263 var
11264 $previousModal = $otherModals.filter('.' + className.active).last()
11265 ;
11266 callback = $.isFunction(callback)
11267 ? callback
11268 : function(){}
11269 ;
11270 module.debug('Hiding modal');
11271 if(settings.onHide.call(element, $(this)) === false) {
11272 module.verbose('Hide callback returned false cancelling hide');
11273 ignoreRepeatedEvents = false;
11274 return false;
11275 }
11276
11277 if( module.is.animating() || module.is.active() ) {
11278 if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
11279 module.remove.active();
11280 $module
11281 .transition({
11282 debug : settings.debug,
11283 animation : settings.transition + ' out',
11284 queue : settings.queue,
11285 duration : settings.duration,
11286 useFailSafe : true,
11287 onStart : function() {
11288 if(!module.others.active() && !keepDimmed) {
11289 module.hideDimmer();
11290 }
11291 if( settings.keyboardShortcuts && !module.others.active() ) {
11292 module.remove.keyboardShortcuts();
11293 }
11294 },
11295 onComplete : function() {
11296 module.unbind.scrollLock();
11297 if ( settings.allowMultiple ) {
11298 $previousModal.addClass(className.top);
11299 $module.removeClass(className.top);
11300
11301 if ( hideOthersToo ) {
11302 $allModals.find(selector.dimmer).removeClass('active');
11303 }
11304 else {
11305 $previousModal.find(selector.dimmer).removeClass('active');
11306 }
11307 }
11308 settings.onHidden.call(element);
11309 module.remove.dimmerStyles();
11310 module.restore.focus();
11311 callback();
11312 }
11313 })
11314 ;
11315 }
11316 else {
11317 module.error(error.noTransition);
11318 }
11319 }
11320 },
11321
11322 showDimmer: function() {
11323 if($dimmable.dimmer('is animating') || !$dimmable.dimmer('is active') ) {
11324 module.debug('Showing dimmer');
11325 $dimmable.dimmer('show');
11326 }
11327 else {
11328 module.debug('Dimmer already visible');
11329 }
11330 },
11331
11332 hideDimmer: function() {
11333 if( $dimmable.dimmer('is animating') || ($dimmable.dimmer('is active')) ) {
11334 module.unbind.scrollLock();
11335 $dimmable.dimmer('hide', function() {
11336 module.remove.clickaway();
11337 module.remove.screenHeight();
11338 });
11339 }
11340 else {
11341 module.debug('Dimmer is not visible cannot hide');
11342 return;
11343 }
11344 },
11345
11346 hideAll: function(callback) {
11347 var
11348 $visibleModals = $allModals.filter('.' + className.active + ', .' + className.animating)
11349 ;
11350 callback = $.isFunction(callback)
11351 ? callback
11352 : function(){}
11353 ;
11354 if( $visibleModals.length > 0 ) {
11355 module.debug('Hiding all visible modals');
11356 var hideOk = true;
11357//check in reverse order trying to hide most top displayed modal first
11358 $($visibleModals.get().reverse()).each(function(index,element){
11359 if(hideOk){
11360 hideOk = $(element).modal('hide modal', callback, false, true);
11361 }
11362 });
11363 if(hideOk) {
11364 module.hideDimmer();
11365 }
11366 return hideOk;
11367 }
11368 },
11369
11370 hideOthers: function(callback) {
11371 var
11372 $visibleModals = $otherModals.filter('.' + className.active + ', .' + className.animating)
11373 ;
11374 callback = $.isFunction(callback)
11375 ? callback
11376 : function(){}
11377 ;
11378 if( $visibleModals.length > 0 ) {
11379 module.debug('Hiding other modals', $otherModals);
11380 $visibleModals
11381 .modal('hide modal', callback, true)
11382 ;
11383 }
11384 },
11385
11386 others: {
11387 active: function() {
11388 return ($otherModals.filter('.' + className.active).length > 0);
11389 },
11390 animating: function() {
11391 return ($otherModals.filter('.' + className.animating).length > 0);
11392 }
11393 },
11394
11395
11396 add: {
11397 keyboardShortcuts: function() {
11398 module.verbose('Adding keyboard shortcuts');
11399 $document
11400 .on('keyup' + eventNamespace, module.event.keyboard)
11401 ;
11402 }
11403 },
11404
11405 save: {
11406 focus: function() {
11407 var
11408 $activeElement = $(document.activeElement),
11409 inCurrentModal = $activeElement.closest($module).length > 0
11410 ;
11411 if(!inCurrentModal) {
11412 $focusedElement = $(document.activeElement).blur();
11413 }
11414 }
11415 },
11416
11417 restore: {
11418 focus: function() {
11419 if($focusedElement && $focusedElement.length > 0 && settings.restoreFocus) {
11420 $focusedElement.focus();
11421 }
11422 }
11423 },
11424
11425 remove: {
11426 active: function() {
11427 $module.removeClass(className.active);
11428 },
11429 legacy: function() {
11430 $module.removeClass(className.legacy);
11431 },
11432 clickaway: function() {
11433 $dimmer
11434 .off('mousedown' + elementEventNamespace)
11435 ;
11436 $dimmer
11437 .off('mouseup' + elementEventNamespace)
11438 ;
11439 },
11440 dimmerStyles: function() {
11441 $dimmer.removeClass(className.inverted);
11442 $dimmable.removeClass(className.blurring);
11443 },
11444 bodyStyle: function() {
11445 if($body.attr('style') === '') {
11446 module.verbose('Removing style attribute');
11447 $body.removeAttr('style');
11448 }
11449 },
11450 screenHeight: function() {
11451 module.debug('Removing page height');
11452 $body
11453 .css('height', '')
11454 ;
11455 },
11456 keyboardShortcuts: function() {
11457 module.verbose('Removing keyboard shortcuts');
11458 $document
11459 .off('keyup' + eventNamespace)
11460 ;
11461 },
11462 scrolling: function() {
11463 $dimmable.removeClass(className.scrolling);
11464 $module.removeClass(className.scrolling);
11465 }
11466 },
11467
11468 cacheSizes: function() {
11469 $module.addClass(className.loading);
11470 var
11471 scrollHeight = $module.prop('scrollHeight'),
11472 modalWidth = $module.outerWidth(),
11473 modalHeight = $module.outerHeight()
11474 ;
11475 if(module.cache === undefined || modalHeight !== 0) {
11476 module.cache = {
11477 pageHeight : $(document).outerHeight(),
11478 width : modalWidth,
11479 height : modalHeight + settings.offset,
11480 scrollHeight : scrollHeight + settings.offset,
11481 contextHeight : (settings.context == 'body')
11482 ? $(window).height()
11483 : $dimmable.height(),
11484 };
11485 module.cache.topOffset = -(module.cache.height / 2);
11486 }
11487 $module.removeClass(className.loading);
11488 module.debug('Caching modal and container sizes', module.cache);
11489 },
11490
11491 can: {
11492 useFlex: function() {
11493 return (settings.useFlex == 'auto')
11494 ? settings.detachable && !module.is.ie()
11495 : settings.useFlex
11496 ;
11497 },
11498 fit: function() {
11499 var
11500 contextHeight = module.cache.contextHeight,
11501 verticalCenter = module.cache.contextHeight / 2,
11502 topOffset = module.cache.topOffset,
11503 scrollHeight = module.cache.scrollHeight,
11504 height = module.cache.height,
11505 paddingHeight = settings.padding,
11506 startPosition = (verticalCenter + topOffset)
11507 ;
11508 return (scrollHeight > height)
11509 ? (startPosition + scrollHeight + paddingHeight < contextHeight)
11510 : (height + (paddingHeight * 2) < contextHeight)
11511 ;
11512 }
11513 },
11514
11515 is: {
11516 active: function() {
11517 return $module.hasClass(className.active);
11518 },
11519 ie: function() {
11520 var
11521 isIE11 = (!(window.ActiveXObject) && 'ActiveXObject' in window),
11522 isIE = ('ActiveXObject' in window)
11523 ;
11524 return (isIE11 || isIE);
11525 },
11526 animating: function() {
11527 return $module.transition('is supported')
11528 ? $module.transition('is animating')
11529 : $module.is(':visible')
11530 ;
11531 },
11532 scrolling: function() {
11533 return $dimmable.hasClass(className.scrolling);
11534 },
11535 modernBrowser: function() {
11536 // appName for IE11 reports 'Netscape' can no longer use
11537 return !(window.ActiveXObject || 'ActiveXObject' in window);
11538 }
11539 },
11540
11541 set: {
11542 autofocus: function() {
11543 var
11544 $inputs = $module.find('[tabindex], :input').filter(':visible'),
11545 $autofocus = $inputs.filter('[autofocus]'),
11546 $input = ($autofocus.length > 0)
11547 ? $autofocus.first()
11548 : $inputs.first()
11549 ;
11550 if($input.length > 0) {
11551 $input.focus();
11552 }
11553 },
11554 clickaway: function() {
11555 $dimmer
11556 .on('mousedown' + elementEventNamespace, module.event.mousedown)
11557 ;
11558 $dimmer
11559 .on('mouseup' + elementEventNamespace, module.event.mouseup)
11560 ;
11561 },
11562 dimmerSettings: function() {
11563 if($.fn.dimmer === undefined) {
11564 module.error(error.dimmer);
11565 return;
11566 }
11567 var
11568 defaultSettings = {
11569 debug : settings.debug,
11570 dimmerName : 'modals',
11571 closable : 'auto',
11572 useFlex : module.can.useFlex(),
11573 variation : settings.centered
11574 ? false
11575 : 'top aligned',
11576 duration : {
11577 show : settings.duration,
11578 hide : settings.duration
11579 }
11580 },
11581 dimmerSettings = $.extend(true, defaultSettings, settings.dimmerSettings)
11582 ;
11583 if(settings.inverted) {
11584 dimmerSettings.variation = (dimmerSettings.variation !== undefined)
11585 ? dimmerSettings.variation + ' inverted'
11586 : 'inverted'
11587 ;
11588 }
11589 $context.dimmer('setting', dimmerSettings);
11590 },
11591 dimmerStyles: function() {
11592 if(settings.inverted) {
11593 $dimmer.addClass(className.inverted);
11594 }
11595 else {
11596 $dimmer.removeClass(className.inverted);
11597 }
11598 if(settings.blurring) {
11599 $dimmable.addClass(className.blurring);
11600 }
11601 else {
11602 $dimmable.removeClass(className.blurring);
11603 }
11604 },
11605 modalOffset: function() {
11606 var
11607 width = module.cache.width,
11608 height = module.cache.height
11609 ;
11610 $module
11611 .css({
11612 marginTop: (settings.centered && module.can.fit())
11613 ? -(height / 2)
11614 : 0,
11615 marginLeft: -(width / 2)
11616 })
11617 ;
11618 module.verbose('Setting modal offset for legacy mode');
11619 },
11620 screenHeight: function() {
11621 if( module.can.fit() ) {
11622 $body.css('height', '');
11623 }
11624 else {
11625 module.debug('Modal is taller than page content, resizing page height');
11626 $body
11627 .css('height', module.cache.height + (settings.padding * 2) )
11628 ;
11629 }
11630 },
11631 active: function() {
11632 $module.addClass(className.active + ' ' + className.top);
11633 $otherModals.filter('.' + className.active).removeClass(className.top);
11634 },
11635 scrolling: function() {
11636 $dimmable.addClass(className.scrolling);
11637 $module.addClass(className.scrolling);
11638 module.unbind.scrollLock();
11639 },
11640 legacy: function() {
11641 $module.addClass(className.legacy);
11642 },
11643 type: function() {
11644 if(module.can.fit()) {
11645 module.verbose('Modal fits on screen');
11646 if(!module.others.active() && !module.others.animating()) {
11647 module.remove.scrolling();
11648 module.bind.scrollLock();
11649 }
11650 }
11651 else {
11652 module.verbose('Modal cannot fit on screen setting to scrolling');
11653 module.set.scrolling();
11654 }
11655 },
11656 undetached: function() {
11657 $dimmable.addClass(className.undetached);
11658 }
11659 },
11660
11661 setting: function(name, value) {
11662 module.debug('Changing setting', name, value);
11663 if( $.isPlainObject(name) ) {
11664 $.extend(true, settings, name);
11665 }
11666 else if(value !== undefined) {
11667 if($.isPlainObject(settings[name])) {
11668 $.extend(true, settings[name], value);
11669 }
11670 else {
11671 settings[name] = value;
11672 }
11673 }
11674 else {
11675 return settings[name];
11676 }
11677 },
11678 internal: function(name, value) {
11679 if( $.isPlainObject(name) ) {
11680 $.extend(true, module, name);
11681 }
11682 else if(value !== undefined) {
11683 module[name] = value;
11684 }
11685 else {
11686 return module[name];
11687 }
11688 },
11689 debug: function() {
11690 if(!settings.silent && settings.debug) {
11691 if(settings.performance) {
11692 module.performance.log(arguments);
11693 }
11694 else {
11695 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
11696 module.debug.apply(console, arguments);
11697 }
11698 }
11699 },
11700 verbose: function() {
11701 if(!settings.silent && settings.verbose && settings.debug) {
11702 if(settings.performance) {
11703 module.performance.log(arguments);
11704 }
11705 else {
11706 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
11707 module.verbose.apply(console, arguments);
11708 }
11709 }
11710 },
11711 error: function() {
11712 if(!settings.silent) {
11713 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
11714 module.error.apply(console, arguments);
11715 }
11716 },
11717 performance: {
11718 log: function(message) {
11719 var
11720 currentTime,
11721 executionTime,
11722 previousTime
11723 ;
11724 if(settings.performance) {
11725 currentTime = new Date().getTime();
11726 previousTime = time || currentTime;
11727 executionTime = currentTime - previousTime;
11728 time = currentTime;
11729 performance.push({
11730 'Name' : message[0],
11731 'Arguments' : [].slice.call(message, 1) || '',
11732 'Element' : element,
11733 'Execution Time' : executionTime
11734 });
11735 }
11736 clearTimeout(module.performance.timer);
11737 module.performance.timer = setTimeout(module.performance.display, 500);
11738 },
11739 display: function() {
11740 var
11741 title = settings.name + ':',
11742 totalTime = 0
11743 ;
11744 time = false;
11745 clearTimeout(module.performance.timer);
11746 $.each(performance, function(index, data) {
11747 totalTime += data['Execution Time'];
11748 });
11749 title += ' ' + totalTime + 'ms';
11750 if(moduleSelector) {
11751 title += ' \'' + moduleSelector + '\'';
11752 }
11753 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
11754 console.groupCollapsed(title);
11755 if(console.table) {
11756 console.table(performance);
11757 }
11758 else {
11759 $.each(performance, function(index, data) {
11760 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
11761 });
11762 }
11763 console.groupEnd();
11764 }
11765 performance = [];
11766 }
11767 },
11768 invoke: function(query, passedArguments, context) {
11769 var
11770 object = instance,
11771 maxDepth,
11772 found,
11773 response
11774 ;
11775 passedArguments = passedArguments || queryArguments;
11776 context = element || context;
11777 if(typeof query == 'string' && object !== undefined) {
11778 query = query.split(/[\. ]/);
11779 maxDepth = query.length - 1;
11780 $.each(query, function(depth, value) {
11781 var camelCaseValue = (depth != maxDepth)
11782 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
11783 : query
11784 ;
11785 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
11786 object = object[camelCaseValue];
11787 }
11788 else if( object[camelCaseValue] !== undefined ) {
11789 found = object[camelCaseValue];
11790 return false;
11791 }
11792 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
11793 object = object[value];
11794 }
11795 else if( object[value] !== undefined ) {
11796 found = object[value];
11797 return false;
11798 }
11799 else {
11800 return false;
11801 }
11802 });
11803 }
11804 if ( $.isFunction( found ) ) {
11805 response = found.apply(context, passedArguments);
11806 }
11807 else if(found !== undefined) {
11808 response = found;
11809 }
11810 if(Array.isArray(returnedValue)) {
11811 returnedValue.push(response);
11812 }
11813 else if(returnedValue !== undefined) {
11814 returnedValue = [returnedValue, response];
11815 }
11816 else if(response !== undefined) {
11817 returnedValue = response;
11818 }
11819 return found;
11820 }
11821 };
11822
11823 if(methodInvoked) {
11824 if(instance === undefined) {
11825 module.initialize();
11826 }
11827 module.invoke(query);
11828 }
11829 else {
11830 if(instance !== undefined) {
11831 instance.invoke('destroy');
11832 }
11833 module.initialize();
11834 }
11835 })
11836 ;
11837
11838 return (returnedValue !== undefined)
11839 ? returnedValue
11840 : this
11841 ;
11842};
11843
11844$.fn.modal.settings = {
11845
11846 name : 'Modal',
11847 namespace : 'modal',
11848
11849 useFlex : 'auto',
11850 offset : 0,
11851
11852 silent : false,
11853 debug : false,
11854 verbose : false,
11855 performance : true,
11856
11857 observeChanges : false,
11858
11859 allowMultiple : false,
11860 detachable : true,
11861 closable : true,
11862 autofocus : true,
11863 restoreFocus : true,
11864
11865 inverted : false,
11866 blurring : false,
11867
11868 centered : true,
11869
11870 dimmerSettings : {
11871 closable : false,
11872 useCSS : true
11873 },
11874
11875 // whether to use keyboard shortcuts
11876 keyboardShortcuts: true,
11877
11878 context : 'body',
11879
11880 queue : false,
11881 duration : 500,
11882 transition : 'scale',
11883
11884 // padding with edge of page
11885 padding : 50,
11886 scrollbarWidth: 10,
11887
11888 // called before show animation
11889 onShow : function(){},
11890
11891 // called after show animation
11892 onVisible : function(){},
11893
11894 // called before hide animation
11895 onHide : function(){ return true; },
11896
11897 // called after hide animation
11898 onHidden : function(){},
11899
11900 // called after approve selector match
11901 onApprove : function(){ return true; },
11902
11903 // called after deny selector match
11904 onDeny : function(){ return true; },
11905
11906 selector : {
11907 close : '> .close',
11908 approve : '.actions .positive, .actions .approve, .actions .ok',
11909 deny : '.actions .negative, .actions .deny, .actions .cancel',
11910 modal : '.ui.modal',
11911 dimmer : '> .ui.dimmer'
11912 },
11913 error : {
11914 dimmer : 'UI Dimmer, a required component is not included in this page',
11915 method : 'The method you called is not defined.',
11916 notFound : 'The element you specified could not be found'
11917 },
11918 className : {
11919 active : 'active',
11920 animating : 'animating',
11921 blurring : 'blurring',
11922 inverted : 'inverted',
11923 legacy : 'legacy',
11924 loading : 'loading',
11925 scrolling : 'scrolling',
11926 undetached : 'undetached',
11927 top : 'top'
11928 }
11929};
11930
11931
11932})( jQuery, window, document );
11933
11934/*!
11935 * # Semantic UI 2.7.2 - Nag
11936 * http://github.com/semantic-org/semantic-ui/
11937 *
11938 *
11939 * Released under the MIT license
11940 * http://opensource.org/licenses/MIT
11941 *
11942 */
11943
11944;(function ($, window, document, undefined) {
11945
11946'use strict';
11947
11948$.isFunction = $.isFunction || function(obj) {
11949 return typeof obj === "function" && typeof obj.nodeType !== "number";
11950};
11951
11952window = (typeof window != 'undefined' && window.Math == Math)
11953 ? window
11954 : (typeof self != 'undefined' && self.Math == Math)
11955 ? self
11956 : Function('return this')()
11957;
11958
11959$.fn.nag = function(parameters) {
11960 var
11961 $allModules = $(this),
11962 moduleSelector = $allModules.selector || '',
11963
11964 time = new Date().getTime(),
11965 performance = [],
11966
11967 query = arguments[0],
11968 methodInvoked = (typeof query == 'string'),
11969 queryArguments = [].slice.call(arguments, 1),
11970 returnedValue
11971 ;
11972 $allModules
11973 .each(function() {
11974 var
11975 settings = ( $.isPlainObject(parameters) )
11976 ? $.extend(true, {}, $.fn.nag.settings, parameters)
11977 : $.extend({}, $.fn.nag.settings),
11978
11979 className = settings.className,
11980 selector = settings.selector,
11981 error = settings.error,
11982 namespace = settings.namespace,
11983
11984 eventNamespace = '.' + namespace,
11985 moduleNamespace = namespace + '-module',
11986
11987 $module = $(this),
11988
11989 $close = $module.find(selector.close),
11990 $context = (settings.context)
11991 ? $(settings.context)
11992 : $('body'),
11993
11994 element = this,
11995 instance = $module.data(moduleNamespace),
11996
11997 moduleOffset,
11998 moduleHeight,
11999
12000 contextWidth,
12001 contextHeight,
12002 contextOffset,
12003
12004 yOffset,
12005 yPosition,
12006
12007 timer,
12008 module,
12009
12010 requestAnimationFrame = window.requestAnimationFrame
12011 || window.mozRequestAnimationFrame
12012 || window.webkitRequestAnimationFrame
12013 || window.msRequestAnimationFrame
12014 || function(callback) { setTimeout(callback, 0); }
12015 ;
12016 module = {
12017
12018 initialize: function() {
12019 module.verbose('Initializing element');
12020
12021 $module
12022 .on('click' + eventNamespace, selector.close, module.dismiss)
12023 .data(moduleNamespace, module)
12024 ;
12025
12026 if(settings.detachable && $module.parent()[0] !== $context[0]) {
12027 $module
12028 .detach()
12029 .prependTo($context)
12030 ;
12031 }
12032
12033 if(settings.displayTime > 0) {
12034 setTimeout(module.hide, settings.displayTime);
12035 }
12036 module.show();
12037 },
12038
12039 destroy: function() {
12040 module.verbose('Destroying instance');
12041 $module
12042 .removeData(moduleNamespace)
12043 .off(eventNamespace)
12044 ;
12045 },
12046
12047 show: function() {
12048 if( module.should.show() && !$module.is(':visible') ) {
12049 module.debug('Showing nag', settings.animation.show);
12050 if(settings.animation.show == 'fade') {
12051 $module
12052 .fadeIn(settings.duration, settings.easing)
12053 ;
12054 }
12055 else {
12056 $module
12057 .slideDown(settings.duration, settings.easing)
12058 ;
12059 }
12060 }
12061 },
12062
12063 hide: function() {
12064 module.debug('Showing nag', settings.animation.hide);
12065 if(settings.animation.show == 'fade') {
12066 $module
12067 .fadeIn(settings.duration, settings.easing)
12068 ;
12069 }
12070 else {
12071 $module
12072 .slideUp(settings.duration, settings.easing)
12073 ;
12074 }
12075 },
12076
12077 onHide: function() {
12078 module.debug('Removing nag', settings.animation.hide);
12079 $module.remove();
12080 if (settings.onHide) {
12081 settings.onHide();
12082 }
12083 },
12084
12085 dismiss: function(event) {
12086 if(settings.storageMethod) {
12087 module.storage.set(settings.key, settings.value);
12088 }
12089 module.hide();
12090 event.stopImmediatePropagation();
12091 event.preventDefault();
12092 },
12093
12094 should: {
12095 show: function() {
12096 if(settings.persist) {
12097 module.debug('Persistent nag is set, can show nag');
12098 return true;
12099 }
12100 if( module.storage.get(settings.key) != settings.value.toString() ) {
12101 module.debug('Stored value is not set, can show nag', module.storage.get(settings.key));
12102 return true;
12103 }
12104 module.debug('Stored value is set, cannot show nag', module.storage.get(settings.key));
12105 return false;
12106 }
12107 },
12108
12109 get: {
12110 storageOptions: function() {
12111 var
12112 options = {}
12113 ;
12114 if(settings.expires) {
12115 options.expires = settings.expires;
12116 }
12117 if(settings.domain) {
12118 options.domain = settings.domain;
12119 }
12120 if(settings.path) {
12121 options.path = settings.path;
12122 }
12123 return options;
12124 }
12125 },
12126
12127 clear: function() {
12128 module.storage.remove(settings.key);
12129 },
12130
12131 storage: {
12132 set: function(key, value) {
12133 var
12134 options = module.get.storageOptions()
12135 ;
12136 if(settings.storageMethod == 'localstorage' && window.localStorage !== undefined) {
12137 window.localStorage.setItem(key, value);
12138 module.debug('Value stored using local storage', key, value);
12139 }
12140 else if(settings.storageMethod == 'sessionstorage' && window.sessionStorage !== undefined) {
12141 window.sessionStorage.setItem(key, value);
12142 module.debug('Value stored using session storage', key, value);
12143 }
12144 else if($.cookie !== undefined) {
12145 $.cookie(key, value, options);
12146 module.debug('Value stored using cookie', key, value, options);
12147 }
12148 else {
12149 module.error(error.noCookieStorage);
12150 return;
12151 }
12152 },
12153 get: function(key, value) {
12154 var
12155 storedValue
12156 ;
12157 if(settings.storageMethod == 'localstorage' && window.localStorage !== undefined) {
12158 storedValue = window.localStorage.getItem(key);
12159 }
12160 else if(settings.storageMethod == 'sessionstorage' && window.sessionStorage !== undefined) {
12161 storedValue = window.sessionStorage.getItem(key);
12162 }
12163 // get by cookie
12164 else if($.cookie !== undefined) {
12165 storedValue = $.cookie(key);
12166 }
12167 else {
12168 module.error(error.noCookieStorage);
12169 }
12170 if(storedValue == 'undefined' || storedValue == 'null' || storedValue === undefined || storedValue === null) {
12171 storedValue = undefined;
12172 }
12173 return storedValue;
12174 },
12175 remove: function(key) {
12176 var
12177 options = module.get.storageOptions()
12178 ;
12179 if(settings.storageMethod == 'localstorage' && window.localStorage !== undefined) {
12180 window.localStorage.removeItem(key);
12181 }
12182 else if(settings.storageMethod == 'sessionstorage' && window.sessionStorage !== undefined) {
12183 window.sessionStorage.removeItem(key);
12184 }
12185 // store by cookie
12186 else if($.cookie !== undefined) {
12187 $.removeCookie(key, options);
12188 }
12189 else {
12190 module.error(error.noStorage);
12191 }
12192 }
12193 },
12194
12195 setting: function(name, value) {
12196 module.debug('Changing setting', name, value);
12197 if( $.isPlainObject(name) ) {
12198 $.extend(true, settings, name);
12199 }
12200 else if(value !== undefined) {
12201 if($.isPlainObject(settings[name])) {
12202 $.extend(true, settings[name], value);
12203 }
12204 else {
12205 settings[name] = value;
12206 }
12207 }
12208 else {
12209 return settings[name];
12210 }
12211 },
12212 internal: function(name, value) {
12213 if( $.isPlainObject(name) ) {
12214 $.extend(true, module, name);
12215 }
12216 else if(value !== undefined) {
12217 module[name] = value;
12218 }
12219 else {
12220 return module[name];
12221 }
12222 },
12223 debug: function() {
12224 if(!settings.silent && settings.debug) {
12225 if(settings.performance) {
12226 module.performance.log(arguments);
12227 }
12228 else {
12229 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
12230 module.debug.apply(console, arguments);
12231 }
12232 }
12233 },
12234 verbose: function() {
12235 if(!settings.silent && settings.verbose && settings.debug) {
12236 if(settings.performance) {
12237 module.performance.log(arguments);
12238 }
12239 else {
12240 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
12241 module.verbose.apply(console, arguments);
12242 }
12243 }
12244 },
12245 error: function() {
12246 if(!settings.silent) {
12247 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
12248 module.error.apply(console, arguments);
12249 }
12250 },
12251 performance: {
12252 log: function(message) {
12253 var
12254 currentTime,
12255 executionTime,
12256 previousTime
12257 ;
12258 if(settings.performance) {
12259 currentTime = new Date().getTime();
12260 previousTime = time || currentTime;
12261 executionTime = currentTime - previousTime;
12262 time = currentTime;
12263 performance.push({
12264 'Name' : message[0],
12265 'Arguments' : [].slice.call(message, 1) || '',
12266 'Element' : element,
12267 'Execution Time' : executionTime
12268 });
12269 }
12270 clearTimeout(module.performance.timer);
12271 module.performance.timer = setTimeout(module.performance.display, 500);
12272 },
12273 display: function() {
12274 var
12275 title = settings.name + ':',
12276 totalTime = 0
12277 ;
12278 time = false;
12279 clearTimeout(module.performance.timer);
12280 $.each(performance, function(index, data) {
12281 totalTime += data['Execution Time'];
12282 });
12283 title += ' ' + totalTime + 'ms';
12284 if(moduleSelector) {
12285 title += ' \'' + moduleSelector + '\'';
12286 }
12287 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
12288 console.groupCollapsed(title);
12289 if(console.table) {
12290 console.table(performance);
12291 }
12292 else {
12293 $.each(performance, function(index, data) {
12294 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
12295 });
12296 }
12297 console.groupEnd();
12298 }
12299 performance = [];
12300 }
12301 },
12302 invoke: function(query, passedArguments, context) {
12303 var
12304 object = instance,
12305 maxDepth,
12306 found,
12307 response
12308 ;
12309 passedArguments = passedArguments || queryArguments;
12310 context = element || context;
12311 if(typeof query == 'string' && object !== undefined) {
12312 query = query.split(/[\. ]/);
12313 maxDepth = query.length - 1;
12314 $.each(query, function(depth, value) {
12315 var camelCaseValue = (depth != maxDepth)
12316 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
12317 : query
12318 ;
12319 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
12320 object = object[camelCaseValue];
12321 }
12322 else if( object[camelCaseValue] !== undefined ) {
12323 found = object[camelCaseValue];
12324 return false;
12325 }
12326 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
12327 object = object[value];
12328 }
12329 else if( object[value] !== undefined ) {
12330 found = object[value];
12331 return false;
12332 }
12333 else {
12334 module.error(error.method, query);
12335 return false;
12336 }
12337 });
12338 }
12339 if ( $.isFunction( found ) ) {
12340 response = found.apply(context, passedArguments);
12341 }
12342 else if(found !== undefined) {
12343 response = found;
12344 }
12345 if(Array.isArray(returnedValue)) {
12346 returnedValue.push(response);
12347 }
12348 else if(returnedValue !== undefined) {
12349 returnedValue = [returnedValue, response];
12350 }
12351 else if(response !== undefined) {
12352 returnedValue = response;
12353 }
12354 return found;
12355 }
12356 };
12357
12358 if(methodInvoked) {
12359 if(instance === undefined) {
12360 module.initialize();
12361 }
12362 module.invoke(query);
12363 }
12364 else {
12365 if(instance !== undefined) {
12366 instance.invoke('destroy');
12367 }
12368 module.initialize();
12369 }
12370 })
12371 ;
12372
12373 return (returnedValue !== undefined)
12374 ? returnedValue
12375 : this
12376 ;
12377};
12378
12379$.fn.nag.settings = {
12380
12381 name : 'Nag',
12382
12383 silent : false,
12384 debug : false,
12385 verbose : false,
12386 performance : true,
12387
12388 namespace : 'Nag',
12389
12390 // allows cookie to be overridden
12391 persist : false,
12392
12393 // set to zero to require manually dismissal, otherwise hides on its own
12394 displayTime : 0,
12395
12396 animation : {
12397 show : 'slide',
12398 hide : 'slide'
12399 },
12400
12401 context : false,
12402 detachable : false,
12403
12404 expires : 30,
12405 domain : false,
12406 path : '/',
12407
12408 // type of storage to use
12409 storageMethod : 'cookie',
12410
12411 // value to store in dismissed localstorage/cookie
12412 key : 'nag',
12413 value : 'dismiss',
12414
12415 error: {
12416 noCookieStorage : '$.cookie is not included. A storage solution is required.',
12417 noStorage : 'Neither $.cookie or store is defined. A storage solution is required for storing state',
12418 method : 'The method you called is not defined.'
12419 },
12420
12421 className : {
12422 bottom : 'bottom',
12423 fixed : 'fixed'
12424 },
12425
12426 selector : {
12427 close : '.close.icon'
12428 },
12429
12430 speed : 500,
12431 easing : 'easeOutQuad',
12432
12433 onHide: function() {}
12434
12435};
12436
12437// Adds easing
12438$.extend( $.easing, {
12439 easeOutQuad: function (x, t, b, c, d) {
12440 return -c *(t/=d)*(t-2) + b;
12441 }
12442});
12443
12444})( jQuery, window, document );
12445
12446/*!
12447 * # Semantic UI 2.7.2 - Popup
12448 * http://github.com/semantic-org/semantic-ui/
12449 *
12450 *
12451 * Released under the MIT license
12452 * http://opensource.org/licenses/MIT
12453 *
12454 */
12455
12456;(function ($, window, document, undefined) {
12457
12458'use strict';
12459
12460$.isFunction = $.isFunction || function(obj) {
12461 return typeof obj === "function" && typeof obj.nodeType !== "number";
12462};
12463
12464window = (typeof window != 'undefined' && window.Math == Math)
12465 ? window
12466 : (typeof self != 'undefined' && self.Math == Math)
12467 ? self
12468 : Function('return this')()
12469;
12470
12471$.fn.popup = function(parameters) {
12472 var
12473 $allModules = $(this),
12474 $document = $(document),
12475 $window = $(window),
12476 $body = $('body'),
12477
12478 moduleSelector = $allModules.selector || '',
12479
12480 time = new Date().getTime(),
12481 performance = [],
12482
12483 query = arguments[0],
12484 methodInvoked = (typeof query == 'string'),
12485 queryArguments = [].slice.call(arguments, 1),
12486
12487 returnedValue
12488 ;
12489 $allModules
12490 .each(function() {
12491 var
12492 settings = ( $.isPlainObject(parameters) )
12493 ? $.extend(true, {}, $.fn.popup.settings, parameters)
12494 : $.extend({}, $.fn.popup.settings),
12495
12496 selector = settings.selector,
12497 className = settings.className,
12498 error = settings.error,
12499 metadata = settings.metadata,
12500 namespace = settings.namespace,
12501
12502 eventNamespace = '.' + settings.namespace,
12503 moduleNamespace = 'module-' + namespace,
12504
12505 $module = $(this),
12506 $context = $(settings.context),
12507 $scrollContext = $(settings.scrollContext),
12508 $boundary = $(settings.boundary),
12509 $target = (settings.target)
12510 ? $(settings.target)
12511 : $module,
12512
12513 $popup,
12514 $offsetParent,
12515
12516 searchDepth = 0,
12517 triedPositions = false,
12518 openedWithTouch = false,
12519
12520 element = this,
12521 instance = $module.data(moduleNamespace),
12522
12523 documentObserver,
12524 elementNamespace,
12525 id,
12526 module
12527 ;
12528
12529 module = {
12530
12531 // binds events
12532 initialize: function() {
12533 module.debug('Initializing', $module);
12534 module.createID();
12535 module.bind.events();
12536 if(!module.exists() && settings.preserve) {
12537 module.create();
12538 }
12539 if(settings.observeChanges) {
12540 module.observeChanges();
12541 }
12542 module.instantiate();
12543 },
12544
12545 instantiate: function() {
12546 module.verbose('Storing instance', module);
12547 instance = module;
12548 $module
12549 .data(moduleNamespace, instance)
12550 ;
12551 },
12552
12553 observeChanges: function() {
12554 if('MutationObserver' in window) {
12555 documentObserver = new MutationObserver(module.event.documentChanged);
12556 documentObserver.observe(document, {
12557 childList : true,
12558 subtree : true
12559 });
12560 module.debug('Setting up mutation observer', documentObserver);
12561 }
12562 },
12563
12564 refresh: function() {
12565 if(settings.popup) {
12566 $popup = $(settings.popup).eq(0);
12567 }
12568 else {
12569 if(settings.inline) {
12570 $popup = $target.nextAll(selector.popup).eq(0);
12571 settings.popup = $popup;
12572 }
12573 }
12574 if(settings.popup) {
12575 $popup.addClass(className.loading);
12576 $offsetParent = module.get.offsetParent();
12577 $popup.removeClass(className.loading);
12578 if(settings.movePopup && module.has.popup() && module.get.offsetParent($popup)[0] !== $offsetParent[0]) {
12579 module.debug('Moving popup to the same offset parent as target');
12580 $popup
12581 .detach()
12582 .appendTo($offsetParent)
12583 ;
12584 }
12585 }
12586 else {
12587 $offsetParent = (settings.inline)
12588 ? module.get.offsetParent($target)
12589 : module.has.popup()
12590 ? module.get.offsetParent($popup)
12591 : $body
12592 ;
12593 }
12594 if( $offsetParent.is('html') && $offsetParent[0] !== $body[0] ) {
12595 module.debug('Setting page as offset parent');
12596 $offsetParent = $body;
12597 }
12598 if( module.get.variation() ) {
12599 module.set.variation();
12600 }
12601 },
12602
12603 reposition: function() {
12604 module.refresh();
12605 module.set.position();
12606 },
12607
12608 destroy: function() {
12609 module.debug('Destroying previous module');
12610 if(documentObserver) {
12611 documentObserver.disconnect();
12612 }
12613 // remove element only if was created dynamically
12614 if($popup && !settings.preserve) {
12615 module.removePopup();
12616 }
12617 // clear all timeouts
12618 clearTimeout(module.hideTimer);
12619 clearTimeout(module.showTimer);
12620 // remove events
12621 module.unbind.close();
12622 module.unbind.events();
12623 $module
12624 .removeData(moduleNamespace)
12625 ;
12626 },
12627
12628 event: {
12629 start: function(event) {
12630 var
12631 delay = ($.isPlainObject(settings.delay))
12632 ? settings.delay.show
12633 : settings.delay
12634 ;
12635 clearTimeout(module.hideTimer);
12636 if(!openedWithTouch || (openedWithTouch && settings.addTouchEvents) ) {
12637 module.showTimer = setTimeout(module.show, delay);
12638 }
12639 },
12640 end: function() {
12641 var
12642 delay = ($.isPlainObject(settings.delay))
12643 ? settings.delay.hide
12644 : settings.delay
12645 ;
12646 clearTimeout(module.showTimer);
12647 module.hideTimer = setTimeout(module.hide, delay);
12648 },
12649 touchstart: function(event) {
12650 openedWithTouch = true;
12651 if(settings.addTouchEvents) {
12652 module.show();
12653 }
12654 },
12655 resize: function() {
12656 if( module.is.visible() ) {
12657 module.set.position();
12658 }
12659 },
12660 documentChanged: function(mutations) {
12661 [].forEach.call(mutations, function(mutation) {
12662 if(mutation.removedNodes) {
12663 [].forEach.call(mutation.removedNodes, function(node) {
12664 if(node == element || $(node).find(element).length > 0) {
12665 module.debug('Element removed from DOM, tearing down events');
12666 module.destroy();
12667 }
12668 });
12669 }
12670 });
12671 },
12672 hideGracefully: function(event) {
12673 var
12674 $target = $(event.target),
12675 isInDOM = $.contains(document.documentElement, event.target),
12676 inPopup = ($target.closest(selector.popup).length > 0)
12677 ;
12678 // don't close on clicks inside popup
12679 if(event && !inPopup && isInDOM) {
12680 module.debug('Click occurred outside popup hiding popup');
12681 module.hide();
12682 }
12683 else {
12684 module.debug('Click was inside popup, keeping popup open');
12685 }
12686 }
12687 },
12688
12689 // generates popup html from metadata
12690 create: function() {
12691 var
12692 html = module.get.html(),
12693 title = module.get.title(),
12694 content = module.get.content()
12695 ;
12696
12697 if(html || content || title) {
12698 module.debug('Creating pop-up html');
12699 if(!html) {
12700 html = settings.templates.popup({
12701 title : title,
12702 content : content
12703 });
12704 }
12705 $popup = $('<div/>')
12706 .addClass(className.popup)
12707 .data(metadata.activator, $module)
12708 .html(html)
12709 ;
12710 if(settings.inline) {
12711 module.verbose('Inserting popup element inline', $popup);
12712 $popup
12713 .insertAfter($module)
12714 ;
12715 }
12716 else {
12717 module.verbose('Appending popup element to body', $popup);
12718 $popup
12719 .appendTo( $context )
12720 ;
12721 }
12722 module.refresh();
12723 module.set.variation();
12724
12725 if(settings.hoverable) {
12726 module.bind.popup();
12727 }
12728 settings.onCreate.call($popup, element);
12729 }
12730 else if($target.next(selector.popup).length !== 0) {
12731 module.verbose('Pre-existing popup found');
12732 settings.inline = true;
12733 settings.popup = $target.next(selector.popup).data(metadata.activator, $module);
12734 module.refresh();
12735 if(settings.hoverable) {
12736 module.bind.popup();
12737 }
12738 }
12739 else if(settings.popup) {
12740 $(settings.popup).data(metadata.activator, $module);
12741 module.verbose('Used popup specified in settings');
12742 module.refresh();
12743 if(settings.hoverable) {
12744 module.bind.popup();
12745 }
12746 }
12747 else {
12748 module.debug('No content specified skipping display', element);
12749 }
12750 },
12751
12752 createID: function() {
12753 id = (Math.random().toString(16) + '000000000').substr(2, 8);
12754 elementNamespace = '.' + id;
12755 module.verbose('Creating unique id for element', id);
12756 },
12757
12758 // determines popup state
12759 toggle: function() {
12760 module.debug('Toggling pop-up');
12761 if( module.is.hidden() ) {
12762 module.debug('Popup is hidden, showing pop-up');
12763 module.unbind.close();
12764 module.show();
12765 }
12766 else {
12767 module.debug('Popup is visible, hiding pop-up');
12768 module.hide();
12769 }
12770 },
12771
12772 show: function(callback) {
12773 callback = callback || function(){};
12774 module.debug('Showing pop-up', settings.transition);
12775 if(module.is.hidden() && !( module.is.active() && module.is.dropdown()) ) {
12776 if( !module.exists() ) {
12777 module.create();
12778 }
12779 if(settings.onShow.call($popup, element) === false) {
12780 module.debug('onShow callback returned false, cancelling popup animation');
12781 return;
12782 }
12783 else if(!settings.preserve && !settings.popup) {
12784 module.refresh();
12785 }
12786 if( $popup && module.set.position() ) {
12787 module.save.conditions();
12788 if(settings.exclusive) {
12789 module.hideAll();
12790 }
12791 module.animate.show(callback);
12792 }
12793 }
12794 },
12795
12796
12797 hide: function(callback) {
12798 callback = callback || function(){};
12799 if( module.is.visible() || module.is.animating() ) {
12800 if(settings.onHide.call($popup, element) === false) {
12801 module.debug('onHide callback returned false, cancelling popup animation');
12802 return;
12803 }
12804 module.remove.visible();
12805 module.unbind.close();
12806 module.restore.conditions();
12807 module.animate.hide(callback);
12808 }
12809 },
12810
12811 hideAll: function() {
12812 $(selector.popup)
12813 .filter('.' + className.popupVisible)
12814 .each(function() {
12815 $(this)
12816 .data(metadata.activator)
12817 .popup('hide')
12818 ;
12819 })
12820 ;
12821 },
12822 exists: function() {
12823 if(!$popup) {
12824 return false;
12825 }
12826 if(settings.inline || settings.popup) {
12827 return ( module.has.popup() );
12828 }
12829 else {
12830 return ( $popup.closest($context).length >= 1 )
12831 ? true
12832 : false
12833 ;
12834 }
12835 },
12836
12837 removePopup: function() {
12838 if( module.has.popup() && !settings.popup) {
12839 module.debug('Removing popup', $popup);
12840 $popup.remove();
12841 $popup = undefined;
12842 settings.onRemove.call($popup, element);
12843 }
12844 },
12845
12846 save: {
12847 conditions: function() {
12848 module.cache = {
12849 title: $module.attr('title')
12850 };
12851 if (module.cache.title) {
12852 $module.removeAttr('title');
12853 }
12854 module.verbose('Saving original attributes', module.cache.title);
12855 }
12856 },
12857 restore: {
12858 conditions: function() {
12859 if(module.cache && module.cache.title) {
12860 $module.attr('title', module.cache.title);
12861 module.verbose('Restoring original attributes', module.cache.title);
12862 }
12863 return true;
12864 }
12865 },
12866 supports: {
12867 svg: function() {
12868 return (typeof SVGGraphicsElement !== 'undefined');
12869 }
12870 },
12871 animate: {
12872 show: function(callback) {
12873 callback = $.isFunction(callback) ? callback : function(){};
12874 if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
12875 module.set.visible();
12876 $popup
12877 .transition({
12878 animation : settings.transition + ' in',
12879 queue : false,
12880 debug : settings.debug,
12881 verbose : settings.verbose,
12882 duration : settings.duration,
12883 onComplete : function() {
12884 module.bind.close();
12885 callback.call($popup, element);
12886 settings.onVisible.call($popup, element);
12887 }
12888 })
12889 ;
12890 }
12891 else {
12892 module.error(error.noTransition);
12893 }
12894 },
12895 hide: function(callback) {
12896 callback = $.isFunction(callback) ? callback : function(){};
12897 module.debug('Hiding pop-up');
12898 if(settings.onHide.call($popup, element) === false) {
12899 module.debug('onHide callback returned false, cancelling popup animation');
12900 return;
12901 }
12902 if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
12903 $popup
12904 .transition({
12905 animation : settings.transition + ' out',
12906 queue : false,
12907 duration : settings.duration,
12908 debug : settings.debug,
12909 verbose : settings.verbose,
12910 onComplete : function() {
12911 module.reset();
12912 callback.call($popup, element);
12913 settings.onHidden.call($popup, element);
12914 }
12915 })
12916 ;
12917 }
12918 else {
12919 module.error(error.noTransition);
12920 }
12921 }
12922 },
12923
12924 change: {
12925 content: function(html) {
12926 $popup.html(html);
12927 }
12928 },
12929
12930 get: {
12931 html: function() {
12932 $module.removeData(metadata.html);
12933 return $module.data(metadata.html) || settings.html;
12934 },
12935 title: function() {
12936 $module.removeData(metadata.title);
12937 return $module.data(metadata.title) || settings.title;
12938 },
12939 content: function() {
12940 $module.removeData(metadata.content);
12941 return $module.data(metadata.content) || settings.content || $module.attr('title');
12942 },
12943 variation: function() {
12944 $module.removeData(metadata.variation);
12945 return $module.data(metadata.variation) || settings.variation;
12946 },
12947 popup: function() {
12948 return $popup;
12949 },
12950 popupOffset: function() {
12951 return $popup.offset();
12952 },
12953 calculations: function() {
12954 var
12955 $popupOffsetParent = module.get.offsetParent($popup),
12956 targetElement = $target[0],
12957 isWindow = ($boundary[0] == window),
12958 targetPosition = (settings.inline || (settings.popup && settings.movePopup))
12959 ? $target.position()
12960 : $target.offset(),
12961 screenPosition = (isWindow)
12962 ? { top: 0, left: 0 }
12963 : $boundary.offset(),
12964 calculations = {},
12965 scroll = (isWindow)
12966 ? { top: $window.scrollTop(), left: $window.scrollLeft() }
12967 : { top: 0, left: 0},
12968 screen
12969 ;
12970 calculations = {
12971 // element which is launching popup
12972 target : {
12973 element : $target[0],
12974 width : $target.outerWidth(),
12975 height : $target.outerHeight(),
12976 top : targetPosition.top,
12977 left : targetPosition.left,
12978 margin : {}
12979 },
12980 // popup itself
12981 popup : {
12982 width : $popup.outerWidth(),
12983 height : $popup.outerHeight()
12984 },
12985 // offset container (or 3d context)
12986 parent : {
12987 width : $offsetParent.outerWidth(),
12988 height : $offsetParent.outerHeight()
12989 },
12990 // screen boundaries
12991 screen : {
12992 top : screenPosition.top,
12993 left : screenPosition.left,
12994 scroll: {
12995 top : scroll.top,
12996 left : scroll.left
12997 },
12998 width : $boundary.width(),
12999 height : $boundary.height()
13000 }
13001 };
13002
13003 // if popup offset context is not same as target, then adjust calculations
13004 if($popupOffsetParent.get(0) !== $offsetParent.get(0)) {
13005 var
13006 popupOffset = $popupOffsetParent.offset()
13007 ;
13008 calculations.target.top -= popupOffset.top;
13009 calculations.target.left -= popupOffset.left;
13010 calculations.parent.width = $popupOffsetParent.outerWidth();
13011 calculations.parent.height = $popupOffsetParent.outerHeight();
13012 }
13013
13014 // add in container calcs if fluid
13015 if( settings.setFluidWidth && module.is.fluid() ) {
13016 calculations.container = {
13017 width: $popup.parent().outerWidth()
13018 };
13019 calculations.popup.width = calculations.container.width;
13020 }
13021
13022 // add in margins if inline
13023 calculations.target.margin.top = (settings.inline)
13024 ? parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-top'), 10)
13025 : 0
13026 ;
13027 calculations.target.margin.left = (settings.inline)
13028 ? module.is.rtl()
13029 ? parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-right'), 10)
13030 : parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-left'), 10)
13031 : 0
13032 ;
13033 // calculate screen boundaries
13034 screen = calculations.screen;
13035 calculations.boundary = {
13036 top : screen.top + screen.scroll.top,
13037 bottom : screen.top + screen.scroll.top + screen.height,
13038 left : screen.left + screen.scroll.left,
13039 right : screen.left + screen.scroll.left + screen.width
13040 };
13041 return calculations;
13042 },
13043 id: function() {
13044 return id;
13045 },
13046 startEvent: function() {
13047 if(settings.on == 'hover') {
13048 return 'mouseenter';
13049 }
13050 else if(settings.on == 'focus') {
13051 return 'focus';
13052 }
13053 return false;
13054 },
13055 scrollEvent: function() {
13056 return 'scroll';
13057 },
13058 endEvent: function() {
13059 if(settings.on == 'hover') {
13060 return 'mouseleave';
13061 }
13062 else if(settings.on == 'focus') {
13063 return 'blur';
13064 }
13065 return false;
13066 },
13067 distanceFromBoundary: function(offset, calculations) {
13068 var
13069 distanceFromBoundary = {},
13070 popup,
13071 boundary
13072 ;
13073 calculations = calculations || module.get.calculations();
13074
13075 // shorthand
13076 popup = calculations.popup;
13077 boundary = calculations.boundary;
13078
13079 if(offset) {
13080 distanceFromBoundary = {
13081 top : (offset.top - boundary.top),
13082 left : (offset.left - boundary.left),
13083 right : (boundary.right - (offset.left + popup.width) ),
13084 bottom : (boundary.bottom - (offset.top + popup.height) )
13085 };
13086 module.verbose('Distance from boundaries determined', offset, distanceFromBoundary);
13087 }
13088 return distanceFromBoundary;
13089 },
13090 offsetParent: function($element) {
13091 var
13092 element = ($element !== undefined)
13093 ? $element[0]
13094 : $target[0],
13095 parentNode = element.parentNode,
13096 $node = $(parentNode)
13097 ;
13098 if(parentNode) {
13099 var
13100 is2D = ($node.css('transform') === 'none'),
13101 isStatic = ($node.css('position') === 'static'),
13102 isBody = $node.is('body')
13103 ;
13104 while(parentNode && !isBody && isStatic && is2D) {
13105 parentNode = parentNode.parentNode;
13106 $node = $(parentNode);
13107 is2D = ($node.css('transform') === 'none');
13108 isStatic = ($node.css('position') === 'static');
13109 isBody = $node.is('body');
13110 }
13111 }
13112 return ($node && $node.length > 0)
13113 ? $node
13114 : $()
13115 ;
13116 },
13117 positions: function() {
13118 return {
13119 'top left' : false,
13120 'top center' : false,
13121 'top right' : false,
13122 'bottom left' : false,
13123 'bottom center' : false,
13124 'bottom right' : false,
13125 'left center' : false,
13126 'right center' : false
13127 };
13128 },
13129 nextPosition: function(position) {
13130 var
13131 positions = position.split(' '),
13132 verticalPosition = positions[0],
13133 horizontalPosition = positions[1],
13134 opposite = {
13135 top : 'bottom',
13136 bottom : 'top',
13137 left : 'right',
13138 right : 'left'
13139 },
13140 adjacent = {
13141 left : 'center',
13142 center : 'right',
13143 right : 'left'
13144 },
13145 backup = {
13146 'top left' : 'top center',
13147 'top center' : 'top right',
13148 'top right' : 'right center',
13149 'right center' : 'bottom right',
13150 'bottom right' : 'bottom center',
13151 'bottom center' : 'bottom left',
13152 'bottom left' : 'left center',
13153 'left center' : 'top left'
13154 },
13155 adjacentsAvailable = (verticalPosition == 'top' || verticalPosition == 'bottom'),
13156 oppositeTried = false,
13157 adjacentTried = false,
13158 nextPosition = false
13159 ;
13160 if(!triedPositions) {
13161 module.verbose('All available positions available');
13162 triedPositions = module.get.positions();
13163 }
13164
13165 module.debug('Recording last position tried', position);
13166 triedPositions[position] = true;
13167
13168 if(settings.prefer === 'opposite') {
13169 nextPosition = [opposite[verticalPosition], horizontalPosition];
13170 nextPosition = nextPosition.join(' ');
13171 oppositeTried = (triedPositions[nextPosition] === true);
13172 module.debug('Trying opposite strategy', nextPosition);
13173 }
13174 if((settings.prefer === 'adjacent') && adjacentsAvailable ) {
13175 nextPosition = [verticalPosition, adjacent[horizontalPosition]];
13176 nextPosition = nextPosition.join(' ');
13177 adjacentTried = (triedPositions[nextPosition] === true);
13178 module.debug('Trying adjacent strategy', nextPosition);
13179 }
13180 if(adjacentTried || oppositeTried) {
13181 module.debug('Using backup position', nextPosition);
13182 nextPosition = backup[position];
13183 }
13184 return nextPosition;
13185 }
13186 },
13187
13188 set: {
13189 position: function(position, calculations) {
13190
13191 // exit conditions
13192 if($target.length === 0 || $popup.length === 0) {
13193 module.error(error.notFound);
13194 return;
13195 }
13196 var
13197 offset,
13198 distanceAway,
13199 target,
13200 popup,
13201 parent,
13202 positioning,
13203 popupOffset,
13204 distanceFromBoundary
13205 ;
13206
13207 calculations = calculations || module.get.calculations();
13208 position = position || $module.data(metadata.position) || settings.position;
13209
13210 offset = $module.data(metadata.offset) || settings.offset;
13211 distanceAway = settings.distanceAway;
13212
13213 // shorthand
13214 target = calculations.target;
13215 popup = calculations.popup;
13216 parent = calculations.parent;
13217
13218 if(module.should.centerArrow(calculations)) {
13219 module.verbose('Adjusting offset to center arrow on small target element');
13220 if(position == 'top left' || position == 'bottom left') {
13221 offset += (target.width / 2)
13222 offset -= settings.arrowPixelsFromEdge;
13223 }
13224 if(position == 'top right' || position == 'bottom right') {
13225 offset -= (target.width / 2)
13226 offset += settings.arrowPixelsFromEdge;
13227 }
13228 }
13229
13230 if(target.width === 0 && target.height === 0 && !module.is.svg(target.element)) {
13231 module.debug('Popup target is hidden, no action taken');
13232 return false;
13233 }
13234
13235 if(settings.inline) {
13236 module.debug('Adding margin to calculation', target.margin);
13237 if(position == 'left center' || position == 'right center') {
13238 offset += target.margin.top;
13239 distanceAway += -target.margin.left;
13240 }
13241 else if (position == 'top left' || position == 'top center' || position == 'top right') {
13242 offset += target.margin.left;
13243 distanceAway -= target.margin.top;
13244 }
13245 else {
13246 offset += target.margin.left;
13247 distanceAway += target.margin.top;
13248 }
13249 }
13250
13251 module.debug('Determining popup position from calculations', position, calculations);
13252
13253 if (module.is.rtl()) {
13254 position = position.replace(/left|right/g, function (match) {
13255 return (match == 'left')
13256 ? 'right'
13257 : 'left'
13258 ;
13259 });
13260 module.debug('RTL: Popup position updated', position);
13261 }
13262
13263 // if last attempt use specified last resort position
13264 if(searchDepth == settings.maxSearchDepth && typeof settings.lastResort === 'string') {
13265 position = settings.lastResort;
13266 }
13267
13268 switch (position) {
13269 case 'top left':
13270 positioning = {
13271 top : 'auto',
13272 bottom : parent.height - target.top + distanceAway,
13273 left : target.left + offset,
13274 right : 'auto'
13275 };
13276 break;
13277 case 'top center':
13278 positioning = {
13279 bottom : parent.height - target.top + distanceAway,
13280 left : target.left + (target.width / 2) - (popup.width / 2) + offset,
13281 top : 'auto',
13282 right : 'auto'
13283 };
13284 break;
13285 case 'top right':
13286 positioning = {
13287 bottom : parent.height - target.top + distanceAway,
13288 right : parent.width - target.left - target.width - offset,
13289 top : 'auto',
13290 left : 'auto'
13291 };
13292 break;
13293 case 'left center':
13294 positioning = {
13295 top : target.top + (target.height / 2) - (popup.height / 2) + offset,
13296 right : parent.width - target.left + distanceAway,
13297 left : 'auto',
13298 bottom : 'auto'
13299 };
13300 break;
13301 case 'right center':
13302 positioning = {
13303 top : target.top + (target.height / 2) - (popup.height / 2) + offset,
13304 left : target.left + target.width + distanceAway,
13305 bottom : 'auto',
13306 right : 'auto'
13307 };
13308 break;
13309 case 'bottom left':
13310 positioning = {
13311 top : target.top + target.height + distanceAway,
13312 left : target.left + offset,
13313 bottom : 'auto',
13314 right : 'auto'
13315 };
13316 break;
13317 case 'bottom center':
13318 positioning = {
13319 top : target.top + target.height + distanceAway,
13320 left : target.left + (target.width / 2) - (popup.width / 2) + offset,
13321 bottom : 'auto',
13322 right : 'auto'
13323 };
13324 break;
13325 case 'bottom right':
13326 positioning = {
13327 top : target.top + target.height + distanceAway,
13328 right : parent.width - target.left - target.width - offset,
13329 left : 'auto',
13330 bottom : 'auto'
13331 };
13332 break;
13333 }
13334 if(positioning === undefined) {
13335 module.error(error.invalidPosition, position);
13336 }
13337
13338 module.debug('Calculated popup positioning values', positioning);
13339
13340 // tentatively place on stage
13341 $popup
13342 .css(positioning)
13343 .removeClass(className.position)
13344 .addClass(position)
13345 .addClass(className.loading)
13346 ;
13347
13348 popupOffset = module.get.popupOffset();
13349
13350 // see if any boundaries are surpassed with this tentative position
13351 distanceFromBoundary = module.get.distanceFromBoundary(popupOffset, calculations);
13352
13353 if( module.is.offstage(distanceFromBoundary, position) ) {
13354 module.debug('Position is outside viewport', position);
13355 if(searchDepth < settings.maxSearchDepth) {
13356 searchDepth++;
13357 position = module.get.nextPosition(position);
13358 module.debug('Trying new position', position);
13359 return ($popup)
13360 ? module.set.position(position, calculations)
13361 : false
13362 ;
13363 }
13364 else {
13365 if(settings.lastResort) {
13366 module.debug('No position found, showing with last position');
13367 }
13368 else {
13369 module.debug('Popup could not find a position to display', $popup);
13370 module.error(error.cannotPlace, element);
13371 module.remove.attempts();
13372 module.remove.loading();
13373 module.reset();
13374 settings.onUnplaceable.call($popup, element);
13375 return false;
13376 }
13377 }
13378 }
13379 module.debug('Position is on stage', position);
13380 module.remove.attempts();
13381 module.remove.loading();
13382 if( settings.setFluidWidth && module.is.fluid() ) {
13383 module.set.fluidWidth(calculations);
13384 }
13385 return true;
13386 },
13387
13388 fluidWidth: function(calculations) {
13389 calculations = calculations || module.get.calculations();
13390 module.debug('Automatically setting element width to parent width', calculations.parent.width);
13391 $popup.css('width', calculations.container.width);
13392 },
13393
13394 variation: function(variation) {
13395 variation = variation || module.get.variation();
13396 if(variation && module.has.popup() ) {
13397 module.verbose('Adding variation to popup', variation);
13398 $popup.addClass(variation);
13399 }
13400 },
13401
13402 visible: function() {
13403 $module.addClass(className.visible);
13404 }
13405 },
13406
13407 remove: {
13408 loading: function() {
13409 $popup.removeClass(className.loading);
13410 },
13411 variation: function(variation) {
13412 variation = variation || module.get.variation();
13413 if(variation) {
13414 module.verbose('Removing variation', variation);
13415 $popup.removeClass(variation);
13416 }
13417 },
13418 visible: function() {
13419 $module.removeClass(className.visible);
13420 },
13421 attempts: function() {
13422 module.verbose('Resetting all searched positions');
13423 searchDepth = 0;
13424 triedPositions = false;
13425 }
13426 },
13427
13428 bind: {
13429 events: function() {
13430 module.debug('Binding popup events to module');
13431 if(settings.on == 'click') {
13432 $module
13433 .on('click' + eventNamespace, module.toggle)
13434 ;
13435 }
13436 if(settings.on == 'hover') {
13437 $module
13438 .on('touchstart' + eventNamespace, module.event.touchstart)
13439 ;
13440 }
13441 if( module.get.startEvent() ) {
13442 $module
13443 .on(module.get.startEvent() + eventNamespace, module.event.start)
13444 .on(module.get.endEvent() + eventNamespace, module.event.end)
13445 ;
13446 }
13447 if(settings.target) {
13448 module.debug('Target set to element', $target);
13449 }
13450 $window.on('resize' + elementNamespace, module.event.resize);
13451 },
13452 popup: function() {
13453 module.verbose('Allowing hover events on popup to prevent closing');
13454 if( $popup && module.has.popup() ) {
13455 $popup
13456 .on('mouseenter' + eventNamespace, module.event.start)
13457 .on('mouseleave' + eventNamespace, module.event.end)
13458 ;
13459 }
13460 },
13461 close: function() {
13462 if(settings.hideOnScroll === true || (settings.hideOnScroll == 'auto' && settings.on != 'click')) {
13463 module.bind.closeOnScroll();
13464 }
13465 if(module.is.closable()) {
13466 module.bind.clickaway();
13467 }
13468 else if(settings.on == 'hover' && openedWithTouch) {
13469 module.bind.touchClose();
13470 }
13471 },
13472 closeOnScroll: function() {
13473 module.verbose('Binding scroll close event to document');
13474 $scrollContext
13475 .one(module.get.scrollEvent() + elementNamespace, module.event.hideGracefully)
13476 ;
13477 },
13478 touchClose: function() {
13479 module.verbose('Binding popup touchclose event to document');
13480 $document
13481 .on('touchstart' + elementNamespace, function(event) {
13482 module.verbose('Touched away from popup');
13483 module.event.hideGracefully.call(element, event);
13484 })
13485 ;
13486 },
13487 clickaway: function() {
13488 module.verbose('Binding popup close event to document');
13489 $document
13490 .on('click' + elementNamespace, function(event) {
13491 module.verbose('Clicked away from popup');
13492 module.event.hideGracefully.call(element, event);
13493 })
13494 ;
13495 }
13496 },
13497
13498 unbind: {
13499 events: function() {
13500 $window
13501 .off(elementNamespace)
13502 ;
13503 $module
13504 .off(eventNamespace)
13505 ;
13506 },
13507 close: function() {
13508 $document
13509 .off(elementNamespace)
13510 ;
13511 $scrollContext
13512 .off(elementNamespace)
13513 ;
13514 },
13515 },
13516
13517 has: {
13518 popup: function() {
13519 return ($popup && $popup.length > 0);
13520 }
13521 },
13522
13523 should: {
13524 centerArrow: function(calculations) {
13525 return !module.is.basic() && calculations.target.width <= (settings.arrowPixelsFromEdge * 2);
13526 },
13527 },
13528
13529 is: {
13530 closable: function() {
13531 if(settings.closable == 'auto') {
13532 if(settings.on == 'hover') {
13533 return false;
13534 }
13535 return true;
13536 }
13537 return settings.closable;
13538 },
13539 offstage: function(distanceFromBoundary, position) {
13540 var
13541 offstage = []
13542 ;
13543 // return boundaries that have been surpassed
13544 $.each(distanceFromBoundary, function(direction, distance) {
13545 if(distance < -settings.jitter) {
13546 module.debug('Position exceeds allowable distance from edge', direction, distance, position);
13547 offstage.push(direction);
13548 }
13549 });
13550 if(offstage.length > 0) {
13551 return true;
13552 }
13553 else {
13554 return false;
13555 }
13556 },
13557 svg: function(element) {
13558 return module.supports.svg() && (element instanceof SVGGraphicsElement);
13559 },
13560 basic: function() {
13561 return $module.hasClass(className.basic);
13562 },
13563 active: function() {
13564 return $module.hasClass(className.active);
13565 },
13566 animating: function() {
13567 return ($popup !== undefined && $popup.hasClass(className.animating) );
13568 },
13569 fluid: function() {
13570 return ($popup !== undefined && $popup.hasClass(className.fluid));
13571 },
13572 visible: function() {
13573 return ($popup !== undefined && $popup.hasClass(className.popupVisible));
13574 },
13575 dropdown: function() {
13576 return $module.hasClass(className.dropdown);
13577 },
13578 hidden: function() {
13579 return !module.is.visible();
13580 },
13581 rtl: function () {
13582 return $module.css('direction') == 'rtl';
13583 }
13584 },
13585
13586 reset: function() {
13587 module.remove.visible();
13588 if(settings.preserve) {
13589 if($.fn.transition !== undefined) {
13590 $popup
13591 .transition('remove transition')
13592 ;
13593 }
13594 }
13595 else {
13596 module.removePopup();
13597 }
13598 },
13599
13600 setting: function(name, value) {
13601 if( $.isPlainObject(name) ) {
13602 $.extend(true, settings, name);
13603 }
13604 else if(value !== undefined) {
13605 settings[name] = value;
13606 }
13607 else {
13608 return settings[name];
13609 }
13610 },
13611 internal: function(name, value) {
13612 if( $.isPlainObject(name) ) {
13613 $.extend(true, module, name);
13614 }
13615 else if(value !== undefined) {
13616 module[name] = value;
13617 }
13618 else {
13619 return module[name];
13620 }
13621 },
13622 debug: function() {
13623 if(!settings.silent && settings.debug) {
13624 if(settings.performance) {
13625 module.performance.log(arguments);
13626 }
13627 else {
13628 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
13629 module.debug.apply(console, arguments);
13630 }
13631 }
13632 },
13633 verbose: function() {
13634 if(!settings.silent && settings.verbose && settings.debug) {
13635 if(settings.performance) {
13636 module.performance.log(arguments);
13637 }
13638 else {
13639 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
13640 module.verbose.apply(console, arguments);
13641 }
13642 }
13643 },
13644 error: function() {
13645 if(!settings.silent) {
13646 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
13647 module.error.apply(console, arguments);
13648 }
13649 },
13650 performance: {
13651 log: function(message) {
13652 var
13653 currentTime,
13654 executionTime,
13655 previousTime
13656 ;
13657 if(settings.performance) {
13658 currentTime = new Date().getTime();
13659 previousTime = time || currentTime;
13660 executionTime = currentTime - previousTime;
13661 time = currentTime;
13662 performance.push({
13663 'Name' : message[0],
13664 'Arguments' : [].slice.call(message, 1) || '',
13665 'Element' : element,
13666 'Execution Time' : executionTime
13667 });
13668 }
13669 clearTimeout(module.performance.timer);
13670 module.performance.timer = setTimeout(module.performance.display, 500);
13671 },
13672 display: function() {
13673 var
13674 title = settings.name + ':',
13675 totalTime = 0
13676 ;
13677 time = false;
13678 clearTimeout(module.performance.timer);
13679 $.each(performance, function(index, data) {
13680 totalTime += data['Execution Time'];
13681 });
13682 title += ' ' + totalTime + 'ms';
13683 if(moduleSelector) {
13684 title += ' \'' + moduleSelector + '\'';
13685 }
13686 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
13687 console.groupCollapsed(title);
13688 if(console.table) {
13689 console.table(performance);
13690 }
13691 else {
13692 $.each(performance, function(index, data) {
13693 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
13694 });
13695 }
13696 console.groupEnd();
13697 }
13698 performance = [];
13699 }
13700 },
13701 invoke: function(query, passedArguments, context) {
13702 var
13703 object = instance,
13704 maxDepth,
13705 found,
13706 response
13707 ;
13708 passedArguments = passedArguments || queryArguments;
13709 context = element || context;
13710 if(typeof query == 'string' && object !== undefined) {
13711 query = query.split(/[\. ]/);
13712 maxDepth = query.length - 1;
13713 $.each(query, function(depth, value) {
13714 var camelCaseValue = (depth != maxDepth)
13715 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
13716 : query
13717 ;
13718 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
13719 object = object[camelCaseValue];
13720 }
13721 else if( object[camelCaseValue] !== undefined ) {
13722 found = object[camelCaseValue];
13723 return false;
13724 }
13725 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
13726 object = object[value];
13727 }
13728 else if( object[value] !== undefined ) {
13729 found = object[value];
13730 return false;
13731 }
13732 else {
13733 return false;
13734 }
13735 });
13736 }
13737 if ( $.isFunction( found ) ) {
13738 response = found.apply(context, passedArguments);
13739 }
13740 else if(found !== undefined) {
13741 response = found;
13742 }
13743 if(Array.isArray(returnedValue)) {
13744 returnedValue.push(response);
13745 }
13746 else if(returnedValue !== undefined) {
13747 returnedValue = [returnedValue, response];
13748 }
13749 else if(response !== undefined) {
13750 returnedValue = response;
13751 }
13752 return found;
13753 }
13754 };
13755
13756 if(methodInvoked) {
13757 if(instance === undefined) {
13758 module.initialize();
13759 }
13760 module.invoke(query);
13761 }
13762 else {
13763 if(instance !== undefined) {
13764 instance.invoke('destroy');
13765 }
13766 module.initialize();
13767 }
13768 })
13769 ;
13770
13771 return (returnedValue !== undefined)
13772 ? returnedValue
13773 : this
13774 ;
13775};
13776
13777$.fn.popup.settings = {
13778
13779 name : 'Popup',
13780
13781 // module settings
13782 silent : false,
13783 debug : false,
13784 verbose : false,
13785 performance : true,
13786 namespace : 'popup',
13787
13788 // whether it should use dom mutation observers
13789 observeChanges : true,
13790
13791 // callback only when element added to dom
13792 onCreate : function(){},
13793
13794 // callback before element removed from dom
13795 onRemove : function(){},
13796
13797 // callback before show animation
13798 onShow : function(){},
13799
13800 // callback after show animation
13801 onVisible : function(){},
13802
13803 // callback before hide animation
13804 onHide : function(){},
13805
13806 // callback when popup cannot be positioned in visible screen
13807 onUnplaceable : function(){},
13808
13809 // callback after hide animation
13810 onHidden : function(){},
13811
13812 // when to show popup
13813 on : 'hover',
13814
13815 // element to use to determine if popup is out of boundary
13816 boundary : window,
13817
13818 // whether to add touchstart events when using hover
13819 addTouchEvents : true,
13820
13821 // default position relative to element
13822 position : 'top left',
13823
13824 // name of variation to use
13825 variation : '',
13826
13827 // whether popup should be moved to context
13828 movePopup : true,
13829
13830 // element which popup should be relative to
13831 target : false,
13832
13833 // jq selector or element that should be used as popup
13834 popup : false,
13835
13836 // popup should remain inline next to activator
13837 inline : false,
13838
13839 // popup should be removed from page on hide
13840 preserve : false,
13841
13842 // popup should not close when being hovered on
13843 hoverable : false,
13844
13845 // explicitly set content
13846 content : false,
13847
13848 // explicitly set html
13849 html : false,
13850
13851 // explicitly set title
13852 title : false,
13853
13854 // whether automatically close on clickaway when on click
13855 closable : true,
13856
13857 // automatically hide on scroll
13858 hideOnScroll : 'auto',
13859
13860 // hide other popups on show
13861 exclusive : false,
13862
13863 // context to attach popups
13864 context : 'body',
13865
13866 // context for binding scroll events
13867 scrollContext : window,
13868
13869 // position to prefer when calculating new position
13870 prefer : 'opposite',
13871
13872 // specify position to appear even if it doesn't fit
13873 lastResort : false,
13874
13875 // number of pixels from edge of popup to pointing arrow center (used from centering)
13876 arrowPixelsFromEdge: 20,
13877
13878 // delay used to prevent accidental refiring of animations due to user error
13879 delay : {
13880 show : 50,
13881 hide : 70
13882 },
13883
13884 // whether fluid variation should assign width explicitly
13885 setFluidWidth : true,
13886
13887 // transition settings
13888 duration : 200,
13889 transition : 'scale',
13890
13891 // distance away from activating element in px
13892 distanceAway : 0,
13893
13894 // number of pixels an element is allowed to be "offstage" for a position to be chosen (allows for rounding)
13895 jitter : 2,
13896
13897 // offset on aligning axis from calculated position
13898 offset : 0,
13899
13900 // maximum times to look for a position before failing (9 positions total)
13901 maxSearchDepth : 15,
13902
13903 error: {
13904 invalidPosition : 'The position you specified is not a valid position',
13905 cannotPlace : 'Popup does not fit within the boundaries of the viewport',
13906 method : 'The method you called is not defined.',
13907 noTransition : 'This module requires ui transitions <https://github.com/Semantic-Org/UI-Transition>',
13908 notFound : 'The target or popup you specified does not exist on the page'
13909 },
13910
13911 metadata: {
13912 activator : 'activator',
13913 content : 'content',
13914 html : 'html',
13915 offset : 'offset',
13916 position : 'position',
13917 title : 'title',
13918 variation : 'variation'
13919 },
13920
13921 className : {
13922 active : 'active',
13923 basic : 'basic',
13924 animating : 'animating',
13925 dropdown : 'dropdown',
13926 fluid : 'fluid',
13927 loading : 'loading',
13928 popup : 'ui popup',
13929 position : 'top left center bottom right',
13930 visible : 'visible',
13931 popupVisible : 'visible'
13932 },
13933
13934 selector : {
13935 popup : '.ui.popup'
13936 },
13937
13938 templates: {
13939 escape: function(string) {
13940 var
13941 badChars = /[&<>"'`]/g,
13942 shouldEscape = /[&<>"'`]/,
13943 escape = {
13944 "&": "&amp;",
13945 "<": "&lt;",
13946 ">": "&gt;",
13947 '"': "&quot;",
13948 "'": "&#x27;",
13949 "`": "&#x60;"
13950 },
13951 escapedChar = function(chr) {
13952 return escape[chr];
13953 }
13954 ;
13955 if(shouldEscape.test(string)) {
13956 return string.replace(badChars, escapedChar);
13957 }
13958 return string;
13959 },
13960 popup: function(text) {
13961 var
13962 html = '',
13963 escape = $.fn.popup.settings.templates.escape
13964 ;
13965 if(typeof text !== undefined) {
13966 if(typeof text.title !== undefined && text.title) {
13967 text.title = escape(text.title);
13968 html += '<div class="header">' + text.title + '</div>';
13969 }
13970 if(typeof text.content !== undefined && text.content) {
13971 text.content = escape(text.content);
13972 html += '<div class="content">' + text.content + '</div>';
13973 }
13974 }
13975 return html;
13976 }
13977 }
13978
13979};
13980
13981
13982})( jQuery, window, document );
13983
13984/*!
13985 * # Semantic UI 2.7.2 - Progress
13986 * http://github.com/semantic-org/semantic-ui/
13987 *
13988 *
13989 * Released under the MIT license
13990 * http://opensource.org/licenses/MIT
13991 *
13992 */
13993
13994;(function ($, window, document, undefined) {
13995
13996'use strict';
13997
13998$.isFunction = $.isFunction || function(obj) {
13999 return typeof obj === "function" && typeof obj.nodeType !== "number";
14000};
14001
14002window = (typeof window != 'undefined' && window.Math == Math)
14003 ? window
14004 : (typeof self != 'undefined' && self.Math == Math)
14005 ? self
14006 : Function('return this')()
14007;
14008
14009$.fn.progress = function(parameters) {
14010 var
14011 $allModules = $(this),
14012
14013 moduleSelector = $allModules.selector || '',
14014
14015 time = new Date().getTime(),
14016 performance = [],
14017
14018 query = arguments[0],
14019 methodInvoked = (typeof query == 'string'),
14020 queryArguments = [].slice.call(arguments, 1),
14021
14022 returnedValue
14023 ;
14024
14025 $allModules
14026 .each(function() {
14027 var
14028 settings = ( $.isPlainObject(parameters) )
14029 ? $.extend(true, {}, $.fn.progress.settings, parameters)
14030 : $.extend({}, $.fn.progress.settings),
14031
14032 className = settings.className,
14033 metadata = settings.metadata,
14034 namespace = settings.namespace,
14035 selector = settings.selector,
14036 error = settings.error,
14037
14038 eventNamespace = '.' + namespace,
14039 moduleNamespace = 'module-' + namespace,
14040
14041 $module = $(this),
14042 $bar = $(this).find(selector.bar),
14043 $progress = $(this).find(selector.progress),
14044 $label = $(this).find(selector.label),
14045
14046 element = this,
14047 instance = $module.data(moduleNamespace),
14048
14049 animating = false,
14050 transitionEnd,
14051 module
14052 ;
14053
14054 module = {
14055
14056 initialize: function() {
14057 module.debug('Initializing progress bar', settings);
14058
14059 module.set.duration();
14060 module.set.transitionEvent();
14061
14062 module.read.metadata();
14063 module.read.settings();
14064
14065 module.instantiate();
14066 },
14067
14068 instantiate: function() {
14069 module.verbose('Storing instance of progress', module);
14070 instance = module;
14071 $module
14072 .data(moduleNamespace, module)
14073 ;
14074 },
14075 destroy: function() {
14076 module.verbose('Destroying previous progress for', $module);
14077 clearInterval(instance.interval);
14078 module.remove.state();
14079 $module.removeData(moduleNamespace);
14080 instance = undefined;
14081 },
14082
14083 reset: function() {
14084 module.remove.nextValue();
14085 module.update.progress(0);
14086 },
14087
14088 complete: function() {
14089 if(module.percent === undefined || module.percent < 100) {
14090 module.remove.progressPoll();
14091 module.set.percent(100);
14092 }
14093 },
14094
14095 read: {
14096 metadata: function() {
14097 var
14098 data = {
14099 percent : $module.data(metadata.percent),
14100 total : $module.data(metadata.total),
14101 value : $module.data(metadata.value)
14102 }
14103 ;
14104 if(data.total) {
14105 module.debug('Total value set from metadata', data.total);
14106 module.set.total(data.total);
14107 }
14108 if(!isNaN(data.value)) {
14109 module.debug('Current value set from metadata', data.value);
14110 module.set.value(data.value);
14111 module.set.progress(data.value);
14112 }
14113 if(!isNaN(data.percent)) {
14114 module.debug('Current percent value set from metadata', data.percent);
14115 module.set.percent(data.percent);
14116 }
14117 },
14118 settings: function() {
14119 if(settings.total !== false) {
14120 module.debug('Current total set in settings', settings.total);
14121 module.set.total(settings.total);
14122 }
14123 if(settings.value !== false) {
14124 module.debug('Current value set in settings', settings.value);
14125 module.set.value(settings.value);
14126 module.set.progress(module.value);
14127 }
14128 if(settings.percent !== false) {
14129 module.debug('Current percent set in settings', settings.percent);
14130 module.set.percent(settings.percent);
14131 }
14132 }
14133 },
14134
14135 bind: {
14136 transitionEnd: function(callback) {
14137 var
14138 transitionEnd = module.get.transitionEnd()
14139 ;
14140 $bar
14141 .one(transitionEnd + eventNamespace, function(event) {
14142 clearTimeout(module.failSafeTimer);
14143 callback.call(this, event);
14144 })
14145 ;
14146 module.failSafeTimer = setTimeout(function() {
14147 $bar.triggerHandler(transitionEnd);
14148 }, settings.duration + settings.failSafeDelay);
14149 module.verbose('Adding fail safe timer', module.timer);
14150 }
14151 },
14152
14153 increment: function(incrementValue) {
14154 var
14155 maxValue,
14156 startValue,
14157 newValue
14158 ;
14159 if( module.has.total() ) {
14160 startValue = module.get.value();
14161 incrementValue = incrementValue || 1;
14162 newValue = startValue + incrementValue;
14163 }
14164 else {
14165 startValue = module.get.percent();
14166 incrementValue = incrementValue || module.get.randomValue();
14167
14168 newValue = startValue + incrementValue;
14169 maxValue = 100;
14170 module.debug('Incrementing percentage by', startValue, newValue);
14171 }
14172 newValue = module.get.normalizedValue(newValue);
14173 module.set.progress(newValue);
14174 },
14175 decrement: function(decrementValue) {
14176 var
14177 total = module.get.total(),
14178 startValue,
14179 newValue
14180 ;
14181 if(total) {
14182 startValue = module.get.value();
14183 decrementValue = decrementValue || 1;
14184 newValue = startValue - decrementValue;
14185 module.debug('Decrementing value by', decrementValue, startValue);
14186 }
14187 else {
14188 startValue = module.get.percent();
14189 decrementValue = decrementValue || module.get.randomValue();
14190 newValue = startValue - decrementValue;
14191 module.debug('Decrementing percentage by', decrementValue, startValue);
14192 }
14193 newValue = module.get.normalizedValue(newValue);
14194 module.set.progress(newValue);
14195 },
14196
14197 has: {
14198 progressPoll: function() {
14199 return module.progressPoll;
14200 },
14201 total: function() {
14202 return (module.get.total() !== false);
14203 }
14204 },
14205
14206 get: {
14207 text: function(templateText) {
14208 var
14209 value = module.value || 0,
14210 total = module.total || 0,
14211 percent = (animating)
14212 ? module.get.displayPercent()
14213 : module.percent || 0,
14214 left = (module.total > 0)
14215 ? (total - value)
14216 : (100 - percent)
14217 ;
14218 templateText = templateText || '';
14219 templateText = templateText
14220 .replace('{value}', value)
14221 .replace('{total}', total)
14222 .replace('{left}', left)
14223 .replace('{percent}', percent)
14224 ;
14225 module.verbose('Adding variables to progress bar text', templateText);
14226 return templateText;
14227 },
14228
14229 normalizedValue: function(value) {
14230 if(value < 0) {
14231 module.debug('Value cannot decrement below 0');
14232 return 0;
14233 }
14234 if(module.has.total()) {
14235 if(value > module.total) {
14236 module.debug('Value cannot increment above total', module.total);
14237 return module.total;
14238 }
14239 }
14240 else if(value > 100 ) {
14241 module.debug('Value cannot increment above 100 percent');
14242 return 100;
14243 }
14244 return value;
14245 },
14246
14247 updateInterval: function() {
14248 if(settings.updateInterval == 'auto') {
14249 return settings.duration;
14250 }
14251 return settings.updateInterval;
14252 },
14253
14254 randomValue: function() {
14255 module.debug('Generating random increment percentage');
14256 return Math.floor((Math.random() * settings.random.max) + settings.random.min);
14257 },
14258
14259 numericValue: function(value) {
14260 return (typeof value === 'string')
14261 ? (value.replace(/[^\d.]/g, '') !== '')
14262 ? +(value.replace(/[^\d.]/g, ''))
14263 : false
14264 : value
14265 ;
14266 },
14267
14268 transitionEnd: function() {
14269 var
14270 element = document.createElement('element'),
14271 transitions = {
14272 'transition' :'transitionend',
14273 'OTransition' :'oTransitionEnd',
14274 'MozTransition' :'transitionend',
14275 'WebkitTransition' :'webkitTransitionEnd'
14276 },
14277 transition
14278 ;
14279 for(transition in transitions){
14280 if( element.style[transition] !== undefined ){
14281 return transitions[transition];
14282 }
14283 }
14284 },
14285
14286 // gets current displayed percentage (if animating values this is the intermediary value)
14287 displayPercent: function() {
14288 var
14289 barWidth = $bar.width(),
14290 totalWidth = $module.width(),
14291 minDisplay = parseInt($bar.css('min-width'), 10),
14292 displayPercent = (barWidth > minDisplay)
14293 ? (barWidth / totalWidth * 100)
14294 : module.percent
14295 ;
14296 return (settings.precision > 0)
14297 ? Math.round(displayPercent * (10 * settings.precision)) / (10 * settings.precision)
14298 : Math.round(displayPercent)
14299 ;
14300 },
14301
14302 percent: function() {
14303 return module.percent || 0;
14304 },
14305 value: function() {
14306 return module.nextValue || module.value || 0;
14307 },
14308 total: function() {
14309 return module.total || false;
14310 }
14311 },
14312
14313 create: {
14314 progressPoll: function() {
14315 module.progressPoll = setTimeout(function() {
14316 module.update.toNextValue();
14317 module.remove.progressPoll();
14318 }, module.get.updateInterval());
14319 },
14320 },
14321
14322 is: {
14323 complete: function() {
14324 return module.is.success() || module.is.warning() || module.is.error();
14325 },
14326 success: function() {
14327 return $module.hasClass(className.success);
14328 },
14329 warning: function() {
14330 return $module.hasClass(className.warning);
14331 },
14332 error: function() {
14333 return $module.hasClass(className.error);
14334 },
14335 active: function() {
14336 return $module.hasClass(className.active);
14337 },
14338 visible: function() {
14339 return $module.is(':visible');
14340 }
14341 },
14342
14343 remove: {
14344 progressPoll: function() {
14345 module.verbose('Removing progress poll timer');
14346 if(module.progressPoll) {
14347 clearTimeout(module.progressPoll);
14348 delete module.progressPoll;
14349 }
14350 },
14351 nextValue: function() {
14352 module.verbose('Removing progress value stored for next update');
14353 delete module.nextValue;
14354 },
14355 state: function() {
14356 module.verbose('Removing stored state');
14357 delete module.total;
14358 delete module.percent;
14359 delete module.value;
14360 },
14361 active: function() {
14362 module.verbose('Removing active state');
14363 $module.removeClass(className.active);
14364 },
14365 success: function() {
14366 module.verbose('Removing success state');
14367 $module.removeClass(className.success);
14368 },
14369 warning: function() {
14370 module.verbose('Removing warning state');
14371 $module.removeClass(className.warning);
14372 },
14373 error: function() {
14374 module.verbose('Removing error state');
14375 $module.removeClass(className.error);
14376 }
14377 },
14378
14379 set: {
14380 barWidth: function(value) {
14381 if(value > 100) {
14382 module.error(error.tooHigh, value);
14383 }
14384 else if (value < 0) {
14385 module.error(error.tooLow, value);
14386 }
14387 else {
14388 $bar
14389 .css('width', value + '%')
14390 ;
14391 $module
14392 .attr('data-percent', parseInt(value, 10))
14393 ;
14394 }
14395 },
14396 duration: function(duration) {
14397 duration = duration || settings.duration;
14398 duration = (typeof duration == 'number')
14399 ? duration + 'ms'
14400 : duration
14401 ;
14402 module.verbose('Setting progress bar transition duration', duration);
14403 $bar
14404 .css({
14405 'transition-duration': duration
14406 })
14407 ;
14408 },
14409 percent: function(percent) {
14410 percent = (typeof percent == 'string')
14411 ? +(percent.replace('%', ''))
14412 : percent
14413 ;
14414 // round display percentage
14415 percent = (settings.precision > 0)
14416 ? Math.round(percent * (10 * settings.precision)) / (10 * settings.precision)
14417 : Math.round(percent)
14418 ;
14419 module.percent = percent;
14420 if( !module.has.total() ) {
14421 module.value = (settings.precision > 0)
14422 ? Math.round( (percent / 100) * module.total * (10 * settings.precision)) / (10 * settings.precision)
14423 : Math.round( (percent / 100) * module.total * 10) / 10
14424 ;
14425 if(settings.limitValues) {
14426 module.value = (module.value > 100)
14427 ? 100
14428 : (module.value < 0)
14429 ? 0
14430 : module.value
14431 ;
14432 }
14433 }
14434 module.set.barWidth(percent);
14435 module.set.labelInterval();
14436 module.set.labels();
14437 settings.onChange.call(element, percent, module.value, module.total);
14438 },
14439 labelInterval: function() {
14440 var
14441 animationCallback = function() {
14442 module.verbose('Bar finished animating, removing continuous label updates');
14443 clearInterval(module.interval);
14444 animating = false;
14445 module.set.labels();
14446 }
14447 ;
14448 clearInterval(module.interval);
14449 module.bind.transitionEnd(animationCallback);
14450 animating = true;
14451 module.interval = setInterval(function() {
14452 var
14453 isInDOM = $.contains(document.documentElement, element)
14454 ;
14455 if(!isInDOM) {
14456 clearInterval(module.interval);
14457 animating = false;
14458 }
14459 module.set.labels();
14460 }, settings.framerate);
14461 },
14462 labels: function() {
14463 module.verbose('Setting both bar progress and outer label text');
14464 module.set.barLabel();
14465 module.set.state();
14466 },
14467 label: function(text) {
14468 text = text || '';
14469 if(text) {
14470 text = module.get.text(text);
14471 module.verbose('Setting label to text', text);
14472 $label.text(text);
14473 }
14474 },
14475 state: function(percent) {
14476 percent = (percent !== undefined)
14477 ? percent
14478 : module.percent
14479 ;
14480 if(percent === 100) {
14481 if(settings.autoSuccess && !(module.is.warning() || module.is.error() || module.is.success())) {
14482 module.set.success();
14483 module.debug('Automatically triggering success at 100%');
14484 }
14485 else {
14486 module.verbose('Reached 100% removing active state');
14487 module.remove.active();
14488 module.remove.progressPoll();
14489 }
14490 }
14491 else if(percent > 0) {
14492 module.verbose('Adjusting active progress bar label', percent);
14493 module.set.active();
14494 }
14495 else {
14496 module.remove.active();
14497 module.set.label(settings.text.active);
14498 }
14499 },
14500 barLabel: function(text) {
14501 if(text !== undefined) {
14502 $progress.text( module.get.text(text) );
14503 }
14504 else if(settings.label == 'ratio' && module.total) {
14505 module.verbose('Adding ratio to bar label');
14506 $progress.text( module.get.text(settings.text.ratio) );
14507 }
14508 else if(settings.label == 'percent') {
14509 module.verbose('Adding percentage to bar label');
14510 $progress.text( module.get.text(settings.text.percent) );
14511 }
14512 },
14513 active: function(text) {
14514 text = text || settings.text.active;
14515 module.debug('Setting active state');
14516 if(settings.showActivity && !module.is.active() ) {
14517 $module.addClass(className.active);
14518 }
14519 module.remove.warning();
14520 module.remove.error();
14521 module.remove.success();
14522 text = settings.onLabelUpdate('active', text, module.value, module.total);
14523 if(text) {
14524 module.set.label(text);
14525 }
14526 module.bind.transitionEnd(function() {
14527 settings.onActive.call(element, module.value, module.total);
14528 });
14529 },
14530 success : function(text) {
14531 text = text || settings.text.success || settings.text.active;
14532 module.debug('Setting success state');
14533 $module.addClass(className.success);
14534 module.remove.active();
14535 module.remove.warning();
14536 module.remove.error();
14537 module.complete();
14538 if(settings.text.success) {
14539 text = settings.onLabelUpdate('success', text, module.value, module.total);
14540 module.set.label(text);
14541 }
14542 else {
14543 text = settings.onLabelUpdate('active', text, module.value, module.total);
14544 module.set.label(text);
14545 }
14546 module.bind.transitionEnd(function() {
14547 settings.onSuccess.call(element, module.total);
14548 });
14549 },
14550 warning : function(text) {
14551 text = text || settings.text.warning;
14552 module.debug('Setting warning state');
14553 $module.addClass(className.warning);
14554 module.remove.active();
14555 module.remove.success();
14556 module.remove.error();
14557 module.complete();
14558 text = settings.onLabelUpdate('warning', text, module.value, module.total);
14559 if(text) {
14560 module.set.label(text);
14561 }
14562 module.bind.transitionEnd(function() {
14563 settings.onWarning.call(element, module.value, module.total);
14564 });
14565 },
14566 error : function(text) {
14567 text = text || settings.text.error;
14568 module.debug('Setting error state');
14569 $module.addClass(className.error);
14570 module.remove.active();
14571 module.remove.success();
14572 module.remove.warning();
14573 module.complete();
14574 text = settings.onLabelUpdate('error', text, module.value, module.total);
14575 if(text) {
14576 module.set.label(text);
14577 }
14578 module.bind.transitionEnd(function() {
14579 settings.onError.call(element, module.value, module.total);
14580 });
14581 },
14582 transitionEvent: function() {
14583 transitionEnd = module.get.transitionEnd();
14584 },
14585 total: function(totalValue) {
14586 module.total = totalValue;
14587 },
14588 value: function(value) {
14589 module.value = value;
14590 },
14591 progress: function(value) {
14592 if(!module.has.progressPoll()) {
14593 module.debug('First update in progress update interval, immediately updating', value);
14594 module.update.progress(value);
14595 module.create.progressPoll();
14596 }
14597 else {
14598 module.debug('Updated within interval, setting next update to use new value', value);
14599 module.set.nextValue(value);
14600 }
14601 },
14602 nextValue: function(value) {
14603 module.nextValue = value;
14604 }
14605 },
14606
14607 update: {
14608 toNextValue: function() {
14609 var
14610 nextValue = module.nextValue
14611 ;
14612 if(nextValue) {
14613 module.debug('Update interval complete using last updated value', nextValue);
14614 module.update.progress(nextValue);
14615 module.remove.nextValue();
14616 }
14617 },
14618 progress: function(value) {
14619 var
14620 percentComplete
14621 ;
14622 value = module.get.numericValue(value);
14623 if(value === false) {
14624 module.error(error.nonNumeric, value);
14625 }
14626 value = module.get.normalizedValue(value);
14627 if( module.has.total() ) {
14628 module.set.value(value);
14629 percentComplete = (value / module.total) * 100;
14630 module.debug('Calculating percent complete from total', percentComplete);
14631 module.set.percent( percentComplete );
14632 }
14633 else {
14634 percentComplete = value;
14635 module.debug('Setting value to exact percentage value', percentComplete);
14636 module.set.percent( percentComplete );
14637 }
14638 }
14639 },
14640
14641 setting: function(name, value) {
14642 module.debug('Changing setting', name, value);
14643 if( $.isPlainObject(name) ) {
14644 $.extend(true, settings, name);
14645 }
14646 else if(value !== undefined) {
14647 if($.isPlainObject(settings[name])) {
14648 $.extend(true, settings[name], value);
14649 }
14650 else {
14651 settings[name] = value;
14652 }
14653 }
14654 else {
14655 return settings[name];
14656 }
14657 },
14658 internal: function(name, value) {
14659 if( $.isPlainObject(name) ) {
14660 $.extend(true, module, name);
14661 }
14662 else if(value !== undefined) {
14663 module[name] = value;
14664 }
14665 else {
14666 return module[name];
14667 }
14668 },
14669 debug: function() {
14670 if(!settings.silent && settings.debug) {
14671 if(settings.performance) {
14672 module.performance.log(arguments);
14673 }
14674 else {
14675 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
14676 module.debug.apply(console, arguments);
14677 }
14678 }
14679 },
14680 verbose: function() {
14681 if(!settings.silent && settings.verbose && settings.debug) {
14682 if(settings.performance) {
14683 module.performance.log(arguments);
14684 }
14685 else {
14686 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
14687 module.verbose.apply(console, arguments);
14688 }
14689 }
14690 },
14691 error: function() {
14692 if(!settings.silent) {
14693 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
14694 module.error.apply(console, arguments);
14695 }
14696 },
14697 performance: {
14698 log: function(message) {
14699 var
14700 currentTime,
14701 executionTime,
14702 previousTime
14703 ;
14704 if(settings.performance) {
14705 currentTime = new Date().getTime();
14706 previousTime = time || currentTime;
14707 executionTime = currentTime - previousTime;
14708 time = currentTime;
14709 performance.push({
14710 'Name' : message[0],
14711 'Arguments' : [].slice.call(message, 1) || '',
14712 'Element' : element,
14713 'Execution Time' : executionTime
14714 });
14715 }
14716 clearTimeout(module.performance.timer);
14717 module.performance.timer = setTimeout(module.performance.display, 500);
14718 },
14719 display: function() {
14720 var
14721 title = settings.name + ':',
14722 totalTime = 0
14723 ;
14724 time = false;
14725 clearTimeout(module.performance.timer);
14726 $.each(performance, function(index, data) {
14727 totalTime += data['Execution Time'];
14728 });
14729 title += ' ' + totalTime + 'ms';
14730 if(moduleSelector) {
14731 title += ' \'' + moduleSelector + '\'';
14732 }
14733 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
14734 console.groupCollapsed(title);
14735 if(console.table) {
14736 console.table(performance);
14737 }
14738 else {
14739 $.each(performance, function(index, data) {
14740 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
14741 });
14742 }
14743 console.groupEnd();
14744 }
14745 performance = [];
14746 }
14747 },
14748 invoke: function(query, passedArguments, context) {
14749 var
14750 object = instance,
14751 maxDepth,
14752 found,
14753 response
14754 ;
14755 passedArguments = passedArguments || queryArguments;
14756 context = element || context;
14757 if(typeof query == 'string' && object !== undefined) {
14758 query = query.split(/[\. ]/);
14759 maxDepth = query.length - 1;
14760 $.each(query, function(depth, value) {
14761 var camelCaseValue = (depth != maxDepth)
14762 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
14763 : query
14764 ;
14765 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
14766 object = object[camelCaseValue];
14767 }
14768 else if( object[camelCaseValue] !== undefined ) {
14769 found = object[camelCaseValue];
14770 return false;
14771 }
14772 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
14773 object = object[value];
14774 }
14775 else if( object[value] !== undefined ) {
14776 found = object[value];
14777 return false;
14778 }
14779 else {
14780 module.error(error.method, query);
14781 return false;
14782 }
14783 });
14784 }
14785 if ( $.isFunction( found ) ) {
14786 response = found.apply(context, passedArguments);
14787 }
14788 else if(found !== undefined) {
14789 response = found;
14790 }
14791 if(Array.isArray(returnedValue)) {
14792 returnedValue.push(response);
14793 }
14794 else if(returnedValue !== undefined) {
14795 returnedValue = [returnedValue, response];
14796 }
14797 else if(response !== undefined) {
14798 returnedValue = response;
14799 }
14800 return found;
14801 }
14802 };
14803
14804 if(methodInvoked) {
14805 if(instance === undefined) {
14806 module.initialize();
14807 }
14808 module.invoke(query);
14809 }
14810 else {
14811 if(instance !== undefined) {
14812 instance.invoke('destroy');
14813 }
14814 module.initialize();
14815 }
14816 })
14817 ;
14818
14819 return (returnedValue !== undefined)
14820 ? returnedValue
14821 : this
14822 ;
14823};
14824
14825$.fn.progress.settings = {
14826
14827 name : 'Progress',
14828 namespace : 'progress',
14829
14830 silent : false,
14831 debug : false,
14832 verbose : false,
14833 performance : true,
14834
14835 random : {
14836 min : 2,
14837 max : 5
14838 },
14839
14840 duration : 300,
14841
14842 updateInterval : 'auto',
14843
14844 autoSuccess : true,
14845 showActivity : true,
14846 limitValues : true,
14847
14848 label : 'percent',
14849 precision : 0,
14850 framerate : (1000 / 30), /// 30 fps
14851
14852 percent : false,
14853 total : false,
14854 value : false,
14855
14856 // delay in ms for fail safe animation callback
14857 failSafeDelay : 100,
14858
14859 onLabelUpdate : function(state, text, value, total){
14860 return text;
14861 },
14862 onChange : function(percent, value, total){},
14863 onSuccess : function(total){},
14864 onActive : function(value, total){},
14865 onError : function(value, total){},
14866 onWarning : function(value, total){},
14867
14868 error : {
14869 method : 'The method you called is not defined.',
14870 nonNumeric : 'Progress value is non numeric',
14871 tooHigh : 'Value specified is above 100%',
14872 tooLow : 'Value specified is below 0%'
14873 },
14874
14875 regExp: {
14876 variable: /\{\$*[A-z0-9]+\}/g
14877 },
14878
14879 metadata: {
14880 percent : 'percent',
14881 total : 'total',
14882 value : 'value'
14883 },
14884
14885 selector : {
14886 bar : '> .bar',
14887 label : '> .label',
14888 progress : '.bar > .progress'
14889 },
14890
14891 text : {
14892 active : false,
14893 error : false,
14894 success : false,
14895 warning : false,
14896 percent : '{percent}%',
14897 ratio : '{value} of {total}'
14898 },
14899
14900 className : {
14901 active : 'active',
14902 error : 'error',
14903 success : 'success',
14904 warning : 'warning'
14905 }
14906
14907};
14908
14909
14910})( jQuery, window, document );
14911
14912/*!
14913 * # Semantic UI 2.7.2 - Slider
14914 * http://github.com/semantic-org/semantic-ui/
14915 *
14916 *
14917 * Released under the MIT license
14918 * http://opensource.org/licenses/MIT
14919 *
14920 */
14921
14922;(function ( $, window, document, undefined ) {
14923
14924"use strict";
14925
14926window = (typeof window != 'undefined' && window.Math == Math)
14927 ? window
14928 : (typeof self != 'undefined' && self.Math == Math)
14929 ? self
14930 : Function('return this')()
14931;
14932
14933$.fn.slider = function(parameters) {
14934
14935 var
14936 $allModules = $(this),
14937
14938 moduleSelector = $allModules.selector || '',
14939
14940 time = new Date().getTime(),
14941 performance = [],
14942
14943 query = arguments[0],
14944 methodInvoked = (typeof query == 'string'),
14945 queryArguments = [].slice.call(arguments, 1),
14946
14947 alphabet = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'],
14948
14949 SINGLE_STEP = 1,
14950 BIG_STEP = 2,
14951 NO_STEP = 0,
14952 SINGLE_BACKSTEP = -1,
14953 BIG_BACKSTEP = -2,
14954
14955 // Used to manage document bound events.
14956 // Use this so that we can distinguish between which document events are bound to which range.
14957 currentRange = 0,
14958
14959 returnedValue
14960 ;
14961
14962 $allModules
14963 .each(function() {
14964
14965 var
14966 settings = ( $.isPlainObject(parameters) )
14967 ? $.extend(true, {}, $.fn.slider.settings, parameters)
14968 : $.extend({}, $.fn.slider.settings),
14969
14970 className = settings.className,
14971 metadata = settings.metadata,
14972 namespace = settings.namespace,
14973 error = settings.error,
14974 keys = settings.keys,
14975 interpretLabel = settings.interpretLabel,
14976
14977 isHover = false,
14978 eventNamespace = '.' + namespace,
14979 moduleNamespace = 'module-' + namespace,
14980
14981 $module = $(this),
14982 $currThumb,
14983 $thumb,
14984 $secondThumb,
14985 $track,
14986 $trackFill,
14987 $labels,
14988
14989 element = this,
14990 instance = $module.data(moduleNamespace),
14991
14992 documentEventID,
14993
14994 value,
14995 position,
14996 secondPos,
14997 offset,
14998 precision,
14999 isTouch,
15000
15001 module
15002 ;
15003
15004 module = {
15005
15006 initialize: function() {
15007 module.debug('Initializing slider', settings);
15008
15009 currentRange += 1;
15010 documentEventID = currentRange;
15011
15012 isTouch = module.setup.testOutTouch();
15013 module.setup.layout();
15014 module.setup.labels();
15015
15016 if(!module.is.disabled()) {
15017 module.bind.events();
15018 }
15019
15020 module.read.metadata();
15021 module.read.settings();
15022
15023 module.instantiate();
15024 },
15025
15026 instantiate: function() {
15027 module.verbose('Storing instance of slider', module);
15028 instance = module;
15029 $module
15030 .data(moduleNamespace, module)
15031 ;
15032 },
15033
15034 destroy: function() {
15035 module.verbose('Destroying previous slider for', $module);
15036 clearInterval(instance.interval);
15037 module.unbind.events();
15038 module.unbind.slidingEvents();
15039 $module.removeData(moduleNamespace);
15040 instance = undefined;
15041 },
15042
15043 setup: {
15044 layout: function() {
15045 if( $module.attr('tabindex') === undefined) {
15046 $module.attr('tabindex', 0);
15047 }
15048 if($module.find('.inner').length == 0) {
15049 $module.append("<div class='inner'>"
15050 + "<div class='track'></div>"
15051 + "<div class='track-fill'></div>"
15052 + "<div class='thumb'></div>"
15053 + "</div>");
15054 }
15055 precision = module.get.precision();
15056 $thumb = $module.find('.thumb:not(.second)');
15057 $currThumb = $thumb;
15058 if(module.is.range()) {
15059 if($module.find('.thumb.second').length == 0) {
15060 $module.find('.inner').append("<div class='thumb second'></div>");
15061 }
15062 $secondThumb = $module.find('.thumb.second');
15063 }
15064 $track = $module.find('.track');
15065 $trackFill = $module.find('.track-fill');
15066 offset = $thumb.width() / 2;
15067 },
15068 labels: function() {
15069 if(module.is.labeled()) {
15070 $labels = $module.find('.labels:not(.auto)');
15071 if($labels.length != 0) {
15072 module.setup.customLabel();
15073 } else {
15074 module.setup.autoLabel();
15075 }
15076
15077 if (settings.showLabelTicks) {
15078 $module.addClass(className.ticked)
15079 }
15080 }
15081 },
15082 testOutTouch: function() {
15083 try {
15084 document.createEvent('TouchEvent');
15085 return true;
15086 } catch (e) {
15087 return false;
15088 }
15089 },
15090 customLabel: function() {
15091 var
15092 $children = $labels.find('.label'),
15093 numChildren = $children.length,
15094 min = module.get.min(),
15095 max = module.get.max(),
15096 ratio
15097 ;
15098 $children.each(function(index) {
15099 var
15100 $child = $(this),
15101 attrValue = $child.attr('data-value')
15102 ;
15103 if(attrValue) {
15104 attrValue = attrValue > max ? max : attrValue < min ? min : attrValue;
15105 ratio = (attrValue - min) / (max - min);
15106 } else {
15107 ratio = (index + 1) / (numChildren + 1);
15108 }
15109 module.update.labelPosition(ratio, $(this));
15110 });
15111 },
15112 autoLabel: function() {
15113 if(module.get.step() != 0) {
15114 $labels = $module.find('.labels');
15115 if($labels.length != 0) {
15116 $labels.empty();
15117 }
15118 else {
15119 $labels = $module.append('<ul class="auto labels"></ul>').find('.labels');
15120 }
15121 for(var i = 0, len = module.get.numLabels(); i <= len; i++) {
15122 var
15123 labelText = module.get.label(i),
15124 $label = (labelText !== "") ? $('<li class="label">' + labelText + '</li>') : null,
15125 ratio = i / len
15126 ;
15127 if($label) {
15128 module.update.labelPosition(ratio, $label);
15129 $labels.append($label);
15130 }
15131 }
15132 }
15133 }
15134 },
15135
15136 bind: {
15137 events: function() {
15138 module.bind.globalKeyboardEvents();
15139 module.bind.keyboardEvents();
15140 module.bind.mouseEvents();
15141 if(module.is.touch()) {
15142 module.bind.touchEvents();
15143 }
15144 },
15145 keyboardEvents: function() {
15146 module.verbose('Binding keyboard events');
15147 $module.on('keydown' + eventNamespace, module.event.keydown);
15148 },
15149 globalKeyboardEvents: function() {
15150 $(document).on('keydown' + eventNamespace + documentEventID, module.event.activateFocus);
15151 },
15152 mouseEvents: function() {
15153 module.verbose('Binding mouse events');
15154 $module.find('.track, .thumb, .inner').on('mousedown' + eventNamespace, function(event) {
15155 event.stopImmediatePropagation();
15156 event.preventDefault();
15157 module.event.down(event);
15158 });
15159 $module.on('mousedown' + eventNamespace, module.event.down);
15160 $module.on('mouseenter' + eventNamespace, function(event) {
15161 isHover = true;
15162 });
15163 $module.on('mouseleave' + eventNamespace, function(event) {
15164 isHover = false;
15165 });
15166 },
15167 touchEvents: function() {
15168 module.verbose('Binding touch events');
15169 $module.find('.track, .thumb, .inner').on('touchstart' + eventNamespace, function(event) {
15170 event.stopImmediatePropagation();
15171 event.preventDefault();
15172 module.event.down(event);
15173 });
15174 $module.on('touchstart' + eventNamespace, module.event.down);
15175 },
15176 slidingEvents: function() {
15177 // these don't need the identifier because we only ever want one of them to be registered with document
15178 module.verbose('Binding page wide events while handle is being draged');
15179 if(module.is.touch()) {
15180 $(document).on('touchmove' + eventNamespace, module.event.move);
15181 $(document).on('touchend' + eventNamespace, module.event.up);
15182 }
15183 else {
15184 $(document).on('mousemove' + eventNamespace, module.event.move);
15185 $(document).on('mouseup' + eventNamespace, module.event.up);
15186 }
15187 }
15188 },
15189
15190 unbind: {
15191 events: function() {
15192 $module.find('.track, .thumb, .inner').off('mousedown' + eventNamespace);
15193 $module.find('.track, .thumb, .inner').off('touchstart' + eventNamespace);
15194 $module.off('mousedown' + eventNamespace);
15195 $module.off('mouseenter' + eventNamespace);
15196 $module.off('mouseleave' + eventNamespace);
15197 $module.off('touchstart' + eventNamespace);
15198 $module.off('keydown' + eventNamespace);
15199 $module.off('focusout' + eventNamespace);
15200 $(document).off('keydown' + eventNamespace + documentEventID, module.event.activateFocus);
15201 },
15202 slidingEvents: function() {
15203 if(module.is.touch()) {
15204 $(document).off('touchmove' + eventNamespace);
15205 $(document).off('touchend' + eventNamespace);
15206 } else {
15207 $(document).off('mousemove' + eventNamespace);
15208 $(document).off('mouseup' + eventNamespace);
15209 }
15210 },
15211 },
15212
15213 event: {
15214 down: function(event, originalEvent) {
15215 event.preventDefault();
15216 if(module.is.range()) {
15217 var
15218 eventPos = module.determine.eventPos(event, originalEvent),
15219 newPos = module.determine.pos(eventPos)
15220 ;
15221 $currThumb = module.determine.closestThumb(newPos);
15222 }
15223 if(!module.is.disabled()) {
15224 module.bind.slidingEvents();
15225 }
15226 },
15227 move: function(event, originalEvent) {
15228 event.preventDefault();
15229 var value = module.determine.valueFromEvent(event, originalEvent);
15230 if(module.get.step() == 0 || module.is.smooth()) {
15231 var
15232 thumbVal = module.thumbVal,
15233 secondThumbVal = module.secondThumbVal,
15234 thumbSmoothVal = module.determine.smoothValueFromEvent(event, originalEvent)
15235 ;
15236 if(!$currThumb.hasClass('second')) {
15237 thumbVal = value;
15238 } else {
15239 secondThumbVal = value;
15240 }
15241 value = Math.abs(thumbVal - (secondThumbVal || 0));
15242 module.update.position(thumbSmoothVal);
15243 settings.onMove.call(element, value, thumbVal, secondThumbVal);
15244 } else {
15245 module.update.value(value, function(value, thumbVal, secondThumbVal) {
15246 settings.onMove.call(element, value, thumbVal, secondThumbVal);
15247 });
15248 }
15249 },
15250 up: function(event, originalEvent) {
15251 event.preventDefault();
15252 var value = module.determine.valueFromEvent(event, originalEvent);
15253 module.set.value(value);
15254 module.unbind.slidingEvents();
15255 },
15256 keydown: function(event, first) {
15257 if(module.is.focused()) {
15258 $(document).trigger(event);
15259 }
15260 if(first || module.is.focused()) {
15261 var step = module.determine.keyMovement(event);
15262 if(step != NO_STEP) {
15263 event.preventDefault();
15264 switch(step) {
15265 case SINGLE_STEP:
15266 module.takeStep();
15267 break;
15268 case BIG_STEP:
15269 module.takeStep(module.get.multiplier());
15270 break;
15271 case SINGLE_BACKSTEP:
15272 module.backStep();
15273 break;
15274 case BIG_BACKSTEP:
15275 module.backStep(module.get.multiplier());
15276 break;
15277 }
15278 }
15279 }
15280 },
15281 activateFocus: function(event) {
15282 if(!module.is.focused() && module.is.hover() && module.determine.keyMovement(event) != NO_STEP) {
15283 event.preventDefault();
15284 module.event.keydown(event, true);
15285 $module.focus();
15286 }
15287 },
15288 },
15289
15290 resync: function() {
15291 module.verbose('Resyncing thumb position based on value');
15292 if(module.is.range()) {
15293 module.update.position(module.secondThumbVal, $secondThumb);
15294 }
15295 module.update.position(module.thumbVal, $thumb);
15296 module.setup.labels();
15297 },
15298 takeStep: function(multiplier) {
15299 var
15300 multiplier = multiplier != undefined ? multiplier : 1,
15301 step = module.get.step(),
15302 currValue = module.get.currentThumbValue()
15303 ;
15304 module.verbose('Taking a step');
15305 if(step > 0) {
15306 module.set.value(currValue + step * multiplier);
15307 } else if (step == 0){
15308 var
15309 precision = module.get.precision(),
15310 newValue = currValue + (multiplier/precision)
15311 ;
15312 module.set.value(Math.round(newValue * precision) / precision);
15313 }
15314 },
15315
15316 backStep: function(multiplier) {
15317 var
15318 multiplier = multiplier != undefined ? multiplier : 1,
15319 step = module.get.step(),
15320 currValue = module.get.currentThumbValue()
15321 ;
15322 module.verbose('Going back a step');
15323 if(step > 0) {
15324 module.set.value(currValue - step * multiplier);
15325 } else if (step == 0) {
15326 var
15327 precision = module.get.precision(),
15328 newValue = currValue - (multiplier/precision)
15329 ;
15330 module.set.value(Math.round(newValue * precision) / precision);
15331 }
15332 },
15333
15334 is: {
15335 range: function() {
15336 return $module.hasClass(settings.className.range);
15337 },
15338 hover: function() {
15339 return isHover;
15340 },
15341 focused: function() {
15342 return $module.is(':focus');
15343 },
15344 disabled: function() {
15345 return $module.hasClass(settings.className.disabled);
15346 },
15347 labeled: function() {
15348 return $module.hasClass(settings.className.labeled);
15349 },
15350 reversed: function() {
15351 return $module.hasClass(settings.className.reversed);
15352 },
15353 vertical: function() {
15354 return $module.hasClass(settings.className.vertical);
15355 },
15356 smooth: function() {
15357 return settings.smooth || $module.hasClass(settings.className.smooth);
15358 },
15359 touch: function() {
15360 return isTouch;
15361 }
15362 },
15363
15364 get: {
15365 trackOffset: function() {
15366 if (module.is.vertical()) {
15367 return $track.offset().top;
15368 } else {
15369 return $track.offset().left;
15370 }
15371 },
15372 trackLength: function() {
15373 if (module.is.vertical()) {
15374 return $track.height();
15375 } else {
15376 return $track.width();
15377 }
15378 },
15379 trackLeft: function() {
15380 if (module.is.vertical()) {
15381 return $track.position().top;
15382 } else {
15383 return $track.position().left;
15384 }
15385 },
15386 trackStartPos: function() {
15387 return module.is.reversed() ? module.get.trackLeft() + module.get.trackLength() : module.get.trackLeft();
15388 },
15389 trackEndPos: function() {
15390 return module.is.reversed() ? module.get.trackLeft() : module.get.trackLeft() + module.get.trackLength();
15391 },
15392 trackStartMargin: function () {
15393 var margin;
15394 if (module.is.vertical()) {
15395 margin = module.is.reversed() ? $module.css('padding-bottom') : $module.css('padding-top');
15396 } else {
15397 margin = module.is.reversed() ? $module.css('padding-right') : $module.css('padding-left');
15398 }
15399 return margin || '0px';
15400 },
15401 trackEndMargin: function () {
15402 var margin;
15403 if (module.is.vertical()) {
15404 margin = module.is.reversed() ? $module.css('padding-top') : $module.css('padding-bottom');
15405 } else {
15406 margin = module.is.reversed() ? $module.css('padding-left') : $module.css('padding-right');
15407 }
15408 return margin || '0px';
15409 },
15410 precision: function() {
15411 var
15412 decimalPlaces,
15413 step = module.get.step()
15414 ;
15415 if(step != 0) {
15416 var split = String(step).split('.');
15417 if(split.length == 2) {
15418 decimalPlaces = split[1].length;
15419 } else {
15420 decimalPlaces = 0;
15421 }
15422 } else {
15423 decimalPlaces = settings.decimalPlaces;
15424 }
15425 var precision = Math.pow(10, decimalPlaces);
15426 module.debug('Precision determined', precision);
15427 return precision;
15428 },
15429 min: function() {
15430 return settings.min;
15431 },
15432 max: function() {
15433 return settings.max;
15434 },
15435 step: function() {
15436 return settings.step;
15437 },
15438 numLabels: function() {
15439 var value = Math.round((module.get.max() - module.get.min()) / module.get.step());
15440 module.debug('Determined that their should be ' + value + ' labels');
15441 return value;
15442 },
15443 labelType: function() {
15444 return settings.labelType;
15445 },
15446 label: function(value) {
15447 if(interpretLabel) {
15448 return interpretLabel(value);
15449 }
15450
15451 switch (settings.labelType) {
15452 case settings.labelTypes.number:
15453 return (value * module.get.step()) + module.get.min();
15454 case settings.labelTypes.letter:
15455 return alphabet[(value) % 26];
15456 default:
15457 return value;
15458 }
15459 },
15460 value: function() {
15461 return value;
15462 },
15463 currentThumbValue: function() {
15464 return $currThumb.hasClass('second') ? module.secondThumbVal : module.thumbVal;
15465 },
15466 thumbValue: function(which) {
15467 switch(which) {
15468 case 'second':
15469 if(module.is.range()) {
15470 return module.secondThumbVal;
15471 }
15472 else {
15473 module.error(error.notrange);
15474 break;
15475 }
15476 case 'first':
15477 default:
15478 return module.thumbVal;
15479 }
15480 },
15481 multiplier: function() {
15482 return settings.pageMultiplier;
15483 },
15484 thumbPosition: function(which) {
15485 switch(which) {
15486 case 'second':
15487 if(module.is.range()) {
15488 return secondPos;
15489 }
15490 else {
15491 module.error(error.notrange);
15492 break;
15493 }
15494 case 'first':
15495 default:
15496 return position;
15497 }
15498 }
15499 },
15500
15501 determine: {
15502 pos: function(pagePos) {
15503 return module.is.reversed()
15504 ?
15505 module.get.trackStartPos() - pagePos + module.get.trackOffset()
15506 :
15507 pagePos - module.get.trackOffset() - module.get.trackStartPos()
15508 ;
15509 },
15510 closestThumb: function(eventPos) {
15511 var
15512 thumbPos = parseFloat(module.determine.thumbPos($thumb)),
15513 thumbDelta = Math.abs(eventPos - thumbPos),
15514 secondThumbPos = parseFloat(module.determine.thumbPos($secondThumb)),
15515 secondThumbDelta = Math.abs(eventPos - secondThumbPos)
15516 ;
15517 return thumbDelta <= secondThumbDelta ? $thumb : $secondThumb;
15518 },
15519 closestThumbPos: function(eventPos) {
15520 var
15521 thumbPos = parseFloat(module.determine.thumbPos($thumb)),
15522 thumbDelta = Math.abs(eventPos - thumbPos),
15523 secondThumbPos = parseFloat(module.determine.thumbPos($secondThumb)),
15524 secondThumbDelta = Math.abs(eventPos - secondThumbPos)
15525 ;
15526 return thumbDelta <= secondThumbDelta ? thumbPos : secondThumbPos;
15527 },
15528 thumbPos: function($element) {
15529 var pos =
15530 module.is.vertical()
15531 ?
15532 module.is.reversed() ? $element.css('bottom') : $element.css('top')
15533 :
15534 module.is.reversed() ? $element.css('right') : $element.css('left')
15535 ;
15536 return pos;
15537 },
15538 positionFromValue: function(value) {
15539 var
15540 min = module.get.min(),
15541 max = module.get.max(),
15542 value = value > max ? max : value < min ? min : value,
15543 trackLength = module.get.trackLength(),
15544 ratio = (value - min) / (max - min),
15545 position = Math.round(ratio * trackLength)
15546 ;
15547 module.verbose('Determined position: ' + position + ' from value: ' + value);
15548 return position;
15549 },
15550 positionFromRatio: function(ratio) {
15551 var
15552 trackLength = module.get.trackLength(),
15553 step = module.get.step(),
15554 position = Math.round(ratio * trackLength),
15555 adjustedPos = (step == 0) ? position : Math.round(position / step) * step
15556 ;
15557 return adjustedPos;
15558 },
15559 valueFromEvent: function(event, originalEvent) {
15560 var
15561 eventPos = module.determine.eventPos(event, originalEvent),
15562 newPos = module.determine.pos(eventPos),
15563 value
15564 ;
15565 if(eventPos < module.get.trackOffset()) {
15566 value = module.is.reversed() ? module.get.max() : module.get.min();
15567 } else if(eventPos > module.get.trackOffset() + module.get.trackLength()) {
15568 value = module.is.reversed() ? module.get.min() : module.get.max();
15569 } else {
15570 value = module.determine.value(newPos);
15571 }
15572 return value;
15573 },
15574 smoothValueFromEvent: function(event, originalEvent) {
15575 var
15576 min = module.get.min(),
15577 max = module.get.max(),
15578 trackLength = module.get.trackLength(),
15579 eventPos = module.determine.eventPos(event, originalEvent),
15580 newPos = eventPos - module.get.trackOffset(),
15581 ratio,
15582 value
15583 ;
15584 newPos = newPos < 0 ? 0 : newPos > trackLength ? trackLength : newPos;
15585 ratio = newPos / trackLength;
15586 if (module.is.reversed()) {
15587 ratio = 1 - ratio;
15588 }
15589 value = ratio * (max - min) + min;
15590 return value;
15591 },
15592 eventPos: function(event, originalEvent) {
15593 if(module.is.touch()) {
15594 var
15595 touchY = event.changedTouches[0].pageY || event.touches[0].pageY,
15596 touchX = event.changedTouches[0].pageX || event.touches[0].pageX
15597 ;
15598 return module.is.vertical() ? touchY : touchX;
15599 }
15600 var
15601 clickY = event.pageY || originalEvent.pageY,
15602 clickX = event.pageX || originalEvent.pageX
15603 ;
15604 return module.is.vertical() ? clickY : clickX;
15605 },
15606 value: function(position) {
15607 var
15608 startPos = module.is.reversed() ? module.get.trackEndPos() : module.get.trackStartPos(),
15609 endPos = module.is.reversed() ? module.get.trackStartPos() : module.get.trackEndPos(),
15610 ratio = (position - startPos) / (endPos - startPos),
15611 range = module.get.max() - module.get.min(),
15612 step = module.get.step(),
15613 value = (ratio * range),
15614 difference = (step == 0) ? value : Math.round(value / step) * step
15615 ;
15616 module.verbose('Determined value based upon position: ' + position + ' as: ' + value);
15617 if(value != difference) {
15618 module.verbose('Rounding value to closest step: ' + difference);
15619 }
15620 // Use precision to avoid ugly Javascript floating point rounding issues
15621 // (like 35 * .01 = 0.35000000000000003)
15622 difference = Math.round(difference * precision) / precision;
15623 module.verbose('Cutting off additional decimal places');
15624 return difference + module.get.min();
15625 },
15626 keyMovement: function(event) {
15627 var
15628 key = event.which,
15629 downArrow =
15630 module.is.vertical()
15631 ?
15632 module.is.reversed() ? keys.downArrow : keys.upArrow
15633 :
15634 keys.downArrow
15635 ,
15636 upArrow =
15637 module.is.vertical()
15638 ?
15639 module.is.reversed() ? keys.upArrow : keys.downArrow
15640 :
15641 keys.upArrow
15642 ,
15643 leftArrow =
15644 !module.is.vertical()
15645 ?
15646 module.is.reversed() ? keys.rightArrow : keys.leftArrow
15647 :
15648 keys.leftArrow
15649 ,
15650 rightArrow =
15651 !module.is.vertical()
15652 ?
15653 module.is.reversed() ? keys.leftArrow : keys.rightArrow
15654 :
15655 keys.rightArrow
15656 ;
15657 if(key == downArrow || key == leftArrow) {
15658 return SINGLE_BACKSTEP;
15659 } else if(key == upArrow || key == rightArrow) {
15660 return SINGLE_STEP;
15661 } else if (key == keys.pageDown) {
15662 return BIG_BACKSTEP;
15663 } else if (key == keys.pageUp) {
15664 return BIG_STEP;
15665 } else {
15666 return NO_STEP;
15667 }
15668 }
15669 },
15670
15671 handleNewValuePosition: function(val) {
15672 var
15673 min = module.get.min(),
15674 max = module.get.max(),
15675 newPos
15676 ;
15677 if (val <= min) {
15678 val = min;
15679 } else if (val >= max) {
15680 val = max;
15681 }
15682 newPos = module.determine.positionFromValue(val);
15683 return newPos;
15684 },
15685
15686 set: {
15687 value: function(newValue) {
15688 module.update.value(newValue, function(value, thumbVal, secondThumbVal) {
15689 settings.onChange.call(element, value, thumbVal, secondThumbVal);
15690 settings.onMove.call(element, value, thumbVal, secondThumbVal);
15691 });
15692 },
15693 rangeValue: function(first, second) {
15694 if(module.is.range()) {
15695 var
15696 min = module.get.min(),
15697 max = module.get.max()
15698 ;
15699 if (first <= min) {
15700 first = min;
15701 } else if(first >= max){
15702 first = max;
15703 }
15704 if (second <= min) {
15705 second = min;
15706 } else if(second >= max){
15707 second = max;
15708 }
15709 module.thumbVal = first;
15710 module.secondThumbVal = second;
15711 value = Math.abs(module.thumbVal - module.secondThumbVal);
15712 module.update.position(module.thumbVal, $thumb);
15713 module.update.position(module.secondThumbVal, $secondThumb);
15714 settings.onChange.call(element, value, module.thumbVal, module.secondThumbVal);
15715 settings.onMove.call(element, value, module.thumbVal, module.secondThumbVal);
15716 } else {
15717 module.error(error.notrange);
15718 }
15719 },
15720 position: function(position, which) {
15721 var thumbVal = module.determine.value(position);
15722 switch (which) {
15723 case 'second':
15724 module.secondThumbVal = thumbVal;
15725 module.update.position(thumbVal, $secondThumb);
15726 break;
15727 default:
15728 module.thumbVal = thumbVal;
15729 module.update.position(thumbVal, $thumb);
15730 }
15731 value = Math.abs(module.thumbVal - (module.secondThumbVal || 0));
15732 module.set.value(value);
15733 }
15734 },
15735
15736 update: {
15737 value: function(newValue, callback) {
15738 var
15739 min = module.get.min(),
15740 max = module.get.max()
15741 ;
15742 if (newValue <= min) {
15743 newValue = min;
15744 } else if(newValue >= max){
15745 newValue = max;
15746 }
15747 if(!module.is.range()) {
15748 value = newValue;
15749 module.thumbVal = value;
15750 } else {
15751 if(!$currThumb.hasClass('second')) {
15752 module.thumbVal = newValue;
15753 } else {
15754 module.secondThumbVal = newValue;
15755 }
15756 value = Math.abs(module.thumbVal - module.secondThumbVal);
15757 }
15758 module.update.position(newValue);
15759 module.debug('Setting slider value to ' + value);
15760 if(typeof callback === 'function') {
15761 callback(value, module.thumbVal, module.secondThumbVal);
15762 }
15763 },
15764 position: function(newValue, $element) {
15765 var
15766 newPos = module.handleNewValuePosition(newValue),
15767 $targetThumb = $element != undefined ? $element : $currThumb,
15768 thumbVal = module.thumbVal || module.get.min(),
15769 secondThumbVal = module.secondThumbVal || module.get.min()
15770 ;
15771 if(module.is.range()) {
15772 if(!$targetThumb.hasClass('second')) {
15773 position = newPos;
15774 thumbVal = newValue;
15775 } else {
15776 secondPos = newPos;
15777 secondThumbVal = newValue;
15778 }
15779 } else {
15780 position = newPos;
15781 thumbVal = newValue;
15782 }
15783 var
15784 trackPosValue,
15785 thumbPosValue,
15786 min = module.get.min(),
15787 max = module.get.max(),
15788 thumbPosPercent = 100 * (newValue - min) / (max - min),
15789 trackStartPosPercent = 100 * (Math.min(thumbVal, secondThumbVal) - min) / (max - min),
15790 trackEndPosPercent = 100 * (1 - (Math.max(thumbVal, secondThumbVal) - min) / (max - min))
15791 ;
15792 if (module.is.vertical()) {
15793 if (module.is.reversed()) {
15794 thumbPosValue = {bottom: 'calc(' + thumbPosPercent + '% - ' + offset + 'px)', top: 'auto'};
15795 trackPosValue = {bottom: trackStartPosPercent + '%', top: trackEndPosPercent + '%'};
15796 }
15797 else {
15798 thumbPosValue = {top: 'calc(' + thumbPosPercent + '% - ' + offset + 'px)', bottom: 'auto'};
15799 trackPosValue = {top: trackStartPosPercent + '%', bottom: trackEndPosPercent + '%'};
15800 }
15801 } else {
15802 if (module.is.reversed()) {
15803 thumbPosValue = {right: 'calc(' + thumbPosPercent + '% - ' + offset + 'px)', left: 'auto'};
15804 trackPosValue = {right: trackStartPosPercent + '%', left: trackEndPosPercent + '%'};
15805 }
15806 else {
15807 thumbPosValue = {left: 'calc(' + thumbPosPercent + '% - ' + offset + 'px)', right: 'auto'};
15808 trackPosValue = {left: trackStartPosPercent + '%', right: trackEndPosPercent + '%'};
15809 }
15810 }
15811 $targetThumb.css(thumbPosValue);
15812 $trackFill.css(trackPosValue);
15813 module.debug('Setting slider position to ' + newPos);
15814 },
15815 labelPosition: function (ratio, $label) {
15816 var
15817 startMargin = module.get.trackStartMargin(),
15818 endMargin = module.get.trackEndMargin(),
15819 posDir =
15820 module.is.vertical()
15821 ?
15822 module.is.reversed() ? 'bottom' : 'top'
15823 :
15824 module.is.reversed() ? 'right' : 'left',
15825 startMarginMod = module.is.reversed() && !module.is.vertical() ? ' - ' : ' + '
15826 ;
15827 var position = '(100% - ' + startMargin + ' - ' + endMargin + ') * ' + ratio;
15828 $label.css(posDir, 'calc(' + position + startMarginMod + startMargin + ')');
15829 }
15830 },
15831
15832 goto: {
15833 max: function() {
15834 module.set.value(module.get.max());
15835 },
15836 min: function() {
15837 module.set.value(module.get.min());
15838 },
15839 },
15840
15841 read: {
15842 metadata: function() {
15843 var
15844 data = {
15845 thumbVal : $module.data(metadata.thumbVal),
15846 secondThumbVal : $module.data(metadata.secondThumbVal)
15847 }
15848 ;
15849 if(data.thumbVal) {
15850 if(module.is.range() && data.secondThumbVal) {
15851 module.debug('Current value set from metadata', data.thumbVal, data.secondThumbVal);
15852 module.set.rangeValue(data.thumbVal, data.secondThumbVal);
15853 } else {
15854 module.debug('Current value set from metadata', data.thumbVal);
15855 module.set.value(data.thumbVal);
15856 }
15857 }
15858 },
15859 settings: function() {
15860 if(settings.start !== false) {
15861 if(module.is.range()) {
15862 module.debug('Start position set from settings', settings.start, settings.end);
15863 module.set.rangeValue(settings.start, settings.end);
15864 } else {
15865 module.debug('Start position set from settings', settings.start);
15866 module.set.value(settings.start);
15867 }
15868 }
15869 }
15870 },
15871
15872 setting: function(name, value) {
15873 module.debug('Changing setting', name, value);
15874 if( $.isPlainObject(name) ) {
15875 $.extend(true, settings, name);
15876 }
15877 else if(value !== undefined) {
15878 if($.isPlainObject(settings[name])) {
15879 $.extend(true, settings[name], value);
15880 }
15881 else {
15882 settings[name] = value;
15883 }
15884 }
15885 else {
15886 return settings[name];
15887 }
15888 },
15889 internal: function(name, value) {
15890 if( $.isPlainObject(name) ) {
15891 $.extend(true, module, name);
15892 }
15893 else if(value !== undefined) {
15894 module[name] = value;
15895 }
15896 else {
15897 return module[name];
15898 }
15899 },
15900 debug: function() {
15901 if(!settings.silent && settings.debug) {
15902 if(settings.performance) {
15903 module.performance.log(arguments);
15904 }
15905 else {
15906 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
15907 module.debug.apply(console, arguments);
15908 }
15909 }
15910 },
15911 verbose: function() {
15912 if(!settings.silent && settings.verbose && settings.debug) {
15913 if(settings.performance) {
15914 module.performance.log(arguments);
15915 }
15916 else {
15917 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
15918 module.verbose.apply(console, arguments);
15919 }
15920 }
15921 },
15922 error: function() {
15923 if(!settings.silent) {
15924 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
15925 module.error.apply(console, arguments);
15926 }
15927 },
15928
15929 performance: {
15930 log: function(message) {
15931 var
15932 currentTime,
15933 executionTime,
15934 previousTime
15935 ;
15936 if(settings.performance) {
15937 currentTime = new Date().getTime();
15938 previousTime = time || currentTime;
15939 executionTime = currentTime - previousTime;
15940 time = currentTime;
15941 performance.push({
15942 'Name' : message[0],
15943 'Arguments' : [].slice.call(message, 1) || '',
15944 'Element' : element,
15945 'Execution Time' : executionTime
15946 });
15947 }
15948 clearTimeout(module.performance.timer);
15949 module.performance.timer = setTimeout(module.performance.display, 500);
15950 },
15951 display: function() {
15952 var
15953 title = settings.name + ':',
15954 totalTime = 0
15955 ;
15956 time = false;
15957 clearTimeout(module.performance.timer);
15958 $.each(performance, function(index, data) {
15959 totalTime += data['Execution Time'];
15960 });
15961 title += ' ' + totalTime + 'ms';
15962 if(moduleSelector) {
15963 title += ' \'' + moduleSelector + '\'';
15964 }
15965 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
15966 console.groupCollapsed(title);
15967 if(console.table) {
15968 console.table(performance);
15969 }
15970 else {
15971 $.each(performance, function(index, data) {
15972 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
15973 });
15974 }
15975 console.groupEnd();
15976 }
15977 performance = [];
15978 }
15979 },
15980
15981 invoke: function(query, passedArguments, context) {
15982 var
15983 object = instance,
15984 maxDepth,
15985 found,
15986 response
15987 ;
15988 passedArguments = passedArguments || queryArguments;
15989 context = element || context;
15990 if(typeof query == 'string' && object !== undefined) {
15991 query = query.split(/[\. ]/);
15992 maxDepth = query.length - 1;
15993 $.each(query, function(depth, value) {
15994 var camelCaseValue = (depth != maxDepth)
15995 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
15996 : query
15997 ;
15998 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
15999 object = object[camelCaseValue];
16000 }
16001 else if( object[camelCaseValue] !== undefined ) {
16002 found = object[camelCaseValue];
16003 return false;
16004 }
16005 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
16006 object = object[value];
16007 }
16008 else if( object[value] !== undefined ) {
16009 found = object[value];
16010 return false;
16011 }
16012 else {
16013 module.error(error.method, query);
16014 return false;
16015 }
16016 });
16017 }
16018 if ( $.isFunction( found ) ) {
16019 response = found.apply(context, passedArguments);
16020 }
16021 else if(found !== undefined) {
16022 response = found;
16023 }
16024 if($.isArray(returnedValue)) {
16025 returnedValue.push(response);
16026 }
16027 else if(returnedValue !== undefined) {
16028 returnedValue = [returnedValue, response];
16029 }
16030 else if(response !== undefined) {
16031 returnedValue = response;
16032 }
16033 return found;
16034 }
16035 };
16036
16037 if(methodInvoked) {
16038 if(instance === undefined) {
16039 module.initialize();
16040 }
16041 module.invoke(query);
16042 }
16043 else {
16044 if(instance !== undefined) {
16045 instance.invoke('destroy');
16046 }
16047 module.initialize();
16048 }
16049 })
16050 ;
16051
16052 return (returnedValue !== undefined)
16053 ? returnedValue
16054 : this
16055 ;
16056
16057};
16058
16059$.fn.slider.settings = {
16060
16061 silent : false,
16062 debug : false,
16063 verbose : false,
16064 performance : true,
16065
16066 name : 'Slider',
16067 namespace : 'slider',
16068
16069 error : {
16070 method : 'The method you called is not defined.',
16071 notrange : 'This slider is not a range slider'
16072 },
16073
16074 metadata: {
16075 thumbVal : 'thumbVal',
16076 secondThumbVal : 'secondThumbVal'
16077 },
16078
16079 min : 0,
16080 max : 20,
16081 step : 1,
16082 start : 0,
16083 end : 20,
16084 labelType : 'number',
16085 showLabelTicks : false,
16086 smooth : false,
16087
16088 //the decimal place to round to if step is undefined
16089 decimalPlaces : 2,
16090
16091 // page up/down multiplier. How many more times the steps to take on page up/down press
16092 pageMultiplier : 2,
16093
16094 selector: {
16095
16096 },
16097
16098 className : {
16099 reversed : 'reversed',
16100 disabled : 'disabled',
16101 labeled : 'labeled',
16102 ticked : 'ticked',
16103 vertical : 'vertical',
16104 range : 'range',
16105 smooth : 'smooth'
16106 },
16107
16108 keys : {
16109 pageUp : 33,
16110 pageDown : 34,
16111 leftArrow : 37,
16112 upArrow : 38,
16113 rightArrow : 39,
16114 downArrow : 40
16115 },
16116
16117 labelTypes : {
16118 number : 'number',
16119 letter : 'letter'
16120 },
16121
16122 onChange : function(value, thumbVal, secondThumbVal){},
16123 onMove : function(value, thumbVal, secondThumbVal){},
16124};
16125
16126
16127})( jQuery, window, document );
16128
16129/*!
16130 * # Semantic UI 2.7.2 - Rating
16131 * http://github.com/semantic-org/semantic-ui/
16132 *
16133 *
16134 * Released under the MIT license
16135 * http://opensource.org/licenses/MIT
16136 *
16137 */
16138
16139;(function ($, window, document, undefined) {
16140
16141'use strict';
16142
16143$.isFunction = $.isFunction || function(obj) {
16144 return typeof obj === "function" && typeof obj.nodeType !== "number";
16145};
16146
16147window = (typeof window != 'undefined' && window.Math == Math)
16148 ? window
16149 : (typeof self != 'undefined' && self.Math == Math)
16150 ? self
16151 : Function('return this')()
16152;
16153
16154$.fn.rating = function(parameters) {
16155 var
16156 $allModules = $(this),
16157 moduleSelector = $allModules.selector || '',
16158
16159 time = new Date().getTime(),
16160 performance = [],
16161
16162 query = arguments[0],
16163 methodInvoked = (typeof query == 'string'),
16164 queryArguments = [].slice.call(arguments, 1),
16165 returnedValue
16166 ;
16167 $allModules
16168 .each(function() {
16169 var
16170 settings = ( $.isPlainObject(parameters) )
16171 ? $.extend(true, {}, $.fn.rating.settings, parameters)
16172 : $.extend({}, $.fn.rating.settings),
16173
16174 namespace = settings.namespace,
16175 className = settings.className,
16176 metadata = settings.metadata,
16177 selector = settings.selector,
16178 error = settings.error,
16179
16180 eventNamespace = '.' + namespace,
16181 moduleNamespace = 'module-' + namespace,
16182
16183 element = this,
16184 instance = $(this).data(moduleNamespace),
16185
16186 $module = $(this),
16187 $icon = $module.find(selector.icon),
16188
16189 initialLoad,
16190 module
16191 ;
16192
16193 module = {
16194
16195 initialize: function() {
16196 module.verbose('Initializing rating module', settings);
16197
16198 if($icon.length === 0) {
16199 module.setup.layout();
16200 }
16201
16202 if(settings.interactive && !module.is.disabled()) {
16203 module.enable();
16204 }
16205 else {
16206 module.disable();
16207 }
16208 module.set.initialLoad();
16209 module.set.rating( module.get.initialRating() );
16210 module.remove.initialLoad();
16211 module.instantiate();
16212 },
16213
16214 instantiate: function() {
16215 module.verbose('Instantiating module', settings);
16216 instance = module;
16217 $module
16218 .data(moduleNamespace, module)
16219 ;
16220 },
16221
16222 destroy: function() {
16223 module.verbose('Destroying previous instance', instance);
16224 module.remove.events();
16225 $module
16226 .removeData(moduleNamespace)
16227 ;
16228 },
16229
16230 refresh: function() {
16231 $icon = $module.find(selector.icon);
16232 },
16233
16234 setup: {
16235 layout: function() {
16236 var
16237 maxRating = module.get.maxRating(),
16238 icon = module.get.icon(),
16239 html = $.fn.rating.settings.templates.icon(maxRating, icon)
16240 ;
16241 module.debug('Generating icon html dynamically');
16242 $module
16243 .html(html)
16244 ;
16245 module.refresh();
16246 }
16247 },
16248
16249 event: {
16250 mouseenter: function() {
16251 var
16252 $activeIcon = $(this)
16253 ;
16254 $activeIcon
16255 .nextAll()
16256 .removeClass(className.selected)
16257 ;
16258 $module
16259 .addClass(className.selected)
16260 ;
16261 $activeIcon
16262 .addClass(className.selected)
16263 .prevAll()
16264 .addClass(className.selected)
16265 ;
16266 },
16267 mouseleave: function() {
16268 $module
16269 .removeClass(className.selected)
16270 ;
16271 $icon
16272 .removeClass(className.selected)
16273 ;
16274 },
16275 click: function() {
16276 var
16277 $activeIcon = $(this),
16278 currentRating = module.get.rating(),
16279 rating = $icon.index($activeIcon) + 1,
16280 canClear = (settings.clearable == 'auto')
16281 ? ($icon.length === 1)
16282 : settings.clearable
16283 ;
16284 if(canClear && currentRating == rating) {
16285 module.clearRating();
16286 }
16287 else {
16288 module.set.rating( rating );
16289 }
16290 }
16291 },
16292
16293 clearRating: function() {
16294 module.debug('Clearing current rating');
16295 module.set.rating(0);
16296 },
16297
16298 bind: {
16299 events: function() {
16300 module.verbose('Binding events');
16301 $module
16302 .on('mouseenter' + eventNamespace, selector.icon, module.event.mouseenter)
16303 .on('mouseleave' + eventNamespace, selector.icon, module.event.mouseleave)
16304 .on('click' + eventNamespace, selector.icon, module.event.click)
16305 ;
16306 }
16307 },
16308
16309 remove: {
16310 events: function() {
16311 module.verbose('Removing events');
16312 $module
16313 .off(eventNamespace)
16314 ;
16315 },
16316 initialLoad: function() {
16317 initialLoad = false;
16318 }
16319 },
16320
16321 enable: function() {
16322 module.debug('Setting rating to interactive mode');
16323 module.bind.events();
16324 $module
16325 .removeClass(className.disabled)
16326 ;
16327 },
16328
16329 disable: function() {
16330 module.debug('Setting rating to read-only mode');
16331 module.remove.events();
16332 $module
16333 .addClass(className.disabled)
16334 ;
16335 },
16336
16337 is: {
16338 initialLoad: function() {
16339 return initialLoad;
16340 },
16341 disabled: function() {
16342 return $module.hasClass(className.disabled);
16343 }
16344 },
16345
16346 get: {
16347 icon: function(){
16348 var icon = $module.data(metadata.icon);
16349 if (icon) {
16350 $module.removeData(metadata.icon);
16351 }
16352 return icon || settings.icon;
16353 },
16354 initialRating: function() {
16355 if($module.data(metadata.rating) !== undefined) {
16356 $module.removeData(metadata.rating);
16357 return $module.data(metadata.rating);
16358 }
16359 return settings.initialRating;
16360 },
16361 maxRating: function() {
16362 if($module.data(metadata.maxRating) !== undefined) {
16363 $module.removeData(metadata.maxRating);
16364 return $module.data(metadata.maxRating);
16365 }
16366 return settings.maxRating;
16367 },
16368 rating: function() {
16369 var
16370 currentRating = $icon.filter('.' + className.active).length
16371 ;
16372 module.verbose('Current rating retrieved', currentRating);
16373 return currentRating;
16374 }
16375 },
16376
16377 set: {
16378 rating: function(rating) {
16379 var
16380 ratingIndex = (rating - 1 >= 0)
16381 ? (rating - 1)
16382 : 0,
16383 $activeIcon = $icon.eq(ratingIndex)
16384 ;
16385 $module
16386 .removeClass(className.selected)
16387 ;
16388 $icon
16389 .removeClass(className.selected)
16390 .removeClass(className.active)
16391 ;
16392 if(rating > 0) {
16393 module.verbose('Setting current rating to', rating);
16394 $activeIcon
16395 .prevAll()
16396 .addBack()
16397 .addClass(className.active)
16398 ;
16399 }
16400 if(!module.is.initialLoad()) {
16401 settings.onRate.call(element, rating);
16402 }
16403 },
16404 initialLoad: function() {
16405 initialLoad = true;
16406 }
16407 },
16408
16409 setting: function(name, value) {
16410 module.debug('Changing setting', name, value);
16411 if( $.isPlainObject(name) ) {
16412 $.extend(true, settings, name);
16413 }
16414 else if(value !== undefined) {
16415 if($.isPlainObject(settings[name])) {
16416 $.extend(true, settings[name], value);
16417 }
16418 else {
16419 settings[name] = value;
16420 }
16421 }
16422 else {
16423 return settings[name];
16424 }
16425 },
16426 internal: function(name, value) {
16427 if( $.isPlainObject(name) ) {
16428 $.extend(true, module, name);
16429 }
16430 else if(value !== undefined) {
16431 module[name] = value;
16432 }
16433 else {
16434 return module[name];
16435 }
16436 },
16437 debug: function() {
16438 if(!settings.silent && settings.debug) {
16439 if(settings.performance) {
16440 module.performance.log(arguments);
16441 }
16442 else {
16443 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
16444 module.debug.apply(console, arguments);
16445 }
16446 }
16447 },
16448 verbose: function() {
16449 if(!settings.silent && settings.verbose && settings.debug) {
16450 if(settings.performance) {
16451 module.performance.log(arguments);
16452 }
16453 else {
16454 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
16455 module.verbose.apply(console, arguments);
16456 }
16457 }
16458 },
16459 error: function() {
16460 if(!settings.silent) {
16461 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
16462 module.error.apply(console, arguments);
16463 }
16464 },
16465 performance: {
16466 log: function(message) {
16467 var
16468 currentTime,
16469 executionTime,
16470 previousTime
16471 ;
16472 if(settings.performance) {
16473 currentTime = new Date().getTime();
16474 previousTime = time || currentTime;
16475 executionTime = currentTime - previousTime;
16476 time = currentTime;
16477 performance.push({
16478 'Name' : message[0],
16479 'Arguments' : [].slice.call(message, 1) || '',
16480 'Element' : element,
16481 'Execution Time' : executionTime
16482 });
16483 }
16484 clearTimeout(module.performance.timer);
16485 module.performance.timer = setTimeout(module.performance.display, 500);
16486 },
16487 display: function() {
16488 var
16489 title = settings.name + ':',
16490 totalTime = 0
16491 ;
16492 time = false;
16493 clearTimeout(module.performance.timer);
16494 $.each(performance, function(index, data) {
16495 totalTime += data['Execution Time'];
16496 });
16497 title += ' ' + totalTime + 'ms';
16498 if(moduleSelector) {
16499 title += ' \'' + moduleSelector + '\'';
16500 }
16501 if($allModules.length > 1) {
16502 title += ' ' + '(' + $allModules.length + ')';
16503 }
16504 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
16505 console.groupCollapsed(title);
16506 if(console.table) {
16507 console.table(performance);
16508 }
16509 else {
16510 $.each(performance, function(index, data) {
16511 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
16512 });
16513 }
16514 console.groupEnd();
16515 }
16516 performance = [];
16517 }
16518 },
16519 invoke: function(query, passedArguments, context) {
16520 var
16521 object = instance,
16522 maxDepth,
16523 found,
16524 response
16525 ;
16526 passedArguments = passedArguments || queryArguments;
16527 context = element || context;
16528 if(typeof query == 'string' && object !== undefined) {
16529 query = query.split(/[\. ]/);
16530 maxDepth = query.length - 1;
16531 $.each(query, function(depth, value) {
16532 var camelCaseValue = (depth != maxDepth)
16533 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
16534 : query
16535 ;
16536 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
16537 object = object[camelCaseValue];
16538 }
16539 else if( object[camelCaseValue] !== undefined ) {
16540 found = object[camelCaseValue];
16541 return false;
16542 }
16543 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
16544 object = object[value];
16545 }
16546 else if( object[value] !== undefined ) {
16547 found = object[value];
16548 return false;
16549 }
16550 else {
16551 return false;
16552 }
16553 });
16554 }
16555 if ( $.isFunction( found ) ) {
16556 response = found.apply(context, passedArguments);
16557 }
16558 else if(found !== undefined) {
16559 response = found;
16560 }
16561 if(Array.isArray(returnedValue)) {
16562 returnedValue.push(response);
16563 }
16564 else if(returnedValue !== undefined) {
16565 returnedValue = [returnedValue, response];
16566 }
16567 else if(response !== undefined) {
16568 returnedValue = response;
16569 }
16570 return found;
16571 }
16572 };
16573 if(methodInvoked) {
16574 if(instance === undefined) {
16575 module.initialize();
16576 }
16577 module.invoke(query);
16578 }
16579 else {
16580 if(instance !== undefined) {
16581 instance.invoke('destroy');
16582 }
16583 module.initialize();
16584 }
16585 })
16586 ;
16587
16588 return (returnedValue !== undefined)
16589 ? returnedValue
16590 : this
16591 ;
16592};
16593
16594$.fn.rating.settings = {
16595
16596 name : 'Rating',
16597 namespace : 'rating',
16598
16599 icon : 'star',
16600
16601 silent : false,
16602 debug : false,
16603 verbose : false,
16604 performance : true,
16605
16606 initialRating : 0,
16607 interactive : true,
16608 maxRating : 4,
16609 clearable : 'auto',
16610
16611 fireOnInit : false,
16612
16613 onRate : function(rating){},
16614
16615 error : {
16616 method : 'The method you called is not defined',
16617 noMaximum : 'No maximum rating specified. Cannot generate HTML automatically'
16618 },
16619
16620
16621 metadata: {
16622 rating : 'rating',
16623 maxRating : 'maxRating',
16624 icon : 'icon'
16625 },
16626
16627 className : {
16628 active : 'active',
16629 disabled : 'disabled',
16630 selected : 'selected',
16631 loading : 'loading'
16632 },
16633
16634 selector : {
16635 icon : '.icon'
16636 },
16637
16638 templates: {
16639 icon: function(maxRating, iconClass) {
16640 var
16641 icon = 1,
16642 html = ''
16643 ;
16644 while(icon <= maxRating) {
16645 html += '<i class="'+iconClass+' icon"></i>';
16646 icon++;
16647 }
16648 return html;
16649 }
16650 }
16651
16652};
16653
16654})( jQuery, window, document );
16655
16656/*!
16657 * # Semantic UI 2.7.2 - Search
16658 * http://github.com/semantic-org/semantic-ui/
16659 *
16660 *
16661 * Released under the MIT license
16662 * http://opensource.org/licenses/MIT
16663 *
16664 */
16665
16666;(function ($, window, document, undefined) {
16667
16668'use strict';
16669
16670$.isFunction = $.isFunction || function(obj) {
16671 return typeof obj === "function" && typeof obj.nodeType !== "number";
16672};
16673
16674window = (typeof window != 'undefined' && window.Math == Math)
16675 ? window
16676 : (typeof self != 'undefined' && self.Math == Math)
16677 ? self
16678 : Function('return this')()
16679;
16680
16681$.fn.search = function(parameters) {
16682 var
16683 $allModules = $(this),
16684 moduleSelector = $allModules.selector || '',
16685
16686 time = new Date().getTime(),
16687 performance = [],
16688
16689 query = arguments[0],
16690 methodInvoked = (typeof query == 'string'),
16691 queryArguments = [].slice.call(arguments, 1),
16692 returnedValue
16693 ;
16694 $(this)
16695 .each(function() {
16696 var
16697 settings = ( $.isPlainObject(parameters) )
16698 ? $.extend(true, {}, $.fn.search.settings, parameters)
16699 : $.extend({}, $.fn.search.settings),
16700
16701 className = settings.className,
16702 metadata = settings.metadata,
16703 regExp = settings.regExp,
16704 fields = settings.fields,
16705 selector = settings.selector,
16706 error = settings.error,
16707 namespace = settings.namespace,
16708
16709 eventNamespace = '.' + namespace,
16710 moduleNamespace = namespace + '-module',
16711
16712 $module = $(this),
16713 $prompt = $module.find(selector.prompt),
16714 $searchButton = $module.find(selector.searchButton),
16715 $results = $module.find(selector.results),
16716 $result = $module.find(selector.result),
16717 $category = $module.find(selector.category),
16718
16719 element = this,
16720 instance = $module.data(moduleNamespace),
16721
16722 disabledBubbled = false,
16723 resultsDismissed = false,
16724
16725 module
16726 ;
16727
16728 module = {
16729
16730 initialize: function() {
16731 module.verbose('Initializing module');
16732 module.get.settings();
16733 module.determine.searchFields();
16734 module.bind.events();
16735 module.set.type();
16736 module.create.results();
16737 module.instantiate();
16738 },
16739 instantiate: function() {
16740 module.verbose('Storing instance of module', module);
16741 instance = module;
16742 $module
16743 .data(moduleNamespace, module)
16744 ;
16745 },
16746 destroy: function() {
16747 module.verbose('Destroying instance');
16748 $module
16749 .off(eventNamespace)
16750 .removeData(moduleNamespace)
16751 ;
16752 },
16753
16754 refresh: function() {
16755 module.debug('Refreshing selector cache');
16756 $prompt = $module.find(selector.prompt);
16757 $searchButton = $module.find(selector.searchButton);
16758 $category = $module.find(selector.category);
16759 $results = $module.find(selector.results);
16760 $result = $module.find(selector.result);
16761 },
16762
16763 refreshResults: function() {
16764 $results = $module.find(selector.results);
16765 $result = $module.find(selector.result);
16766 },
16767
16768 bind: {
16769 events: function() {
16770 module.verbose('Binding events to search');
16771 if(settings.automatic) {
16772 $module
16773 .on(module.get.inputEvent() + eventNamespace, selector.prompt, module.event.input)
16774 ;
16775 $prompt
16776 .attr('autocomplete', 'off')
16777 ;
16778 }
16779 $module
16780 // prompt
16781 .on('focus' + eventNamespace, selector.prompt, module.event.focus)
16782 .on('blur' + eventNamespace, selector.prompt, module.event.blur)
16783 .on('keydown' + eventNamespace, selector.prompt, module.handleKeyboard)
16784 // search button
16785 .on('click' + eventNamespace, selector.searchButton, module.query)
16786 // results
16787 .on('mousedown' + eventNamespace, selector.results, module.event.result.mousedown)
16788 .on('mouseup' + eventNamespace, selector.results, module.event.result.mouseup)
16789 .on('click' + eventNamespace, selector.result, module.event.result.click)
16790 ;
16791 }
16792 },
16793
16794 determine: {
16795 searchFields: function() {
16796 // this makes sure $.extend does not add specified search fields to default fields
16797 // this is the only setting which should not extend defaults
16798 if(parameters && parameters.searchFields !== undefined) {
16799 settings.searchFields = parameters.searchFields;
16800 }
16801 }
16802 },
16803
16804 event: {
16805 input: function() {
16806 if(settings.searchDelay) {
16807 clearTimeout(module.timer);
16808 module.timer = setTimeout(function() {
16809 if(module.is.focused()) {
16810 module.query();
16811 }
16812 }, settings.searchDelay);
16813 }
16814 else {
16815 module.query();
16816 }
16817 },
16818 focus: function() {
16819 module.set.focus();
16820 if(settings.searchOnFocus && module.has.minimumCharacters() ) {
16821 module.query(function() {
16822 if(module.can.show() ) {
16823 module.showResults();
16824 }
16825 });
16826 }
16827 },
16828 blur: function(event) {
16829 var
16830 pageLostFocus = (document.activeElement === this),
16831 callback = function() {
16832 module.cancel.query();
16833 module.remove.focus();
16834 module.timer = setTimeout(module.hideResults, settings.hideDelay);
16835 }
16836 ;
16837 if(pageLostFocus) {
16838 return;
16839 }
16840 resultsDismissed = false;
16841 if(module.resultsClicked) {
16842 module.debug('Determining if user action caused search to close');
16843 $module
16844 .one('click.close' + eventNamespace, selector.results, function(event) {
16845 if(module.is.inMessage(event) || disabledBubbled) {
16846 $prompt.focus();
16847 return;
16848 }
16849 disabledBubbled = false;
16850 if( !module.is.animating() && !module.is.hidden()) {
16851 callback();
16852 }
16853 })
16854 ;
16855 }
16856 else {
16857 module.debug('Input blurred without user action, closing results');
16858 callback();
16859 }
16860 },
16861 result: {
16862 mousedown: function() {
16863 module.resultsClicked = true;
16864 },
16865 mouseup: function() {
16866 module.resultsClicked = false;
16867 },
16868 click: function(event) {
16869 module.debug('Search result selected');
16870 var
16871 $result = $(this),
16872 $title = $result.find(selector.title).eq(0),
16873 $link = $result.is('a[href]')
16874 ? $result
16875 : $result.find('a[href]').eq(0),
16876 href = $link.attr('href') || false,
16877 target = $link.attr('target') || false,
16878 title = $title.html(),
16879 // title is used for result lookup
16880 value = ($title.length > 0)
16881 ? $title.text()
16882 : false,
16883 results = module.get.results(),
16884 result = $result.data(metadata.result) || module.get.result(value, results),
16885 returnedValue
16886 ;
16887 if(value) {
16888 module.set.value(value);
16889 }
16890 if( $.isFunction(settings.onSelect) ) {
16891 if(settings.onSelect.call(element, result, results) === false) {
16892 module.debug('Custom onSelect callback cancelled default select action');
16893 disabledBubbled = true;
16894 return;
16895 }
16896 }
16897 module.hideResults();
16898 if(href) {
16899 module.verbose('Opening search link found in result', $link);
16900 if(target == '_blank' || event.ctrlKey) {
16901 window.open(href);
16902 }
16903 else {
16904 window.location.href = (href);
16905 }
16906 }
16907 }
16908 }
16909 },
16910 handleKeyboard: function(event) {
16911 var
16912 // force selector refresh
16913 $result = $module.find(selector.result),
16914 $category = $module.find(selector.category),
16915 $activeResult = $result.filter('.' + className.active),
16916 currentIndex = $result.index( $activeResult ),
16917 resultSize = $result.length,
16918 hasActiveResult = $activeResult.length > 0,
16919
16920 keyCode = event.which,
16921 keys = {
16922 backspace : 8,
16923 enter : 13,
16924 escape : 27,
16925 upArrow : 38,
16926 downArrow : 40
16927 },
16928 newIndex
16929 ;
16930 // search shortcuts
16931 if(keyCode == keys.escape) {
16932 module.verbose('Escape key pressed, blurring search field');
16933 module.hideResults();
16934 resultsDismissed = true;
16935 }
16936 if( module.is.visible() ) {
16937 if(keyCode == keys.enter) {
16938 module.verbose('Enter key pressed, selecting active result');
16939 if( $result.filter('.' + className.active).length > 0 ) {
16940 module.event.result.click.call($result.filter('.' + className.active), event);
16941 event.preventDefault();
16942 return false;
16943 }
16944 }
16945 else if(keyCode == keys.upArrow && hasActiveResult) {
16946 module.verbose('Up key pressed, changing active result');
16947 newIndex = (currentIndex - 1 < 0)
16948 ? currentIndex
16949 : currentIndex - 1
16950 ;
16951 $category
16952 .removeClass(className.active)
16953 ;
16954 $result
16955 .removeClass(className.active)
16956 .eq(newIndex)
16957 .addClass(className.active)
16958 .closest($category)
16959 .addClass(className.active)
16960 ;
16961 event.preventDefault();
16962 }
16963 else if(keyCode == keys.downArrow) {
16964 module.verbose('Down key pressed, changing active result');
16965 newIndex = (currentIndex + 1 >= resultSize)
16966 ? currentIndex
16967 : currentIndex + 1
16968 ;
16969 $category
16970 .removeClass(className.active)
16971 ;
16972 $result
16973 .removeClass(className.active)
16974 .eq(newIndex)
16975 .addClass(className.active)
16976 .closest($category)
16977 .addClass(className.active)
16978 ;
16979 event.preventDefault();
16980 }
16981 }
16982 else {
16983 // query shortcuts
16984 if(keyCode == keys.enter) {
16985 module.verbose('Enter key pressed, executing query');
16986 module.query();
16987 module.set.buttonPressed();
16988 $prompt.one('keyup', module.remove.buttonFocus);
16989 }
16990 }
16991 },
16992
16993 setup: {
16994 api: function(searchTerm, callback) {
16995 var
16996 apiSettings = {
16997 debug : settings.debug,
16998 on : false,
16999 cache : settings.cache,
17000 action : 'search',
17001 urlData : {
17002 query : searchTerm
17003 },
17004 onSuccess : function(response) {
17005 module.parse.response.call(element, response, searchTerm);
17006 callback();
17007 },
17008 onFailure : function() {
17009 module.displayMessage(error.serverError);
17010 callback();
17011 },
17012 onAbort : function(response) {
17013 },
17014 onError : module.error
17015 },
17016 searchHTML
17017 ;
17018 $.extend(true, apiSettings, settings.apiSettings);
17019 module.verbose('Setting up API request', apiSettings);
17020 $module.api(apiSettings);
17021 }
17022 },
17023
17024 can: {
17025 useAPI: function() {
17026 return $.fn.api !== undefined;
17027 },
17028 show: function() {
17029 return module.is.focused() && !module.is.visible() && !module.is.empty();
17030 },
17031 transition: function() {
17032 return settings.transition && $.fn.transition !== undefined && $module.transition('is supported');
17033 }
17034 },
17035
17036 is: {
17037 animating: function() {
17038 return $results.hasClass(className.animating);
17039 },
17040 hidden: function() {
17041 return $results.hasClass(className.hidden);
17042 },
17043 inMessage: function(event) {
17044 if(!event.target) {
17045 return;
17046 }
17047 var
17048 $target = $(event.target),
17049 isInDOM = $.contains(document.documentElement, event.target)
17050 ;
17051 return (isInDOM && $target.closest(selector.message).length > 0);
17052 },
17053 empty: function() {
17054 return ($results.html() === '');
17055 },
17056 visible: function() {
17057 return ($results.filter(':visible').length > 0);
17058 },
17059 focused: function() {
17060 return ($prompt.filter(':focus').length > 0);
17061 }
17062 },
17063
17064 get: {
17065 settings: function() {
17066 if($.isPlainObject(parameters) && parameters.searchFullText) {
17067 settings.fullTextSearch = parameters.searchFullText;
17068 module.error(settings.error.oldSearchSyntax, element);
17069 }
17070 if (settings.ignoreDiacritics && !String.prototype.normalize) {
17071 settings.ignoreDiacritics = false;
17072 module.error(error.noNormalize, element);
17073 }
17074 },
17075 inputEvent: function() {
17076 var
17077 prompt = $prompt[0],
17078 inputEvent = (prompt !== undefined && prompt.oninput !== undefined)
17079 ? 'input'
17080 : (prompt !== undefined && prompt.onpropertychange !== undefined)
17081 ? 'propertychange'
17082 : 'keyup'
17083 ;
17084 return inputEvent;
17085 },
17086 value: function() {
17087 return $prompt.val();
17088 },
17089 results: function() {
17090 var
17091 results = $module.data(metadata.results)
17092 ;
17093 return results;
17094 },
17095 result: function(value, results) {
17096 var
17097 lookupFields = ['title', 'id'],
17098 result = false
17099 ;
17100 value = (value !== undefined)
17101 ? value
17102 : module.get.value()
17103 ;
17104 results = (results !== undefined)
17105 ? results
17106 : module.get.results()
17107 ;
17108 if(settings.type === 'category') {
17109 module.debug('Finding result that matches', value);
17110 $.each(results, function(index, category) {
17111 if(Array.isArray(category.results)) {
17112 result = module.search.object(value, category.results, lookupFields)[0];
17113 // don't continue searching if a result is found
17114 if(result) {
17115 return false;
17116 }
17117 }
17118 });
17119 }
17120 else {
17121 module.debug('Finding result in results object', value);
17122 result = module.search.object(value, results, lookupFields)[0];
17123 }
17124 return result || false;
17125 },
17126 },
17127
17128 select: {
17129 firstResult: function() {
17130 module.verbose('Selecting first result');
17131 $result.first().addClass(className.active);
17132 }
17133 },
17134
17135 set: {
17136 focus: function() {
17137 $module.addClass(className.focus);
17138 },
17139 loading: function() {
17140 $module.addClass(className.loading);
17141 },
17142 value: function(value) {
17143 module.verbose('Setting search input value', value);
17144 $prompt
17145 .val(value)
17146 ;
17147 },
17148 type: function(type) {
17149 type = type || settings.type;
17150 if(settings.type == 'category') {
17151 $module.addClass(settings.type);
17152 }
17153 },
17154 buttonPressed: function() {
17155 $searchButton.addClass(className.pressed);
17156 }
17157 },
17158
17159 remove: {
17160 loading: function() {
17161 $module.removeClass(className.loading);
17162 },
17163 focus: function() {
17164 $module.removeClass(className.focus);
17165 },
17166 buttonPressed: function() {
17167 $searchButton.removeClass(className.pressed);
17168 },
17169 diacritics: function(text) {
17170 return settings.ignoreDiacritics ? text.normalize('NFD').replace(/[\u0300-\u036f]/g, '') : text;
17171 }
17172 },
17173
17174 query: function(callback) {
17175 callback = $.isFunction(callback)
17176 ? callback
17177 : function(){}
17178 ;
17179 var
17180 searchTerm = module.get.value(),
17181 cache = module.read.cache(searchTerm)
17182 ;
17183 callback = callback || function() {};
17184 if( module.has.minimumCharacters() ) {
17185 if(cache) {
17186 module.debug('Reading result from cache', searchTerm);
17187 module.save.results(cache.results);
17188 module.addResults(cache.html);
17189 module.inject.id(cache.results);
17190 callback();
17191 }
17192 else {
17193 module.debug('Querying for', searchTerm);
17194 if($.isPlainObject(settings.source) || Array.isArray(settings.source)) {
17195 module.search.local(searchTerm);
17196 callback();
17197 }
17198 else if( module.can.useAPI() ) {
17199 module.search.remote(searchTerm, callback);
17200 }
17201 else {
17202 module.error(error.source);
17203 callback();
17204 }
17205 }
17206 settings.onSearchQuery.call(element, searchTerm);
17207 }
17208 else {
17209 module.hideResults();
17210 }
17211 },
17212
17213 search: {
17214 local: function(searchTerm) {
17215 var
17216 results = module.search.object(searchTerm, settings.content),
17217 searchHTML
17218 ;
17219 module.set.loading();
17220 module.save.results(results);
17221 module.debug('Returned full local search results', results);
17222 if(settings.maxResults > 0) {
17223 module.debug('Using specified max results', results);
17224 results = results.slice(0, settings.maxResults);
17225 }
17226 if(settings.type == 'category') {
17227 results = module.create.categoryResults(results);
17228 }
17229 searchHTML = module.generateResults({
17230 results: results
17231 });
17232 module.remove.loading();
17233 module.addResults(searchHTML);
17234 module.inject.id(results);
17235 module.write.cache(searchTerm, {
17236 html : searchHTML,
17237 results : results
17238 });
17239 },
17240 remote: function(searchTerm, callback) {
17241 callback = $.isFunction(callback)
17242 ? callback
17243 : function(){}
17244 ;
17245 if($module.api('is loading')) {
17246 $module.api('abort');
17247 }
17248 module.setup.api(searchTerm, callback);
17249 $module
17250 .api('query')
17251 ;
17252 },
17253 object: function(searchTerm, source, searchFields) {
17254 searchTerm = module.remove.diacritics(String(searchTerm));
17255 var
17256 results = [],
17257 exactResults = [],
17258 fuzzyResults = [],
17259 searchExp = searchTerm.replace(regExp.escape, '\\$&'),
17260 matchRegExp = new RegExp(regExp.beginsWith + searchExp, 'i'),
17261
17262 // avoid duplicates when pushing results
17263 addResult = function(array, result) {
17264 var
17265 notResult = ($.inArray(result, results) == -1),
17266 notFuzzyResult = ($.inArray(result, fuzzyResults) == -1),
17267 notExactResults = ($.inArray(result, exactResults) == -1)
17268 ;
17269 if(notResult && notFuzzyResult && notExactResults) {
17270 array.push(result);
17271 }
17272 }
17273 ;
17274 source = source || settings.source;
17275 searchFields = (searchFields !== undefined)
17276 ? searchFields
17277 : settings.searchFields
17278 ;
17279
17280 // search fields should be array to loop correctly
17281 if(!Array.isArray(searchFields)) {
17282 searchFields = [searchFields];
17283 }
17284
17285 // exit conditions if no source
17286 if(source === undefined || source === false) {
17287 module.error(error.source);
17288 return [];
17289 }
17290 // iterate through search fields looking for matches
17291 $.each(searchFields, function(index, field) {
17292 $.each(source, function(label, content) {
17293 var
17294 fieldExists = (typeof content[field] == 'string')
17295 ;
17296 if(fieldExists) {
17297 var text = module.remove.diacritics(content[field]);
17298 if( text.search(matchRegExp) !== -1) {
17299 // content starts with value (first in results)
17300 addResult(results, content);
17301 }
17302 else if(settings.fullTextSearch === 'exact' && module.exactSearch(searchTerm, text) ) {
17303 // content fuzzy matches (last in results)
17304 addResult(exactResults, content);
17305 }
17306 else if(settings.fullTextSearch == true && module.fuzzySearch(searchTerm, text) ) {
17307 // content fuzzy matches (last in results)
17308 addResult(fuzzyResults, content);
17309 }
17310 }
17311 });
17312 });
17313 $.merge(exactResults, fuzzyResults);
17314 $.merge(results, exactResults);
17315 return results;
17316 }
17317 },
17318 exactSearch: function (query, term) {
17319 query = query.toLowerCase();
17320 term = term.toLowerCase();
17321 return term.indexOf(query) > -1;
17322 },
17323 fuzzySearch: function(query, term) {
17324 var
17325 termLength = term.length,
17326 queryLength = query.length
17327 ;
17328 if(typeof query !== 'string') {
17329 return false;
17330 }
17331 query = query.toLowerCase();
17332 term = term.toLowerCase();
17333 if(queryLength > termLength) {
17334 return false;
17335 }
17336 if(queryLength === termLength) {
17337 return (query === term);
17338 }
17339 search: for (var characterIndex = 0, nextCharacterIndex = 0; characterIndex < queryLength; characterIndex++) {
17340 var
17341 queryCharacter = query.charCodeAt(characterIndex)
17342 ;
17343 while(nextCharacterIndex < termLength) {
17344 if(term.charCodeAt(nextCharacterIndex++) === queryCharacter) {
17345 continue search;
17346 }
17347 }
17348 return false;
17349 }
17350 return true;
17351 },
17352
17353 parse: {
17354 response: function(response, searchTerm) {
17355 if(Array.isArray(response)){
17356 var o={};
17357 o[fields.results]=response;
17358 response = o;
17359 }
17360 var
17361 searchHTML = module.generateResults(response)
17362 ;
17363 module.verbose('Parsing server response', response);
17364 if(response !== undefined) {
17365 if(searchTerm !== undefined && response[fields.results] !== undefined) {
17366 module.addResults(searchHTML);
17367 module.inject.id(response[fields.results]);
17368 module.write.cache(searchTerm, {
17369 html : searchHTML,
17370 results : response[fields.results]
17371 });
17372 module.save.results(response[fields.results]);
17373 }
17374 }
17375 }
17376 },
17377
17378 cancel: {
17379 query: function() {
17380 if( module.can.useAPI() ) {
17381 $module.api('abort');
17382 }
17383 }
17384 },
17385
17386 has: {
17387 minimumCharacters: function() {
17388 var
17389 searchTerm = module.get.value(),
17390 numCharacters = searchTerm.length
17391 ;
17392 return (numCharacters >= settings.minCharacters);
17393 },
17394 results: function() {
17395 if($results.length === 0) {
17396 return false;
17397 }
17398 var
17399 html = $results.html()
17400 ;
17401 return html != '';
17402 }
17403 },
17404
17405 clear: {
17406 cache: function(value) {
17407 var
17408 cache = $module.data(metadata.cache)
17409 ;
17410 if(!value) {
17411 module.debug('Clearing cache', value);
17412 $module.removeData(metadata.cache);
17413 }
17414 else if(value && cache && cache[value]) {
17415 module.debug('Removing value from cache', value);
17416 delete cache[value];
17417 $module.data(metadata.cache, cache);
17418 }
17419 }
17420 },
17421
17422 read: {
17423 cache: function(name) {
17424 var
17425 cache = $module.data(metadata.cache)
17426 ;
17427 if(settings.cache) {
17428 module.verbose('Checking cache for generated html for query', name);
17429 return (typeof cache == 'object') && (cache[name] !== undefined)
17430 ? cache[name]
17431 : false
17432 ;
17433 }
17434 return false;
17435 }
17436 },
17437
17438 create: {
17439 categoryResults: function(results) {
17440 var
17441 categoryResults = {}
17442 ;
17443 $.each(results, function(index, result) {
17444 if(!result.category) {
17445 return;
17446 }
17447 if(categoryResults[result.category] === undefined) {
17448 module.verbose('Creating new category of results', result.category);
17449 categoryResults[result.category] = {
17450 name : result.category,
17451 results : [result]
17452 };
17453 }
17454 else {
17455 categoryResults[result.category].results.push(result);
17456 }
17457 });
17458 return categoryResults;
17459 },
17460 id: function(resultIndex, categoryIndex) {
17461 var
17462 resultID = (resultIndex + 1), // not zero indexed
17463 categoryID = (categoryIndex + 1),
17464 firstCharCode,
17465 letterID,
17466 id
17467 ;
17468 if(categoryIndex !== undefined) {
17469 // start char code for "A"
17470 letterID = String.fromCharCode(97 + categoryIndex);
17471 id = letterID + resultID;
17472 module.verbose('Creating category result id', id);
17473 }
17474 else {
17475 id = resultID;
17476 module.verbose('Creating result id', id);
17477 }
17478 return id;
17479 },
17480 results: function() {
17481 if($results.length === 0) {
17482 $results = $('<div />')
17483 .addClass(className.results)
17484 .appendTo($module)
17485 ;
17486 }
17487 }
17488 },
17489
17490 inject: {
17491 result: function(result, resultIndex, categoryIndex) {
17492 module.verbose('Injecting result into results');
17493 var
17494 $selectedResult = (categoryIndex !== undefined)
17495 ? $results
17496 .children().eq(categoryIndex)
17497 .children(selector.results)
17498 .first()
17499 .children(selector.result)
17500 .eq(resultIndex)
17501 : $results
17502 .children(selector.result).eq(resultIndex)
17503 ;
17504 module.verbose('Injecting results metadata', $selectedResult);
17505 $selectedResult
17506 .data(metadata.result, result)
17507 ;
17508 },
17509 id: function(results) {
17510 module.debug('Injecting unique ids into results');
17511 var
17512 // since results may be object, we must use counters
17513 categoryIndex = 0,
17514 resultIndex = 0
17515 ;
17516 if(settings.type === 'category') {
17517 // iterate through each category result
17518 $.each(results, function(index, category) {
17519 if(category.results.length > 0){
17520 resultIndex = 0;
17521 $.each(category.results, function(index, result) {
17522 if(result.id === undefined) {
17523 result.id = module.create.id(resultIndex, categoryIndex);
17524 }
17525 module.inject.result(result, resultIndex, categoryIndex);
17526 resultIndex++;
17527 });
17528 categoryIndex++;
17529 }
17530 });
17531 }
17532 else {
17533 // top level
17534 $.each(results, function(index, result) {
17535 if(result.id === undefined) {
17536 result.id = module.create.id(resultIndex);
17537 }
17538 module.inject.result(result, resultIndex);
17539 resultIndex++;
17540 });
17541 }
17542 return results;
17543 }
17544 },
17545
17546 save: {
17547 results: function(results) {
17548 module.verbose('Saving current search results to metadata', results);
17549 $module.data(metadata.results, results);
17550 }
17551 },
17552
17553 write: {
17554 cache: function(name, value) {
17555 var
17556 cache = ($module.data(metadata.cache) !== undefined)
17557 ? $module.data(metadata.cache)
17558 : {}
17559 ;
17560 if(settings.cache) {
17561 module.verbose('Writing generated html to cache', name, value);
17562 cache[name] = value;
17563 $module
17564 .data(metadata.cache, cache)
17565 ;
17566 }
17567 }
17568 },
17569
17570 addResults: function(html) {
17571 if( $.isFunction(settings.onResultsAdd) ) {
17572 if( settings.onResultsAdd.call($results, html) === false ) {
17573 module.debug('onResultsAdd callback cancelled default action');
17574 return false;
17575 }
17576 }
17577 if(html) {
17578 $results
17579 .html(html)
17580 ;
17581 module.refreshResults();
17582 if(settings.selectFirstResult) {
17583 module.select.firstResult();
17584 }
17585 module.showResults();
17586 }
17587 else {
17588 module.hideResults(function() {
17589 $results.empty();
17590 });
17591 }
17592 },
17593
17594 showResults: function(callback) {
17595 callback = $.isFunction(callback)
17596 ? callback
17597 : function(){}
17598 ;
17599 if(resultsDismissed) {
17600 return;
17601 }
17602 if(!module.is.visible() && module.has.results()) {
17603 if( module.can.transition() ) {
17604 module.debug('Showing results with css animations');
17605 $results
17606 .transition({
17607 animation : settings.transition + ' in',
17608 debug : settings.debug,
17609 verbose : settings.verbose,
17610 duration : settings.duration,
17611 onComplete : function() {
17612 callback();
17613 },
17614 queue : true
17615 })
17616 ;
17617 }
17618 else {
17619 module.debug('Showing results with javascript');
17620 $results
17621 .stop()
17622 .fadeIn(settings.duration, settings.easing)
17623 ;
17624 }
17625 settings.onResultsOpen.call($results);
17626 }
17627 },
17628 hideResults: function(callback) {
17629 callback = $.isFunction(callback)
17630 ? callback
17631 : function(){}
17632 ;
17633 if( module.is.visible() ) {
17634 if( module.can.transition() ) {
17635 module.debug('Hiding results with css animations');
17636 $results
17637 .transition({
17638 animation : settings.transition + ' out',
17639 debug : settings.debug,
17640 verbose : settings.verbose,
17641 duration : settings.duration,
17642 onComplete : function() {
17643 callback();
17644 },
17645 queue : true
17646 })
17647 ;
17648 }
17649 else {
17650 module.debug('Hiding results with javascript');
17651 $results
17652 .stop()
17653 .fadeOut(settings.duration, settings.easing)
17654 ;
17655 }
17656 settings.onResultsClose.call($results);
17657 }
17658 },
17659
17660 generateResults: function(response) {
17661 module.debug('Generating html from response', response);
17662 var
17663 template = settings.templates[settings.type],
17664 isProperObject = ($.isPlainObject(response[fields.results]) && !$.isEmptyObject(response[fields.results])),
17665 isProperArray = (Array.isArray(response[fields.results]) && response[fields.results].length > 0),
17666 html = ''
17667 ;
17668 if(isProperObject || isProperArray ) {
17669 if(settings.maxResults > 0) {
17670 if(isProperObject) {
17671 if(settings.type == 'standard') {
17672 module.error(error.maxResults);
17673 }
17674 }
17675 else {
17676 response[fields.results] = response[fields.results].slice(0, settings.maxResults);
17677 }
17678 }
17679 if($.isFunction(template)) {
17680 html = template(response, fields, settings.preserveHTML);
17681 }
17682 else {
17683 module.error(error.noTemplate, false);
17684 }
17685 }
17686 else if(settings.showNoResults) {
17687 html = module.displayMessage(error.noResults, 'empty', error.noResultsHeader);
17688 }
17689 settings.onResults.call(element, response);
17690 return html;
17691 },
17692
17693 displayMessage: function(text, type, header) {
17694 type = type || 'standard';
17695 module.debug('Displaying message', text, type, header);
17696 module.addResults( settings.templates.message(text, type, header) );
17697 return settings.templates.message(text, type, header);
17698 },
17699
17700 setting: function(name, value) {
17701 if( $.isPlainObject(name) ) {
17702 $.extend(true, settings, name);
17703 }
17704 else if(value !== undefined) {
17705 settings[name] = value;
17706 }
17707 else {
17708 return settings[name];
17709 }
17710 },
17711 internal: function(name, value) {
17712 if( $.isPlainObject(name) ) {
17713 $.extend(true, module, name);
17714 }
17715 else if(value !== undefined) {
17716 module[name] = value;
17717 }
17718 else {
17719 return module[name];
17720 }
17721 },
17722 debug: function() {
17723 if(!settings.silent && settings.debug) {
17724 if(settings.performance) {
17725 module.performance.log(arguments);
17726 }
17727 else {
17728 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
17729 module.debug.apply(console, arguments);
17730 }
17731 }
17732 },
17733 verbose: function() {
17734 if(!settings.silent && settings.verbose && settings.debug) {
17735 if(settings.performance) {
17736 module.performance.log(arguments);
17737 }
17738 else {
17739 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
17740 module.verbose.apply(console, arguments);
17741 }
17742 }
17743 },
17744 error: function() {
17745 if(!settings.silent) {
17746 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
17747 module.error.apply(console, arguments);
17748 }
17749 },
17750 performance: {
17751 log: function(message) {
17752 var
17753 currentTime,
17754 executionTime,
17755 previousTime
17756 ;
17757 if(settings.performance) {
17758 currentTime = new Date().getTime();
17759 previousTime = time || currentTime;
17760 executionTime = currentTime - previousTime;
17761 time = currentTime;
17762 performance.push({
17763 'Name' : message[0],
17764 'Arguments' : [].slice.call(message, 1) || '',
17765 'Element' : element,
17766 'Execution Time' : executionTime
17767 });
17768 }
17769 clearTimeout(module.performance.timer);
17770 module.performance.timer = setTimeout(module.performance.display, 500);
17771 },
17772 display: function() {
17773 var
17774 title = settings.name + ':',
17775 totalTime = 0
17776 ;
17777 time = false;
17778 clearTimeout(module.performance.timer);
17779 $.each(performance, function(index, data) {
17780 totalTime += data['Execution Time'];
17781 });
17782 title += ' ' + totalTime + 'ms';
17783 if(moduleSelector) {
17784 title += ' \'' + moduleSelector + '\'';
17785 }
17786 if($allModules.length > 1) {
17787 title += ' ' + '(' + $allModules.length + ')';
17788 }
17789 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
17790 console.groupCollapsed(title);
17791 if(console.table) {
17792 console.table(performance);
17793 }
17794 else {
17795 $.each(performance, function(index, data) {
17796 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
17797 });
17798 }
17799 console.groupEnd();
17800 }
17801 performance = [];
17802 }
17803 },
17804 invoke: function(query, passedArguments, context) {
17805 var
17806 object = instance,
17807 maxDepth,
17808 found,
17809 response
17810 ;
17811 passedArguments = passedArguments || queryArguments;
17812 context = element || context;
17813 if(typeof query == 'string' && object !== undefined) {
17814 query = query.split(/[\. ]/);
17815 maxDepth = query.length - 1;
17816 $.each(query, function(depth, value) {
17817 var camelCaseValue = (depth != maxDepth)
17818 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
17819 : query
17820 ;
17821 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
17822 object = object[camelCaseValue];
17823 }
17824 else if( object[camelCaseValue] !== undefined ) {
17825 found = object[camelCaseValue];
17826 return false;
17827 }
17828 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
17829 object = object[value];
17830 }
17831 else if( object[value] !== undefined ) {
17832 found = object[value];
17833 return false;
17834 }
17835 else {
17836 return false;
17837 }
17838 });
17839 }
17840 if( $.isFunction( found ) ) {
17841 response = found.apply(context, passedArguments);
17842 }
17843 else if(found !== undefined) {
17844 response = found;
17845 }
17846 if(Array.isArray(returnedValue)) {
17847 returnedValue.push(response);
17848 }
17849 else if(returnedValue !== undefined) {
17850 returnedValue = [returnedValue, response];
17851 }
17852 else if(response !== undefined) {
17853 returnedValue = response;
17854 }
17855 return found;
17856 }
17857 };
17858 if(methodInvoked) {
17859 if(instance === undefined) {
17860 module.initialize();
17861 }
17862 module.invoke(query);
17863 }
17864 else {
17865 if(instance !== undefined) {
17866 instance.invoke('destroy');
17867 }
17868 module.initialize();
17869 }
17870
17871 })
17872 ;
17873
17874 return (returnedValue !== undefined)
17875 ? returnedValue
17876 : this
17877 ;
17878};
17879
17880$.fn.search.settings = {
17881
17882 name : 'Search',
17883 namespace : 'search',
17884
17885 silent : false,
17886 debug : false,
17887 verbose : false,
17888 performance : true,
17889
17890 // template to use (specified in settings.templates)
17891 type : 'standard',
17892
17893 // minimum characters required to search
17894 minCharacters : 1,
17895
17896 // whether to select first result after searching automatically
17897 selectFirstResult : false,
17898
17899 // API config
17900 apiSettings : false,
17901
17902 // object to search
17903 source : false,
17904
17905 // Whether search should query current term on focus
17906 searchOnFocus : true,
17907
17908 // fields to search
17909 searchFields : [
17910 'title',
17911 'description'
17912 ],
17913
17914 // field to display in standard results template
17915 displayField : '',
17916
17917 // search anywhere in value (set to 'exact' to require exact matches
17918 fullTextSearch : 'exact',
17919
17920 // match results also if they contain diacritics of the same base character (for example searching for "a" will also match "á" or "â" or "à", etc...)
17921 ignoreDiacritics : false,
17922
17923 // whether to add events to prompt automatically
17924 automatic : true,
17925
17926 // delay before hiding menu after blur
17927 hideDelay : 0,
17928
17929 // delay before searching
17930 searchDelay : 200,
17931
17932 // maximum results returned from search
17933 maxResults : 7,
17934
17935 // whether to store lookups in local cache
17936 cache : true,
17937
17938 // whether no results errors should be shown
17939 showNoResults : true,
17940
17941 // preserve possible html of resultset values
17942 preserveHTML : true,
17943
17944 // transition settings
17945 transition : 'scale',
17946 duration : 200,
17947 easing : 'easeOutExpo',
17948
17949 // callbacks
17950 onSelect : false,
17951 onResultsAdd : false,
17952
17953 onSearchQuery : function(query){},
17954 onResults : function(response){},
17955
17956 onResultsOpen : function(){},
17957 onResultsClose : function(){},
17958
17959 className: {
17960 animating : 'animating',
17961 active : 'active',
17962 empty : 'empty',
17963 focus : 'focus',
17964 hidden : 'hidden',
17965 loading : 'loading',
17966 results : 'results',
17967 pressed : 'down'
17968 },
17969
17970 error : {
17971 source : 'Cannot search. No source used, and Semantic API module was not included',
17972 noResultsHeader : 'No Results',
17973 noResults : 'Your search returned no results',
17974 logging : 'Error in debug logging, exiting.',
17975 noEndpoint : 'No search endpoint was specified',
17976 noTemplate : 'A valid template name was not specified.',
17977 oldSearchSyntax : 'searchFullText setting has been renamed fullTextSearch for consistency, please adjust your settings.',
17978 serverError : 'There was an issue querying the server.',
17979 maxResults : 'Results must be an array to use maxResults setting',
17980 method : 'The method you called is not defined.',
17981 noNormalize : '"ignoreDiacritics" setting will be ignored. Browser does not support String().normalize(). You may consider including <https://cdn.jsdelivr.net/npm/unorm@1.4.1/lib/unorm.min.js> as a polyfill.'
17982 },
17983
17984 metadata: {
17985 cache : 'cache',
17986 results : 'results',
17987 result : 'result'
17988 },
17989
17990 regExp: {
17991 escape : /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,
17992 beginsWith : '(?:\s|^)'
17993 },
17994
17995 // maps api response attributes to internal representation
17996 fields: {
17997 categories : 'results', // array of categories (category view)
17998 categoryName : 'name', // name of category (category view)
17999 categoryResults : 'results', // array of results (category view)
18000 description : 'description', // result description
18001 image : 'image', // result image
18002 price : 'price', // result price
18003 results : 'results', // array of results (standard)
18004 title : 'title', // result title
18005 url : 'url', // result url
18006 action : 'action', // "view more" object name
18007 actionText : 'text', // "view more" text
18008 actionURL : 'url' // "view more" url
18009 },
18010
18011 selector : {
18012 prompt : '.prompt',
18013 searchButton : '.search.button',
18014 results : '.results',
18015 message : '.results > .message',
18016 category : '.category',
18017 result : '.result',
18018 title : '.title, .name'
18019 },
18020
18021 templates: {
18022 escape: function(string, preserveHTML) {
18023 if (preserveHTML){
18024 return string;
18025 }
18026 var
18027 badChars = /[&<>"'`]/g,
18028 shouldEscape = /[&<>"'`]/,
18029 escape = {
18030 "&": "&amp;",
18031 "<": "&lt;",
18032 ">": "&gt;",
18033 '"': "&quot;",
18034 "'": "&#x27;",
18035 "`": "&#x60;"
18036 },
18037 escapedChar = function(chr) {
18038 return escape[chr];
18039 }
18040 ;
18041 if(shouldEscape.test(string)) {
18042 return string.replace(badChars, escapedChar);
18043 }
18044 return string;
18045 },
18046 message: function(message, type, header) {
18047 var
18048 html = ''
18049 ;
18050 if(message !== undefined && type !== undefined) {
18051 html += ''
18052 + '<div class="message ' + type + '">'
18053 ;
18054 if(header) {
18055 html += ''
18056 + '<div class="header">' + header + '</div>'
18057 ;
18058 }
18059 html += ' <div class="description">' + message + '</div>';
18060 html += '</div>';
18061 }
18062 return html;
18063 },
18064 category: function(response, fields, preserveHTML) {
18065 var
18066 html = '',
18067 escape = $.fn.search.settings.templates.escape
18068 ;
18069 if(response[fields.categoryResults] !== undefined) {
18070
18071 // each category
18072 $.each(response[fields.categoryResults], function(index, category) {
18073 if(category[fields.results] !== undefined && category.results.length > 0) {
18074
18075 html += '<div class="category">';
18076
18077 if(category[fields.categoryName] !== undefined) {
18078 html += '<div class="name">' + escape(category[fields.categoryName], preserveHTML) + '</div>';
18079 }
18080
18081 // each item inside category
18082 html += '<div class="results">';
18083 $.each(category.results, function(index, result) {
18084 if(result[fields.url]) {
18085 html += '<a class="result" href="' + result[fields.url].replace(/"/g,"") + '">';
18086 }
18087 else {
18088 html += '<a class="result">';
18089 }
18090 if(result[fields.image] !== undefined) {
18091 html += ''
18092 + '<div class="image">'
18093 + ' <img src="' + result[fields.image].replace(/"/g,"") + '">'
18094 + '</div>'
18095 ;
18096 }
18097 html += '<div class="content">';
18098 if(result[fields.price] !== undefined) {
18099 html += '<div class="price">' + escape(result[fields.price], preserveHTML) + '</div>';
18100 }
18101 if(result[fields.title] !== undefined) {
18102 html += '<div class="title">' + escape(result[fields.title], preserveHTML) + '</div>';
18103 }
18104 if(result[fields.description] !== undefined) {
18105 html += '<div class="description">' + escape(result[fields.description], preserveHTML) + '</div>';
18106 }
18107 html += ''
18108 + '</div>'
18109 ;
18110 html += '</a>';
18111 });
18112 html += '</div>';
18113 html += ''
18114 + '</div>'
18115 ;
18116 }
18117 });
18118 if(response[fields.action]) {
18119 if(fields.actionURL === false) {
18120 html += ''
18121 + '<div class="action">'
18122 + escape(response[fields.action][fields.actionText], preserveHTML)
18123 + '</div>';
18124 } else {
18125 html += ''
18126 + '<a href="' + response[fields.action][fields.actionURL].replace(/"/g,"") + '" class="action">'
18127 + escape(response[fields.action][fields.actionText], preserveHTML)
18128 + '</a>';
18129 }
18130 }
18131 return html;
18132 }
18133 return false;
18134 },
18135 standard: function(response, fields, preserveHTML) {
18136 var
18137 html = '',
18138 escape = $.fn.search.settings.templates.escape
18139 ;
18140 if(response[fields.results] !== undefined) {
18141
18142 // each result
18143 $.each(response[fields.results], function(index, result) {
18144 if(result[fields.url]) {
18145 html += '<a class="result" href="' + result[fields.url].replace(/"/g,"") + '">';
18146 }
18147 else {
18148 html += '<a class="result">';
18149 }
18150 if(result[fields.image] !== undefined) {
18151 html += ''
18152 + '<div class="image">'
18153 + ' <img src="' + result[fields.image].replace(/"/g,"") + '">'
18154 + '</div>'
18155 ;
18156 }
18157 html += '<div class="content">';
18158 if(result[fields.price] !== undefined) {
18159 html += '<div class="price">' + escape(result[fields.price], preserveHTML) + '</div>';
18160 }
18161 if(result[fields.title] !== undefined) {
18162 html += '<div class="title">' + escape(result[fields.title], preserveHTML) + '</div>';
18163 }
18164 if(result[fields.description] !== undefined) {
18165 html += '<div class="description">' + escape(result[fields.description], preserveHTML) + '</div>';
18166 }
18167 html += ''
18168 + '</div>'
18169 ;
18170 html += '</a>';
18171 });
18172 if(response[fields.action]) {
18173 if(fields.actionURL === false) {
18174 html += ''
18175 + '<div class="action">'
18176 + escape(response[fields.action][fields.actionText], preserveHTML)
18177 + '</div>';
18178 } else {
18179 html += ''
18180 + '<a href="' + response[fields.action][fields.actionURL].replace(/"/g,"") + '" class="action">'
18181 + escape(response[fields.action][fields.actionText], preserveHTML)
18182 + '</a>';
18183 }
18184 }
18185 return html;
18186 }
18187 return false;
18188 }
18189 }
18190};
18191
18192})( jQuery, window, document );
18193
18194/*!
18195 * # Semantic UI 2.7.2 - Shape
18196 * http://github.com/semantic-org/semantic-ui/
18197 *
18198 *
18199 * Released under the MIT license
18200 * http://opensource.org/licenses/MIT
18201 *
18202 */
18203
18204;(function ($, window, document, undefined) {
18205
18206'use strict';
18207
18208$.isFunction = $.isFunction || function(obj) {
18209 return typeof obj === "function" && typeof obj.nodeType !== "number";
18210};
18211
18212window = (typeof window != 'undefined' && window.Math == Math)
18213 ? window
18214 : (typeof self != 'undefined' && self.Math == Math)
18215 ? self
18216 : Function('return this')()
18217;
18218
18219$.fn.shape = function(parameters) {
18220 var
18221 $allModules = $(this),
18222 $body = $('body'),
18223
18224 time = new Date().getTime(),
18225 performance = [],
18226
18227 query = arguments[0],
18228 methodInvoked = (typeof query == 'string'),
18229 queryArguments = [].slice.call(arguments, 1),
18230
18231 requestAnimationFrame = window.requestAnimationFrame
18232 || window.mozRequestAnimationFrame
18233 || window.webkitRequestAnimationFrame
18234 || window.msRequestAnimationFrame
18235 || function(callback) { setTimeout(callback, 0); },
18236
18237 returnedValue
18238 ;
18239
18240 $allModules
18241 .each(function() {
18242 var
18243 moduleSelector = $allModules.selector || '',
18244 settings = ( $.isPlainObject(parameters) )
18245 ? $.extend(true, {}, $.fn.shape.settings, parameters)
18246 : $.extend({}, $.fn.shape.settings),
18247
18248 // internal aliases
18249 namespace = settings.namespace,
18250 selector = settings.selector,
18251 error = settings.error,
18252 className = settings.className,
18253
18254 // define namespaces for modules
18255 eventNamespace = '.' + namespace,
18256 moduleNamespace = 'module-' + namespace,
18257
18258 // selector cache
18259 $module = $(this),
18260 $sides = $module.find(selector.sides),
18261 $side = $module.find(selector.side),
18262
18263 // private variables
18264 nextIndex = false,
18265 $activeSide,
18266 $nextSide,
18267
18268 // standard module
18269 element = this,
18270 instance = $module.data(moduleNamespace),
18271 module
18272 ;
18273
18274 module = {
18275
18276 initialize: function() {
18277 module.verbose('Initializing module for', element);
18278 module.set.defaultSide();
18279 module.instantiate();
18280 },
18281
18282 instantiate: function() {
18283 module.verbose('Storing instance of module', module);
18284 instance = module;
18285 $module
18286 .data(moduleNamespace, instance)
18287 ;
18288 },
18289
18290 destroy: function() {
18291 module.verbose('Destroying previous module for', element);
18292 $module
18293 .removeData(moduleNamespace)
18294 .off(eventNamespace)
18295 ;
18296 },
18297
18298 refresh: function() {
18299 module.verbose('Refreshing selector cache for', element);
18300 $module = $(element);
18301 $sides = $(this).find(selector.shape);
18302 $side = $(this).find(selector.side);
18303 },
18304
18305 repaint: function() {
18306 module.verbose('Forcing repaint event');
18307 var
18308 shape = $sides[0] || document.createElement('div'),
18309 fakeAssignment = shape.offsetWidth
18310 ;
18311 },
18312
18313 animate: function(propertyObject, callback) {
18314 module.verbose('Animating box with properties', propertyObject);
18315 callback = callback || function(event) {
18316 module.verbose('Executing animation callback');
18317 if(event !== undefined) {
18318 event.stopPropagation();
18319 }
18320 module.reset();
18321 module.set.active();
18322 };
18323 settings.beforeChange.call($nextSide[0]);
18324 if(module.get.transitionEvent()) {
18325 module.verbose('Starting CSS animation');
18326 $module
18327 .addClass(className.animating)
18328 ;
18329 $sides
18330 .css(propertyObject)
18331 .one(module.get.transitionEvent(), callback)
18332 ;
18333 module.set.duration(settings.duration);
18334 requestAnimationFrame(function() {
18335 $module
18336 .addClass(className.animating)
18337 ;
18338 $activeSide
18339 .addClass(className.hidden)
18340 ;
18341 });
18342 }
18343 else {
18344 callback();
18345 }
18346 },
18347
18348 queue: function(method) {
18349 module.debug('Queueing animation of', method);
18350 $sides
18351 .one(module.get.transitionEvent(), function() {
18352 module.debug('Executing queued animation');
18353 setTimeout(function(){
18354 $module.shape(method);
18355 }, 0);
18356 })
18357 ;
18358 },
18359
18360 reset: function() {
18361 module.verbose('Animating states reset');
18362 $module
18363 .removeClass(className.animating)
18364 .attr('style', '')
18365 .removeAttr('style')
18366 ;
18367 // removeAttr style does not consistently work in safari
18368 $sides
18369 .attr('style', '')
18370 .removeAttr('style')
18371 ;
18372 $side
18373 .attr('style', '')
18374 .removeAttr('style')
18375 .removeClass(className.hidden)
18376 ;
18377 $nextSide
18378 .removeClass(className.animating)
18379 .attr('style', '')
18380 .removeAttr('style')
18381 ;
18382 },
18383
18384 is: {
18385 complete: function() {
18386 return ($side.filter('.' + className.active)[0] == $nextSide[0]);
18387 },
18388 animating: function() {
18389 return $module.hasClass(className.animating);
18390 }
18391 },
18392
18393 set: {
18394
18395 defaultSide: function() {
18396 $activeSide = $module.find('.' + settings.className.active);
18397 $nextSide = ( $activeSide.next(selector.side).length > 0 )
18398 ? $activeSide.next(selector.side)
18399 : $module.find(selector.side).first()
18400 ;
18401 nextIndex = false;
18402 module.verbose('Active side set to', $activeSide);
18403 module.verbose('Next side set to', $nextSide);
18404 },
18405
18406 duration: function(duration) {
18407 duration = duration || settings.duration;
18408 duration = (typeof duration == 'number')
18409 ? duration + 'ms'
18410 : duration
18411 ;
18412 module.verbose('Setting animation duration', duration);
18413 if(settings.duration || settings.duration === 0) {
18414 $sides.add($side)
18415 .css({
18416 '-webkit-transition-duration': duration,
18417 '-moz-transition-duration': duration,
18418 '-ms-transition-duration': duration,
18419 '-o-transition-duration': duration,
18420 'transition-duration': duration
18421 })
18422 ;
18423 }
18424 },
18425
18426 currentStageSize: function() {
18427 var
18428 $activeSide = $module.find('.' + settings.className.active),
18429 width = $activeSide.outerWidth(true),
18430 height = $activeSide.outerHeight(true)
18431 ;
18432 $module
18433 .css({
18434 width: width,
18435 height: height
18436 })
18437 ;
18438 },
18439
18440 stageSize: function() {
18441 var
18442 $clone = $module.clone().addClass(className.loading),
18443 $activeSide = $clone.find('.' + settings.className.active),
18444 $nextSide = (nextIndex)
18445 ? $clone.find(selector.side).eq(nextIndex)
18446 : ( $activeSide.next(selector.side).length > 0 )
18447 ? $activeSide.next(selector.side)
18448 : $clone.find(selector.side).first(),
18449 newWidth = (settings.width == 'next')
18450 ? $nextSide.outerWidth(true)
18451 : (settings.width == 'initial')
18452 ? $module.width()
18453 : settings.width,
18454 newHeight = (settings.height == 'next')
18455 ? $nextSide.outerHeight(true)
18456 : (settings.height == 'initial')
18457 ? $module.height()
18458 : settings.height
18459 ;
18460 $activeSide.removeClass(className.active);
18461 $nextSide.addClass(className.active);
18462 $clone.insertAfter($module);
18463 $clone.remove();
18464 if(settings.width != 'auto') {
18465 $module.css('width', newWidth + settings.jitter);
18466 module.verbose('Specifying width during animation', newWidth);
18467 }
18468 if(settings.height != 'auto') {
18469 $module.css('height', newHeight + settings.jitter);
18470 module.verbose('Specifying height during animation', newHeight);
18471 }
18472 },
18473
18474 nextSide: function(selector) {
18475 nextIndex = selector;
18476 $nextSide = $side.filter(selector);
18477 nextIndex = $side.index($nextSide);
18478 if($nextSide.length === 0) {
18479 module.set.defaultSide();
18480 module.error(error.side);
18481 }
18482 module.verbose('Next side manually set to', $nextSide);
18483 },
18484
18485 active: function() {
18486 module.verbose('Setting new side to active', $nextSide);
18487 $side
18488 .removeClass(className.active)
18489 ;
18490 $nextSide
18491 .addClass(className.active)
18492 ;
18493 settings.onChange.call($nextSide[0]);
18494 module.set.defaultSide();
18495 }
18496 },
18497
18498 flip: {
18499
18500 up: function() {
18501 if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
18502 module.debug('Side already visible', $nextSide);
18503 return;
18504 }
18505 if( !module.is.animating()) {
18506 module.debug('Flipping up', $nextSide);
18507 var
18508 transform = module.get.transform.up()
18509 ;
18510 module.set.stageSize();
18511 module.stage.above();
18512 module.animate(transform);
18513 }
18514 else {
18515 module.queue('flip up');
18516 }
18517 },
18518
18519 down: function() {
18520 if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
18521 module.debug('Side already visible', $nextSide);
18522 return;
18523 }
18524 if( !module.is.animating()) {
18525 module.debug('Flipping down', $nextSide);
18526 var
18527 transform = module.get.transform.down()
18528 ;
18529 module.set.stageSize();
18530 module.stage.below();
18531 module.animate(transform);
18532 }
18533 else {
18534 module.queue('flip down');
18535 }
18536 },
18537
18538 left: function() {
18539 if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
18540 module.debug('Side already visible', $nextSide);
18541 return;
18542 }
18543 if( !module.is.animating()) {
18544 module.debug('Flipping left', $nextSide);
18545 var
18546 transform = module.get.transform.left()
18547 ;
18548 module.set.stageSize();
18549 module.stage.left();
18550 module.animate(transform);
18551 }
18552 else {
18553 module.queue('flip left');
18554 }
18555 },
18556
18557 right: function() {
18558 if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
18559 module.debug('Side already visible', $nextSide);
18560 return;
18561 }
18562 if( !module.is.animating()) {
18563 module.debug('Flipping right', $nextSide);
18564 var
18565 transform = module.get.transform.right()
18566 ;
18567 module.set.stageSize();
18568 module.stage.right();
18569 module.animate(transform);
18570 }
18571 else {
18572 module.queue('flip right');
18573 }
18574 },
18575
18576 over: function() {
18577 if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
18578 module.debug('Side already visible', $nextSide);
18579 return;
18580 }
18581 if( !module.is.animating()) {
18582 module.debug('Flipping over', $nextSide);
18583 module.set.stageSize();
18584 module.stage.behind();
18585 module.animate(module.get.transform.over() );
18586 }
18587 else {
18588 module.queue('flip over');
18589 }
18590 },
18591
18592 back: function() {
18593 if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
18594 module.debug('Side already visible', $nextSide);
18595 return;
18596 }
18597 if( !module.is.animating()) {
18598 module.debug('Flipping back', $nextSide);
18599 module.set.stageSize();
18600 module.stage.behind();
18601 module.animate(module.get.transform.back() );
18602 }
18603 else {
18604 module.queue('flip back');
18605 }
18606 }
18607
18608 },
18609
18610 get: {
18611
18612 transform: {
18613 up: function() {
18614 var
18615 translate = {
18616 y: -(($activeSide.outerHeight(true) - $nextSide.outerHeight(true)) / 2),
18617 z: -($activeSide.outerHeight(true) / 2)
18618 }
18619 ;
18620 return {
18621 transform: 'translateY(' + translate.y + 'px) translateZ('+ translate.z + 'px) rotateX(-90deg)'
18622 };
18623 },
18624
18625 down: function() {
18626 var
18627 translate = {
18628 y: -(($activeSide.outerHeight(true) - $nextSide.outerHeight(true)) / 2),
18629 z: -($activeSide.outerHeight(true) / 2)
18630 }
18631 ;
18632 return {
18633 transform: 'translateY(' + translate.y + 'px) translateZ('+ translate.z + 'px) rotateX(90deg)'
18634 };
18635 },
18636
18637 left: function() {
18638 var
18639 translate = {
18640 x : -(($activeSide.outerWidth(true) - $nextSide.outerWidth(true)) / 2),
18641 z : -($activeSide.outerWidth(true) / 2)
18642 }
18643 ;
18644 return {
18645 transform: 'translateX(' + translate.x + 'px) translateZ(' + translate.z + 'px) rotateY(90deg)'
18646 };
18647 },
18648
18649 right: function() {
18650 var
18651 translate = {
18652 x : -(($activeSide.outerWidth(true) - $nextSide.outerWidth(true)) / 2),
18653 z : -($activeSide.outerWidth(true) / 2)
18654 }
18655 ;
18656 return {
18657 transform: 'translateX(' + translate.x + 'px) translateZ(' + translate.z + 'px) rotateY(-90deg)'
18658 };
18659 },
18660
18661 over: function() {
18662 var
18663 translate = {
18664 x : -(($activeSide.outerWidth(true) - $nextSide.outerWidth(true)) / 2)
18665 }
18666 ;
18667 return {
18668 transform: 'translateX(' + translate.x + 'px) rotateY(180deg)'
18669 };
18670 },
18671
18672 back: function() {
18673 var
18674 translate = {
18675 x : -(($activeSide.outerWidth(true) - $nextSide.outerWidth(true)) / 2)
18676 }
18677 ;
18678 return {
18679 transform: 'translateX(' + translate.x + 'px) rotateY(-180deg)'
18680 };
18681 }
18682 },
18683
18684 transitionEvent: function() {
18685 var
18686 element = document.createElement('element'),
18687 transitions = {
18688 'transition' :'transitionend',
18689 'OTransition' :'oTransitionEnd',
18690 'MozTransition' :'transitionend',
18691 'WebkitTransition' :'webkitTransitionEnd'
18692 },
18693 transition
18694 ;
18695 for(transition in transitions){
18696 if( element.style[transition] !== undefined ){
18697 return transitions[transition];
18698 }
18699 }
18700 },
18701
18702 nextSide: function() {
18703 return ( $activeSide.next(selector.side).length > 0 )
18704 ? $activeSide.next(selector.side)
18705 : $module.find(selector.side).first()
18706 ;
18707 }
18708
18709 },
18710
18711 stage: {
18712
18713 above: function() {
18714 var
18715 box = {
18716 origin : (($activeSide.outerHeight(true) - $nextSide.outerHeight(true)) / 2),
18717 depth : {
18718 active : ($nextSide.outerHeight(true) / 2),
18719 next : ($activeSide.outerHeight(true) / 2)
18720 }
18721 }
18722 ;
18723 module.verbose('Setting the initial animation position as above', $nextSide, box);
18724 $sides
18725 .css({
18726 'transform' : 'translateZ(-' + box.depth.active + 'px)'
18727 })
18728 ;
18729 $activeSide
18730 .css({
18731 'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)'
18732 })
18733 ;
18734 $nextSide
18735 .addClass(className.animating)
18736 .css({
18737 'top' : box.origin + 'px',
18738 'transform' : 'rotateX(90deg) translateZ(' + box.depth.next + 'px)'
18739 })
18740 ;
18741 },
18742
18743 below: function() {
18744 var
18745 box = {
18746 origin : (($activeSide.outerHeight(true) - $nextSide.outerHeight(true)) / 2),
18747 depth : {
18748 active : ($nextSide.outerHeight(true) / 2),
18749 next : ($activeSide.outerHeight(true) / 2)
18750 }
18751 }
18752 ;
18753 module.verbose('Setting the initial animation position as below', $nextSide, box);
18754 $sides
18755 .css({
18756 'transform' : 'translateZ(-' + box.depth.active + 'px)'
18757 })
18758 ;
18759 $activeSide
18760 .css({
18761 'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)'
18762 })
18763 ;
18764 $nextSide
18765 .addClass(className.animating)
18766 .css({
18767 'top' : box.origin + 'px',
18768 'transform' : 'rotateX(-90deg) translateZ(' + box.depth.next + 'px)'
18769 })
18770 ;
18771 },
18772
18773 left: function() {
18774 var
18775 height = {
18776 active : $activeSide.outerWidth(true),
18777 next : $nextSide.outerWidth(true)
18778 },
18779 box = {
18780 origin : ( ( height.active - height.next ) / 2),
18781 depth : {
18782 active : (height.next / 2),
18783 next : (height.active / 2)
18784 }
18785 }
18786 ;
18787 module.verbose('Setting the initial animation position as left', $nextSide, box);
18788 $sides
18789 .css({
18790 'transform' : 'translateZ(-' + box.depth.active + 'px)'
18791 })
18792 ;
18793 $activeSide
18794 .css({
18795 'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)'
18796 })
18797 ;
18798 $nextSide
18799 .addClass(className.animating)
18800 .css({
18801 'left' : box.origin + 'px',
18802 'transform' : 'rotateY(-90deg) translateZ(' + box.depth.next + 'px)'
18803 })
18804 ;
18805 },
18806
18807 right: function() {
18808 var
18809 height = {
18810 active : $activeSide.outerWidth(true),
18811 next : $nextSide.outerWidth(true)
18812 },
18813 box = {
18814 origin : ( ( height.active - height.next ) / 2),
18815 depth : {
18816 active : (height.next / 2),
18817 next : (height.active / 2)
18818 }
18819 }
18820 ;
18821 module.verbose('Setting the initial animation position as left', $nextSide, box);
18822 $sides
18823 .css({
18824 'transform' : 'translateZ(-' + box.depth.active + 'px)'
18825 })
18826 ;
18827 $activeSide
18828 .css({
18829 'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)'
18830 })
18831 ;
18832 $nextSide
18833 .addClass(className.animating)
18834 .css({
18835 'left' : box.origin + 'px',
18836 'transform' : 'rotateY(90deg) translateZ(' + box.depth.next + 'px)'
18837 })
18838 ;
18839 },
18840
18841 behind: function() {
18842 var
18843 height = {
18844 active : $activeSide.outerWidth(true),
18845 next : $nextSide.outerWidth(true)
18846 },
18847 box = {
18848 origin : ( ( height.active - height.next ) / 2),
18849 depth : {
18850 active : (height.next / 2),
18851 next : (height.active / 2)
18852 }
18853 }
18854 ;
18855 module.verbose('Setting the initial animation position as behind', $nextSide, box);
18856 $activeSide
18857 .css({
18858 'transform' : 'rotateY(0deg)'
18859 })
18860 ;
18861 $nextSide
18862 .addClass(className.animating)
18863 .css({
18864 'left' : box.origin + 'px',
18865 'transform' : 'rotateY(-180deg)'
18866 })
18867 ;
18868 }
18869 },
18870 setting: function(name, value) {
18871 module.debug('Changing setting', name, value);
18872 if( $.isPlainObject(name) ) {
18873 $.extend(true, settings, name);
18874 }
18875 else if(value !== undefined) {
18876 if($.isPlainObject(settings[name])) {
18877 $.extend(true, settings[name], value);
18878 }
18879 else {
18880 settings[name] = value;
18881 }
18882 }
18883 else {
18884 return settings[name];
18885 }
18886 },
18887 internal: function(name, value) {
18888 if( $.isPlainObject(name) ) {
18889 $.extend(true, module, name);
18890 }
18891 else if(value !== undefined) {
18892 module[name] = value;
18893 }
18894 else {
18895 return module[name];
18896 }
18897 },
18898 debug: function() {
18899 if(!settings.silent && settings.debug) {
18900 if(settings.performance) {
18901 module.performance.log(arguments);
18902 }
18903 else {
18904 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
18905 module.debug.apply(console, arguments);
18906 }
18907 }
18908 },
18909 verbose: function() {
18910 if(!settings.silent && settings.verbose && settings.debug) {
18911 if(settings.performance) {
18912 module.performance.log(arguments);
18913 }
18914 else {
18915 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
18916 module.verbose.apply(console, arguments);
18917 }
18918 }
18919 },
18920 error: function() {
18921 if(!settings.silent) {
18922 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
18923 module.error.apply(console, arguments);
18924 }
18925 },
18926 performance: {
18927 log: function(message) {
18928 var
18929 currentTime,
18930 executionTime,
18931 previousTime
18932 ;
18933 if(settings.performance) {
18934 currentTime = new Date().getTime();
18935 previousTime = time || currentTime;
18936 executionTime = currentTime - previousTime;
18937 time = currentTime;
18938 performance.push({
18939 'Name' : message[0],
18940 'Arguments' : [].slice.call(message, 1) || '',
18941 'Element' : element,
18942 'Execution Time' : executionTime
18943 });
18944 }
18945 clearTimeout(module.performance.timer);
18946 module.performance.timer = setTimeout(module.performance.display, 500);
18947 },
18948 display: function() {
18949 var
18950 title = settings.name + ':',
18951 totalTime = 0
18952 ;
18953 time = false;
18954 clearTimeout(module.performance.timer);
18955 $.each(performance, function(index, data) {
18956 totalTime += data['Execution Time'];
18957 });
18958 title += ' ' + totalTime + 'ms';
18959 if(moduleSelector) {
18960 title += ' \'' + moduleSelector + '\'';
18961 }
18962 if($allModules.length > 1) {
18963 title += ' ' + '(' + $allModules.length + ')';
18964 }
18965 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
18966 console.groupCollapsed(title);
18967 if(console.table) {
18968 console.table(performance);
18969 }
18970 else {
18971 $.each(performance, function(index, data) {
18972 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
18973 });
18974 }
18975 console.groupEnd();
18976 }
18977 performance = [];
18978 }
18979 },
18980 invoke: function(query, passedArguments, context) {
18981 var
18982 object = instance,
18983 maxDepth,
18984 found,
18985 response
18986 ;
18987 passedArguments = passedArguments || queryArguments;
18988 context = element || context;
18989 if(typeof query == 'string' && object !== undefined) {
18990 query = query.split(/[\. ]/);
18991 maxDepth = query.length - 1;
18992 $.each(query, function(depth, value) {
18993 var camelCaseValue = (depth != maxDepth)
18994 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
18995 : query
18996 ;
18997 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
18998 object = object[camelCaseValue];
18999 }
19000 else if( object[camelCaseValue] !== undefined ) {
19001 found = object[camelCaseValue];
19002 return false;
19003 }
19004 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
19005 object = object[value];
19006 }
19007 else if( object[value] !== undefined ) {
19008 found = object[value];
19009 return false;
19010 }
19011 else {
19012 return false;
19013 }
19014 });
19015 }
19016 if ( $.isFunction( found ) ) {
19017 response = found.apply(context, passedArguments);
19018 }
19019 else if(found !== undefined) {
19020 response = found;
19021 }
19022 if(Array.isArray(returnedValue)) {
19023 returnedValue.push(response);
19024 }
19025 else if(returnedValue !== undefined) {
19026 returnedValue = [returnedValue, response];
19027 }
19028 else if(response !== undefined) {
19029 returnedValue = response;
19030 }
19031 return found;
19032 }
19033 };
19034
19035 if(methodInvoked) {
19036 if(instance === undefined) {
19037 module.initialize();
19038 }
19039 module.invoke(query);
19040 }
19041 else {
19042 if(instance !== undefined) {
19043 instance.invoke('destroy');
19044 }
19045 module.initialize();
19046 }
19047 })
19048 ;
19049
19050 return (returnedValue !== undefined)
19051 ? returnedValue
19052 : this
19053 ;
19054};
19055
19056$.fn.shape.settings = {
19057
19058 // module info
19059 name : 'Shape',
19060
19061 // hide all debug content
19062 silent : false,
19063
19064 // debug content outputted to console
19065 debug : false,
19066
19067 // verbose debug output
19068 verbose : false,
19069
19070 // fudge factor in pixels when swapping from 2d to 3d (can be useful to correct rounding errors)
19071 jitter : 0,
19072
19073 // performance data output
19074 performance: true,
19075
19076 // event namespace
19077 namespace : 'shape',
19078
19079 // width during animation, can be set to 'auto', initial', 'next' or pixel amount
19080 width: 'initial',
19081
19082 // height during animation, can be set to 'auto', 'initial', 'next' or pixel amount
19083 height: 'initial',
19084
19085 // callback occurs on side change
19086 beforeChange : function() {},
19087 onChange : function() {},
19088
19089 // allow animation to same side
19090 allowRepeats: false,
19091
19092 // animation duration
19093 duration : false,
19094
19095 // possible errors
19096 error: {
19097 side : 'You tried to switch to a side that does not exist.',
19098 method : 'The method you called is not defined'
19099 },
19100
19101 // classnames used
19102 className : {
19103 animating : 'animating',
19104 hidden : 'hidden',
19105 loading : 'loading',
19106 active : 'active'
19107 },
19108
19109 // selectors used
19110 selector : {
19111 sides : '.sides',
19112 side : '.side'
19113 }
19114
19115};
19116
19117
19118})( jQuery, window, document );
19119
19120/*!
19121 * # Semantic UI 2.7.2 - Sidebar
19122 * http://github.com/semantic-org/semantic-ui/
19123 *
19124 *
19125 * Released under the MIT license
19126 * http://opensource.org/licenses/MIT
19127 *
19128 */
19129
19130;(function ($, window, document, undefined) {
19131
19132'use strict';
19133
19134$.isFunction = $.isFunction || function(obj) {
19135 return typeof obj === "function" && typeof obj.nodeType !== "number";
19136};
19137
19138window = (typeof window != 'undefined' && window.Math == Math)
19139 ? window
19140 : (typeof self != 'undefined' && self.Math == Math)
19141 ? self
19142 : Function('return this')()
19143;
19144
19145$.fn.sidebar = function(parameters) {
19146 var
19147 $allModules = $(this),
19148 $window = $(window),
19149 $document = $(document),
19150 $html = $('html'),
19151 $head = $('head'),
19152
19153 moduleSelector = $allModules.selector || '',
19154
19155 time = new Date().getTime(),
19156 performance = [],
19157
19158 query = arguments[0],
19159 methodInvoked = (typeof query == 'string'),
19160 queryArguments = [].slice.call(arguments, 1),
19161
19162 requestAnimationFrame = window.requestAnimationFrame
19163 || window.mozRequestAnimationFrame
19164 || window.webkitRequestAnimationFrame
19165 || window.msRequestAnimationFrame
19166 || function(callback) { setTimeout(callback, 0); },
19167
19168 returnedValue
19169 ;
19170
19171 $allModules
19172 .each(function() {
19173 var
19174 settings = ( $.isPlainObject(parameters) )
19175 ? $.extend(true, {}, $.fn.sidebar.settings, parameters)
19176 : $.extend({}, $.fn.sidebar.settings),
19177
19178 selector = settings.selector,
19179 className = settings.className,
19180 namespace = settings.namespace,
19181 regExp = settings.regExp,
19182 error = settings.error,
19183
19184 eventNamespace = '.' + namespace,
19185 moduleNamespace = 'module-' + namespace,
19186
19187 $module = $(this),
19188 $context = $(settings.context),
19189
19190 $sidebars = $module.children(selector.sidebar),
19191 $fixed = $context.children(selector.fixed),
19192 $pusher = $context.children(selector.pusher),
19193 $style,
19194
19195 element = this,
19196 instance = $module.data(moduleNamespace),
19197
19198 elementNamespace,
19199 id,
19200 currentScroll,
19201 transitionEvent,
19202
19203 module
19204 ;
19205
19206 module = {
19207
19208 initialize: function() {
19209 module.debug('Initializing sidebar', parameters);
19210
19211 module.create.id();
19212
19213 transitionEvent = module.get.transitionEvent();
19214
19215 // avoids locking rendering if initialized in onReady
19216 if(settings.delaySetup) {
19217 requestAnimationFrame(module.setup.layout);
19218 }
19219 else {
19220 module.setup.layout();
19221 }
19222
19223 requestAnimationFrame(function() {
19224 module.setup.cache();
19225 });
19226
19227 module.instantiate();
19228 },
19229
19230 instantiate: function() {
19231 module.verbose('Storing instance of module', module);
19232 instance = module;
19233 $module
19234 .data(moduleNamespace, module)
19235 ;
19236 },
19237
19238 create: {
19239 id: function() {
19240 id = (Math.random().toString(16) + '000000000').substr(2,8);
19241 elementNamespace = '.' + id;
19242 module.verbose('Creating unique id for element', id);
19243 }
19244 },
19245
19246 destroy: function() {
19247 module.verbose('Destroying previous module for', $module);
19248 $module
19249 .off(eventNamespace)
19250 .removeData(moduleNamespace)
19251 ;
19252 if(module.is.ios()) {
19253 module.remove.ios();
19254 }
19255 // bound by uuid
19256 $context.off(elementNamespace);
19257 $window.off(elementNamespace);
19258 $document.off(elementNamespace);
19259 },
19260
19261 event: {
19262 clickaway: function(event) {
19263 var
19264 clickedInPusher = ($pusher.find(event.target).length > 0 || $pusher.is(event.target)),
19265 clickedContext = ($context.is(event.target))
19266 ;
19267 if(clickedInPusher) {
19268 module.verbose('User clicked on dimmed page');
19269 module.hide();
19270 }
19271 if(clickedContext) {
19272 module.verbose('User clicked on dimmable context (scaled out page)');
19273 module.hide();
19274 }
19275 },
19276 touch: function(event) {
19277 //event.stopPropagation();
19278 },
19279 containScroll: function(event) {
19280 if(element.scrollTop <= 0) {
19281 element.scrollTop = 1;
19282 }
19283 if((element.scrollTop + element.offsetHeight) >= element.scrollHeight) {
19284 element.scrollTop = element.scrollHeight - element.offsetHeight - 1;
19285 }
19286 },
19287 scroll: function(event) {
19288 if( $(event.target).closest(selector.sidebar).length === 0 ) {
19289 event.preventDefault();
19290 }
19291 }
19292 },
19293
19294 bind: {
19295 clickaway: function() {
19296 module.verbose('Adding clickaway events to context', $context);
19297 $context
19298 .on('click' + elementNamespace, module.event.clickaway)
19299 .on('touchend' + elementNamespace, module.event.clickaway)
19300 ;
19301 },
19302 scrollLock: function() {
19303 if(settings.scrollLock) {
19304 module.debug('Disabling page scroll');
19305 $window
19306 .on('DOMMouseScroll' + elementNamespace, module.event.scroll)
19307 ;
19308 }
19309 module.verbose('Adding events to contain sidebar scroll');
19310 $document
19311 .on('touchmove' + elementNamespace, module.event.touch)
19312 ;
19313 $module
19314 .on('scroll' + eventNamespace, module.event.containScroll)
19315 ;
19316 }
19317 },
19318 unbind: {
19319 clickaway: function() {
19320 module.verbose('Removing clickaway events from context', $context);
19321 $context.off(elementNamespace);
19322 },
19323 scrollLock: function() {
19324 module.verbose('Removing scroll lock from page');
19325 $document.off(elementNamespace);
19326 $window.off(elementNamespace);
19327 $module.off('scroll' + eventNamespace);
19328 }
19329 },
19330
19331 add: {
19332 inlineCSS: function() {
19333 var
19334 width = module.cache.width || $module.outerWidth(),
19335 height = module.cache.height || $module.outerHeight(),
19336 isRTL = module.is.rtl(),
19337 direction = module.get.direction(),
19338 distance = {
19339 left : width,
19340 right : -width,
19341 top : height,
19342 bottom : -height
19343 },
19344 style
19345 ;
19346
19347 if(isRTL){
19348 module.verbose('RTL detected, flipping widths');
19349 distance.left = -width;
19350 distance.right = width;
19351 }
19352
19353 style = '<style>';
19354
19355 if(direction === 'left' || direction === 'right') {
19356 module.debug('Adding CSS rules for animation distance', width);
19357 style += ''
19358 + ' .ui.visible.' + direction + '.sidebar ~ .fixed,'
19359 + ' .ui.visible.' + direction + '.sidebar ~ .pusher {'
19360 + ' -webkit-transform: translate3d('+ distance[direction] + 'px, 0, 0);'
19361 + ' transform: translate3d('+ distance[direction] + 'px, 0, 0);'
19362 + ' }'
19363 ;
19364 }
19365 else if(direction === 'top' || direction == 'bottom') {
19366 style += ''
19367 + ' .ui.visible.' + direction + '.sidebar ~ .fixed,'
19368 + ' .ui.visible.' + direction + '.sidebar ~ .pusher {'
19369 + ' -webkit-transform: translate3d(0, ' + distance[direction] + 'px, 0);'
19370 + ' transform: translate3d(0, ' + distance[direction] + 'px, 0);'
19371 + ' }'
19372 ;
19373 }
19374
19375 /* IE is only browser not to create context with transforms */
19376 /* https://www.w3.org/Bugs/Public/show_bug.cgi?id=16328 */
19377 if( module.is.ie() ) {
19378 if(direction === 'left' || direction === 'right') {
19379 module.debug('Adding CSS rules for animation distance', width);
19380 style += ''
19381 + ' body.pushable > .ui.visible.' + direction + '.sidebar ~ .pusher:after {'
19382 + ' -webkit-transform: translate3d('+ distance[direction] + 'px, 0, 0);'
19383 + ' transform: translate3d('+ distance[direction] + 'px, 0, 0);'
19384 + ' }'
19385 ;
19386 }
19387 else if(direction === 'top' || direction == 'bottom') {
19388 style += ''
19389 + ' body.pushable > .ui.visible.' + direction + '.sidebar ~ .pusher:after {'
19390 + ' -webkit-transform: translate3d(0, ' + distance[direction] + 'px, 0);'
19391 + ' transform: translate3d(0, ' + distance[direction] + 'px, 0);'
19392 + ' }'
19393 ;
19394 }
19395 /* opposite sides visible forces content overlay */
19396 style += ''
19397 + ' body.pushable > .ui.visible.left.sidebar ~ .ui.visible.right.sidebar ~ .pusher:after,'
19398 + ' body.pushable > .ui.visible.right.sidebar ~ .ui.visible.left.sidebar ~ .pusher:after {'
19399 + ' -webkit-transform: translate3d(0, 0, 0);'
19400 + ' transform: translate3d(0, 0, 0);'
19401 + ' }'
19402 ;
19403 }
19404 style += '</style>';
19405 $style = $(style)
19406 .appendTo($head)
19407 ;
19408 module.debug('Adding sizing css to head', $style);
19409 }
19410 },
19411
19412 refresh: function() {
19413 module.verbose('Refreshing selector cache');
19414 $context = $(settings.context);
19415 $sidebars = $context.children(selector.sidebar);
19416 $pusher = $context.children(selector.pusher);
19417 $fixed = $context.children(selector.fixed);
19418 module.clear.cache();
19419 },
19420
19421 refreshSidebars: function() {
19422 module.verbose('Refreshing other sidebars');
19423 $sidebars = $context.children(selector.sidebar);
19424 },
19425
19426 repaint: function() {
19427 module.verbose('Forcing repaint event');
19428 element.style.display = 'none';
19429 var ignored = element.offsetHeight;
19430 element.scrollTop = element.scrollTop;
19431 element.style.display = '';
19432 },
19433
19434 setup: {
19435 cache: function() {
19436 module.cache = {
19437 width : $module.outerWidth(),
19438 height : $module.outerHeight(),
19439 rtl : ($module.css('direction') == 'rtl')
19440 };
19441 },
19442 layout: function() {
19443 if( $context.children(selector.pusher).length === 0 ) {
19444 module.debug('Adding wrapper element for sidebar');
19445 module.error(error.pusher);
19446 $pusher = $('<div class="pusher" />');
19447 $context
19448 .children()
19449 .not(selector.omitted)
19450 .not($sidebars)
19451 .wrapAll($pusher)
19452 ;
19453 module.refresh();
19454 }
19455 if($module.nextAll(selector.pusher).length === 0 || $module.nextAll(selector.pusher)[0] !== $pusher[0]) {
19456 module.debug('Moved sidebar to correct parent element');
19457 module.error(error.movedSidebar, element);
19458 $module.detach().prependTo($context);
19459 module.refresh();
19460 }
19461 module.clear.cache();
19462 module.set.pushable();
19463 module.set.direction();
19464 }
19465 },
19466
19467 attachEvents: function(selector, event) {
19468 var
19469 $toggle = $(selector)
19470 ;
19471 event = $.isFunction(module[event])
19472 ? module[event]
19473 : module.toggle
19474 ;
19475 if($toggle.length > 0) {
19476 module.debug('Attaching sidebar events to element', selector, event);
19477 $toggle
19478 .on('click' + eventNamespace, event)
19479 ;
19480 }
19481 else {
19482 module.error(error.notFound, selector);
19483 }
19484 },
19485
19486 show: function(callback) {
19487 callback = $.isFunction(callback)
19488 ? callback
19489 : function(){}
19490 ;
19491 if(module.is.hidden()) {
19492 module.refreshSidebars();
19493 if(settings.overlay) {
19494 module.error(error.overlay);
19495 settings.transition = 'overlay';
19496 }
19497 module.refresh();
19498 if(module.othersActive()) {
19499 module.debug('Other sidebars currently visible');
19500 if(settings.exclusive) {
19501 // if not overlay queue animation after hide
19502 if(settings.transition != 'overlay') {
19503 module.hideOthers(module.show);
19504 return;
19505 }
19506 else {
19507 module.hideOthers();
19508 }
19509 }
19510 else {
19511 settings.transition = 'overlay';
19512 }
19513 }
19514 module.pushPage(function() {
19515 callback.call(element);
19516 settings.onShow.call(element);
19517 });
19518 settings.onChange.call(element);
19519 settings.onVisible.call(element);
19520 }
19521 else {
19522 module.debug('Sidebar is already visible');
19523 }
19524 },
19525
19526 hide: function(callback) {
19527 callback = $.isFunction(callback)
19528 ? callback
19529 : function(){}
19530 ;
19531 if(settings.closable && (module.is.visible() || module.is.animating())) {
19532 module.debug('Hiding sidebar', callback);
19533 module.refreshSidebars();
19534 module.pullPage(function() {
19535 callback.call(element);
19536 settings.onHidden.call(element);
19537 });
19538 settings.onChange.call(element);
19539 settings.onHide.call(element);
19540 }
19541 },
19542
19543 othersAnimating: function() {
19544 return ($sidebars.not($module).filter('.' + className.animating).length > 0);
19545 },
19546 othersVisible: function() {
19547 return ($sidebars.not($module).filter('.' + className.visible).length > 0);
19548 },
19549 othersActive: function() {
19550 return(module.othersVisible() || module.othersAnimating());
19551 },
19552
19553 hideOthers: function(callback) {
19554 var
19555 $otherSidebars = $sidebars.not($module).filter('.' + className.visible),
19556 sidebarCount = $otherSidebars.length,
19557 callbackCount = 0
19558 ;
19559 callback = callback || function(){};
19560 $otherSidebars
19561 .sidebar('hide', function() {
19562 callbackCount++;
19563 if(callbackCount == sidebarCount) {
19564 callback();
19565 }
19566 })
19567 ;
19568 },
19569
19570 toggle: function() {
19571 module.verbose('Determining toggled direction');
19572 if(module.is.hidden()) {
19573 module.show();
19574 }
19575 else {
19576 module.hide();
19577 }
19578 },
19579
19580 pushPage: function(callback) {
19581 var
19582 transition = module.get.transition(),
19583 $transition = (transition === 'overlay' || module.othersActive())
19584 ? $module
19585 : $pusher,
19586 animate,
19587 dim,
19588 transitionEnd
19589 ;
19590 callback = $.isFunction(callback)
19591 ? callback
19592 : function(){}
19593 ;
19594 if(settings.transition == 'scale down') {
19595 module.scrollToTop();
19596 }
19597 module.set.transition(transition);
19598 module.repaint();
19599 animate = function() {
19600 module.bind.clickaway();
19601 module.add.inlineCSS();
19602 module.set.animating();
19603 module.set.visible();
19604 };
19605 dim = function() {
19606 module.set.dimmed();
19607 };
19608 transitionEnd = function(event) {
19609 if( event.target == $transition[0] ) {
19610 $transition.off(transitionEvent + elementNamespace, transitionEnd);
19611 module.remove.animating();
19612 module.bind.scrollLock();
19613 callback.call(element);
19614 }
19615 };
19616 $transition.off(transitionEvent + elementNamespace);
19617 $transition.on(transitionEvent + elementNamespace, transitionEnd);
19618 requestAnimationFrame(animate);
19619 if(settings.dimPage && !module.othersVisible()) {
19620 requestAnimationFrame(dim);
19621 }
19622 },
19623
19624 pullPage: function(callback) {
19625 var
19626 transition = module.get.transition(),
19627 $transition = (transition == 'overlay' || module.othersActive())
19628 ? $module
19629 : $pusher,
19630 animate,
19631 transitionEnd
19632 ;
19633 callback = $.isFunction(callback)
19634 ? callback
19635 : function(){}
19636 ;
19637 module.verbose('Removing context push state', module.get.direction());
19638
19639 module.unbind.clickaway();
19640 module.unbind.scrollLock();
19641
19642 animate = function() {
19643 module.set.transition(transition);
19644 module.set.animating();
19645 module.remove.visible();
19646 if(settings.dimPage && !module.othersVisible()) {
19647 $pusher.removeClass(className.dimmed);
19648 }
19649 };
19650 transitionEnd = function(event) {
19651 if( event.target == $transition[0] ) {
19652 $transition.off(transitionEvent + elementNamespace, transitionEnd);
19653 module.remove.animating();
19654 module.remove.transition();
19655 module.remove.inlineCSS();
19656 if(transition == 'scale down' || (settings.returnScroll && module.is.mobile()) ) {
19657 module.scrollBack();
19658 }
19659 callback.call(element);
19660 }
19661 };
19662 $transition.off(transitionEvent + elementNamespace);
19663 $transition.on(transitionEvent + elementNamespace, transitionEnd);
19664 requestAnimationFrame(animate);
19665 },
19666
19667 scrollToTop: function() {
19668 module.verbose('Scrolling to top of page to avoid animation issues');
19669 currentScroll = $(window).scrollTop();
19670 $module.scrollTop(0);
19671 window.scrollTo(0, 0);
19672 },
19673
19674 scrollBack: function() {
19675 module.verbose('Scrolling back to original page position');
19676 window.scrollTo(0, currentScroll);
19677 },
19678
19679 clear: {
19680 cache: function() {
19681 module.verbose('Clearing cached dimensions');
19682 module.cache = {};
19683 }
19684 },
19685
19686 set: {
19687
19688 // ios only (scroll on html not document). This prevent auto-resize canvas/scroll in ios
19689 // (This is no longer necessary in latest iOS)
19690 ios: function() {
19691 $html.addClass(className.ios);
19692 },
19693
19694 // container
19695 pushed: function() {
19696 $context.addClass(className.pushed);
19697 },
19698 pushable: function() {
19699 $context.addClass(className.pushable);
19700 },
19701
19702 // pusher
19703 dimmed: function() {
19704 $pusher.addClass(className.dimmed);
19705 },
19706
19707 // sidebar
19708 active: function() {
19709 $module.addClass(className.active);
19710 },
19711 animating: function() {
19712 $module.addClass(className.animating);
19713 },
19714 transition: function(transition) {
19715 transition = transition || module.get.transition();
19716 $module.addClass(transition);
19717 },
19718 direction: function(direction) {
19719 direction = direction || module.get.direction();
19720 $module.addClass(className[direction]);
19721 },
19722 visible: function() {
19723 $module.addClass(className.visible);
19724 },
19725 overlay: function() {
19726 $module.addClass(className.overlay);
19727 }
19728 },
19729 remove: {
19730
19731 inlineCSS: function() {
19732 module.debug('Removing inline css styles', $style);
19733 if($style && $style.length > 0) {
19734 $style.remove();
19735 }
19736 },
19737
19738 // ios scroll on html not document
19739 ios: function() {
19740 $html.removeClass(className.ios);
19741 },
19742
19743 // context
19744 pushed: function() {
19745 $context.removeClass(className.pushed);
19746 },
19747 pushable: function() {
19748 $context.removeClass(className.pushable);
19749 },
19750
19751 // sidebar
19752 active: function() {
19753 $module.removeClass(className.active);
19754 },
19755 animating: function() {
19756 $module.removeClass(className.animating);
19757 },
19758 transition: function(transition) {
19759 transition = transition || module.get.transition();
19760 $module.removeClass(transition);
19761 },
19762 direction: function(direction) {
19763 direction = direction || module.get.direction();
19764 $module.removeClass(className[direction]);
19765 },
19766 visible: function() {
19767 $module.removeClass(className.visible);
19768 },
19769 overlay: function() {
19770 $module.removeClass(className.overlay);
19771 }
19772 },
19773
19774 get: {
19775 direction: function() {
19776 if($module.hasClass(className.top)) {
19777 return className.top;
19778 }
19779 else if($module.hasClass(className.right)) {
19780 return className.right;
19781 }
19782 else if($module.hasClass(className.bottom)) {
19783 return className.bottom;
19784 }
19785 return className.left;
19786 },
19787 transition: function() {
19788 var
19789 direction = module.get.direction(),
19790 transition
19791 ;
19792 transition = ( module.is.mobile() )
19793 ? (settings.mobileTransition == 'auto')
19794 ? settings.defaultTransition.mobile[direction]
19795 : settings.mobileTransition
19796 : (settings.transition == 'auto')
19797 ? settings.defaultTransition.computer[direction]
19798 : settings.transition
19799 ;
19800 module.verbose('Determined transition', transition);
19801 return transition;
19802 },
19803 transitionEvent: function() {
19804 var
19805 element = document.createElement('element'),
19806 transitions = {
19807 'transition' :'transitionend',
19808 'OTransition' :'oTransitionEnd',
19809 'MozTransition' :'transitionend',
19810 'WebkitTransition' :'webkitTransitionEnd'
19811 },
19812 transition
19813 ;
19814 for(transition in transitions){
19815 if( element.style[transition] !== undefined ){
19816 return transitions[transition];
19817 }
19818 }
19819 }
19820 },
19821
19822 is: {
19823
19824 ie: function() {
19825 var
19826 isIE11 = (!(window.ActiveXObject) && 'ActiveXObject' in window),
19827 isIE = ('ActiveXObject' in window)
19828 ;
19829 return (isIE11 || isIE);
19830 },
19831
19832 ios: function() {
19833 var
19834 userAgent = navigator.userAgent,
19835 isIOS = userAgent.match(regExp.ios),
19836 isMobileChrome = userAgent.match(regExp.mobileChrome)
19837 ;
19838 if(isIOS && !isMobileChrome) {
19839 module.verbose('Browser was found to be iOS', userAgent);
19840 return true;
19841 }
19842 else {
19843 return false;
19844 }
19845 },
19846 mobile: function() {
19847 var
19848 userAgent = navigator.userAgent,
19849 isMobile = userAgent.match(regExp.mobile)
19850 ;
19851 if(isMobile) {
19852 module.verbose('Browser was found to be mobile', userAgent);
19853 return true;
19854 }
19855 else {
19856 module.verbose('Browser is not mobile, using regular transition', userAgent);
19857 return false;
19858 }
19859 },
19860 hidden: function() {
19861 return !module.is.visible();
19862 },
19863 visible: function() {
19864 return $module.hasClass(className.visible);
19865 },
19866 // alias
19867 open: function() {
19868 return module.is.visible();
19869 },
19870 closed: function() {
19871 return module.is.hidden();
19872 },
19873 vertical: function() {
19874 return $module.hasClass(className.top);
19875 },
19876 animating: function() {
19877 return $context.hasClass(className.animating);
19878 },
19879 rtl: function () {
19880 if(module.cache.rtl === undefined) {
19881 module.cache.rtl = ($module.css('direction') == 'rtl');
19882 }
19883 return module.cache.rtl;
19884 }
19885 },
19886
19887 setting: function(name, value) {
19888 module.debug('Changing setting', name, value);
19889 if( $.isPlainObject(name) ) {
19890 $.extend(true, settings, name);
19891 }
19892 else if(value !== undefined) {
19893 if($.isPlainObject(settings[name])) {
19894 $.extend(true, settings[name], value);
19895 }
19896 else {
19897 settings[name] = value;
19898 }
19899 }
19900 else {
19901 return settings[name];
19902 }
19903 },
19904 internal: function(name, value) {
19905 if( $.isPlainObject(name) ) {
19906 $.extend(true, module, name);
19907 }
19908 else if(value !== undefined) {
19909 module[name] = value;
19910 }
19911 else {
19912 return module[name];
19913 }
19914 },
19915 debug: function() {
19916 if(!settings.silent && settings.debug) {
19917 if(settings.performance) {
19918 module.performance.log(arguments);
19919 }
19920 else {
19921 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
19922 module.debug.apply(console, arguments);
19923 }
19924 }
19925 },
19926 verbose: function() {
19927 if(!settings.silent && settings.verbose && settings.debug) {
19928 if(settings.performance) {
19929 module.performance.log(arguments);
19930 }
19931 else {
19932 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
19933 module.verbose.apply(console, arguments);
19934 }
19935 }
19936 },
19937 error: function() {
19938 if(!settings.silent) {
19939 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
19940 module.error.apply(console, arguments);
19941 }
19942 },
19943 performance: {
19944 log: function(message) {
19945 var
19946 currentTime,
19947 executionTime,
19948 previousTime
19949 ;
19950 if(settings.performance) {
19951 currentTime = new Date().getTime();
19952 previousTime = time || currentTime;
19953 executionTime = currentTime - previousTime;
19954 time = currentTime;
19955 performance.push({
19956 'Name' : message[0],
19957 'Arguments' : [].slice.call(message, 1) || '',
19958 'Element' : element,
19959 'Execution Time' : executionTime
19960 });
19961 }
19962 clearTimeout(module.performance.timer);
19963 module.performance.timer = setTimeout(module.performance.display, 500);
19964 },
19965 display: function() {
19966 var
19967 title = settings.name + ':',
19968 totalTime = 0
19969 ;
19970 time = false;
19971 clearTimeout(module.performance.timer);
19972 $.each(performance, function(index, data) {
19973 totalTime += data['Execution Time'];
19974 });
19975 title += ' ' + totalTime + 'ms';
19976 if(moduleSelector) {
19977 title += ' \'' + moduleSelector + '\'';
19978 }
19979 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
19980 console.groupCollapsed(title);
19981 if(console.table) {
19982 console.table(performance);
19983 }
19984 else {
19985 $.each(performance, function(index, data) {
19986 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
19987 });
19988 }
19989 console.groupEnd();
19990 }
19991 performance = [];
19992 }
19993 },
19994 invoke: function(query, passedArguments, context) {
19995 var
19996 object = instance,
19997 maxDepth,
19998 found,
19999 response
20000 ;
20001 passedArguments = passedArguments || queryArguments;
20002 context = element || context;
20003 if(typeof query == 'string' && object !== undefined) {
20004 query = query.split(/[\. ]/);
20005 maxDepth = query.length - 1;
20006 $.each(query, function(depth, value) {
20007 var camelCaseValue = (depth != maxDepth)
20008 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
20009 : query
20010 ;
20011 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
20012 object = object[camelCaseValue];
20013 }
20014 else if( object[camelCaseValue] !== undefined ) {
20015 found = object[camelCaseValue];
20016 return false;
20017 }
20018 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
20019 object = object[value];
20020 }
20021 else if( object[value] !== undefined ) {
20022 found = object[value];
20023 return false;
20024 }
20025 else {
20026 module.error(error.method, query);
20027 return false;
20028 }
20029 });
20030 }
20031 if ( $.isFunction( found ) ) {
20032 response = found.apply(context, passedArguments);
20033 }
20034 else if(found !== undefined) {
20035 response = found;
20036 }
20037 if(Array.isArray(returnedValue)) {
20038 returnedValue.push(response);
20039 }
20040 else if(returnedValue !== undefined) {
20041 returnedValue = [returnedValue, response];
20042 }
20043 else if(response !== undefined) {
20044 returnedValue = response;
20045 }
20046 return found;
20047 }
20048 }
20049 ;
20050
20051 if(methodInvoked) {
20052 if(instance === undefined) {
20053 module.initialize();
20054 }
20055 module.invoke(query);
20056 }
20057 else {
20058 if(instance !== undefined) {
20059 module.invoke('destroy');
20060 }
20061 module.initialize();
20062 }
20063 });
20064
20065 return (returnedValue !== undefined)
20066 ? returnedValue
20067 : this
20068 ;
20069};
20070
20071$.fn.sidebar.settings = {
20072
20073 name : 'Sidebar',
20074 namespace : 'sidebar',
20075
20076 silent : false,
20077 debug : false,
20078 verbose : false,
20079 performance : true,
20080
20081 transition : 'auto',
20082 mobileTransition : 'auto',
20083
20084 defaultTransition : {
20085 computer: {
20086 left : 'uncover',
20087 right : 'uncover',
20088 top : 'overlay',
20089 bottom : 'overlay'
20090 },
20091 mobile: {
20092 left : 'uncover',
20093 right : 'uncover',
20094 top : 'overlay',
20095 bottom : 'overlay'
20096 }
20097 },
20098
20099 context : 'body',
20100 exclusive : false,
20101 closable : true,
20102 dimPage : true,
20103 scrollLock : false,
20104 returnScroll : false,
20105 delaySetup : false,
20106
20107 duration : 500,
20108
20109 onChange : function(){},
20110 onShow : function(){},
20111 onHide : function(){},
20112
20113 onHidden : function(){},
20114 onVisible : function(){},
20115
20116 className : {
20117 active : 'active',
20118 animating : 'animating',
20119 dimmed : 'dimmed',
20120 ios : 'ios',
20121 pushable : 'pushable',
20122 pushed : 'pushed',
20123 right : 'right',
20124 top : 'top',
20125 left : 'left',
20126 bottom : 'bottom',
20127 visible : 'visible'
20128 },
20129
20130 selector: {
20131 fixed : '.fixed',
20132 omitted : 'script, link, style, .ui.modal, .ui.dimmer, .ui.nag, .ui.fixed',
20133 pusher : '.pusher',
20134 sidebar : '.ui.sidebar'
20135 },
20136
20137 regExp: {
20138 ios : /(iPad|iPhone|iPod)/g,
20139 mobileChrome : /(CriOS)/g,
20140 mobile : /Mobile|iP(hone|od|ad)|Android|BlackBerry|IEMobile|Kindle|NetFront|Silk-Accelerated|(hpw|web)OS|Fennec|Minimo|Opera M(obi|ini)|Blazer|Dolfin|Dolphin|Skyfire|Zune/g
20141 },
20142
20143 error : {
20144 method : 'The method you called is not defined.',
20145 pusher : 'Had to add pusher element. For optimal performance make sure body content is inside a pusher element',
20146 movedSidebar : 'Had to move sidebar. For optimal performance make sure sidebar and pusher are direct children of your body tag',
20147 overlay : 'The overlay setting is no longer supported, use animation: overlay',
20148 notFound : 'There were no elements that matched the specified selector'
20149 }
20150
20151};
20152
20153
20154})( jQuery, window, document );
20155
20156/*!
20157 * # Semantic UI 2.7.2 - Sticky
20158 * http://github.com/semantic-org/semantic-ui/
20159 *
20160 *
20161 * Released under the MIT license
20162 * http://opensource.org/licenses/MIT
20163 *
20164 */
20165
20166;(function ($, window, document, undefined) {
20167
20168'use strict';
20169
20170$.isFunction = $.isFunction || function(obj) {
20171 return typeof obj === "function" && typeof obj.nodeType !== "number";
20172};
20173
20174window = (typeof window != 'undefined' && window.Math == Math)
20175 ? window
20176 : (typeof self != 'undefined' && self.Math == Math)
20177 ? self
20178 : Function('return this')()
20179;
20180
20181$.fn.sticky = function(parameters) {
20182 var
20183 $allModules = $(this),
20184 moduleSelector = $allModules.selector || '',
20185
20186 time = new Date().getTime(),
20187 performance = [],
20188
20189 query = arguments[0],
20190 methodInvoked = (typeof query == 'string'),
20191 queryArguments = [].slice.call(arguments, 1),
20192 returnedValue
20193 ;
20194
20195 $allModules
20196 .each(function() {
20197 var
20198 settings = ( $.isPlainObject(parameters) )
20199 ? $.extend(true, {}, $.fn.sticky.settings, parameters)
20200 : $.extend({}, $.fn.sticky.settings),
20201
20202 className = settings.className,
20203 namespace = settings.namespace,
20204 error = settings.error,
20205
20206 eventNamespace = '.' + namespace,
20207 moduleNamespace = 'module-' + namespace,
20208
20209 $module = $(this),
20210 $window = $(window),
20211 $scroll = $(settings.scrollContext),
20212 $container,
20213 $context,
20214
20215 selector = $module.selector || '',
20216 instance = $module.data(moduleNamespace),
20217
20218 requestAnimationFrame = window.requestAnimationFrame
20219 || window.mozRequestAnimationFrame
20220 || window.webkitRequestAnimationFrame
20221 || window.msRequestAnimationFrame
20222 || function(callback) { setTimeout(callback, 0); },
20223
20224 element = this,
20225
20226 documentObserver,
20227 observer,
20228 module
20229 ;
20230
20231 module = {
20232
20233 initialize: function() {
20234
20235 module.determineContainer();
20236 module.determineContext();
20237 module.verbose('Initializing sticky', settings, $container);
20238
20239 module.save.positions();
20240 module.checkErrors();
20241 module.bind.events();
20242
20243 if(settings.observeChanges) {
20244 module.observeChanges();
20245 }
20246 module.instantiate();
20247 },
20248
20249 instantiate: function() {
20250 module.verbose('Storing instance of module', module);
20251 instance = module;
20252 $module
20253 .data(moduleNamespace, module)
20254 ;
20255 },
20256
20257 destroy: function() {
20258 module.verbose('Destroying previous instance');
20259 module.reset();
20260 if(documentObserver) {
20261 documentObserver.disconnect();
20262 }
20263 if(observer) {
20264 observer.disconnect();
20265 }
20266 $window
20267 .off('load' + eventNamespace, module.event.load)
20268 .off('resize' + eventNamespace, module.event.resize)
20269 ;
20270 $scroll
20271 .off('scrollchange' + eventNamespace, module.event.scrollchange)
20272 ;
20273 $module.removeData(moduleNamespace);
20274 },
20275
20276 observeChanges: function() {
20277 if('MutationObserver' in window) {
20278 documentObserver = new MutationObserver(module.event.documentChanged);
20279 observer = new MutationObserver(module.event.changed);
20280 documentObserver.observe(document, {
20281 childList : true,
20282 subtree : true
20283 });
20284 observer.observe(element, {
20285 childList : true,
20286 subtree : true
20287 });
20288 observer.observe($context[0], {
20289 childList : true,
20290 subtree : true
20291 });
20292 module.debug('Setting up mutation observer', observer);
20293 }
20294 },
20295
20296 determineContainer: function() {
20297 if(settings.container) {
20298 $container = $(settings.container);
20299 }
20300 else {
20301 $container = $module.offsetParent();
20302 }
20303 },
20304
20305 determineContext: function() {
20306 if(settings.context) {
20307 $context = $(settings.context);
20308 }
20309 else {
20310 $context = $container;
20311 }
20312 if($context.length === 0) {
20313 module.error(error.invalidContext, settings.context, $module);
20314 return;
20315 }
20316 },
20317
20318 checkErrors: function() {
20319 if( module.is.hidden() ) {
20320 module.error(error.visible, $module);
20321 }
20322 if(module.cache.element.height > module.cache.context.height) {
20323 module.reset();
20324 module.error(error.elementSize, $module);
20325 return;
20326 }
20327 },
20328
20329 bind: {
20330 events: function() {
20331 $window
20332 .on('load' + eventNamespace, module.event.load)
20333 .on('resize' + eventNamespace, module.event.resize)
20334 ;
20335 // pub/sub pattern
20336 $scroll
20337 .off('scroll' + eventNamespace)
20338 .on('scroll' + eventNamespace, module.event.scroll)
20339 .on('scrollchange' + eventNamespace, module.event.scrollchange)
20340 ;
20341 }
20342 },
20343
20344 event: {
20345 changed: function(mutations) {
20346 clearTimeout(module.timer);
20347 module.timer = setTimeout(function() {
20348 module.verbose('DOM tree modified, updating sticky menu', mutations);
20349 module.refresh();
20350 }, 100);
20351 },
20352 documentChanged: function(mutations) {
20353 [].forEach.call(mutations, function(mutation) {
20354 if(mutation.removedNodes) {
20355 [].forEach.call(mutation.removedNodes, function(node) {
20356 if(node == element || $(node).find(element).length > 0) {
20357 module.debug('Element removed from DOM, tearing down events');
20358 module.destroy();
20359 }
20360 });
20361 }
20362 });
20363 },
20364 load: function() {
20365 module.verbose('Page contents finished loading');
20366 requestAnimationFrame(module.refresh);
20367 },
20368 resize: function() {
20369 module.verbose('Window resized');
20370 requestAnimationFrame(module.refresh);
20371 },
20372 scroll: function() {
20373 requestAnimationFrame(function() {
20374 $scroll.triggerHandler('scrollchange' + eventNamespace, $scroll.scrollTop() );
20375 });
20376 },
20377 scrollchange: function(event, scrollPosition) {
20378 module.stick(scrollPosition);
20379 settings.onScroll.call(element);
20380 }
20381 },
20382
20383 refresh: function(hardRefresh) {
20384 module.reset();
20385 if(!settings.context) {
20386 module.determineContext();
20387 }
20388 if(hardRefresh) {
20389 module.determineContainer();
20390 }
20391 module.save.positions();
20392 module.stick();
20393 settings.onReposition.call(element);
20394 },
20395
20396 supports: {
20397 sticky: function() {
20398 var
20399 $element = $('<div/>'),
20400 element = $element[0]
20401 ;
20402 $element.addClass(className.supported);
20403 return($element.css('position').match('sticky'));
20404 }
20405 },
20406
20407 save: {
20408 lastScroll: function(scroll) {
20409 module.lastScroll = scroll;
20410 },
20411 elementScroll: function(scroll) {
20412 module.elementScroll = scroll;
20413 },
20414 positions: function() {
20415 var
20416 scrollContext = {
20417 height : $scroll.height()
20418 },
20419 element = {
20420 margin: {
20421 top : parseInt($module.css('margin-top'), 10),
20422 bottom : parseInt($module.css('margin-bottom'), 10),
20423 },
20424 offset : $module.offset(),
20425 width : $module.outerWidth(),
20426 height : $module.outerHeight()
20427 },
20428 context = {
20429 offset : $context.offset(),
20430 height : $context.outerHeight()
20431 },
20432 container = {
20433 height: $container.outerHeight()
20434 }
20435 ;
20436 if( !module.is.standardScroll() ) {
20437 module.debug('Non-standard scroll. Removing scroll offset from element offset');
20438
20439 scrollContext.top = $scroll.scrollTop();
20440 scrollContext.left = $scroll.scrollLeft();
20441
20442 element.offset.top += scrollContext.top;
20443 context.offset.top += scrollContext.top;
20444 element.offset.left += scrollContext.left;
20445 context.offset.left += scrollContext.left;
20446 }
20447 module.cache = {
20448 fits : ( (element.height + settings.offset) <= scrollContext.height),
20449 sameHeight : (element.height == context.height),
20450 scrollContext : {
20451 height : scrollContext.height
20452 },
20453 element: {
20454 margin : element.margin,
20455 top : element.offset.top - element.margin.top,
20456 left : element.offset.left,
20457 width : element.width,
20458 height : element.height,
20459 bottom : element.offset.top + element.height
20460 },
20461 context: {
20462 top : context.offset.top,
20463 height : context.height,
20464 bottom : context.offset.top + context.height
20465 }
20466 };
20467 module.set.containerSize();
20468
20469 module.stick();
20470 module.debug('Caching element positions', module.cache);
20471 }
20472 },
20473
20474 get: {
20475 direction: function(scroll) {
20476 var
20477 direction = 'down'
20478 ;
20479 scroll = scroll || $scroll.scrollTop();
20480 if(module.lastScroll !== undefined) {
20481 if(module.lastScroll < scroll) {
20482 direction = 'down';
20483 }
20484 else if(module.lastScroll > scroll) {
20485 direction = 'up';
20486 }
20487 }
20488 return direction;
20489 },
20490 scrollChange: function(scroll) {
20491 scroll = scroll || $scroll.scrollTop();
20492 return (module.lastScroll)
20493 ? (scroll - module.lastScroll)
20494 : 0
20495 ;
20496 },
20497 currentElementScroll: function() {
20498 if(module.elementScroll) {
20499 return module.elementScroll;
20500 }
20501 return ( module.is.top() )
20502 ? Math.abs(parseInt($module.css('top'), 10)) || 0
20503 : Math.abs(parseInt($module.css('bottom'), 10)) || 0
20504 ;
20505 },
20506
20507 elementScroll: function(scroll) {
20508 scroll = scroll || $scroll.scrollTop();
20509 var
20510 element = module.cache.element,
20511 scrollContext = module.cache.scrollContext,
20512 delta = module.get.scrollChange(scroll),
20513 maxScroll = (element.height - scrollContext.height + settings.offset),
20514 elementScroll = module.get.currentElementScroll(),
20515 possibleScroll = (elementScroll + delta)
20516 ;
20517 if(module.cache.fits || possibleScroll < 0) {
20518 elementScroll = 0;
20519 }
20520 else if(possibleScroll > maxScroll ) {
20521 elementScroll = maxScroll;
20522 }
20523 else {
20524 elementScroll = possibleScroll;
20525 }
20526 return elementScroll;
20527 }
20528 },
20529
20530 remove: {
20531 lastScroll: function() {
20532 delete module.lastScroll;
20533 },
20534 elementScroll: function(scroll) {
20535 delete module.elementScroll;
20536 },
20537 minimumSize: function() {
20538 $container
20539 .css('min-height', '')
20540 ;
20541 },
20542 offset: function() {
20543 $module.css('margin-top', '');
20544 }
20545 },
20546
20547 set: {
20548 offset: function() {
20549 module.verbose('Setting offset on element', settings.offset);
20550 $module
20551 .css('margin-top', settings.offset)
20552 ;
20553 },
20554 containerSize: function() {
20555 var
20556 tagName = $container.get(0).tagName
20557 ;
20558 if(tagName === 'HTML' || tagName == 'body') {
20559 // this can trigger for too many reasons
20560 //module.error(error.container, tagName, $module);
20561 module.determineContainer();
20562 }
20563 else {
20564 if( Math.abs($container.outerHeight() - module.cache.context.height) > settings.jitter) {
20565 module.debug('Context has padding, specifying exact height for container', module.cache.context.height);
20566 $container.css({
20567 height: module.cache.context.height
20568 });
20569 }
20570 }
20571 },
20572 minimumSize: function() {
20573 var
20574 element = module.cache.element
20575 ;
20576 $container
20577 .css('min-height', element.height)
20578 ;
20579 },
20580 scroll: function(scroll) {
20581 module.debug('Setting scroll on element', scroll);
20582 if(module.elementScroll == scroll) {
20583 return;
20584 }
20585 if( module.is.top() ) {
20586 $module
20587 .css('bottom', '')
20588 .css('top', -scroll)
20589 ;
20590 }
20591 if( module.is.bottom() ) {
20592 $module
20593 .css('top', '')
20594 .css('bottom', scroll)
20595 ;
20596 }
20597 },
20598 size: function() {
20599 if(module.cache.element.height !== 0 && module.cache.element.width !== 0) {
20600 element.style.setProperty('width', module.cache.element.width + 'px', 'important');
20601 element.style.setProperty('height', module.cache.element.height + 'px', 'important');
20602 }
20603 }
20604 },
20605
20606 is: {
20607 standardScroll: function() {
20608 return ($scroll[0] == window);
20609 },
20610 top: function() {
20611 return $module.hasClass(className.top);
20612 },
20613 bottom: function() {
20614 return $module.hasClass(className.bottom);
20615 },
20616 initialPosition: function() {
20617 return (!module.is.fixed() && !module.is.bound());
20618 },
20619 hidden: function() {
20620 return (!$module.is(':visible'));
20621 },
20622 bound: function() {
20623 return $module.hasClass(className.bound);
20624 },
20625 fixed: function() {
20626 return $module.hasClass(className.fixed);
20627 }
20628 },
20629
20630 stick: function(scroll) {
20631 var
20632 cachedPosition = scroll || $scroll.scrollTop(),
20633 cache = module.cache,
20634 fits = cache.fits,
20635 sameHeight = cache.sameHeight,
20636 element = cache.element,
20637 scrollContext = cache.scrollContext,
20638 context = cache.context,
20639 offset = (module.is.bottom() && settings.pushing)
20640 ? settings.bottomOffset
20641 : settings.offset,
20642 scroll = {
20643 top : cachedPosition + offset,
20644 bottom : cachedPosition + offset + scrollContext.height
20645 },
20646 direction = module.get.direction(scroll.top),
20647 elementScroll = (fits)
20648 ? 0
20649 : module.get.elementScroll(scroll.top),
20650
20651 // shorthand
20652 doesntFit = !fits,
20653 elementVisible = (element.height !== 0)
20654 ;
20655 if(elementVisible && !sameHeight) {
20656
20657 if( module.is.initialPosition() ) {
20658 if(scroll.top >= context.bottom) {
20659 module.debug('Initial element position is bottom of container');
20660 module.bindBottom();
20661 }
20662 else if(scroll.top > element.top) {
20663 if( (element.height + scroll.top - elementScroll) >= context.bottom ) {
20664 module.debug('Initial element position is bottom of container');
20665 module.bindBottom();
20666 }
20667 else {
20668 module.debug('Initial element position is fixed');
20669 module.fixTop();
20670 }
20671 }
20672
20673 }
20674 else if( module.is.fixed() ) {
20675
20676 // currently fixed top
20677 if( module.is.top() ) {
20678 if( scroll.top <= element.top ) {
20679 module.debug('Fixed element reached top of container');
20680 module.setInitialPosition();
20681 }
20682 else if( (element.height + scroll.top - elementScroll) >= context.bottom ) {
20683 module.debug('Fixed element reached bottom of container');
20684 module.bindBottom();
20685 }
20686 // scroll element if larger than screen
20687 else if(doesntFit) {
20688 module.set.scroll(elementScroll);
20689 module.save.lastScroll(scroll.top);
20690 module.save.elementScroll(elementScroll);
20691 }
20692 }
20693
20694 // currently fixed bottom
20695 else if(module.is.bottom() ) {
20696
20697 // top edge
20698 if( (scroll.bottom - element.height) <= element.top) {
20699 module.debug('Bottom fixed rail has reached top of container');
20700 module.setInitialPosition();
20701 }
20702 // bottom edge
20703 else if(scroll.bottom >= context.bottom) {
20704 module.debug('Bottom fixed rail has reached bottom of container');
20705 module.bindBottom();
20706 }
20707 // scroll element if larger than screen
20708 else if(doesntFit) {
20709 module.set.scroll(elementScroll);
20710 module.save.lastScroll(scroll.top);
20711 module.save.elementScroll(elementScroll);
20712 }
20713
20714 }
20715 }
20716 else if( module.is.bottom() ) {
20717 if( scroll.top <= element.top ) {
20718 module.debug('Jumped from bottom fixed to top fixed, most likely used home/end button');
20719 module.setInitialPosition();
20720 }
20721 else {
20722 if(settings.pushing) {
20723 if(module.is.bound() && scroll.bottom <= context.bottom ) {
20724 module.debug('Fixing bottom attached element to bottom of browser.');
20725 module.fixBottom();
20726 }
20727 }
20728 else {
20729 if(module.is.bound() && (scroll.top <= context.bottom - element.height) ) {
20730 module.debug('Fixing bottom attached element to top of browser.');
20731 module.fixTop();
20732 }
20733 }
20734 }
20735 }
20736 }
20737 },
20738
20739 bindTop: function() {
20740 module.debug('Binding element to top of parent container');
20741 module.remove.offset();
20742 $module
20743 .css({
20744 left : '',
20745 top : '',
20746 marginBottom : ''
20747 })
20748 .removeClass(className.fixed)
20749 .removeClass(className.bottom)
20750 .addClass(className.bound)
20751 .addClass(className.top)
20752 ;
20753 settings.onTop.call(element);
20754 settings.onUnstick.call(element);
20755 },
20756 bindBottom: function() {
20757 module.debug('Binding element to bottom of parent container');
20758 module.remove.offset();
20759 $module
20760 .css({
20761 left : '',
20762 top : ''
20763 })
20764 .removeClass(className.fixed)
20765 .removeClass(className.top)
20766 .addClass(className.bound)
20767 .addClass(className.bottom)
20768 ;
20769 settings.onBottom.call(element);
20770 settings.onUnstick.call(element);
20771 },
20772
20773 setInitialPosition: function() {
20774 module.debug('Returning to initial position');
20775 module.unfix();
20776 module.unbind();
20777 },
20778
20779
20780 fixTop: function() {
20781 module.debug('Fixing element to top of page');
20782 if(settings.setSize) {
20783 module.set.size();
20784 }
20785 module.set.minimumSize();
20786 module.set.offset();
20787 $module
20788 .css({
20789 left : module.cache.element.left,
20790 bottom : '',
20791 marginBottom : ''
20792 })
20793 .removeClass(className.bound)
20794 .removeClass(className.bottom)
20795 .addClass(className.fixed)
20796 .addClass(className.top)
20797 ;
20798 settings.onStick.call(element);
20799 },
20800
20801 fixBottom: function() {
20802 module.debug('Sticking element to bottom of page');
20803 if(settings.setSize) {
20804 module.set.size();
20805 }
20806 module.set.minimumSize();
20807 module.set.offset();
20808 $module
20809 .css({
20810 left : module.cache.element.left,
20811 bottom : '',
20812 marginBottom : ''
20813 })
20814 .removeClass(className.bound)
20815 .removeClass(className.top)
20816 .addClass(className.fixed)
20817 .addClass(className.bottom)
20818 ;
20819 settings.onStick.call(element);
20820 },
20821
20822 unbind: function() {
20823 if( module.is.bound() ) {
20824 module.debug('Removing container bound position on element');
20825 module.remove.offset();
20826 $module
20827 .removeClass(className.bound)
20828 .removeClass(className.top)
20829 .removeClass(className.bottom)
20830 ;
20831 }
20832 },
20833
20834 unfix: function() {
20835 if( module.is.fixed() ) {
20836 module.debug('Removing fixed position on element');
20837 module.remove.minimumSize();
20838 module.remove.offset();
20839 $module
20840 .removeClass(className.fixed)
20841 .removeClass(className.top)
20842 .removeClass(className.bottom)
20843 ;
20844 settings.onUnstick.call(element);
20845 }
20846 },
20847
20848 reset: function() {
20849 module.debug('Resetting elements position');
20850 module.unbind();
20851 module.unfix();
20852 module.resetCSS();
20853 module.remove.offset();
20854 module.remove.lastScroll();
20855 },
20856
20857 resetCSS: function() {
20858 $module
20859 .css({
20860 width : '',
20861 height : ''
20862 })
20863 ;
20864 $container
20865 .css({
20866 height: ''
20867 })
20868 ;
20869 },
20870
20871 setting: function(name, value) {
20872 if( $.isPlainObject(name) ) {
20873 $.extend(true, settings, name);
20874 }
20875 else if(value !== undefined) {
20876 settings[name] = value;
20877 }
20878 else {
20879 return settings[name];
20880 }
20881 },
20882 internal: function(name, value) {
20883 if( $.isPlainObject(name) ) {
20884 $.extend(true, module, name);
20885 }
20886 else if(value !== undefined) {
20887 module[name] = value;
20888 }
20889 else {
20890 return module[name];
20891 }
20892 },
20893 debug: function() {
20894 if(!settings.silent && settings.debug) {
20895 if(settings.performance) {
20896 module.performance.log(arguments);
20897 }
20898 else {
20899 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
20900 module.debug.apply(console, arguments);
20901 }
20902 }
20903 },
20904 verbose: function() {
20905 if(!settings.silent && settings.verbose && settings.debug) {
20906 if(settings.performance) {
20907 module.performance.log(arguments);
20908 }
20909 else {
20910 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
20911 module.verbose.apply(console, arguments);
20912 }
20913 }
20914 },
20915 error: function() {
20916 if(!settings.silent) {
20917 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
20918 module.error.apply(console, arguments);
20919 }
20920 },
20921 performance: {
20922 log: function(message) {
20923 var
20924 currentTime,
20925 executionTime,
20926 previousTime
20927 ;
20928 if(settings.performance) {
20929 currentTime = new Date().getTime();
20930 previousTime = time || currentTime;
20931 executionTime = currentTime - previousTime;
20932 time = currentTime;
20933 performance.push({
20934 'Name' : message[0],
20935 'Arguments' : [].slice.call(message, 1) || '',
20936 'Element' : element,
20937 'Execution Time' : executionTime
20938 });
20939 }
20940 clearTimeout(module.performance.timer);
20941 module.performance.timer = setTimeout(module.performance.display, 0);
20942 },
20943 display: function() {
20944 var
20945 title = settings.name + ':',
20946 totalTime = 0
20947 ;
20948 time = false;
20949 clearTimeout(module.performance.timer);
20950 $.each(performance, function(index, data) {
20951 totalTime += data['Execution Time'];
20952 });
20953 title += ' ' + totalTime + 'ms';
20954 if(moduleSelector) {
20955 title += ' \'' + moduleSelector + '\'';
20956 }
20957 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
20958 console.groupCollapsed(title);
20959 if(console.table) {
20960 console.table(performance);
20961 }
20962 else {
20963 $.each(performance, function(index, data) {
20964 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
20965 });
20966 }
20967 console.groupEnd();
20968 }
20969 performance = [];
20970 }
20971 },
20972 invoke: function(query, passedArguments, context) {
20973 var
20974 object = instance,
20975 maxDepth,
20976 found,
20977 response
20978 ;
20979 passedArguments = passedArguments || queryArguments;
20980 context = element || context;
20981 if(typeof query == 'string' && object !== undefined) {
20982 query = query.split(/[\. ]/);
20983 maxDepth = query.length - 1;
20984 $.each(query, function(depth, value) {
20985 var camelCaseValue = (depth != maxDepth)
20986 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
20987 : query
20988 ;
20989 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
20990 object = object[camelCaseValue];
20991 }
20992 else if( object[camelCaseValue] !== undefined ) {
20993 found = object[camelCaseValue];
20994 return false;
20995 }
20996 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
20997 object = object[value];
20998 }
20999 else if( object[value] !== undefined ) {
21000 found = object[value];
21001 return false;
21002 }
21003 else {
21004 return false;
21005 }
21006 });
21007 }
21008 if ( $.isFunction( found ) ) {
21009 response = found.apply(context, passedArguments);
21010 }
21011 else if(found !== undefined) {
21012 response = found;
21013 }
21014 if(Array.isArray(returnedValue)) {
21015 returnedValue.push(response);
21016 }
21017 else if(returnedValue !== undefined) {
21018 returnedValue = [returnedValue, response];
21019 }
21020 else if(response !== undefined) {
21021 returnedValue = response;
21022 }
21023 return found;
21024 }
21025 };
21026
21027 if(methodInvoked) {
21028 if(instance === undefined) {
21029 module.initialize();
21030 }
21031 module.invoke(query);
21032 }
21033 else {
21034 if(instance !== undefined) {
21035 instance.invoke('destroy');
21036 }
21037 module.initialize();
21038 }
21039 })
21040 ;
21041
21042 return (returnedValue !== undefined)
21043 ? returnedValue
21044 : this
21045 ;
21046};
21047
21048$.fn.sticky.settings = {
21049
21050 name : 'Sticky',
21051 namespace : 'sticky',
21052
21053 silent : false,
21054 debug : false,
21055 verbose : true,
21056 performance : true,
21057
21058 // whether to stick in the opposite direction on scroll up
21059 pushing : false,
21060
21061 context : false,
21062 container : false,
21063
21064 // Context to watch scroll events
21065 scrollContext : window,
21066
21067 // Offset to adjust scroll
21068 offset : 0,
21069
21070 // Offset to adjust scroll when attached to bottom of screen
21071 bottomOffset : 0,
21072
21073 // will only set container height if difference between context and container is larger than this number
21074 jitter : 5,
21075
21076 // set width of sticky element when it is fixed to page (used to make sure 100% width is maintained if no fixed size set)
21077 setSize : true,
21078
21079 // Whether to automatically observe changes with Mutation Observers
21080 observeChanges : false,
21081
21082 // Called when position is recalculated
21083 onReposition : function(){},
21084
21085 // Called on each scroll
21086 onScroll : function(){},
21087
21088 // Called when element is stuck to viewport
21089 onStick : function(){},
21090
21091 // Called when element is unstuck from viewport
21092 onUnstick : function(){},
21093
21094 // Called when element reaches top of context
21095 onTop : function(){},
21096
21097 // Called when element reaches bottom of context
21098 onBottom : function(){},
21099
21100 error : {
21101 container : 'Sticky element must be inside a relative container',
21102 visible : 'Element is hidden, you must call refresh after element becomes visible. Use silent setting to surpress this warning in production.',
21103 method : 'The method you called is not defined.',
21104 invalidContext : 'Context specified does not exist',
21105 elementSize : 'Sticky element is larger than its container, cannot create sticky.'
21106 },
21107
21108 className : {
21109 bound : 'bound',
21110 fixed : 'fixed',
21111 supported : 'native',
21112 top : 'top',
21113 bottom : 'bottom'
21114 }
21115
21116};
21117
21118})( jQuery, window, document );
21119
21120/*!
21121 * # Semantic UI 2.7.2 - Tab
21122 * http://github.com/semantic-org/semantic-ui/
21123 *
21124 *
21125 * Released under the MIT license
21126 * http://opensource.org/licenses/MIT
21127 *
21128 */
21129
21130;(function ($, window, document, undefined) {
21131
21132'use strict';
21133
21134$.isWindow = $.isWindow || function(obj) {
21135 return obj != null && obj === obj.window;
21136};
21137$.isFunction = $.isFunction || function(obj) {
21138 return typeof obj === "function" && typeof obj.nodeType !== "number";
21139};
21140
21141window = (typeof window != 'undefined' && window.Math == Math)
21142 ? window
21143 : (typeof self != 'undefined' && self.Math == Math)
21144 ? self
21145 : Function('return this')()
21146;
21147
21148$.fn.tab = function(parameters) {
21149
21150 var
21151 // use window context if none specified
21152 $allModules = $.isFunction(this)
21153 ? $(window)
21154 : $(this),
21155
21156 moduleSelector = $allModules.selector || '',
21157 time = new Date().getTime(),
21158 performance = [],
21159
21160 query = arguments[0],
21161 methodInvoked = (typeof query == 'string'),
21162 queryArguments = [].slice.call(arguments, 1),
21163
21164 initializedHistory = false,
21165 returnedValue
21166 ;
21167
21168 $allModules
21169 .each(function() {
21170 var
21171
21172 settings = ( $.isPlainObject(parameters) )
21173 ? $.extend(true, {}, $.fn.tab.settings, parameters)
21174 : $.extend({}, $.fn.tab.settings),
21175
21176 className = settings.className,
21177 metadata = settings.metadata,
21178 selector = settings.selector,
21179 error = settings.error,
21180
21181 eventNamespace = '.' + settings.namespace,
21182 moduleNamespace = 'module-' + settings.namespace,
21183
21184 $module = $(this),
21185 $context,
21186 $tabs,
21187
21188 cache = {},
21189 firstLoad = true,
21190 recursionDepth = 0,
21191 element = this,
21192 instance = $module.data(moduleNamespace),
21193
21194 activeTabPath,
21195 parameterArray,
21196 module,
21197
21198 historyEvent
21199
21200 ;
21201
21202 module = {
21203
21204 initialize: function() {
21205 module.debug('Initializing tab menu item', $module);
21206 module.fix.callbacks();
21207 module.determineTabs();
21208
21209 module.debug('Determining tabs', settings.context, $tabs);
21210 // set up automatic routing
21211 if(settings.auto) {
21212 module.set.auto();
21213 }
21214 module.bind.events();
21215
21216 if(settings.history && !initializedHistory) {
21217 module.initializeHistory();
21218 initializedHistory = true;
21219 }
21220
21221 module.instantiate();
21222 },
21223
21224 instantiate: function () {
21225 module.verbose('Storing instance of module', module);
21226 instance = module;
21227 $module
21228 .data(moduleNamespace, module)
21229 ;
21230 },
21231
21232 destroy: function() {
21233 module.debug('Destroying tabs', $module);
21234 $module
21235 .removeData(moduleNamespace)
21236 .off(eventNamespace)
21237 ;
21238 },
21239
21240 bind: {
21241 events: function() {
21242 // if using $.tab don't add events
21243 if( !$.isWindow( element ) ) {
21244 module.debug('Attaching tab activation events to element', $module);
21245 $module
21246 .on('click' + eventNamespace, module.event.click)
21247 ;
21248 }
21249 }
21250 },
21251
21252 determineTabs: function() {
21253 var
21254 $reference
21255 ;
21256
21257 // determine tab context
21258 if(settings.context === 'parent') {
21259 if($module.closest(selector.ui).length > 0) {
21260 $reference = $module.closest(selector.ui);
21261 module.verbose('Using closest UI element as parent', $reference);
21262 }
21263 else {
21264 $reference = $module;
21265 }
21266 $context = $reference.parent();
21267 module.verbose('Determined parent element for creating context', $context);
21268 }
21269 else if(settings.context) {
21270 $context = $(settings.context);
21271 module.verbose('Using selector for tab context', settings.context, $context);
21272 }
21273 else {
21274 $context = $('body');
21275 }
21276 // find tabs
21277 if(settings.childrenOnly) {
21278 $tabs = $context.children(selector.tabs);
21279 module.debug('Searching tab context children for tabs', $context, $tabs);
21280 }
21281 else {
21282 $tabs = $context.find(selector.tabs);
21283 module.debug('Searching tab context for tabs', $context, $tabs);
21284 }
21285 },
21286
21287 fix: {
21288 callbacks: function() {
21289 if( $.isPlainObject(parameters) && (parameters.onTabLoad || parameters.onTabInit) ) {
21290 if(parameters.onTabLoad) {
21291 parameters.onLoad = parameters.onTabLoad;
21292 delete parameters.onTabLoad;
21293 module.error(error.legacyLoad, parameters.onLoad);
21294 }
21295 if(parameters.onTabInit) {
21296 parameters.onFirstLoad = parameters.onTabInit;
21297 delete parameters.onTabInit;
21298 module.error(error.legacyInit, parameters.onFirstLoad);
21299 }
21300 settings = $.extend(true, {}, $.fn.tab.settings, parameters);
21301 }
21302 }
21303 },
21304
21305 initializeHistory: function() {
21306 module.debug('Initializing page state');
21307 if( $.address === undefined ) {
21308 module.error(error.state);
21309 return false;
21310 }
21311 else {
21312 if(settings.historyType == 'state') {
21313 module.debug('Using HTML5 to manage state');
21314 if(settings.path !== false) {
21315 $.address
21316 .history(true)
21317 .state(settings.path)
21318 ;
21319 }
21320 else {
21321 module.error(error.path);
21322 return false;
21323 }
21324 }
21325 $.address
21326 .bind('change', module.event.history.change)
21327 ;
21328 }
21329 },
21330
21331 event: {
21332 click: function(event) {
21333 var
21334 tabPath = $(this).data(metadata.tab)
21335 ;
21336 if(tabPath !== undefined) {
21337 if(settings.history) {
21338 module.verbose('Updating page state', event);
21339 $.address.value(tabPath);
21340 }
21341 else {
21342 module.verbose('Changing tab', event);
21343 module.changeTab(tabPath);
21344 }
21345 event.preventDefault();
21346 }
21347 else {
21348 module.debug('No tab specified');
21349 }
21350 },
21351 history: {
21352 change: function(event) {
21353 var
21354 tabPath = event.pathNames.join('/') || module.get.initialPath(),
21355 pageTitle = settings.templates.determineTitle(tabPath) || false
21356 ;
21357 module.performance.display();
21358 module.debug('History change event', tabPath, event);
21359 historyEvent = event;
21360 if(tabPath !== undefined) {
21361 module.changeTab(tabPath);
21362 }
21363 if(pageTitle) {
21364 $.address.title(pageTitle);
21365 }
21366 }
21367 }
21368 },
21369
21370 refresh: function() {
21371 if(activeTabPath) {
21372 module.debug('Refreshing tab', activeTabPath);
21373 module.changeTab(activeTabPath);
21374 }
21375 },
21376
21377 cache: {
21378
21379 read: function(cacheKey) {
21380 return (cacheKey !== undefined)
21381 ? cache[cacheKey]
21382 : false
21383 ;
21384 },
21385 add: function(cacheKey, content) {
21386 cacheKey = cacheKey || activeTabPath;
21387 module.debug('Adding cached content for', cacheKey);
21388 cache[cacheKey] = content;
21389 },
21390 remove: function(cacheKey) {
21391 cacheKey = cacheKey || activeTabPath;
21392 module.debug('Removing cached content for', cacheKey);
21393 delete cache[cacheKey];
21394 }
21395 },
21396
21397 set: {
21398 auto: function() {
21399 var
21400 url = (typeof settings.path == 'string')
21401 ? settings.path.replace(/\/$/, '') + '/{$tab}'
21402 : '/{$tab}'
21403 ;
21404 module.verbose('Setting up automatic tab retrieval from server', url);
21405 if($.isPlainObject(settings.apiSettings)) {
21406 settings.apiSettings.url = url;
21407 }
21408 else {
21409 settings.apiSettings = {
21410 url: url
21411 };
21412 }
21413 },
21414 loading: function(tabPath) {
21415 var
21416 $tab = module.get.tabElement(tabPath),
21417 isLoading = $tab.hasClass(className.loading)
21418 ;
21419 if(!isLoading) {
21420 module.verbose('Setting loading state for', $tab);
21421 $tab
21422 .addClass(className.loading)
21423 .siblings($tabs)
21424 .removeClass(className.active + ' ' + className.loading)
21425 ;
21426 if($tab.length > 0) {
21427 settings.onRequest.call($tab[0], tabPath);
21428 }
21429 }
21430 },
21431 state: function(state) {
21432 $.address.value(state);
21433 }
21434 },
21435
21436 changeTab: function(tabPath) {
21437 var
21438 pushStateAvailable = (window.history && window.history.pushState),
21439 shouldIgnoreLoad = (pushStateAvailable && settings.ignoreFirstLoad && firstLoad),
21440 remoteContent = (settings.auto || $.isPlainObject(settings.apiSettings) ),
21441 // only add default path if not remote content
21442 pathArray = (remoteContent && !shouldIgnoreLoad)
21443 ? module.utilities.pathToArray(tabPath)
21444 : module.get.defaultPathArray(tabPath)
21445 ;
21446 tabPath = module.utilities.arrayToPath(pathArray);
21447 $.each(pathArray, function(index, tab) {
21448 var
21449 currentPathArray = pathArray.slice(0, index + 1),
21450 currentPath = module.utilities.arrayToPath(currentPathArray),
21451
21452 isTab = module.is.tab(currentPath),
21453 isLastIndex = (index + 1 == pathArray.length),
21454
21455 $tab = module.get.tabElement(currentPath),
21456 $anchor,
21457 nextPathArray,
21458 nextPath,
21459 isLastTab
21460 ;
21461 module.verbose('Looking for tab', tab);
21462 if(isTab) {
21463 module.verbose('Tab was found', tab);
21464 // scope up
21465 activeTabPath = currentPath;
21466 parameterArray = module.utilities.filterArray(pathArray, currentPathArray);
21467
21468 if(isLastIndex) {
21469 isLastTab = true;
21470 }
21471 else {
21472 nextPathArray = pathArray.slice(0, index + 2);
21473 nextPath = module.utilities.arrayToPath(nextPathArray);
21474 isLastTab = ( !module.is.tab(nextPath) );
21475 if(isLastTab) {
21476 module.verbose('Tab parameters found', nextPathArray);
21477 }
21478 }
21479 if(isLastTab && remoteContent) {
21480 if(!shouldIgnoreLoad) {
21481 module.activate.navigation(currentPath);
21482 module.fetch.content(currentPath, tabPath);
21483 }
21484 else {
21485 module.debug('Ignoring remote content on first tab load', currentPath);
21486 firstLoad = false;
21487 module.cache.add(tabPath, $tab.html());
21488 module.activate.all(currentPath);
21489 settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent);
21490 settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent);
21491 }
21492 return false;
21493 }
21494 else {
21495 module.debug('Opened local tab', currentPath);
21496 module.activate.all(currentPath);
21497 if( !module.cache.read(currentPath) ) {
21498 module.cache.add(currentPath, true);
21499 module.debug('First time tab loaded calling tab init');
21500 settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent);
21501 }
21502 settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent);
21503 }
21504
21505 }
21506 else if(tabPath.search('/') == -1 && tabPath !== '') {
21507 // look for in page anchor
21508 $anchor = $('#' + tabPath + ', a[name="' + tabPath + '"]');
21509 currentPath = $anchor.closest('[data-tab]').data(metadata.tab);
21510 $tab = module.get.tabElement(currentPath);
21511 // if anchor exists use parent tab
21512 if($anchor && $anchor.length > 0 && currentPath) {
21513 module.debug('Anchor link used, opening parent tab', $tab, $anchor);
21514 if( !$tab.hasClass(className.active) ) {
21515 setTimeout(function() {
21516 module.scrollTo($anchor);
21517 }, 0);
21518 }
21519 module.activate.all(currentPath);
21520 if( !module.cache.read(currentPath) ) {
21521 module.cache.add(currentPath, true);
21522 module.debug('First time tab loaded calling tab init');
21523 settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent);
21524 }
21525 settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent);
21526 return false;
21527 }
21528 }
21529 else {
21530 module.error(error.missingTab, $module, $context, currentPath);
21531 return false;
21532 }
21533 });
21534 },
21535
21536 scrollTo: function($element) {
21537 var
21538 scrollOffset = ($element && $element.length > 0)
21539 ? $element.offset().top
21540 : false
21541 ;
21542 if(scrollOffset !== false) {
21543 module.debug('Forcing scroll to an in-page link in a hidden tab', scrollOffset, $element);
21544 $(document).scrollTop(scrollOffset);
21545 }
21546 },
21547
21548 update: {
21549 content: function(tabPath, html, evaluateScripts) {
21550 var
21551 $tab = module.get.tabElement(tabPath),
21552 tab = $tab[0]
21553 ;
21554 evaluateScripts = (evaluateScripts !== undefined)
21555 ? evaluateScripts
21556 : settings.evaluateScripts
21557 ;
21558 if(typeof settings.cacheType == 'string' && settings.cacheType.toLowerCase() == 'dom' && typeof html !== 'string') {
21559 $tab
21560 .empty()
21561 .append($(html).clone(true))
21562 ;
21563 }
21564 else {
21565 if(evaluateScripts) {
21566 module.debug('Updating HTML and evaluating inline scripts', tabPath, html);
21567 $tab.html(html);
21568 }
21569 else {
21570 module.debug('Updating HTML', tabPath, html);
21571 tab.innerHTML = html;
21572 }
21573 }
21574 }
21575 },
21576
21577 fetch: {
21578
21579 content: function(tabPath, fullTabPath) {
21580 var
21581 $tab = module.get.tabElement(tabPath),
21582 apiSettings = {
21583 dataType : 'html',
21584 encodeParameters : false,
21585 on : 'now',
21586 cache : settings.alwaysRefresh,
21587 headers : {
21588 'X-Remote': true
21589 },
21590 onSuccess : function(response) {
21591 if(settings.cacheType == 'response') {
21592 module.cache.add(fullTabPath, response);
21593 }
21594 module.update.content(tabPath, response);
21595 if(tabPath == activeTabPath) {
21596 module.debug('Content loaded', tabPath);
21597 module.activate.tab(tabPath);
21598 }
21599 else {
21600 module.debug('Content loaded in background', tabPath);
21601 }
21602 settings.onFirstLoad.call($tab[0], tabPath, parameterArray, historyEvent);
21603 settings.onLoad.call($tab[0], tabPath, parameterArray, historyEvent);
21604
21605 if(settings.loadOnce) {
21606 module.cache.add(fullTabPath, true);
21607 }
21608 else if(typeof settings.cacheType == 'string' && settings.cacheType.toLowerCase() == 'dom' && $tab.children().length > 0) {
21609 setTimeout(function() {
21610 var
21611 $clone = $tab.children().clone(true)
21612 ;
21613 $clone = $clone.not('script');
21614 module.cache.add(fullTabPath, $clone);
21615 }, 0);
21616 }
21617 else {
21618 module.cache.add(fullTabPath, $tab.html());
21619 }
21620 },
21621 urlData: {
21622 tab: fullTabPath
21623 }
21624 },
21625 request = $tab.api('get request') || false,
21626 existingRequest = ( request && request.state() === 'pending' ),
21627 requestSettings,
21628 cachedContent
21629 ;
21630
21631 fullTabPath = fullTabPath || tabPath;
21632 cachedContent = module.cache.read(fullTabPath);
21633
21634
21635 if(settings.cache && cachedContent) {
21636 module.activate.tab(tabPath);
21637 module.debug('Adding cached content', fullTabPath);
21638 if(!settings.loadOnce) {
21639 if(settings.evaluateScripts == 'once') {
21640 module.update.content(tabPath, cachedContent, false);
21641 }
21642 else {
21643 module.update.content(tabPath, cachedContent);
21644 }
21645 }
21646 settings.onLoad.call($tab[0], tabPath, parameterArray, historyEvent);
21647 }
21648 else if(existingRequest) {
21649 module.set.loading(tabPath);
21650 module.debug('Content is already loading', fullTabPath);
21651 }
21652 else if($.api !== undefined) {
21653 requestSettings = $.extend(true, {}, settings.apiSettings, apiSettings);
21654 module.debug('Retrieving remote content', fullTabPath, requestSettings);
21655 module.set.loading(tabPath);
21656 $tab.api(requestSettings);
21657 }
21658 else {
21659 module.error(error.api);
21660 }
21661 }
21662 },
21663
21664 activate: {
21665 all: function(tabPath) {
21666 module.activate.tab(tabPath);
21667 module.activate.navigation(tabPath);
21668 },
21669 tab: function(tabPath) {
21670 var
21671 $tab = module.get.tabElement(tabPath),
21672 $deactiveTabs = (settings.deactivate == 'siblings')
21673 ? $tab.siblings($tabs)
21674 : $tabs.not($tab),
21675 isActive = $tab.hasClass(className.active)
21676 ;
21677 module.verbose('Showing tab content for', $tab);
21678 if(!isActive) {
21679 $tab
21680 .addClass(className.active)
21681 ;
21682 $deactiveTabs
21683 .removeClass(className.active + ' ' + className.loading)
21684 ;
21685 if($tab.length > 0) {
21686 settings.onVisible.call($tab[0], tabPath);
21687 }
21688 }
21689 },
21690 navigation: function(tabPath) {
21691 var
21692 $navigation = module.get.navElement(tabPath),
21693 $deactiveNavigation = (settings.deactivate == 'siblings')
21694 ? $navigation.siblings($allModules)
21695 : $allModules.not($navigation),
21696 isActive = $navigation.hasClass(className.active)
21697 ;
21698 module.verbose('Activating tab navigation for', $navigation, tabPath);
21699 if(!isActive) {
21700 $navigation
21701 .addClass(className.active)
21702 ;
21703 $deactiveNavigation
21704 .removeClass(className.active + ' ' + className.loading)
21705 ;
21706 }
21707 }
21708 },
21709
21710 deactivate: {
21711 all: function() {
21712 module.deactivate.navigation();
21713 module.deactivate.tabs();
21714 },
21715 navigation: function() {
21716 $allModules
21717 .removeClass(className.active)
21718 ;
21719 },
21720 tabs: function() {
21721 $tabs
21722 .removeClass(className.active + ' ' + className.loading)
21723 ;
21724 }
21725 },
21726
21727 is: {
21728 tab: function(tabName) {
21729 return (tabName !== undefined)
21730 ? ( module.get.tabElement(tabName).length > 0 )
21731 : false
21732 ;
21733 }
21734 },
21735
21736 get: {
21737 initialPath: function() {
21738 return $allModules.eq(0).data(metadata.tab) || $tabs.eq(0).data(metadata.tab);
21739 },
21740 path: function() {
21741 return $.address.value();
21742 },
21743 // adds default tabs to tab path
21744 defaultPathArray: function(tabPath) {
21745 return module.utilities.pathToArray( module.get.defaultPath(tabPath) );
21746 },
21747 defaultPath: function(tabPath) {
21748 var
21749 $defaultNav = $allModules.filter('[data-' + metadata.tab + '^="' + tabPath + '/"]').eq(0),
21750 defaultTab = $defaultNav.data(metadata.tab) || false
21751 ;
21752 if( defaultTab ) {
21753 module.debug('Found default tab', defaultTab);
21754 if(recursionDepth < settings.maxDepth) {
21755 recursionDepth++;
21756 return module.get.defaultPath(defaultTab);
21757 }
21758 module.error(error.recursion);
21759 }
21760 else {
21761 module.debug('No default tabs found for', tabPath, $tabs);
21762 }
21763 recursionDepth = 0;
21764 return tabPath;
21765 },
21766 navElement: function(tabPath) {
21767 tabPath = tabPath || activeTabPath;
21768 return $allModules.filter('[data-' + metadata.tab + '="' + tabPath + '"]');
21769 },
21770 tabElement: function(tabPath) {
21771 var
21772 $fullPathTab,
21773 $simplePathTab,
21774 tabPathArray,
21775 lastTab
21776 ;
21777 tabPath = tabPath || activeTabPath;
21778 tabPathArray = module.utilities.pathToArray(tabPath);
21779 lastTab = module.utilities.last(tabPathArray);
21780 $fullPathTab = $tabs.filter('[data-' + metadata.tab + '="' + tabPath + '"]');
21781 $simplePathTab = $tabs.filter('[data-' + metadata.tab + '="' + lastTab + '"]');
21782 return ($fullPathTab.length > 0)
21783 ? $fullPathTab
21784 : $simplePathTab
21785 ;
21786 },
21787 tab: function() {
21788 return activeTabPath;
21789 }
21790 },
21791
21792 utilities: {
21793 filterArray: function(keepArray, removeArray) {
21794 return $.grep(keepArray, function(keepValue) {
21795 return ( $.inArray(keepValue, removeArray) == -1);
21796 });
21797 },
21798 last: function(array) {
21799 return Array.isArray(array)
21800 ? array[ array.length - 1]
21801 : false
21802 ;
21803 },
21804 pathToArray: function(pathName) {
21805 if(pathName === undefined) {
21806 pathName = activeTabPath;
21807 }
21808 return typeof pathName == 'string'
21809 ? pathName.split('/')
21810 : [pathName]
21811 ;
21812 },
21813 arrayToPath: function(pathArray) {
21814 return Array.isArray(pathArray)
21815 ? pathArray.join('/')
21816 : false
21817 ;
21818 }
21819 },
21820
21821 setting: function(name, value) {
21822 module.debug('Changing setting', name, value);
21823 if( $.isPlainObject(name) ) {
21824 $.extend(true, settings, name);
21825 }
21826 else if(value !== undefined) {
21827 if($.isPlainObject(settings[name])) {
21828 $.extend(true, settings[name], value);
21829 }
21830 else {
21831 settings[name] = value;
21832 }
21833 }
21834 else {
21835 return settings[name];
21836 }
21837 },
21838 internal: function(name, value) {
21839 if( $.isPlainObject(name) ) {
21840 $.extend(true, module, name);
21841 }
21842 else if(value !== undefined) {
21843 module[name] = value;
21844 }
21845 else {
21846 return module[name];
21847 }
21848 },
21849 debug: function() {
21850 if(!settings.silent && settings.debug) {
21851 if(settings.performance) {
21852 module.performance.log(arguments);
21853 }
21854 else {
21855 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
21856 module.debug.apply(console, arguments);
21857 }
21858 }
21859 },
21860 verbose: function() {
21861 if(!settings.silent && settings.verbose && settings.debug) {
21862 if(settings.performance) {
21863 module.performance.log(arguments);
21864 }
21865 else {
21866 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
21867 module.verbose.apply(console, arguments);
21868 }
21869 }
21870 },
21871 error: function() {
21872 if(!settings.silent) {
21873 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
21874 module.error.apply(console, arguments);
21875 }
21876 },
21877 performance: {
21878 log: function(message) {
21879 var
21880 currentTime,
21881 executionTime,
21882 previousTime
21883 ;
21884 if(settings.performance) {
21885 currentTime = new Date().getTime();
21886 previousTime = time || currentTime;
21887 executionTime = currentTime - previousTime;
21888 time = currentTime;
21889 performance.push({
21890 'Name' : message[0],
21891 'Arguments' : [].slice.call(message, 1) || '',
21892 'Element' : element,
21893 'Execution Time' : executionTime
21894 });
21895 }
21896 clearTimeout(module.performance.timer);
21897 module.performance.timer = setTimeout(module.performance.display, 500);
21898 },
21899 display: function() {
21900 var
21901 title = settings.name + ':',
21902 totalTime = 0
21903 ;
21904 time = false;
21905 clearTimeout(module.performance.timer);
21906 $.each(performance, function(index, data) {
21907 totalTime += data['Execution Time'];
21908 });
21909 title += ' ' + totalTime + 'ms';
21910 if(moduleSelector) {
21911 title += ' \'' + moduleSelector + '\'';
21912 }
21913 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
21914 console.groupCollapsed(title);
21915 if(console.table) {
21916 console.table(performance);
21917 }
21918 else {
21919 $.each(performance, function(index, data) {
21920 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
21921 });
21922 }
21923 console.groupEnd();
21924 }
21925 performance = [];
21926 }
21927 },
21928 invoke: function(query, passedArguments, context) {
21929 var
21930 object = instance,
21931 maxDepth,
21932 found,
21933 response
21934 ;
21935 passedArguments = passedArguments || queryArguments;
21936 context = element || context;
21937 if(typeof query == 'string' && object !== undefined) {
21938 query = query.split(/[\. ]/);
21939 maxDepth = query.length - 1;
21940 $.each(query, function(depth, value) {
21941 var camelCaseValue = (depth != maxDepth)
21942 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
21943 : query
21944 ;
21945 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
21946 object = object[camelCaseValue];
21947 }
21948 else if( object[camelCaseValue] !== undefined ) {
21949 found = object[camelCaseValue];
21950 return false;
21951 }
21952 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
21953 object = object[value];
21954 }
21955 else if( object[value] !== undefined ) {
21956 found = object[value];
21957 return false;
21958 }
21959 else {
21960 module.error(error.method, query);
21961 return false;
21962 }
21963 });
21964 }
21965 if ( $.isFunction( found ) ) {
21966 response = found.apply(context, passedArguments);
21967 }
21968 else if(found !== undefined) {
21969 response = found;
21970 }
21971 if(Array.isArray(returnedValue)) {
21972 returnedValue.push(response);
21973 }
21974 else if(returnedValue !== undefined) {
21975 returnedValue = [returnedValue, response];
21976 }
21977 else if(response !== undefined) {
21978 returnedValue = response;
21979 }
21980 return found;
21981 }
21982 };
21983 if(methodInvoked) {
21984 if(instance === undefined) {
21985 module.initialize();
21986 }
21987 module.invoke(query);
21988 }
21989 else {
21990 if(instance !== undefined) {
21991 instance.invoke('destroy');
21992 }
21993 module.initialize();
21994 }
21995 })
21996 ;
21997 return (returnedValue !== undefined)
21998 ? returnedValue
21999 : this
22000 ;
22001
22002};
22003
22004// shortcut for tabbed content with no defined navigation
22005$.tab = function() {
22006 $(window).tab.apply(this, arguments);
22007};
22008
22009$.fn.tab.settings = {
22010
22011 name : 'Tab',
22012 namespace : 'tab',
22013
22014 silent : false,
22015 debug : false,
22016 verbose : false,
22017 performance : true,
22018
22019 auto : false, // uses pjax style endpoints fetching content from same url with remote-content headers
22020 history : false, // use browser history
22021 historyType : 'hash', // #/ or html5 state
22022 path : false, // base path of url
22023
22024 context : false, // specify a context that tabs must appear inside
22025 childrenOnly : false, // use only tabs that are children of context
22026 maxDepth : 25, // max depth a tab can be nested
22027
22028 deactivate : 'siblings', // whether tabs should deactivate sibling menu elements or all elements initialized together
22029
22030 alwaysRefresh : false, // load tab content new every tab click
22031 cache : true, // cache the content requests to pull locally
22032 loadOnce : false, // Whether tab data should only be loaded once when using remote content
22033 cacheType : 'response', // Whether to cache exact response, or to html cache contents after scripts execute
22034 ignoreFirstLoad : false, // don't load remote content on first load
22035
22036 apiSettings : false, // settings for api call
22037 evaluateScripts : 'once', // whether inline scripts should be parsed (true/false/once). Once will not re-evaluate on cached content
22038
22039 onFirstLoad : function(tabPath, parameterArray, historyEvent) {}, // called first time loaded
22040 onLoad : function(tabPath, parameterArray, historyEvent) {}, // called on every load
22041 onVisible : function(tabPath, parameterArray, historyEvent) {}, // called every time tab visible
22042 onRequest : function(tabPath, parameterArray, historyEvent) {}, // called ever time a tab beings loading remote content
22043
22044 templates : {
22045 determineTitle: function(tabArray) {} // returns page title for path
22046 },
22047
22048 error: {
22049 api : 'You attempted to load content without API module',
22050 method : 'The method you called is not defined',
22051 missingTab : 'Activated tab cannot be found. Tabs are case-sensitive.',
22052 noContent : 'The tab you specified is missing a content url.',
22053 path : 'History enabled, but no path was specified',
22054 recursion : 'Max recursive depth reached',
22055 legacyInit : 'onTabInit has been renamed to onFirstLoad in 2.0, please adjust your code.',
22056 legacyLoad : 'onTabLoad has been renamed to onLoad in 2.0. Please adjust your code',
22057 state : 'History requires Asual\'s Address library <https://github.com/asual/jquery-address>'
22058 },
22059
22060 metadata : {
22061 tab : 'tab',
22062 loaded : 'loaded',
22063 promise: 'promise'
22064 },
22065
22066 className : {
22067 loading : 'loading',
22068 active : 'active'
22069 },
22070
22071 selector : {
22072 tabs : '.ui.tab',
22073 ui : '.ui'
22074 }
22075
22076};
22077
22078})( jQuery, window, document );
22079
22080/*!
22081 * # Semantic UI 2.7.2 - Toast
22082 * http://github.com/semantic-org/semantic-ui/
22083 *
22084 *
22085 * Released under the MIT license
22086 * http://opensource.org/licenses/MIT
22087 *
22088 */
22089
22090;(function ($, window, document, undefined) {
22091
22092'use strict';
22093
22094$.isFunction = $.isFunction || function(obj) {
22095 return typeof obj === "function" && typeof obj.nodeType !== "number";
22096};
22097
22098window = (typeof window != 'undefined' && window.Math == Math)
22099 ? window
22100 : (typeof self != 'undefined' && self.Math == Math)
22101 ? self
22102 : Function('return this')()
22103;
22104
22105$.fn.toast = function(parameters) {
22106 var
22107 $allModules = $(this),
22108 moduleSelector = $allModules.selector || '',
22109
22110 time = new Date().getTime(),
22111 performance = [],
22112
22113 query = arguments[0],
22114 methodInvoked = (typeof query == 'string'),
22115 queryArguments = [].slice.call(arguments, 1),
22116 returnedValue
22117 ;
22118 $allModules
22119 .each(function() {
22120 var
22121 settings = ( $.isPlainObject(parameters) )
22122 ? $.extend(true, {}, $.fn.toast.settings, parameters)
22123 : $.extend({}, $.fn.toast.settings),
22124
22125 className = settings.className,
22126 selector = settings.selector,
22127 error = settings.error,
22128 namespace = settings.namespace,
22129
22130 eventNamespace = '.' + namespace,
22131 moduleNamespace = namespace + '-module',
22132
22133 $module = $(this),
22134 $toastBox = $('<div/>',{'class':settings.className.box}),
22135 $toast = $('<div/>'),
22136 $progress = $('<div/>',{'class':settings.className.progress+' '+settings.class}),
22137 $progressBar = $('<div/>',{'class':'bar'}),
22138
22139 $close = $('<i/>',{'class':'close icon'}),
22140 $context = (settings.context)
22141 ? $(settings.context)
22142 : $('body'),
22143
22144 element = this,
22145 instance = $module.data(moduleNamespace),
22146
22147 module
22148 ;
22149 module = {
22150
22151 initialize: function() {
22152 module.verbose('Initializing element');
22153 if(typeof settings.showProgress !== 'string' || ['top','bottom'].indexOf(settings.showProgress) === -1 ) {
22154 settings.showProgress = false;
22155 }
22156 if (!module.has.container()) {
22157 module.create.container();
22158 }
22159
22160 module.create.toast();
22161
22162 module.bind.events();
22163
22164 if(settings.displayTime > 0) {
22165 module.closeTimer = setTimeout(module.close, settings.displayTime+(!!settings.showProgress ? 300 : 0));
22166 }
22167 module.show();
22168 },
22169
22170 destroy: function() {
22171 module.debug('Removing toast', $toast);
22172 $toast.remove();
22173 $toast = undefined;
22174 settings.onRemove.call($toast, element);
22175 },
22176
22177 show: function(callback) {
22178 callback = callback || function(){};
22179 module.debug('Showing toast');
22180 if(settings.onShow.call($toast, element) === false) {
22181 module.debug('onShow callback returned false, cancelling toast animation');
22182 return;
22183 }
22184 module.animate.show(callback);
22185 },
22186
22187 close: function(callback) {
22188 if(module.closeTimer) {
22189 clearTimeout(module.closeTimer);
22190 }
22191 callback = callback || function(){};
22192 module.remove.visible();
22193 module.unbind.events();
22194 module.animate.close(callback);
22195
22196 },
22197
22198 create: {
22199 container: function() {
22200 module.verbose('Creating container');
22201 $context.append('<div class="ui ' + settings.position + ' ' + className.container + '"></div>');
22202 },
22203 toast: function() {
22204 var $content = $('<div/>').addClass(className.content);
22205 module.verbose('Creating toast');
22206 if(settings.closeIcon) {
22207 $toast.append($close);
22208 $toast.css('cursor','default');
22209 }
22210
22211 var iconClass = typeof settings.showIcon === 'string' ? settings.showIcon : settings.showIcon && settings.icons[settings.class] ? settings.icons[settings.class] : '';
22212 if (iconClass != '') {
22213 var $icon = $('<i/>').addClass(iconClass + ' ' + className.icon);
22214
22215 $toast
22216 .addClass(className.icon)
22217 .append($icon)
22218 ;
22219 }
22220
22221 if (settings.title !== '') {
22222 var
22223 $title = $('<div/>')
22224 .addClass(className.title)
22225 .text(settings.title)
22226 ;
22227
22228 $content.append($title);
22229 }
22230
22231 $content.append($('<div/>').html(settings.message));
22232
22233 $toast
22234 .addClass(settings.class + ' ' + className.toast)
22235 .append($content)
22236 ;
22237 $toast.css('opacity', settings.opacity);
22238 if(settings.compact || $toast.hasClass('compact')) {
22239 $toastBox.addClass('compact');
22240 }
22241 if($toast.hasClass('toast') && !$toast.hasClass('inverted')){
22242 $progress.addClass('inverted');
22243 } else {
22244 $progress.removeClass('inverted');
22245 }
22246 $toast = $toastBox.append($toast);
22247 if(!!settings.showProgress && settings.displayTime > 0){
22248 $progress
22249 .addClass(settings.showProgress)
22250 .append($progressBar);
22251 if ($progress.hasClass('top')) {
22252 $toast.prepend($progress);
22253 } else {
22254 $toast.append($progress);
22255 }
22256 $progressBar.css('transition','width '+(settings.displayTime/1000)+'s linear');
22257 $progressBar.width(settings.progressUp?'0%':'100%');
22258 setTimeout(function() {
22259 if(typeof $progress !== 'undefined'){
22260 $progressBar.width(settings.progressUp?'100%':'0%');
22261 }
22262 },300);
22263 }
22264 if (settings.newestOnTop) {
22265 $toast.prependTo(module.get.container());
22266 }
22267 else {
22268 $toast.appendTo(module.get.container());
22269 }
22270 }
22271 },
22272
22273 bind: {
22274 events: function() {
22275 module.debug('Binding events to toast');
22276 (settings.closeIcon ? $close : $toast)
22277 .on('click' + eventNamespace, module.event.click)
22278 ;
22279 }
22280 },
22281
22282 unbind: {
22283 events: function() {
22284 module.debug('Unbinding events to toast');
22285 (settings.closeIcon ? $close : $toast)
22286 .off('click' + eventNamespace)
22287 ;
22288 }
22289 },
22290
22291 animate: {
22292 show: function(callback) {
22293 callback = $.isFunction(callback) ? callback : function(){};
22294 if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
22295 module.set.visible();
22296 $toast
22297 .transition({
22298 animation : settings.transition.showMethod + ' in',
22299 queue : false,
22300 debug : settings.debug,
22301 verbose : settings.verbose,
22302 duration : settings.transition.showDuration,
22303 onComplete : function() {
22304 callback.call($toast, element);
22305 settings.onVisible.call($toast, element);
22306 }
22307 })
22308 ;
22309 }
22310 else {
22311 module.error(error.noTransition);
22312 }
22313 },
22314 close: function(callback) {
22315 callback = $.isFunction(callback) ? callback : function(){};
22316 module.debug('Closing toast');
22317 if(settings.onHide.call($toast, element) === false) {
22318 module.debug('onHide callback returned false, cancelling toast animation');
22319 return;
22320 }
22321 if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
22322 $toast
22323 .transition({
22324 animation : settings.transition.hideMethod + ' out',
22325 queue : false,
22326 duration : settings.transition.hideDuration,
22327 debug : settings.debug,
22328 verbose : settings.verbose,
22329
22330 onBeforeHide: function(callback){
22331 callback = $.isFunction(callback)?callback : function(){};
22332 if(settings.transition.closeEasing !== ''){
22333 $toast.css('opacity',0);
22334 $toast.wrap('<div/>').parent().slideUp(500,settings.transition.closeEasing,function(){
22335 $toast.parent().remove();
22336 callback.call($toast);
22337 });
22338 } else {
22339 callback.call($toast);
22340 }
22341 },
22342 onComplete : function() {
22343 module.destroy();
22344 callback.call($toast, element);
22345 settings.onHidden.call($toast, element);
22346 }
22347 })
22348 ;
22349 }
22350 else {
22351 module.error(error.noTransition);
22352 }
22353 }
22354 },
22355
22356 has: {
22357 container: function() {
22358 module.verbose('Determining if there is already a container');
22359 return ($context.find(module.helpers.toClass(settings.position) + selector.container).length > 0);
22360 }
22361 },
22362
22363 get: {
22364 container: function() {
22365 return ($context.find(module.helpers.toClass(settings.position) + selector.container)[0]);
22366 }
22367 },
22368
22369 set: {
22370 visible: function() {
22371 $toast.addClass(className.visible);
22372 }
22373 },
22374
22375 remove: {
22376 visible: function() {
22377 $toast.removeClass(className.visible);
22378 }
22379 },
22380
22381 event: {
22382 click: function() {
22383 settings.onClick.call($toast, element);
22384 module.close();
22385 }
22386 },
22387
22388 helpers: {
22389 toClass: function(selector) {
22390 var
22391 classes = selector.split(' '),
22392 result = ''
22393 ;
22394
22395 classes.forEach(function (element) {
22396 result += '.' + element;
22397 });
22398
22399 return result;
22400 }
22401 },
22402
22403 setting: function(name, value) {
22404 module.debug('Changing setting', name, value);
22405 if( $.isPlainObject(name) ) {
22406 $.extend(true, settings, name);
22407 }
22408 else if(value !== undefined) {
22409 if($.isPlainObject(settings[name])) {
22410 $.extend(true, settings[name], value);
22411 }
22412 else {
22413 settings[name] = value;
22414 }
22415 }
22416 else {
22417 return settings[name];
22418 }
22419 },
22420 internal: function(name, value) {
22421 if( $.isPlainObject(name) ) {
22422 $.extend(true, module, name);
22423 }
22424 else if(value !== undefined) {
22425 module[name] = value;
22426 }
22427 else {
22428 return module[name];
22429 }
22430 },
22431 debug: function() {
22432 if(!settings.silent && settings.debug) {
22433 if(settings.performance) {
22434 module.performance.log(arguments);
22435 }
22436 else {
22437 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
22438 module.debug.apply(console, arguments);
22439 }
22440 }
22441 },
22442 verbose: function() {
22443 if(!settings.silent && settings.verbose && settings.debug) {
22444 if(settings.performance) {
22445 module.performance.log(arguments);
22446 }
22447 else {
22448 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
22449 module.verbose.apply(console, arguments);
22450 }
22451 }
22452 },
22453 error: function() {
22454 if(!settings.silent) {
22455 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
22456 module.error.apply(console, arguments);
22457 }
22458 },
22459 performance: {
22460 log: function(message) {
22461 var
22462 currentTime,
22463 executionTime,
22464 previousTime
22465 ;
22466 if(settings.performance) {
22467 currentTime = new Date().getTime();
22468 previousTime = time || currentTime;
22469 executionTime = currentTime - previousTime;
22470 time = currentTime;
22471 performance.push({
22472 'Name' : message[0],
22473 'Arguments' : [].slice.call(message, 1) || '',
22474 'Element' : element,
22475 'Execution Time' : executionTime
22476 });
22477 }
22478 clearTimeout(module.performance.timer);
22479 module.performance.timer = setTimeout(module.performance.display, 500);
22480 },
22481 display: function() {
22482 var
22483 title = settings.name + ':',
22484 totalTime = 0
22485 ;
22486 time = false;
22487 clearTimeout(module.performance.timer);
22488 $.each(performance, function(index, data) {
22489 totalTime += data['Execution Time'];
22490 });
22491 title += ' ' + totalTime + 'ms';
22492 if(moduleSelector) {
22493 title += ' \'' + moduleSelector + '\'';
22494 }
22495 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
22496 console.groupCollapsed(title);
22497 if(console.table) {
22498 console.table(performance);
22499 }
22500 else {
22501 $.each(performance, function(index, data) {
22502 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
22503 });
22504 }
22505 console.groupEnd();
22506 }
22507 performance = [];
22508 }
22509 },
22510 invoke: function(query, passedArguments, context) {
22511 var
22512 object = instance,
22513 maxDepth,
22514 found,
22515 response
22516 ;
22517 passedArguments = passedArguments || queryArguments;
22518 context = element || context;
22519 if(typeof query == 'string' && object !== undefined) {
22520 query = query.split(/[\. ]/);
22521 maxDepth = query.length - 1;
22522 $.each(query, function(depth, value) {
22523 var camelCaseValue = (depth != maxDepth)
22524 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
22525 : query
22526 ;
22527 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
22528 object = object[camelCaseValue];
22529 }
22530 else if( object[camelCaseValue] !== undefined ) {
22531 found = object[camelCaseValue];
22532 return false;
22533 }
22534 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
22535 object = object[value];
22536 }
22537 else if( object[value] !== undefined ) {
22538 found = object[value];
22539 return false;
22540 }
22541 else {
22542 module.error(error.method, query);
22543 return false;
22544 }
22545 });
22546 }
22547 if ( $.isFunction( found ) ) {
22548 response = found.apply(context, passedArguments);
22549 }
22550 else if(found !== undefined) {
22551 response = found;
22552 }
22553 if(Array.isArray(returnedValue)) {
22554 returnedValue.push(response);
22555 }
22556 else if(returnedValue !== undefined) {
22557 returnedValue = [returnedValue, response];
22558 }
22559 else if(response !== undefined) {
22560 returnedValue = response;
22561 }
22562 return found;
22563 }
22564 };
22565
22566 if(methodInvoked) {
22567 if(instance === undefined) {
22568 module.initialize();
22569 }
22570 module.invoke(query);
22571 }
22572 else {
22573 if(instance !== undefined) {
22574 instance.invoke('destroy');
22575 }
22576 module.initialize();
22577 }
22578 })
22579 ;
22580
22581 return (returnedValue !== undefined)
22582 ? returnedValue
22583 : this
22584 ;
22585};
22586
22587$.fn.toast.settings = {
22588
22589 name : 'Toast',
22590 namespace : 'toast',
22591
22592 silent : false,
22593 debug : false,
22594 verbose : false,
22595 performance : true,
22596
22597 context : 'body',
22598
22599 position : 'top right',
22600 class : 'info',
22601
22602 title : '',
22603 message : '',
22604 displayTime : 3000, // set to zero to require manually dismissal, otherwise hides on its own
22605 showIcon : true,
22606 newestOnTop : false,
22607 showProgress : false,
22608 progressUp : true, //if false, the bar will start at 100% and decrease to 0%
22609 opacity : 1,
22610 compact : true,
22611 closeIcon : false,
22612
22613 // transition settings
22614 transition : {
22615 showMethod : 'scale',
22616 showDuration : 500,
22617 hideMethod : 'scale',
22618 hideDuration : 500,
22619 closeEasing : 'easeOutBounce' //Set to empty string to stack the closed toast area immediately (old behaviour)
22620 },
22621
22622 error: {
22623 method : 'The method you called is not defined.',
22624 noTransition : 'This module requires ui transitions <https://github.com/Semantic-Org/UI-Transition>'
22625 },
22626
22627 className : {
22628 container : 'toast-container',
22629 box : 'toast-box',
22630 progress : 'ui attached active progress',
22631 toast : 'ui toast',
22632 icon : 'icon',
22633 visible : 'visible',
22634 content : 'content',
22635 title : 'header'
22636 },
22637
22638 icons : {
22639 info : 'info',
22640 success : 'checkmark',
22641 warning : 'warning',
22642 error : 'times'
22643 },
22644
22645 selector : {
22646 container : '.toast-container',
22647 box : '.toast-box',
22648 toast : '.ui.toast'
22649 },
22650
22651 // callbacks
22652 onShow : function(){},
22653 onVisible : function(){},
22654 onClick : function(){},
22655 onHide : function(){},
22656 onHidden : function(){},
22657 onRemove : function(){},
22658};
22659
22660$.extend( $.easing, {
22661 easeOutBounce: function (x, t, b, c, d) {
22662 if ((t/=d) < (1/2.75)) {
22663 return c*(7.5625*t*t) + b;
22664 } else if (t < (2/2.75)) {
22665 return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
22666 } else if (t < (2.5/2.75)) {
22667 return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
22668 } else {
22669 return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
22670 }
22671 }
22672});
22673
22674
22675})( jQuery, window, document );
22676
22677/*!
22678 * # Semantic UI 2.7.2 - Transition
22679 * http://github.com/semantic-org/semantic-ui/
22680 *
22681 *
22682 * Released under the MIT license
22683 * http://opensource.org/licenses/MIT
22684 *
22685 */
22686
22687;(function ($, window, document, undefined) {
22688
22689'use strict';
22690
22691$.isFunction = $.isFunction || function(obj) {
22692 return typeof obj === "function" && typeof obj.nodeType !== "number";
22693};
22694
22695window = (typeof window != 'undefined' && window.Math == Math)
22696 ? window
22697 : (typeof self != 'undefined' && self.Math == Math)
22698 ? self
22699 : Function('return this')()
22700;
22701
22702$.fn.transition = function() {
22703 var
22704 $allModules = $(this),
22705 moduleSelector = $allModules.selector || '',
22706
22707 time = new Date().getTime(),
22708 performance = [],
22709
22710 moduleArguments = arguments,
22711 query = moduleArguments[0],
22712 queryArguments = [].slice.call(arguments, 1),
22713 methodInvoked = (typeof query === 'string'),
22714
22715 requestAnimationFrame = window.requestAnimationFrame
22716 || window.mozRequestAnimationFrame
22717 || window.webkitRequestAnimationFrame
22718 || window.msRequestAnimationFrame
22719 || function(callback) { setTimeout(callback, 0); },
22720
22721 returnedValue
22722 ;
22723 $allModules
22724 .each(function(index) {
22725 var
22726 $module = $(this),
22727 element = this,
22728
22729 // set at run time
22730 settings,
22731 instance,
22732
22733 error,
22734 className,
22735 metadata,
22736 animationEnd,
22737 animationName,
22738
22739 namespace,
22740 moduleNamespace,
22741 eventNamespace,
22742 module
22743 ;
22744
22745 module = {
22746
22747 initialize: function() {
22748
22749 // get full settings
22750 settings = module.get.settings.apply(element, moduleArguments);
22751
22752 // shorthand
22753 className = settings.className;
22754 error = settings.error;
22755 metadata = settings.metadata;
22756
22757 // define namespace
22758 eventNamespace = '.' + settings.namespace;
22759 moduleNamespace = 'module-' + settings.namespace;
22760 instance = $module.data(moduleNamespace) || module;
22761
22762 // get vendor specific events
22763 animationEnd = module.get.animationEndEvent();
22764
22765 if(methodInvoked) {
22766 methodInvoked = module.invoke(query);
22767 }
22768
22769 // method not invoked, lets run an animation
22770 if(methodInvoked === false) {
22771 module.verbose('Converted arguments into settings object', settings);
22772 if(settings.interval) {
22773 module.delay(settings.animate);
22774 }
22775 else {
22776 module.animate();
22777 }
22778 module.instantiate();
22779 }
22780 },
22781
22782 instantiate: function() {
22783 module.verbose('Storing instance of module', module);
22784 instance = module;
22785 $module
22786 .data(moduleNamespace, instance)
22787 ;
22788 },
22789
22790 destroy: function() {
22791 module.verbose('Destroying previous module for', element);
22792 $module
22793 .removeData(moduleNamespace)
22794 ;
22795 },
22796
22797 refresh: function() {
22798 module.verbose('Refreshing display type on next animation');
22799 delete module.displayType;
22800 },
22801
22802 forceRepaint: function() {
22803 module.verbose('Forcing element repaint');
22804 var
22805 $parentElement = $module.parent(),
22806 $nextElement = $module.next()
22807 ;
22808 if($nextElement.length === 0) {
22809 $module.detach().appendTo($parentElement);
22810 }
22811 else {
22812 $module.detach().insertBefore($nextElement);
22813 }
22814 },
22815
22816 repaint: function() {
22817 module.verbose('Repainting element');
22818 var
22819 fakeAssignment = element.offsetWidth
22820 ;
22821 },
22822
22823 delay: function(interval) {
22824 var
22825 direction = module.get.animationDirection(),
22826 shouldReverse,
22827 delay
22828 ;
22829 if(!direction) {
22830 direction = module.can.transition()
22831 ? module.get.direction()
22832 : 'static'
22833 ;
22834 }
22835 interval = (interval !== undefined)
22836 ? interval
22837 : settings.interval
22838 ;
22839 shouldReverse = (settings.reverse == 'auto' && direction == className.outward);
22840 delay = (shouldReverse || settings.reverse == true)
22841 ? ($allModules.length - index) * settings.interval
22842 : index * settings.interval
22843 ;
22844 module.debug('Delaying animation by', delay);
22845 setTimeout(module.animate, delay);
22846 },
22847
22848 animate: function(overrideSettings) {
22849 settings = overrideSettings || settings;
22850 if(!module.is.supported()) {
22851 module.error(error.support);
22852 return false;
22853 }
22854 module.debug('Preparing animation', settings.animation);
22855 if(module.is.animating()) {
22856 if(settings.queue) {
22857 if(!settings.allowRepeats && module.has.direction() && module.is.occurring() && module.queuing !== true) {
22858 module.debug('Animation is currently occurring, preventing queueing same animation', settings.animation);
22859 }
22860 else {
22861 module.queue(settings.animation);
22862 }
22863 return false;
22864 }
22865 else if(!settings.allowRepeats && module.is.occurring()) {
22866 module.debug('Animation is already occurring, will not execute repeated animation', settings.animation);
22867 return false;
22868 }
22869 else {
22870 module.debug('New animation started, completing previous early', settings.animation);
22871 instance.complete();
22872 }
22873 }
22874 if( module.can.animate() ) {
22875 module.set.animating(settings.animation);
22876 }
22877 else {
22878 module.error(error.noAnimation, settings.animation, element);
22879 }
22880 },
22881
22882 reset: function() {
22883 module.debug('Resetting animation to beginning conditions');
22884 module.remove.animationCallbacks();
22885 module.restore.conditions();
22886 module.remove.animating();
22887 },
22888
22889 queue: function(animation) {
22890 module.debug('Queueing animation of', animation);
22891 module.queuing = true;
22892 $module
22893 .one(animationEnd + '.queue' + eventNamespace, function() {
22894 module.queuing = false;
22895 module.repaint();
22896 module.animate.apply(this, settings);
22897 })
22898 ;
22899 },
22900
22901 complete: function (event) {
22902 module.debug('Animation complete', settings.animation);
22903 module.remove.completeCallback();
22904 module.remove.failSafe();
22905 if(!module.is.looping()) {
22906 if( module.is.outward() ) {
22907 module.verbose('Animation is outward, hiding element');
22908 module.restore.conditions();
22909 module.hide();
22910 }
22911 else if( module.is.inward() ) {
22912 module.verbose('Animation is outward, showing element');
22913 module.restore.conditions();
22914 module.show();
22915 }
22916 else {
22917 module.verbose('Static animation completed');
22918 module.restore.conditions();
22919 settings.onComplete.call(element);
22920 }
22921 }
22922 },
22923
22924 force: {
22925 visible: function() {
22926 var
22927 style = $module.attr('style'),
22928 userStyle = module.get.userStyle(style),
22929 displayType = module.get.displayType(),
22930 overrideStyle = userStyle + 'display: ' + displayType + ' !important;',
22931 inlineDisplay = $module[0].style.display,
22932 mustStayHidden = !displayType || (inlineDisplay === 'none' && settings.skipInlineHidden) || $module[0].tagName.match(/(script|link|style)/i)
22933 ;
22934 if (mustStayHidden){
22935 module.remove.transition();
22936 return false;
22937 }
22938 module.verbose('Overriding default display to show element', displayType);
22939 $module
22940 .attr('style', overrideStyle)
22941 ;
22942 if(style === '') {
22943 $module.removeAttr('style');
22944 }
22945 return true;
22946 },
22947 hidden: function() {
22948 var
22949 style = $module.attr('style'),
22950 currentDisplay = $module.css('display'),
22951 emptyStyle = (style === undefined || style === '')
22952 ;
22953 if(currentDisplay !== 'none' && !module.is.hidden()) {
22954 module.verbose('Overriding default display to hide element');
22955 $module
22956 .css('display', 'none')
22957 ;
22958 }
22959 else if(emptyStyle) {
22960 $module
22961 .removeAttr('style')
22962 ;
22963 }
22964 }
22965 },
22966
22967 has: {
22968 direction: function(animation) {
22969 var
22970 hasDirection = false
22971 ;
22972 animation = animation || settings.animation;
22973 if(typeof animation === 'string') {
22974 animation = animation.split(' ');
22975 $.each(animation, function(index, word){
22976 if(word === className.inward || word === className.outward) {
22977 hasDirection = true;
22978 }
22979 });
22980 }
22981 return hasDirection;
22982 },
22983 inlineDisplay: function() {
22984 var
22985 style = $module.attr('style') || ''
22986 ;
22987 return Array.isArray(style.match(/display.*?;/, ''));
22988 }
22989 },
22990
22991 set: {
22992 animating: function(animation) {
22993 // override display if necessary so animation appears visibly
22994 if(module.force.visible()) {
22995 var
22996 animationClass,
22997 direction
22998 ;
22999 // remove previous callbacks
23000 module.remove.completeCallback();
23001
23002 // determine exact animation
23003 animation = animation || settings.animation;
23004 animationClass = module.get.animationClass(animation);
23005
23006 // save animation class in cache to restore class names
23007 module.save.animation(animationClass);
23008
23009 module.remove.hidden();
23010 module.remove.direction();
23011
23012 module.start.animation(animationClass);
23013 }
23014 },
23015 duration: function(animationName, duration) {
23016 duration = duration || settings.duration;
23017 duration = (typeof duration == 'number')
23018 ? duration + 'ms'
23019 : duration
23020 ;
23021 if(duration || duration === 0) {
23022 module.verbose('Setting animation duration', duration);
23023 $module
23024 .css({
23025 'animation-duration': duration
23026 })
23027 ;
23028 }
23029 },
23030 direction: function(direction) {
23031 direction = direction || module.get.direction();
23032 if(direction == className.inward) {
23033 module.set.inward();
23034 }
23035 else {
23036 module.set.outward();
23037 }
23038 },
23039 looping: function() {
23040 module.debug('Transition set to loop');
23041 $module
23042 .addClass(className.looping)
23043 ;
23044 },
23045 hidden: function() {
23046 $module
23047 .addClass(className.transition)
23048 .addClass(className.hidden)
23049 ;
23050 },
23051 inward: function() {
23052 module.debug('Setting direction to inward');
23053 $module
23054 .removeClass(className.outward)
23055 .addClass(className.inward)
23056 ;
23057 },
23058 outward: function() {
23059 module.debug('Setting direction to outward');
23060 $module
23061 .removeClass(className.inward)
23062 .addClass(className.outward)
23063 ;
23064 },
23065 visible: function() {
23066 $module
23067 .addClass(className.transition)
23068 .addClass(className.visible)
23069 ;
23070 }
23071 },
23072
23073 start: {
23074 animation: function(animationClass) {
23075 animationClass = animationClass || module.get.animationClass();
23076 module.debug('Starting tween', animationClass);
23077 $module
23078 .addClass(animationClass)
23079 .one(animationEnd + '.complete' + eventNamespace, module.complete)
23080 ;
23081 if(settings.useFailSafe) {
23082 module.add.failSafe();
23083 }
23084 module.set.duration(settings.duration);
23085 settings.onStart.call(element);
23086 }
23087 },
23088
23089 save: {
23090 animation: function(animation) {
23091 if(!module.cache) {
23092 module.cache = {};
23093 }
23094 module.cache.animation = animation;
23095 },
23096 displayType: function(displayType) {
23097 if(displayType !== 'none') {
23098 $module.data(metadata.displayType, displayType);
23099 }
23100 },
23101 transitionExists: function(animation, exists) {
23102 $.fn.transition.exists[animation] = exists;
23103 module.verbose('Saving existence of transition', animation, exists);
23104 }
23105 },
23106
23107 restore: {
23108 conditions: function() {
23109 var
23110 animation = module.get.currentAnimation()
23111 ;
23112 if(animation) {
23113 $module
23114 .removeClass(animation)
23115 ;
23116 module.verbose('Removing animation class', module.cache);
23117 }
23118 module.remove.duration();
23119 }
23120 },
23121
23122 add: {
23123 failSafe: function() {
23124 var
23125 duration = module.get.duration()
23126 ;
23127 module.timer = setTimeout(function() {
23128 $module.triggerHandler(animationEnd);
23129 }, duration + settings.failSafeDelay);
23130 module.verbose('Adding fail safe timer', module.timer);
23131 }
23132 },
23133
23134 remove: {
23135 animating: function() {
23136 $module.removeClass(className.animating);
23137 },
23138 animationCallbacks: function() {
23139 module.remove.queueCallback();
23140 module.remove.completeCallback();
23141 },
23142 queueCallback: function() {
23143 $module.off('.queue' + eventNamespace);
23144 },
23145 completeCallback: function() {
23146 $module.off('.complete' + eventNamespace);
23147 },
23148 display: function() {
23149 $module.css('display', '');
23150 },
23151 direction: function() {
23152 $module
23153 .removeClass(className.inward)
23154 .removeClass(className.outward)
23155 ;
23156 },
23157 duration: function() {
23158 $module
23159 .css('animation-duration', '')
23160 ;
23161 },
23162 failSafe: function() {
23163 module.verbose('Removing fail safe timer', module.timer);
23164 if(module.timer) {
23165 clearTimeout(module.timer);
23166 }
23167 },
23168 hidden: function() {
23169 $module.removeClass(className.hidden);
23170 },
23171 visible: function() {
23172 $module.removeClass(className.visible);
23173 },
23174 looping: function() {
23175 module.debug('Transitions are no longer looping');
23176 if( module.is.looping() ) {
23177 module.reset();
23178 $module
23179 .removeClass(className.looping)
23180 ;
23181 }
23182 },
23183 transition: function() {
23184 $module
23185 .removeClass(className.transition)
23186 .removeClass(className.visible)
23187 .removeClass(className.hidden)
23188 ;
23189 }
23190 },
23191 get: {
23192 settings: function(animation, duration, onComplete) {
23193 // single settings object
23194 if(typeof animation == 'object') {
23195 return $.extend(true, {}, $.fn.transition.settings, animation);
23196 }
23197 // all arguments provided
23198 else if(typeof onComplete == 'function') {
23199 return $.extend({}, $.fn.transition.settings, {
23200 animation : animation,
23201 onComplete : onComplete,
23202 duration : duration
23203 });
23204 }
23205 // only duration provided
23206 else if(typeof duration == 'string' || typeof duration == 'number') {
23207 return $.extend({}, $.fn.transition.settings, {
23208 animation : animation,
23209 duration : duration
23210 });
23211 }
23212 // duration is actually settings object
23213 else if(typeof duration == 'object') {
23214 return $.extend({}, $.fn.transition.settings, duration, {
23215 animation : animation
23216 });
23217 }
23218 // duration is actually callback
23219 else if(typeof duration == 'function') {
23220 return $.extend({}, $.fn.transition.settings, {
23221 animation : animation,
23222 onComplete : duration
23223 });
23224 }
23225 // only animation provided
23226 else {
23227 return $.extend({}, $.fn.transition.settings, {
23228 animation : animation
23229 });
23230 }
23231 },
23232 animationClass: function(animation) {
23233 var
23234 animationClass = animation || settings.animation,
23235 directionClass = (module.can.transition() && !module.has.direction())
23236 ? module.get.direction() + ' '
23237 : ''
23238 ;
23239 return className.animating + ' '
23240 + className.transition + ' '
23241 + directionClass
23242 + animationClass
23243 ;
23244 },
23245 currentAnimation: function() {
23246 return (module.cache && module.cache.animation !== undefined)
23247 ? module.cache.animation
23248 : false
23249 ;
23250 },
23251 currentDirection: function() {
23252 return module.is.inward()
23253 ? className.inward
23254 : className.outward
23255 ;
23256 },
23257 direction: function() {
23258 return module.is.hidden() || !module.is.visible()
23259 ? className.inward
23260 : className.outward
23261 ;
23262 },
23263 animationDirection: function(animation) {
23264 var
23265 direction
23266 ;
23267 animation = animation || settings.animation;
23268 if(typeof animation === 'string') {
23269 animation = animation.split(' ');
23270 // search animation name for out/in class
23271 $.each(animation, function(index, word){
23272 if(word === className.inward) {
23273 direction = className.inward;
23274 }
23275 else if(word === className.outward) {
23276 direction = className.outward;
23277 }
23278 });
23279 }
23280 // return found direction
23281 if(direction) {
23282 return direction;
23283 }
23284 return false;
23285 },
23286 duration: function(duration) {
23287 duration = duration || settings.duration;
23288 if(duration === false) {
23289 duration = $module.css('animation-duration') || 0;
23290 }
23291 return (typeof duration === 'string')
23292 ? (duration.indexOf('ms') > -1)
23293 ? parseFloat(duration)
23294 : parseFloat(duration) * 1000
23295 : duration
23296 ;
23297 },
23298 displayType: function(shouldDetermine) {
23299 shouldDetermine = (shouldDetermine !== undefined)
23300 ? shouldDetermine
23301 : true
23302 ;
23303 if(settings.displayType) {
23304 return settings.displayType;
23305 }
23306 if(shouldDetermine && $module.data(metadata.displayType) === undefined) {
23307 var currentDisplay = $module.css('display');
23308 if(currentDisplay === '' || currentDisplay === 'none'){
23309 // create fake element to determine display state
23310 module.can.transition(true);
23311 } else {
23312 module.save.displayType(currentDisplay);
23313 }
23314 }
23315 return $module.data(metadata.displayType);
23316 },
23317 userStyle: function(style) {
23318 style = style || $module.attr('style') || '';
23319 return style.replace(/display.*?;/, '');
23320 },
23321 transitionExists: function(animation) {
23322 return $.fn.transition.exists[animation];
23323 },
23324 animationStartEvent: function() {
23325 var
23326 element = document.createElement('div'),
23327 animations = {
23328 'animation' :'animationstart',
23329 'OAnimation' :'oAnimationStart',
23330 'MozAnimation' :'mozAnimationStart',
23331 'WebkitAnimation' :'webkitAnimationStart'
23332 },
23333 animation
23334 ;
23335 for(animation in animations){
23336 if( element.style[animation] !== undefined ){
23337 return animations[animation];
23338 }
23339 }
23340 return false;
23341 },
23342 animationEndEvent: function() {
23343 var
23344 element = document.createElement('div'),
23345 animations = {
23346 'animation' :'animationend',
23347 'OAnimation' :'oAnimationEnd',
23348 'MozAnimation' :'mozAnimationEnd',
23349 'WebkitAnimation' :'webkitAnimationEnd'
23350 },
23351 animation
23352 ;
23353 for(animation in animations){
23354 if( element.style[animation] !== undefined ){
23355 return animations[animation];
23356 }
23357 }
23358 return false;
23359 }
23360
23361 },
23362
23363 can: {
23364 transition: function(forced) {
23365 var
23366 animation = settings.animation,
23367 transitionExists = module.get.transitionExists(animation),
23368 displayType = module.get.displayType(false),
23369 elementClass,
23370 tagName,
23371 $clone,
23372 currentAnimation,
23373 inAnimation,
23374 directionExists
23375 ;
23376 if( transitionExists === undefined || forced) {
23377 module.verbose('Determining whether animation exists');
23378 elementClass = $module.attr('class');
23379 tagName = $module.prop('tagName');
23380
23381 $clone = $('<' + tagName + ' />').addClass( elementClass ).insertAfter($module);
23382 currentAnimation = $clone
23383 .addClass(animation)
23384 .removeClass(className.inward)
23385 .removeClass(className.outward)
23386 .addClass(className.animating)
23387 .addClass(className.transition)
23388 .css('animationName')
23389 ;
23390 inAnimation = $clone
23391 .addClass(className.inward)
23392 .css('animationName')
23393 ;
23394 if(!displayType) {
23395 displayType = $clone
23396 .attr('class', elementClass)
23397 .removeAttr('style')
23398 .removeClass(className.hidden)
23399 .removeClass(className.visible)
23400 .show()
23401 .css('display')
23402 ;
23403 module.verbose('Determining final display state', displayType);
23404 module.save.displayType(displayType);
23405 }
23406
23407 $clone.remove();
23408 if(currentAnimation != inAnimation) {
23409 module.debug('Direction exists for animation', animation);
23410 directionExists = true;
23411 }
23412 else if(currentAnimation == 'none' || !currentAnimation) {
23413 module.debug('No animation defined in css', animation);
23414 return;
23415 }
23416 else {
23417 module.debug('Static animation found', animation, displayType);
23418 directionExists = false;
23419 }
23420 module.save.transitionExists(animation, directionExists);
23421 }
23422 return (transitionExists !== undefined)
23423 ? transitionExists
23424 : directionExists
23425 ;
23426 },
23427 animate: function() {
23428 // can transition does not return a value if animation does not exist
23429 return (module.can.transition() !== undefined);
23430 }
23431 },
23432
23433 is: {
23434 animating: function() {
23435 return $module.hasClass(className.animating);
23436 },
23437 inward: function() {
23438 return $module.hasClass(className.inward);
23439 },
23440 outward: function() {
23441 return $module.hasClass(className.outward);
23442 },
23443 looping: function() {
23444 return $module.hasClass(className.looping);
23445 },
23446 occurring: function(animation) {
23447 animation = animation || settings.animation;
23448 animation = '.' + animation.replace(' ', '.');
23449 return ( $module.filter(animation).length > 0 );
23450 },
23451 visible: function() {
23452 return $module.is(':visible');
23453 },
23454 hidden: function() {
23455 return $module.css('visibility') === 'hidden';
23456 },
23457 supported: function() {
23458 return(animationEnd !== false);
23459 }
23460 },
23461
23462 hide: function() {
23463 module.verbose('Hiding element');
23464 if( module.is.animating() ) {
23465 module.reset();
23466 }
23467 element.blur(); // IE will trigger focus change if element is not blurred before hiding
23468 module.remove.display();
23469 module.remove.visible();
23470 if($.isFunction(settings.onBeforeHide)){
23471 settings.onBeforeHide.call(element,function(){
23472 module.hideNow();
23473 });
23474 } else {
23475 module.hideNow();
23476 }
23477
23478 },
23479
23480 hideNow: function() {
23481 module.set.hidden();
23482 module.force.hidden();
23483 settings.onHide.call(element);
23484 settings.onComplete.call(element);
23485 // module.repaint();
23486 },
23487
23488 show: function(display) {
23489 module.verbose('Showing element', display);
23490 if(module.force.visible()) {
23491 module.remove.hidden();
23492 module.set.visible();
23493 settings.onShow.call(element);
23494 settings.onComplete.call(element);
23495 // module.repaint();
23496 }
23497 },
23498
23499 toggle: function() {
23500 if( module.is.visible() ) {
23501 module.hide();
23502 }
23503 else {
23504 module.show();
23505 }
23506 },
23507
23508 stop: function() {
23509 module.debug('Stopping current animation');
23510 $module.triggerHandler(animationEnd);
23511 },
23512
23513 stopAll: function() {
23514 module.debug('Stopping all animation');
23515 module.remove.queueCallback();
23516 $module.triggerHandler(animationEnd);
23517 },
23518
23519 clear: {
23520 queue: function() {
23521 module.debug('Clearing animation queue');
23522 module.remove.queueCallback();
23523 }
23524 },
23525
23526 enable: function() {
23527 module.verbose('Starting animation');
23528 $module.removeClass(className.disabled);
23529 },
23530
23531 disable: function() {
23532 module.debug('Stopping animation');
23533 $module.addClass(className.disabled);
23534 },
23535
23536 setting: function(name, value) {
23537 module.debug('Changing setting', name, value);
23538 if( $.isPlainObject(name) ) {
23539 $.extend(true, settings, name);
23540 }
23541 else if(value !== undefined) {
23542 if($.isPlainObject(settings[name])) {
23543 $.extend(true, settings[name], value);
23544 }
23545 else {
23546 settings[name] = value;
23547 }
23548 }
23549 else {
23550 return settings[name];
23551 }
23552 },
23553 internal: function(name, value) {
23554 if( $.isPlainObject(name) ) {
23555 $.extend(true, module, name);
23556 }
23557 else if(value !== undefined) {
23558 module[name] = value;
23559 }
23560 else {
23561 return module[name];
23562 }
23563 },
23564 debug: function() {
23565 if(!settings.silent && settings.debug) {
23566 if(settings.performance) {
23567 module.performance.log(arguments);
23568 }
23569 else {
23570 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
23571 module.debug.apply(console, arguments);
23572 }
23573 }
23574 },
23575 verbose: function() {
23576 if(!settings.silent && settings.verbose && settings.debug) {
23577 if(settings.performance) {
23578 module.performance.log(arguments);
23579 }
23580 else {
23581 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
23582 module.verbose.apply(console, arguments);
23583 }
23584 }
23585 },
23586 error: function() {
23587 if(!settings.silent) {
23588 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
23589 module.error.apply(console, arguments);
23590 }
23591 },
23592 performance: {
23593 log: function(message) {
23594 var
23595 currentTime,
23596 executionTime,
23597 previousTime
23598 ;
23599 if(settings.performance) {
23600 currentTime = new Date().getTime();
23601 previousTime = time || currentTime;
23602 executionTime = currentTime - previousTime;
23603 time = currentTime;
23604 performance.push({
23605 'Name' : message[0],
23606 'Arguments' : [].slice.call(message, 1) || '',
23607 'Element' : element,
23608 'Execution Time' : executionTime
23609 });
23610 }
23611 clearTimeout(module.performance.timer);
23612 module.performance.timer = setTimeout(module.performance.display, 500);
23613 },
23614 display: function() {
23615 var
23616 title = settings.name + ':',
23617 totalTime = 0
23618 ;
23619 time = false;
23620 clearTimeout(module.performance.timer);
23621 $.each(performance, function(index, data) {
23622 totalTime += data['Execution Time'];
23623 });
23624 title += ' ' + totalTime + 'ms';
23625 if(moduleSelector) {
23626 title += ' \'' + moduleSelector + '\'';
23627 }
23628 if($allModules.length > 1) {
23629 title += ' ' + '(' + $allModules.length + ')';
23630 }
23631 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
23632 console.groupCollapsed(title);
23633 if(console.table) {
23634 console.table(performance);
23635 }
23636 else {
23637 $.each(performance, function(index, data) {
23638 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
23639 });
23640 }
23641 console.groupEnd();
23642 }
23643 performance = [];
23644 }
23645 },
23646 // modified for transition to return invoke success
23647 invoke: function(query, passedArguments, context) {
23648 var
23649 object = instance,
23650 maxDepth,
23651 found,
23652 response
23653 ;
23654 passedArguments = passedArguments || queryArguments;
23655 context = element || context;
23656 if(typeof query == 'string' && object !== undefined) {
23657 query = query.split(/[\. ]/);
23658 maxDepth = query.length - 1;
23659 $.each(query, function(depth, value) {
23660 var camelCaseValue = (depth != maxDepth)
23661 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
23662 : query
23663 ;
23664 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
23665 object = object[camelCaseValue];
23666 }
23667 else if( object[camelCaseValue] !== undefined ) {
23668 found = object[camelCaseValue];
23669 return false;
23670 }
23671 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
23672 object = object[value];
23673 }
23674 else if( object[value] !== undefined ) {
23675 found = object[value];
23676 return false;
23677 }
23678 else {
23679 return false;
23680 }
23681 });
23682 }
23683 if ( $.isFunction( found ) ) {
23684 response = found.apply(context, passedArguments);
23685 }
23686 else if(found !== undefined) {
23687 response = found;
23688 }
23689
23690 if(Array.isArray(returnedValue)) {
23691 returnedValue.push(response);
23692 }
23693 else if(returnedValue !== undefined) {
23694 returnedValue = [returnedValue, response];
23695 }
23696 else if(response !== undefined) {
23697 returnedValue = response;
23698 }
23699 return (found !== undefined)
23700 ? found
23701 : false
23702 ;
23703 }
23704 };
23705 module.initialize();
23706 })
23707 ;
23708 return (returnedValue !== undefined)
23709 ? returnedValue
23710 : this
23711 ;
23712};
23713
23714// Records if CSS transition is available
23715$.fn.transition.exists = {};
23716
23717$.fn.transition.settings = {
23718
23719 // module info
23720 name : 'Transition',
23721
23722 // hide all output from this component regardless of other settings
23723 silent : false,
23724
23725 // debug content outputted to console
23726 debug : false,
23727
23728 // verbose debug output
23729 verbose : false,
23730
23731 // performance data output
23732 performance : true,
23733
23734 // event namespace
23735 namespace : 'transition',
23736
23737 // delay between animations in group
23738 interval : 0,
23739
23740 // whether group animations should be reversed
23741 reverse : 'auto',
23742
23743 // animation callback event
23744 onStart : function() {},
23745 onComplete : function() {},
23746 onShow : function() {},
23747 onHide : function() {},
23748
23749 // whether timeout should be used to ensure callback fires in cases animationend does not
23750 useFailSafe : true,
23751
23752 // delay in ms for fail safe
23753 failSafeDelay : 100,
23754
23755 // whether EXACT animation can occur twice in a row
23756 allowRepeats : false,
23757
23758 // Override final display type on visible
23759 displayType : false,
23760
23761 // animation duration
23762 animation : 'fade',
23763 duration : false,
23764
23765 // new animations will occur after previous ones
23766 queue : true,
23767
23768// whether initially inline hidden objects should be skipped for transition
23769 skipInlineHidden: false,
23770
23771 metadata : {
23772 displayType: 'display'
23773 },
23774
23775 className : {
23776 animating : 'animating',
23777 disabled : 'disabled',
23778 hidden : 'hidden',
23779 inward : 'in',
23780 loading : 'loading',
23781 looping : 'looping',
23782 outward : 'out',
23783 transition : 'transition',
23784 visible : 'visible'
23785 },
23786
23787 // possible errors
23788 error: {
23789 noAnimation : 'Element is no longer attached to DOM. Unable to animate. Use silent setting to surpress this warning in production.',
23790 repeated : 'That animation is already occurring, cancelling repeated animation',
23791 method : 'The method you called is not defined',
23792 support : 'This browser does not support CSS animations'
23793 }
23794
23795};
23796
23797
23798})( jQuery, window, document );
23799
23800/*!
23801 * # Semantic UI 2.7.2 - API
23802 * http://github.com/semantic-org/semantic-ui/
23803 *
23804 *
23805 * Released under the MIT license
23806 * http://opensource.org/licenses/MIT
23807 *
23808 */
23809
23810;(function ($, window, document, undefined) {
23811
23812'use strict';
23813
23814$.isWindow = $.isWindow || function(obj) {
23815 return obj != null && obj === obj.window;
23816};
23817
23818var
23819 window = (typeof window != 'undefined' && window.Math == Math)
23820 ? window
23821 : (typeof self != 'undefined' && self.Math == Math)
23822 ? self
23823 : Function('return this')()
23824;
23825
23826$.api = $.fn.api = function(parameters) {
23827
23828 var
23829 // use window context if none specified
23830 $allModules = $.isFunction(this)
23831 ? $(window)
23832 : $(this),
23833 moduleSelector = $allModules.selector || '',
23834 time = new Date().getTime(),
23835 performance = [],
23836
23837 query = arguments[0],
23838 methodInvoked = (typeof query == 'string'),
23839 queryArguments = [].slice.call(arguments, 1),
23840
23841 returnedValue
23842 ;
23843
23844 $allModules
23845 .each(function() {
23846 var
23847 settings = ( $.isPlainObject(parameters) )
23848 ? $.extend(true, {}, $.fn.api.settings, parameters)
23849 : $.extend({}, $.fn.api.settings),
23850
23851 // internal aliases
23852 namespace = settings.namespace,
23853 metadata = settings.metadata,
23854 selector = settings.selector,
23855 error = settings.error,
23856 className = settings.className,
23857
23858 // define namespaces for modules
23859 eventNamespace = '.' + namespace,
23860 moduleNamespace = 'module-' + namespace,
23861
23862 // element that creates request
23863 $module = $(this),
23864 $form = $module.closest(selector.form),
23865
23866 // context used for state
23867 $context = (settings.stateContext)
23868 ? $(settings.stateContext)
23869 : $module,
23870
23871 // request details
23872 ajaxSettings,
23873 requestSettings,
23874 url,
23875 data,
23876 requestStartTime,
23877
23878 // standard module
23879 element = this,
23880 context = $context[0],
23881 instance = $module.data(moduleNamespace),
23882 module
23883 ;
23884
23885 module = {
23886
23887 initialize: function() {
23888 if(!methodInvoked) {
23889 module.bind.events();
23890 }
23891 module.instantiate();
23892 },
23893
23894 instantiate: function() {
23895 module.verbose('Storing instance of module', module);
23896 instance = module;
23897 $module
23898 .data(moduleNamespace, instance)
23899 ;
23900 },
23901
23902 destroy: function() {
23903 module.verbose('Destroying previous module for', element);
23904 $module
23905 .removeData(moduleNamespace)
23906 .off(eventNamespace)
23907 ;
23908 },
23909
23910 bind: {
23911 events: function() {
23912 var
23913 triggerEvent = module.get.event()
23914 ;
23915 if( triggerEvent ) {
23916 module.verbose('Attaching API events to element', triggerEvent);
23917 $module
23918 .on(triggerEvent + eventNamespace, module.event.trigger)
23919 ;
23920 }
23921 else if(settings.on == 'now') {
23922 module.debug('Querying API endpoint immediately');
23923 module.query();
23924 }
23925 }
23926 },
23927
23928 decode: {
23929 json: function(response) {
23930 if(response !== undefined && typeof response == 'string') {
23931 try {
23932 response = JSON.parse(response);
23933 }
23934 catch(e) {
23935 // isnt json string
23936 }
23937 }
23938 return response;
23939 }
23940 },
23941
23942 read: {
23943 cachedResponse: function(url) {
23944 var
23945 response
23946 ;
23947 if(window.Storage === undefined) {
23948 module.error(error.noStorage);
23949 return;
23950 }
23951 response = sessionStorage.getItem(url);
23952 module.debug('Using cached response', url, response);
23953 response = module.decode.json(response);
23954 return response;
23955 }
23956 },
23957 write: {
23958 cachedResponse: function(url, response) {
23959 if(response && response === '') {
23960 module.debug('Response empty, not caching', response);
23961 return;
23962 }
23963 if(window.Storage === undefined) {
23964 module.error(error.noStorage);
23965 return;
23966 }
23967 if( $.isPlainObject(response) ) {
23968 response = JSON.stringify(response);
23969 }
23970 sessionStorage.setItem(url, response);
23971 module.verbose('Storing cached response for url', url, response);
23972 }
23973 },
23974
23975 query: function() {
23976
23977 if(module.is.disabled()) {
23978 module.debug('Element is disabled API request aborted');
23979 return;
23980 }
23981
23982 if(module.is.loading()) {
23983 if(settings.interruptRequests) {
23984 module.debug('Interrupting previous request');
23985 module.abort();
23986 }
23987 else {
23988 module.debug('Cancelling request, previous request is still pending');
23989 return;
23990 }
23991 }
23992
23993 // pass element metadata to url (value, text)
23994 if(settings.defaultData) {
23995 $.extend(true, settings.urlData, module.get.defaultData());
23996 }
23997
23998 // Add form content
23999 if(settings.serializeForm) {
24000 settings.data = module.add.formData(settings.data);
24001 }
24002
24003 // call beforesend and get any settings changes
24004 requestSettings = module.get.settings();
24005
24006 // check if before send cancelled request
24007 if(requestSettings === false) {
24008 module.cancelled = true;
24009 module.error(error.beforeSend);
24010 return;
24011 }
24012 else {
24013 module.cancelled = false;
24014 }
24015
24016 // get url
24017 url = module.get.templatedURL();
24018
24019 if(!url && !module.is.mocked()) {
24020 module.error(error.missingURL);
24021 return;
24022 }
24023
24024 // replace variables
24025 url = module.add.urlData( url );
24026 // missing url parameters
24027 if( !url && !module.is.mocked()) {
24028 return;
24029 }
24030
24031 requestSettings.url = settings.base + url;
24032
24033 // look for jQuery ajax parameters in settings
24034 ajaxSettings = $.extend(true, {}, settings, {
24035 type : settings.method || settings.type,
24036 data : data,
24037 url : settings.base + url,
24038 beforeSend : settings.beforeXHR,
24039 success : function() {},
24040 failure : function() {},
24041 complete : function() {}
24042 });
24043
24044 module.debug('Querying URL', ajaxSettings.url);
24045 module.verbose('Using AJAX settings', ajaxSettings);
24046 if(settings.cache === 'local' && module.read.cachedResponse(url)) {
24047 module.debug('Response returned from local cache');
24048 module.request = module.create.request();
24049 module.request.resolveWith(context, [ module.read.cachedResponse(url) ]);
24050 return;
24051 }
24052
24053 if( !settings.throttle ) {
24054 module.debug('Sending request', data, ajaxSettings.method);
24055 module.send.request();
24056 }
24057 else {
24058 if(!settings.throttleFirstRequest && !module.timer) {
24059 module.debug('Sending request', data, ajaxSettings.method);
24060 module.send.request();
24061 module.timer = setTimeout(function(){}, settings.throttle);
24062 }
24063 else {
24064 module.debug('Throttling request', settings.throttle);
24065 clearTimeout(module.timer);
24066 module.timer = setTimeout(function() {
24067 if(module.timer) {
24068 delete module.timer;
24069 }
24070 module.debug('Sending throttled request', data, ajaxSettings.method);
24071 module.send.request();
24072 }, settings.throttle);
24073 }
24074 }
24075
24076 },
24077
24078 should: {
24079 removeError: function() {
24080 return ( settings.hideError === true || (settings.hideError === 'auto' && !module.is.form()) );
24081 }
24082 },
24083
24084 is: {
24085 disabled: function() {
24086 return ($module.filter(selector.disabled).length > 0);
24087 },
24088 expectingJSON: function() {
24089 return settings.dataType === 'json' || settings.dataType === 'jsonp';
24090 },
24091 form: function() {
24092 return $module.is('form') || $context.is('form');
24093 },
24094 mocked: function() {
24095 return (settings.mockResponse || settings.mockResponseAsync || settings.response || settings.responseAsync);
24096 },
24097 input: function() {
24098 return $module.is('input');
24099 },
24100 loading: function() {
24101 return (module.request)
24102 ? (module.request.state() == 'pending')
24103 : false
24104 ;
24105 },
24106 abortedRequest: function(xhr) {
24107 if(xhr && xhr.readyState !== undefined && xhr.readyState === 0) {
24108 module.verbose('XHR request determined to be aborted');
24109 return true;
24110 }
24111 else {
24112 module.verbose('XHR request was not aborted');
24113 return false;
24114 }
24115 },
24116 validResponse: function(response) {
24117 if( (!module.is.expectingJSON()) || !$.isFunction(settings.successTest) ) {
24118 module.verbose('Response is not JSON, skipping validation', settings.successTest, response);
24119 return true;
24120 }
24121 module.debug('Checking JSON returned success', settings.successTest, response);
24122 if( settings.successTest(response) ) {
24123 module.debug('Response passed success test', response);
24124 return true;
24125 }
24126 else {
24127 module.debug('Response failed success test', response);
24128 return false;
24129 }
24130 }
24131 },
24132
24133 was: {
24134 cancelled: function() {
24135 return (module.cancelled || false);
24136 },
24137 succesful: function() {
24138 return (module.request && module.request.state() == 'resolved');
24139 },
24140 failure: function() {
24141 return (module.request && module.request.state() == 'rejected');
24142 },
24143 complete: function() {
24144 return (module.request && (module.request.state() == 'resolved' || module.request.state() == 'rejected') );
24145 }
24146 },
24147
24148 add: {
24149 urlData: function(url, urlData) {
24150 var
24151 requiredVariables,
24152 optionalVariables
24153 ;
24154 if(url) {
24155 requiredVariables = url.match(settings.regExp.required);
24156 optionalVariables = url.match(settings.regExp.optional);
24157 urlData = urlData || settings.urlData;
24158 if(requiredVariables) {
24159 module.debug('Looking for required URL variables', requiredVariables);
24160 $.each(requiredVariables, function(index, templatedString) {
24161 var
24162 // allow legacy {$var} style
24163 variable = (templatedString.indexOf('$') !== -1)
24164 ? templatedString.substr(2, templatedString.length - 3)
24165 : templatedString.substr(1, templatedString.length - 2),
24166 value = ($.isPlainObject(urlData) && urlData[variable] !== undefined)
24167 ? urlData[variable]
24168 : ($module.data(variable) !== undefined)
24169 ? $module.data(variable)
24170 : ($context.data(variable) !== undefined)
24171 ? $context.data(variable)
24172 : urlData[variable]
24173 ;
24174 // remove value
24175 if(value === undefined) {
24176 module.error(error.requiredParameter, variable, url);
24177 url = false;
24178 return false;
24179 }
24180 else {
24181 module.verbose('Found required variable', variable, value);
24182 value = (settings.encodeParameters)
24183 ? module.get.urlEncodedValue(value)
24184 : value
24185 ;
24186 url = url.replace(templatedString, value);
24187 }
24188 });
24189 }
24190 if(optionalVariables) {
24191 module.debug('Looking for optional URL variables', requiredVariables);
24192 $.each(optionalVariables, function(index, templatedString) {
24193 var
24194 // allow legacy {/$var} style
24195 variable = (templatedString.indexOf('$') !== -1)
24196 ? templatedString.substr(3, templatedString.length - 4)
24197 : templatedString.substr(2, templatedString.length - 3),
24198 value = ($.isPlainObject(urlData) && urlData[variable] !== undefined)
24199 ? urlData[variable]
24200 : ($module.data(variable) !== undefined)
24201 ? $module.data(variable)
24202 : ($context.data(variable) !== undefined)
24203 ? $context.data(variable)
24204 : urlData[variable]
24205 ;
24206 // optional replacement
24207 if(value !== undefined) {
24208 module.verbose('Optional variable Found', variable, value);
24209 url = url.replace(templatedString, value);
24210 }
24211 else {
24212 module.verbose('Optional variable not found', variable);
24213 // remove preceding slash if set
24214 if(url.indexOf('/' + templatedString) !== -1) {
24215 url = url.replace('/' + templatedString, '');
24216 }
24217 else {
24218 url = url.replace(templatedString, '');
24219 }
24220 }
24221 });
24222 }
24223 }
24224 return url;
24225 },
24226 formData: function(data) {
24227 var
24228 canSerialize = ($.fn.serializeObject !== undefined),
24229 formData = (canSerialize)
24230 ? $form.serializeObject()
24231 : $form.serialize(),
24232 hasOtherData
24233 ;
24234 data = data || settings.data;
24235 hasOtherData = $.isPlainObject(data);
24236
24237 if(hasOtherData) {
24238 if(canSerialize) {
24239 module.debug('Extending existing data with form data', data, formData);
24240 data = $.extend(true, {}, data, formData);
24241 }
24242 else {
24243 module.error(error.missingSerialize);
24244 module.debug('Cant extend data. Replacing data with form data', data, formData);
24245 data = formData;
24246 }
24247 }
24248 else {
24249 module.debug('Adding form data', formData);
24250 data = formData;
24251 }
24252 return data;
24253 }
24254 },
24255
24256 send: {
24257 request: function() {
24258 module.set.loading();
24259 module.request = module.create.request();
24260 if( module.is.mocked() ) {
24261 module.mockedXHR = module.create.mockedXHR();
24262 }
24263 else {
24264 module.xhr = module.create.xhr();
24265 }
24266 settings.onRequest.call(context, module.request, module.xhr);
24267 }
24268 },
24269
24270 event: {
24271 trigger: function(event) {
24272 module.query();
24273 if(event.type == 'submit' || event.type == 'click') {
24274 event.preventDefault();
24275 }
24276 },
24277 xhr: {
24278 always: function() {
24279 // nothing special
24280 },
24281 done: function(response, textStatus, xhr) {
24282 var
24283 context = this,
24284 elapsedTime = (new Date().getTime() - requestStartTime),
24285 timeLeft = (settings.loadingDuration - elapsedTime),
24286 translatedResponse = ( $.isFunction(settings.onResponse) )
24287 ? module.is.expectingJSON() && !settings.rawResponse
24288 ? settings.onResponse.call(context, $.extend(true, {}, response))
24289 : settings.onResponse.call(context, response)
24290 : false
24291 ;
24292 timeLeft = (timeLeft > 0)
24293 ? timeLeft
24294 : 0
24295 ;
24296 if(translatedResponse) {
24297 module.debug('Modified API response in onResponse callback', settings.onResponse, translatedResponse, response);
24298 response = translatedResponse;
24299 }
24300 if(timeLeft > 0) {
24301 module.debug('Response completed early delaying state change by', timeLeft);
24302 }
24303 setTimeout(function() {
24304 if( module.is.validResponse(response) ) {
24305 module.request.resolveWith(context, [response, xhr]);
24306 }
24307 else {
24308 module.request.rejectWith(context, [xhr, 'invalid']);
24309 }
24310 }, timeLeft);
24311 },
24312 fail: function(xhr, status, httpMessage) {
24313 var
24314 context = this,
24315 elapsedTime = (new Date().getTime() - requestStartTime),
24316 timeLeft = (settings.loadingDuration - elapsedTime)
24317 ;
24318 timeLeft = (timeLeft > 0)
24319 ? timeLeft
24320 : 0
24321 ;
24322 if(timeLeft > 0) {
24323 module.debug('Response completed early delaying state change by', timeLeft);
24324 }
24325 setTimeout(function() {
24326 if( module.is.abortedRequest(xhr) ) {
24327 module.request.rejectWith(context, [xhr, 'aborted', httpMessage]);
24328 }
24329 else {
24330 module.request.rejectWith(context, [xhr, 'error', status, httpMessage]);
24331 }
24332 }, timeLeft);
24333 }
24334 },
24335 request: {
24336 done: function(response, xhr) {
24337 module.debug('Successful API Response', response);
24338 if(settings.cache === 'local' && url) {
24339 module.write.cachedResponse(url, response);
24340 module.debug('Saving server response locally', module.cache);
24341 }
24342 settings.onSuccess.call(context, response, $module, xhr);
24343 },
24344 complete: function(firstParameter, secondParameter) {
24345 var
24346 xhr,
24347 response
24348 ;
24349 // have to guess callback parameters based on request success
24350 if( module.was.succesful() ) {
24351 response = firstParameter;
24352 xhr = secondParameter;
24353 }
24354 else {
24355 xhr = firstParameter;
24356 response = module.get.responseFromXHR(xhr);
24357 }
24358 module.remove.loading();
24359 settings.onComplete.call(context, response, $module, xhr);
24360 },
24361 fail: function(xhr, status, httpMessage) {
24362 var
24363 // pull response from xhr if available
24364 response = module.get.responseFromXHR(xhr),
24365 errorMessage = module.get.errorFromRequest(response, status, httpMessage)
24366 ;
24367 if(status == 'aborted') {
24368 module.debug('XHR Aborted (Most likely caused by page navigation or CORS Policy)', status, httpMessage);
24369 settings.onAbort.call(context, status, $module, xhr);
24370 return true;
24371 }
24372 else if(status == 'invalid') {
24373 module.debug('JSON did not pass success test. A server-side error has most likely occurred', response);
24374 }
24375 else if(status == 'error') {
24376 if(xhr !== undefined) {
24377 module.debug('XHR produced a server error', status, httpMessage);
24378 // make sure we have an error to display to console
24379 if( xhr.status != 200 && httpMessage !== undefined && httpMessage !== '') {
24380 module.error(error.statusMessage + httpMessage, ajaxSettings.url);
24381 }
24382 settings.onError.call(context, errorMessage, $module, xhr);
24383 }
24384 }
24385
24386 if(settings.errorDuration && status !== 'aborted') {
24387 module.debug('Adding error state');
24388 module.set.error();
24389 if( module.should.removeError() ) {
24390 setTimeout(module.remove.error, settings.errorDuration);
24391 }
24392 }
24393 module.debug('API Request failed', errorMessage, xhr);
24394 settings.onFailure.call(context, response, $module, xhr);
24395 }
24396 }
24397 },
24398
24399 create: {
24400
24401 request: function() {
24402 // api request promise
24403 return $.Deferred()
24404 .always(module.event.request.complete)
24405 .done(module.event.request.done)
24406 .fail(module.event.request.fail)
24407 ;
24408 },
24409
24410 mockedXHR: function () {
24411 var
24412 // xhr does not simulate these properties of xhr but must return them
24413 textStatus = false,
24414 status = false,
24415 httpMessage = false,
24416 responder = settings.mockResponse || settings.response,
24417 asyncResponder = settings.mockResponseAsync || settings.responseAsync,
24418 asyncCallback,
24419 response,
24420 mockedXHR
24421 ;
24422
24423 mockedXHR = $.Deferred()
24424 .always(module.event.xhr.complete)
24425 .done(module.event.xhr.done)
24426 .fail(module.event.xhr.fail)
24427 ;
24428
24429 if(responder) {
24430 if( $.isFunction(responder) ) {
24431 module.debug('Using specified synchronous callback', responder);
24432 response = responder.call(context, requestSettings);
24433 }
24434 else {
24435 module.debug('Using settings specified response', responder);
24436 response = responder;
24437 }
24438 // simulating response
24439 mockedXHR.resolveWith(context, [ response, textStatus, { responseText: response }]);
24440 }
24441 else if( $.isFunction(asyncResponder) ) {
24442 asyncCallback = function(response) {
24443 module.debug('Async callback returned response', response);
24444
24445 if(response) {
24446 mockedXHR.resolveWith(context, [ response, textStatus, { responseText: response }]);
24447 }
24448 else {
24449 mockedXHR.rejectWith(context, [{ responseText: response }, status, httpMessage]);
24450 }
24451 };
24452 module.debug('Using specified async response callback', asyncResponder);
24453 asyncResponder.call(context, requestSettings, asyncCallback);
24454 }
24455 return mockedXHR;
24456 },
24457
24458 xhr: function() {
24459 var
24460 xhr
24461 ;
24462 // ajax request promise
24463 xhr = $.ajax(ajaxSettings)
24464 .always(module.event.xhr.always)
24465 .done(module.event.xhr.done)
24466 .fail(module.event.xhr.fail)
24467 ;
24468 module.verbose('Created server request', xhr, ajaxSettings);
24469 return xhr;
24470 }
24471 },
24472
24473 set: {
24474 error: function() {
24475 module.verbose('Adding error state to element', $context);
24476 $context.addClass(className.error);
24477 },
24478 loading: function() {
24479 module.verbose('Adding loading state to element', $context);
24480 $context.addClass(className.loading);
24481 requestStartTime = new Date().getTime();
24482 }
24483 },
24484
24485 remove: {
24486 error: function() {
24487 module.verbose('Removing error state from element', $context);
24488 $context.removeClass(className.error);
24489 },
24490 loading: function() {
24491 module.verbose('Removing loading state from element', $context);
24492 $context.removeClass(className.loading);
24493 }
24494 },
24495
24496 get: {
24497 responseFromXHR: function(xhr) {
24498 return $.isPlainObject(xhr)
24499 ? (module.is.expectingJSON())
24500 ? module.decode.json(xhr.responseText)
24501 : xhr.responseText
24502 : false
24503 ;
24504 },
24505 errorFromRequest: function(response, status, httpMessage) {
24506 return ($.isPlainObject(response) && response.error !== undefined)
24507 ? response.error // use json error message
24508 : (settings.error[status] !== undefined) // use server error message
24509 ? settings.error[status]
24510 : httpMessage
24511 ;
24512 },
24513 request: function() {
24514 return module.request || false;
24515 },
24516 xhr: function() {
24517 return module.xhr || false;
24518 },
24519 settings: function() {
24520 var
24521 runSettings
24522 ;
24523 runSettings = settings.beforeSend.call(context, settings);
24524 if(runSettings) {
24525 if(runSettings.success !== undefined) {
24526 module.debug('Legacy success callback detected', runSettings);
24527 module.error(error.legacyParameters, runSettings.success);
24528 runSettings.onSuccess = runSettings.success;
24529 }
24530 if(runSettings.failure !== undefined) {
24531 module.debug('Legacy failure callback detected', runSettings);
24532 module.error(error.legacyParameters, runSettings.failure);
24533 runSettings.onFailure = runSettings.failure;
24534 }
24535 if(runSettings.complete !== undefined) {
24536 module.debug('Legacy complete callback detected', runSettings);
24537 module.error(error.legacyParameters, runSettings.complete);
24538 runSettings.onComplete = runSettings.complete;
24539 }
24540 }
24541 if(runSettings === undefined) {
24542 module.error(error.noReturnedValue);
24543 }
24544 if(runSettings === false) {
24545 return runSettings;
24546 }
24547 return (runSettings !== undefined)
24548 ? $.extend(true, {}, runSettings)
24549 : $.extend(true, {}, settings)
24550 ;
24551 },
24552 urlEncodedValue: function(value) {
24553 var
24554 decodedValue = window.decodeURIComponent(value),
24555 encodedValue = window.encodeURIComponent(value),
24556 alreadyEncoded = (decodedValue !== value)
24557 ;
24558 if(alreadyEncoded) {
24559 module.debug('URL value is already encoded, avoiding double encoding', value);
24560 return value;
24561 }
24562 module.verbose('Encoding value using encodeURIComponent', value, encodedValue);
24563 return encodedValue;
24564 },
24565 defaultData: function() {
24566 var
24567 data = {}
24568 ;
24569 if( !$.isWindow(element) ) {
24570 if( module.is.input() ) {
24571 data.value = $module.val();
24572 }
24573 else if( module.is.form() ) {
24574
24575 }
24576 else {
24577 data.text = $module.text();
24578 }
24579 }
24580 return data;
24581 },
24582 event: function() {
24583 if( $.isWindow(element) || settings.on == 'now' ) {
24584 module.debug('API called without element, no events attached');
24585 return false;
24586 }
24587 else if(settings.on == 'auto') {
24588 if( $module.is('input') ) {
24589 return (element.oninput !== undefined)
24590 ? 'input'
24591 : (element.onpropertychange !== undefined)
24592 ? 'propertychange'
24593 : 'keyup'
24594 ;
24595 }
24596 else if( $module.is('form') ) {
24597 return 'submit';
24598 }
24599 else {
24600 return 'click';
24601 }
24602 }
24603 else {
24604 return settings.on;
24605 }
24606 },
24607 templatedURL: function(action) {
24608 action = action || $module.data(metadata.action) || settings.action || false;
24609 url = $module.data(metadata.url) || settings.url || false;
24610 if(url) {
24611 module.debug('Using specified url', url);
24612 return url;
24613 }
24614 if(action) {
24615 module.debug('Looking up url for action', action, settings.api);
24616 if(settings.api[action] === undefined && !module.is.mocked()) {
24617 module.error(error.missingAction, settings.action, settings.api);
24618 return;
24619 }
24620 url = settings.api[action];
24621 }
24622 else if( module.is.form() ) {
24623 url = $module.attr('action') || $context.attr('action') || false;
24624 module.debug('No url or action specified, defaulting to form action', url);
24625 }
24626 return url;
24627 }
24628 },
24629
24630 abort: function() {
24631 var
24632 xhr = module.get.xhr()
24633 ;
24634 if( xhr && xhr.state() !== 'resolved') {
24635 module.debug('Cancelling API request');
24636 xhr.abort();
24637 }
24638 },
24639
24640 // reset state
24641 reset: function() {
24642 module.remove.error();
24643 module.remove.loading();
24644 },
24645
24646 setting: function(name, value) {
24647 module.debug('Changing setting', name, value);
24648 if( $.isPlainObject(name) ) {
24649 $.extend(true, settings, name);
24650 }
24651 else if(value !== undefined) {
24652 if($.isPlainObject(settings[name])) {
24653 $.extend(true, settings[name], value);
24654 }
24655 else {
24656 settings[name] = value;
24657 }
24658 }
24659 else {
24660 return settings[name];
24661 }
24662 },
24663 internal: function(name, value) {
24664 if( $.isPlainObject(name) ) {
24665 $.extend(true, module, name);
24666 }
24667 else if(value !== undefined) {
24668 module[name] = value;
24669 }
24670 else {
24671 return module[name];
24672 }
24673 },
24674 debug: function() {
24675 if(!settings.silent && settings.debug) {
24676 if(settings.performance) {
24677 module.performance.log(arguments);
24678 }
24679 else {
24680 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
24681 module.debug.apply(console, arguments);
24682 }
24683 }
24684 },
24685 verbose: function() {
24686 if(!settings.silent && settings.verbose && settings.debug) {
24687 if(settings.performance) {
24688 module.performance.log(arguments);
24689 }
24690 else {
24691 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
24692 module.verbose.apply(console, arguments);
24693 }
24694 }
24695 },
24696 error: function() {
24697 if(!settings.silent) {
24698 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
24699 module.error.apply(console, arguments);
24700 }
24701 },
24702 performance: {
24703 log: function(message) {
24704 var
24705 currentTime,
24706 executionTime,
24707 previousTime
24708 ;
24709 if(settings.performance) {
24710 currentTime = new Date().getTime();
24711 previousTime = time || currentTime;
24712 executionTime = currentTime - previousTime;
24713 time = currentTime;
24714 performance.push({
24715 'Name' : message[0],
24716 'Arguments' : [].slice.call(message, 1) || '',
24717 //'Element' : element,
24718 'Execution Time' : executionTime
24719 });
24720 }
24721 clearTimeout(module.performance.timer);
24722 module.performance.timer = setTimeout(module.performance.display, 500);
24723 },
24724 display: function() {
24725 var
24726 title = settings.name + ':',
24727 totalTime = 0
24728 ;
24729 time = false;
24730 clearTimeout(module.performance.timer);
24731 $.each(performance, function(index, data) {
24732 totalTime += data['Execution Time'];
24733 });
24734 title += ' ' + totalTime + 'ms';
24735 if(moduleSelector) {
24736 title += ' \'' + moduleSelector + '\'';
24737 }
24738 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
24739 console.groupCollapsed(title);
24740 if(console.table) {
24741 console.table(performance);
24742 }
24743 else {
24744 $.each(performance, function(index, data) {
24745 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
24746 });
24747 }
24748 console.groupEnd();
24749 }
24750 performance = [];
24751 }
24752 },
24753 invoke: function(query, passedArguments, context) {
24754 var
24755 object = instance,
24756 maxDepth,
24757 found,
24758 response
24759 ;
24760 passedArguments = passedArguments || queryArguments;
24761 context = element || context;
24762 if(typeof query == 'string' && object !== undefined) {
24763 query = query.split(/[\. ]/);
24764 maxDepth = query.length - 1;
24765 $.each(query, function(depth, value) {
24766 var camelCaseValue = (depth != maxDepth)
24767 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
24768 : query
24769 ;
24770 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
24771 object = object[camelCaseValue];
24772 }
24773 else if( object[camelCaseValue] !== undefined ) {
24774 found = object[camelCaseValue];
24775 return false;
24776 }
24777 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
24778 object = object[value];
24779 }
24780 else if( object[value] !== undefined ) {
24781 found = object[value];
24782 return false;
24783 }
24784 else {
24785 module.error(error.method, query);
24786 return false;
24787 }
24788 });
24789 }
24790 if ( $.isFunction( found ) ) {
24791 response = found.apply(context, passedArguments);
24792 }
24793 else if(found !== undefined) {
24794 response = found;
24795 }
24796 if(Array.isArray(returnedValue)) {
24797 returnedValue.push(response);
24798 }
24799 else if(returnedValue !== undefined) {
24800 returnedValue = [returnedValue, response];
24801 }
24802 else if(response !== undefined) {
24803 returnedValue = response;
24804 }
24805 return found;
24806 }
24807 };
24808
24809 if(methodInvoked) {
24810 if(instance === undefined) {
24811 module.initialize();
24812 }
24813 module.invoke(query);
24814 }
24815 else {
24816 if(instance !== undefined) {
24817 instance.invoke('destroy');
24818 }
24819 module.initialize();
24820 }
24821 })
24822 ;
24823
24824 return (returnedValue !== undefined)
24825 ? returnedValue
24826 : this
24827 ;
24828};
24829
24830$.api.settings = {
24831
24832 name : 'API',
24833 namespace : 'api',
24834
24835 debug : false,
24836 verbose : false,
24837 performance : true,
24838
24839 // object containing all templates endpoints
24840 api : {},
24841
24842 // whether to cache responses
24843 cache : true,
24844
24845 // whether new requests should abort previous requests
24846 interruptRequests : true,
24847
24848 // event binding
24849 on : 'auto',
24850
24851 // context for applying state classes
24852 stateContext : false,
24853
24854 // duration for loading state
24855 loadingDuration : 0,
24856
24857 // whether to hide errors after a period of time
24858 hideError : 'auto',
24859
24860 // duration for error state
24861 errorDuration : 2000,
24862
24863 // whether parameters should be encoded with encodeURIComponent
24864 encodeParameters : true,
24865
24866 // API action to use
24867 action : false,
24868
24869 // templated URL to use
24870 url : false,
24871
24872 // base URL to apply to all endpoints
24873 base : '',
24874
24875 // data that will
24876 urlData : {},
24877
24878 // whether to add default data to url data
24879 defaultData : true,
24880
24881 // whether to serialize closest form
24882 serializeForm : false,
24883
24884 // how long to wait before request should occur
24885 throttle : 0,
24886
24887 // whether to throttle first request or only repeated
24888 throttleFirstRequest : true,
24889
24890 // standard ajax settings
24891 method : 'get',
24892 data : {},
24893 dataType : 'json',
24894
24895 // mock response
24896 mockResponse : false,
24897 mockResponseAsync : false,
24898
24899 // aliases for mock
24900 response : false,
24901 responseAsync : false,
24902
24903// whether onResponse should work with response value without force converting into an object
24904 rawResponse : false,
24905
24906 // callbacks before request
24907 beforeSend : function(settings) { return settings; },
24908 beforeXHR : function(xhr) {},
24909 onRequest : function(promise, xhr) {},
24910
24911 // after request
24912 onResponse : false, // function(response) { },
24913
24914 // response was successful, if JSON passed validation
24915 onSuccess : function(response, $module) {},
24916
24917 // request finished without aborting
24918 onComplete : function(response, $module) {},
24919
24920 // failed JSON success test
24921 onFailure : function(response, $module) {},
24922
24923 // server error
24924 onError : function(errorMessage, $module) {},
24925
24926 // request aborted
24927 onAbort : function(errorMessage, $module) {},
24928
24929 successTest : false,
24930
24931 // errors
24932 error : {
24933 beforeSend : 'The before send function has aborted the request',
24934 error : 'There was an error with your request',
24935 exitConditions : 'API Request Aborted. Exit conditions met',
24936 JSONParse : 'JSON could not be parsed during error handling',
24937 legacyParameters : 'You are using legacy API success callback names',
24938 method : 'The method you called is not defined',
24939 missingAction : 'API action used but no url was defined',
24940 missingSerialize : 'jquery-serialize-object is required to add form data to an existing data object',
24941 missingURL : 'No URL specified for api event',
24942 noReturnedValue : 'The beforeSend callback must return a settings object, beforeSend ignored.',
24943 noStorage : 'Caching responses locally requires session storage',
24944 parseError : 'There was an error parsing your request',
24945 requiredParameter : 'Missing a required URL parameter: ',
24946 statusMessage : 'Server gave an error: ',
24947 timeout : 'Your request timed out'
24948 },
24949
24950 regExp : {
24951 required : /\{\$*[A-z0-9]+\}/g,
24952 optional : /\{\/\$*[A-z0-9]+\}/g,
24953 },
24954
24955 className: {
24956 loading : 'loading',
24957 error : 'error'
24958 },
24959
24960 selector: {
24961 disabled : '.disabled',
24962 form : 'form'
24963 },
24964
24965 metadata: {
24966 action : 'action',
24967 url : 'url'
24968 }
24969};
24970
24971
24972
24973})( jQuery, window, document );
24974
24975/*!
24976 * # Semantic UI 2.7.2 - State
24977 * http://github.com/semantic-org/semantic-ui/
24978 *
24979 *
24980 * Released under the MIT license
24981 * http://opensource.org/licenses/MIT
24982 *
24983 */
24984
24985;(function ($, window, document, undefined) {
24986
24987"use strict";
24988
24989$.isFunction = $.isFunction || function(obj) {
24990 return typeof obj === "function" && typeof obj.nodeType !== "number";
24991};
24992
24993window = (typeof window != 'undefined' && window.Math == Math)
24994 ? window
24995 : (typeof self != 'undefined' && self.Math == Math)
24996 ? self
24997 : Function('return this')()
24998;
24999
25000$.fn.state = function(parameters) {
25001 var
25002 $allModules = $(this),
25003
25004 moduleSelector = $allModules.selector || '',
25005
25006 hasTouch = ('ontouchstart' in document.documentElement),
25007 time = new Date().getTime(),
25008 performance = [],
25009
25010 query = arguments[0],
25011 methodInvoked = (typeof query == 'string'),
25012 queryArguments = [].slice.call(arguments, 1),
25013
25014 returnedValue
25015 ;
25016 $allModules
25017 .each(function() {
25018 var
25019 settings = ( $.isPlainObject(parameters) )
25020 ? $.extend(true, {}, $.fn.state.settings, parameters)
25021 : $.extend({}, $.fn.state.settings),
25022
25023 error = settings.error,
25024 metadata = settings.metadata,
25025 className = settings.className,
25026 namespace = settings.namespace,
25027 states = settings.states,
25028 text = settings.text,
25029
25030 eventNamespace = '.' + namespace,
25031 moduleNamespace = namespace + '-module',
25032
25033 $module = $(this),
25034
25035 element = this,
25036 instance = $module.data(moduleNamespace),
25037
25038 module
25039 ;
25040 module = {
25041
25042 initialize: function() {
25043 module.verbose('Initializing module');
25044
25045 // allow module to guess desired state based on element
25046 if(settings.automatic) {
25047 module.add.defaults();
25048 }
25049
25050 // bind events with delegated events
25051 if(settings.context && moduleSelector !== '') {
25052 $(settings.context)
25053 .on(moduleSelector, 'mouseenter' + eventNamespace, module.change.text)
25054 .on(moduleSelector, 'mouseleave' + eventNamespace, module.reset.text)
25055 .on(moduleSelector, 'click' + eventNamespace, module.toggle.state)
25056 ;
25057 }
25058 else {
25059 $module
25060 .on('mouseenter' + eventNamespace, module.change.text)
25061 .on('mouseleave' + eventNamespace, module.reset.text)
25062 .on('click' + eventNamespace, module.toggle.state)
25063 ;
25064 }
25065 module.instantiate();
25066 },
25067
25068 instantiate: function() {
25069 module.verbose('Storing instance of module', module);
25070 instance = module;
25071 $module
25072 .data(moduleNamespace, module)
25073 ;
25074 },
25075
25076 destroy: function() {
25077 module.verbose('Destroying previous module', instance);
25078 $module
25079 .off(eventNamespace)
25080 .removeData(moduleNamespace)
25081 ;
25082 },
25083
25084 refresh: function() {
25085 module.verbose('Refreshing selector cache');
25086 $module = $(element);
25087 },
25088
25089 add: {
25090 defaults: function() {
25091 var
25092 userStates = parameters && $.isPlainObject(parameters.states)
25093 ? parameters.states
25094 : {}
25095 ;
25096 $.each(settings.defaults, function(type, typeStates) {
25097 if( module.is[type] !== undefined && module.is[type]() ) {
25098 module.verbose('Adding default states', type, element);
25099 $.extend(settings.states, typeStates, userStates);
25100 }
25101 });
25102 }
25103 },
25104
25105 is: {
25106
25107 active: function() {
25108 return $module.hasClass(className.active);
25109 },
25110 loading: function() {
25111 return $module.hasClass(className.loading);
25112 },
25113 inactive: function() {
25114 return !( $module.hasClass(className.active) );
25115 },
25116 state: function(state) {
25117 if(className[state] === undefined) {
25118 return false;
25119 }
25120 return $module.hasClass( className[state] );
25121 },
25122
25123 enabled: function() {
25124 return !( $module.is(settings.filter.active) );
25125 },
25126 disabled: function() {
25127 return ( $module.is(settings.filter.active) );
25128 },
25129 textEnabled: function() {
25130 return !( $module.is(settings.filter.text) );
25131 },
25132
25133 // definitions for automatic type detection
25134 button: function() {
25135 return $module.is('.button:not(a, .submit)');
25136 },
25137 input: function() {
25138 return $module.is('input');
25139 },
25140 progress: function() {
25141 return $module.is('.ui.progress');
25142 }
25143 },
25144
25145 allow: function(state) {
25146 module.debug('Now allowing state', state);
25147 states[state] = true;
25148 },
25149 disallow: function(state) {
25150 module.debug('No longer allowing', state);
25151 states[state] = false;
25152 },
25153
25154 allows: function(state) {
25155 return states[state] || false;
25156 },
25157
25158 enable: function() {
25159 $module.removeClass(className.disabled);
25160 },
25161
25162 disable: function() {
25163 $module.addClass(className.disabled);
25164 },
25165
25166 setState: function(state) {
25167 if(module.allows(state)) {
25168 $module.addClass( className[state] );
25169 }
25170 },
25171
25172 removeState: function(state) {
25173 if(module.allows(state)) {
25174 $module.removeClass( className[state] );
25175 }
25176 },
25177
25178 toggle: {
25179 state: function() {
25180 var
25181 apiRequest,
25182 requestCancelled
25183 ;
25184 if( module.allows('active') && module.is.enabled() ) {
25185 module.refresh();
25186 if($.fn.api !== undefined) {
25187 apiRequest = $module.api('get request');
25188 requestCancelled = $module.api('was cancelled');
25189 if( requestCancelled ) {
25190 module.debug('API Request cancelled by beforesend');
25191 settings.activateTest = function(){ return false; };
25192 settings.deactivateTest = function(){ return false; };
25193 }
25194 else if(apiRequest) {
25195 module.listenTo(apiRequest);
25196 return;
25197 }
25198 }
25199 module.change.state();
25200 }
25201 }
25202 },
25203
25204 listenTo: function(apiRequest) {
25205 module.debug('API request detected, waiting for state signal', apiRequest);
25206 if(apiRequest) {
25207 if(text.loading) {
25208 module.update.text(text.loading);
25209 }
25210 $.when(apiRequest)
25211 .then(function() {
25212 if(apiRequest.state() == 'resolved') {
25213 module.debug('API request succeeded');
25214 settings.activateTest = function(){ return true; };
25215 settings.deactivateTest = function(){ return true; };
25216 }
25217 else {
25218 module.debug('API request failed');
25219 settings.activateTest = function(){ return false; };
25220 settings.deactivateTest = function(){ return false; };
25221 }
25222 module.change.state();
25223 })
25224 ;
25225 }
25226 },
25227
25228 // checks whether active/inactive state can be given
25229 change: {
25230
25231 state: function() {
25232 module.debug('Determining state change direction');
25233 // inactive to active change
25234 if( module.is.inactive() ) {
25235 module.activate();
25236 }
25237 else {
25238 module.deactivate();
25239 }
25240 if(settings.sync) {
25241 module.sync();
25242 }
25243 settings.onChange.call(element);
25244 },
25245
25246 text: function() {
25247 if( module.is.textEnabled() ) {
25248 if(module.is.disabled() ) {
25249 module.verbose('Changing text to disabled text', text.hover);
25250 module.update.text(text.disabled);
25251 }
25252 else if( module.is.active() ) {
25253 if(text.hover) {
25254 module.verbose('Changing text to hover text', text.hover);
25255 module.update.text(text.hover);
25256 }
25257 else if(text.deactivate) {
25258 module.verbose('Changing text to deactivating text', text.deactivate);
25259 module.update.text(text.deactivate);
25260 }
25261 }
25262 else {
25263 if(text.hover) {
25264 module.verbose('Changing text to hover text', text.hover);
25265 module.update.text(text.hover);
25266 }
25267 else if(text.activate){
25268 module.verbose('Changing text to activating text', text.activate);
25269 module.update.text(text.activate);
25270 }
25271 }
25272 }
25273 }
25274
25275 },
25276
25277 activate: function() {
25278 if( settings.activateTest.call(element) ) {
25279 module.debug('Setting state to active');
25280 $module
25281 .addClass(className.active)
25282 ;
25283 module.update.text(text.active);
25284 settings.onActivate.call(element);
25285 }
25286 },
25287
25288 deactivate: function() {
25289 if( settings.deactivateTest.call(element) ) {
25290 module.debug('Setting state to inactive');
25291 $module
25292 .removeClass(className.active)
25293 ;
25294 module.update.text(text.inactive);
25295 settings.onDeactivate.call(element);
25296 }
25297 },
25298
25299 sync: function() {
25300 module.verbose('Syncing other buttons to current state');
25301 if( module.is.active() ) {
25302 $allModules
25303 .not($module)
25304 .state('activate');
25305 }
25306 else {
25307 $allModules
25308 .not($module)
25309 .state('deactivate')
25310 ;
25311 }
25312 },
25313
25314 get: {
25315 text: function() {
25316 return (settings.selector.text)
25317 ? $module.find(settings.selector.text).text()
25318 : $module.html()
25319 ;
25320 },
25321 textFor: function(state) {
25322 return text[state] || false;
25323 }
25324 },
25325
25326 flash: {
25327 text: function(text, duration, callback) {
25328 var
25329 previousText = module.get.text()
25330 ;
25331 module.debug('Flashing text message', text, duration);
25332 text = text || settings.text.flash;
25333 duration = duration || settings.flashDuration;
25334 callback = callback || function() {};
25335 module.update.text(text);
25336 setTimeout(function(){
25337 module.update.text(previousText);
25338 callback.call(element);
25339 }, duration);
25340 }
25341 },
25342
25343 reset: {
25344 // on mouseout sets text to previous value
25345 text: function() {
25346 var
25347 activeText = text.active || $module.data(metadata.storedText),
25348 inactiveText = text.inactive || $module.data(metadata.storedText)
25349 ;
25350 if( module.is.textEnabled() ) {
25351 if( module.is.active() && activeText) {
25352 module.verbose('Resetting active text', activeText);
25353 module.update.text(activeText);
25354 }
25355 else if(inactiveText) {
25356 module.verbose('Resetting inactive text', activeText);
25357 module.update.text(inactiveText);
25358 }
25359 }
25360 }
25361 },
25362
25363 update: {
25364 text: function(text) {
25365 var
25366 currentText = module.get.text()
25367 ;
25368 if(text && text !== currentText) {
25369 module.debug('Updating text', text);
25370 if(settings.selector.text) {
25371 $module
25372 .data(metadata.storedText, text)
25373 .find(settings.selector.text)
25374 .text(text)
25375 ;
25376 }
25377 else {
25378 $module
25379 .data(metadata.storedText, text)
25380 .html(text)
25381 ;
25382 }
25383 }
25384 else {
25385 module.debug('Text is already set, ignoring update', text);
25386 }
25387 }
25388 },
25389
25390 setting: function(name, value) {
25391 module.debug('Changing setting', name, value);
25392 if( $.isPlainObject(name) ) {
25393 $.extend(true, settings, name);
25394 }
25395 else if(value !== undefined) {
25396 if($.isPlainObject(settings[name])) {
25397 $.extend(true, settings[name], value);
25398 }
25399 else {
25400 settings[name] = value;
25401 }
25402 }
25403 else {
25404 return settings[name];
25405 }
25406 },
25407 internal: function(name, value) {
25408 if( $.isPlainObject(name) ) {
25409 $.extend(true, module, name);
25410 }
25411 else if(value !== undefined) {
25412 module[name] = value;
25413 }
25414 else {
25415 return module[name];
25416 }
25417 },
25418 debug: function() {
25419 if(!settings.silent && settings.debug) {
25420 if(settings.performance) {
25421 module.performance.log(arguments);
25422 }
25423 else {
25424 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
25425 module.debug.apply(console, arguments);
25426 }
25427 }
25428 },
25429 verbose: function() {
25430 if(!settings.silent && settings.verbose && settings.debug) {
25431 if(settings.performance) {
25432 module.performance.log(arguments);
25433 }
25434 else {
25435 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
25436 module.verbose.apply(console, arguments);
25437 }
25438 }
25439 },
25440 error: function() {
25441 if(!settings.silent) {
25442 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
25443 module.error.apply(console, arguments);
25444 }
25445 },
25446 performance: {
25447 log: function(message) {
25448 var
25449 currentTime,
25450 executionTime,
25451 previousTime
25452 ;
25453 if(settings.performance) {
25454 currentTime = new Date().getTime();
25455 previousTime = time || currentTime;
25456 executionTime = currentTime - previousTime;
25457 time = currentTime;
25458 performance.push({
25459 'Name' : message[0],
25460 'Arguments' : [].slice.call(message, 1) || '',
25461 'Element' : element,
25462 'Execution Time' : executionTime
25463 });
25464 }
25465 clearTimeout(module.performance.timer);
25466 module.performance.timer = setTimeout(module.performance.display, 500);
25467 },
25468 display: function() {
25469 var
25470 title = settings.name + ':',
25471 totalTime = 0
25472 ;
25473 time = false;
25474 clearTimeout(module.performance.timer);
25475 $.each(performance, function(index, data) {
25476 totalTime += data['Execution Time'];
25477 });
25478 title += ' ' + totalTime + 'ms';
25479 if(moduleSelector) {
25480 title += ' \'' + moduleSelector + '\'';
25481 }
25482 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
25483 console.groupCollapsed(title);
25484 if(console.table) {
25485 console.table(performance);
25486 }
25487 else {
25488 $.each(performance, function(index, data) {
25489 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
25490 });
25491 }
25492 console.groupEnd();
25493 }
25494 performance = [];
25495 }
25496 },
25497 invoke: function(query, passedArguments, context) {
25498 var
25499 object = instance,
25500 maxDepth,
25501 found,
25502 response
25503 ;
25504 passedArguments = passedArguments || queryArguments;
25505 context = element || context;
25506 if(typeof query == 'string' && object !== undefined) {
25507 query = query.split(/[\. ]/);
25508 maxDepth = query.length - 1;
25509 $.each(query, function(depth, value) {
25510 var camelCaseValue = (depth != maxDepth)
25511 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
25512 : query
25513 ;
25514 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
25515 object = object[camelCaseValue];
25516 }
25517 else if( object[camelCaseValue] !== undefined ) {
25518 found = object[camelCaseValue];
25519 return false;
25520 }
25521 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
25522 object = object[value];
25523 }
25524 else if( object[value] !== undefined ) {
25525 found = object[value];
25526 return false;
25527 }
25528 else {
25529 module.error(error.method, query);
25530 return false;
25531 }
25532 });
25533 }
25534 if ( $.isFunction( found ) ) {
25535 response = found.apply(context, passedArguments);
25536 }
25537 else if(found !== undefined) {
25538 response = found;
25539 }
25540 if(Array.isArray(returnedValue)) {
25541 returnedValue.push(response);
25542 }
25543 else if(returnedValue !== undefined) {
25544 returnedValue = [returnedValue, response];
25545 }
25546 else if(response !== undefined) {
25547 returnedValue = response;
25548 }
25549 return found;
25550 }
25551 };
25552
25553 if(methodInvoked) {
25554 if(instance === undefined) {
25555 module.initialize();
25556 }
25557 module.invoke(query);
25558 }
25559 else {
25560 if(instance !== undefined) {
25561 instance.invoke('destroy');
25562 }
25563 module.initialize();
25564 }
25565 })
25566 ;
25567
25568 return (returnedValue !== undefined)
25569 ? returnedValue
25570 : this
25571 ;
25572};
25573
25574$.fn.state.settings = {
25575
25576 // module info
25577 name : 'State',
25578
25579 // debug output
25580 debug : false,
25581
25582 // verbose debug output
25583 verbose : false,
25584
25585 // namespace for events
25586 namespace : 'state',
25587
25588 // debug data includes performance
25589 performance : true,
25590
25591 // callback occurs on state change
25592 onActivate : function() {},
25593 onDeactivate : function() {},
25594 onChange : function() {},
25595
25596 // state test functions
25597 activateTest : function() { return true; },
25598 deactivateTest : function() { return true; },
25599
25600 // whether to automatically map default states
25601 automatic : true,
25602
25603 // activate / deactivate changes all elements instantiated at same time
25604 sync : false,
25605
25606 // default flash text duration, used for temporarily changing text of an element
25607 flashDuration : 1000,
25608
25609 // selector filter
25610 filter : {
25611 text : '.loading, .disabled',
25612 active : '.disabled'
25613 },
25614
25615 context : false,
25616
25617 // error
25618 error: {
25619 beforeSend : 'The before send function has cancelled state change',
25620 method : 'The method you called is not defined.'
25621 },
25622
25623 // metadata
25624 metadata: {
25625 promise : 'promise',
25626 storedText : 'stored-text'
25627 },
25628
25629 // change class on state
25630 className: {
25631 active : 'active',
25632 disabled : 'disabled',
25633 error : 'error',
25634 loading : 'loading',
25635 success : 'success',
25636 warning : 'warning'
25637 },
25638
25639 selector: {
25640 // selector for text node
25641 text: false
25642 },
25643
25644 defaults : {
25645 input: {
25646 disabled : true,
25647 loading : true,
25648 active : true
25649 },
25650 button: {
25651 disabled : true,
25652 loading : true,
25653 active : true,
25654 },
25655 progress: {
25656 active : true,
25657 success : true,
25658 warning : true,
25659 error : true
25660 }
25661 },
25662
25663 states : {
25664 active : true,
25665 disabled : true,
25666 error : true,
25667 loading : true,
25668 success : true,
25669 warning : true
25670 },
25671
25672 text : {
25673 disabled : false,
25674 flash : false,
25675 hover : false,
25676 active : false,
25677 inactive : false,
25678 activate : false,
25679 deactivate : false
25680 }
25681
25682};
25683
25684
25685
25686})( jQuery, window, document );
25687
25688/*!
25689 * # Semantic UI 2.7.2 - Visibility
25690 * http://github.com/semantic-org/semantic-ui/
25691 *
25692 *
25693 * Released under the MIT license
25694 * http://opensource.org/licenses/MIT
25695 *
25696 */
25697
25698;(function ($, window, document, undefined) {
25699
25700'use strict';
25701
25702$.isFunction = $.isFunction || function(obj) {
25703 return typeof obj === "function" && typeof obj.nodeType !== "number";
25704};
25705
25706window = (typeof window != 'undefined' && window.Math == Math)
25707 ? window
25708 : (typeof self != 'undefined' && self.Math == Math)
25709 ? self
25710 : Function('return this')()
25711;
25712
25713$.fn.visibility = function(parameters) {
25714 var
25715 $allModules = $(this),
25716 moduleSelector = $allModules.selector || '',
25717
25718 time = new Date().getTime(),
25719 performance = [],
25720
25721 query = arguments[0],
25722 methodInvoked = (typeof query == 'string'),
25723 queryArguments = [].slice.call(arguments, 1),
25724 returnedValue,
25725
25726 moduleCount = $allModules.length,
25727 loadedCount = 0
25728 ;
25729
25730 $allModules
25731 .each(function() {
25732 var
25733 settings = ( $.isPlainObject(parameters) )
25734 ? $.extend(true, {}, $.fn.visibility.settings, parameters)
25735 : $.extend({}, $.fn.visibility.settings),
25736
25737 className = settings.className,
25738 namespace = settings.namespace,
25739 error = settings.error,
25740 metadata = settings.metadata,
25741
25742 eventNamespace = '.' + namespace,
25743 moduleNamespace = 'module-' + namespace,
25744
25745 $window = $(window),
25746
25747 $module = $(this),
25748 $context = $(settings.context),
25749
25750 $placeholder,
25751
25752 selector = $module.selector || '',
25753 instance = $module.data(moduleNamespace),
25754
25755 requestAnimationFrame = window.requestAnimationFrame
25756 || window.mozRequestAnimationFrame
25757 || window.webkitRequestAnimationFrame
25758 || window.msRequestAnimationFrame
25759 || function(callback) { setTimeout(callback, 0); },
25760
25761 element = this,
25762 disabled = false,
25763
25764 contextObserver,
25765 observer,
25766 module
25767 ;
25768
25769 module = {
25770
25771 initialize: function() {
25772 module.debug('Initializing', settings);
25773
25774 module.setup.cache();
25775
25776 if( module.should.trackChanges() ) {
25777
25778 if(settings.type == 'image') {
25779 module.setup.image();
25780 }
25781 if(settings.type == 'fixed') {
25782 module.setup.fixed();
25783 }
25784
25785 if(settings.observeChanges) {
25786 module.observeChanges();
25787 }
25788 module.bind.events();
25789 }
25790
25791 module.save.position();
25792 if( !module.is.visible() ) {
25793 module.error(error.visible, $module);
25794 }
25795
25796 if(settings.initialCheck) {
25797 module.checkVisibility();
25798 }
25799 module.instantiate();
25800 },
25801
25802 instantiate: function() {
25803 module.debug('Storing instance', module);
25804 $module
25805 .data(moduleNamespace, module)
25806 ;
25807 instance = module;
25808 },
25809
25810 destroy: function() {
25811 module.verbose('Destroying previous module');
25812 if(observer) {
25813 observer.disconnect();
25814 }
25815 if(contextObserver) {
25816 contextObserver.disconnect();
25817 }
25818 $window
25819 .off('load' + eventNamespace, module.event.load)
25820 .off('resize' + eventNamespace, module.event.resize)
25821 ;
25822 $context
25823 .off('scroll' + eventNamespace, module.event.scroll)
25824 .off('scrollchange' + eventNamespace, module.event.scrollchange)
25825 ;
25826 if(settings.type == 'fixed') {
25827 module.resetFixed();
25828 module.remove.placeholder();
25829 }
25830 $module
25831 .off(eventNamespace)
25832 .removeData(moduleNamespace)
25833 ;
25834 },
25835
25836 observeChanges: function() {
25837 if('MutationObserver' in window) {
25838 contextObserver = new MutationObserver(module.event.contextChanged);
25839 observer = new MutationObserver(module.event.changed);
25840 contextObserver.observe(document, {
25841 childList : true,
25842 subtree : true
25843 });
25844 observer.observe(element, {
25845 childList : true,
25846 subtree : true
25847 });
25848 module.debug('Setting up mutation observer', observer);
25849 }
25850 },
25851
25852 bind: {
25853 events: function() {
25854 module.verbose('Binding visibility events to scroll and resize');
25855 if(settings.refreshOnLoad) {
25856 $window
25857 .on('load' + eventNamespace, module.event.load)
25858 ;
25859 }
25860 $window
25861 .on('resize' + eventNamespace, module.event.resize)
25862 ;
25863 // pub/sub pattern
25864 $context
25865 .off('scroll' + eventNamespace)
25866 .on('scroll' + eventNamespace, module.event.scroll)
25867 .on('scrollchange' + eventNamespace, module.event.scrollchange)
25868 ;
25869 }
25870 },
25871
25872 event: {
25873 changed: function(mutations) {
25874 module.verbose('DOM tree modified, updating visibility calculations');
25875 module.timer = setTimeout(function() {
25876 module.verbose('DOM tree modified, updating sticky menu');
25877 module.refresh();
25878 }, 100);
25879 },
25880 contextChanged: function(mutations) {
25881 [].forEach.call(mutations, function(mutation) {
25882 if(mutation.removedNodes) {
25883 [].forEach.call(mutation.removedNodes, function(node) {
25884 if(node == element || $(node).find(element).length > 0) {
25885 module.debug('Element removed from DOM, tearing down events');
25886 module.destroy();
25887 }
25888 });
25889 }
25890 });
25891 },
25892 resize: function() {
25893 module.debug('Window resized');
25894 if(settings.refreshOnResize) {
25895 requestAnimationFrame(module.refresh);
25896 }
25897 },
25898 load: function() {
25899 module.debug('Page finished loading');
25900 requestAnimationFrame(module.refresh);
25901 },
25902 // publishes scrollchange event on one scroll
25903 scroll: function() {
25904 if(settings.throttle) {
25905 clearTimeout(module.timer);
25906 module.timer = setTimeout(function() {
25907 $context.triggerHandler('scrollchange' + eventNamespace, [ $context.scrollTop() ]);
25908 }, settings.throttle);
25909 }
25910 else {
25911 requestAnimationFrame(function() {
25912 $context.triggerHandler('scrollchange' + eventNamespace, [ $context.scrollTop() ]);
25913 });
25914 }
25915 },
25916 // subscribes to scrollchange
25917 scrollchange: function(event, scrollPosition) {
25918 module.checkVisibility(scrollPosition);
25919 },
25920 },
25921
25922 precache: function(images, callback) {
25923 if (!(images instanceof Array)) {
25924 images = [images];
25925 }
25926 var
25927 imagesLength = images.length,
25928 loadedCounter = 0,
25929 cache = [],
25930 cacheImage = document.createElement('img'),
25931 handleLoad = function() {
25932 loadedCounter++;
25933 if (loadedCounter >= images.length) {
25934 if ($.isFunction(callback)) {
25935 callback();
25936 }
25937 }
25938 }
25939 ;
25940 while (imagesLength--) {
25941 cacheImage = document.createElement('img');
25942 cacheImage.onload = handleLoad;
25943 cacheImage.onerror = handleLoad;
25944 cacheImage.src = images[imagesLength];
25945 cache.push(cacheImage);
25946 }
25947 },
25948
25949 enableCallbacks: function() {
25950 module.debug('Allowing callbacks to occur');
25951 disabled = false;
25952 },
25953
25954 disableCallbacks: function() {
25955 module.debug('Disabling all callbacks temporarily');
25956 disabled = true;
25957 },
25958
25959 should: {
25960 trackChanges: function() {
25961 if(methodInvoked) {
25962 module.debug('One time query, no need to bind events');
25963 return false;
25964 }
25965 module.debug('Callbacks being attached');
25966 return true;
25967 }
25968 },
25969
25970 setup: {
25971 cache: function() {
25972 module.cache = {
25973 occurred : {},
25974 screen : {},
25975 element : {},
25976 };
25977 },
25978 image: function() {
25979 var
25980 src = $module.data(metadata.src)
25981 ;
25982 if(src) {
25983 module.verbose('Lazy loading image', src);
25984 settings.once = true;
25985 settings.observeChanges = false;
25986
25987 // show when top visible
25988 settings.onOnScreen = function() {
25989 module.debug('Image on screen', element);
25990 module.precache(src, function() {
25991 module.set.image(src, function() {
25992 loadedCount++;
25993 if(loadedCount == moduleCount) {
25994 settings.onAllLoaded.call(this);
25995 }
25996 settings.onLoad.call(this);
25997 });
25998 });
25999 };
26000 }
26001 },
26002 fixed: function() {
26003 module.debug('Setting up fixed');
26004 settings.once = false;
26005 settings.observeChanges = false;
26006 settings.initialCheck = true;
26007 settings.refreshOnLoad = true;
26008 if(!parameters.transition) {
26009 settings.transition = false;
26010 }
26011 module.create.placeholder();
26012 module.debug('Added placeholder', $placeholder);
26013 settings.onTopPassed = function() {
26014 module.debug('Element passed, adding fixed position', $module);
26015 module.show.placeholder();
26016 module.set.fixed();
26017 if(settings.transition) {
26018 if($.fn.transition !== undefined) {
26019 $module.transition(settings.transition, settings.duration);
26020 }
26021 }
26022 };
26023 settings.onTopPassedReverse = function() {
26024 module.debug('Element returned to position, removing fixed', $module);
26025 module.hide.placeholder();
26026 module.remove.fixed();
26027 };
26028 }
26029 },
26030
26031 create: {
26032 placeholder: function() {
26033 module.verbose('Creating fixed position placeholder');
26034 $placeholder = $module
26035 .clone(false)
26036 .css('display', 'none')
26037 .addClass(className.placeholder)
26038 .insertAfter($module)
26039 ;
26040 }
26041 },
26042
26043 show: {
26044 placeholder: function() {
26045 module.verbose('Showing placeholder');
26046 $placeholder
26047 .css('display', 'block')
26048 .css('visibility', 'hidden')
26049 ;
26050 }
26051 },
26052 hide: {
26053 placeholder: function() {
26054 module.verbose('Hiding placeholder');
26055 $placeholder
26056 .css('display', 'none')
26057 .css('visibility', '')
26058 ;
26059 }
26060 },
26061
26062 set: {
26063 fixed: function() {
26064 module.verbose('Setting element to fixed position');
26065 $module
26066 .addClass(className.fixed)
26067 .css({
26068 position : 'fixed',
26069 top : settings.offset + 'px',
26070 left : 'auto',
26071 zIndex : settings.zIndex
26072 })
26073 ;
26074 settings.onFixed.call(element);
26075 },
26076 image: function(src, callback) {
26077 $module
26078 .attr('src', src)
26079 ;
26080 if(settings.transition) {
26081 if( $.fn.transition !== undefined) {
26082 if($module.hasClass(className.visible)) {
26083 module.debug('Transition already occurred on this image, skipping animation');
26084 return;
26085 }
26086 $module.transition(settings.transition, settings.duration, callback);
26087 }
26088 else {
26089 $module.fadeIn(settings.duration, callback);
26090 }
26091 }
26092 else {
26093 $module.show();
26094 }
26095 }
26096 },
26097
26098 is: {
26099 onScreen: function() {
26100 var
26101 calculations = module.get.elementCalculations()
26102 ;
26103 return calculations.onScreen;
26104 },
26105 offScreen: function() {
26106 var
26107 calculations = module.get.elementCalculations()
26108 ;
26109 return calculations.offScreen;
26110 },
26111 visible: function() {
26112 if(module.cache && module.cache.element) {
26113 return !(module.cache.element.width === 0 && module.cache.element.offset.top === 0);
26114 }
26115 return false;
26116 },
26117 verticallyScrollableContext: function() {
26118 var
26119 overflowY = ($context.get(0) !== window)
26120 ? $context.css('overflow-y')
26121 : false
26122 ;
26123 return (overflowY == 'auto' || overflowY == 'scroll');
26124 },
26125 horizontallyScrollableContext: function() {
26126 var
26127 overflowX = ($context.get(0) !== window)
26128 ? $context.css('overflow-x')
26129 : false
26130 ;
26131 return (overflowX == 'auto' || overflowX == 'scroll');
26132 }
26133 },
26134
26135 refresh: function() {
26136 module.debug('Refreshing constants (width/height)');
26137 if(settings.type == 'fixed') {
26138 module.resetFixed();
26139 }
26140 module.reset();
26141 module.save.position();
26142 if(settings.checkOnRefresh) {
26143 module.checkVisibility();
26144 }
26145 settings.onRefresh.call(element);
26146 },
26147
26148 resetFixed: function () {
26149 module.remove.fixed();
26150 module.remove.occurred();
26151 },
26152
26153 reset: function() {
26154 module.verbose('Resetting all cached values');
26155 if( $.isPlainObject(module.cache) ) {
26156 module.cache.screen = {};
26157 module.cache.element = {};
26158 }
26159 },
26160
26161 checkVisibility: function(scroll) {
26162 module.verbose('Checking visibility of element', module.cache.element);
26163
26164 if( !disabled && module.is.visible() ) {
26165
26166 // save scroll position
26167 module.save.scroll(scroll);
26168
26169 // update calculations derived from scroll
26170 module.save.calculations();
26171
26172 // percentage
26173 module.passed();
26174
26175 // reverse (must be first)
26176 module.passingReverse();
26177 module.topVisibleReverse();
26178 module.bottomVisibleReverse();
26179 module.topPassedReverse();
26180 module.bottomPassedReverse();
26181
26182 // one time
26183 module.onScreen();
26184 module.offScreen();
26185 module.passing();
26186 module.topVisible();
26187 module.bottomVisible();
26188 module.topPassed();
26189 module.bottomPassed();
26190
26191 // on update callback
26192 if(settings.onUpdate) {
26193 settings.onUpdate.call(element, module.get.elementCalculations());
26194 }
26195 }
26196 },
26197
26198 passed: function(amount, newCallback) {
26199 var
26200 calculations = module.get.elementCalculations(),
26201 amountInPixels
26202 ;
26203 // assign callback
26204 if(amount && newCallback) {
26205 settings.onPassed[amount] = newCallback;
26206 }
26207 else if(amount !== undefined) {
26208 return (module.get.pixelsPassed(amount) > calculations.pixelsPassed);
26209 }
26210 else if(calculations.passing) {
26211 $.each(settings.onPassed, function(amount, callback) {
26212 if(calculations.bottomVisible || calculations.pixelsPassed > module.get.pixelsPassed(amount)) {
26213 module.execute(callback, amount);
26214 }
26215 else if(!settings.once) {
26216 module.remove.occurred(callback);
26217 }
26218 });
26219 }
26220 },
26221
26222 onScreen: function(newCallback) {
26223 var
26224 calculations = module.get.elementCalculations(),
26225 callback = newCallback || settings.onOnScreen,
26226 callbackName = 'onScreen'
26227 ;
26228 if(newCallback) {
26229 module.debug('Adding callback for onScreen', newCallback);
26230 settings.onOnScreen = newCallback;
26231 }
26232 if(calculations.onScreen) {
26233 module.execute(callback, callbackName);
26234 }
26235 else if(!settings.once) {
26236 module.remove.occurred(callbackName);
26237 }
26238 if(newCallback !== undefined) {
26239 return calculations.onOnScreen;
26240 }
26241 },
26242
26243 offScreen: function(newCallback) {
26244 var
26245 calculations = module.get.elementCalculations(),
26246 callback = newCallback || settings.onOffScreen,
26247 callbackName = 'offScreen'
26248 ;
26249 if(newCallback) {
26250 module.debug('Adding callback for offScreen', newCallback);
26251 settings.onOffScreen = newCallback;
26252 }
26253 if(calculations.offScreen) {
26254 module.execute(callback, callbackName);
26255 }
26256 else if(!settings.once) {
26257 module.remove.occurred(callbackName);
26258 }
26259 if(newCallback !== undefined) {
26260 return calculations.onOffScreen;
26261 }
26262 },
26263
26264 passing: function(newCallback) {
26265 var
26266 calculations = module.get.elementCalculations(),
26267 callback = newCallback || settings.onPassing,
26268 callbackName = 'passing'
26269 ;
26270 if(newCallback) {
26271 module.debug('Adding callback for passing', newCallback);
26272 settings.onPassing = newCallback;
26273 }
26274 if(calculations.passing) {
26275 module.execute(callback, callbackName);
26276 }
26277 else if(!settings.once) {
26278 module.remove.occurred(callbackName);
26279 }
26280 if(newCallback !== undefined) {
26281 return calculations.passing;
26282 }
26283 },
26284
26285
26286 topVisible: function(newCallback) {
26287 var
26288 calculations = module.get.elementCalculations(),
26289 callback = newCallback || settings.onTopVisible,
26290 callbackName = 'topVisible'
26291 ;
26292 if(newCallback) {
26293 module.debug('Adding callback for top visible', newCallback);
26294 settings.onTopVisible = newCallback;
26295 }
26296 if(calculations.topVisible) {
26297 module.execute(callback, callbackName);
26298 }
26299 else if(!settings.once) {
26300 module.remove.occurred(callbackName);
26301 }
26302 if(newCallback === undefined) {
26303 return calculations.topVisible;
26304 }
26305 },
26306
26307 bottomVisible: function(newCallback) {
26308 var
26309 calculations = module.get.elementCalculations(),
26310 callback = newCallback || settings.onBottomVisible,
26311 callbackName = 'bottomVisible'
26312 ;
26313 if(newCallback) {
26314 module.debug('Adding callback for bottom visible', newCallback);
26315 settings.onBottomVisible = newCallback;
26316 }
26317 if(calculations.bottomVisible) {
26318 module.execute(callback, callbackName);
26319 }
26320 else if(!settings.once) {
26321 module.remove.occurred(callbackName);
26322 }
26323 if(newCallback === undefined) {
26324 return calculations.bottomVisible;
26325 }
26326 },
26327
26328 topPassed: function(newCallback) {
26329 var
26330 calculations = module.get.elementCalculations(),
26331 callback = newCallback || settings.onTopPassed,
26332 callbackName = 'topPassed'
26333 ;
26334 if(newCallback) {
26335 module.debug('Adding callback for top passed', newCallback);
26336 settings.onTopPassed = newCallback;
26337 }
26338 if(calculations.topPassed) {
26339 module.execute(callback, callbackName);
26340 }
26341 else if(!settings.once) {
26342 module.remove.occurred(callbackName);
26343 }
26344 if(newCallback === undefined) {
26345 return calculations.topPassed;
26346 }
26347 },
26348
26349 bottomPassed: function(newCallback) {
26350 var
26351 calculations = module.get.elementCalculations(),
26352 callback = newCallback || settings.onBottomPassed,
26353 callbackName = 'bottomPassed'
26354 ;
26355 if(newCallback) {
26356 module.debug('Adding callback for bottom passed', newCallback);
26357 settings.onBottomPassed = newCallback;
26358 }
26359 if(calculations.bottomPassed) {
26360 module.execute(callback, callbackName);
26361 }
26362 else if(!settings.once) {
26363 module.remove.occurred(callbackName);
26364 }
26365 if(newCallback === undefined) {
26366 return calculations.bottomPassed;
26367 }
26368 },
26369
26370 passingReverse: function(newCallback) {
26371 var
26372 calculations = module.get.elementCalculations(),
26373 callback = newCallback || settings.onPassingReverse,
26374 callbackName = 'passingReverse'
26375 ;
26376 if(newCallback) {
26377 module.debug('Adding callback for passing reverse', newCallback);
26378 settings.onPassingReverse = newCallback;
26379 }
26380 if(!calculations.passing) {
26381 if(module.get.occurred('passing')) {
26382 module.execute(callback, callbackName);
26383 }
26384 }
26385 else if(!settings.once) {
26386 module.remove.occurred(callbackName);
26387 }
26388 if(newCallback !== undefined) {
26389 return !calculations.passing;
26390 }
26391 },
26392
26393
26394 topVisibleReverse: function(newCallback) {
26395 var
26396 calculations = module.get.elementCalculations(),
26397 callback = newCallback || settings.onTopVisibleReverse,
26398 callbackName = 'topVisibleReverse'
26399 ;
26400 if(newCallback) {
26401 module.debug('Adding callback for top visible reverse', newCallback);
26402 settings.onTopVisibleReverse = newCallback;
26403 }
26404 if(!calculations.topVisible) {
26405 if(module.get.occurred('topVisible')) {
26406 module.execute(callback, callbackName);
26407 }
26408 }
26409 else if(!settings.once) {
26410 module.remove.occurred(callbackName);
26411 }
26412 if(newCallback === undefined) {
26413 return !calculations.topVisible;
26414 }
26415 },
26416
26417 bottomVisibleReverse: function(newCallback) {
26418 var
26419 calculations = module.get.elementCalculations(),
26420 callback = newCallback || settings.onBottomVisibleReverse,
26421 callbackName = 'bottomVisibleReverse'
26422 ;
26423 if(newCallback) {
26424 module.debug('Adding callback for bottom visible reverse', newCallback);
26425 settings.onBottomVisibleReverse = newCallback;
26426 }
26427 if(!calculations.bottomVisible) {
26428 if(module.get.occurred('bottomVisible')) {
26429 module.execute(callback, callbackName);
26430 }
26431 }
26432 else if(!settings.once) {
26433 module.remove.occurred(callbackName);
26434 }
26435 if(newCallback === undefined) {
26436 return !calculations.bottomVisible;
26437 }
26438 },
26439
26440 topPassedReverse: function(newCallback) {
26441 var
26442 calculations = module.get.elementCalculations(),
26443 callback = newCallback || settings.onTopPassedReverse,
26444 callbackName = 'topPassedReverse'
26445 ;
26446 if(newCallback) {
26447 module.debug('Adding callback for top passed reverse', newCallback);
26448 settings.onTopPassedReverse = newCallback;
26449 }
26450 if(!calculations.topPassed) {
26451 if(module.get.occurred('topPassed')) {
26452 module.execute(callback, callbackName);
26453 }
26454 }
26455 else if(!settings.once) {
26456 module.remove.occurred(callbackName);
26457 }
26458 if(newCallback === undefined) {
26459 return !calculations.onTopPassed;
26460 }
26461 },
26462
26463 bottomPassedReverse: function(newCallback) {
26464 var
26465 calculations = module.get.elementCalculations(),
26466 callback = newCallback || settings.onBottomPassedReverse,
26467 callbackName = 'bottomPassedReverse'
26468 ;
26469 if(newCallback) {
26470 module.debug('Adding callback for bottom passed reverse', newCallback);
26471 settings.onBottomPassedReverse = newCallback;
26472 }
26473 if(!calculations.bottomPassed) {
26474 if(module.get.occurred('bottomPassed')) {
26475 module.execute(callback, callbackName);
26476 }
26477 }
26478 else if(!settings.once) {
26479 module.remove.occurred(callbackName);
26480 }
26481 if(newCallback === undefined) {
26482 return !calculations.bottomPassed;
26483 }
26484 },
26485
26486 execute: function(callback, callbackName) {
26487 var
26488 calculations = module.get.elementCalculations(),
26489 screen = module.get.screenCalculations()
26490 ;
26491 callback = callback || false;
26492 if(callback) {
26493 if(settings.continuous) {
26494 module.debug('Callback being called continuously', callbackName, calculations);
26495 callback.call(element, calculations, screen);
26496 }
26497 else if(!module.get.occurred(callbackName)) {
26498 module.debug('Conditions met', callbackName, calculations);
26499 callback.call(element, calculations, screen);
26500 }
26501 }
26502 module.save.occurred(callbackName);
26503 },
26504
26505 remove: {
26506 fixed: function() {
26507 module.debug('Removing fixed position');
26508 $module
26509 .removeClass(className.fixed)
26510 .css({
26511 position : '',
26512 top : '',
26513 left : '',
26514 zIndex : ''
26515 })
26516 ;
26517 settings.onUnfixed.call(element);
26518 },
26519 placeholder: function() {
26520 module.debug('Removing placeholder content');
26521 if($placeholder) {
26522 $placeholder.remove();
26523 }
26524 },
26525 occurred: function(callback) {
26526 if(callback) {
26527 var
26528 occurred = module.cache.occurred
26529 ;
26530 if(occurred[callback] !== undefined && occurred[callback] === true) {
26531 module.debug('Callback can now be called again', callback);
26532 module.cache.occurred[callback] = false;
26533 }
26534 }
26535 else {
26536 module.cache.occurred = {};
26537 }
26538 }
26539 },
26540
26541 save: {
26542 calculations: function() {
26543 module.verbose('Saving all calculations necessary to determine positioning');
26544 module.save.direction();
26545 module.save.screenCalculations();
26546 module.save.elementCalculations();
26547 },
26548 occurred: function(callback) {
26549 if(callback) {
26550 if(module.cache.occurred[callback] === undefined || (module.cache.occurred[callback] !== true)) {
26551 module.verbose('Saving callback occurred', callback);
26552 module.cache.occurred[callback] = true;
26553 }
26554 }
26555 },
26556 scroll: function(scrollPosition) {
26557 scrollPosition = scrollPosition + settings.offset || $context.scrollTop() + settings.offset;
26558 module.cache.scroll = scrollPosition;
26559 },
26560 direction: function() {
26561 var
26562 scroll = module.get.scroll(),
26563 lastScroll = module.get.lastScroll(),
26564 direction
26565 ;
26566 if(scroll > lastScroll && lastScroll) {
26567 direction = 'down';
26568 }
26569 else if(scroll < lastScroll && lastScroll) {
26570 direction = 'up';
26571 }
26572 else {
26573 direction = 'static';
26574 }
26575 module.cache.direction = direction;
26576 return module.cache.direction;
26577 },
26578 elementPosition: function() {
26579 var
26580 element = module.cache.element,
26581 screen = module.get.screenSize()
26582 ;
26583 module.verbose('Saving element position');
26584 // (quicker than $.extend)
26585 element.fits = (element.height < screen.height);
26586 element.offset = $module.offset();
26587 element.width = $module.outerWidth();
26588 element.height = $module.outerHeight();
26589 // compensate for scroll in context
26590 if(module.is.verticallyScrollableContext()) {
26591 element.offset.top += $context.scrollTop() - $context.offset().top;
26592 }
26593 if(module.is.horizontallyScrollableContext()) {
26594 element.offset.left += $context.scrollLeft - $context.offset().left;
26595 }
26596 // store
26597 module.cache.element = element;
26598 return element;
26599 },
26600 elementCalculations: function() {
26601 var
26602 screen = module.get.screenCalculations(),
26603 element = module.get.elementPosition()
26604 ;
26605 // offset
26606 if(settings.includeMargin) {
26607 element.margin = {};
26608 element.margin.top = parseInt($module.css('margin-top'), 10);
26609 element.margin.bottom = parseInt($module.css('margin-bottom'), 10);
26610 element.top = element.offset.top - element.margin.top;
26611 element.bottom = element.offset.top + element.height + element.margin.bottom;
26612 }
26613 else {
26614 element.top = element.offset.top;
26615 element.bottom = element.offset.top + element.height;
26616 }
26617
26618 // visibility
26619 element.topPassed = (screen.top >= element.top);
26620 element.bottomPassed = (screen.top >= element.bottom);
26621 element.topVisible = (screen.bottom >= element.top) && !element.topPassed;
26622 element.bottomVisible = (screen.bottom >= element.bottom) && !element.bottomPassed;
26623 element.pixelsPassed = 0;
26624 element.percentagePassed = 0;
26625
26626 // meta calculations
26627 element.onScreen = ((element.topVisible || element.passing) && !element.bottomPassed);
26628 element.passing = (element.topPassed && !element.bottomPassed);
26629 element.offScreen = (!element.onScreen);
26630
26631 // passing calculations
26632 if(element.passing) {
26633 element.pixelsPassed = (screen.top - element.top);
26634 element.percentagePassed = (screen.top - element.top) / element.height;
26635 }
26636 module.cache.element = element;
26637 module.verbose('Updated element calculations', element);
26638 return element;
26639 },
26640 screenCalculations: function() {
26641 var
26642 scroll = module.get.scroll()
26643 ;
26644 module.save.direction();
26645 module.cache.screen.top = scroll;
26646 module.cache.screen.bottom = scroll + module.cache.screen.height;
26647 return module.cache.screen;
26648 },
26649 screenSize: function() {
26650 module.verbose('Saving window position');
26651 module.cache.screen = {
26652 height: $context.height()
26653 };
26654 },
26655 position: function() {
26656 module.save.screenSize();
26657 module.save.elementPosition();
26658 }
26659 },
26660
26661 get: {
26662 pixelsPassed: function(amount) {
26663 var
26664 element = module.get.elementCalculations()
26665 ;
26666 if(amount.search('%') > -1) {
26667 return ( element.height * (parseInt(amount, 10) / 100) );
26668 }
26669 return parseInt(amount, 10);
26670 },
26671 occurred: function(callback) {
26672 return (module.cache.occurred !== undefined)
26673 ? module.cache.occurred[callback] || false
26674 : false
26675 ;
26676 },
26677 direction: function() {
26678 if(module.cache.direction === undefined) {
26679 module.save.direction();
26680 }
26681 return module.cache.direction;
26682 },
26683 elementPosition: function() {
26684 if(module.cache.element === undefined) {
26685 module.save.elementPosition();
26686 }
26687 return module.cache.element;
26688 },
26689 elementCalculations: function() {
26690 if(module.cache.element === undefined) {
26691 module.save.elementCalculations();
26692 }
26693 return module.cache.element;
26694 },
26695 screenCalculations: function() {
26696 if(module.cache.screen === undefined) {
26697 module.save.screenCalculations();
26698 }
26699 return module.cache.screen;
26700 },
26701 screenSize: function() {
26702 if(module.cache.screen === undefined) {
26703 module.save.screenSize();
26704 }
26705 return module.cache.screen;
26706 },
26707 scroll: function() {
26708 if(module.cache.scroll === undefined) {
26709 module.save.scroll();
26710 }
26711 return module.cache.scroll;
26712 },
26713 lastScroll: function() {
26714 if(module.cache.screen === undefined) {
26715 module.debug('First scroll event, no last scroll could be found');
26716 return false;
26717 }
26718 return module.cache.screen.top;
26719 }
26720 },
26721
26722 setting: function(name, value) {
26723 if( $.isPlainObject(name) ) {
26724 $.extend(true, settings, name);
26725 }
26726 else if(value !== undefined) {
26727 settings[name] = value;
26728 }
26729 else {
26730 return settings[name];
26731 }
26732 },
26733 internal: function(name, value) {
26734 if( $.isPlainObject(name) ) {
26735 $.extend(true, module, name);
26736 }
26737 else if(value !== undefined) {
26738 module[name] = value;
26739 }
26740 else {
26741 return module[name];
26742 }
26743 },
26744 debug: function() {
26745 if(!settings.silent && settings.debug) {
26746 if(settings.performance) {
26747 module.performance.log(arguments);
26748 }
26749 else {
26750 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
26751 module.debug.apply(console, arguments);
26752 }
26753 }
26754 },
26755 verbose: function() {
26756 if(!settings.silent && settings.verbose && settings.debug) {
26757 if(settings.performance) {
26758 module.performance.log(arguments);
26759 }
26760 else {
26761 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
26762 module.verbose.apply(console, arguments);
26763 }
26764 }
26765 },
26766 error: function() {
26767 if(!settings.silent) {
26768 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
26769 module.error.apply(console, arguments);
26770 }
26771 },
26772 performance: {
26773 log: function(message) {
26774 var
26775 currentTime,
26776 executionTime,
26777 previousTime
26778 ;
26779 if(settings.performance) {
26780 currentTime = new Date().getTime();
26781 previousTime = time || currentTime;
26782 executionTime = currentTime - previousTime;
26783 time = currentTime;
26784 performance.push({
26785 'Name' : message[0],
26786 'Arguments' : [].slice.call(message, 1) || '',
26787 'Element' : element,
26788 'Execution Time' : executionTime
26789 });
26790 }
26791 clearTimeout(module.performance.timer);
26792 module.performance.timer = setTimeout(module.performance.display, 500);
26793 },
26794 display: function() {
26795 var
26796 title = settings.name + ':',
26797 totalTime = 0
26798 ;
26799 time = false;
26800 clearTimeout(module.performance.timer);
26801 $.each(performance, function(index, data) {
26802 totalTime += data['Execution Time'];
26803 });
26804 title += ' ' + totalTime + 'ms';
26805 if(moduleSelector) {
26806 title += ' \'' + moduleSelector + '\'';
26807 }
26808 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
26809 console.groupCollapsed(title);
26810 if(console.table) {
26811 console.table(performance);
26812 }
26813 else {
26814 $.each(performance, function(index, data) {
26815 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
26816 });
26817 }
26818 console.groupEnd();
26819 }
26820 performance = [];
26821 }
26822 },
26823 invoke: function(query, passedArguments, context) {
26824 var
26825 object = instance,
26826 maxDepth,
26827 found,
26828 response
26829 ;
26830 passedArguments = passedArguments || queryArguments;
26831 context = element || context;
26832 if(typeof query == 'string' && object !== undefined) {
26833 query = query.split(/[\. ]/);
26834 maxDepth = query.length - 1;
26835 $.each(query, function(depth, value) {
26836 var camelCaseValue = (depth != maxDepth)
26837 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
26838 : query
26839 ;
26840 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
26841 object = object[camelCaseValue];
26842 }
26843 else if( object[camelCaseValue] !== undefined ) {
26844 found = object[camelCaseValue];
26845 return false;
26846 }
26847 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
26848 object = object[value];
26849 }
26850 else if( object[value] !== undefined ) {
26851 found = object[value];
26852 return false;
26853 }
26854 else {
26855 module.error(error.method, query);
26856 return false;
26857 }
26858 });
26859 }
26860 if ( $.isFunction( found ) ) {
26861 response = found.apply(context, passedArguments);
26862 }
26863 else if(found !== undefined) {
26864 response = found;
26865 }
26866 if(Array.isArray(returnedValue)) {
26867 returnedValue.push(response);
26868 }
26869 else if(returnedValue !== undefined) {
26870 returnedValue = [returnedValue, response];
26871 }
26872 else if(response !== undefined) {
26873 returnedValue = response;
26874 }
26875 return found;
26876 }
26877 };
26878
26879 if(methodInvoked) {
26880 if(instance === undefined) {
26881 module.initialize();
26882 }
26883 instance.save.scroll();
26884 instance.save.calculations();
26885 module.invoke(query);
26886 }
26887 else {
26888 if(instance !== undefined) {
26889 instance.invoke('destroy');
26890 }
26891 module.initialize();
26892 }
26893 })
26894 ;
26895
26896 return (returnedValue !== undefined)
26897 ? returnedValue
26898 : this
26899 ;
26900};
26901
26902$.fn.visibility.settings = {
26903
26904 name : 'Visibility',
26905 namespace : 'visibility',
26906
26907 debug : false,
26908 verbose : false,
26909 performance : true,
26910
26911 // whether to use mutation observers to follow changes
26912 observeChanges : true,
26913
26914 // check position immediately on init
26915 initialCheck : true,
26916
26917 // whether to refresh calculations after all page images load
26918 refreshOnLoad : true,
26919
26920 // whether to refresh calculations after page resize event
26921 refreshOnResize : true,
26922
26923 // should call callbacks on refresh event (resize, etc)
26924 checkOnRefresh : true,
26925
26926 // callback should only occur one time
26927 once : true,
26928
26929 // callback should fire continuously whe evaluates to true
26930 continuous : false,
26931
26932 // offset to use with scroll top
26933 offset : 0,
26934
26935 // whether to include margin in elements position
26936 includeMargin : false,
26937
26938 // scroll context for visibility checks
26939 context : window,
26940
26941 // visibility check delay in ms (defaults to animationFrame)
26942 throttle : false,
26943
26944 // special visibility type (image, fixed)
26945 type : false,
26946
26947 // z-index to use with visibility 'fixed'
26948 zIndex : '10',
26949
26950 // image only animation settings
26951 transition : 'fade in',
26952 duration : 1000,
26953
26954 // array of callbacks for percentage
26955 onPassed : {},
26956
26957 // standard callbacks
26958 onOnScreen : false,
26959 onOffScreen : false,
26960 onPassing : false,
26961 onTopVisible : false,
26962 onBottomVisible : false,
26963 onTopPassed : false,
26964 onBottomPassed : false,
26965
26966 // reverse callbacks
26967 onPassingReverse : false,
26968 onTopVisibleReverse : false,
26969 onBottomVisibleReverse : false,
26970 onTopPassedReverse : false,
26971 onBottomPassedReverse : false,
26972
26973 // special callbacks for image
26974 onLoad : function() {},
26975 onAllLoaded : function() {},
26976
26977 // special callbacks for fixed position
26978 onFixed : function() {},
26979 onUnfixed : function() {},
26980
26981 // utility callbacks
26982 onUpdate : false, // disabled by default for performance
26983 onRefresh : function(){},
26984
26985 metadata : {
26986 src: 'src'
26987 },
26988
26989 className: {
26990 fixed : 'fixed',
26991 placeholder : 'constraint',
26992 visible : 'visible'
26993 },
26994
26995 error : {
26996 method : 'The method you called is not defined.',
26997 visible : 'Element is hidden, you must call refresh after element becomes visible'
26998 }
26999
27000};
27001
27002})( jQuery, window, document );